Rabbit Remote Control 0.0.35
Loading...
Searching...
No Matches
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}
The Handle CConnecter class.
Definition Client.h:151
virtual int onProcess(const QString &id, CPluginClient *pPlug)=0
Process plugins.
manage plugins and connecter
Definition Client.h:49
virtual CConnecter * LoadConnecter(const QString &szFile)
New CConnecter pointer from file, the owner is caller.
Definition Client.cpp:284
virtual CConnecter * CreateConnecter(const QString &id)
New CConnecter pointer, the owner is caller.
Definition Client.cpp:223
virtual int LoadSettings(const QString szFile=QString())
Load Client parameters from file.
Definition Client.cpp:372
virtual int DeleteConnecter(CConnecter *p)
Delete CConnecter.
Definition Client.cpp:251
virtual QList< QWidget * > GetSettingsWidgets(QWidget *parent)
Get parameter settings widget.
Definition Client.cpp:400
virtual int SaveConnecter(CConnecter *pConnecter)
Accept connecter parameters to file.
Definition Client.cpp:324
virtual int SaveSettings(const QString szFile=QString())
Save Client parameters to file.
Definition Client.cpp:386
virtual int EnumPlugins(Handle *handle)
Enum plugins.
Definition Client.cpp:419
Connecter interface.
Definition Connecter.h:62
virtual const QString Id()
Identity.
Definition Connecter.cpp:39
virtual int SetParameter(CParameter *pParameter) override
Set the parameters and initialize the user interface.
The parameters of client.
The plugin interface.
virtual const QString Details() const
Display more information in About dialog or log.
virtual const QString Id() const
ID. Default: Protocol() + ":" + Name()
virtual const QString DisplayName() const
The plugin display name.
virtual const QString Description() const =0
Plugin description.
virtual const QString Version() const =0
Version.
virtual const QString Name() const =0
This name must be the same as the project name (${PROJECT_NAME}). The translation file (${PROJECT_NAM...
virtual const QString Protocol() const =0
Plugin Protocol.