qgis 插件开发
qgis 是一个开源的地理信息系统,https://github.com/qgis/QGIS
qgis 是一个开源的地理信息系统,源代码:https://github.com/qgis/QGIS ,基于Qt进行开发,因为Qt支持Android平台,因此,qgis也可以移植到Android平台下。具体移植方法见于:https://github.com/qgis/QGIS-Android 。
qgis目前主要支持python 形式的插件,文档较为丰富,可用的插件也非常多。但是本人不太会,本人只会使用c++进行插件开发,虽然这是qgis所不太推荐的方式。
在qgis源代码目录中src/plugins/中有一个plugin_builder.py ,是一个python脚本,用来通过一个插件模板生成一个基本的插件。
生成的插件目录如下所示。
plugin.cpp 是插件的实现文件,
CMakeLists.txt是工程控制文件,
plugin.png是插件的图标文件,
plugingui.cpp是一个示例的对话框。
pluginguibase.ui是对话框的窗体。
我们先看plugin.h
插件类 Plugin继承了 QgisPlugin 和 QObject类,
mPluginType 是enum类型,一般都是一样的,都是 QgisPlugin::PLUGINTYPE sPluginType = QgisPlugin::UI;
mQGisIface 是接口类,用来与主程序进行交互。
mQActionPointer 是插件显示在主程序上的按钮相关的QAction。
#ifndef Plugin_H
#define Plugin_H
//QT4 includes
#include <QObject>
//QGIS includes
#include "../qgisplugin.h"
//forward declarations
class QAction;
class QToolBar;
class QgisInterface;
/**
* \class Plugin
* \brief [name] plugin for QGIS
* [description]
*/
class Plugin: public QObject, public QgisPlugin
{
Q_OBJECT
public:
//
//
// MANDATORY PLUGIN METHODS FOLLOW
//
//
/**
* Constructor for a plugin. The QgisInterface pointer is passed by
* QGIS when it attempts to instantiate the plugin.
* @param theInterface Pointer to the QgisInterface object.
*/
Plugin( QgisInterface * theInterface );
//! Destructor
virtual ~Plugin();
public slots:
//! init the gui
virtual void initGui();
//! Show the dialog box
void run();
//! unload the plugin
void unload();
//! show the help document
void help();
private:
//
// MANDATORY PLUGIN PROPERTY DECLARATIONS .....
//
int mPluginType;
//! Pointer to the QGIS interface object
QgisInterface *mQGisIface;
//!pointer to the qaction for this plugin
QAction * mQActionPointer;
//
// ADD YOUR OWN PROPERTY DECLARATIONS AFTER THIS POINT.....
//
};
#endif //Plugin_H
在plugin.cpp中,请注意这几个函数,这几个函数与类无关,是这个插件的导出函数,
QGISEXTERN 被定义成 __declspec(dllexport),用来导出函数。
/**
* Required extern functions needed for every plugin
* These functions can be called prior to creating an instance
* of the plugin class
*/
// Class factory to return a new instance of the plugin class
QGISEXTERN QgisPlugin * classFactory( QgisInterface * theQgisInterfacePointer )
{
return new Plugin( theQgisInterfacePointer );
}
// Return the name of the plugin - note that we do not user class members as
// the class may not yet be insantiated when this method is called.
QGISEXTERN QString name()
{
return sName;
}
// Return the description
QGISEXTERN QString description()
{
return sDescription;
}
// Return the category
QGISEXTERN QString category()
{
return sCategory;
}
// Return the type (either UI or MapLayer plugin)
QGISEXTERN int type()
{
return sPluginType;
}
// Return the version number for the plugin
QGISEXTERN QString version()
{
return sPluginVersion;
}
QGISEXTERN QString icon()
{
return sPluginIcon;
}
// Delete ourself
QGISEXTERN void unload( QgisPlugin * thePluginPointer )
{
delete thePluginPointer;
}
插件加载过程在 src/app/qgspluginregistry.cpp 中的void QgsPluginRegistry::loadCppPlugin( QString theFullPathName )实现
void QgsPluginRegistry::loadCppPlugin( QString theFullPathName )
{
QSettings settings;
QString baseName = QFileInfo( theFullPathName ).baseName();
// first check to see if its already loaded
if ( isLoaded( baseName ) )
{
// plugin is loaded
// QMessageBox::warning(this, "Already Loaded", description + " is already loaded");
return;
}
QLibrary myLib( theFullPathName );
QString myError; //we will only show detailed diagnostics if something went wrong
myError += QObject::tr( "Library name is %1\n" ).arg( myLib.fileName() );
bool loaded = myLib.load();
if ( !loaded )
{
QgsMessageLog::logMessage( QObject::tr( "Failed to load %1 (Reason: %2)" ).arg( myLib.fileName() ).arg( myLib.errorString() ), QObject::tr( "Plugins" ) );
return;
}
myError += QObject::tr( "Attempting to resolve the classFactory function\n" );
type_t *pType = ( type_t * ) cast_to_fptr( myLib.resolve( "type" ) );
name_t *pName = ( name_t * ) cast_to_fptr( myLib.resolve( "name" ) );
switch ( pType() )
{
case QgisPlugin::RENDERER:
case QgisPlugin::UI:
{
// UI only -- doesn't use mapcanvas
create_ui *cf = ( create_ui * ) cast_to_fptr( myLib.resolve( "classFactory" ) );
if ( cf )
{
QgisPlugin *pl = cf( mQgisInterface );
if ( pl )
{
pl->initGui();
// add it to the plugin registry
addPlugin( baseName, QgsPluginMetadata( myLib.fileName(), pName(), pl ) );
//add it to the qsettings file [ts]
settings.setValue( "/Plugins/" + baseName, true );
QgsMessageLog::logMessage( QObject::tr( "Loaded %1 (Path: %2)" ).arg( pName() ).arg( myLib.fileName() ), QObject::tr( "Plugins" ), QgsMessageLog::INFO );
QObject *o = dynamic_cast<QObject *>( pl );
if ( o )
{
QgsDebugMsg( QString( "plugin object name: %1" ).arg( o->objectName() ) );
if ( o->objectName().isEmpty() )
{
#ifndef WIN32
baseName = baseName.mid( 3 );
#endif
QgsDebugMsg( QString( "object name to %1" ).arg( baseName ) );
o->setObjectName( QString( "qgis_plugin_%1" ).arg( baseName ) );
QgsDebugMsg( QString( "plugin object name now: %1" ).arg( o->objectName() ) );
}
if ( !o->parent() )
{
QgsDebugMsg( QString( "setting plugin parent" ) );
o->setParent( QgisApp::instance() );
}
else
{
QgsDebugMsg( QString( "plugin parent already set" ) );
}
}
}
else
{
// something went wrong
QMessageBox::warning( mQgisInterface->mainWindow(), QObject::tr( "Error Loading Plugin" ),
QObject::tr( "There was an error loading a plugin."
"The following diagnostic information may help the QGIS developers resolve the issue:\n%1." )
.arg( myError ) );
//disable it to the qsettings file [ts]
settings.setValue( "/Plugins/" + baseName, false );
}
}
else
{
QgsMessageLog::logMessage( QObject::tr( "Unable to find the class factory for %1." ).arg( theFullPathName ), QObject::tr( "Plugins" ) );
}
}
break;
default:
// type is unknown
QgsMessageLog::logMessage( QObject::tr( "Plugin %1 did not return a valid type and cannot be loaded" ).arg( theFullPathName ), QObject::tr( "Plugins" ) );
break;
}
}
插件加载的过程可以从中看出来, 用到了Qlib类, 其实就是打开一个dll的操作。
create_ui *cf = ( create_ui * ) cast_to_fptr( myLib.resolve( "classFactory" ) );
if ( cf )
{
QgisPlugin *pl = cf( mQgisInterface );
----------------------------------------------------------------------------------------------------------
class GUI_EXPORT QgisInterface : public QObject
{
Q_OBJECT
public:
/** Constructor */
QgisInterface();
/** Virtual destructor */
virtual ~QgisInterface();
/** Get pointer to legend interface
\note added in 1.4
*/
virtual QgsLegendInterface* legendInterface() = 0;
virtual QgsPluginManagerInterface* pluginManagerInterface() = 0;
public slots: // TODO: do these functions really need to be slots?
/* Exposed functions */
//! Zoom to full extent of map layers
virtual void zoomFull() = 0;
//! Zoom to previous view extent
virtual void zoomToPrevious() = 0;
//! Zoom to next view extent
virtual void zoomToNext() = 0;
//! Zoom to extent of the active layer
virtual void zoomToActiveLayer() = 0;
}
OK,基本上就是这样了,其他更多的内容,请与作者进行深入交流。
更多推荐
所有评论(0)