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 m_pHook->UnRegisterKeyboard();
58 m_pHook->deleteLater();
62 if(m_pParameterPlugin) {
63 m_pParameterPlugin->deleteLater();
64 m_pParameterPlugin =
nullptr;
68 RabbitCommon::CTools::Instance()->RemoveTranslator(m_Translator);
77int CManager::Initial(QString szFile)
84 m_Translator = RabbitCommon::CTools::Instance()->InstallTranslator(
85 "Plugin", RabbitCommon::CTools::TranslationType::Library);
87 m_szSettingsFile = szFile;
92 if(m_pParameterPlugin) {
98#if defined(Q_OS_ANDROID)
101#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0) && defined(Q_OS_WIN)
102 szSnap = qEnvironmentVariable(
"SNAP");
103 szFlatpak = qEnvironmentVariable(
"FLATPAK_ID");
105 szSnap = QString::fromLocal8Bit(qgetenv(
"SNAP"));
106 szFlatpak = QString::fromLocal8Bit(qgetenv(
"FLATPAK_ID"));
108 if(!szSnap.isEmpty() || !szFlatpak.isEmpty())
110 if(bReboot && !RabbitCommon::CTools::Instance()->HasAdministratorPrivilege()
111 && m_pParameterPlugin->GetPromptAdministratorPrivilege())
115 szMsg = tr(
"The programe is not administrator privilege.\n"
116 "Some features are limited.\n");
118 szMsg += tr(
"Eg: Can not disable system shortcuts(eg: Ctrl+Alt+del).") +
"\n";
120 szMsg += tr(
"Eg: Can not use the wake on LAN feature.") +
"\n";
122 szMsg += tr(
"Restart program by administrator?");
123 QMessageBox msg(QMessageBox::Warning, tr(
"Warning"), szMsg,
124 QMessageBox::Yes | QMessageBox::No);
125 msg.setCheckBox(
new QCheckBox(tr(
"Always shown"), &msg));
126 msg.checkBox()->setCheckable(
true);
127 msg.checkBox()->setChecked(
128 m_pParameterPlugin->GetPromptAdministratorPrivilege());
131 m_pParameterPlugin->SetPromptAdministratorPrivilege(
132 msg.checkBox()->isChecked());
135 if(QMessageBox::Yes == nRet) {
136 RabbitCommon::CTools::Instance()->StartWithAdministratorPrivilege(
true);
141 check = connect(m_pParameterPlugin, SIGNAL(sigCaptureAllKeyboard()),
142 this, SLOT(slotCaptureAllKeyboard()));
144 if(m_pParameterPlugin->GetCaptureAllKeyboard()) {
145 m_pHook = CHook::GetHook(m_pParameterPlugin,
this);
147 m_pHook->RegisterKeyboard();
150 qCritical(log) <<
"new CParameterPlugin() fail";
151 Q_ASSERT(m_pParameterPlugin);
157 if(m_pDatabaseFile) {
167int CManager::LoadPlugins()
186 QStringList lstPaths;
187 if(m_pParameterPlugin->GetEnableSetPluginsPath()) {
188 lstPaths = m_pParameterPlugin->GetPluginsPath();
191 lstPaths << RabbitCommon::CDir::Instance()->GetDirPlugins();
192 if(lstPaths.isEmpty())
193 qWarning(log) <<
"The plugins path is empty. please set it from: `Menu` -> `Tools` -> `Settings` -> `Load Plugins`";
195 if(m_pParameterPlugin->GetOnlyLoadInWhitelist()) {
196 m_pParameterPlugin->m_WhiteList.OnProcess([
this, lstPaths](
const QString& szPath) ->
int{
197 QFileInfo fi(szPath);
200 foreach (
auto d, lstPaths) {
201 if(d.isEmpty())
continue;
202 QString szFile = d + QDir::separator() + szPath;
210 foreach (
auto szPath, lstPaths) {
214 if(filters.isEmpty())
216#if defined (Q_OS_WINDOWS) || defined(Q_OS_WIN)
217 filters <<
"*Plugin*.dll";
218#elif defined(Q_OS_MACOS) || defined(Q_OS_MAC)
219 filters <<
"*Plugin*.dylib";
221 filters <<
"*Plugin*.so";
224 nRet = FindPlugins(szPath, filters);
227 if(m_Plugins.empty()) {
228 qWarning(log) <<
"The plugins is empty. please set it from: `Menu` -> `Tools` -> `Settings` -> `Load Plugins`";
231 if(!m_szDetails.isEmpty())
232 m_szDetails =
"## " + tr(
"Plugins") +
"\n" + m_szDetails;
234 qDebug(log) << (
"Client details:\n" + Details()).toStdString().c_str();
238int CManager::FindPlugins(QDir dir, QStringList filters)
242 QString szCurrentPath = QDir::currentPath();
243 QStringList files = dir.entryList(filters, QDir::Files | QDir::NoDotAndDotDot);
249 QDir::setCurrent(QDir::cleanPath(dir.absolutePath()));
260 foreach (fileName, files) {
261 QString szPlugins = dir.absoluteFilePath(fileName);
262 if(m_pParameterPlugin
263 && (!m_pParameterPlugin->m_WhiteList.contains(szPlugins) || !m_pParameterPlugin->m_WhiteList.contains(fileName))
264 && (m_pParameterPlugin->m_BlackList.contains(szPlugins) || m_pParameterPlugin->m_BlackList.contains(fileName))) {
265 qInfo(log) <<
"Filter:" << szPlugins <<
"in blacklist";
271 foreach (fileName, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
272 QDir pluginDir = dir;
273 if(pluginDir.cd(fileName))
274 FindPlugins(pluginDir, filters);
277 QDir::setCurrent(szCurrentPath);
285 QPluginLoader loader(szPath);
286 QObject *plugin = loader.instance();
288 CPlugin* p = qobject_cast<CPlugin*>(plugin);
291 if(m_Plugins.find(p->
Id()) == m_Plugins.end())
293 qInfo(log) <<
"Success: Load plugin"
294 << p->
Name() <<
"from" << szPath;
298 qWarning(log) <<
"The plugin [" << p->
Name() <<
"] is exist.";
301 qCritical(log) <<
"The plugin is not \"CPlugin\":" << szPath;
304 szMsg =
"Error: Load plugin fail from " + szPath;
305 if(!loader.errorString().isEmpty())
306 szMsg +=
"; Error: " + loader.errorString();
307 qCritical(log) << szMsg.toStdString().c_str();
315 m_Plugins.insert(p->
Id(), p);
318 bool bRet = QMetaObject::invokeMethod(
321 Qt::DirectConnection,
322 Q_RETURN_ARG(
int, val));
325 qCritical(log) <<
"The plugin" << p->
Name()
326 <<
"initial translator fail" << bRet << val;
330 + tr(
"Version:") +
" " + p->
Version() +
" \n"
333 m_szDetails += p->
Details() +
"\n";
343 auto it = m_Plugins.find(
id);
344 if(m_Plugins.end() != it)
347 qDebug(log) <<
"CreateOperate id:" << id;
348 auto plugin = it.value();
351 bRet = QMetaObject::invokeMethod(
354 Qt::DirectConnection,
359 qCritical(log) <<
"Create COperate fail.";
370 qDebug(log) << Q_FUNC_INFO;
375 bool bRet = QMetaObject::invokeMethod(
378 Qt::DirectConnection,
379 Q_RETURN_ARG(
CPlugin*, pPlugin));
381 if(bRet && pPlugin) {
384 bRet = QMetaObject::invokeMethod(
387 Qt::DirectConnection,
388 Q_RETURN_ARG(
int, nRet),
392 qCritical(log) <<
"Call pPlugin->DeleteOperate(p) fail";
397 qCritical(log) <<
"Get CManager fail.";
404 if(szFile.isEmpty())
return nullptr;
405 qDebug(log) <<
"Load operate configure file:"<< szFile;
406 if(m_pParameterPlugin->GetGlobalParameters()->GetSaveSettingsType()
407 == CParameterGlobal::SaveSettingsType::Database) {
408 QByteArray content = m_pDatabaseFile->
Load(szFile);
409 if(!content.isEmpty()) {
411 if(!f.open(QFile::WriteOnly | QFile::Text))
return nullptr;
412 f.write(content.data(), content.length());
417 QSettings set(szFile, QSettings::IniFormat);
418 m_FileVersion = set.value(
"Manage/FileVersion", m_FileVersion).toInt();
419 QString
id = set.value(
"Plugin/ID").toString();
420 QString protocol = set.value(
"Plugin/Protocol").toString();
421 QString name = set.value(
"Plugin/Name").toString();
422 qDebug(log) <<
"LoadOperate protocol:" << protocol
423 <<
"name:" << name <<
"id:" << id;
428 bool bRet = QMetaObject::invokeMethod(
431 Qt::DirectConnection,
432 Q_RETURN_ARG(
int, nRet),
433 Q_ARG(QString, szFile));
435 qCritical(log) <<
"Call pOperate->Load(szFile) fail.";
439 qCritical(log) <<
"Load parameter fail" << nRet;
443 pOperate->SetSettingsFile(szFile);
446 qCritical(log) <<
"Don't create Operate:" << name << protocol <<
id << szFile;
453 if(!pOperate)
return -1;
455 QString szFile = pOperate->GetSettingsFile();
457 szFile = RabbitCommon::CDir::Instance()->GetDirUserData()
462 QSettings set(szFile, QSettings::IniFormat);
464 bool bRet = QMetaObject::invokeMethod(
467 Qt::DirectConnection,
468 Q_RETURN_ARG(
CPlugin*, pPlugin));
469 if(!bRet || !pPlugin)
471 qCritical(log) <<
"Get plugin client fail";
475 set.setValue(
"Manage/FileVersion", m_FileVersion);
476 set.setValue(
"Plugin/ID", pPlugin->
Id());
477 set.setValue(
"Plugin/Protocol", pPlugin->
Protocol());
478 set.setValue(
"Plugin/Name", pPlugin->
Name());
481 bRet = QMetaObject::invokeMethod(
484 Qt::DirectConnection,
485 Q_RETURN_ARG(
int, nRet),
486 Q_ARG(QString, szFile));
488 qCritical(log) <<
"Call pOperate->Save(szFile) fail.";
492 qCritical(log) <<
"Save parameter fail" << nRet;
496 if(m_pParameterPlugin->GetGlobalParameters()->GetSaveSettingsType()
497 == CParameterGlobal::SaveSettingsType::Database) {
498 return m_pDatabaseFile->
Save(szFile) ? 0 : -1;
506 if(!m_pParameterPlugin) {
507 qCritical(log) <<
"The m_pParameter is nullptr";
508 Q_ASSERT_X(m_pParameterPlugin,
"CManager",
"The m_pParameter is nullptr");
514 s = m_szSettingsFile;
515 return m_pParameterPlugin->
Load(s);
520 if(!m_pParameterPlugin) {
521 qCritical(log) <<
"The m_pParameter is nullptr";
522 Q_ASSERT_X(m_pParameterPlugin,
"CManager",
"The m_pParameter is nullptr");
528 s = m_szSettingsFile;
529 return m_pParameterPlugin->
Save(s);
534 if(m_pParameterPlugin)
535 return m_pParameterPlugin->GetGlobalParameters();
541 QList<QWidget*> lstWidget;
546 lstWidget.push_back(pManagePlugins);
552 lstWidget.push_back(pClient);
559 lstWidget.push_back(pDatabase);
562#if defined(HAVE_QTERMWIDGET)
565 pTermina->
SetParameter(&m_pParameterPlugin->m_Terminal);
566 pTermina->setWindowTitle(tr(
"Terminal"));
567 lstWidget.push_back(pTermina);
572 pRecord->SetParameter(&m_pParameterPlugin->m_Record);
573 lstWidget.push_back(pRecord);
576 CFrmMediaDevices* pMediaDevices =
new CFrmMediaDevices(parent);
578 pMediaDevices->SetParameter(&m_pParameterPlugin->m_MediaDevices.m_Para);
579 lstWidget.push_back(pMediaDevices);
583 foreach(
auto plugin, m_Plugins) {
584 if(!plugin)
continue;
585 QWidget* pSettings =
nullptr;
586 bool bRet = QMetaObject::invokeMethod(
589 Qt::DirectConnection,
590 Q_RETURN_ARG(QWidget*, pSettings),
591 Q_ARG(QWidget*, parent));
593 qCritical(log) <<
"Call CPlugin::GetSettingsWidget() fail.";
596 if(!pSettings)
continue;
597 lstWidget.push_back(pSettings);
607 QMap<QString, CPlugin*>::iterator it;
608 for(it = m_Plugins.begin(); it != m_Plugins.end(); it++)
610 nRet = handle->
onProcess(it.key(), it.value());
621 QMap<QString, CPlugin*>::iterator it;
622 for(it = m_Plugins.begin(); it != m_Plugins.end(); it++)
624 nRet = cb(it.key(), it.value());
632const QString CManager::Details()
const
636 szDetail += COperateTerminal::Details();
640 szDetail += channel.GetDetails();
643 szDetail +=
"- QtKeyChain\n" +
644 QString(
" - ") + tr(
"Version:")
645 +
" 0x" + QString::number(QTKEYCHAIN_VERSION, 16) +
"\n";
648 if(!szDetail.isEmpty()) {
649 szDetail =
"## " + tr(
"Dependency libraries:") +
"\n" + szDetail;
651 szDetail += m_szDetails;
655void CManager::slotCaptureAllKeyboard()
657 Q_ASSERT(m_pParameterPlugin);
658 if(m_pParameterPlugin->GetCaptureAllKeyboard()) {
660 m_pHook = CHook::GetHook(m_pParameterPlugin,
this);
662 m_pHook->RegisterKeyboard();
665 m_pHook->UnRegisterKeyboard();
666 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
virtual bool OpenDatabase(CParameterDatabase *pPara=nullptr)
OpenDatabase
virtual int SetParameter(CParameter *pParameter) override
[override functions]
virtual int onProcess(const QString &id, CPlugin *pPlugin)=0
Process plugins
virtual QList< QWidget * > GetSettingsWidgets(QWidget *parent)
得到设置参数窗口
virtual int EnumPlugins(Handle *handle)
Enum plugins
virtual COperate * CreateOperate(const QString &id)
新建 COperate 指针,所有者是调用者。 当不在使用时,调用者必调用 DeteleOperate() 须释放指针。 调用者必须连接信号 COperate::sigFinished 。 释放指针 (...
int LoadPlugin(const QString &szPath)
LoadPlugin
virtual COperate * LoadOperate(const QString &szFile)
从文件中新建 COperate 指针,所有者是调用者。 当不再使用时,调用者必须负责调用 DeleteOperate() 删除此指针。 调用者必须连接信号 COperate::sigFinished 。...
virtual int DeleteOperate(COperate *p)
Delete COperate
virtual int SaveOperate(COperate *pOperate)
保存连接参数到文件
int AppendPlugin(CPlugin *plugin)
Append Plugin
virtual int SaveSettings(const QString szFile=QString())
保存客户端参数到文件
CParameterGlobal * GetGlobalParameters()
Get Global Parameters
void sigNewOperate(COperate *pOperate, bool bOpenSettingsDialog)
当在插件中新建操作时,触发此信号
virtual int LoadSettings(const QString szFile=QString())
从文件中加载客户端参数
virtual const QString Id()
Identity
virtual int SetParameter(CParameter *pParameter) override
[override functions]
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)
当在插件中新建操作时,触发此信号
virtual const QString Details() const
显示更多细节。 例如: 在关于对话框或日志中显示。 包括插件的依赖库的版本信息和描述
virtual const QString Name() const =0
插件名,这个名一定要与工程名(${PROJECT_NAME})相同。 翻译文件(${PROJECT_NAME}_*.ts))名与其相关。
virtual const QString DisplayName() const
在界面上显示的名称
virtual const QString Protocol() const =0
协议
virtual const QString Id() const
标识。默认: Type() + ":" + Protocol() + ":" + Name()
virtual const QString Description() const =0
描述