Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[processing] first implementation of github-based resources manager
- Loading branch information
Showing
8 changed files
with
497 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,237 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
""" | ||
*************************************************************************** | ||
GetScriptsAndModels.py | ||
--------------------- | ||
Date : June 2014 | ||
Copyright : (C) 2014 by Victor Olaya | ||
Email : volayaf at gmail dot com | ||
*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
*************************************************************************** | ||
""" | ||
import os | ||
from PyQt4 import QtGui | ||
from processing.ui.ui_DlgGetScriptsAndModels import Ui_DlgGetScriptsAndModels | ||
from processing.script.ScriptUtils import ScriptUtils | ||
from processing.modeler.ModelerUtils import ModelerUtils | ||
import json | ||
from processing.gui import Help2Html | ||
from qgis.utils import iface | ||
from processing.gui.Help2Html import getDescription, ALG_DESC, ALG_VERSION,\ | ||
ALG_CREATOR | ||
|
||
__author__ = 'Victor Olaya' | ||
__date__ = 'June 2014' | ||
__copyright__ = '(C) 201, Victor Olaya' | ||
|
||
# This will get replaced with a git SHA1 when you do a git archive | ||
|
||
__revision__ = '$Format:%H$' | ||
|
||
import urllib2 | ||
from urllib2 import HTTPError | ||
from PyQt4.QtCore import * | ||
from PyQt4.QtGui import * | ||
from processing.gui.ToolboxAction import ToolboxAction | ||
|
||
|
||
class GetScriptsAction(ToolboxAction): | ||
|
||
def __init__(self): | ||
self.name = "Get scripts from on-line scripts collection" | ||
self.group = 'Tools' | ||
|
||
def getIcon(self): | ||
return QIcon(':/processing/images/script.png') | ||
|
||
def execute(self): | ||
try: | ||
dlg = GetScriptsAndModelsDialog(GetScriptsAndModelsDialog.SCRIPTS) | ||
dlg.exec_() | ||
if dlg.updateToolbox: | ||
self.toolbox.updateProvider('script') | ||
|
||
except HTTPError: | ||
QMessageBox.critical(iface.mainWindow(), "Connection problem", "Could not connect to scripts/models repository") | ||
|
||
class GetModelsAction(ToolboxAction): | ||
|
||
def __init__(self): | ||
self.name = "Get models from on-line scripts collection" | ||
self.group = 'Tools' | ||
|
||
def getIcon(self): | ||
return QIcon(':/processing/images/model.png') | ||
|
||
def execute(self): | ||
try: | ||
dlg = GetScriptsAndModelsDialog(GetScriptsAndModelsDialog.MODELS) | ||
dlg.exec_() | ||
if dlg.updateToolbox: | ||
self.toolbox.updateProvider('model') | ||
except HTTPError: | ||
QMessageBox.critical(iface.mainWindow(), "Connection problem", "Could not connect to scripts/models repository") | ||
|
||
|
||
def readUrl(url): | ||
try: | ||
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) | ||
return urllib2.urlopen(url).read() | ||
finally: | ||
QApplication.restoreOverrideCursor() | ||
|
||
|
||
class GetScriptsAndModelsDialog(QDialog, Ui_DlgGetScriptsAndModels): | ||
|
||
HELP_TEXT = ("<h3> Processing resources manager </h3>" | ||
"<p>Check/uncheck algorithms in the tree to select the ones that you want to install or remove</p>" | ||
"<p>Algorithms are divided in 3 groups:</p>" | ||
"<ul><li><b>Installed:</b> Algorihms already in your system, with the latest version available</li>" | ||
"<li><b>Upgradable:</b> Algorihms already in your system, but with a newer version available in the server</li>" | ||
"<li><b>Not installed:</b> Algorithms not installed in your system</li></ul>") | ||
MODELS = 0 | ||
SCRIPTS = 1 | ||
|
||
def __init__(self, resourceType): | ||
QDialog.__init__(self, iface.mainWindow()) | ||
self.resourceType = resourceType | ||
if self.resourceType == self.MODELS: | ||
self.folder = ModelerUtils.modelsFolder() | ||
self.urlBase = "https://raw.githubusercontent.com/qgis/QGIS-Processing/master/models/" | ||
self.icon = QtGui.QIcon(os.path.dirname(__file__) + '/../images/model.png') | ||
else: | ||
self.folder = ScriptUtils.scriptsFolder() | ||
self.urlBase = "https://raw.githubusercontent.com/qgis/QGIS-Processing/master/scripts/" | ||
self.icon = QtGui.QIcon(os.path.dirname(__file__) + '/../images/script.png') | ||
self.lastSelectedItem = None | ||
self.setupUi(self) | ||
self.populateTree() | ||
self.updateToolbox = False | ||
self.buttonBox.accepted.connect(self.okPressed) | ||
self.buttonBox.rejected.connect(self.cancelPressed) | ||
self.tree.currentItemChanged .connect(self.currentItemChanged) | ||
|
||
def populateTree(self): | ||
self.uptodateItem = QTreeWidgetItem() | ||
self.uptodateItem.setText(0, "Installed") | ||
self.toupdateItem = QTreeWidgetItem() | ||
self.toupdateItem.setText(0, "Upgradable") | ||
self.notinstalledItem = QTreeWidgetItem() | ||
self.notinstalledItem.setText(0, "Not installed") | ||
self.toupdateItem.setIcon(0, self.icon) | ||
self.uptodateItem.setIcon(0, self.icon) | ||
self.notinstalledItem.setIcon(0, self.icon) | ||
resources = readUrl(self.urlBase + "list.txt").splitlines() | ||
resources = [r.split(",") for r in resources] | ||
for filename, version, name in resources: | ||
treeBranch = self.getTreeBranchForState(filename, float(version)) | ||
item = TreeItem(filename, name, self.icon) | ||
treeBranch.addChild(item) | ||
if treeBranch != self.notinstalledItem: | ||
item.setCheckState(0, Qt.Checked) | ||
|
||
self.tree.addTopLevelItem(self.toupdateItem) | ||
self.tree.addTopLevelItem(self.notinstalledItem) | ||
self.tree.addTopLevelItem(self.uptodateItem) | ||
|
||
self.webView.setHtml(self.HELP_TEXT) | ||
|
||
def currentItemChanged(self, item, prev): | ||
if isinstance(item, TreeItem): | ||
try: | ||
url = self.urlBase + item.filename.replace(" ","%20") + ".help" | ||
helpContent = readUrl(url) | ||
descriptions = json.loads(helpContent) | ||
html = "<h2>%s</h2>" % item.name | ||
html+="<p><b>Description:</b> " + getDescription(ALG_DESC, descriptions)+"</p>" | ||
html+="<p><b>Created by:</b> " + getDescription(ALG_CREATOR, descriptions)+"</p>" | ||
html+="<p><b>Version:</b> " + getDescription(ALG_VERSION, descriptions)+"</p>" | ||
except HTTPError, e: | ||
html = "<h2>No detailed description available for this script</h2>" | ||
self.webView.setHtml(html) | ||
else: | ||
self.webView.setHtml(self.HELP_TEXT) | ||
|
||
def getTreeBranchForState(self, filename, version): | ||
if not os.path.exists(os.path.join(self.folder, filename)): | ||
return self.notinstalledItem | ||
else: | ||
helpFile = os.path.join(self.folder, filename + ".help") | ||
if not os.path.exists(helpFile): | ||
currentVersion = 1 | ||
else: | ||
with open(helpFile) as f: | ||
helpContent = json.load(f) | ||
try: | ||
currentVersion = float(helpContent[Help2Html.ALG_VERSION]) | ||
except: | ||
currentVersion = 1 | ||
print filename, currentVersion, version | ||
if version > currentVersion: | ||
print version - currentVersion | ||
return self.toupdateItem | ||
else: | ||
return self.uptodateItem | ||
|
||
|
||
def cancelPressed(self): | ||
self.close() | ||
|
||
def okPressed(self): | ||
toDownload = [] | ||
for i in xrange(self.toupdateItem.childCount()): | ||
item = self.toupdateItem.child(i) | ||
if item.checkState(0) == Qt.Checked: | ||
toDownload.append(item.filename) | ||
for i in xrange(self.notinstalledItem.childCount()): | ||
item = self.notinstalledItem.child(i) | ||
if item.checkState(0) == Qt.Checked: | ||
toDownload.append(item.filename) | ||
|
||
if toDownload: | ||
self.progressBar.setMaximum(len(toDownload)) | ||
for i, filename in enumerate(toDownload): | ||
QCoreApplication.processEvents() | ||
url = self.urlBase + filename.replace(" ","%20") | ||
code = readUrl(url) | ||
path = os.path.join(self.folder, filename) | ||
with open(path, "w") as f: | ||
f.write(code) | ||
self.progressBar.setValue(i + 1) | ||
|
||
toDelete = [] | ||
for i in xrange(self.uptodateItem.childCount()): | ||
item = self.uptodateItem.child(i) | ||
if item.checkState(0) == Qt.Unchecked: | ||
toDelete.append(item.filename) | ||
for filename in toDelete: | ||
path = os.path.join(self.folder, filename) | ||
os.remove(path) | ||
|
||
self.updateToolbox = len(toDownload) + len(toDelete)> 0 | ||
self.close() | ||
|
||
|
||
class TreeItem(QTreeWidgetItem): | ||
|
||
def __init__(self, filename, name, icon): | ||
QTreeWidgetItem.__init__(self) | ||
self.name = name | ||
self.filename = filename | ||
self.setText(0, name) | ||
self.setIcon(0, icon) | ||
self.setCheckState(0, Qt.Unchecked) | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
python/plugins/processing/script/scripts/Unique_values_count.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.