3#include <QPluginLoader>
7#include <QTemporaryFile>
10#include <QLoggingCategory>
14#include "RabbitCommonDir.h"
15#include "RabbitCommonTools.h"
16#include "ParameterPluginUI.h"
17#include "ParameterRecordUI.h"
18#if defined(HAVE_QTERMWIDGET)
19 #include "ParameterTerminalUI.h"
20 #include "OperateTerminal.h"
23 #include "ChannelSSH.h"
30#include "FrmMediaDevices.h"
31#include "ParameterFilter.h"
32#include "FrmManagePlugins.h"
34#include "ParameterDatabaseUI.h"
35#include "ParameterPlugin.h"
40static Q_LOGGING_CATEGORY(log,
"Manager")
45 , m_pParameterPlugin(
nullptr)
46 , m_pDatabaseFile(
nullptr)
52 qDebug(log) <<
"CManager::~CManager()";
54 qApp->removeEventFilter(
this);
57 delete m_pDatabaseFile;
58 m_pDatabaseFile =
nullptr;
63 auto pLoader = it.value();
65 pLoader->deleteLater();
69 m_pHook->UnRegisterKeyboard();
70 m_pHook->deleteLater();
74 if(m_pParameterPlugin) {
75 m_pParameterPlugin->deleteLater();
76 m_pParameterPlugin =
nullptr;
80 RabbitCommon::CTools::Instance()->RemoveTranslator(m_Translator);
96 m_Translator = RabbitCommon::CTools::Instance()->InstallTranslator(
97 "Plugin", RabbitCommon::CTools::TranslationType::Library);
99 m_szSettingsFile = szFile;
104 if(m_pParameterPlugin) {
111 szFile = pg->m_Database.GetDatabaseName();
112 bool bRet = pg->m_DatabaseLocal.OpenSQLiteDatabase(szFile,
"Local_connect");
114 bRet = pg->m_DatabaseRemote.OpenDatabase(&pg->m_Database,
"Remote_connect");
116 bRet = m_pParameterPlugin->m_WhiteList.InitDatabase(&pg->m_DatabaseLocal);
118 bRet = m_pParameterPlugin->m_BlackList.InitDatabase(&pg->m_DatabaseLocal);
124#if defined(Q_OS_ANDROID)
127#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0) && defined(Q_OS_WIN)
128 szSnap = qEnvironmentVariable(
"SNAP");
129 szFlatpak = qEnvironmentVariable(
"FLATPAK_ID");
131 szSnap = QString::fromLocal8Bit(qgetenv(
"SNAP"));
132 szFlatpak = QString::fromLocal8Bit(qgetenv(
"FLATPAK_ID"));
134 if(!szSnap.isEmpty() || !szFlatpak.isEmpty())
136 if(bReboot && !RabbitCommon::CTools::Instance()->HasAdministratorPrivilege()
137 && m_pParameterPlugin->GetPromptAdministratorPrivilege())
141 szMsg = tr(
"The programe is not administrator privilege.\n"
142 "Some features are limited.\n");
144 szMsg += tr(
"Eg: Can not disable system shortcuts(eg: Ctrl+Alt+del).") +
"\n";
146 szMsg += tr(
"Eg: Can not use the wake on LAN feature.") +
"\n";
148 szMsg += tr(
"Restart program by administrator?");
149 QMessageBox msg(QMessageBox::Warning, tr(
"Warning"), szMsg,
150 QMessageBox::Yes | QMessageBox::No);
151 msg.setCheckBox(
new QCheckBox(tr(
"Always shown"), &msg));
152 msg.checkBox()->setCheckable(
true);
153 msg.checkBox()->setChecked(
154 m_pParameterPlugin->GetPromptAdministratorPrivilege());
157 m_pParameterPlugin->SetPromptAdministratorPrivilege(
158 msg.checkBox()->isChecked());
161 if(QMessageBox::Yes == nRet) {
162 RabbitCommon::CTools::Instance()->StartWithAdministratorPrivilege(
true);
167 check = connect(m_pParameterPlugin, SIGNAL(sigCaptureAllKeyboard()),
168 this, SLOT(slotCaptureAllKeyboard()));
170 if(m_pParameterPlugin->GetCaptureAllKeyboard()) {
171 m_pHook = CHook::GetHook(m_pParameterPlugin,
this);
173 m_pHook->RegisterKeyboard();
176 qCritical(log) <<
"new CParameterPlugin() fail";
177 Q_ASSERT(m_pParameterPlugin);
183 if(m_pDatabaseFile) {
185 bool bRet = m_pDatabaseFile->
SetDatabase(&pg->m_DatabaseRemote);
192int CManager::LoadPlugins()
196 QStringList lstPaths;
197 if(m_pParameterPlugin->GetEnableSetPluginsPath()) {
198 lstPaths = m_pParameterPlugin->GetPluginsPath();
201 lstPaths << RabbitCommon::CDir::Instance()->GetDirPlugins();
202 if(lstPaths.isEmpty())
203 qWarning(log) <<
"The plugins path is empty. please set it from: `Menu` -> `Tools` -> `Settings` -> `Load Plugins`";
205 if(m_pParameterPlugin->GetOnlyLoadInWhitelist()) {
206 m_pParameterPlugin->m_WhiteList.OnProcess([
this, lstPaths](
const QString& szPath) ->
int{
207 QFileInfo fi(szPath);
210 foreach (
auto d, lstPaths) {
211 if(d.isEmpty())
continue;
212 QString szFile = d + QDir::separator() + szPath;
220 foreach (
auto szPath, lstPaths) {
224 if(filters.isEmpty())
226#if defined (Q_OS_WINDOWS) || defined(Q_OS_WIN)
227 filters <<
"*Plugin*.dll";
228#elif defined(Q_OS_MACOS) || defined(Q_OS_MAC)
229 filters <<
"*Plugin*.dylib";
231 filters <<
"*Plugin*.so";
234 nRet = FindPlugins(szPath, filters);
238 qWarning(log) <<
"The plugins is empty. please set it from: `Menu` -> `Tools` -> `Settings` -> `Load Plugins`";
241 if(!m_szDetails.isEmpty())
242 m_szDetails =
"## " + tr(
"Plugins") +
"\n" + m_szDetails;
244 qDebug(log) << (
"Client details:\n" + Details()).toStdString().c_str();
248int CManager::FindPlugins(QDir dir, QStringList filters)
252 QString szCurrentPath = QDir::currentPath();
253 QStringList files = dir.entryList(filters, QDir::Files | QDir::NoDotAndDotDot);
259 QDir::setCurrent(QDir::cleanPath(dir.absolutePath()));
270 foreach (fileName, files) {
271 QString szPlugins = dir.absoluteFilePath(fileName);
272 if(m_pParameterPlugin
273 && (!m_pParameterPlugin->m_WhiteList.contains(fileName) || !m_pParameterPlugin->m_WhiteList.contains(fileName))
274 && (m_pParameterPlugin->m_BlackList.contains(fileName) || m_pParameterPlugin->m_BlackList.contains(fileName))) {
275 qInfo(log) <<
"Filter:" << szPlugins <<
"in blacklist";
281 foreach (fileName, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
282 QDir pluginDir = dir;
283 if(pluginDir.cd(fileName))
284 FindPlugins(pluginDir, filters);
287 QDir::setCurrent(szCurrentPath);
295 QPluginLoader* pLoader =
new QPluginLoader(szPath,
this);
297 QObject *plugin = pLoader->instance();
299 CPlugin* p = qobject_cast<CPlugin*>(plugin);
302 qInfo(log) <<
"Success: Load plugin"
303 << p->
Name() <<
"from" << szPath;
307 qWarning(log) <<
"The plugin [" << p->
Name() <<
"] is exist.";
311 qCritical(log) <<
"The plugin is not \"CPlugin\":" << szPath;
314 szMsg =
"Error: Load plugin fail from " + szPath;
315 if(!pLoader->errorString().isEmpty())
316 szMsg +=
"; Error: " + pLoader->errorString();
317 qCritical(log) << szMsg.toStdString().c_str();
320 pLoader->deleteLater();
326 if(!pLoader)
return -1;
330 bool bRet = QMetaObject::invokeMethod(
333 Qt::DirectConnection,
334 Q_RETURN_ARG(
int, val));
337 qCritical(log) <<
"The plugin" << p->
Name()
338 <<
"initial translator fail" << bRet << val;
342 m_szDetails +=
"- " + tr(
"Version:") +
" " + p->
Version() +
"\n";
343 m_szDetails +=
"- " + tr(
"Type:") +
" " + p->TypeName(p->Type()) +
"\n";
345 m_szDetails +=
"- " + tr(
"Protocol:") +
" " + p->
Protocol() +
"\n";
346 m_szDetails +=
"- " + tr(
"ID:") +
" " + p->
Id() +
"\n";
348 m_szDetails +=
"- " + tr(
"Description:") +
" " + p->
Description() +
"\n";
351 m_szDetails += p->
Details() +
"\n";
366 qDebug(log) <<
"CreateOperate id:" << id;
367 auto plugin = it.value()->instance();
370 bRet = QMetaObject::invokeMethod(
373 Qt::DirectConnection,
378 qCritical(log) <<
"Create COperate fail.";
389 qDebug(log) << Q_FUNC_INFO;
394 bool bRet = QMetaObject::invokeMethod(
397 Qt::DirectConnection,
398 Q_RETURN_ARG(
CPlugin*, pPlugin));
400 if(bRet && pPlugin) {
403 bRet = QMetaObject::invokeMethod(
406 Qt::DirectConnection,
407 Q_RETURN_ARG(
int, nRet),
411 qCritical(log) <<
"Call pPlugin->DeleteOperate(p) fail";
416 qCritical(log) <<
"Get CManager fail.";
423 if(szFile.isEmpty())
return nullptr;
424 qDebug(log) <<
"Load operate configure file:"<< szFile;
426 == CParameterGlobal::SaveSettingsType::Database && m_pDatabaseFile) {
427 qDebug(log) <<
"Load file from database";
428 QByteArray content = m_pDatabaseFile->
Load(szFile);
429 if(!content.isEmpty()) {
431 if(!f.open(QFile::WriteOnly | QFile::Text))
return nullptr;
432 f.write(content.data(), content.length());
437 QSettings set(szFile, QSettings::IniFormat);
438 m_FileVersion = set.value(
"Manage/FileVersion", m_FileVersion).toInt();
439 QString
id = set.value(
"Plugin/ID").toString();
440 QString protocol = set.value(
"Plugin/Protocol").toString();
441 QString name = set.value(
"Plugin/Name").toString();
442 qDebug(log) <<
"LoadOperate protocol:" << protocol
443 <<
"name:" << name <<
"id:" << id;
448 bool bRet = QMetaObject::invokeMethod(
451 Qt::DirectConnection,
452 Q_RETURN_ARG(
int, nRet),
453 Q_ARG(QString, szFile));
455 qCritical(log) <<
"Call pOperate->Load(szFile) fail.";
459 qCritical(log) <<
"Load parameter fail" << nRet;
463 pOperate->SetSettingsFile(szFile);
466 qCritical(log) <<
"Don't create Operate:" << name << protocol <<
id << szFile;
473 if(!pOperate)
return -1;
475 QString szFile = pOperate->GetSettingsFile();
477 szFile = RabbitCommon::CDir::Instance()->GetDirUserData()
482 QSettings set(szFile, QSettings::IniFormat);
484 bool bRet = QMetaObject::invokeMethod(
487 Qt::DirectConnection,
488 Q_RETURN_ARG(
CPlugin*, pPlugin));
489 if(!bRet || !pPlugin)
491 qCritical(log) <<
"Get plugin client fail";
495 set.setValue(
"Manage/FileVersion", m_FileVersion);
496 set.setValue(
"Plugin/ID", pPlugin->
Id());
497 set.setValue(
"Plugin/Protocol", pPlugin->
Protocol());
498 set.setValue(
"Plugin/Name", pPlugin->
Name());
501 bRet = QMetaObject::invokeMethod(
504 Qt::DirectConnection,
505 Q_RETURN_ARG(
int, nRet),
506 Q_ARG(QString, szFile));
508 qCritical(log) <<
"Call pOperate->Save(szFile) fail.";
512 qCritical(log) <<
"Save parameter fail" << nRet;
517 == CParameterGlobal::SaveSettingsType::Database && m_pDatabaseFile) {
518 qDebug(log) <<
"Save file to database";
519 return m_pDatabaseFile->
Save(szFile) ? 0 : -1;
527 if(!m_pParameterPlugin) {
528 qCritical(log) <<
"The m_pParameter is nullptr";
529 Q_ASSERT_X(m_pParameterPlugin,
"CManager",
"The m_pParameter is nullptr");
535 s = m_szSettingsFile;
536 return m_pParameterPlugin->
Load(s);
541 if(!m_pParameterPlugin) {
542 qCritical(log) <<
"The m_pParameter is nullptr";
543 Q_ASSERT_X(m_pParameterPlugin,
"CManager",
"The m_pParameter is nullptr");
549 s = m_szSettingsFile;
550 return m_pParameterPlugin->
Save(s);
555 if(m_pParameterPlugin)
562 QList<QWidget*> lstWidget;
566 int nRet = pManagePlugins->
SetParameter(m_pParameterPlugin);
568 lstWidget.push_back(pManagePlugins);
575 lstWidget.push_back(pClient);
583 lstWidget.push_back(pDatabase);
587#if defined(HAVE_QTERMWIDGET)
590 pTermina->
SetParameter(&m_pParameterPlugin->m_Terminal);
591 pTermina->setWindowTitle(tr(
"Terminal"));
592 lstWidget.push_back(pTermina);
597 int nRet = pRecord->SetParameter(&m_pParameterPlugin->m_Record);
599 lstWidget.push_back(pRecord);
602 CFrmMediaDevices* pMediaDevices =
new CFrmMediaDevices(
true, parent);
604 int nRet = pMediaDevices->SetParameter(&m_pParameterPlugin->m_MediaDevices.m_Para);
606 lstWidget.push_back(pMediaDevices);
611 auto plugin = pLoader->instance();
612 if(!plugin)
continue;
613 QWidget* pSettings =
nullptr;
614 bool bRet = QMetaObject::invokeMethod(
617 Qt::DirectConnection,
618 Q_RETURN_ARG(QWidget*, pSettings),
619 Q_ARG(QWidget*, parent));
621 qCritical(log) <<
"Call CPlugin::GetSettingsWidget() fail.";
624 if(!pSettings)
continue;
625 lstWidget.push_back(pSettings);
637 CPlugin* p = qobject_cast<CPlugin*>(it.value()->instance());
651 CPlugin* p = qobject_cast<CPlugin*>(it.value()->instance());
652 nRet = cb(it.key(), p);
660const QString CManager::Details()
const
664 szDetail += COperateTerminal::Details();
668 szDetail += channel.GetDetails();
671 szDetail +=
"- QtKeyChain\n" +
672 QString(
" - ") + tr(
"Version:")
673 +
" 0x" + QString::number(QTKEYCHAIN_VERSION, 16) +
"\n";
676 if(!szDetail.isEmpty()) {
677 szDetail =
"## " + tr(
"Dependency libraries") +
"\n" + szDetail;
680 if(m_pParameterPlugin)
683 szDetail += m_szDetails;
687void CManager::slotCaptureAllKeyboard()
689 Q_ASSERT(m_pParameterPlugin);
690 if(m_pParameterPlugin->GetCaptureAllKeyboard()) {
692 m_pHook = CHook::GetHook(m_pParameterPlugin,
this);
694 m_pHook->RegisterKeyboard();
697 m_pHook->UnRegisterKeyboard();
698 m_pHook->deleteLater();
static int RemoveTranslation()
Remove translation.
static int InitTranslation()
Initial translation.
bool Save(const QString &szFile)
Save.
QByteArray Load(const QString &szFile)
Load.
bool SetDatabase(const CDatabase *db)
Share an existing database.
virtual int SetParameter(CParameter *pParameter) override
[override functions]
The Handle COperate class.
virtual int onProcess(const QString &id, CPlugin *pPlugin)=0
Process plugins.
virtual QList< QWidget * > GetSettingsWidgets(QWidget *parent)
Get parameter settings widget.
virtual int EnumPlugins(Handle *handle)
Enum plugins.
virtual COperate * CreateOperate(const QString &id)
New COperate pointer, the owner is caller.
int LoadPlugin(const QString &szPath)
LoadPlugin.
virtual COperate * LoadOperate(const QString &szFile)
New COperate pointer from file, the owner is caller.
virtual int DeleteOperate(COperate *p)
Delete COperate.
virtual int SaveOperate(COperate *pOperate)
Accept Operate parameters to file.
int AppendPlugin(QPluginLoader *pLoader, CPlugin *p)
Append Plugin.
int Initial(QString szFile=QString())
Initial.
QMap< QString, QPluginLoader * > m_Plugins
ID -> CPlugin.
virtual int SaveSettings(const QString szFile=QString())
Save Client parameters to file.
CParameterGlobal * GetGlobalParameters()
Get Global Parameters.
void sigNewOperate(COperate *pOperate, bool bOpenSettingsDialog)
This signal is triggered when a new operate is created in the plugin.
virtual int LoadSettings(const QString szFile=QString())
Load Client parameters from file.
virtual int SetParameter(CParameter *pParameter) override
[override functions]
Global parameters of plugins.
CParameterGlobal * GetGlobalParameters()
Get global parameters.
virtual int SetParameter(CParameter *pParameter) override
[override functions]
virtual int Save(QString szFile=QString(), bool bForce=true)
Save to file.
virtual int Load(QString szFile=QString())
Load from file.
virtual const QString Version() const =0
Version.
void sigNewOperate(COperate *pOperate, bool bOpenSettingsDialog)
This signal is triggered when a new operate is created in the plugin.
virtual const QString Details() const =0
Display more information in About dialog or log.
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.
virtual const QString Protocol() const =0
Plugin Protocol.
virtual const QString Id() const
ID. Default: Type() + ":" + Protocol() + ":" + Name()
virtual const QString Description() const =0
Plugin description.