玉兔远程控制 0.1.0-bate8
载入中...
搜索中...
未找到
FrmQWebEnginePluginManager.cpp
1// Author: Kang Lin <kl222@126.com>
2
3#include <QLoggingCategory>
4#include <QVBoxLayout>
5#include <QHBoxLayout>
6#include <QHeaderView>
7#include <QPushButton>
8#include <QTableView>
9#include <QMessageBox>
10#include <QFileDialog>
11#include <QStandardItemModel>
12#include <QWebEngineProfile>
13#include <QSettings>
14#include <QDir>
15#include <QJsonDocument>
16#include <QJsonObject>
17#include <QJsonArray>
18
19#include "FrmQWebEnginePluginManager.h"
20#include "ParameterWebBrowser.h"
21#include "ui_FrmQWebEnginePluginManager.h"
22
23static Q_LOGGING_CATEGORY(log, "WebBrowser.PluginManager")
24
26 : QWidget(parent)
27 , ui(new Ui::CFrmQWebEnginePluginManagerUI)
28 , m_pPara(nullptr)
29 , m_pModelPlugins(nullptr)
30{
31 ui->setupUi(this);
32 setWindowTitle(tr("QWebEngine Plugin Manager"));
33 setWindowIcon(QIcon::fromTheme("extension"));
34
35 InitializeUI();
36 SetupConnections();
37
38 qDebug(log) << Q_FUNC_INFO << "Plugin manager initialized";
39}
40
41CFrmQWebEnginePluginManager::~CFrmQWebEnginePluginManager()
42{
43 qDebug(log) << Q_FUNC_INFO;
44 delete ui;
45}
46
47void CFrmQWebEnginePluginManager::InitializeUI()
48{
49 // 创建插件列表模型
50 m_pModelPlugins = new QStandardItemModel(this);
51 m_pModelPlugins->setColumnCount(6);
52
53 // 设置表头
54 QStringList headers;
55 headers << tr("Enable") << tr("Name") << tr("Type")
56 << tr("Version") << tr("Path") << tr("Description");
57 m_pModelPlugins->setHorizontalHeaderLabels(headers);
58
59 // 配置表视图
60 ui->tvPlugins->setModel(m_pModelPlugins);
61 ui->tvPlugins->setSelectionMode(QAbstractItemView::SingleSelection);
62 ui->tvPlugins->setSelectionBehavior(QAbstractItemView::SelectRows);
63 ui->tvPlugins->setEditTriggers(QAbstractItemView::NoEditTriggers);
64 ui->tvPlugins->setContextMenuPolicy(Qt::CustomContextMenu);
65
66 // 设置列宽自适应
67 ui->tvPlugins->horizontalHeader()->setStretchLastSection(true);
68 ui->tvPlugins->horizontalHeader()->setSectionResizeMode(
69 ColumnNo::Path, QHeaderView::Stretch);
70
71 // 设置行高
72 ui->tvPlugins->verticalHeader()->setDefaultSectionSize(24);
73
74 // 配置按钮
75 ui->pbEnableAll->setText(tr("Enable All"));
76 ui->pbDisableAll->setText(tr("Disable All"));
77 ui->pbAdd->setText(tr("Add Plugin"));
78 ui->pbRemove->setText(tr("Remove"));
79 ui->pbDetails->setText(tr("Details"));
80 ui->pbExport->setText(tr("Export"));
81 ui->pbImport->setText(tr("Import"));
82 ui->pbApply->setText(tr("Apply"));
83 ui->pbReset->setText(tr("Reset"));
84
85 qDebug(log) << "UI initialized";
86}
87
88void CFrmQWebEnginePluginManager::SetupConnections()
89{
90 bool check = true;
91
92 // 按钮连接
93 check &= connect(ui->pbEnableAll, &QPushButton::clicked,
94 this, &CFrmQWebEnginePluginManager::on_pbEnableAll_clicked);
95 check &= connect(ui->pbDisableAll, &QPushButton::clicked,
96 this, &CFrmQWebEnginePluginManager::on_pbDisableAll_clicked);
97 check &= connect(ui->pbAdd, &QPushButton::clicked,
98 this, &CFrmQWebEnginePluginManager::on_pbAdd_clicked);
99 check &= connect(ui->pbRemove, &QPushButton::clicked,
100 this, &CFrmQWebEnginePluginManager::on_pbRemove_clicked);
101 check &= connect(ui->pbDetails, &QPushButton::clicked,
102 this, &CFrmQWebEnginePluginManager::on_pbDetails_clicked);
103 check &= connect(ui->pbExport, &QPushButton::clicked,
104 this, &CFrmQWebEnginePluginManager::on_pbExport_clicked);
105 check &= connect(ui->pbImport, &QPushButton::clicked,
106 this, &CFrmQWebEnginePluginManager::on_pbImport_clicked);
107 check &= connect(ui->pbApply, &QPushButton::clicked,
108 this, &CFrmQWebEnginePluginManager::on_pbApply_clicked);
109 check &= connect(ui->pbReset, &QPushButton::clicked,
110 this, &CFrmQWebEnginePluginManager::on_pbReset_clicked);
111
112 // 模型连接
113 check &= connect(m_pModelPlugins, &QStandardItemModel::itemChanged,
114 this, &CFrmQWebEnginePluginManager::slotPluginItemChanged);
115
116 // 表视图连接
117 check &= connect(ui->tvPlugins->selectionModel(), &QItemSelectionModel::selectionChanged,
118 this, &CFrmQWebEnginePluginManager::slotSelectionChanged);
119 check &= connect(ui->tvPlugins, &QTableView::customContextMenuRequested,
120 this, &CFrmQWebEnginePluginManager::slotCustomContextMenu);
121
122 Q_ASSERT(check);
123 qDebug(log) << "Connections setup completed";
124}
125
127{
128 m_pPara = pPara;
129 if(!m_pPara) {
130 qWarning(log) << "Failed to set parameter: pPara is null";
131 return -1;
132 }
133
134 LoadPluginConfiguration();
135 RefreshPluginList();
136
137 return 0;
138}
139
140int CFrmQWebEnginePluginManager::RefreshPluginList()
141{
142 if(!m_pModelPlugins) return -1;
143
144 m_pModelPlugins->removeRows(0, m_pModelPlugins->rowCount());
145
146 qDebug(log) << "Refreshing plugin list";
147
148#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
149 // Qt 6 及以上版本使用现代 QWebEngine API
150 auto profile = QWebEngineProfile::defaultProfile();
151 if(!profile) {
152 qWarning(log) << "Default profile is null";
153 return -1;
154 }
155#endif
156
157 // 扫描插件目录
158 QStringList pluginPaths;
159 pluginPaths << QCoreApplication::libraryPaths();
160
161 for(const auto &path : pluginPaths) {
162 QDir dir(path);
163 if(!dir.exists()) continue;
164
165 QStringList filters;
166#ifdef Q_OS_WIN
167 filters << "*.dll";
168#elif defined(Q_OS_MACOS)
169 filters << "*.dylib" << "*.so";
170#else
171 filters << "*.so";
172#endif
173
174 dir.setNameFilters(filters);
175 QFileInfoList files = dir.entryInfoList();
176
177 for(const auto &fileInfo : files) {
178 if(IsValidPlugin(fileInfo.filePath())) {
179 AddPluginItem(fileInfo.baseName(), fileInfo.filePath(), true);
180 }
181 }
182 }
183
184 qDebug(log) << "Plugin list refreshed, total plugins:" << m_pModelPlugins->rowCount();
185 return 0;
186}
187
188int CFrmQWebEnginePluginManager::AddPluginItem(
189 const QString &pluginName, const QString &pluginPath, bool enabled)
190{
191 if(!m_pModelPlugins) return -1;
192
193 int row = m_pModelPlugins->rowCount();
194 m_pModelPlugins->insertRow(row);
195
196 // 启用状态
197 auto itemEnabled = new QStandardItem();
198 itemEnabled->setCheckable(true);
199 itemEnabled->setCheckState(enabled ? Qt::Checked : Qt::Unchecked);
200 m_pModelPlugins->setItem(row, ColumnNo::Enabled, itemEnabled);
201
202 // 插件名称
203 auto itemName = new QStandardItem(pluginName);
204 itemName->setEditable(false);
205 m_pModelPlugins->setItem(row, ColumnNo::Name, itemName);
206
207 // 插件类型
208 auto itemType = new QStandardItem("Web Plugin");
209 itemType->setEditable(false);
210 m_pModelPlugins->setItem(row, ColumnNo::Type, itemType);
211
212 // 版本信息
213 auto itemVersion = new QStandardItem("1.0.0");
214 itemVersion->setEditable(false);
215 m_pModelPlugins->setItem(row, ColumnNo::Version, itemVersion);
216
217 // 路径
218 auto itemPath = new QStandardItem(pluginPath);
219 itemPath->setEditable(false);
220 m_pModelPlugins->setItem(row, ColumnNo::Path, itemPath);
221
222 // 描述
223 auto itemDesc = new QStandardItem(GetPluginInfo(pluginPath));
224 itemDesc->setEditable(false);
225 m_pModelPlugins->setItem(row, ColumnNo::Description, itemDesc);
226
227 qDebug(log) << "Added plugin:" << pluginName << "at path:" << pluginPath;
228 return 0;
229}
230
231bool CFrmQWebEnginePluginManager::IsValidPlugin(const QString &pluginPath) const
232{
233 QFileInfo fi(pluginPath);
234 if(!fi.exists() || !fi.isFile()) return false;
235
236 // 可添加更多验证逻辑
237 return fi.isReadable();
238}
239
240QString CFrmQWebEnginePluginManager::GetPluginInfo(const QString &pluginPath) const
241{
242 QFileInfo fi(pluginPath);
243 return QString("%1 (%2 bytes)")
244 .arg(fi.fileName())
245 .arg(fi.size());
246}
247
249{
250 return m_pluginConfig;
251}
252
254 const QMap<QString, QVariant> &config)
255{
256 m_pluginConfig = config;
257 return LoadPluginConfiguration();
258}
259
260int CFrmQWebEnginePluginManager::SavePluginConfiguration()
261{
262 QJsonArray pluginsArray;
263
264 for(int i = 0; i < m_pModelPlugins->rowCount(); i++) {
265 QJsonObject pluginObj;
266
267 auto itemName = m_pModelPlugins->item(i, ColumnNo::Name);
268 auto itemPath = m_pModelPlugins->item(i, ColumnNo::Path);
269 auto itemEnabled = m_pModelPlugins->item(i, ColumnNo::Enabled);
270
271 if(itemName && itemPath && itemEnabled) {
272 pluginObj["name"] = itemName->text();
273 pluginObj["path"] = itemPath->text();
274 pluginObj["enabled"] = (itemEnabled->checkState() == Qt::Checked);
275 pluginsArray.append(pluginObj);
276 }
277 }
278
279 QJsonObject configObj;
280 configObj["plugins"] = pluginsArray;
281 configObj["version"] = "1.0";
282
283 m_pluginConfig["config"] = QJsonDocument(configObj).toJson();
284
285 qDebug(log) << "Plugin configuration saved";
286 return 0;
287}
288
289int CFrmQWebEnginePluginManager::LoadPluginConfiguration()
290{
291 // 从配置中恢复插件状态
292 qDebug(log) << "Plugin configuration loaded";
293 return 0;
294}
295
296void CFrmQWebEnginePluginManager::on_pbEnableAll_clicked()
297{
298 qDebug(log) << Q_FUNC_INFO;
299 for(int i = 0; i < m_pModelPlugins->rowCount(); i++) {
300 auto item = m_pModelPlugins->item(i, ColumnNo::Enabled);
301 if(item) {
302 item->setCheckState(Qt::Checked);
303 }
304 }
305 QMessageBox::information(this, tr("Info"), tr("All plugins enabled"));
306}
307
308void CFrmQWebEnginePluginManager::on_pbDisableAll_clicked()
309{
310 qDebug(log) << Q_FUNC_INFO;
311 for(int i = 0; i < m_pModelPlugins->rowCount(); i++) {
312 auto item = m_pModelPlugins->item(i, ColumnNo::Enabled);
313 if(item) {
314 item->setCheckState(Qt::Unchecked);
315 }
316 }
317 QMessageBox::information(this, tr("Info"), tr("All plugins disabled"));
318}
319
320void CFrmQWebEnginePluginManager::on_pbAdd_clicked()
321{
322 qDebug(log) << Q_FUNC_INFO;
323 QString filter = tr("Plugin Files (*.dll *.so *.dylib);;All Files (*)");
324 QString filePath = QFileDialog::getOpenFileName(this, tr("Select Plugin"), "", filter);
325
326 if(!filePath.isEmpty() && IsValidPlugin(filePath)) {
327 QFileInfo fi(filePath);
328 AddPluginItem(fi.baseName(), filePath, true);
329 }
330}
331
332void CFrmQWebEnginePluginManager::on_pbRemove_clicked()
333{
334 qDebug(log) << Q_FUNC_INFO;
335 auto indexes = ui->tvPlugins->selectionModel()->selectedRows();
336 if(indexes.isEmpty()) {
337 QMessageBox::warning(this, tr("Warning"), tr("Please select a plugin to remove"));
338 return;
339 }
340
341 int row = indexes.at(0).row();
342 m_pModelPlugins->removeRow(row);
343}
344
345void CFrmQWebEnginePluginManager::on_pbDetails_clicked()
346{
347 qDebug(log) << Q_FUNC_INFO;
348 auto indexes = ui->tvPlugins->selectionModel()->selectedRows();
349 if(indexes.isEmpty()) return;
350
351 int row = indexes.at(0).row();
352 QString name = m_pModelPlugins->item(row, ColumnNo::Name)->text();
353 QString path = m_pModelPlugins->item(row, ColumnNo::Path)->text();
354 QString version = m_pModelPlugins->item(row, ColumnNo::Version)->text();
355 QString description = m_pModelPlugins->item(row, ColumnNo::Description)->text();
356
357 QString details = QString("Plugin Details:\n\nName: %1\nPath: %2\nVersion: %3\n\nInfo: %4")
358 .arg(name, path, version, description);
359
360 QMessageBox::information(this, tr("Plugin Details"), details);
361}
362
363void CFrmQWebEnginePluginManager::on_pbExport_clicked()
364{
365 qDebug(log) << Q_FUNC_INFO;
366 QString filePath = QFileDialog::getSaveFileName(this,
367 tr("Export Plugin Configuration"), "",
368 tr("JSON Files (*.json);;All Files (*)"));
369
370 if(!filePath.isEmpty()) {
371 SavePluginConfiguration();
372 // TODO: 实现导出逻辑
373 QMessageBox::information(this, tr("Success"), tr("Configuration exported successfully"));
374 }
375}
376
377void CFrmQWebEnginePluginManager::on_pbImport_clicked()
378{
379 qDebug(log) << Q_FUNC_INFO;
380 QString filePath = QFileDialog::getOpenFileName(this,
381 tr("Import Plugin Configuration"), "",
382 tr("JSON Files (*.json);;All Files (*)"));
383
384 if(!filePath.isEmpty()) {
385 // TODO: 实现导入逻辑
386 QMessageBox::information(this, tr("Success"), tr("Configuration imported successfully"));
387 }
388}
389
390void CFrmQWebEnginePluginManager::on_pbApply_clicked()
391{
392 qDebug(log) << Q_FUNC_INFO;
393 SavePluginConfiguration();
394 QMessageBox::information(this, tr("Success"), tr("Configuration applied"));
395}
396
397void CFrmQWebEnginePluginManager::on_pbReset_clicked()
398{
399 qDebug(log) << Q_FUNC_INFO;
400 LoadPluginConfiguration();
401 RefreshPluginList();
402 QMessageBox::information(this, tr("Success"), tr("Configuration reset"));
403}
404
405void CFrmQWebEnginePluginManager::slotPluginItemChanged(QStandardItem *item)
406{
407 if(!item) return;
408 qDebug(log) << "Plugin item changed:" << item->text();
409}
410
411void CFrmQWebEnginePluginManager::slotSelectionChanged()
412{
413 auto indexes = ui->tvPlugins->selectionModel()->selectedRows();
414 bool hasSelection = !indexes.isEmpty();
415
416 ui->pbRemove->setEnabled(hasSelection);
417 ui->pbDetails->setEnabled(hasSelection);
418}
419
420void CFrmQWebEnginePluginManager::slotCustomContextMenu(const QPoint &pos)
421{
422 qDebug(log) << Q_FUNC_INFO;
423 // TODO: 实现右键菜单
424}
CFrmQWebEnginePluginManager - QWebEngine 插件管理窗体
QMap< QString, QVariant > GetPluginConfiguration() const
获取插件管理器配置
int SetPluginConfiguration(const QMap< QString, QVariant > &config)
设置插件管理器配置
int SetParameter(CParameterWebBrowser *pPara)
设置 WebEngine 参数