Skip to content
Permalink
Browse files

Merge pull request #5221 from nyalldawson/browser_awesome

Add QLR, processing models to browser
  • Loading branch information
nyalldawson committed Sep 20, 2017
2 parents d34fd9f + a67dab5 commit 15e650d6243cc45d2b95dee0f8fbc3b83b72d7b6
@@ -49,7 +49,8 @@ class QgsDataItem : QObject
Layer,
Error,
Favorites,
Project
Project,
Custom,
};


@@ -153,6 +154,15 @@ Create new data item.
:rtype: bool
%End

virtual bool handleDoubleClick();
%Docstring
Called when a user double clicks on the item. Subclasses should return true
if they have implemented a double-click handler and do not want the default
double-click behavior for items.
.. versionadded:: 3.0
:rtype: bool
%End

virtual bool hasDragEnabled() const;
%Docstring
Returns true if the item may be dragged.
@@ -33,10 +33,14 @@

from qgis.core import (QgsApplication,
QgsProcessingUtils,
QgsProcessingModelAlgorithm)
QgsProcessingModelAlgorithm,
QgsDataItemProvider,
QgsDataProvider,
QgsDataItem,
QgsMimeDataUtils)
from qgis.gui import (QgsOptionsWidgetFactory,
QgsCustomDropHandler)
from qgis.PyQt.QtCore import Qt, QCoreApplication, QDir
from qgis.PyQt.QtCore import Qt, QCoreApplication, QDir, QFileInfo
from qgis.PyQt.QtWidgets import QMenu, QAction
from qgis.PyQt.QtGui import QIcon

@@ -74,7 +78,10 @@ class ProcessingDropHandler(QgsCustomDropHandler):
def handleFileDrop(self, file):
if not file.lower().endswith('.model3'):
return False
self.runAlg(file)

@staticmethod
def runAlg(file):
alg = QgsProcessingModelAlgorithm()
if not alg.fromFile(file):
return False
@@ -85,6 +92,73 @@ def handleFileDrop(self, file):
dlg.show()
return True

def customUriProviderKey(self):
return 'processing'

def handleCustomUriDrop(self, uri):
path = uri.uri
self.runAlg(path)


class ProcessingModelItem(QgsDataItem):

def __init__(self, parent, name, path):
super(ProcessingModelItem, self).__init__(QgsDataItem.Custom, parent, name, path)
self.setState(QgsDataItem.Populated) # no children
self.setIconName(":/images/themes/default/processingModel.svg")
self.setToolTip(QDir.toNativeSeparators(path))

def hasDragEnabled(self):
return True

def handleDoubleClick(self):
self.runModel()
return True

def mimeUri(self):
u = QgsMimeDataUtils.Uri()
u.layerType = "custom"
u.providerKey = "processing"
u.name = self.name()
u.uri = self.path()
return u

def runModel(self):
ProcessingDropHandler.runAlg(self.path())

def editModel(self):
dlg = ModelerDialog()
dlg.loadModel(self.path())
dlg.show()

def actions(self):
run_model_action = QAction(self.tr('&Run Model…'), self)
run_model_action.triggered.connect(self.runModel)
edit_model_action = QAction(self.tr('&Edit Model…'), self)
edit_model_action.triggered.connect(self.editModel)
return [run_model_action, edit_model_action]


class ProcessingDataItemProvider(QgsDataItemProvider):

def __init__(self):
super(ProcessingDataItemProvider, self).__init__()

def name(self):
return 'processing'

def capabilities(self):
return QgsDataProvider.File

def createDataItem(self, path, parentItem):
file_info = QFileInfo(path)

if file_info.suffix().lower() == 'model3':
alg = QgsProcessingModelAlgorithm()
if alg.fromFile(path):
return ProcessingModelItem(parentItem, alg.name(), path)
return None


class ProcessingPlugin(object):

