Skip to content
Permalink
Browse files

[FEATURE][geonode] integration - copy style action

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 e2678936df84d0c0a58fb04e899e5d4bb8d561ea
@@ -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.
@@ -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 };
@@ -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
@@ -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 )
@@ -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()
@@ -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.
@@ -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() )
@@ -12,6 +12,10 @@
* (at your option) any later version. *
* *
***************************************************************************/

#include <QClipboard>
#include <QMenu>

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

#ifdef HAVE_GUI
#include "qgsnewhttpconnection.h"
@@ -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
//
@@ -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();
};


0 comments on commit e267893

Please sign in to comment.
You can’t perform that action at this time.