[FEATURE][processing] Add buttons to save/clear/copy log

In the algorithm execution dialog, this adds buttons to allow
users to save the current log (to text or HTML files), copy the
log contents to the clipboard, and clear the log.
This commit is contained in:
Nyall Dawson 2018-04-19 11:39:47 +10:00
parent 0dfb3c2d8c
commit 4a594d3f32
4 changed files with 251 additions and 1 deletions

View File

@ -28,6 +28,12 @@ class QgsProcessingAlgorithmDialogBase : QDialog
%End
public:
enum LogFormat
{
FormatPlainText,
FormatHtml,
};
QgsProcessingAlgorithmDialogBase( QWidget *parent = 0, Qt::WindowFlags flags = 0 );
%Docstring
Constructor for QgsProcessingAlgorithmDialogBase.
@ -93,6 +99,16 @@ slots in this dialog.
virtual QVariantMap getParameterValues() const;
%Docstring
Returns the parameter values for the algorithm to run in the dialog.
%End
void saveLogToFile( const QString &path, LogFormat format = FormatPlainText );
%Docstring
Saves the log contents to a text file (specified by the file ``path``), in
the given ``format``.
.. versionadded:: 3.2
.. seealso:: :py:func:`saveLog`
%End
public slots:
@ -141,6 +157,29 @@ Pushes a console info string to the dialog's log.
%Docstring
Creates a modal progress dialog showing progress and log messages
from this dialog.
%End
void clearLog();
%Docstring
Clears the current log contents.
.. versionadded:: 3.2
%End
void saveLog();
%Docstring
Opens a dialog allowing users to save the current log contents.
.. versionadded:: 3.2
.. seealso:: :py:func:`saveLogToFile`
%End
void copyLogToClipboard();
%Docstring
Copies the current log contents to the clipboard.
.. versionadded:: 3.2
%End
protected:

View File