@@ -95,6 +169,8 @@ def __init__(self, iface):
iface.registerOptionsWidgetFactory(self.options_factory)
self.drop_handler = ProcessingDropHandler()
iface.registerCustomDropHandler(self.drop_handler)
self.item_provider = ProcessingDataItemProvider()
QgsApplication.dataItemProviderRegistry().addProvider(self.item_provider)
self.locator_filter = AlgorithmLocatorFilter()
iface.registerLocatorFilter(self.locator_filter)
Processing.initialize()
@@ -182,6 +258,7 @@ def unload(self):
self.iface.unregisterOptionsWidgetFactory(self.options_factory)
self.iface.deregisterLocatorFilter(self.locator_filter)
self.iface.unregisterCustomDropHandler(self.drop_handler)
QgsApplication.dataItemProviderRegistry().removeProvider(self.item_provider)

removeMenus()
Processing.deinitialize()
@@ -503,23 +503,26 @@ def openModel(self):
ModelerUtils.modelsFolders()[0],
self.tr('Processing models (*.model3 *.MODEL3)'))
if filename:
alg = QgsProcessingModelAlgorithm()
if alg.fromFile(filename):
self.model = alg
self.model.setProvider(QgsApplication.processingRegistry().providerById('model'))
self.textGroup.setText(alg.group())
self.textName.setText(alg.name())
self.repaintModel()
self.loadModel(filename)

self.view.centerOn(0, 0)
self.hasChanged = False
else:
QgsMessageLog.logMessage(self.tr('Could not load model {0}').format(filename),
self.tr('Processing'),
QgsMessageLog.CRITICAL)
QMessageBox.critical(self, self.tr('Could not open model'),
self.tr('The selected model could not be loaded.\n'
'See the log for more information.'))
def loadModel(self, filename):
alg = QgsProcessingModelAlgorithm()
if alg.fromFile(filename):
self.model = alg
self.model.setProvider(QgsApplication.processingRegistry().providerById('model'))
self.textGroup.setText(alg.group())
self.textName.setText(alg.name())
self.repaintModel()

self.view.centerOn(0, 0)
self.hasChanged = False
else:
QgsMessageLog.logMessage(self.tr('Could not load model {0}').format(filename),
self.tr('Processing'),
QgsMessageLog.CRITICAL)
QMessageBox.critical(self, self.tr('Could not open model'),
self.tr('The selected model could not be loaded.\n'
'See the log for more information.'))

