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