玉兔远程控制 0.1.0-bate6
载入中...
搜索中...
未找到
FrmBookmark.cpp
1// Author: Kang Lin <kl222@126.com>
2
3#include <QMenu>
4#include <QLabel>
5#include <QPushButton>
6#include <QVBoxLayout>
7#include <QHBoxLayout>
8#include <QHeaderView>
9#include <QMessageBox>
10#include <QInputDialog>
11#include <QFileDialog>
12#include <QLoggingCategory>
13
14#include "RabbitCommonDir.h"
15#include "FrmBookmark.h"
16#include "ui_FrmBookmark.h"
17
18static Q_LOGGING_CATEGORY(log, "WebBrowser.Bookmark")
19CFrmBookmark::CFrmBookmark(CParameterWebBrowser *pPara, QWidget *parent)
20 : QWidget(parent)
21 , ui(new Ui::CFrmBookmark)
22 , m_pDatabase(CBookmarkDatabase::Instance())
23 , m_pPara(pPara)
24 , m_pTreeView(nullptr)
25 , m_pSearchEdit(nullptr)
26 , m_pToolBar(nullptr)
27 , m_pModel(new QStandardItemModel(this))
28{
29 ui->setupUi(this);
30 setWindowTitle(tr("Bookmark"));
31 setAcceptDrops(true);
32
33 setupUI();
34 loadBookmarks();
35
36 if(m_pPara)
37 resize(m_pPara->GetWindowSize());
38}
39
40CFrmBookmark::~CFrmBookmark()
41{
42 delete ui;
43}
44
45void CFrmBookmark::setupUI()
46{
47 bool check = false;
48 QVBoxLayout *pMainLayout = new QVBoxLayout(this);
49 if(!pMainLayout) return;
50
51 // 工具栏
52 setupToolBar();
53 pMainLayout->addWidget(m_pToolBar);
54
55 // 搜索框
56 QHBoxLayout *pSearchLayout = new QHBoxLayout;
57 if(pSearchLayout) {
58 pSearchLayout->addWidget(new QLabel(tr("Search:")));
59
60 m_pSearchEdit = new QLineEdit(this);
61 if(m_pSearchEdit) {
62 m_pSearchEdit->setPlaceholderText(tr("Input keyword to search boolmark ......"));
63 m_pSearchEdit->setClearButtonEnabled(true);
64 check = connect(m_pSearchEdit, &QLineEdit::textChanged,
65 this, &CFrmBookmark::onSearchTextChanged);
66 Q_ASSERT(check);
67 pSearchLayout->addWidget(m_pSearchEdit);
68 }
69 pMainLayout->addLayout(pSearchLayout);
70 }
71
72 // 书签树
73 setupTreeView();
74 pMainLayout->addWidget(m_pTreeView);
75
76 // 按钮
77 QHBoxLayout *pButtonLayout = new QHBoxLayout;
78 if(pButtonLayout) {
79 pButtonLayout->addStretch();
80
81 QPushButton *closeButton = new QPushButton(tr("Close"), this);
82 connect(closeButton, &QPushButton::clicked, this, &CFrmBookmark::close);
83 pButtonLayout->addWidget(closeButton);
84
85 pMainLayout->addLayout(pButtonLayout);
86 }
87 setLayout(pMainLayout);
88}
89
90void CFrmBookmark::setupToolBar()
91{
92 bool check = false;
93 m_pToolBar = new QToolBar(this);
94 if(!m_pToolBar) return;
95
96 // 添加书签
97 QAction *addAction = m_pToolBar->addAction(QIcon::fromTheme("add"), tr("Add bookmark"));
98 if(addAction) {
99 check = connect(addAction, &QAction::triggered, this, &CFrmBookmark::onAddBookmark);
100 Q_ASSERT(check);
101 }
102
103 // 添加文件夹
104 QAction *addFolderAction = m_pToolBar->addAction(QIcon::fromTheme("folder-new"), tr("Add folder"));
105 if(addFolderAction) {
106 check = connect(addFolderAction, &QAction::triggered, this, &CFrmBookmark::onAddFolder);
107 Q_ASSERT(check);
108 }
109
110 m_pToolBar->addSeparator();
111
112 // 编辑
113 QAction *editAction = m_pToolBar->addAction(QIcon::fromTheme("edit"), tr("Edit"));
114 if(editAction) {
115 check = connect(editAction, &QAction::triggered, this, &CFrmBookmark::onEditBookmark);
116 Q_ASSERT(check);
117 }
118
119 // 删除
120 QAction *pDeleteAction = m_pToolBar->addAction(QIcon::fromTheme("edit-delete"), tr("Delete"));
121 if(pDeleteAction) {
122 check = connect(pDeleteAction, &QAction::triggered, this, &CFrmBookmark::onDeleteBookmark);
123 Q_ASSERT(check);
124 }
125
126 // 设为最爱
127 QAction *favoriteAction = m_pToolBar->addAction(QIcon::fromTheme("favorites"), tr("Favorite"));
128 if(favoriteAction) {
129 check = connect(favoriteAction, &QAction::triggered, this, &CFrmBookmark::onSetFavorite);
130 Q_ASSERT(check);
131 }
132
133 m_pToolBar->addSeparator();
134
135 // 导入
136 QAction *importAction = m_pToolBar->addAction(QIcon::fromTheme("import"), tr("Import"));
137 if(importAction) {
138 check = connect(importAction, &QAction::triggered, this, &CFrmBookmark::onImportBookmarks);
139 Q_ASSERT(check);
140 }
141
142 // 导出
143 QAction *exportAction = m_pToolBar->addAction(QIcon::fromTheme("export"), tr("Export"));
144 if(exportAction) {
145 check = connect(exportAction, &QAction::triggered, this, &CFrmBookmark::onExportBookmarks);
146 Q_ASSERT(check);
147 }
148
149 m_pToolBar->addSeparator();
150
151 // 刷新
152 QAction *refreshAction = m_pToolBar->addAction(QIcon::fromTheme("view-refresh"), tr("Refresh"));
153 if(refreshAction) {
154 check = connect(refreshAction, &QAction::triggered, this, &CFrmBookmark::refresh);
155 Q_ASSERT(check);
156 }
157}
158
159void CFrmBookmark::setupTreeView()
160{
161 bool check = false;
162 m_pTreeView = new QTreeView(this);
163 if(!m_pTreeView) return;
164 m_pTreeView->setHeaderHidden(true);
165 m_pTreeView->setContextMenuPolicy(Qt::CustomContextMenu);
166 m_pTreeView->setEditTriggers(QAbstractItemView::NoEditTriggers);
167
168 // 连接信号
169 check = connect(m_pTreeView, &QTreeView::doubleClicked,
170 this, &CFrmBookmark::onTreeViewDoubleClicked);
171 Q_ASSERT(check);
172 check = connect(m_pTreeView, &QTreeView::customContextMenuRequested,
173 this, &CFrmBookmark::onCustomContextMenu);
174 Q_ASSERT(check);
175
176 if(m_pModel) {
177 m_pTreeView->setModel(m_pModel);
178 // 设置列
179 m_pModel->setColumnCount(1);
180 }
181 /*
182 if(m_pTreeView->header())
183 m_pTreeView->header()->setStretchLastSection(true); // 最后一列自适应//*/
184}
185
186void CFrmBookmark::loadBookmarks()
187{
188 if(!m_pDatabase || !m_pModel || !m_pTreeView) return;
189 m_pModel->clear();
190 m_folderItems.clear();
191
192 // 设置表头
193 m_pModel->setHorizontalHeaderLabels(QStringList() << tr("Title"));
194
195 // 加载文件夹结构
196 QList<BookmarkItem> folders = m_pDatabase->getAllFolders();
197
198 // 创建根节点
199 QStandardItem *rootItem = m_pModel->invisibleRootItem();
200
201 int nCurrent = m_pPara->GetBookmarkCurrentFolder();
202 QStandardItem* pCurrentItem = nullptr;
203
204 // 先添加顶级文件夹
205 for (const auto &folder : folders) {
206 if (folder.folderId == 0) { // 顶级文件夹
207 QStandardItem *pFolderItem = new QStandardItem(folder.getIcon(), folder.title);
208 if(!pFolderItem) continue;
209 pFolderItem->setData(folder.id, ID);
210 pFolderItem->setData(BookmarkType_Folder, Type);
211 rootItem->appendRow(pFolderItem);
212 m_folderItems[folder.id] = pFolderItem;
213 if(folder.id == nCurrent)
214 pCurrentItem = pFolderItem;
215 continue;
216 }
217
218 auto it = m_folderItems.find(folder.folderId);
219 if(m_folderItems.end() == it) {
220 qWarning(log) << "The parent of folder is not find:" << folder.folderId;
221 continue;
222 }
223 QStandardItem *pFolderItem = new QStandardItem(folder.getIcon(), folder.title);
224 if(!pFolderItem) continue;
225 pFolderItem->setData(folder.id, ID);
226 pFolderItem->setData(BookmarkType_Folder, Type);
227 (*it)->appendRow(pFolderItem);
228 m_folderItems[folder.id] = pFolderItem;
229 if(folder.id == nCurrent)
230 pCurrentItem = pFolderItem;
231 }
232
233 // Set current index
234 if(pCurrentItem) {
235 auto index = m_pModel->indexFromItem(pCurrentItem);
236 m_pTreeView->setCurrentIndex(index);
237 }
238
239 // 添加书签到对应的文件夹
240 QList<BookmarkItem> bookmarks = m_pDatabase->getAllBookmarks(-1);
241 for (const auto &bookmark : bookmarks) {
242 QStandardItem *pParentItem = nullptr;
243
244 if (bookmark.folderId > 0 && m_folderItems.contains(bookmark.folderId)) {
245 pParentItem = m_folderItems[bookmark.folderId];
246 } else {
247 pParentItem = rootItem;
248 }
249
250 QStandardItem *bookmarkItem = new QStandardItem(bookmark.getIcon(), bookmark.title);
251 bookmarkItem->setData(bookmark.id, ID);
252 bookmarkItem->setData(BookmarkType_Bookmark, Type);
253 bookmarkItem->setData(bookmark.url, Url);
254
255 if(pParentItem)
256 pParentItem->appendRow(bookmarkItem);
257 }
258
259 // 展开所有节点
260 m_pTreeView->expandAll();
261}
262
263void CFrmBookmark::onAddBookmark()
264{
265 bool ok;
266 QString url = QInputDialog::getText(this, tr("Add bookmark"),
267 tr("Url:"), QLineEdit::Normal,
268 "http://", &ok);
269 if (!ok || url.isEmpty()) return;
270
271 QString title = QInputDialog::getText(this, tr("Add bookmark"),
272 tr("Title:"), QLineEdit::Normal,
273 "", &ok);
274 if (!ok) return;
275
276 BookmarkItem item;
277 item.url = url;
278 item.title = title.isEmpty() ? url : title;
279 item.createdTime = QDateTime::currentDateTime();
280 item.lastVisitTime = item.createdTime;
281 item.modifiedTime = item.createdTime;
282
283 // 获取选中的文件夹
284 QModelIndex currentIndex = m_pTreeView->currentIndex();
285 if (currentIndex.isValid()) {
286 int type = currentIndex.data(Type).toInt();
287 if (BookmarkType_Folder == type) {
288 item.folderId = currentIndex.data(Qt::UserRole).toInt();
289 }
290 }
291
292 if (m_pDatabase->addBookmark(item)) {
293 refresh();
294 }
295}
296
297void CFrmBookmark::onAddFolder()
298{
299 bool ok;
300 QString name = QInputDialog::getText(this, tr("Add folder"),
301 tr("Folder name:"), QLineEdit::Normal,
302 "", &ok);
303 if (!ok || name.isEmpty()) return;
304
305 int parentId = 0;
306 QModelIndex currentIndex = m_pTreeView->currentIndex();
307 if (currentIndex.isValid()) {
308 int type = currentIndex.data(Type).toInt();
309 if (BookmarkType_Folder == type) {
310 parentId = currentIndex.data(Qt::UserRole).toInt();
311 }
312 }
313
314 if (m_pDatabase->addFolder(name, parentId)) {
315 refresh();
316 }
317}
318
319void CFrmBookmark::onEditBookmark()
320{
321 QModelIndex index = m_pTreeView->currentIndex();
322 if (!index.isValid()) return;
323
324 int type = index.data(Type).toInt();
325 int id = index.data(Qt::UserRole).toInt();
326
327 if (BookmarkType_Bookmark == type) {
328 BookmarkItem item = m_pDatabase->getBookmark(id);
329 if (item.id == 0) return;
330
331 bool ok;
332 QString title = QInputDialog::getText(this, tr("Edit bookmark"),
333 tr("Title:"), QLineEdit::Normal,
334 item.title, &ok);
335 if (!ok) return;
336
337 QString url = QInputDialog::getText(this, tr("Add bookmark"),
338 tr("Url:"), QLineEdit::Normal,
339 item.url, &ok);
340 if (!ok) return;
341
342 item.title = title;
343 item.url = url;
344
345 if (m_pDatabase->updateBookmark(item)) {
346 refresh();
347 }
348 } else if (BookmarkType_Folder == type) {
349 QString oldName = index.data(Qt::DisplayRole).toString();
350
351 bool ok;
352 QString newName = QInputDialog::getText(this, tr("Rename folder"),
353 tr("Folder name:"), QLineEdit::Normal,
354 oldName, &ok);
355 if (!ok || newName.isEmpty()) return;
356
357 if (m_pDatabase->renameFolder(id, newName)) {
358 refresh();
359 }
360 }
361}
362
363void CFrmBookmark::onDeleteBookmark()
364{
365 QModelIndex index = m_pTreeView->currentIndex();
366 if (!index.isValid()) return;
367
368 int type = index.data(Type).toInt();
369 QString name = index.data(Qt::DisplayRole).toString();
370 int id = index.data(Qt::UserRole).toInt();
371 if(1 == id && BookmarkType_Folder == type) {
372 QMessageBox::warning(this, tr("Warning"), tr("The folder \"%1\" is not delete").arg(name));
373 return;
374 }
375
376 QString message;
377 if (BookmarkType_Bookmark == type) {
378 message = tr("Are you sure you want to delete the bookmark \"%1\"?").arg(name);
379 } else if (BookmarkType_Folder == type) {
380 message = tr("Are you sure you want to delete the folder \"%1\"?").arg(name);
381 } else {
382 return;
383 }
384
385 QMessageBox::StandardButton reply = QMessageBox::question(
386 this, tr("Confirm deletion"), message,
387 QMessageBox::Yes | QMessageBox::No,
388 QMessageBox::No
389 );
390
391 if (reply == QMessageBox::Yes) {
392 if (BookmarkType_Bookmark == type) {
393 m_pDatabase->deleteBookmark(id);
394 } else if (BookmarkType_Folder == type) {
395 m_pDatabase->deleteFolder(id);
396 }
397 refresh();
398 }
399}
400
401void CFrmBookmark::onSetFavorite()
402{
403 QModelIndex index = m_pTreeView->currentIndex();
404 if (!index.isValid()) return;
405
406 int type = index.data(Type).toInt();
407 if (type != BookmarkType_Bookmark) return;
408
409 int id = index.data(ID).toInt();
410 BookmarkItem item = m_pDatabase->getBookmark(id);
411 if (item.id == 0) return;
412
413 if (m_pDatabase->updateBookmark(item)) {
414 refresh();
415 }
416}
417
418void CFrmBookmark::onImportBookmarks()
419{
420 QString filename = QFileDialog::getOpenFileName(
421 this, tr("Import bookmarks"),
422 RabbitCommon::CDir::Instance()->GetDirUserDocument(),
423 tr("HTML(*.html);; All files (*.*)"));
424
425 if (!filename.isEmpty()) {
426 if (m_pDatabase->importFromHtml(filename)) {
427 QMessageBox::information(this, tr("Success"), tr("Bookmarks imported successfully"));
428 refresh();
429 } else {
430 QMessageBox::warning(this, tr("Failure"), tr("Failed to import bookmark"));
431 }
432 }
433}
434
435void CFrmBookmark::onExportBookmarks()
436{
437 QString filename = QFileDialog::getSaveFileName(
438 this, tr("Export bookmarks"),
439 RabbitCommon::CDir::Instance()->GetDirUserDocument(),
440 tr("HTML (*.html);; All files (*.*)"));
441
442 if (!filename.isEmpty()) {
443 if (m_pDatabase->exportToHtml(filename)) {
444 QMessageBox::information(this, tr("Success"), tr("Bookmarks exported successfully"));
445 } else {
446 QMessageBox::warning(this, tr("Failure"), tr("Failed to export bookmark"));
447 }
448 }
449}
450
451void CFrmBookmark::onSearchTextChanged(const QString &text)
452{
453 if (text.isEmpty()) {
454 loadBookmarks();
455 return;
456 }
457
458 if(!m_pModel) return;
459
460 m_pModel->clear();
461 m_folderItems.clear();
462
463 QList<BookmarkItem> bookmarks = m_pDatabase->searchBookmarks(text);
464 QStandardItem *pRootItem = m_pModel->invisibleRootItem();
465 if(!pRootItem) return;
466
467 foreach (const auto &bookmark, bookmarks) {
468 QStandardItem *item = new QStandardItem(
469 bookmark.getIcon(), bookmark.title);
470 item->setData(bookmark.id, ID);
471 item->setData(BookmarkType_Bookmark, Type);
472 item->setData(bookmark.url, Url);
473
474 item->setToolTip(bookmark.url);
475
476 pRootItem->appendRow(item);
477 }
478}
479
480void CFrmBookmark::onTreeViewDoubleClicked(const QModelIndex &index)
481{
482 if(!m_pDatabase) return;
483 int type = index.data(Type).toInt();
484 if (BookmarkType_Bookmark == type) {
485 QString url = index.data(Url).toString();
486 int id = index.data(ID).toInt();
487 if (!url.isEmpty()) {
488 BookmarkItem item = m_pDatabase->getBookmark(id);
489 item.lastVisitTime = QDateTime::currentDateTime();
490 m_pDatabase->updateBookmark(item);
491 emit openUrlRequested(url);
492 close(); // 关闭对话框
493 }
494 }
495}
496
497void CFrmBookmark::onCustomContextMenu(const QPoint &pos)
498{
499 if(!m_pTreeView) return;
500 QModelIndex index = m_pTreeView->indexAt(pos);
501 if (!index.isValid()) return;
502
503 QMenu menu(this);
504
505 int id = index.data(ID).toInt();
506 int type = index.data(Type).toInt();
507
508 if (BookmarkType_Bookmark == type) {
509 menu.addAction(QIcon::fromTheme("document-open"), tr("Open"), this, [this, index]() {
510 onTreeViewDoubleClicked(index);
511 });
512
513 menu.addAction(QIcon::fromTheme("edit"), tr("Edit"), this, &CFrmBookmark::onEditBookmark);
514 menu.addSeparator();
515
516 QAction *favoriteAction = menu.addAction(QIcon::fromTheme("favorites"), tr("Favorite"));
517 connect(favoriteAction, &QAction::triggered, this, &CFrmBookmark::onSetFavorite);
518
519 menu.addAction(QIcon::fromTheme("edit-delete"), tr("Delete"), this, &CFrmBookmark::onDeleteBookmark);
520 } else if (BookmarkType_Folder == type) {
521 menu.addAction(QIcon::fromTheme("Add"), tr("Add bookmark"), this, &CFrmBookmark::onAddBookmark);
522 menu.addAction(QIcon::fromTheme("folder-new"), tr("Add folder"), this, &CFrmBookmark::onAddFolder);
523 menu.addSeparator();
524 menu.addAction(QIcon::fromTheme("edit"), tr("Edit"), this, &CFrmBookmark::onEditBookmark);
525 if(1 != id)
526 menu.addAction(QIcon::fromTheme("edit-delete"), tr("Delete"), this, &CFrmBookmark::onDeleteBookmark);
527 }
528
529 menu.exec(m_pTreeView->viewport()->mapToGlobal(pos));
530}
531
532void CFrmBookmark::refresh()
533{
534 loadBookmarks();
535}