Skip to content

Commit

Permalink
Merge pull request #5926 from nyalldawson/proc_dialog
Browse files Browse the repository at this point in the history
[processing] Add api to show algorithm dialog, use dialog for history
  • Loading branch information
nyalldawson committed Dec 27, 2017
2 parents d58053d + b25681c commit e7e37ef
Show file tree
Hide file tree
Showing 9 changed files with 154 additions and 31 deletions.
31 changes: 26 additions & 5 deletions python/gui/processing/qgsprocessingalgorithmdialogbase.sip
Expand Up @@ -69,6 +69,19 @@ Switches the dialog to the log page.
bool wasExecuted() const;
%Docstring
Returns true if an algorithm was executed in the dialog.

.. seealso:: :py:func:`results()`

.. seealso:: :py:func:`setExecuted()`
%End

QVariantMap results() const;
%Docstring
Returns the results returned by the algorithm executed.

.. seealso:: :py:func:`wasExecuted()`

.. seealso:: :py:func:`setResults()`
%End

QgsProcessingFeedback *createFeedback() /Factory/;
Expand All @@ -86,8 +99,6 @@ Returns the parameter values for the algorithm to run in the dialog.

virtual void accept();

virtual void reject();


void reportError( const QString &error );
%Docstring
Expand Down Expand Up @@ -126,9 +137,6 @@ Pushes a console info string to the dialog's log.

protected:

virtual void closeEvent( QCloseEvent *e );


QPushButton *runButton();
%Docstring
Returns the dialog's run button.
Expand Down Expand Up @@ -157,6 +165,19 @@ Clears any current progress from the dialog.
void setExecuted( bool executed );
%Docstring
Sets whether the algorithm was executed through the dialog.

.. seealso:: :py:func:`wasExecuted()`

.. seealso:: :py:func:`setResults()`
%End

void setResults( const QVariantMap &results );
%Docstring
Sets the algorithm results.

.. seealso:: :py:func:`results()`

.. seealso:: :py:func:`setExecuted()`
%End

void setInfo( const QString &message, bool isError = false, bool escapeHtml = true );
Expand Down
4 changes: 4 additions & 0 deletions python/plugins/processing/gui/AlgorithmDialog.py
Expand Up @@ -80,6 +80,9 @@ def runAsBatch(self):
dlg.show()
dlg.exec_()

def setParameters(self, parameters):
self.mainWidget().setParameters(parameters)

def getParameterValues(self):
parameters = {}

Expand Down Expand Up @@ -273,6 +276,7 @@ def finish(self, successful, result, context, feedback):
return

self.setExecuted(True)
self.setResults(result)
self.setInfo(self.tr('Algorithm \'{0}\' finished').format(self.algorithm().displayName()), escapeHtml=False)

if not keepOpen:
Expand Down
6 changes: 6 additions & 0 deletions python/plugins/processing/gui/DestinationSelectionPanel.py
Expand Up @@ -266,6 +266,12 @@ def selectDirectory(self):
self.leText.setText(QDir.toNativeSeparators(dirName))
settings.setValue('/Processing/LastOutputPath', dirName)

def setValue(self, value):
if value == 'memory:':
self.saveToTemporary()
else:
self.leText.setText(value)

def getValue(self):
key = None
if self.use_temporary and isinstance(self.parameter, QgsProcessingParameterFeatureSink):
Expand Down
3 changes: 2 additions & 1 deletion python/plugins/processing/gui/HistoryDialog.py
Expand Up @@ -113,7 +113,8 @@ def executeAlgorithm(self):
if item.isAlg:
script = 'import processing\n'
script += 'from qgis.core import QgsProcessingOutputLayerDefinition, QgsProcessingFeatureSourceDefinition\n'
script += item.entry.text.replace('processing.run(', 'processing.runAndLoadResults(')
script += item.entry.text.replace('processing.run(', 'processing.execAlgorithmDialog(')
self.close()
exec(script)

def changeText(self):
Expand Down
15 changes: 15 additions & 0 deletions python/plugins/processing/gui/ParametersPanel.py
Expand Up @@ -183,6 +183,21 @@ def initWidgets(self):
for wrapper in list(self.wrappers.values()):
wrapper.postInitialize(list(self.wrappers.values()))

def setParameters(self, parameters):
for param in self.alg.parameterDefinitions():
if param.flags() & QgsProcessingParameterDefinition.FlagHidden:
continue

if not param.name() in parameters:
continue

