玉兔远程控制 0.1.0-bate4
载入中...
搜索中...
未找到
Manager.cpp
1// Author: Kang Lin <kl222@126.com>
2
3#include <QPluginLoader>
4#include <QKeyEvent>
5#include <QtPlugin>
6#include <QFile>
7#include <QApplication>
8#include <QSettings>
9#include <QLoggingCategory>
10#include <QMessageBox>
11#include <QCheckBox>
12
13#include "RabbitCommonDir.h"
14#include "RabbitCommonTools.h"
15#include "ParameterPluginUI.h"
16#include "ParameterRecordUI.h"
17#if defined(HAVE_QTERMWIDGET)
18 #include "ParameterTerminalUI.h"
19 #include "OperateTerminal.h"
20#endif
21#ifdef HAVE_LIBSSH
22 #include "ChannelSSH.h"
23#endif
24
25#if HAVE_QTKEYCHAIN
26 #include "keychain.h"
27#endif
28
29#include "Channel.h"
30#include "Manager.h"
31
32static Q_LOGGING_CATEGORY(log, "Manager")
33
34CManager::CManager(QObject *parent, QString szFile) : QObject(parent)
35 , m_FileVersion(1) //TODO: update version it if update data
36 , m_pHook(nullptr)
37{
38 bool check = false;
39 //#if defined (_DEBUG) || !defined(BUILD_SHARED_LIBS)
40 // Q_INIT_RESOURCE(translations_Plugin);
41 //#endif
42
43 m_Translator = RabbitCommon::CTools::Instance()->InstallTranslator(
44 "Plugin", RabbitCommon::CTools::TranslationType::Library);
45
47 m_szSettingsFile = szFile;
48 m_pParameter = new CParameterPlugin();
49 if(m_pParameter) {
50 LoadSettings(m_szSettingsFile);
51 check = connect(m_pParameter, SIGNAL(sigNativeWindowRecieveKeyboard()),
52 this, SLOT(slotNativeWindowRecieveKeyboard()));
53 m_pHook = CHook::GetHook(m_pParameter, this);
54 if(m_pHook)
55 m_pHook->RegisterKeyboard();
56 } else {
57 qCritical(log) << "new CParameterPlugin() fail";
58 Q_ASSERT(m_pParameter);
59 }
60
61 LoadPlugins();
62}
63
64CManager::~CManager()
65{
66 qDebug(log) << "CManager::~CManager()";
67
68 qApp->removeEventFilter(this);
69
70 if(m_pHook) {
71 m_pHook->UnRegisterKeyboard();
72 m_pHook->deleteLater();
73 m_pHook = nullptr;
74 }
75
76 if(m_pParameter) {
77 m_pParameter->deleteLater();
78 m_pParameter = nullptr;
79 }
80
81 if(m_Translator)
82 RabbitCommon::CTools::Instance()->RemoveTranslator(m_Translator);
83
85
86 //#if defined (_DEBUG) || !defined(BUILD_SHARED_LIBS)
87 // Q_CLEANUP_RESOURCE(translations_Plugin);
88 //#endif
89}
90
91int CManager::LoadPlugins()
92{
93 int nRet = 0;
94 foreach (QObject *plugin, QPluginLoader::staticInstances())
95 {
96 CPlugin* p = qobject_cast<CPlugin*>(plugin);
97 if(p)
98 {
99 if(m_Plugins.find(p->Id()) == m_Plugins.end())
100 {
101 qInfo(log) << "Success: Load plugin" << p->Name();
102 AppendPlugin(p);
103 }
104 else
105 qWarning(log) << "The plugin" << p->Name() << " is exist.";
106 }
107 }
108
109 QString szPath = RabbitCommon::CDir::Instance()->GetDirPlugins();
110
111 QStringList filters;
112 if(filters.isEmpty())
113 {
114#if defined (Q_OS_WINDOWS) || defined(Q_OS_WIN)
115 filters << "*Plugin*.dll";
116#elif defined(Q_OS_MACOS) || defined(Q_OS_MAC)
117 filters << "*Plugin*.dylib";
118#else
119 filters << "*Plugin*.so";
120#endif
121 }
122 nRet = FindPlugins(szPath, filters);
123 if(!m_szDetails.isEmpty())
124 m_szDetails = "#### " + tr("Plugins") + "\n" + m_szDetails;
125
126 qDebug(log) << ("Client details:\n" + Details()).toStdString().c_str();
127 return nRet;
128}
129
130int CManager::FindPlugins(QDir dir, QStringList filters)
131{
132 QString fileName;
133
134 QString szCurrentPath = QDir::currentPath();
135 QStringList files = dir.entryList(filters, QDir::Files | QDir::NoDotAndDotDot);
136 if(!files.isEmpty())
137 {
138 //This method is invalid
139 //QCoreApplication::addLibraryPath(QDir::cleanPath(dir.absolutePath()));
140
141 QDir::setCurrent(QDir::cleanPath(dir.absolutePath()));
142
143 // This method is valid
144 //#if defined(Q_OS_WINDOWS)
145 // QString szPath = QString::fromLocal8Bit(qgetenv("PATH"));
146 // szPath += ";";
147 // szPath += QDir::cleanPath(dir.absolutePath());
148 // qputenv("PATH", szPath.toLatin1());
149 //#endif
150 }
151
152 foreach (fileName, files) {
153 QString szPlugins = dir.absoluteFilePath(fileName);
154 QPluginLoader loader(szPlugins);
155 QObject *plugin = loader.instance();
156 if (plugin) {
157 CPlugin* p = qobject_cast<CPlugin*>(plugin);
158 if(p)
159 {
160 if(m_Plugins.find(p->Id()) == m_Plugins.end())
161 {
162 qInfo(log) << "Success: Load plugin"
163 << p->Name() << "from" << szPlugins;
164 AppendPlugin(p);
165 }
166 else
167 qWarning(log) << "The plugin [" << p->Name() << "] is exist.";
168 }
169 } else {
170 QString szMsg;
171 szMsg = "Error: Load plugin fail from " + szPlugins;
172 if(!loader.errorString().isEmpty())
173 szMsg += "; Error: " + loader.errorString();
174 qCritical(log) << szMsg.toStdString().c_str();
175 }
176 }
177
178 foreach (fileName, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
179 QDir pluginDir = dir;
180 if(pluginDir.cd(fileName))
181 FindPlugins(pluginDir, filters);
182 }
183
184 QDir::setCurrent(szCurrentPath);
185
186 return 0;
187}
188
189int CManager::AppendPlugin(CPlugin *p)
190{
191 if(!p) return -1;
192 m_Plugins.insert(p->Id(), p);
193 //p->InitTranslator();
194 int val = 0;
195 bool bRet = QMetaObject::invokeMethod(
196 p,
197 "InitTranslator",
198 Qt::DirectConnection,
199 Q_RETURN_ARG(int, val));
200 if(!bRet || val)
201 {
202 qCritical(log) << "The plugin" << p->Name()
203 << "initial translator fail" << bRet << val;
204 }
205
206 m_szDetails += "##### " + p->DisplayName() + "\n"
207 + tr("Version:") + " " + p->Version() + " \n"
208 + p->Description() + "\n";
209 if(!p->Details().isEmpty())
210 m_szDetails += p->Details() + "\n";
211
212 return 0;
213}
214
217{
218 COperate* pOperate = nullptr;
219 auto it = m_Plugins.find(id);
220 if(m_Plugins.end() != it)
221 {
222 bool bRet = 0;
223 qDebug(log) << "CreateOperate id:" << id;
224 auto plugin = it.value();
225 if(plugin) {
226 //p = plugin->CreateOperate(id);
227 bRet = QMetaObject::invokeMethod(
228 plugin,
229 "CreateOperate",
230 Qt::DirectConnection,
231 Q_RETURN_ARG(COperate*, pOperate),
232 Q_ARG(QString, id),
233 Q_ARG(CParameterPlugin*, m_pParameter));
234 if(!bRet) {
235 qCritical(log) << "Create COperate fail.";
236 return nullptr;
237 }
238 }
239 }
240 return pOperate;
241}
243
245{
246 qDebug(log) << Q_FUNC_INFO;
247 if(!p) return 0;
248
249 CPlugin* pPlugin = nullptr;
250 //pPlugin->GetPlugin();
251 bool bRet = QMetaObject::invokeMethod(
252 p,
253 "GetPlugin",
254 Qt::DirectConnection,
255 Q_RETURN_ARG(CPlugin*, pPlugin));
256
257 if(bRet && pPlugin) {
258 int nRet = 0;
259 //pPlugin->DeleteOperate(p);
260 bRet = QMetaObject::invokeMethod(
261 pPlugin,
262 "DeleteOperate",
263 Qt::DirectConnection,
264 Q_RETURN_ARG(int, nRet),
265 Q_ARG(COperate*, p));
266 if(!bRet) {
267 nRet = -1;
268 qCritical(log) << "Call pPlugin->DeleteOperate(p) fail";
269 }
270 return nRet;
271 }
272
273 qCritical(log) << "Get CManager fail.";
274 return -1;
275}
276
277COperate* CManager::LoadOperate(const QString &szFile)
278{
279 COperate* pOperate = nullptr;
280 if(szFile.isEmpty()) return nullptr;
281 qDebug(log) << "LoadOperate:"<< szFile;
282 QSettings set(szFile, QSettings::IniFormat);
283 m_FileVersion = set.value("Manage/FileVersion", m_FileVersion).toInt();
284 QString id = set.value("Plugin/ID").toString();
285 QString protocol = set.value("Plugin/Protocol").toString();
286 QString name = set.value("Plugin/Name").toString();
287 qDebug(log) << "LoadOperate protocol:" << protocol
288 << "name:" << name << "id:" << id;
289 pOperate = CreateOperate(id);
290 if(pOperate) {
291 int nRet = false;
292 //bRet = pOperate->Load(szFile);
293 bool bRet = QMetaObject::invokeMethod(
294 pOperate,
295 "Load",
296 Qt::DirectConnection,
297 Q_RETURN_ARG(int, nRet),
298 Q_ARG(QString, szFile));
299 if(!bRet) {
300 qCritical(log) << "Call pOperate->Load(szFile) fail.";
301 return nullptr;
302 }
303 if(nRet) {
304 qCritical(log) << "Load parameter fail" << nRet;
305 DeleteOperate(pOperate);
306 return nullptr;
307 }
308 pOperate->SetSettingsFile(szFile);
309 }
310 else
311 qCritical(log) << "Don't create Operate:" << name << protocol << id << szFile;
312
313 return pOperate;
314}
315
317{
318 if(!pOperate) return -1;
319
320 QString szFile = pOperate->GetSettingsFile();
321 if(szFile.isEmpty())
322 szFile = RabbitCommon::CDir::Instance()->GetDirUserData()
323 + QDir::separator()
324 + pOperate->Id()
325 + ".rrc";
326
327 QSettings set(szFile, QSettings::IniFormat);
328
329 CPlugin* pPlugin = nullptr; //pOperate->GetPlugin;
330 bool bRet = QMetaObject::invokeMethod(
331 pOperate,
332 "GetPlugin",
333 Qt::DirectConnection,
334 Q_RETURN_ARG(CPlugin*, pPlugin));
335 if(!bRet || !pPlugin)
336 {
337 qCritical(log) << "Get plugin client fail";
338 }
339 Q_ASSERT(pPlugin);
340
341 set.setValue("Manage/FileVersion", m_FileVersion);
342 set.setValue("Plugin/ID", pPlugin->Id());
343 set.setValue("Plugin/Protocol", pPlugin->Protocol());
344 set.setValue("Plugin/Name", pPlugin->Name());
345 int nRet = 0;
346 //nRet = pOperate->Save(szFile);
347 bRet = QMetaObject::invokeMethod(
348 pOperate,
349 "Save",
350 Qt::DirectConnection,
351 Q_RETURN_ARG(int, nRet),
352 Q_ARG(QString, szFile));
353 if(!bRet) {
354 qCritical(log) << "Call pOperate->Save(szFile) fail.";
355 return -1;
356 }
357 if(nRet) {
358 qCritical(log) << "Save parameter fail" << nRet;
359 return -2;
360 }
361 return 0;
362}
363
364int CManager::LoadSettings(const QString szFile)
365{
366 if(!m_pParameter) {
367 qCritical(log) << "The m_pParameter is nullptr";
368 Q_ASSERT_X(m_pParameter, "CManager", "The m_pParameter is nullptr");
369 return -1;
370 }
371
372 QString s = szFile;
373 if(s.isEmpty())
374 s = m_szSettingsFile;
375 return m_pParameter->Load(s);
376}
377
378int CManager::SaveSettings(const QString szFile)
379{
380 if(!m_pParameter) {
381 qCritical(log) << "The m_pParameter is nullptr";
382 Q_ASSERT_X(m_pParameter, "CManager", "The m_pParameter is nullptr");
383 return -1;
384 }
385
386 QString s = szFile;
387 if(s.isEmpty())
388 s = m_szSettingsFile;
389 return m_pParameter->Save(s);
390}
391
392QList<QWidget*> CManager::GetSettingsWidgets(QWidget* parent)
393{
394 QList<QWidget*> lstWidget;
395
396 CParameterPluginUI* pClient = new CParameterPluginUI(parent);
397 if(pClient) {
398 pClient->SetParameter(m_pParameter);
399 lstWidget.push_back(pClient);
400 }
401#if defined(HAVE_QTERMWIDGET)
402 CParameterTerminalUI* pTermina = new CParameterTerminalUI(parent);
403 if(pTermina) {
404 pTermina->SetParameter(&m_pParameter->m_Terminal);
405 pTermina->setWindowTitle(tr("Terminal"));
406 lstWidget.push_back(pTermina);
407 }
408#endif
409 CParameterRecordUI* pRecord = new CParameterRecordUI(parent);
410 if(pRecord) {
411 pRecord->SetParameter(&m_pParameter->m_Record);
412 lstWidget.push_back(pRecord);
413 }
414
415 return lstWidget;
416}
417
419{
420 int nRet = 0;
421 QMap<QString, CPlugin*>::iterator it;
422 for(it = m_Plugins.begin(); it != m_Plugins.end(); it++)
423 {
424 nRet = handle->onProcess(it.key(), it.value());
425 if(nRet)
426 return nRet;
427 }
428 return nRet;
429}
430
431#if HAS_CPP_11
432int CManager::EnumPlugins(std::function<int(const QString &, CPlugin *)> cb)
433{
434 int nRet = 0;
435 QMap<QString, CPlugin*>::iterator it;
436 for(it = m_Plugins.begin(); it != m_Plugins.end(); it++)
437 {
438 nRet = cb(it.key(), it.value());
439 if(nRet)
440 return nRet;
441 }
442 return nRet;
443}
444#endif
445
446const QString CManager::Details() const
447{
448 QString szDetail;
449#if HAVE_QTERMWIDGET
450 szDetail += COperateTerminal::Details();
451#endif
452#ifdef HAVE_LIBSSH
453 CChannelSSH channel(nullptr, nullptr);
454 szDetail += channel.GetDetails();
455#endif
456#if HAVE_QTKEYCHAIN
457 szDetail += "- QtKeyChain\n" +
458 QString(" - ") + tr("Version:")
459 + " 0x" + QString::number(QTKEYCHAIN_VERSION, 16) + "\n";
460#endif
461
462 if(!szDetail.isEmpty()) {
463 szDetail = "#### " + tr("Dependency libraries:") + "\n" + szDetail;
464 }
465 szDetail += m_szDetails;
466 return szDetail;
467}
468
469void CManager::slotNativeWindowRecieveKeyboard()
470{
471 Q_ASSERT(m_pParameter);
472 if(m_pParameter->GetNativeWindowReceiveKeyboard()) {
473 if(m_pHook) {
474 m_pHook->UnRegisterKeyboard();
475 m_pHook->deleteLater();
476 m_pHook = nullptr;
477 }
478 } else {
479 if(m_pHook) return;
480 m_pHook = CHook::GetHook(m_pParameter, this);
481 if(m_pHook)
482 m_pHook->RegisterKeyboard();
483 }
484}
static int RemoveTranslation()
Remove translation
Definition Channel.cpp:138
static int InitTranslation()
Initial translation
Definition Channel.cpp:130
处理连接者。用于客户端得到连接者信号
Definition Manager.h:145
virtual int onProcess(const QString &id, CPlugin *pPlugin)=0
Process plugins
管理插件
Definition Manager.h:45
virtual QList< QWidget * > GetSettingsWidgets(QWidget *parent)
得到设置参数窗口
Definition Manager.cpp:392
virtual int EnumPlugins(Handle *handle)
Enum plugins
Definition Manager.cpp:418
virtual COperate * CreateOperate(const QString &id)
新建 COperate 指针,所有者是调用者。 当不在使用时,调用者必调用 DeteleOperate() 须释放指针。 调用者必须连接信号 COperate::sigFinished 。 释放指针 (...
Definition Manager.cpp:216
virtual COperate * LoadOperate(const QString &szFile)
从文件中新建 COperate 指针,所有者是调用者。 当不再使用时,调用者必须负责调用 DeleteOperate() 删除此指针。 调用者必须连接信号 COperate::sigFinished 。...
Definition Manager.cpp:277
virtual int DeleteOperate(COperate *p)
Delete COperate
Definition Manager.cpp:244
virtual int SaveOperate(COperate *pOperate)
保存连接参数到文件
Definition Manager.cpp:316
virtual int SaveSettings(const QString szFile=QString())
保存客户端参数到文件
Definition Manager.cpp:378
virtual int LoadSettings(const QString szFile=QString())
从文件中加载客户端参数
Definition Manager.cpp:364
操作接口。
Definition Operate.h:51
virtual const QString Id()
Identity
Definition Operate.cpp:33
virtual int SetParameter(CParameter *pParameter) override
[override functions]
插件的全局参数。
virtual int SetParameter(CParameter *pParameter) override
[override functions]
virtual int Save(QString szFile=QString(), bool bForce=true)
Save to file
Definition Parameter.cpp:46
virtual int Load(QString szFile=QString())
Load from file
Definition Parameter.cpp:35
插件接口
Definition Plugin.h:15
virtual const QString Version() const =0
Version
virtual const QString Details() const
显示更多细节。 例如: 在关于对话框或日志中显示。 包括插件的依赖库的版本信息和描述
Definition Plugin.cpp:78
virtual const QString Id()
标识。默认: Type() + ":" + Protocol() + ":" + Name()
Definition Plugin.cpp:68
virtual const QString Name() const =0
插件名,这个名一定要与工程名(${PROJECT_NAME})相同。 翻译文件(${PROJECT_NAME}_*.ts))名与其相关。
virtual const QString DisplayName() const
在界面上显示的名称
Definition Plugin.cpp:73
virtual const QString Protocol() const =0
协议
virtual const QString Description() const =0
描述