take screenshots in app for user documentation

This commit is contained in:
Denis Rouzaud 2018-09-26 08:30:29 -04:00
parent 2a974e304c
commit ffdf617277
10 changed files with 175 additions and 0 deletions

View File

@ -598,6 +598,13 @@ used for interacting and adding widgets and messages to the app's
status bar (do not use the native Qt statusBar() method).
.. versionadded:: 3.0
%End
virtual void takeAppScreenShots( const QString &saveDirectory, const int categories = 0 );
%Docstring
Take screenshots for the user documentation
.. versionadded:: 3.4
%End
public slots: // TODO: do these functions really need to be slots?

View File

@ -13,6 +13,7 @@ SET(QGIS_APP_SRCS
qgsappwindowmanager.cpp
qgsaddattrdialog.cpp
qgsaddtaborgroup.cpp
qgsappscreenshots.cpp
qgsjoindialog.cpp
qgsannotationwidget.cpp
qgsattributeactiondialog.cpp
@ -236,6 +237,7 @@ SET (QGIS_APP_MOC_HDRS
qgsaddattrdialog.h
qgsalignrasterdialog.h
qgsappbrowserproviders.h
qgsappscreenshots.h
qgsjoindialog.h
qgsaddtaborgroup.h
qgsannotationwidget.h

View File

@ -149,6 +149,7 @@ Q_GUI_EXPORT extern int qt_defaultDpiX();
#include "qgsauthcertutils.h"
#include "qgsauthsslerrorsdialog.h"
#endif
#include "qgsappscreenshots.h"
#include "qgsbookmarks.h"
#include "qgsbrowserdockwidget.h"
#include "qgsadvanceddigitizingdockwidget.h"
@ -13062,6 +13063,12 @@ void QgisApp::zoomToBookmarkIndex( const QModelIndex &index )
mBookMarksDockWidget->zoomToBookmarkIndex( index );
}
void QgisApp::takeAppScreenShots( const QString &saveDirectory, const int categories )
{
QgsAppScreenShots ass( saveDirectory );
ass.takeScreenshots( QgsAppScreenShots::Categories( categories ) );
}
// Slot that gets called when the project file was saved with an older
// version of QGIS

View File

@ -696,6 +696,9 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
//! Returns pointer to the identify map tool - used by identify tool in 3D view
QgsMapToolIdentifyAction *identifyMapTool() const { return mMapTools.mIdentify; }
//! Take screenshots for user documentation
void takeAppScreenShots( const QString &saveDirectory, const int categories = 0 );
public slots:
//! save current vector layer
void saveAsFile( QgsMapLayer *layer = nullptr, bool onlySelected = false );

View File

@ -789,3 +789,8 @@ bool QgisAppInterface::askForDatumTransform( QgsCoordinateReferenceSystem source
{
return qgis->askUserForDatumTransform( sourceCrs, destinationCrs );
}
void QgisAppInterface::takeAppScreenShots( const QString &saveDirectory, const int categories )
{
return qgis->takeAppScreenShots( saveDirectory, categories );
}

View File

@ -551,6 +551,8 @@ class APP_EXPORT QgisAppInterface : public QgisInterface
bool askForDatumTransform( QgsCoordinateReferenceSystem sourceCrs, QgsCoordinateReferenceSystem destinationCrs ) override;
void takeAppScreenShots( const QString &saveDirectory, const int categories = 0 ) override;
private slots:

View File

@ -0,0 +1,96 @@
#include <QWindow>
#include <QScreen>
#include <QImageWriter>
#include "qgsappscreenshots.h"
#include "qgsvectorlayerproperties.h"
#include "qgsvectorlayer.h"
#include "qgsproject.h"
#include "qgsmessagelog.h"
QgsAppScreenShots::QgsAppScreenShots( const QString &saveDirectory )
: mSaveDirectory( saveDirectory )
{
QString layerDef = QStringLiteral( "Point?crs=epsg:4326&field=pk:integer&field=my_text:string&field=my_integer:integer&field=my_double:double&key=pk" );
mVectorLayer = new QgsVectorLayer( layerDef, QStringLiteral( "Layer" ), QStringLiteral( "memory" ) );
QgsProject::instance()->addMapLayer( mVectorLayer );
}
void QgsAppScreenShots::saveScreenshot( const QString &name, QWidget *widget, GrabMode mode )
{
QPixmap pix;
int x = 0;
int y = 0;
int w = -1;
int h = -1;
QScreen *screen = QGuiApplication::primaryScreen();
if ( widget )
{
const QWindow *window = widget->windowHandle();
if ( window )
{
screen = window->screen();
}
widget->raise();
if ( mode == GrabWidget )
{
pix = widget->grab();
}
else if ( mode == GrabWidgetAndFrame )
{
const QRect geom = widget->frameGeometry();
QPoint tl = geom.topLeft();
x = tl.x();
y = tl.y();
w = geom.width();
h = geom.height();
}
}
if ( !widget || mode != GrabWidget )
{
pix = screen->grabWindow( 0, x, y, w, h );
}
const QString &fileName = mSaveDirectory + "/" + name + ".png";
pix.save( fileName );
QMetaEnum metaEnum = QMetaEnum::fromType<GrabMode>();
QgsMessageLog::logMessage( QString( "Screenshot saved: %1 (%2)" ).arg( fileName, metaEnum.key( mode ) ) );
}
void QgsAppScreenShots::takeScreenshots( Categories categories )
{
if ( !categories || categories.testFlag( VectorLayerProperties ) )
takeVectorLayerProperties();
}
void QgsAppScreenShots::takeVectorLayerProperties()
{
QgsVectorLayerProperties *dlg = new QgsVectorLayerProperties( mVectorLayer );
dlg->show();
// ----------------
// do all the pages
for ( int row = 0; row < dlg->mOptionsListWidget->count(); ++row )
{
dlg->mOptionsListWidget->setCurrentRow( row );
dlg->adjustSize();
QCoreApplication::processEvents();
QString name = dlg->mOptionsListWidget->item( row )[0].text().toLower();
name.replace( " ", "_" );
saveScreenshot( name, dlg );
}
// ------------------
// style menu clicked
dlg->mOptionsListWidget->setCurrentRow( 0 );
QCoreApplication::processEvents();
dlg->mBtnStyle->click();
saveScreenshot( "style", dlg );
// exit properly
dlg->close();
dlg->deleteLater();
}

View File

@ -0,0 +1,45 @@
#ifndef QGSAPPSCREENSHOTS_H
#define QGSAPPSCREENSHOTS_H
#include <QObject>
class QgsVectorLayer;
class QgsAppScreenShots
{
Q_GADGET
public:
enum GrabMode
{
GrabWidget,
GrabWidgetAndFrame,
GrabWholeWindow
};
Q_ENUM( GrabMode )
enum Category
{
VectorLayerProperties = 1,
};
Q_ENUM( Category )
Q_DECLARE_FLAGS( Categories, Category )
Q_FLAG( Categories )
QgsAppScreenShots( const QString &saveDirectory );
//! if categories is null, then takes all categories
void takeScreenshots( Categories categories = nullptr );
private:
void takeVectorLayerProperties();
void saveScreenshot( const QString &name, QWidget *widget = nullptr, GrabMode mode = GrabWidgetAndFrame );
QString mSaveDirectory;
QgsVectorLayer *mVectorLayer = nullptr;
};
Q_DECLARE_OPERATORS_FOR_FLAGS( QgsAppScreenShots::Categories )
#endif // QGSAPPSCREENSHOTS_H

View File

@ -251,6 +251,8 @@ class APP_EXPORT QgsVectorLayerProperties : public QgsOptionsDialogBase, private
private slots:
void openPanel( QgsPanelWidget *panel );
friend class QgsAppScreenShots;
};

View File

@ -528,6 +528,12 @@ class GUI_EXPORT QgisInterface : public QObject
*/
virtual QgsStatusBar *statusBarIface() = 0;
/**
* Take screenshots for the user documentation
* \since QGIS 3.4
*/
virtual void takeAppScreenShots( const QString &saveDirectory, const int categories = 0 ) {Q_UNUSED( saveDirectory ); Q_UNUSED( categories );}
public slots: // TODO: do these functions really need to be slots?
/* Exposed functions */