def repaintModel(self, controls=True):
self.scene = ModelerScene(self, dialog=self)
@@ -6,6 +6,7 @@ SET(QGIS_APP_SRCS
qgisappstylesheet.cpp
qgsabout.cpp
qgsalignrasterdialog.cpp
qgsappbrowserproviders.cpp
qgsapplayertreeviewmenuprovider.cpp
qgsaddattrdialog.cpp
qgsaddtaborgroup.cpp
@@ -194,6 +195,7 @@ SET (QGIS_APP_MOC_HDRS
qgsabout.h
qgsaddattrdialog.h
qgsalignrasterdialog.h
qgsappbrowserproviders.h
qgsjoindialog.h
qgsaddtaborgroup.h
qgsannotationwidget.h
@@ -124,6 +124,7 @@ Q_GUI_EXPORT extern int qt_defaultDpiX();
#include "qgisplugin.h"
#include "qgsabout.h"
#include "qgsalignrasterdialog.h"
#include "qgsappbrowserproviders.h"
#include "qgsapplayertreeviewmenuprovider.h"
#include "qgsapplication.h"
#include "qgsactionmanager.h"
@@ -153,6 +154,7 @@ Q_GUI_EXPORT extern int qt_defaultDpiX();
#include "qgscustomization.h"
#include "qgscustomlayerorderwidget.h"
#include "qgscustomprojectiondialog.h"
#include "qgsdataitemproviderregistry.h"
#include "qgsdatasourceuri.h"
#include "qgsdatumtransformdialog.h"
#include "qgsdoublespinbox.h"
@@ -975,6 +977,9 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
qApp->processEvents();
QgsApplication::initQgis();

QgsApplication::dataItemProviderRegistry()->addProvider( new QgsQlrDataItemProvider() );
registerCustomDropHandler( new QgsQlrDropHandler() );

mSplash->showMessage( tr( "Starting Python" ), Qt::AlignHCenter | Qt::AlignBottom );
qApp->processEvents();
loadPythonSupport();
@@ -0,0 +1,80 @@
/***************************************************************************
qgsappbrowserproviders.cpp
---------------------------
begin : September 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 "qgsappbrowserproviders.h"
#include "qgisapp.h"

//
// QgsQlrDataItem
//

QgsQlrDataItem::QgsQlrDataItem( QgsDataItem *parent, const QString &name, const QString &path )
: QgsLayerItem( parent, name, path, path, QgsLayerItem::NoType, QStringLiteral( "qlr" ) )
{
setState( QgsDataItem::Populated ); // no children
setIconName( QStringLiteral( ":/images/icons/qgis-icon-16x16.png" ) );
setToolTip( QDir::toNativeSeparators( path ) );
}

bool QgsQlrDataItem::hasDragEnabled() const
{
return true;
}

QgsMimeDataUtils::Uri QgsQlrDataItem::mimeUri() const
{
QgsMimeDataUtils::Uri u;
u.layerType = QStringLiteral( "custom" );
u.providerKey = QStringLiteral( "qlr" );
u.name = name();
u.uri = path();
return u;
}

//
// QgsQlrDataItemProvider
//

QString QgsQlrDataItemProvider::name()
{
return QStringLiteral( "QLR" );
}

int QgsQlrDataItemProvider::capabilities()
{
return QgsDataProvider::File;
}

QgsDataItem *QgsQlrDataItemProvider::createDataItem( const QString &path, QgsDataItem *parentItem )
{
QFileInfo fileInfo( path );

if ( fileInfo.suffix().compare( QStringLiteral( "qlr" ), Qt::CaseInsensitive ) == 0 )
{
return new QgsQlrDataItem( parentItem, fileInfo.fileName(), path );
}
return nullptr;
}

QString QgsQlrDropHandler::customUriProviderKey() const
{
return QStringLiteral( "qlr" );
}

void QgsQlrDropHandler::handleCustomUriDrop( const QgsMimeDataUtils::Uri &uri ) const
{
QString path = uri.uri;
QgisApp::instance()->openLayerDefinition( path );
}
@@ -0,0 +1,50 @@
/***************************************************************************
qgsappbrowserproviders.h
-------------------------
begin : September 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 QGSAPPBROWSERPROVIDERS_H
#define QGSAPPBROWSERPROVIDERS_H

#include "qgsdataitemprovider.h"
#include "qgsdataprovider.h"
#include "qgscustomdrophandler.h"

class QgsQlrDataItem : public QgsLayerItem
{
Q_OBJECT

public:

QgsQlrDataItem( QgsDataItem *parent, const QString &name, const QString &path );
bool hasDragEnabled() const override;
QgsMimeDataUtils::Uri mimeUri() const override;

};

class QgsQlrDataItemProvider : public QgsDataItemProvider
{
public:
QString name() override;
int capabilities() override;
QgsDataItem *createDataItem( const QString &path, QgsDataItem *parentItem ) override;
};

class QgsQlrDropHandler : public QgsCustomDropHandler
{
public:

QString customUriProviderKey() const override;
void handleCustomUriDrop( const QgsMimeDataUtils::Uri &uri ) const override;
};

#endif // QGSAPPBROWSERPROVIDERS_H
@@ -511,6 +511,11 @@ bool QgsDataItem::equal( const QgsDataItem *other )
mPath == other->path() );
}

bool QgsDataItem::handleDoubleClick()
{
return false;
}

QgsDataItem::State QgsDataItem::state() const
{
return mState;
@@ -79,7 +79,8 @@ class CORE_EXPORT QgsDataItem : public QObject
Layer,
Error,
Favorites, //!< Represents a favorite item
Project //!< Represents a QGIS project
Project, //!< Represents a QGIS project
Custom, //!< Custom item type
};

Q_ENUM( Type );
@@ -155,6 +156,14 @@ class CORE_EXPORT QgsDataItem : public QObject
*/
virtual bool handleDrop( const QMimeData * /*data*/, Qt::DropAction /*action*/ ) { return false; }

/**
* Called when a user double clicks on the item. Subclasses should return true
* if they have implemented a double-click handler and do not want the default
* double-click behavior for items.
* \since QGIS 3.0
*/
virtual bool handleDoubleClick();

/** Returns true if the item may be dragged.
* Default implementation returns false.
* A draggable item has to implement mimeUri() that will be used to pass data.

0 comments on commit 15e650d

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