[FEATURE][layouts] Support drag and drop of QPT templates onto layout windows

To add contents of template onto layout
This commit is contained in:
Nyall Dawson 2017-12-04 15:36:14 +10:00
parent eea36c0212
commit a64a675830
17 changed files with 180 additions and 10 deletions

View File

@ -51,7 +51,6 @@
%Include qgsfeaturestore.sip
%Include qgsfieldformatter.sip
%Include qgsfields.sip
%Include qgsfileutils.sip
%Include qgsfontutils.sip
%Include qgsgeometrysimplifier.sip
%Include qgshistogram.sip
@ -314,6 +313,7 @@
%Include qgsfieldmodel.sip
%Include qgsfieldproxymodel.sip
%Include qgsfiledownloader.sip
%Include qgsfileutils.sip
%Include qgsfeaturefiltermodel.sip
%Include qgsgeometryvalidator.sip
%Include qgsgml.sip

View File

@ -8,6 +8,7 @@
class QgsLayoutCustomDropHandler : QObject
{
%Docstring
@ -20,9 +21,15 @@ class QgsLayoutCustomDropHandler : QObject
#include "qgslayoutcustomdrophandler.h"
%End
public:
QgsLayoutCustomDropHandler( QObject *parent /TransferThis/ = 0 );
%Docstring
Constructor for QgsLayoutCustomDropHandler.
%End
virtual ~QgsLayoutCustomDropHandler();
virtual bool handleFileDrop( const QString &file );
virtual bool handleFileDrop( QgsLayoutDesignerInterface *iface, const QString &file );
%Docstring
Called when the specified ``file`` has been dropped onto a QGIS layout. If true
is returned, then the handler has accepted this file and it should not

View File

@ -48,6 +48,11 @@ class QgsLayoutDesignerInterface: QObject
:rtype: QgsLayoutView
%End
virtual void selectItems( const QList< QgsLayoutItem * > items ) = 0;
%Docstring
Selects the specified ``items``.
%End
public slots:
virtual void close() = 0;

View File

@ -468,6 +468,8 @@ class QgsLayoutView: QGraphicsView
virtual void scrollContentsBy( int dx, int dy );
virtual void dragEnterEvent( QDragEnterEvent *e );
};

View File

