3#include <QPluginLoader>
7#include <QTemporaryFile>
10#include <QLoggingCategory>
13#include <QSplashScreen>
16#include "RabbitCommonDir.h"
17#include "RabbitCommonTools.h"
18#include "ParameterPluginUI.h"
19#include "ParameterRecordUI.h"
20#if defined(HAVE_QTERMWIDGET)
21 #include "ParameterTerminalUI.h"
22 #include "OperateTerminal.h"
25 #include "ChannelSSH.h"
32#include "FrmMediaDevices.h"
33#include "ParameterFilter.h"
34#include "FrmManagePlugins.h"
36#include "ParameterDatabaseUI.h"
37#include "ParameterPlugin.h"
42static Q_LOGGING_CATEGORY(log,
"Manager")
44void ShowMessageInSplashScreen(const QString &szMsg)
46 static QSplashScreen* pSplashScreen =
nullptr;
48 pSplashScreen =
new QSplashScreen();
49 QScreen* pScreen = QApplication::primaryScreen();
51 QRect rect = pScreen->availableGeometry();
52 pSplashScreen->move(rect.width() / 4, rect.height() / 4);
53 QCoreApplication::processEvents();
54 pSplashScreen->resize(rect.width() / 2, rect.height() / 2);
55 QCoreApplication::processEvents();
57 RC_SHOW_WINDOW(pSplashScreen);
58 QCoreApplication::processEvents();
61 pSplashScreen->deleteLater();
62 pSplashScreen = nullptr;
65 QString szTitle = qApp->applicationDisplayName()
66 +
"\n" + qApp->applicationVersion() +
"\n\n";
67 pSplashScreen->showMessage(szTitle + szMsg, Qt::AlignCenter,
68 pSplashScreen->palette().color(QPalette::WindowText));
69 QCoreApplication::processEvents();
72CManager::CManager(QObject *parent) : QObject(parent)
75 , m_pParameterPlugin(nullptr)
76 , m_pDatabaseFile(nullptr)
82 qDebug(log) <<
"CManager::~CManager()";
84 qApp->removeEventFilter(
this);
87 delete m_pDatabaseFile;
88 m_pDatabaseFile =
nullptr;
93 auto pLoader = it.value();
95 pLoader->deleteLater();
99 m_pHook->UnRegisterKeyboard();
100 m_pHook->deleteLater();
104 if(m_pParameterPlugin) {
105 m_pParameterPlugin->deleteLater();
106 m_pParameterPlugin =
nullptr;
110 RabbitCommon::CTools::Instance()->RemoveTranslator(m_Translator);
126 ShowMessageInSplashScreen(tr(
"Load manager translations ......"));
127 m_Translator = RabbitCommon::CTools::Instance()->InstallTranslator(
128 "Plugin", RabbitCommon::CTools::TranslationType::Library);
130 m_szSettingsFile = szFile;
134 ShowMessageInSplashScreen(tr(
"Load manager parameters and database ......"));
136 if(m_pParameterPlugin) {
143 szFile = pg->m_Database.GetDatabaseName();
144 bool bRet = pg->m_DatabaseLocal.OpenSQLiteDatabase(szFile,
"Local_connect");
146 bRet = pg->m_DatabaseRemote.OpenDatabase(&pg->m_Database,
"Remote_connect");
148 bRet = m_pParameterPlugin->m_WhiteList.InitDatabase(&pg->m_DatabaseLocal);
150 bRet = m_pParameterPlugin->m_BlackList.InitDatabase(&pg->m_DatabaseLocal);
156#if defined(Q_OS_ANDROID)
159#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0) && defined(Q_OS_WIN)
160 szSnap = qEnvironmentVariable(
"SNAP");
161 szFlatpak = qEnvironmentVariable(
"FLATPAK_ID");
163 szSnap = QString::fromLocal8Bit(qgetenv(
"SNAP"));
164 szFlatpak = QString::fromLocal8Bit(qgetenv(
"FLATPAK_ID"));
166 if(!szSnap.isEmpty() || !szFlatpak.isEmpty())
168 if(bReboot && !RabbitCommon::CTools::Instance()->HasAdministratorPrivilege()
169 && m_pParameterPlugin->GetPromptAdministratorPrivilege())
173 szMsg = tr(
"The programe is not administrator privilege.\n"
174 "Some features are limited.\n");
176 szMsg += tr(
"Eg: Can not disable system shortcuts(eg: Ctrl+Alt+del).") +
"\n";
178 szMsg += tr(
"Eg: Can not use the wake on LAN feature.") +
"\n";
180 szMsg += tr(
"Restart program by administrator?");
181 QMessageBox msg(QMessageBox::Warning, tr(
"Warning"), szMsg,
182 QMessageBox::Yes | QMessageBox::No);
183 msg.setCheckBox(
new QCheckBox(tr(
"Always shown"), &msg));
184 msg.checkBox()->setCheckable(
true);
185 msg.checkBox()->setChecked(
186 m_pParameterPlugin->GetPromptAdministratorPrivilege());
189 m_pParameterPlugin->SetPromptAdministratorPrivilege(
190 msg.checkBox()->isChecked());
193 if(QMessageBox::Yes == nRet) {
194 RabbitCommon::CTools::Instance()->StartWithAdministratorPrivilege(
true);
199 check = connect(m_pParameterPlugin, SIGNAL(sigCaptureAllKeyboard()),
200 this, SLOT(slotCaptureAllKeyboard()));
202 if(m_pParameterPlugin->GetCaptureAllKeyboard()) {
203 m_pHook = CHook::GetHook(m_pParameterPlugin,
this);
205 m_pHook->RegisterKeyboard();
208 qCritical(log) <<
"new CParameterPlugin() fail";
209 Q_ASSERT(m_pParameterPlugin);
212 ShowMessageInSplashScreen(tr(
"Load plugins ......"));
216 if(m_pDatabaseFile) {
218 bool bRet = m_pDatabaseFile->SetDatabase(&pg->m_DatabaseRemote);
225int CManager::LoadPlugins()
229 QStringList lstPaths;
230 if(m_pParameterPlugin->GetEnableSetPluginsPath()) {
231 lstPaths = m_pParameterPlugin->GetPluginsPath();
234 lstPaths << RabbitCommon::CDir::Instance()->GetDirPlugins();
235 if(lstPaths.isEmpty())
236 qWarning(log) <<
"The plugins path is empty. please set it from: `Menu` -> `Tools` -> `Settings` -> `Load Plugins`";
238 if(m_pParameterPlugin->GetOnlyLoadInWhitelist()) {
239 m_pParameterPlugin->m_WhiteList.OnProcess([
this, lstPaths](
const QString& szPath) ->
int{
240 QFileInfo fi(szPath);
243 foreach (
auto d, lstPaths) {
244 if(d.isEmpty())
continue;
245 QString szFile = d + QDir::separator() + szPath;
253 foreach (
auto szPath, lstPaths) {
257 if(filters.isEmpty())
259#if defined (Q_OS_WINDOWS) || defined(Q_OS_WIN)
260 filters <<
"*Plugin*.dll";
261#elif defined(Q_OS_MACOS) || defined(Q_OS_MAC)
262 filters <<
"*Plugin*.dylib";
264 filters <<
"*Plugin*.so";
267 nRet = FindPlugins(szPath, filters);
271 qWarning(log) <<
"The plugins is empty. please set it from: `Menu` -> `Tools` -> `Settings` -> `Load Plugins`";
274 if(!m_szDetails.isEmpty())
275 m_szDetails =
"## " + tr(
"Plugins") +
"\n" + m_szDetails;
277 qDebug(log) << (
"Client details:\n" + Details()).toStdString().c_str();
281int CManager::FindPlugins(QDir dir, QStringList filters)
285 QString szCurrentPath = QDir::currentPath();
286 QStringList files = dir.entryList(filters, QDir::Files | QDir::NoDotAndDotDot);
292 QDir::setCurrent(QDir::cleanPath(dir.absolutePath()));
303 foreach (fileName, files) {
304 QString szPlugins = dir.absoluteFilePath(fileName);
305 if(m_pParameterPlugin
306 && (!m_pParameterPlugin->m_WhiteList.contains(fileName) || !m_pParameterPlugin->m_WhiteList.contains(fileName))
307 && (m_pParameterPlugin->m_BlackList.contains(fileName) || m_pParameterPlugin->m_BlackList.contains(fileName))) {
308 qInfo(log) <<
"Filter:" << szPlugins <<
"in blacklist";
314 foreach (fileName, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
315 QDir pluginDir = dir;
316 if(pluginDir.cd(fileName))
317 FindPlugins(pluginDir, filters);
320 QDir::setCurrent(szCurrentPath);
328 QPluginLoader* pLoader =
new QPluginLoader(szPath,
this);
330 QString szTitle = tr(
"Load plugins ......") +
"\n";
331 QObject *plugin = pLoader->instance();
333 CPlugin* p = qobject_cast<CPlugin*>(plugin);
337 tr(
"Success: Load plugin %1").arg(p->
Name());
338 qInfo(log) << szMsg <<
"from" << szPath;
339 ShowMessageInSplashScreen(szTitle + szMsg);
343 qWarning(log) <<
"The plugin [" << p->
Name() <<
"] is exist.";
347 qCritical(log) <<
"The plugin is not \"CPlugin\":" << szPath;
350 szMsg = tr(
"Failed: Load plugin from %1").arg(szPath);
351 if(!pLoader->errorString().isEmpty())
352 szMsg +=
"; " + tr(
"Error:") +
" " + pLoader->errorString();
353 qCritical(log) << szMsg.toStdString().c_str();
354 ShowMessageInSplashScreen(szTitle + szMsg);
357 pLoader->deleteLater();
363 if(!pLoader)
return -1;
367 bool bRet = QMetaObject::invokeMethod(
370 Qt::DirectConnection,
371 Q_RETURN_ARG(
int, val));
374 qCritical(log) <<
"The plugin" << p->
Name()
375 <<
"initial translator fail" << bRet << val;
379 m_szDetails +=
"- " + tr(
"Version:") +
" " + p->
Version() +
"\n";
380 m_szDetails +=
"- " + tr(
"Type:") +
" " + p->TypeName(p->Type()) +
"\n";
382 m_szDetails +=
"- " + tr(
"Protocol:") +
" " + p->
Protocol() +
"\n";
383 m_szDetails +=
"- " + tr(
"ID:") +
" " + p->
Id() +
"\n";
385 m_szDetails +=
"- " + tr(
"Description:") +
" " + p->
Description() +
"\n";
388 m_szDetails += p->
Details() +
"\n";
403 qDebug(log) <<
"CreateOperate id:" << id;
404 auto plugin = it.value()->instance();
407 bRet = QMetaObject::invokeMethod(
410 Qt::DirectConnection,
415 qCritical(log) <<
"Create COperate fail.";
426 qDebug(log) << Q_FUNC_INFO;
431 bool bRet = QMetaObject::invokeMethod(
434 Qt::DirectConnection,
435 Q_RETURN_ARG(
CPlugin*, pPlugin));
437 if(bRet && pPlugin) {
440 bRet = QMetaObject::invokeMethod(
443 Qt::DirectConnection,
444 Q_RETURN_ARG(
int, nRet),
448 qCritical(log) <<
"Call pPlugin->DeleteOperate(p) fail";
453 qCritical(log) <<
"Get CManager fail.";
460 if(szFile.isEmpty())
return nullptr;
461 qDebug(log) <<
"Load operate configure file:"<< szFile;
462 if(m_pParameterPlugin->GetGlobalParameters()->GetSaveSettingsType()
463 == CParameterGlobal::SaveSettingsType::Database && m_pDatabaseFile) {
464 qDebug(log) <<
"Load file from database";
465 QByteArray content = m_pDatabaseFile->Load(szFile);
466 if(!content.isEmpty()) {
468 if(!f.open(QFile::WriteOnly | QFile::Text))
return nullptr;
469 f.write(content.data(), content.length());
474 QSettings set(szFile, QSettings::IniFormat);
475 m_FileVersion = set.value(
"Manage/FileVersion", m_FileVersion).toInt();
476 QString
id = set.value(
"Plugin/ID").toString();
477 QString protocol = set.value(
"Plugin/Protocol").toString();
478 QString name = set.value(
"Plugin/Name").toString();
479 qDebug(log) <<
"LoadOperate protocol:" << protocol
480 <<
"name:" << name <<
"id:" << id;
485 bool bRet = QMetaObject::invokeMethod(
488 Qt::DirectConnection,
489 Q_RETURN_ARG(
int, nRet),
490 Q_ARG(QString, szFile));
492 qCritical(log) <<
"Call pOperate->Load(szFile) fail.";
496 qCritical(log) <<
"Load parameter fail" << nRet;
500 pOperate->SetSettingsFile(szFile);
503 qCritical(log) <<
"Don't create Operate:" << name << protocol <<
id << szFile;
510 if(!pOperate)
return -1;
512 QString szFile = pOperate->GetSettingsFile();
514 szFile = RabbitCommon::CDir::Instance()->GetDirUserData()
519 QSettings set(szFile, QSettings::IniFormat);
521 bool bRet = QMetaObject::invokeMethod(
524 Qt::DirectConnection,
525 Q_RETURN_ARG(
CPlugin*, pPlugin));
526 if(!bRet || !pPlugin)
528 qCritical(log) <<
"Get plugin client fail";
532 set.setValue(
"Manage/FileVersion", m_FileVersion);
533 set.setValue(
"Plugin/ID", pPlugin->
Id());
534 set.setValue(
"Plugin/Protocol", pPlugin->
Protocol());
535 set.setValue(
"Plugin/Name", pPlugin->
Name());
538 bRet = QMetaObject::invokeMethod(
541 Qt::DirectConnection,
542 Q_RETURN_ARG(
int, nRet),
543 Q_ARG(QString, szFile));
545 qCritical(log) <<
"Call pOperate->Save(szFile) fail.";
549 qCritical(log) <<
"Save parameter fail" << nRet;
553 if(m_pParameterPlugin->GetGlobalParameters()->GetSaveSettingsType()
554 == CParameterGlobal::SaveSettingsType::Database && m_pDatabaseFile) {
555 qDebug(log) <<
"Save file to database";
556 return m_pDatabaseFile->Save(szFile) ? 0 : -1;
564 if(!m_pParameterPlugin) {
565 qCritical(log) <<
"The m_pParameter is nullptr";
566 Q_ASSERT_X(m_pParameterPlugin,
"CManager",
"The m_pParameter is nullptr");
572 s = m_szSettingsFile;
573 return m_pParameterPlugin->Load(s);
578 if(!m_pParameterPlugin) {
579 qCritical(log) <<
"The m_pParameter is nullptr";
580 Q_ASSERT_X(m_pParameterPlugin,
"CManager",
"The m_pParameter is nullptr");
586 s = m_szSettingsFile;
587 return m_pParameterPlugin->Save(s);
592 if(m_pParameterPlugin)
593 return m_pParameterPlugin->GetGlobalParameters();
599 QList<QWidget*> lstWidget;
603 int nRet = pManagePlugins->
SetParameter(m_pParameterPlugin);
605 lstWidget.push_back(pManagePlugins);
612 lstWidget.push_back(pClient);
620 lstWidget.push_back(pDatabase);
624#if defined(HAVE_QTERMWIDGET)
627 pTermina->
SetParameter(&m_pParameterPlugin->m_Terminal);
628 pTermina->setWindowTitle(tr(
"Terminal"));
629 lstWidget.push_back(pTermina);
634 int nRet = pRecord->SetParameter(&m_pParameterPlugin->m_Record);
636 lstWidget.push_back(pRecord);
639 CFrmMediaDevices* pMediaDevices =
new CFrmMediaDevices(
true, parent);
641 int nRet = pMediaDevices->SetParameter(&m_pParameterPlugin->m_MediaDevices.m_Para);
643 lstWidget.push_back(pMediaDevices);
648 auto plugin = pLoader->instance();
649 if(!plugin)
continue;
650 QWidget* pSettings =
nullptr;
651 bool bRet = QMetaObject::invokeMethod(
654 Qt::DirectConnection,
655 Q_RETURN_ARG(QWidget*, pSettings),
656 Q_ARG(QWidget*, parent));
658 qCritical(log) <<
"Call CPlugin::GetSettingsWidget() fail.";
661 if(!pSettings)
continue;
662 lstWidget.push_back(pSettings);
674 CPlugin* p = qobject_cast<CPlugin*>(it.value()->instance());
688 CPlugin* p = qobject_cast<CPlugin*>(it.value()->instance());
689 nRet = cb(it.key(), p);
697const QString CManager::Details()
const
701 szDetail += COperateTerminal::Details();
704 CChannelSSH channel(
nullptr,
nullptr);
705 szDetail += channel.GetDetails();
708 szDetail +=
"- QtKeyChain\n" +
709 QString(
" - ") + tr(
"Version:")
710 +
" 0x" + QString::number(QTKEYCHAIN_VERSION, 16) +
"\n";
713 if(!szDetail.isEmpty()) {
714 szDetail =
"## " + tr(
"Dependency libraries") +
"\n" + szDetail;
717 if(m_pParameterPlugin)
718 szDetail += m_pParameterPlugin->GetGlobalParameters()->m_Database.Details();
720 szDetail += m_szDetails;
724void CManager::slotCaptureAllKeyboard()
726 Q_ASSERT(m_pParameterPlugin);
727 if(m_pParameterPlugin->GetCaptureAllKeyboard()) {
729 m_pHook = CHook::GetHook(m_pParameterPlugin,
this);
731 m_pHook->RegisterKeyboard();
734 m_pHook->UnRegisterKeyboard();
735 m_pHook->deleteLater();
static int RemoveTranslation()
Remove translation.
static int InitTranslation()
Initial translation.
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.
virtual int SetParameter(CParameter *pParameter) override
[override functions]
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.