Rabbit Remote Control 0.0.37
Loading...
Searching...
No Matches
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#endif
20#include "Channel.h"
21#include "Manager.h"
22
23static Q_LOGGING_CATEGORY(log, "Manager")
24
25CManager::CManager(QObject *parent, QString szFile) : QObject(parent)
26 , m_FileVersion(1) //TODO: update version it if update data
27 , m_pHook(nullptr)
28{
29 bool check = false;
30 //#if defined (_DEBUG) || !defined(BUILD_SHARED_LIBS)
31 // Q_INIT_RESOURCE(translations_Plugin);
32 //#endif
33
34 m_Translator = RabbitCommon::CTools::Instance()->InstallTranslator(
35 "Plugin", RabbitCommon::CTools::TranslationType::Library);
36
38 m_szSettingsFile = szFile;
39 m_pParameter = new CParameterPlugin();
40 if(m_pParameter) {
41 LoadSettings(m_szSettingsFile);
42 check = connect(m_pParameter, SIGNAL(sigNativeWindowRecieveKeyboard()),
43 this, SLOT(slotNativeWindowRecieveKeyboard()));
44 m_pHook = CHook::GetHook(m_pParameter, this);
45 if(m_pHook)
46 m_pHook->RegisterKeyboard();
47 } else {
48 qCritical(log) << "new CParameterPlugin() fail";
49 Q_ASSERT(m_pParameter);
50 }
51
52 LoadPlugins();
53}
54
55CManager::~CManager()
56{
57 qDebug(log) << "CManager::~CManager()";
58
59 qApp->removeEventFilter(this);
60
61 if(m_pHook) {
62 m_pHook->UnRegisterKeyboard();
63 m_pHook->deleteLater();
64 m_pHook = nullptr;
65 }
66
67 if(m_pParameter) {
68 m_pParameter->deleteLater();
69 m_pParameter = nullptr;
70 }
71
72 if(m_Translator)
73 RabbitCommon::CTools::Instance()->RemoveTranslator(m_Translator);
74
76
77 //#if defined (_DEBUG) || !defined(BUILD_SHARED_LIBS)
78 // Q_CLEANUP_RESOURCE(translations_Plugin);
79 //#endif
80}
81
82int CManager::LoadPlugins()
83{
84 int nRet = 0;
85 foreach (QObject *plugin, QPluginLoader::staticInstances())
86 {
87 CPlugin* p = qobject_cast<CPlugin*>(plugin);
88 if(p)
89 {
90 if(m_Plugins.find(p->Id()) == m_Plugins.end())
91 {
92 qInfo(log) << "Success: Load plugin" << p->Name();
93 AppendPlugin(p);
94 }
95 else
96 qWarning(log) << "The plugin" << p->Name() << " is exist.";
97 }
98 }
99
100 QString szPath = RabbitCommon::CDir::Instance()->GetDirPlugins();
101
102 QStringList filters;
103 if(filters.isEmpty())
104 {
105#if defined (Q_OS_WINDOWS) || defined(Q_OS_WIN)
106 filters << "*Plugin*.dll";
107#elif defined(Q_OS_MACOS) || defined(Q_OS_MAC)
108 filters << "*Plugin*.dylib";
109#else
110 filters << "*Plugin*.so";
111#endif
112 }
113 nRet = FindPlugins(szPath, filters);
114 if(!m_szDetails.isEmpty())
115 m_szDetails = tr("### Plugins") + "\n" + m_szDetails;
116
117 qDebug(log) << ("Client details:\n" + Details()).toStdString().c_str();
118 return nRet;
119}
120
121int CManager::FindPlugins(QDir dir, QStringList filters)
122{
123 QString fileName;
124
125 QString szCurrentPath = QDir::currentPath();
126 QStringList files = dir.entryList(filters, QDir::Files | QDir::NoDotAndDotDot);
127 if(!files.isEmpty())
128 {
129 //This method is invalid
130 //QCoreApplication::addLibraryPath(QDir::cleanPath(dir.absolutePath()));
131
132 QDir::setCurrent(QDir::cleanPath(dir.absolutePath()));
133
134 // This method is valid
135 //#if defined(Q_OS_WINDOWS)
136 // QString szPath = QString::fromLocal8Bit(qgetenv("PATH"));
137 // szPath += ";";
138 // szPath += QDir::cleanPath(dir.absolutePath());
139 // qputenv("PATH", szPath.toLatin1());
140 //#endif
141 }
142
143 foreach (fileName, files) {
144 QString szPlugins = dir.absoluteFilePath(fileName);
145 QPluginLoader loader(szPlugins);
146 QObject *plugin = loader.instance();
147 if (plugin) {
148 CPlugin* p = qobject_cast<CPlugin*>(plugin);
149 if(p)
150 {
151 if(m_Plugins.find(p->Id()) == m_Plugins.end())
152 {
153 qInfo(log) << "Success: Load plugin"
154 << p->Name() << "from" << szPlugins;
155 AppendPlugin(p);
156 }
157 else
158 qWarning(log) << "The plugin [" << p->Name() << "] is exist.";
159 }
160 }else{
161 QString szMsg;
162 szMsg = "Error: Load plugin fail from " + szPlugins;
163 if(!loader.errorString().isEmpty())
164 szMsg += "; Error: " + loader.errorString();
165 qCritical(log) << szMsg.toStdString().c_str();
166 }
167 }
168
169 foreach (fileName, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
170 QDir pluginDir = dir;
171 if(pluginDir.cd(fileName))
172 FindPlugins(pluginDir, filters);
173 }
174
175 QDir::setCurrent(szCurrentPath);
176
177 return 0;
178}
179
180int CManager::AppendPlugin(CPlugin *p)
181{
182 if(!p) return -1;
183 m_Plugins.insert(p->Id(), p);
184 //p->InitTranslator();
185 int val = 0;
186 bool bRet = QMetaObject::invokeMethod(
187 p,
188 "InitTranslator",
189 Qt::DirectConnection,
190 Q_RETURN_ARG(int, val));
191 if(!bRet || val)
192 {
193 qCritical(log) << "The plugin" << p->Name()
194 << "initial translator fail" << bRet << val;
195 }
196
197 m_szDetails += "#### " + p->DisplayName() + "\n"
198 + tr("Version:") + " " + p->Version() + " \n"
199 + p->Description() + "\n";
200 if(!p->Details().isEmpty())
201 m_szDetails += p->Details() + "\n";
202
203 return 0;
204}
205
208{
209 COperate* pOperate = nullptr;
210 auto it = m_Plugins.find(id);
211 if(m_Plugins.end() != it)
212 {
213 bool bRet = 0;
214 qDebug(log) << "CreateOperate id:" << id;
215 auto plugin = it.value();
216 if(plugin) {
217 //p = plugin->CreateOperate(id);
218 bRet = QMetaObject::invokeMethod(
219 plugin,
220 "CreateOperate",
221 Qt::DirectConnection,
222 Q_RETURN_ARG(COperate*, pOperate),
223 Q_ARG(QString, id),
224 Q_ARG(CParameterPlugin*, m_pParameter));
225 if(!bRet) {
226 qCritical(log) << "Create COperate fail.";
227 return nullptr;
228 }
229 }
230 }
231 return pOperate;
232}
234
236{
237 qDebug(log) << Q_FUNC_INFO;
238 if(!p) return 0;
239
240 CPlugin* pPlugin = nullptr;
241 //pPlugin->GetPlugin();
242 bool bRet = QMetaObject::invokeMethod(
243 p,
244 "GetPlugin",
245 Qt::DirectConnection,
246 Q_RETURN_ARG(CPlugin*, pPlugin));
247
248 if(bRet && pPlugin) {
249 int nRet = 0;
250 //pPlugin->DeleteOperate(p);
251 bRet = QMetaObject::invokeMethod(
252 pPlugin,
253 "DeleteOperate",
254 Qt::DirectConnection,
255 Q_RETURN_ARG(int, nRet),
256 Q_ARG(COperate*, p));
257 if(!bRet) {
258 nRet = -1;
259 qCritical(log) << "Call pPlugin->DeleteOperate(p) fail";
260 }
261 return nRet;
262 }
263
264 qCritical(log) << "Get CManager fail.";
265 return -1;
266}
267
268COperate* CManager::LoadOperate(const QString &szFile)
269{
270 COperate* pOperate = nullptr;
271 if(szFile.isEmpty()) return nullptr;
272
273 QSettings set(szFile, QSettings::IniFormat);
274 m_FileVersion = set.value("Manage/FileVersion", m_FileVersion).toInt();
275 QString id = set.value("Plugin/ID").toString();
276 QString protocol = set.value("Plugin/Protocol").toString();
277 QString name = set.value("Plugin/Name").toString();
278 qDebug(log) << "LoadOperate protocol:" << protocol
279 << "name:" << name << "id:" << id;
280 pOperate = CreateOperate(id);
281 if(pOperate) {
282 int nRet = false;
283 //bRet = pOperate->Load(szFile);
284 bool bRet = QMetaObject::invokeMethod(
285 pOperate,
286 "Load",
287 Qt::DirectConnection,
288 Q_RETURN_ARG(int, nRet),
289 Q_ARG(QString, szFile));
290 if(!bRet) {
291 qCritical(log) << "Call pOperate->Load(szFile) fail.";
292 return nullptr;
293 }
294 if(nRet) {
295 qCritical(log) << "Load parameter fail" << nRet;
296 DeleteOperate(pOperate);
297 return nullptr;
298 }
299 pOperate->SetSettingsFile(szFile);
300 }
301 else
302 qCritical(log) << "Don't create Operate:" << protocol;
303
304 return pOperate;
305}
306
308{
309 if(!pOperate) return -1;
310
311 QString szFile = pOperate->GetSettingsFile();
312 if(szFile.isEmpty())
313 szFile = RabbitCommon::CDir::Instance()->GetDirUserData()
314 + QDir::separator()
315 + pOperate->Id()
316 + ".rrc";
317
318 QSettings set(szFile, QSettings::IniFormat);
319
320 CPlugin* pPlugin = nullptr; //pOperate->GetPlugin;
321 bool bRet = QMetaObject::invokeMethod(
322 pOperate,
323 "GetPlugin",
324 Qt::DirectConnection,
325 Q_RETURN_ARG(CPlugin*, pPlugin));
326 if(!bRet || !pPlugin)
327 {
328 qCritical(log) << "Get plugin client fail";
329 }
330 Q_ASSERT(pPlugin);
331
332 set.setValue("Manage/FileVersion", m_FileVersion);
333 set.setValue("Plugin/ID", pPlugin->Id());
334 set.setValue("Plugin/Protocol", pPlugin->Protocol());
335 set.setValue("Plugin/Name", pPlugin->Name());
336 int nRet = 0;
337 //nRet = pOperate->Save(szFile);
338 bRet = QMetaObject::invokeMethod(
339 pOperate,
340 "Save",
341 Qt::DirectConnection,
342 Q_RETURN_ARG(int, nRet),
343 Q_ARG(QString, szFile));
344 if(!bRet) {
345 qCritical(log) << "Call pOperate->Save(szFile) fail.";
346 return -1;
347 }
348 if(nRet) {
349 qCritical(log) << "Save parameter fail" << nRet;
350 return -2;
351 }
352 return 0;
353}
354
355int CManager::LoadSettings(const QString szFile)
356{
357 if(!m_pParameter) {
358 qCritical(log) << "The m_pParameter is nullptr";
359 Q_ASSERT_X(m_pParameter, "CManager", "The m_pParameter is nullptr");
360 return -1;
361 }
362
363 QString s = szFile;
364 if(s.isEmpty())
365 s = m_szSettingsFile;
366 return m_pParameter->Load(s);
367}
368
369int CManager::SaveSettings(const QString szFile)
370{
371 if(!m_pParameter) {
372 qCritical(log) << "The m_pParameter is nullptr";
373 Q_ASSERT_X(m_pParameter, "CManager", "The m_pParameter is nullptr");
374 return -1;
375 }
376
377 QString s = szFile;
378 if(s.isEmpty())
379 s = m_szSettingsFile;
380 return m_pParameter->Save(s);
381}
382
383QList<QWidget*> CManager::GetSettingsWidgets(QWidget* parent)
384{
385 QList<QWidget*> lstWidget;
386
387 CParameterPluginUI* pClient = new CParameterPluginUI(parent);
388 if(pClient) {
389 pClient->SetParameter(m_pParameter);
390 lstWidget.push_back(pClient);
391 }
392#if defined(HAVE_QTERMWIDGET)
393 CParameterTerminalUI* pTermina = new CParameterTerminalUI(parent);
394 if(pTermina) {
395 pTermina->SetParameter(&m_pParameter->m_Terminal);
396 pTermina->setWindowTitle(tr("Terminal"));
397 lstWidget.push_back(pTermina);
398 }
399#endif
400 CParameterRecordUI* pRecord = new CParameterRecordUI(parent);
401 if(pRecord) {
402 pRecord->SetParameter(&m_pParameter->m_Record);
403 lstWidget.push_back(pRecord);
404 }
405
406 return lstWidget;
407}
408
410{
411 int nRet = 0;
412 QMap<QString, CPlugin*>::iterator it;
413 for(it = m_Plugins.begin(); it != m_Plugins.end(); it++)
414 {
415 nRet = handle->onProcess(it.key(), it.value());
416 if(nRet)
417 return nRet;
418 }
419 return nRet;
420}
421
422#if HAS_CPP_11
423int CManager::EnumPlugins(std::function<int(const QString &, CPlugin *)> cb)
424{
425 int nRet = 0;
426 QMap<QString, CPlugin*>::iterator it;
427 for(it = m_Plugins.begin(); it != m_Plugins.end(); it++)
428 {
429 nRet = cb(it.key(), it.value());
430 if(nRet)
431 return nRet;
432 }
433 return nRet;
434}
435#endif
436
437const QString CManager::Details() const
438{
439 return m_szDetails;
440}
441
442void CManager::slotNativeWindowRecieveKeyboard()
443{
444 Q_ASSERT(m_pParameter);
445 if(m_pParameter->GetNativeWindowReceiveKeyboard()) {
446 if(m_pHook) {
447 m_pHook->UnRegisterKeyboard();
448 m_pHook->deleteLater();
449 m_pHook = nullptr;
450 }
451 } else {
452 if(m_pHook) return;
453 m_pHook = CHook::GetHook(m_pParameter, this);
454 if(m_pHook)
455 m_pHook->RegisterKeyboard();
456 }
457}
static int RemoveTranslation()
Remove translation.
Definition Channel.cpp:138
static int InitTranslation()
Initial translation.
Definition Channel.cpp:130
The Handle COperate class.
Definition Manager.h:145
virtual int onProcess(const QString &id, CPlugin *pPlugin)=0
Process plugins.
Manage plugins.
Definition Manager.h:45
virtual QList< QWidget * > GetSettingsWidgets(QWidget *parent)
Get parameter settings widget.
Definition Manager.cpp:383
virtual int EnumPlugins(Handle *handle)
Enum plugins.
Definition Manager.cpp:409
virtual COperate * CreateOperate(const QString &id)
New COperate pointer, the owner is caller.
Definition Manager.cpp:207
virtual COperate * LoadOperate(const QString &szFile)
New COperate pointer from file, the owner is caller.
Definition Manager.cpp:268
virtual int DeleteOperate(COperate *p)
Delete COperate.
Definition Manager.cpp:235
virtual int SaveOperate(COperate *pOperate)
Accept Operate parameters to file.
Definition Manager.cpp:307
virtual int SaveSettings(const QString szFile=QString())
Save Client parameters to file.
Definition Manager.cpp:369
virtual int LoadSettings(const QString szFile=QString())
Load Client parameters from file.
Definition Manager.cpp:355
Operate interface.
Definition Operate.h:50
virtual const QString Id()
Identity.
Definition Operate.cpp:33
virtual int SetParameter(CParameter *pParameter) override
[override functions]
Global parameters of plugins.
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
Plugin interface.
Definition Plugin.h:15
virtual const QString Version() const =0
Version.
virtual const QString Details() const
Display more information in About dialog or log.
Definition Plugin.cpp:78
virtual const QString Id()
ID. Default: Type() + ":" + Protocol() + ":" + Name()
Definition Plugin.cpp:68
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 DisplayName() const
The plugin display name.
Definition Plugin.cpp:73
virtual const QString Protocol() const =0
Plugin Protocol.
virtual const QString Description() const =0
Plugin description.