if not param.isDestination():
wrapper = self.wrappers[param.name()]
wrapper.setValue(parameters[param.name()])
else:
dest_widget = self.outputWidgets[param.name()]
dest_widget.setValue(parameters[param.name()])

def buttonToggled(self, value):
if value:
sender = self.sender()
Expand Down
24 changes: 21 additions & 3 deletions python/plugins/processing/gui/wrappers.py
Expand Up @@ -782,7 +782,13 @@ def selectFile(self):

def setValue(self, value):
if self.dialogType == DIALOG_STANDARD:
pass # TODO
if self.combo.findText(value) >= 0:
self.combo.setCurrentIndex(self.combo.findText(value))
else:
items = self.combo.additionalItems()
items.append(value)
self.combo.setAdditionalItems(items)
self.combo.setCurrentIndex(self.combo.findText(value))
elif self.dialogType == DIALOG_BATCH:
self.widget.setText(value)
else:
Expand Down Expand Up @@ -985,7 +991,13 @@ def selectFile(self):

def setValue(self, value):
if self.dialogType == DIALOG_STANDARD:
pass # TODO
if self.combo.findText(value) >= 0:
self.combo.setCurrentIndex(self.combo.findText(value))
else:
items = self.combo.additionalItems()
items.append(value)
self.combo.setAdditionalItems(items)
self.combo.setCurrentIndex(self.combo.findText(value))
elif self.dialogType == DIALOG_BATCH:
self.widget.setValue(value)
else:
Expand Down Expand Up @@ -1262,7 +1274,13 @@ def selectFile(self):

def setValue(self, value):
if self.dialogType == DIALOG_STANDARD:
pass # TODO
if self.combo.findText(value) >= 0:
self.combo.setCurrentIndex(self.combo.findText(value))
else:
items = self.combo.additionalItems()
items.append(value)
self.combo.setAdditionalItems(items)
self.combo.setCurrentIndex(self.combo.findText(value))
elif self.dialogType == DIALOG_BATCH:
return self.widget.setText(value)
else:
Expand Down
53 changes: 53 additions & 0 deletions python/plugins/processing/tools/general.py
Expand Up @@ -38,6 +38,8 @@
QgsProject)
from processing.core.Processing import Processing
from processing.gui.Postprocessing import handleAlgorithmResults
from processing.gui.AlgorithmDialog import AlgorithmDialog
from qgis.utils import iface


def algorithmHelp(id):
Expand Down Expand Up @@ -105,3 +107,54 @@ def runAndLoadResults(algOrName, parameters, feedback=None, context=None):
parameters[param.name()] = p

return Processing.runAlgorithm(alg, parameters=parameters, onFinish=handleAlgorithmResults, feedback=feedback, context=context)


def createAlgorithmDialog(algOrName, parameters={}):
"""Creates and returns an algorithm dialog for the specified algorithm, prepopulated
with a given set of parameters. It is the caller's responsibility to execute
and delete this dialog.
"""
if isinstance(algOrName, QgsProcessingAlgorithm):
alg = algOrName
else:
alg = QgsApplication.processingRegistry().createAlgorithmById(algOrName)

if alg is None:
return False

dlg = alg.createCustomParametersWidget(iface.mainWindow())

if not dlg:
dlg = AlgorithmDialog(alg)

dlg.setParameters(parameters)

return dlg


def execAlgorithmDialog(algOrName, parameters={}):
"""Executes an algorithm dialog for the specified algorithm, prepopulated
with a given set of parameters.
Returns the algorithm's results.
"""
dlg = createAlgorithmDialog(algOrName, parameters)
if dlg is None:
return {}

canvas = iface.mapCanvas()
prevMapTool = canvas.mapTool()
dlg.show()
dlg.exec_()
if canvas.mapTool() != prevMapTool:
try:
canvas.mapTool().reset()
except:
pass
canvas.setMapTool(prevMapTool)

results = dlg.results()
# have to manually delete the dialog - otherwise it's owned by the
# iface mainWindow and never deleted
dlg.deleteLater()
return results
26 changes: 8 additions & 18 deletions src/gui/processing/qgsprocessingalgorithmdialogbase.cpp
Expand Up @@ -17,6 +17,7 @@
#include "qgssettings.h"
#include "qgshelp.h"
#include "qgsmessagebar.h"
#include "qgsgui.h"
#include "processing/qgsprocessingalgorithm.h"
#include "processing/qgsprocessingprovider.h"
#include <QToolButton>
Expand Down Expand Up @@ -83,8 +84,9 @@ QgsProcessingAlgorithmDialogBase::QgsProcessingAlgorithmDialogBase( QWidget *par
handleLayout->addStretch();
splitterHandle->setLayout( handleLayout );

QgsGui::instance()->enableAutoGeometryRestore( this );

QgsSettings settings;
restoreGeometry( settings.value( QStringLiteral( "/Processing/dialogBase" ) ).toByteArray() );
splitter->restoreState( settings.value( QStringLiteral( "/Processing/dialogBaseSplitter" ), QByteArray() ).toByteArray() );
mSplitterState = splitter->saveState();
splitterChanged( 0, 0 );
Expand Down Expand Up @@ -184,12 +186,6 @@ void QgsProcessingAlgorithmDialogBase::showLog()
mTabWidget->setCurrentIndex( 1 );
}

