Skip to content

Commit

Permalink
[FEATURE][geonode] integration - copy style action
Browse files Browse the repository at this point in the history
Allows copying styles directly from geonode layers for pasting into project layers.
  • Loading branch information
myarjunar authored and nyalldawson committed Sep 23, 2017
1 parent 54e5bfd commit e267893
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 5 deletions.
11 changes: 11 additions & 0 deletions python/core/qgsdataitem.sip
Expand Up @@ -141,6 +141,17 @@ Create new data item.
:rtype: list of QAction
%End

virtual QList<QMenu *> menus( QWidget *parent );
%Docstring
Returns the list of menus available for this item. This is usually used for the popup menu on right-clicking
the item. Subclasses should override this to provide actions. Subclasses should ensure that ownership of
created menus is correctly handled by parenting them to the specified parent widget.
\param parent a parent widget of the menu
:return: list of menus
.. versionadded:: 3.0
:rtype: list of QMenu
%End

virtual bool acceptDrop();
%Docstring
Returns whether the item accepts drag and dropped layers - e.g. for importing a dataset to a provider.
Expand Down
1 change: 1 addition & 0 deletions python/core/symbology/qgsstyle.sip
Expand Up @@ -15,6 +15,7 @@
typedef QMap<QString, QgsColorRamp * > QgsVectorColorRampMap;
typedef QMap<int, QString> QgsSymbolGroupMap;


typedef QMultiMap<QString, QString> QgsSmartConditionMap;

enum SymbolTable { SymbolId, SymbolName, SymbolXML, SymbolFavoriteId };
Expand Down
5 changes: 0 additions & 5 deletions src/app/qgsclipboard.h
Expand Up @@ -46,11 +46,6 @@
class QgsVectorLayer;
class QgsFeatureStore;

/*
* Constants used to describe copy-paste MIME types
*/
#define QGSCLIPBOARD_STYLE_MIME "application/qgis.style"

class APP_EXPORT QgsClipboard : public QObject
{
Q_OBJECT
Expand Down
6 changes: 6 additions & 0 deletions src/core/qgsdataitem.cpp
Expand Up @@ -558,6 +558,12 @@ void QgsDataItem::setState( State state )
updateIcon();
}

QList<QMenu *> QgsDataItem::menus( QWidget *parent )
{
Q_UNUSED( parent );
return QList<QMenu *>();
}

// ---------------------------------------------------------------------

QgsLayerItem::QgsLayerItem( QgsDataItem *parent, const QString &name, const QString &path, const QString &uri, LayerType layerType, const QString &providerKey )
Expand Down
9 changes: 9 additions & 0 deletions src/core/qgsdataitem.h
Expand Up @@ -148,6 +148,15 @@ class CORE_EXPORT QgsDataItem : public QObject
*/
virtual QList<QAction *> actions( QWidget *parent );

/** Returns the list of menus available for this item. This is usually used for the popup menu on right-clicking
* the item. Subclasses should override this to provide actions. Subclasses should ensure that ownership of
* created menus is correctly handled by parenting them to the specified parent widget.
* \param parent a parent widget of the menu
* \returns list of menus
* \since QGIS 3.0
*/
virtual QList<QMenu *> menus( QWidget *parent );

/** Returns whether the item accepts drag and dropped layers - e.g. for importing a dataset to a provider.
* Subclasses should override this and handleDrop() to accept dropped layers.
* \see handleDrop()
Expand Down
5 changes: 5 additions & 0 deletions src/core/symbology/qgsstyle.h
Expand Up @@ -36,6 +36,11 @@ class QDomElement;
typedef QMap<QString, QgsColorRamp * > QgsVectorColorRampMap;
typedef QMap<int, QString> QgsSymbolGroupMap;

/*
* Constants used to describe copy-paste MIME types
*/
#define QGSCLIPBOARD_STYLE_MIME "application/qgis.style"

/** \ingroup core
* A multimap to hold the smart group conditions as constraint and parameter pairs.
* Both the key and the value of the map are QString. The key is the constraint of the condition and the value is the parameter which is applied for the constraint.
Expand Down
10 changes: 10 additions & 0 deletions src/gui/qgsbrowserdockwidget.cpp
Expand Up @@ -209,7 +209,17 @@ void QgsBrowserDockWidget::showContextMenu( QPoint pt )
menu->addAction( tr( "Add a Directory..." ), this, SLOT( addFavoriteDirectory() ) );
}

const QList<QMenu *> menus = item->menus( menu );
QList<QAction *> actions = item->actions( menu );

if ( !menus.isEmpty() )
{
for ( QMenu *mn : menus )
{
menu->addMenu( mn );
}
}

if ( !actions.isEmpty() )
{
if ( !menu->actions().isEmpty() )
Expand Down
79 changes: 79 additions & 0 deletions src/providers/wfs/qgswfsdataitems.cpp
Expand Up @@ -12,6 +12,10 @@
* (at your option) any later version. *
* *
***************************************************************************/

