diff --git a/packages/ExtensionStore/github_scrubber.js b/packages/ExtensionStore/github_scrubber.js index 12a85c4..5736893 100644 --- a/packages/ExtensionStore/github_scrubber.js +++ b/packages/ExtensionStore/github_scrubber.js @@ -934,26 +934,30 @@ LocalExtensionList.prototype.install = function (extension) { /** * Remove the installation from the hard drive + * @param {Extension} extension - The extension to be removed locally. + * @returns {boolean} the success of the uninstallation. */ LocalExtensionList.prototype.uninstall = function (extension) { if (!this.isInstalled(extension)) return true // extension isn't installed var localExtension = this.extensions[extension.id]; - var files = localExtension.package.localFiles; - for (var i in files) { - this.log.debug("removing file " + files[i]) - var file = new File(files[i]) - if (file.exists) file.remove(); - - // remove containing folder if all files were removed - var folder = files[i].slice(0, files[i].lastIndexOf("/") + 1); - if (listFiles(folder).length == 0) (new Dir(folder)).rmdirs(); - } + // Remove packages recursively as they have a parent directory. if (extension.package.isPackage) { var folder = new Dir(this.installFolder + "packages/" + extension.name.replace(" ", "")); - this.log.debug("removing folder " + folder.path) + this.log.debug("removing folder " + folder.path); if (folder.exists) folder.rmdirs(); } + // Otherwise remove all script files (.js, .ui, .png etc.) + else { + var files = localExtension.package.localFiles; + for (var i in files) { + this.log.debug("removing file " + files[i]); + var file = new File(files[i]); + if (file.exists) file.remove(); + } + } + + // Update the extension list accordingly. this.removeFromList(extension); return true; @@ -1140,6 +1144,7 @@ ExtensionDownloader.prototype.downloadFiles = function () { progress.title = "Installing extension "+this.extension.name; progress.setLabelText( "Downloading files..." ); progress.setRange( 0, files.length ); + progress.modal = true; progress.show(); @@ -1289,15 +1294,33 @@ CURL.prototype.get = function (command, wait) { CURL.prototype.runCommand = function (bin, command, wait, test){ if (typeof test === 'undefined') var test = false; // test will not print the output, just the errors + var loop = new QEventLoop(); + var p = new QProcess(); + p["finished(int,QProcess::ExitStatus)"].connect(this, function () { + loop.exit(); + }); + + // Use a timer to kill the QProcess after the wait period. + var timer = new QTimer(); + timer.singleShot = true; + timer["timeout"].connect(this, function() { + if (loop.isRunning()) { + p.kill(); + loop.exit(); + throw new Error("Timeout updating extension."); + } + }); + // The toonboom bundled curl doesn't seem to be equiped for ssh so we have to use unsafe mode if (bin.indexOf("bin_3rdParty") != -1) command = ["-k"].concat(command); command = ["-s", "-S"].concat(command); + // Start the process and enter an event loop until the QProcessx exits. this.log.debug("starting process :" + bin + " " + command.join(" ")); p.start(bin, command); - - p.waitForFinished(wait); + timer.start(wait); + loop.exec(); var readOut = p.readAllStandardOutput(); var output = new QTextStream(readOut).readAll(); @@ -1374,6 +1397,7 @@ function Logger(name) { // by default will only output errors and log this.LEVEL = { "ERROR": 0, "LOG": 1, "DEBUG": 2 }; if (typeof Logger.level === 'undefined') Logger.level = this.LEVEL.LOG; + if (MessageLog.isDebug()) Logger.level = this.LEVEL.DEBUG; } @@ -1503,7 +1527,7 @@ function recursiveFileCopy(folder, destination) { var command = ["/E", "/TEE", "/MOV", folder, destination]; } else { var bin = "cp"; - var command = ["-Rv", folder + "/*", destination]; + var command = ["-Rv", folder + "/.", destination]; } log.debug("starting process :"+bin+" "+command); diff --git a/packages/ExtensionStore/store.ui b/packages/ExtensionStore/store.ui index 63b6643..5fe85e8 100644 --- a/packages/ExtensionStore/store.ui +++ b/packages/ExtensionStore/store.ui @@ -685,7 +685,7 @@ 0 0 513 - 303 + 266 @@ -769,23 +769,50 @@ - + - - - - 80 - 30 - + + + + + + 80 + 30 + + + + + 150 + 16777215 + + + + Load Store + + + + + + + + + <html><head/><body><p><span style=" font-weight:600;">Please Wait - Updating Extension List...</span></p></body></html> - - - 150 - 16777215 - + + Qt::AlignCenter - - Load Store + + 5 + + + + + + + 0 + + + -1 diff --git a/packages/ExtensionStore/storeui.js b/packages/ExtensionStore/storeui.js index f77b113..67f15a9 100644 --- a/packages/ExtensionStore/storeui.js +++ b/packages/ExtensionStore/storeui.js @@ -30,8 +30,9 @@ function StoreUI(){ this.storeDescriptionPanel = this.storeFrame.storeSplitter.widget(1); this.extensionsList = this.storeListPanel.extensionsList; - // disable store frame until store is loaded + // Hide the store and the loading UI elements. this.storeFrame.hide(); + this.setUpdateProgressUIState(false); var logo = storelib.currentFolder+"/logo.png" var logoPixmap = new QPixmap(logo); @@ -94,13 +95,29 @@ StoreUI.prototype.show = function(){ this.ui.show() } +/** + * Show widgets responsible for showing progress to the user when loading the + * store and retrieving extensions. + * @param {boolean} visible - Determine whether the progress state should be enabled or disabled. + */ +StoreUI.prototype.setUpdateProgressUIState = function(visible){ + if (visible === true) { + this.aboutFrame.loadStoreButton.hide(); + this.aboutFrame.updateLabel.show(); + this.aboutFrame.updateProgress.show(); + } + else{ + this.aboutFrame.loadStoreButton.show(); + this.aboutFrame.updateLabel.hide(); + this.aboutFrame.updateProgress.hide(); + } +} + /** * Loads the store */ StoreUI.prototype.loadStore = function(){ - this.storeFrame.show(); - this.aboutFrame.hide(); // setup the store widget sizes this.extensionsList.setColumnWidth(0, UiLoader.dpiScale(220)); @@ -118,9 +135,12 @@ StoreUI.prototype.loadStore = function(){ storeFrame.storeSplitter.setSizes([storeFrame.width / 2, storeFrame.width / 2]); this.storeFrameState = storeFrame.storeSplitter.saveState(); storeFrame.storeSplitter.setSizes([storeFrame.storeSplitter.width, 0]); - - // expensive loading operation, maybe we could show a progress bar here somehow - // (instead of doing it one line, do it seller by seller then extension by extension and update progress?) + + // Show progress dialog to give user indication that the list of extensions is being + // updated. + this.setUpdateProgressUIState(true); + + // Update list of available operations. var extensions = this.store.extensions; // saving the list of extensions so we can pinpoint the new ones at next startup and highlight them @@ -137,6 +157,10 @@ StoreUI.prototype.loadStore = function(){ this.localList.saveData("newExtensions", newExtensions); this.updateExtensionsList(); + + // Show the fully loaded store. + this.storeFrame.show(); + this.aboutFrame.hide(); } diff --git a/packages/ExtensionStore/tbpackage.json b/packages/ExtensionStore/tbpackage.json index 5e5f20e..bb98e01 100644 --- a/packages/ExtensionStore/tbpackage.json +++ b/packages/ExtensionStore/tbpackage.json @@ -1,8 +1,8 @@ { "name": "ExtensionStore", - "version": "0.2.1", + "version": "0.2.2", "compatibility": "Harmony Premium 16", - "description": "Changelog: fix bug when checking for updates during the first connexion.", + "description": "Changelog: Added loading UI. Enabled additional debug mode. Fixed file copy syntax on MacOS / Linux.", "isPackage": "true", "repository": "https://github.com/mchaptel/ExtensionStore/", "files": [