@ -195,6 +195,7 @@ SET(QGIS_APP_SRCS
layout/qgslayoutpolygonwidget.cpp
layout/qgslayoutpolylinewidget.cpp
layout/qgslayoutpropertieswidget.cpp
layout/qgslayoutqptdrophandler.cpp
layout/qgslayoutscalebarwidget.cpp
layout/qgslayoutshapewidget.cpp
layout/qgslayouttablebackgroundcolorsdialog.cpp
@ -408,6 +409,7 @@ SET (QGIS_APP_MOC_HDRS
layout/qgslayoutpolygonwidget.h
layout/qgslayoutpolylinewidget.h
layout/qgslayoutpropertieswidget.h
layout/qgslayoutqptdrophandler.h
layout/qgslayoutscalebarwidget.h
layout/qgslayoutshapewidget.h
layout/qgslayouttablebackgroundcolorsdialog.h

View File

@ -33,4 +33,6 @@ class QgsLayoutAppUtils
};
#endif // QGSLAYOUTAPPUTILS_H

View File

@ -83,6 +83,11 @@ QgsLayoutView *QgsAppLayoutDesignerInterface::view()
return mDesigner->view();
}
void QgsAppLayoutDesignerInterface::selectItems( const QList<QgsLayoutItem *> items )
{
mDesigner->selectItems( items );
}
void QgsAppLayoutDesignerInterface::close()
{
mDesigner->close();
@ -105,6 +110,7 @@ QgsLayoutDesignerDialog::QgsLayoutDesignerDialog( QWidget *parent, Qt::WindowFla
setupUi( this );
setWindowTitle( tr( "QGIS Layout Designer" ) );
setAcceptDrops( true );
setAttribute( Qt::WA_DeleteOnClose );
#if QT_VERSION >= 0x050600
@ -977,7 +983,7 @@ void QgsLayoutDesignerDialog::dropEvent( QDropEvent *event )
const QVector<QPointer<QgsLayoutCustomDropHandler >> handlers = QgisApp::instance()->customLayoutDropHandlers();
for ( QgsLayoutCustomDropHandler *handler : handlers )
{
if ( handler && handler->handleFileDrop( file ) )
if ( handler && handler->handleFileDrop( iface(), file ) )
{
break;
}
@ -991,6 +997,14 @@ void QgsLayoutDesignerDialog::dropEvent( QDropEvent *event )
timer->start();
}
void QgsLayoutDesignerDialog::dragEnterEvent( QDragEnterEvent *event )
{
if ( event->mimeData()->hasUrls() )
{
event->acceptProposedAction();
}
}
void QgsLayoutDesignerDialog::itemTypeAdded( int id )
{
if ( QgsGui::layoutItemGuiRegistry()->itemMetadata( id )->flags() & QgsLayoutItemAbstractGuiMetadata::FlagNoCreationTools )

View File

@ -50,6 +50,7 @@ class QgsAppLayoutDesignerInterface : public QgsLayoutDesignerInterface
QgsAppLayoutDesignerInterface( QgsLayoutDesignerDialog *dialog );
QgsLayout *layout() override;
QgsLayoutView *view() override;
void selectItems( const QList< QgsLayoutItem * > items ) override;
public slots:
@ -107,6 +108,11 @@ class QgsLayoutDesignerDialog: public QMainWindow, private Ui::QgsLayoutDesigner
*/
void showItemOptions( QgsLayoutItem *item, bool bringPanelToFront = true );
/**
* Selects the specified \a items.
*/
void selectItems( const QList< QgsLayoutItem * > items );
public slots:
/**
@ -237,8 +243,9 @@ class QgsLayoutDesignerDialog: public QMainWindow, private Ui::QgsLayoutDesigner
protected:
virtual void closeEvent( QCloseEvent * ) override;
virtual void dropEvent( QDropEvent *event ) override;
void closeEvent( QCloseEvent * ) override;
void dropEvent( QDropEvent *event ) override;
void dragEnterEvent( QDragEnterEvent *event ) override;
private slots:
@ -347,8 +354,6 @@ class QgsLayoutDesignerDialog: public QMainWindow, private Ui::QgsLayoutDesigner
void initializeRegistry();
void selectItems( const QList< QgsLayoutItem * > items );
};
#endif // QGSLAYOUTDESIGNERDIALOG_H

View File

@ -0,0 +1,63 @@
/***************************************************************************
qgslayoutqptdrophandler.cpp
------------------------------
begin : December 2017
copyright : (C) 2017 by nyall Dawson
email : nyall dot dawson 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. *
* *
***************************************************************************/
#include "qgslayoutqptdrophandler.h"
#include "qgslayoutdesignerinterface.h"
#include "qgslayout.h"
#include "qgsreadwritecontext.h"
#include "qgsproject.h"
#include "qgslayoutview.h"
#include <QMessageBox>
QgsLayoutQptDropHandler::QgsLayoutQptDropHandler( QObject *parent )
: QgsLayoutCustomDropHandler( parent )
{
}
bool QgsLayoutQptDropHandler::handleFileDrop( QgsLayoutDesignerInterface *iface, const QString &file )
{
QFileInfo fi( file );
if ( !fi.suffix().compare( QLatin1String( "qpt" ), Qt::CaseInsensitive ) == 0 )
return false;
QFile templateFile( file );
if ( !templateFile.open( QIODevice::ReadOnly ) )
{
QMessageBox::warning( iface->view(), tr( "Load from template" ), tr( "Could not read template file." ) );
return true;
}
QDomDocument templateDoc;
QgsReadWriteContext context;
context.setPathResolver( QgsProject::instance()->pathResolver() );
if ( templateDoc.setContent( &templateFile ) )
{
bool ok = false;
QList< QgsLayoutItem * > items = iface->layout()->loadFromTemplate( templateDoc, context, false, &ok );
if ( !ok )
{
QMessageBox::warning( iface->view(), tr( "Load from template" ), tr( "Could not read template file." ) );
return true;
}
else
{
whileBlocking( iface->layout() )->deselectAll();
iface->selectItems( items );
}
}
return true;
}

View File

@ -0,0 +1,32 @@
/***************************************************************************
qgslayoutqptdrophandler.h
-------------------------
begin : December 2017
copyright : (C) 2017 by nyall Dawson
email : nyall dot dawson 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. *
* *
***************************************************************************/
#ifndef QGSLAYOUTQPTDROPHANDLER_H
#define QGSLAYOUTQPTDROPHANDLER_H
#include "qgslayoutcustomdrophandler.h"
class QgsLayoutQptDropHandler : public QgsLayoutCustomDropHandler
{
Q_OBJECT
public:
QgsLayoutQptDropHandler( QObject *parent = nullptr );
virtual bool handleFileDrop( QgsLayoutDesignerInterface *iface, const QString &file );
};
#endif // QGSLAYOUTQPTDROPHANDLER_H

View File

@ -208,6 +208,7 @@ Q_GUI_EXPORT extern int qt_defaultDpiX();
#include "qgslayoutcustomdrophandler.h"
#include "qgslayoutdesignerdialog.h"
#include "qgslayoutmanager.h"
#include "qgslayoutqptdrophandler.h"
#include "qgslayoutapputils.h"
#include "qgslocatorwidget.h"
#include "qgslocator.h"
@ -1397,6 +1398,8 @@ QgisApp::~QgisApp()
// cancel request for FileOpen events
QgsApplication::setFileOpenEventReceiver( nullptr );
unregisterCustomLayoutDropHandler( mLayoutQptDropHandler );
delete mPythonUtils;
delete mTray;
delete mDataSourceManagerDialog;
@ -10245,6 +10248,9 @@ void QgisApp::initNativeProcessing()
void QgisApp::initLayouts()
{
QgsLayoutAppUtils::registerGuiForKnownItemTypes();
mLayoutQptDropHandler = new QgsLayoutQptDropHandler( this );
registerCustomLayoutDropHandler( mLayoutQptDropHandler );
}
void QgisApp::new3DMapCanvas()

View File

@ -129,6 +129,7 @@ class QgsLocatorWidget;
class QgsDataSourceManagerDialog;
class QgsBrowserModel;
class QgsGeoCmsProviderRegistry;
class QgsLayoutQptDropHandler;
#include <QMainWindow>
@ -2131,6 +2132,8 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
QVector<QPointer<QgsCustomDropHandler>> mCustomDropHandlers;
QVector<QPointer<QgsLayoutCustomDropHandler>> mCustomLayoutDropHandlers;
QgsLayoutQptDropHandler *mLayoutQptDropHandler = nullptr;
QDateTime mProjectLastModified;
QgsWelcomePage *mWelcomePage = nullptr;

View File

@ -15,8 +15,13 @@
#include "qgslayoutcustomdrophandler.h"
bool QgsLayoutCustomDropHandler::handleFileDrop( const QString &file )
QgsLayoutCustomDropHandler::QgsLayoutCustomDropHandler( QObject *parent )
: QObject( parent )
{
}
bool QgsLayoutCustomDropHandler::handleFileDrop( QgsLayoutDesignerInterface *, const QString & )
{
Q_UNUSED( file );
return false;
}

View File

@ -17,8 +17,11 @@
#define QGSLAYOUTCUSTOMDROPHANDLER_H
#include "qgis_gui.h"
#include "qgis_sip.h"
#include <QObject>
class QgsLayoutDesignerInterface;
/**
* \ingroup gui
* Abstract base class that may be implemented to handle new types of data to be dropped in QGIS layouts.
@ -30,6 +33,12 @@ class GUI_EXPORT QgsLayoutCustomDropHandler : public QObject
Q_OBJECT
public:
/**
* Constructor for QgsLayoutCustomDropHandler.
*/
QgsLayoutCustomDropHandler( QObject *parent SIP_TRANSFERTHIS = nullptr );
virtual ~QgsLayoutCustomDropHandler() = default;
/**
@ -39,7 +48,7 @@ class GUI_EXPORT QgsLayoutCustomDropHandler : public QObject
*
* The base class implementation does nothing.
*/
virtual bool handleFileDrop( const QString &file );
virtual bool handleFileDrop( QgsLayoutDesignerInterface *iface, const QString &file );
};
#endif // QGSLAYOUTCUSTOMDROPHANDLER_H

View File

@ -22,6 +22,7 @@
class QgsLayout;
class QgsLayoutView;
class QgsLayoutItem;
/**
* \ingroup gui
@ -62,6 +63,11 @@ class GUI_EXPORT QgsLayoutDesignerInterface: public QObject
*/
virtual QgsLayoutView *view() = 0;
/**
* Selects the specified \a items.
*/
virtual void selectItems( const QList< QgsLayoutItem * > items ) = 0;
public slots:
/**

View File

@ -972,6 +972,14 @@ void QgsLayoutView::scrollContentsBy( int dx, int dy )
viewChanged();
}
void QgsLayoutView::dragEnterEvent( QDragEnterEvent *e )
{
// By default graphics view delegates the drag events to graphics items.
// But we do not want that and by ignoring the drag enter we let the
// parent (e.g. QgsLayoutDesignerDialog) to handle drops of files.
e->ignore();
}
void QgsLayoutView::invalidateCachedRenders()
{
if ( !currentLayout() )

View File

@ -500,6 +500,7 @@ class GUI_EXPORT QgsLayoutView: public QGraphicsView
void keyReleaseEvent( QKeyEvent *event ) override;
void resizeEvent( QResizeEvent *event ) override;
void scrollContentsBy( int dx, int dy ) override;
void dragEnterEvent( QDragEnterEvent *e ) override;
private slots: