Addon Manager: Add branch switching GUI
For users with git and GitPython installed, a new button is added to the details view allowing them to change the branch they are on. Some other minor UI changes are made to accomodate this new behavior.
This commit is contained in:
@@ -757,6 +757,8 @@ class CommandAddonManager:
|
||||
if repo.status() == AddonManagerRepo.UpdateStatus.UPDATE_AVAILABLE:
|
||||
self.packages_with_updates.append(repo)
|
||||
self.enable_updates(len(self.packages_with_updates))
|
||||
elif repo.status() == AddonManagerRepo.UpdateStatus.PENDING_RESTART:
|
||||
self.restart_required = True
|
||||
|
||||
def enable_updates(self, number_of_updates: int) -> None:
|
||||
"""enables the update button"""
|
||||
|
||||
@@ -13,6 +13,8 @@ SET(AddonManager_SRCS
|
||||
AddonManager.ui
|
||||
AddonManagerOptions.ui
|
||||
ALLOWED_PYTHON_PACKAGES.txt
|
||||
change_branch.py
|
||||
change_branch.ui
|
||||
first_run.ui
|
||||
compact_view.py
|
||||
dependency_resolution_dialog.ui
|
||||
|
||||
@@ -433,21 +433,32 @@ class UpdateChecker:
|
||||
with wb.git_lock:
|
||||
utils.repair_git_repo(wb.url, clonedir)
|
||||
with wb.git_lock:
|
||||
gitrepo = git.Git(clonedir)
|
||||
gitrepo = git.Repo(clonedir)
|
||||
try:
|
||||
gitrepo.fetch()
|
||||
except Exception:
|
||||
if gitrepo.head.is_detached:
|
||||
# By definition, in a detached-head state we cannot
|
||||
# update, so don't even bother checking.
|
||||
wb.set_status(AddonManagerRepo.UpdateStatus.NO_UPDATE_AVAILABLE)
|
||||
if hasattr(gitrepo.head, "ref"):
|
||||
wb.branch = gitrepo.head.ref.name
|
||||
else:
|
||||
wb.branch = gitrepo.head.name
|
||||
return
|
||||
gitrepo.git.fetch()
|
||||
except Exception as e:
|
||||
FreeCAD.Console.PrintWarning(
|
||||
"AddonManager: "
|
||||
+ translate(
|
||||
"AddonsInstaller",
|
||||
"Unable to fetch git updates for workbench {}",
|
||||
).format(wb.name)
|
||||
+ "\n"
|
||||
)
|
||||
FreeCAD.Console.PrintWarning(str(e) + "\n")
|
||||
wb.set_status(AddonManagerRepo.UpdateStatus.CANNOT_CHECK)
|
||||
else:
|
||||
try:
|
||||
if "git pull" in gitrepo.status():
|
||||
if "git pull" in gitrepo.git.status():
|
||||
wb.set_status(
|
||||
AddonManagerRepo.UpdateStatus.UPDATE_AVAILABLE
|
||||
)
|
||||
@@ -460,12 +471,22 @@ class UpdateChecker:
|
||||
translate(
|
||||
"AddonsInstaller", "git fetch failed for {}"
|
||||
).format(wb.name)
|
||||
+ "\n"
|
||||
)
|
||||
wb.set_status(AddonManagerRepo.UpdateStatus.CANNOT_CHECK)
|
||||
|
||||
def check_package(self, package: AddonManagerRepo) -> None:
|
||||
clonedir = self.moddir + os.sep + package.name
|
||||
if os.path.exists(clonedir):
|
||||
|
||||
# First, try to just do a git-based update, which will give the most accurate results:
|
||||
if have_git and not NOGIT:
|
||||
self.check_workbench(package)
|
||||
if package.status() != AddonManagerRepo.UpdateStatus.CANNOT_CHECK:
|
||||
# It worked, just exit now
|
||||
return
|
||||
|
||||
# If we were unable to do a git-based update, try using the package.xml file instead:
|
||||
installed_metadata_file = os.path.join(clonedir, "package.xml")
|
||||
if not os.path.isfile(installed_metadata_file):
|
||||
# If there is no package.xml file, then it's because the package author added it after the last time
|
||||
@@ -1020,7 +1041,9 @@ class InstallWorkbenchWorker(QtCore.QThread):
|
||||
if self.repo.git_lock.locked():
|
||||
FreeCAD.Console.PrintMessage("Waiting for lock to be released to us...\n")
|
||||
if not self.repo.git_lock.acquire(timeout=2):
|
||||
FreeCAD.Console.PrintError("Timeout waiting for a lock on the git process, failed to clone repo\n")
|
||||
FreeCAD.Console.PrintError(
|
||||
"Timeout waiting for a lock on the git process, failed to clone repo\n"
|
||||
)
|
||||
return
|
||||
else:
|
||||
self.repo.git_lock.release()
|
||||
|
||||
284
src/Mod/AddonManager/change_branch.py
Normal file
284
src/Mod/AddonManager/change_branch.py
Normal file
@@ -0,0 +1,284 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2022 Chris Hennes <chennes@pioneerlibrarysystem.org> *
|
||||
# * *
|
||||
# * This library 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. *
|
||||
# * *
|
||||
# * This library 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 this library; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
# * 02110-1301 USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
import os
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
|
||||
from PySide2 import QtWidgets, QtCore
|
||||
|
||||
translate = FreeCAD.Qt.translate
|
||||
|
||||
try:
|
||||
import git
|
||||
|
||||
NO_GIT = False
|
||||
except Exception:
|
||||
NO_GIT = True
|
||||
|
||||
|
||||
class ChangeBranchDialog(QtWidgets.QWidget):
|
||||
|
||||
branch_changed = QtCore.Signal(str)
|
||||
|
||||
def __init__(self, path: os.PathLike, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
self.ui = FreeCADGui.PySideUic.loadUi(
|
||||
os.path.join(os.path.dirname(__file__), "change_branch.ui")
|
||||
)
|
||||
|
||||
self.item_filter = ChangeBranchDialogFilter()
|
||||
self.ui.tableView.setModel(self.item_filter)
|
||||
|
||||
self.item_model = ChangeBranchDialogModel(path, self)
|
||||
self.item_filter.setSourceModel(self.item_model)
|
||||
self.ui.tableView.sortByColumn(
|
||||
4, QtCore.Qt.DescendingOrder
|
||||
) # Default to sorting by remote last-changed date
|
||||
|
||||
# Figure out what row gets selected:
|
||||
row = 0
|
||||
current_ref = self.item_model.repo.head.ref
|
||||
selection_model = self.ui.tableView.selectionModel()
|
||||
for ref in self.item_model.refs:
|
||||
if ref == current_ref:
|
||||
index = self.item_filter.mapFromSource(self.item_model.index(row, 0))
|
||||
selection_model.select(index, QtCore.QItemSelectionModel.ClearAndSelect)
|
||||
selection_model.select(
|
||||
index.siblingAtColumn(1), QtCore.QItemSelectionModel.Select
|
||||
)
|
||||
selection_model.select(
|
||||
index.siblingAtColumn(2), QtCore.QItemSelectionModel.Select
|
||||
)
|
||||
selection_model.select(
|
||||
index.siblingAtColumn(3), QtCore.QItemSelectionModel.Select
|
||||
)
|
||||
selection_model.select(
|
||||
index.siblingAtColumn(4), QtCore.QItemSelectionModel.Select
|
||||
)
|
||||
break
|
||||
row += 1
|
||||
|
||||
# Make sure the column widths are OK:
|
||||
header = self.ui.tableView.horizontalHeader()
|
||||
header.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
|
||||
|
||||
def exec(self):
|
||||
if self.ui.exec() == QtWidgets.QDialog.Accepted:
|
||||
|
||||
selection = self.ui.tableView.selectedIndexes()
|
||||
index = self.item_filter.mapToSource(selection[0])
|
||||
ref = self.item_model.data(index, ChangeBranchDialogModel.RefAccessRole)
|
||||
|
||||
if ref == self.item_model.repo.head.ref:
|
||||
# This is the one we are already on... just return
|
||||
return
|
||||
|
||||
if self.item_model.repo.is_dirty():
|
||||
result = QtWidgets.QMessageBox.critical(
|
||||
self,
|
||||
translate("AddonsInstaller", "There are local changes"),
|
||||
translate(
|
||||
"AddonsInstaller",
|
||||
"WARNING: This repo has uncommitted local changes. Are you sure you want to change branches (bringing the changes with you)?",
|
||||
),
|
||||
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.Cancel,
|
||||
QtWidgets.QMessageBox.Cancel,
|
||||
)
|
||||
if result == QtWidgets.QMessageBox.Cancel:
|
||||
return
|
||||
|
||||
if isinstance(ref, git.TagReference):
|
||||
# Detach the head
|
||||
self.item_model.repo.head.reference = ref
|
||||
self.item_model.repo.head.reset(index=True, working_tree=True)
|
||||
elif isinstance(ref, git.RemoteReference):
|
||||
# Set up a local tracking branch
|
||||
slash_index = ref.name.find("/")
|
||||
if slash_index != -1:
|
||||
local_name = ref.name[slash_index + 1 :]
|
||||
else:
|
||||
local_name = ref.name
|
||||
self.item_model.repo.create_head(local_name, ref)
|
||||
self.item_model.repo.heads[local_name].set_tracking_branch(ref)
|
||||
self.item_model.repo.heads[local_name].checkout()
|
||||
else:
|
||||
# It's already a local branch, just check it out
|
||||
ref.checkout()
|
||||
|
||||
self.branch_changed.emit(ref.name)
|
||||
|
||||
|
||||
class ChangeBranchDialogModel(QtCore.QAbstractTableModel):
|
||||
|
||||
refs = []
|
||||
display_data = []
|
||||
DataSortRole = QtCore.Qt.UserRole
|
||||
RefAccessRole = QtCore.Qt.UserRole + 1
|
||||
|
||||
def __init__(self, path: os.PathLike, parent=None) -> None:
|
||||
super().__init__(parent)
|
||||
self.repo = git.Repo(path)
|
||||
|
||||
self.refs = []
|
||||
tracking_refs = []
|
||||
for ref in self.repo.refs:
|
||||
row = ["", None, None, None, None]
|
||||
if "HEAD" in ref.name:
|
||||
continue
|
||||
if isinstance(ref, git.RemoteReference):
|
||||
if ref.name in tracking_refs:
|
||||
# Already seen, it's the remote part of a remote tracking branch
|
||||
continue
|
||||
else:
|
||||
# Just a remote branch, not tracking:
|
||||
row[0] = translate("AddonsInstaller", "Branch", "git terminology")
|
||||
row[2] = ref.name
|
||||
if hasattr(ref, "commit") and hasattr(ref.commit, "committed_date"):
|
||||
row[4] = ref.commit.committed_date
|
||||
else:
|
||||
row[4] = ref.log_entry(0).time[0]
|
||||
elif isinstance(ref, git.TagReference):
|
||||
# Tags are simple, there is no tracking to worry about
|
||||
row[0] = translate("AddonsInstaller", "Tag", "git terminology")
|
||||
row[1] = ref.name
|
||||
row[3] = ref.commit.committed_date
|
||||
elif isinstance(ref, git.Head):
|
||||
if hasattr(ref, "tracking_branch") and ref.tracking_branch():
|
||||
# This local branch tracks a remote: we have all five pieces of data...
|
||||
row[0] = translate("AddonsInstaller", "Branch", "git terminology")
|
||||
row[1] = ref.name
|
||||
row[2] = ref.tracking_branch().name
|
||||
row[3] = ref.commit.committed_date
|
||||
row[4] = ref.tracking_branch().commit.committed_date
|
||||
tracking_refs.append(ref.tracking_branch().name)
|
||||
else:
|
||||
# Just a local branch, no remote tracking:
|
||||
row[0] = translate("AddonsInstaller", "Branch", "git terminology")
|
||||
row[1] = ref.name
|
||||
if hasattr(ref, "commit") and hasattr(ref.commit, "committed_date"):
|
||||
row[3] = ref.commit.committed_date
|
||||
else:
|
||||
row[3] = ref.log_entry(0).time[0]
|
||||
else:
|
||||
continue
|
||||
|
||||
self.display_data.append(row.copy())
|
||||
self.refs.append(ref)
|
||||
|
||||
def rowCount(self, parent: QtCore.QModelIndex = QtCore.QModelIndex()) -> int:
|
||||
if parent.isValid():
|
||||
return 0
|
||||
return len(self.refs)
|
||||
|
||||
def columnCount(self, parent: QtCore.QModelIndex = QtCore.QModelIndex()) -> int:
|
||||
if parent.isValid():
|
||||
return 0
|
||||
return 5 # Type, local name, tracking name, local update, and remote update
|
||||
|
||||
def data(self, index: QtCore.QModelIndex, role: int = QtCore.Qt.DisplayRole):
|
||||
if not index.isValid():
|
||||
return None
|
||||
row = index.row()
|
||||
column = index.column()
|
||||
if role == QtCore.Qt.ToolTipRole:
|
||||
tooltip = ""
|
||||
# TODO: What should the tooltip be for these items? Last commit message?
|
||||
return tooltip
|
||||
elif role == QtCore.Qt.DisplayRole:
|
||||
dd = self.display_data[row]
|
||||
if column == 3 or column == 4:
|
||||
if dd[column] is not None:
|
||||
qdate = QtCore.QDateTime.fromTime_t(dd[column])
|
||||
return QtCore.QLocale().toString(qdate, QtCore.QLocale.ShortFormat)
|
||||
elif column < len(dd):
|
||||
return dd[column]
|
||||
else:
|
||||
return None
|
||||
elif role == ChangeBranchDialogModel.DataSortRole:
|
||||
if column == 0:
|
||||
if self.refs[row] in self.repo.heads:
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
elif column < len(self.display_data[row]):
|
||||
return self.display_data[row][column]
|
||||
else:
|
||||
return None
|
||||
elif role == ChangeBranchDialogModel.RefAccessRole:
|
||||
return self.refs[row]
|
||||
|
||||
def headerData(
|
||||
self,
|
||||
section: int,
|
||||
orientation: QtCore.Qt.Orientation,
|
||||
role: int = QtCore.Qt.DisplayRole,
|
||||
):
|
||||
if orientation == QtCore.Qt.Vertical:
|
||||
return None
|
||||
if role != QtCore.Qt.DisplayRole:
|
||||
return None
|
||||
if section == 0:
|
||||
return translate(
|
||||
"AddonsInstaller",
|
||||
"Kind",
|
||||
"Table header for git ref type (e.g. either Tag or Branch)",
|
||||
)
|
||||
elif section == 1:
|
||||
return translate(
|
||||
"AddonsInstaller", "Local name", "Table header for git ref name"
|
||||
)
|
||||
elif section == 2:
|
||||
return translate(
|
||||
"AddonsInstaller",
|
||||
"Tracking",
|
||||
"Table header for git remote tracking branch name name",
|
||||
)
|
||||
elif section == 3:
|
||||
return translate(
|
||||
"AddonsInstaller",
|
||||
"Local updated",
|
||||
"Table header for git update time of local branch",
|
||||
)
|
||||
elif section == 4:
|
||||
return translate(
|
||||
"AddonsInstaller",
|
||||
"Remote updated",
|
||||
"Table header for git update time of remote branch",
|
||||
)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
class ChangeBranchDialogFilter(QtCore.QSortFilterProxyModel):
|
||||
def lessThan(self, left: QtCore.QModelIndex, right: QtCore.QModelIndex):
|
||||
leftData = self.sourceModel().data(left, ChangeBranchDialogModel.DataSortRole)
|
||||
rightData = self.sourceModel().data(right, ChangeBranchDialogModel.DataSortRole)
|
||||
if leftData is None or rightData is None:
|
||||
if rightData is not None:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
return leftData < rightData
|
||||
105
src/Mod/AddonManager/change_branch.ui
Normal file
105
src/Mod/AddonManager/change_branch.ui
Normal file
@@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>change_branch</class>
|
||||
<widget class="QDialog" name="change_branch">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>550</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Change Branch</string>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Change to branch or tag:</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableView" name="tableView">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="showDropIndicator" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderShowSortIndicator" stdset="0">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>change_branch</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>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>change_branch</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>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -29,11 +29,22 @@ from PySide2.QtWidgets import *
|
||||
import os
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
|
||||
import addonmanager_utilities as utils
|
||||
from addonmanager_workers import GetMacroDetailsWorker, CheckSingleUpdateWorker
|
||||
from AddonManagerRepo import AddonManagerRepo
|
||||
import NetworkManager
|
||||
from change_branch import ChangeBranchDialog
|
||||
|
||||
have_git = False
|
||||
try:
|
||||
import git
|
||||
|
||||
if hasattr(git, "Repo"):
|
||||
have_git = True
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
from typing import Optional
|
||||
|
||||
@@ -83,6 +94,7 @@ class PackageDetails(QWidget):
|
||||
self.ui.buttonCheckForUpdate.clicked.connect(
|
||||
lambda: self.check_for_update.emit(self.repo)
|
||||
)
|
||||
self.ui.buttonChangeBranch.clicked.connect(self.change_branch_clicked)
|
||||
if HAS_QTWEBENGINE:
|
||||
self.ui.webView.loadStarted.connect(self.load_started)
|
||||
self.ui.webView.loadProgress.connect(self.load_progress)
|
||||
@@ -152,6 +164,7 @@ class PackageDetails(QWidget):
|
||||
|
||||
def display_repo_status(self, status):
|
||||
repo = self.repo
|
||||
self.set_change_branch_button_state()
|
||||
if status != AddonManagerRepo.UpdateStatus.NOT_INSTALLED:
|
||||
|
||||
version = repo.installed_version
|
||||
@@ -187,7 +200,7 @@ class PackageDetails(QWidget):
|
||||
if repo.metadata:
|
||||
installed_version_string += (
|
||||
"<b>"
|
||||
+ translate("AddonsInstaller", "Update available to version")
|
||||
+ translate("AddonsInstaller", "On branch {}, update available to version").format(repo.branch)
|
||||
+ " "
|
||||
)
|
||||
installed_version_string += repo.metadata.Version
|
||||
@@ -210,10 +223,25 @@ class PackageDetails(QWidget):
|
||||
+ ".</b>"
|
||||
)
|
||||
elif status == AddonManagerRepo.UpdateStatus.NO_UPDATE_AVAILABLE:
|
||||
installed_version_string += (
|
||||
translate("AddonsInstaller", "This is the latest version available")
|
||||
+ "."
|
||||
)
|
||||
detached_head = False
|
||||
branch = repo.branch
|
||||
if have_git:
|
||||
basedir = FreeCAD.getUserAppDataDir()
|
||||
moddir = os.path.join(basedir, "Mod", repo.name)
|
||||
gitrepo = git.Repo(moddir)
|
||||
branch = gitrepo.head.ref.name
|
||||
detached_head = gitrepo.head.is_detached
|
||||
|
||||
if detached_head:
|
||||
installed_version_string += (
|
||||
translate("AddonsInstaller", "Git tag '{}' checked out, no updates possible").format(branch)
|
||||
+ "."
|
||||
)
|
||||
else:
|
||||
installed_version_string += (
|
||||
translate("AddonsInstaller", "This is the latest version available for branch {}").format(branch)
|
||||
+ "."
|
||||
)
|
||||
elif status == AddonManagerRepo.UpdateStatus.PENDING_RESTART:
|
||||
installed_version_string += (
|
||||
translate(
|
||||
@@ -347,6 +375,34 @@ class PackageDetails(QWidget):
|
||||
return first_supported_version
|
||||
return None
|
||||
|
||||
def set_change_branch_button_state(self):
|
||||
"""The change branch button is only available for installed Addons that have a .git directory
|
||||
and in runs where the GitPython import is available."""
|
||||
|
||||
self.ui.buttonChangeBranch.hide()
|
||||
|
||||
# Is this repo installed? If not, return.
|
||||
if self.repo.status() == AddonManagerRepo.UpdateStatus.NOT_INSTALLED:
|
||||
return
|
||||
|
||||
# Is it a Macro? If so, return:
|
||||
if self.repo.repo_type == AddonManagerRepo.RepoType.MACRO:
|
||||
return
|
||||
|
||||
# Can we actually switch branches? If not, return.
|
||||
if not have_git:
|
||||
return
|
||||
|
||||
# Is there a .git subdirectory? If not, return.
|
||||
basedir = FreeCAD.getUserAppDataDir()
|
||||
path_to_git = os.path.join(basedir, "Mod", self.repo.name, ".git")
|
||||
if not os.path.isdir(path_to_git):
|
||||
return
|
||||
|
||||
# If all four above checks passed, then it's possible for us to switch
|
||||
# branches, if there are any besides the one we are on: show the button
|
||||
self.ui.buttonChangeBranch.show()
|
||||
|
||||
def show_workbench(self, repo: AddonManagerRepo) -> None:
|
||||
"""loads information of a given workbench"""
|
||||
url = utils.get_readme_html_url(repo)
|
||||
@@ -492,6 +548,47 @@ class PackageDetails(QWidget):
|
||||
html = f"<html><body><p>{m}</p></body></html>"
|
||||
self.ui.webView.setHtml(html)
|
||||
|
||||
def change_branch_clicked(self) -> None:
|
||||
basedir = FreeCAD.getUserAppDataDir()
|
||||
path_to_repo = os.path.join(basedir, "Mod", self.repo.name)
|
||||
change_branch_dialog = ChangeBranchDialog(path_to_repo, self)
|
||||
change_branch_dialog.branch_changed.connect(self.branch_changed)
|
||||
change_branch_dialog.exec()
|
||||
|
||||
def branch_changed(self, name: str) -> None:
|
||||
QMessageBox.information(
|
||||
self,
|
||||
translate("AddonsInstaller", "Success"),
|
||||
translate(
|
||||
"AddonsInstaller",
|
||||
"Branch change succeeded, please restart to use the new version.",
|
||||
),
|
||||
)
|
||||
# See if this branch has a package.xml file:
|
||||
basedir = FreeCAD.getUserAppDataDir()
|
||||
path_to_metadata = os.path.join(basedir, "Mod", self.repo.name, "package.xml")
|
||||
if os.path.isfile(path_to_metadata):
|
||||
self.repo.load_metadata_file(path_to_metadata)
|
||||
self.repo.installed_version = self.repo.metadata.Version
|
||||
else:
|
||||
self.repo.repo_type = AddonManagerRepo.RepoType.WORKBENCH
|
||||
self.repo.metadata = None
|
||||
self.repo.installed_version = None
|
||||
self.repo.updated_timestamp = QDateTime.currentDateTime().toSecsSinceEpoch()
|
||||
self.repo.branch = name
|
||||
self.repo.set_status(AddonManagerRepo.UpdateStatus.PENDING_RESTART)
|
||||
|
||||
installed_version_string = "<h3>"
|
||||
installed_version_string += translate(
|
||||
"AddonsInstaller", "Changed to git ref '{}' -- please restart to use Addon."
|
||||
).format(name)
|
||||
installed_version_string += "</h3>"
|
||||
self.ui.labelPackageDetails.setText(installed_version_string)
|
||||
self.ui.labelPackageDetails.setStyleSheet(
|
||||
"color:" + utils.attention_color_string()
|
||||
)
|
||||
self.update_status.emit(self.repo)
|
||||
|
||||
|
||||
if HAS_QTWEBENGINE:
|
||||
|
||||
@@ -570,6 +667,11 @@ class Ui_PackageDetails(object):
|
||||
|
||||
self.layoutDetailsBackButton.addWidget(self.buttonCheckForUpdate)
|
||||
|
||||
self.buttonChangeBranch = QPushButton(PackageDetails)
|
||||
self.buttonChangeBranch.setObjectName("buttonChangeBranch")
|
||||
|
||||
self.layoutDetailsBackButton.addWidget(self.buttonChangeBranch)
|
||||
|
||||
self.buttonExecute = QPushButton(PackageDetails)
|
||||
self.buttonExecute.setObjectName("buttonExecute")
|
||||
|
||||
@@ -663,6 +765,9 @@ class Ui_PackageDetails(object):
|
||||
self.buttonExecute.setText(
|
||||
QCoreApplication.translate("AddonsInstaller", "Run Macro", None)
|
||||
)
|
||||
self.buttonChangeBranch.setText(
|
||||
QCoreApplication.translate("AddonsInstaller", "Change Branch", None)
|
||||
)
|
||||
self.buttonBack.setToolTip(
|
||||
QCoreApplication.translate(
|
||||
"AddonsInstaller", "Return to package list", None
|
||||
|
||||
@@ -74,6 +74,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonChangeBranch">
|
||||
<property name="text">
|
||||
<string>Change branch</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
|
||||
@@ -353,7 +353,9 @@ class PackageListItemDelegate(QStyledItemDelegate):
|
||||
)
|
||||
elif len(maintainers) > 1:
|
||||
n = len(maintainers)
|
||||
maintainers_string = translate("AddonsInstaller", "Maintainers:", "", n)
|
||||
maintainers_string = translate(
|
||||
"AddonsInstaller", "Maintainers:", "", n
|
||||
)
|
||||
for maintainer in maintainers:
|
||||
maintainers_string += (
|
||||
f"\n{maintainer['name']} <{maintainer['email']}>"
|
||||
|
||||
Reference in New Issue
Block a user