3#include <QPluginLoader>
9#include <QLoggingCategory>
14#include "RabbitCommonDir.h"
15#include "RabbitCommonTools.h"
16#include "FrmParameterClient.h"
19#include "ParameterRecordUI.h"
21static Q_LOGGING_CATEGORY(log,
"Client")
23CClient::
CClient(QObject *parent, QString szFile) : QObject(parent),
31 qApp->installEventFilter(
this);
33 m_Translator = RabbitCommon::CTools::Instance()->InstallTranslator(
34 "Client", RabbitCommon::CTools::TranslationType::Library);
36 CChannel::InitTranslation();
37 m_szSettingsFile = szFile;
39 if(m_pParameterClient) {
40 LoadSettings(m_szSettingsFile);
41 check = connect(m_pParameterClient, SIGNAL(sigHookKeyboardChanged()),
42 this, SLOT(slotHookKeyboardChanged()));
44 slotHookKeyboardChanged();
46 qCritical(log) <<
"new CParameterClient() fail";
47 Q_ASSERT(m_pParameterClient);
55 qDebug(log) <<
"CClient::~CClient()";
57 if(m_pParameterClient)
58 delete m_pParameterClient;
60 qApp->installEventFilter(
nullptr);
63 RabbitCommon::CTools::Instance()->RemoveTranslator(m_Translator);
65 CChannel::RemoveTranslation();
72int CClient::LoadPlugins()
75 foreach (QObject *plugin, QPluginLoader::staticInstances())
80 if(m_Plugins.find(p->
Id()) == m_Plugins.end())
82 qInfo(log) <<
"Success: Load plugin" << p->
Name();
86 qWarning(log) <<
"The plugin" << p->
Name() <<
" is exist.";
90 QString szPath = RabbitCommon::CDir::Instance()->GetDirPlugins();
91#if !defined (Q_OS_ANDROID)
92 szPath = szPath + QDir::separator() +
"Client";
96#if defined (Q_OS_WINDOWS) || defined(Q_OS_WIN)
97 filters <<
"*PluginClient*.dll";
99 filters <<
"*PluginClient*.so";
101 nRet = FindPlugins(szPath, filters);
102 if(!m_szDetails.isEmpty())
103 m_szDetails = tr(
"### Plugins") +
"\n" + m_szDetails;
105 qDebug(log) << (
"Client details:\n" + Details()).toStdString().c_str();
109int CClient::FindPlugins(QDir dir, QStringList filters)
112 if(filters.isEmpty())
114#if defined (Q_OS_WINDOWS) || defined(Q_OS_WIN)
115 filters <<
"*PluginClient*.dll";
117 filters <<
"*PluginClient*.so";
121 QString szCurrentPath = QDir::currentPath();
122 QStringList files = dir.entryList(filters, QDir::Files | QDir::NoDotAndDotDot);
128 QDir::setCurrent(QDir::cleanPath(dir.absolutePath()));
139 foreach (fileName, files) {
140 QString szPlugins = dir.absoluteFilePath(fileName);
141 QPluginLoader loader(szPlugins);
142 QObject *plugin = loader.instance();
147 if(m_Plugins.find(p->
Id()) == m_Plugins.end())
149 qInfo(log) <<
"Success: Load plugin"
150 << p->
Name() <<
"from" << szPlugins;
154 qWarning(log) <<
"The plugin [" << p->
Name() <<
"] is exist.";
158 szMsg =
"Error: Load plugin fail from " + szPlugins;
159 if(!loader.errorString().isEmpty())
160 szMsg +=
"; Error: " + loader.errorString();
161 qCritical(log) << szMsg.toStdString().c_str();
165 foreach (fileName, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
166 QDir pluginDir = dir;
167 if(pluginDir.cd(fileName))
168 FindPlugins(pluginDir, filters);
171 QDir::setCurrent(szCurrentPath);
179 m_Plugins.insert(p->
Id(), p);
182 bool bRet = QMetaObject::invokeMethod(
185 Qt::DirectConnection,
186 Q_RETURN_ARG(
int, val));
189 qCritical(log) <<
"The plugin" << p->
Name()
190 <<
"initial translator fail" << bRet << val;
194 + tr(
"Version:") +
" " + p->
Version() +
" \n"
197 m_szDetails += p->
Details() +
"\n";
206 auto it = m_Plugins.find(
id);
207 if(m_Plugins.end() != it)
210 qDebug(log) <<
"CreateConnecter id:" << id;
211 auto plugin = it.value();
214 bRet = QMetaObject::invokeMethod(
217 Qt::DirectConnection,
222 qCritical(log) <<
"Create CConnecter fail.";
233 qDebug(log) << Q_FUNC_INFO;
238 bool bRet = QMetaObject::invokeMethod(
241 Qt::DirectConnection,
244 if(bRet && pPluginClient) {
247 bRet = QMetaObject::invokeMethod(
250 Qt::DirectConnection,
251 Q_RETURN_ARG(
int, nRet),
255 qCritical(log) <<
"Call pPluginClient->DeleteConnecter(p) fail";
260 qCritical(log) <<
"Get CClient fail.";
267 if(szFile.isEmpty())
return nullptr;
269 QSettings set(szFile, QSettings::IniFormat);
270 m_FileVersion = set.value(
"Manage/FileVersion", m_FileVersion).toInt();
271 QString
id = set.value(
"Plugin/ID").toString();
272 QString protocol = set.value(
"Plugin/Protocol").toString();
273 QString name = set.value(
"Plugin/Name").toString();
275 qDebug(log) <<
"LoadConnecter protocol:" << protocol
276 <<
"name:" << name <<
"id:" << id;
281 bool bRet = QMetaObject::invokeMethod(
284 Qt::DirectConnection,
285 Q_RETURN_ARG(
int, nRet),
286 Q_ARG(QString, szFile));
288 qCritical(log) <<
"Call pConnecter->Load(szFile) fail.";
292 qCritical(log) <<
"Load parameter fail" << nRet;
296 pConnecter->SetSettingsFile(szFile);
299 qCritical(log) <<
"Don't create connecter:" << protocol;
306 if(!pConnecter)
return -1;
308 QString szFile = pConnecter->GetSettingsFile();
310 szFile = RabbitCommon::CDir::Instance()->GetDirUserData()
315 QSettings set(szFile, QSettings::IniFormat);
318 bool bRet = QMetaObject::invokeMethod(
321 Qt::DirectConnection,
323 if(!bRet || !pPluginClient)
325 qCritical(log) <<
"Get plugin client fail";
327 Q_ASSERT(pPluginClient);
329 set.setValue(
"Manage/FileVersion", m_FileVersion);
330 set.setValue(
"Plugin/ID", pPluginClient->
Id());
331 set.setValue(
"Plugin/Protocol", pPluginClient->
Protocol());
332 set.setValue(
"Plugin/Name", pPluginClient->
Name());
335 bRet = QMetaObject::invokeMethod(
338 Qt::DirectConnection,
339 Q_RETURN_ARG(
int, nRet),
340 Q_ARG(QString, szFile));
342 qCritical(log) <<
"Call pConnecter->Save(szFile) fail.";
346 qCritical(log) <<
"Save parameter fail" << nRet;
354 if(!m_pParameterClient) {
355 qCritical(log) <<
"The m_pParameterClient is nullptr";
356 Q_ASSERT_X(m_pParameterClient,
"CClient",
"The m_pParameterClient is nullptr");
362 s = m_szSettingsFile;
363 return m_pParameterClient->CParameter::Load(s);
368 if(!m_pParameterClient) {
369 qCritical(log) <<
"The m_pParameterClient is nullptr";
370 Q_ASSERT_X(m_pParameterClient,
"CClient",
"The m_pParameterClient is nullptr");
376 s = m_szSettingsFile;
377 return m_pParameterClient->CParameter::Save(s);
382 QList<QWidget*> lstWidget;
387 lstWidget.push_back(pClient);
392 pRecord->SetParameter(&m_pParameterClient->m_Record);
393 lstWidget.push_back(pRecord);
402 QMap<QString, CPluginClient*>::iterator it;
403 for(it = m_Plugins.begin(); it != m_Plugins.end(); it++)
405 nRet = handle->
onProcess(it.key(), it.value());
416 QMap<QString, CPluginClient*>::iterator it;
417 for(it = m_Plugins.begin(); it != m_Plugins.end(); it++)
419 nRet = cb(it.key(), it.value());
427const QString CClient::Details()
const
432void CClient::slotHookKeyboardChanged()
434 if(m_pParameterClient->GetHookKeyboard())
436 if(!RabbitCommon::CTools::Instance()->HasAdministratorPrivilege()
437 && m_pParameterClient->GetHookShowAdministratorPrivilege())
441 QMessageBox::Warning, tr(
"Warning"),
442 tr(
"The programe is not administrator privilege.\n"
443 "Don't disable system shortcuts(eg: Ctrl+Alt+del).\n"
444 "Restart program by administrator?"),
445 QMessageBox::Yes | QMessageBox::No);
446 msg.setCheckBox(
new QCheckBox(tr(
"Always shown"), &msg));
447 msg.checkBox()->setCheckable(
true);
448 msg.checkBox()->setChecked(
449 m_pParameterClient->GetHookShowAdministratorPrivilege());
451 if(QMessageBox::Yes == nRet) {
452 RabbitCommon::CTools::Instance()->StartWithAdministratorPrivilege(
true);
454 if(m_pParameterClient->GetHookShowAdministratorPrivilege()
455 != msg.checkBox()->isChecked()) {
456 m_pParameterClient->SetHookShowAdministratorPrivilege(
457 msg.checkBox()->isChecked());
461 m_Hook = QSharedPointer<CHook>(CHook::GetHook());
468bool CClient::eventFilter(QObject *watched, QEvent *event)
470 if(QEvent::KeyPress == event->type() || QEvent::KeyRelease == event->type())
473 bool bProcess =
false;
474 QKeyEvent *keyEvent =
static_cast<QKeyEvent *
>(event);
475 int key = keyEvent->key();
479 key = Qt::Key_Super_L;
481#if defined(Q_OS_MACOS)
482 key = Qt::Key_Control;
495 switch(event->type()) {
496 case QEvent::KeyPress:
498 CFrmViewer* focus = qobject_cast<CFrmViewer*>(QApplication::focusWidget());
500 emit focus->sigKeyPressEvent(keyEvent);
504 case QEvent::KeyRelease:
506 CFrmViewer* focus = qobject_cast<CFrmViewer*>(QApplication::focusWidget());
508 emit focus->sigKeyReleaseEvent(keyEvent);
517 return QObject::eventFilter(watched, event);
virtual int onProcess(const QString &id, CPluginClient *pPlug)=0
Process plugins
virtual CConnecter * LoadConnecter(const QString &szFile)
从文件中新建 CConnecter 指针,所有者是调用者。 当不再使用时,调用者必须负责调用 DeleteConnecter() 删除此指针。 调用者必须连接信号 CConnecter::sigDisc...
virtual CConnecter * CreateConnecter(const QString &id)
新建 CConnecter 指针,所有者是调用者。 当不在使用时,调用者必调用 DeteleConnecter() 须释放指针。 调用者必须连接信号 CConnecter::sigDisconnecte...
virtual int LoadSettings(const QString szFile=QString())
从文件中加载客户端参数
virtual int DeleteConnecter(CConnecter *p)
Delete CConnecter
virtual QList< QWidget * > GetSettingsWidgets(QWidget *parent)
得到设置参数窗口
virtual int SaveConnecter(CConnecter *pConnecter)
保存连接参数到文件
virtual int SaveSettings(const QString szFile=QString())
保存客户端参数到文件
virtual int EnumPlugins(Handle *handle)
Enum plugins
virtual const QString Id()
Identity
virtual int SetParameter(CParameter *pParameter) override
设置参数,并初始化界面
用于显示从 CConnectDesktop 输出的图像,和向 CConnectDesktop 发送键盘、鼠标事件。
客户端库 (CClient) 参数。仅在客户端库 (CClient) 和插件中使用。
客户端插件接口。用于建立 CConnecter 实例,它由协议插件实现。
virtual const QString Details() const
显示更多细节。 例如: 在关于对话框或日志中显示。 包括插件的依赖库的版本信息和描述
virtual const QString Id() const
标识。默认: Protocol() + ":" + Name()
virtual const QString DisplayName() const
在界面上显示的名称
virtual const QString Description() const =0
描述
virtual const QString Version() const =0
Version
virtual const QString Name() const =0
插件名,这个名一定要与工程名(${PROJECT_NAME})相同。 翻译文件(${PROJECT_NAME}_*.ts))名与其相关。
virtual const QString Protocol() const =0
协议