From 781e4ba85bd3f9bc37388fd63c94635624d0d87f Mon Sep 17 00:00:00 2001 From: Hamish Campbell Date: Wed, 14 Aug 2024 17:32:26 +1200 Subject: [PATCH] Move progress bar widget out of kartapi and into dockwidget This keeps the UI concerns in the GUI component and removes the UI dependancy in kartapi. An output_handler hook is added to Repository.clone to enable progress reporting. --- kart/gui/dockwidget.py | 43 ++++++++++++++++++++++++++++++++++-------- kart/kartapi.py | 31 +++++------------------------- 2 files changed, 40 insertions(+), 34 deletions(-) diff --git a/kart/gui/dockwidget.py b/kart/gui/dockwidget.py index e180c65..9df901d 100644 --- a/kart/gui/dockwidget.py +++ b/kart/gui/dockwidget.py @@ -1,5 +1,8 @@ import os +import re +import math import tempfile +from functools import partial from qgis.PyQt import uic from qgis.PyQt.QtCore import Qt, QMimeData, QByteArray, QDataStream, QIODevice @@ -50,6 +53,7 @@ setSetting, LASTREPO, waitcursor, + progressBar, ) pluginPath = os.path.split(os.path.dirname(__file__))[0] @@ -227,18 +231,41 @@ def createRepo(self): @executeskart def cloneRepo(self): + def _processProgressLine(bar, line): + if "Writing dataset" in line: + datasetname = line.split(":")[-1].strip() + bar.setText(f"Checking out layer '{datasetname}'") + elif line.startswith("Receiving objects: ") or line.startswith( + "Writing objects: " + ): + tokens = line.split(": ") + bar.setText(tokens[0]) + bar.setValue( + math.floor(float(tokens[1][1 : tokens[1].find("%")].strip())) + ) + else: + msg = line.split(" - ")[-1] + if "%" in msg: + matches = re.findall(r"(\d+(\.\d+)?)", msg) + if matches: + value = math.floor(float(matches[0][0])) + bar.setValue(value) + dialog = CloneDialog() dialog.show() ret = dialog.exec_() if ret == dialog.Accepted: - repo = Repository.clone( - dialog.src, - dialog.dst, - dialog.location, - dialog.extent, - dialog.username, - dialog.password, - ) + with progressBar("Clone") as bar: + bar.setText("Cloning repository") + repo = Repository.clone( + dialog.src, + dialog.dst, + dialog.location, + dialog.extent, + dialog.username, + dialog.password, + output_handler=partial(_processProgressLine, bar), + ) RepoManager.instance().add_repo(repo) def addRepoToUI(self, repo: Repository): diff --git a/kart/kartapi.py b/kart/kartapi.py index af77d21..3d59f70 100644 --- a/kart/kartapi.py +++ b/kart/kartapi.py @@ -1,14 +1,13 @@ import json import locale -import math import os import re import subprocess import sys import tempfile -from typing import Optional, List -from functools import partial, wraps +from typing import Optional, List, Callable +from functools import wraps from urllib.parse import urlparse @@ -33,7 +32,7 @@ from kart.gui.userconfigdialog import UserConfigDialog from kart.gui.installationwarningdialog import InstallationWarningDialog -from kart.utils import progressBar, setting, setSetting, KARTPATH, HELPERMODE +from kart.utils import setting, setSetting, KARTPATH, HELPERMODE from kart import logging @@ -258,23 +257,6 @@ def executeKart(commands, path=None, jsonoutput=False, feedback=None): QApplication.restoreOverrideCursor() -def _processProgressLine(bar, line): - if "Writing dataset" in line: - datasetname = line.split(":")[-1].strip() - bar.setText(f"Checking out layer '{datasetname}'") - elif line.startswith("Receiving objects: ") or line.startswith("Writing objects: "): - tokens = line.split(": ") - bar.setText(tokens[0]) - bar.setValue(math.floor(float(tokens[1][1 : tokens[1].find("%")].strip()))) - else: - msg = line.split(" - ")[-1] - if "%" in msg: - matches = re.findall(r"(\d+(\.\d+)?)", msg) - if matches: - value = math.floor(float(matches[0][0])) - bar.setValue(value) - - class Repository: def __init__(self, path): self.path = path @@ -342,6 +324,7 @@ def clone( extent: Optional[QgsReferencedRectangle] = None, username: Optional[str] = None, password: Optional[str] = None, + output_handler: Callable[[str], None] = None, ) -> "Repository": """ Performs a (blocking, main thread only) clone operation @@ -349,11 +332,7 @@ def clone( commands = Repository.generate_clone_arguments( src, dst, location, extent, username, password ) - - with progressBar("Clone") as bar: - bar.setText("Cloning repository") - executeKart(commands, feedback=partial(_processProgressLine, bar)) - + executeKart(commands, feedback=output_handler) return Repository(dst) def title(self):