mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
Merge pull request #5221 from nyalldawson/browser_awesome
Add QLR, processing models to browser
This commit is contained in:
commit
15e650d624
@ -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 @@ import sys
|
||||
|
||||
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 @@ class ProcessingDropHandler(QgsCustomDropHandler):
|
||||
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 @@ class ProcessingPlugin(object):
|
||||
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 @@ class ProcessingPlugin(object):
|
||||
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 @@ class ModelerDialog(BASE, WIDGET):
|
||||
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();
|
||||
|
80
src/app/qgsappbrowserproviders.cpp
Normal file
80
src/app/qgsappbrowserproviders.cpp
Normal file
@ -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 );
|
||||
}
|
50
src/app/qgsappbrowserproviders.h
Normal file
50
src/app/qgsappbrowserproviders.h
Normal file
@ -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.
|
||||
|
@ -97,7 +97,7 @@ QgsBrowserDockWidget::QgsBrowserDockWidget( const QString &name, QgsBrowserModel
|
||||
connect( mLeFilter, &QgsFilterLineEdit::textChanged, this, &QgsBrowserDockWidget::setFilter );
|
||||
connect( group, &QActionGroup::triggered, this, &QgsBrowserDockWidget::setFilterSyntax );
|
||||
connect( mBrowserView, &QgsDockBrowserTreeView::customContextMenuRequested, this, &QgsBrowserDockWidget::showContextMenu );
|
||||
connect( mBrowserView, &QgsDockBrowserTreeView::doubleClicked, this, &QgsBrowserDockWidget::addLayerAtIndex );
|
||||
connect( mBrowserView, &QgsDockBrowserTreeView::doubleClicked, this, &QgsBrowserDockWidget::itemDoubleClicked );
|
||||
connect( mSplitter, &QSplitter::splitterMoved, this, &QgsBrowserDockWidget::splitterMoved );
|
||||
}
|
||||
|
||||
@ -155,6 +155,18 @@ void QgsBrowserDockWidget::showEvent( QShowEvent *e )
|
||||
QgsDockWidget::showEvent( e );
|
||||
}
|
||||
|
||||
void QgsBrowserDockWidget::itemDoubleClicked( const QModelIndex &index )
|
||||
{
|
||||
QgsDataItem *item = mModel->dataItem( mProxyModel->mapToSource( index ) );
|
||||
if ( !item )
|
||||
return;
|
||||
|
||||
if ( item->handleDoubleClick() )
|
||||
return;
|
||||
else
|
||||
addLayerAtIndex( index ); // default double-click handler
|
||||
}
|
||||
|
||||
void QgsBrowserDockWidget::showContextMenu( QPoint pt )
|
||||
{
|
||||
QModelIndex index = mProxyModel->mapToSource( mBrowserView->indexAt( pt ) );
|
||||
|
@ -110,6 +110,9 @@ class GUI_EXPORT QgsBrowserDockWidget : public QgsDockWidget, private Ui::QgsBro
|
||||
//! Show event override
|
||||
void showEvent( QShowEvent *event ) override;
|
||||
|
||||
private slots:
|
||||
void itemDoubleClicked( const QModelIndex &index );
|
||||
|
||||
private:
|
||||
//! Refresh the model
|
||||
void refreshModel( const QModelIndex &index );
|
||||
|
Loading…
x
Reference in New Issue
Block a user