void QgsProcessingAlgorithmDialogBase::closeEvent( QCloseEvent *e )
{
saveWindowGeometry();
QDialog::closeEvent( e );
}

QPushButton *QgsProcessingAlgorithmDialogBase::runButton()
{
return mButtonRun;
Expand All @@ -210,19 +206,18 @@ void QgsProcessingAlgorithmDialogBase::setExecuted( bool executed )
mExecuted = executed;
}

void QgsProcessingAlgorithmDialogBase::finished( bool, const QVariantMap &, QgsProcessingContext &, QgsProcessingFeedback * )
void QgsProcessingAlgorithmDialogBase::setResults( const QVariantMap &results )
{

mResults = results;
}

void QgsProcessingAlgorithmDialogBase::accept()
void QgsProcessingAlgorithmDialogBase::finished( bool, const QVariantMap &, QgsProcessingContext &, QgsProcessingFeedback * )
{

}

void QgsProcessingAlgorithmDialogBase::reject()
void QgsProcessingAlgorithmDialogBase::accept()
{
saveWindowGeometry();
QDialog::reject();
}

void QgsProcessingAlgorithmDialogBase::openHelp()
Expand Down Expand Up @@ -330,11 +325,6 @@ QString QgsProcessingAlgorithmDialogBase::formatHelp( QgsProcessingAlgorithm *al
return QString();
}

void QgsProcessingAlgorithmDialogBase::saveWindowGeometry()
{

}

void QgsProcessingAlgorithmDialogBase::resetGui()
{
lblProgress->clear();
Expand Down
23 changes: 19 additions & 4 deletions src/gui/processing/qgsprocessingalgorithmdialogbase.h
Expand Up @@ -118,9 +118,18 @@ class GUI_EXPORT QgsProcessingAlgorithmDialogBase : public QDialog, private Ui::

/**
* Returns true if an algorithm was executed in the dialog.
* \see results()
* \see setExecuted()
*/
bool wasExecuted() const { return mExecuted; }

/**
* Returns the results returned by the algorithm executed.
* \see wasExecuted()
* \see setResults()
*/
QVariantMap results() const { return mResults; }

/**
* Creates a new processing feedback object, automatically connected to the appropriate
* slots in this dialog.
Expand All @@ -135,7 +144,6 @@ class GUI_EXPORT QgsProcessingAlgorithmDialogBase : public QDialog, private Ui::
public slots:

void accept() override;
void reject() override;

/**
* Reports an \a error string to the dialog's log.
Expand Down Expand Up @@ -174,8 +182,6 @@ class GUI_EXPORT QgsProcessingAlgorithmDialogBase : public QDialog, private Ui::

protected:

void closeEvent( QCloseEvent *e ) override;

/**
* Returns the dialog's run button.
*/
Expand Down Expand Up @@ -203,9 +209,18 @@ class GUI_EXPORT QgsProcessingAlgorithmDialogBase : public QDialog, private Ui::

/**
* Sets whether the algorithm was executed through the dialog.
* \see wasExecuted()
* \see setResults()
*/
void setExecuted( bool executed );

/**
* Sets the algorithm results.
* \see results()
* \see setExecuted()
*/
void setResults( const QVariantMap &results );

/**
* Displays an info \a message in the dialog's log.
*/
Expand Down Expand Up @@ -250,12 +265,12 @@ class GUI_EXPORT QgsProcessingAlgorithmDialogBase : public QDialog, private Ui::
QgsMessageBar *mMessageBar = nullptr;

bool mExecuted = false;
QVariantMap mResults;
QWidget *mMainWidget = nullptr;
QgsProcessingAlgorithm *mAlgorithm = nullptr;
bool mHelpCollapsed = false;

QString formatHelp( QgsProcessingAlgorithm *algorithm );
void saveWindowGeometry();

};

Expand Down

0 comments on commit e7e37ef

Please sign in to comment.