@ -25,6 +25,10 @@
#include <QToolButton>
#include <QDesktopServices>
#include <QScrollBar>
#include <QApplication>
#include <QClipboard>
#include <QFileDialog>
///@cond NOT_STABLE
@ -108,6 +112,10 @@ QgsProcessingAlgorithmDialogBase::QgsProcessingAlgorithmDialogBase( QWidget *par
connect( mButtonCollapse, &QToolButton::clicked, this, &QgsProcessingAlgorithmDialogBase::toggleCollapsed );
connect( splitter, &QSplitter::splitterMoved, this, &QgsProcessingAlgorithmDialogBase::splitterChanged );
connect( mButtonSaveLog, &QToolButton::clicked, this, &QgsProcessingAlgorithmDialogBase::saveLog );
connect( mButtonCopyLog, &QToolButton::clicked, this, &QgsProcessingAlgorithmDialogBase::copyLogToClipboard );
connect( mButtonClearLog, &QToolButton::clicked, this, &QgsProcessingAlgorithmDialogBase::clearLog );
mMessageBar = new QgsMessageBar();
mMessageBar->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
verticalLayout->insertWidget( 0, mMessageBar );
@ -165,6 +173,27 @@ QVariantMap QgsProcessingAlgorithmDialogBase::getParameterValues() const
return QVariantMap();
}
void QgsProcessingAlgorithmDialogBase::saveLogToFile( const QString &path, const LogFormat format )
{
QFile logFile( path );
if ( !logFile.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate ) )
{
return;
}
QTextStream fout( &logFile );
switch ( format )
{
case FormatPlainText:
fout << txtLog->toPlainText();
break;
case FormatHtml:
fout << txtLog->toHtml();
break;
}
}
QgsProcessingFeedback *QgsProcessingAlgorithmDialogBase::createFeedback()
{
auto feedback = qgis::make_unique< QgsProcessingAlgorithmDialogFeedback >();
@ -369,6 +398,49 @@ QDialog *QgsProcessingAlgorithmDialogBase::createProgressDialog()
return dialog;
}
void QgsProcessingAlgorithmDialogBase::clearLog()
{
txtLog->clear();
}
void QgsProcessingAlgorithmDialogBase::saveLog()
{
QgsSettings settings;
QString lastUsedDir = settings.value( QStringLiteral( "/Processing/lastUsedLogDirectory" ), QDir::homePath() ).toString();
QString filter;
const QString txtExt = tr( "Text files" ) + QStringLiteral( " (*.txt *.TXT)" );
const QString htmlExt = tr( "HTML files" ) + QStringLiteral( " (*.html *.HTML)" );
QString path = QFileDialog::getSaveFileName( this, tr( "Save Log to File" ), lastUsedDir, txtExt + ";;" + htmlExt, &filter );
if ( path.isEmpty() )
{
return;
}
settings.setValue( QStringLiteral( "/Processing/lastUsedLogDirectory" ), QFileInfo( path ).path() );
LogFormat format = FormatPlainText;
if ( filter == htmlExt )
{
format = FormatHtml;
}
saveLogToFile( path, format );
}
void QgsProcessingAlgorithmDialogBase::copyLogToClipboard()
{
QMimeData *m = new QMimeData();
m->setText( txtLog->toPlainText() );
m->setHtml( txtLog->toHtml() );
QClipboard *cb = QApplication::clipboard();
#ifdef Q_OS_LINUX
cb->setMimeData( m, QClipboard::Selection );
#endif
cb->setMimeData( m, QClipboard::Clipboard );
}
void QgsProcessingAlgorithmDialogBase::closeEvent( QCloseEvent *e )
{
QDialog::closeEvent( e );

View File

@ -85,6 +85,16 @@ class GUI_EXPORT QgsProcessingAlgorithmDialogBase : public QDialog, private Ui::
public:
/**
* Log format options.
* \since QGIS 3.2
*/
enum LogFormat
{
FormatPlainText, //!< Plain text file (.txt)
FormatHtml, //!< HTML file (.html)
};
/**
* Constructor for QgsProcessingAlgorithmDialogBase.
*/
@ -144,6 +154,14 @@ class GUI_EXPORT QgsProcessingAlgorithmDialogBase : public QDialog, private Ui::
*/
virtual QVariantMap getParameterValues() const;
/**
* Saves the log contents to a text file (specified by the file \a path), in
* the given \a format.
* \since QGIS 3.2
* \see saveLog()
*/
void saveLogToFile( const QString &path, LogFormat format = FormatPlainText );
public slots:
void accept() override;
@ -191,6 +209,25 @@ class GUI_EXPORT QgsProcessingAlgorithmDialogBase : public QDialog, private Ui::
*/
QDialog *createProgressDialog();
/**
* Clears the current log contents.
* \since QGIS 3.2
*/
void clearLog();
/**
* Opens a dialog allowing users to save the current log contents.
* \since QGIS 3.2
* \see saveLogToFile()
*/
void saveLog();
/**
* Copies the current log contents to the clipboard.
* \since QGIS 3.2
*/
void copyLogToClipboard();
protected:
void closeEvent( QCloseEvent *e ) override;

View File

@ -87,6 +87,77 @@
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="mButtonSaveLog">
<property name="toolTip">
<string>Save Log to File</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../images/images.qrc">
<normaloff>:/images/themes/default/mActionFileSave.svg</normaloff>:/images/themes/default/mActionFileSave.svg</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="mButtonCopyLog">
<property name="toolTip">
<string>Copy Log to Clipboard</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../images/images.qrc">
<normaloff>:/images/themes/default/mActionEditCopy.svg</normaloff>:/images/themes/default/mActionEditCopy.svg</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="mButtonClearLog">
<property name="toolTip">
<string>Clear Log</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../images/images.qrc">
<normaloff>:/images/themes/default/console/iconClearConsole.svg</normaloff>:/images/themes/default/console/iconClearConsole.svg</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
@ -146,6 +217,37 @@
</item>
</layout>
</widget>
<resources/>
<resources>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
</resources>
<connections/>
</ui>