玉兔远程控制 0.1.0-bate5
载入中...
搜索中...
未找到
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 "FrmMediaDevices.h"
30
31#include "Channel.h"
32#include "Manager.h"
33
34static Q_LOGGING_CATEGORY(log, "Manager")
35
36CManager::CManager(QObject *parent) : QObject(parent)
37 , m_FileVersion(1) //TODO: update version it if update data
38 , m_pHook(nullptr)
39{
40}
41
42CManager::~CManager()
43{
44 qDebug(log) << "CManager::~CManager()";
45
46 qApp->removeEventFilter(this);
47
48 if(m_pHook) {
49 m_pHook->UnRegisterKeyboard();
50 m_pHook->deleteLater();
51 m_pHook = nullptr;
52 }
53
54 if(m_pParameter) {
55 m_pParameter->deleteLater();
56 m_pParameter = nullptr;
57 }
58
59 if(m_Translator)
60 RabbitCommon::CTools::Instance()->RemoveTranslator(m_Translator);
61
63
64 //#if defined (_DEBUG) || !defined(BUILD_SHARED_LIBS)
65 // Q_CLEANUP_RESOURCE(translations_Plugin);
66 //#endif
67}
68
69int CManager::Initial(QString szFile)
70{
71 bool check = false;
72 //#if defined (_DEBUG) || !defined(BUILD_SHARED_LIBS)
73 // Q_INIT_RESOURCE(translations_Plugin);
74 //#endif
75
76 m_Translator = RabbitCommon::CTools::Instance()->InstallTranslator(
77 "Plugin", RabbitCommon::CTools::TranslationType::Library);
78
79 m_szSettingsFile = szFile;
80
82
83 m_pParameter = new CParameterPlugin();
84 if(m_pParameter) {
85 LoadSettings(m_szSettingsFile);
86
87 bool bReboot = true;
88 QString szSnap;
89 QString szFlatpak;
90#if defined(Q_OS_ANDROID)
91 bReboot = false;
92#endif
93#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0) && defined(Q_OS_WIN)
94 szSnap = qEnvironmentVariable("SNAP");
95 szFlatpak = qEnvironmentVariable("FLATPAK_ID");
96#else
97 szSnap = QString::fromLocal8Bit(qgetenv("SNAP"));
98 szFlatpak = QString::fromLocal8Bit(qgetenv("FLATPAK_ID"));
99#endif
100 if(!szSnap.isEmpty() || !szFlatpak.isEmpty())
101 bReboot = false;
102 if(bReboot && !RabbitCommon::CTools::Instance()->HasAdministratorPrivilege()
103 && m_pParameter->GetPromptAdministratorPrivilege())
104 {
105 int nRet = 0;
106 QString szMsg;
107 szMsg = tr("The programe is not administrator privilege.\n"
108 "Some features are limited.\n");
109#if defined(Q_OS_WIN)
110 szMsg += tr("Eg: Can not disable system shortcuts(eg: Ctrl+Alt+del).") + "\n";
111#else
112 szMsg += tr("Eg: Can not use the wake on LAN feature.") + "\n";
113#endif
114 szMsg += tr("Restart program by administrator?");
115 QMessageBox msg(QMessageBox::Warning, tr("Warning"), szMsg,
116 QMessageBox::Yes | QMessageBox::No);
117 msg.setCheckBox(new QCheckBox(tr("Always shown"), &msg));
118 msg.checkBox()->setCheckable(true);
119 msg.checkBox()->setChecked(
120 m_pParameter->GetPromptAdministratorPrivilege());
121 nRet = msg.exec();
122
123 m_pParameter->SetPromptAdministratorPrivilege(
124 msg.checkBox()->isChecked());
125 SaveSettings(m_szSettingsFile);
126
127 if(QMessageBox::Yes == nRet) {
128 RabbitCommon::CTools::Instance()->StartWithAdministratorPrivilege(true);
129 return 0;
130 }
131 }
132
133 check = connect(m_pParameter, SIGNAL(sigCaptureAllKeyboard()),
134 this, SLOT(slotCaptureAllKeyboard()));
135 Q_ASSERT(check);
136 if(m_pParameter->GetCaptureAllKeyboard()) {
137 m_pHook = CHook::GetHook(m_pParameter, this);
138 if(m_pHook)
139 m_pHook->RegisterKeyboard();
140 }
141 } else {
142 qCritical(log) << "new CParameterPlugin() fail";
143 Q_ASSERT(m_pParameter);
144 }
145
146 LoadPlugins();
147 return 0;
148}
149
150int CManager::LoadPlugins()
151{
152 int nRet = 0;
153 foreach (QObject *plugin, QPluginLoader::staticInstances())
154 {
155 CPlugin* p = qobject_cast<CPlugin*>(plugin);
156 if(p)
157 {
158 if(m_Plugins.find(p->Id()) == m_Plugins.end())
159 {
160 qInfo(log) << "Success: Load plugin" << p->Name();
161 AppendPlugin(p);
162 }
163 else
164 qWarning(log) << "The plugin" << p->Name() << " is exist.";
165 }
166 }
167
168 QString szPath = RabbitCommon::CDir::Instance()->GetDirPlugins();
169
170 QStringList filters;
171 if(filters.isEmpty())
172 {
173#if defined (Q_OS_WINDOWS) || defined(Q_OS_WIN)
174 filters << "*Plugin*.dll";
175#elif defined(Q_OS_MACOS) || defined(Q_OS_MAC)
176 filters << "*Plugin*.dylib";
177#else
178 filters << "*Plugin*.so";
179#endif
180 }
181 nRet = FindPlugins(szPath, filters);
182 if(!m_szDetails.isEmpty())
183 m_szDetails = "## " + tr("Plugins") + "\n" + m_szDetails;
184
185 qDebug(log) << ("Client details:\n" + Details()).toStdString().c_str();
186 return nRet;
187}
188
189int CManager::FindPlugins(QDir dir, QStringList filters)
190{
191 QString fileName;
192
193 QString szCurrentPath = QDir::currentPath();
194 QStringList files = dir.entryList(filters, QDir::Files | QDir::NoDotAndDotDot);
195 if(!files.isEmpty())
196 {
197 //This method is invalid
198 //QCoreApplication::addLibraryPath(QDir::cleanPath(dir.absolutePath()));
199
200 QDir::setCurrent(QDir::cleanPath(dir.absolutePath()));
201
202 // This method is valid
203 //#if defined(Q_OS_WINDOWS)
204 // QString szPath = QString::fromLocal8Bit(qgetenv("PATH"));
205 // szPath += ";";
206 // szPath += QDir::cleanPath(dir.absolutePath());
207 // qputenv("PATH", szPath.toLatin1());
208 //#endif
209 }
210
211 foreach (fileName, files) {
212 QString szPlugins = dir.absoluteFilePath(fileName);
213 QPluginLoader loader(szPlugins);
214 QObject *plugin = loader.instance();
215 if (plugin) {
216 CPlugin* p = qobject_cast<CPlugin*>(plugin);
217 if(p)
218 {
219 if(m_Plugins.find(p->Id()) == m_Plugins.end())
220 {
221 qInfo(log) << "Success: Load plugin"
222 << p->Name() << "from" << szPlugins;
223 AppendPlugin(p);
224 }
225 else
226 qWarning(log) << "The plugin [" << p->Name() << "] is exist.";
227 }
228 } else {
229 QString szMsg;
230 szMsg = "Error: Load plugin fail from " + szPlugins;
231 if(!loader.errorString().isEmpty())
232 szMsg += "; Error: " + loader.errorString();
233 qCritical(log) << szMsg.toStdString().c_str();
234 }
235 }
236
237 foreach (fileName, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
238 QDir pluginDir = dir;
239 if(pluginDir.cd(fileName))
240 FindPlugins(pluginDir, filters);
241 }
242
243 QDir::setCurrent(szCurrentPath);
244
245 return 0;
246}
247
248int CManager::AppendPlugin(CPlugin *p)
249{
250 if(!p) return -1;
251 m_Plugins.insert(p->Id(), p);
252 //p->InitTranslator();
253 int val = 0;
254 bool bRet = QMetaObject::invokeMethod(
255 p,
256 "InitTranslator",
257 Qt::DirectConnection,
258 Q_RETURN_ARG(int, val));
259 if(!bRet || val)
260 {
261 qCritical(log) << "The plugin" << p->Name()
262 << "initial translator fail" << bRet << val;
263 }
264
265 m_szDetails += "### " + p->DisplayName() + "\n"
266 + tr("Version:") + " " + p->Version() + " \n"
267 + p->Description() + "\n";
268 if(!p->Details().isEmpty())
269 m_szDetails += p->Details() + "\n";
270
271 return 0;
272}
273
276{
277 COperate* pOperate = nullptr;
278 auto it = m_Plugins.find(id);
279 if(m_Plugins.end() != it)
280 {
281 bool bRet = 0;
282 qDebug(log) << "CreateOperate id:" << id;
283 auto plugin = it.value();
284 if(plugin) {
285 //p = plugin->CreateOperate(id);
286 bRet = QMetaObject::invokeMethod(
287 plugin,
288 "CreateOperate",
289 Qt::DirectConnection,
290 Q_RETURN_ARG(COperate*, pOperate),
291 Q_ARG(QString, id),
292 Q_ARG(CParameterPlugin*, m_pParameter));
293 if(!bRet) {
294 qCritical(log) << "Create COperate fail.";
295 return nullptr;
296 }
297 }
298 }
299 return pOperate;
300}
302
304{
305 qDebug(log) << Q_FUNC_INFO;
306 if(!p) return 0;
307
308 CPlugin* pPlugin = nullptr;
309 //pPlugin->GetPlugin();
310 bool bRet = QMetaObject::invokeMethod(
311 p,
312 "GetPlugin",
313 Qt::DirectConnection,
314 Q_RETURN_ARG(CPlugin*, pPlugin));
315
316 if(bRet && pPlugin) {
317 int nRet = 0;
318 //pPlugin->DeleteOperate(p);
319 bRet = QMetaObject::invokeMethod(
320 pPlugin,
321 "DeleteOperate",
322 Qt::DirectConnection,
323 Q_RETURN_ARG(int, nRet),
324 Q_ARG(COperate*, p));
325 if(!bRet) {
326 nRet = -1;
327 qCritical(log) << "Call pPlugin->DeleteOperate(p) fail";
328 }
329 return nRet;
330 }
331
332 qCritical(log) << "Get CManager fail.";
333 return -1;
334}
335
336COperate* CManager::LoadOperate(const QString &szFile)
337{
338 COperate* pOperate = nullptr;
339 if(szFile.isEmpty()) return nullptr;
340 qDebug(log) << "Load operate configure file:"<< szFile;
341 QSettings set(szFile, QSettings::IniFormat);
342 m_FileVersion = set.value("Manage/FileVersion", m_FileVersion).toInt();
343 QString id = set.value("Plugin/ID").toString();
344 QString protocol = set.value("Plugin/Protocol").toString();
345 QString name = set.value("Plugin/Name").toString();
346 qDebug(log) << "LoadOperate protocol:" << protocol
347 << "name:" << name << "id:" << id;
348 pOperate = CreateOperate(id);
349 if(pOperate) {
350 int nRet = false;
351 //bRet = pOperate->Load(szFile);
352 bool bRet = QMetaObject::invokeMethod(
353 pOperate,
354 "Load",
355 Qt::DirectConnection,
356 Q_RETURN_ARG(int, nRet),
357 Q_ARG(QString, szFile));
358 if(!bRet) {
359 qCritical(log) << "Call pOperate->Load(szFile) fail.";
360 return nullptr;
361 }
362 if(nRet) {
363 qCritical(log) << "Load parameter fail" << nRet;
364 DeleteOperate(pOperate);
365 return nullptr;
366 }
367 pOperate->SetSettingsFile(szFile);
368 }
369 else
370 qCritical(log) << "Don't create Operate:" << name << protocol << id << szFile;
371
372 return pOperate;
373}
374
376{
377 if(!pOperate) return -1;
378
379 QString szFile = pOperate->GetSettingsFile();
380 if(szFile.isEmpty())
381 szFile = RabbitCommon::CDir::Instance()->GetDirUserData()
382 + QDir::separator()
383 + pOperate->Id()
384 + ".rrc";
385
386 QSettings set(szFile, QSettings::IniFormat);
387
388 CPlugin* pPlugin = nullptr; //pOperate->GetPlugin;
389 bool bRet = QMetaObject::invokeMethod(
390 pOperate,
391 "GetPlugin",
392 Qt::DirectConnection,
393 Q_RETURN_ARG(CPlugin*, pPlugin));
394 if(!bRet || !pPlugin)
395 {
396 qCritical(log) << "Get plugin client fail";
397 }
398 Q_ASSERT(pPlugin);
399
400 set.setValue("Manage/FileVersion", m_FileVersion);
401 set.setValue("Plugin/ID", pPlugin->Id());
402 set.setValue("Plugin/Protocol", pPlugin->Protocol());
403 set.setValue("Plugin/Name", pPlugin->Name());
404 int nRet = 0;
405 //nRet = pOperate->Save(szFile);
406 bRet = QMetaObject::invokeMethod(
407 pOperate,
408 "Save",
409 Qt::DirectConnection,
410 Q_RETURN_ARG(int, nRet),
411 Q_ARG(QString, szFile));
412 if(!bRet) {
413 qCritical(log) << "Call pOperate->Save(szFile) fail.";
414 return -1;
415 }
416 if(nRet) {
417 qCritical(log) << "Save parameter fail" << nRet;
418 return -2;
419 }
420 return 0;
421}
422
423int CManager::LoadSettings(const QString szFile)
424{
425 if(!m_pParameter) {
426 qCritical(log) << "The m_pParameter is nullptr";
427 Q_ASSERT_X(m_pParameter, "CManager", "The m_pParameter is nullptr");
428 return -1;
429 }
430
431 QString s = szFile;
432 if(s.isEmpty())
433 s = m_szSettingsFile;
434 return m_pParameter->Load(s);
435}
436
437int CManager::SaveSettings(const QString szFile)
438{
439 if(!m_pParameter) {
440 qCritical(log) << "The m_pParameter is nullptr";
441 Q_ASSERT_X(m_pParameter, "CManager", "The m_pParameter is nullptr");
442 return -1;
443 }
444
445 QString s = szFile;
446 if(s.isEmpty())
447 s = m_szSettingsFile;
448 return m_pParameter->Save(s);
449}
450
451QList<QWidget*> CManager::GetSettingsWidgets(QWidget* parent)
452{
453 QList<QWidget*> lstWidget;
454
455 CParameterPluginUI* pClient = new CParameterPluginUI(parent);
456 if(pClient) {
457 pClient->SetParameter(m_pParameter);
458 lstWidget.push_back(pClient);
459 }
460#if defined(HAVE_QTERMWIDGET)
461 CParameterTerminalUI* pTermina = new CParameterTerminalUI(parent);
462 if(pTermina) {
463 pTermina->SetParameter(&m_pParameter->m_Terminal);
464 pTermina->setWindowTitle(tr("Terminal"));
465 lstWidget.push_back(pTermina);
466 }
467#endif
468 CParameterRecordUI* pRecord = new CParameterRecordUI(parent);
469 if(pRecord) {
470 pRecord->SetParameter(&m_pParameter->m_Record);
471 lstWidget.push_back(pRecord);
472 }
473
474 CFrmMediaDevices* pMediaDevices = new CFrmMediaDevices(parent);
475 if(pMediaDevices) {
476 pMediaDevices->SetParameter(&m_pParameter->m_MediaDevices.m_Para);
477 lstWidget.push_back(pMediaDevices);
478 }
479 return lstWidget;
480}
481
483{
484 int nRet = 0;
485 QMap<QString, CPlugin*>::iterator it;
486 for(it = m_Plugins.begin(); it != m_Plugins.end(); it++)
487 {
488 nRet = handle->onProcess(it.key(), it.value());
489 if(nRet)
490 return nRet;
491 }
492 return nRet;
493}
494
495#if HAS_CPP_11
496int CManager::EnumPlugins(std::function<int(const QString &, CPlugin *)> cb)
497{
498 int nRet = 0;
499 QMap<QString, CPlugin*>::iterator it;
500 for(it = m_Plugins.begin(); it != m_Plugins.end(); it++)
501 {
502 nRet = cb(it.key(), it.value());
503 if(nRet)
504 return nRet;
505 }
506 return nRet;
507}
508#endif
509
510const QString CManager::Details() const
511{
512 QString szDetail;
513#if HAVE_QTERMWIDGET
514 szDetail += COperateTerminal::Details();
515#endif
516#ifdef HAVE_LIBSSH
517 CChannelSSH channel(nullptr, nullptr);
518 szDetail += channel.GetDetails();
519#endif
520#if HAVE_QTKEYCHAIN
521 szDetail += "- QtKeyChain\n" +
522 QString(" - ") + tr("Version:")
523 + " 0x" + QString::number(QTKEYCHAIN_VERSION, 16) + "\n";
524#endif
525
526 if(!szDetail.isEmpty()) {
527 szDetail = "## " + tr("Dependency libraries:") + "\n" + szDetail;
528 }
529 szDetail += m_szDetails;
530 return szDetail;
531}
532
533void CManager::slotCaptureAllKeyboard()
534{
535 Q_ASSERT(m_pParameter);
536 if(m_pParameter->GetCaptureAllKeyboard()) {
537 if(m_pHook) return;
538 m_pHook = CHook::GetHook(m_pParameter, this);
539 if(m_pHook)
540 m_pHook->RegisterKeyboard();
541 } else {
542 if(m_pHook) {
543 m_pHook->UnRegisterKeyboard();
544 m_pHook->deleteLater();
545 m_pHook = nullptr;
546 }
547 }
548}
static int RemoveTranslation()
Remove translation
Definition Channel.cpp:138
static int InitTranslation()
Initial translation
Definition Channel.cpp:130
处理连接者。用于客户端得到连接者信号
Definition Manager.h:147
virtual int onProcess(const QString &id, CPlugin *pPlugin)=0
Process plugins
管理插件
Definition Manager.h:45
virtual QList< QWidget * > GetSettingsWidgets(QWidget *parent)
得到设置参数窗口
Definition Manager.cpp:451
virtual int EnumPlugins(Handle *handle)
Enum plugins
Definition Manager.cpp:482
virtual COperate * CreateOperate(const QString &id)
新建 COperate 指针,所有者是调用者。 当不在使用时,调用者必调用 DeteleOperate() 须释放指针。 调用者必须连接信号 COperate::sigFinished 。 释放指针 (...
Definition Manager.cpp:275
virtual COperate * LoadOperate(const QString &szFile)
从文件中新建 COperate 指针,所有者是调用者。 当不再使用时,调用者必须负责调用 DeleteOperate() 删除此指针。 调用者必须连接信号 COperate::sigFinished 。...
Definition Manager.cpp:336
virtual int DeleteOperate(COperate *p)
Delete COperate
Definition Manager.cpp:303
virtual int SaveOperate(COperate *pOperate)
保存连接参数到文件
Definition Manager.cpp:375
virtual int SaveSettings(const QString szFile=QString())
保存客户端参数到文件
Definition Manager.cpp:437
virtual int LoadSettings(const QString szFile=QString())
从文件中加载客户端参数
Definition Manager.cpp:423
操作接口。
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:47
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
描述