1、實作一個應用程式插架架構關鍵點有:
一個插件的标準接口,在主程式中存在一個插件的集合。主程式通過循環讀取每個插件,将插件對象通過多态的機制轉換為插件接口,實作插件的裝載。
主程式對象或者主程式接口需要作為參數傳遞到插件對象中,以友善插件對象調用主程式的内容,如主視圖、工具欄、樹視圖、狀态欄等。
2、開源點雲處理軟體CloudCompare也是一個插件架構,是以也必然包括這些内容。
插件接口:ccPluginInterface,每個插件對象有在ccPluginInterface基礎上定義了一個新的接口類class ccStdPluginInterface : public ccPluginInterface
具體的插件則繼承自ccStdPluginInterface 累,比如這樣,class qMyPlugin : public QObject, public ccStdPluginInterface
主程式對象:class ccMainAppInterface,MainWindow主窗體類實作了ccMainAppInterface接口。
MainWindow::loadPlugins()方法負責插件的調用。(mainwindow.cpp檔案中)
複制代碼
1 void MainWindow::loadPlugins()
2 {
3 menuPlugins->setEnabled(false);
4 menuShadersAndFilters->setEnabled(false);
5 toolBarPluginTools->setVisible(false);
6 toolBarGLFilters->setVisible(false);
7
8 //“static” plugins
9 foreach (QObject plugin, QPluginLoader::staticInstances())
10 dispatchPlugin(plugin);
11
12 ccConsole::Print(QString(“Application path: “)+QCoreApplication::applicationDirPath());
13
14 #if defined(Q_OS_MAC)
15 // plugins are in the bundle
16 QString path = QCoreApplication::applicationDirPath();
17 path.remove( “MacOS” );
18 m_pluginsPath = path + “Plugins/ccPlugins”;
19 #else
20 //plugins are in bin/plugins
21 m_pluginsPath = QCoreApplication::applicationDirPath()+QString(”/plugins”);
22 #endif
23
24 ccConsole::Print(QString(“Plugins lookup dir.: %1”).arg(m_pluginsPath));
25
26 QStringList filters;
27 #if defined(Q_OS_WIN)
28 filters << ".dll";
29 #elif defined(Q_OS_LINUX)
30 filters << “.so";
31 #elif defined(Q_OS_MAC)
32 filters << ".dylib”;
33 #endif
34 QDir pluginsDir(m_pluginsPath);
35 pluginsDir.setNameFilters(filters);
36 foreach (QString filename, pluginsDir.entryList(filters))
37 {
38 QPluginLoader loader(pluginsDir.absoluteFilePath(filename));
39 QObject* plugin = loader.instance();
40 if (plugin)
41 {
42 ccConsole::Print(QString(“Found new plugin: ‘%1’”).arg(filename));
43 if (dispatchPlugin(plugin))
44 {
45 m_pluginFileNames += filename;
46 }
47 else
48 {
49 delete plugin;
50 plugin = 0;
51 ccConsole::Warning("\tUnsupported or invalid plugin type");
52 }
53 }
54 else
55 {
56 delete plugin;
57 plugin = 0;
58 ccConsole::Warning(QString("[Plugin] %1")/.arg(pluginsDir.absoluteFilePath(filename))/.arg(loader.errorString()));
59 }
60 }
61
62 if (menuPlugins)
63 {
64 menuPlugins->setEnabled(!m_stdPlugins.empty());
65 }
66
67 if (toolBarPluginTools->isEnabled())
68 {
69 actionDisplayPluginTools->setEnabled(true);
70 actionDisplayPluginTools->setChecked(true);
71 }
72 else
73 {
74 //DGM: doesn’t work ?
75 //actionDisplayPluginTools->setChecked(false);
76 }
77
78 if (toolBarGLFilters->isEnabled())
79 {
80 actionDisplayGLFiltersTools->setEnabled(true);
81 actionDisplayGLFiltersTools->setChecked(true);
82 }
83 else
84 {
85 //DGM: doesn’t work ?
86 //actionDisplayGLFiltersTools->setChecked(false);
87 }
88 }
複制代碼
主程式在加載插件時會調用插件的setMainAppInterface方法,将主程式參數傳入,這樣插件就可以擷取主程式的内容了。
1 //! Sets application entry point
2 /** Called just after plugin creation by qCC
3 */
4 virtual void setMainAppInterface(ccMainAppInterface app);
3、擷取主窗體中的點雲圖層
在doAction中的代碼:
複制代碼
1 const ccHObject::Container& selectedEntities = m_app->getSelectedEntities();
2 size_t selNum = selectedEntities.size();
3 if (selNum!=1)
4 {
5 m_app->dispToConsole(“Select only one cloud!”,ccMainAppInterface::ERR_CONSOLE_MESSAGE);
6 return;
7 }
8
9 ccHObject* ent = selectedEntities[0];
10 assert(ent);
11 if (!ent || !ent->isA(CC_TYPES::POINT_CLOUD))
12 {
13 m_app->dispToConsole(“Select a real point cloud!”,ccMainAppInterface::ERR_CONSOLE_MESSAGE);
14 return;
15 }
16
17 ccPointCloud* pc = static_cast<ccPointCloud*>(ent);
18
19 //input cloud
20 unsigned count = pc->size();
21 bool hasNorms = pc->hasNormals();
22 CCVector3 bbMin, bbMax;
23 pc->getBoundingBox(bbMin,bbMax);
24 const CCVector3d& globalShift = pc->getGlobalShift();
25 double globalScale = pc->getGlobalScale();
複制代碼