#include <QClipboard>
#include <QMenu>

#include "qgsdataitemprovider.h"
#include "qgsdataprovider.h"
#include "qgslogger.h"
Expand All @@ -23,6 +27,7 @@
#include "qgssettings.h"
#include "qgsgeonodeconnection.h"
#include "qgsgeonoderequest.h"
#include "qgsstyle.h"

#ifdef HAVE_GUI
#include "qgsnewhttpconnection.h"
Expand All @@ -44,12 +49,86 @@ QgsWfsLayerItem::QgsWfsLayerItem( QgsDataItem *parent, QString name, const QgsDa
mUri = QgsWFSDataSourceURI::build( uri.uri(), featureType, crsString, QString(), useCurrentViewExtent );
setState( Populated );
mIconName = QStringLiteral( "mIconConnect.png" );
mBaseUri = uri.param( QString( "url" ) );
}

QgsWfsLayerItem::~QgsWfsLayerItem()
{
}

QList<QMenu *> QgsWfsLayerItem::menus( QWidget *parent )
{
QList<QMenu *> menus;

if ( mPath.startsWith( QLatin1String( "geonode:/" ) ) )
{
QMenu *menuStyleManager = new QMenu( tr( "Styles" ), parent );

QAction *actionCopyStyle = new QAction( tr( "Copy Style" ), menuStyleManager );
connect( actionCopyStyle, &QAction::triggered, this, &QgsWfsLayerItem::copyStyle );

menuStyleManager->addAction( actionCopyStyle );
menus << menuStyleManager;
}

return menus;
}

void QgsWfsLayerItem::copyStyle()
{
std::unique_ptr< QgsGeoNodeConnection > connection;
const QStringList connections = QgsGeoNodeConnectionUtils::connectionList();
for ( const QString &connName : connections )
{
connection.reset( new QgsGeoNodeConnection( connName ) );
if ( mBaseUri.contains( connection->uri().param( QString( "url" ) ) ) )
break;
else
connection.reset( nullptr );
}

if ( !connection )
{
QString errorMsg( QStringLiteral( "Cannot get style for layer %1" ).arg( this->name() ) );
QgsDebugMsg( " Cannot get style: " + errorMsg );
#if 0
// TODO: how to emit message from provider (which does not know about QgisApp)
QgisApp::instance()->messageBar()->pushMessage( tr( "Cannot copy style" ),
errorMsg,
QgsMessageBar::CRITICAL, messageTimeout() );
#endif
return;
}

QString url( connection->uri().encodedUri() );
QgsGeoNodeRequest geoNodeRequest( url.replace( QString( "url=" ), QString() ), true );
QgsGeoNodeStyle style = geoNodeRequest.fetchDefaultStyleBlocking( this->name() );
if ( style.name.isEmpty() )
{
QString errorMsg( QStringLiteral( "Cannot get style for layer %1" ).arg( this->name() ) );
QgsDebugMsg( " Cannot get style: " + errorMsg );
#if 0
// TODO: how to emit message from provider (which does not know about QgisApp)
QgisApp::instance()->messageBar()->pushMessage( tr( "Cannot copy style" ),
errorMsg,
QgsMessageBar::CRITICAL, messageTimeout() );
#endif
return;
}

QClipboard *clipboard = QApplication::clipboard();

QMimeData *mdata = new QMimeData();
mdata->setData( QGSCLIPBOARD_STYLE_MIME, style.body.toByteArray() );
mdata->setText( style.body.toString() );
// Copies data in text form as well, so the XML can be pasted into a text editor
if ( clipboard->supportsSelection() )
clipboard->setMimeData( mdata, QClipboard::Selection );
clipboard->setMimeData( mdata, QClipboard::Clipboard );
// Enables the paste menu element
// actionPasteStyle->setEnabled( true );
}

//
// QgsWfsConnectionItem
//
Expand Down
14 changes: 14 additions & 0 deletions src/providers/wfs/qgswfsdataitems.h
Expand Up @@ -79,6 +79,20 @@ class QgsWfsLayerItem : public QgsLayerItem
QgsWfsLayerItem( QgsDataItem *parent, QString name, const QgsDataSourceUri &uri, QString featureType, QString title, QString crsString );
~QgsWfsLayerItem();

virtual QList<QMenu *> menus( QWidget *parent ) override;

protected:
QString mBaseUri;

private slots:

/** Get style of the active data item (geonode layer item) and copy it to the clipboard.
*/
void copyStyle();

/** Paste style on the clipboard to the active data item (geonode layer item) and push it to the source.
*/
// void pasteStyle();
};


Expand Down

0 comments on commit e267893

Please sign in to comment.