10#include <QInputDialog>
12#include <QLoggingCategory>
14#include "RabbitCommonDir.h"
15#include "FrmBookmark.h"
16#include "ui_FrmBookmark.h"
18static Q_LOGGING_CATEGORY(log,
"WebBrowser.Bookmark")
22 , m_pDatabase(
nullptr)
24 , m_pTreeView(
nullptr)
25 , m_pSearchEdit(
nullptr)
27 , m_pModel(new QStandardItemModel(this))
30 setWindowTitle(tr(
"Bookmark"));
36 m_pDatabase = &pPara->m_BookmarkDatabase;
37 resize(m_pPara->GetWindowSize());
43CFrmBookmark::~CFrmBookmark()
48void CFrmBookmark::setupUI()
51 QVBoxLayout *pMainLayout =
new QVBoxLayout(
this);
52 if(!pMainLayout)
return;
56 pMainLayout->addWidget(m_pToolBar);
59 QHBoxLayout *pSearchLayout =
new QHBoxLayout;
61 pSearchLayout->addWidget(
new QLabel(tr(
"Search:")));
63 m_pSearchEdit =
new QLineEdit(
this);
65 m_pSearchEdit->setPlaceholderText(tr(
"Input keyword to search boolmark ......"));
66 m_pSearchEdit->setClearButtonEnabled(
true);
67 check = connect(m_pSearchEdit, &QLineEdit::textChanged,
68 this, &CFrmBookmark::onSearchTextChanged);
70 pSearchLayout->addWidget(m_pSearchEdit);
72 pMainLayout->addLayout(pSearchLayout);
77 pMainLayout->addWidget(m_pTreeView);
80 QHBoxLayout *pButtonLayout =
new QHBoxLayout;
82 pButtonLayout->addStretch();
84 QPushButton *closeButton =
new QPushButton(tr(
"Close"),
this);
85 connect(closeButton, &QPushButton::clicked,
this, &CFrmBookmark::close);
86 pButtonLayout->addWidget(closeButton);
88 pMainLayout->addLayout(pButtonLayout);
90 setLayout(pMainLayout);
93void CFrmBookmark::setupToolBar()
96 m_pToolBar =
new QToolBar(
this);
97 if(!m_pToolBar)
return;
100 QAction *addAction = m_pToolBar->addAction(QIcon::fromTheme(
"add"), tr(
"Add bookmark"));
102 check = connect(addAction, &QAction::triggered,
this, &CFrmBookmark::onAddBookmark);
107 QAction *addFolderAction = m_pToolBar->addAction(QIcon::fromTheme(
"folder-new"), tr(
"Add folder"));
108 if(addFolderAction) {
109 check = connect(addFolderAction, &QAction::triggered,
this, &CFrmBookmark::onAddFolder);
113 m_pToolBar->addSeparator();
116 QAction *editAction = m_pToolBar->addAction(QIcon::fromTheme(
"edit"), tr(
"Edit"));
118 check = connect(editAction, &QAction::triggered,
this, &CFrmBookmark::onEditBookmark);
123 QAction *pDeleteAction = m_pToolBar->addAction(QIcon::fromTheme(
"edit-delete"), tr(
"Delete"));
125 check = connect(pDeleteAction, &QAction::triggered,
this, &CFrmBookmark::onDeleteBookmark);
137 m_pToolBar->addSeparator();
140 QAction *importAction = m_pToolBar->addAction(QIcon::fromTheme(
"import"), tr(
"Import"));
142 check = connect(importAction, &QAction::triggered,
this, &CFrmBookmark::onImportBookmarks);
147 QAction *exportAction = m_pToolBar->addAction(QIcon::fromTheme(
"export"), tr(
"Export"));
149 check = connect(exportAction, &QAction::triggered,
this, &CFrmBookmark::onExportBookmarks);
153 m_pToolBar->addSeparator();
156 QAction *refreshAction = m_pToolBar->addAction(QIcon::fromTheme(
"view-refresh"), tr(
"Refresh"));
158 check = connect(refreshAction, &QAction::triggered,
this, &CFrmBookmark::refresh);
163void CFrmBookmark::setupTreeView()
166 m_pTreeView =
new QTreeView(
this);
167 if(!m_pTreeView)
return;
168 m_pTreeView->setHeaderHidden(
true);
169 m_pTreeView->setContextMenuPolicy(Qt::CustomContextMenu);
170 m_pTreeView->setEditTriggers(QAbstractItemView::NoEditTriggers);
173 check = connect(m_pTreeView, &QTreeView::doubleClicked,
174 this, &CFrmBookmark::onTreeViewDoubleClicked);
176 check = connect(m_pTreeView, &QTreeView::customContextMenuRequested,
177 this, &CFrmBookmark::onCustomContextMenu);
181 m_pTreeView->setModel(m_pModel);
183 m_pModel->setColumnCount(1);
190void CFrmBookmark::loadBookmarks()
192 if(!m_pDatabase || !m_pModel || !m_pTreeView)
return;
194 m_folderItems.clear();
197 m_pModel->setHorizontalHeaderLabels(QStringList() << tr(
"Title"));
200 QList<BookmarkItem> folders = m_pDatabase->getAllFolders();
203 QStandardItem *rootItem = m_pModel->invisibleRootItem();
205 int nCurrent = m_pPara->GetBookmarkCurrentFolder();
206 QStandardItem* pCurrentItem =
nullptr;
209 for (
const auto &folder : folders) {
210 if (folder.folderId == 0) {
211 QStandardItem *pFolderItem =
new QStandardItem(folder.getIcon(), folder.title);
212 if(!pFolderItem)
continue;
213 pFolderItem->setData(folder.id, ID);
214 pFolderItem->setData(BookmarkType_Folder, Type);
215 rootItem->appendRow(pFolderItem);
216 m_folderItems[folder.id] = pFolderItem;
217 if(folder.id == nCurrent)
218 pCurrentItem = pFolderItem;
222 auto it = m_folderItems.find(folder.folderId);
223 if(m_folderItems.end() == it) {
224 qWarning(log) <<
"The parent of folder is not find:" << folder.folderId;
227 QStandardItem *pFolderItem =
new QStandardItem(folder.getIcon(), folder.title);
228 if(!pFolderItem)
continue;
229 pFolderItem->setData(folder.id, ID);
230 pFolderItem->setData(BookmarkType_Folder, Type);
231 (*it)->appendRow(pFolderItem);
232 m_folderItems[folder.id] = pFolderItem;
233 if(folder.id == nCurrent)
234 pCurrentItem = pFolderItem;
239 auto index = m_pModel->indexFromItem(pCurrentItem);
240 m_pTreeView->setCurrentIndex(index);
244 QList<BookmarkItem> bookmarks = m_pDatabase->getAllBookmarks(-1);
245 for (
const auto &bookmark : bookmarks) {
246 QStandardItem *pParentItem =
nullptr;
248 if (bookmark.folderId > 0 && m_folderItems.contains(bookmark.folderId)) {
249 pParentItem = m_folderItems[bookmark.folderId];
251 pParentItem = rootItem;
254 QStandardItem *bookmarkItem =
new QStandardItem(bookmark.getIcon(), bookmark.title);
255 bookmarkItem->setData(bookmark.id, ID);
256 bookmarkItem->setData(BookmarkType_Bookmark, Type);
257 bookmarkItem->setData(bookmark.url, Url);
260 pParentItem->appendRow(bookmarkItem);
264 m_pTreeView->expandAll();
267void CFrmBookmark::onAddBookmark()
270 QString url = QInputDialog::getText(
this, tr(
"Add bookmark"),
271 tr(
"Url:"), QLineEdit::Normal,
273 if (!ok || url.isEmpty())
return;
275 QString title = QInputDialog::getText(
this, tr(
"Add bookmark"),
276 tr(
"Title:"), QLineEdit::Normal,
282 item.title = title.isEmpty() ? url : title;
283 item.createdTime = QDateTime::currentDateTime();
284 item.lastVisitTime = item.createdTime;
285 item.modifiedTime = item.createdTime;
288 QModelIndex currentIndex = m_pTreeView->currentIndex();
289 if (currentIndex.isValid()) {
290 int type = currentIndex.data(Type).toInt();
291 if (BookmarkType_Folder == type) {
292 item.folderId = currentIndex.data(Qt::UserRole).toInt();
296 if (m_pDatabase->addBookmark(item)) {
301void CFrmBookmark::onAddFolder()
304 QString name = QInputDialog::getText(
this, tr(
"Add folder"),
305 tr(
"Folder name:"), QLineEdit::Normal,
307 if (!ok || name.isEmpty())
return;
310 QModelIndex currentIndex = m_pTreeView->currentIndex();
311 if (currentIndex.isValid()) {
312 int type = currentIndex.data(Type).toInt();
313 if (BookmarkType_Folder == type) {
314 parentId = currentIndex.data(Qt::UserRole).toInt();
318 if (m_pDatabase->addFolder(name, parentId)) {
323void CFrmBookmark::onEditBookmark()
325 QModelIndex index = m_pTreeView->currentIndex();
326 if (!index.isValid())
return;
328 int type = index.data(Type).toInt();
329 int id = index.data(Qt::UserRole).toInt();
331 if (BookmarkType_Bookmark == type) {
333 if (item.id == 0)
return;
336 QString title = QInputDialog::getText(
this, tr(
"Edit bookmark"),
337 tr(
"Title:"), QLineEdit::Normal,
341 QString url = QInputDialog::getText(
this, tr(
"Add bookmark"),
342 tr(
"Url:"), QLineEdit::Normal,
349 if (m_pDatabase->updateBookmark(item)) {
352 }
else if (BookmarkType_Folder == type) {
353 QString oldName = index.data(Qt::DisplayRole).toString();
356 QString newName = QInputDialog::getText(
this, tr(
"Rename folder"),
357 tr(
"Folder name:"), QLineEdit::Normal,
359 if (!ok || newName.isEmpty())
return;
361 if (m_pDatabase->renameFolder(
id, newName)) {
367void CFrmBookmark::onDeleteBookmark()
369 QModelIndex index = m_pTreeView->currentIndex();
370 if (!index.isValid())
return;
372 int type = index.data(Type).toInt();
373 QString name = index.data(Qt::DisplayRole).toString();
374 int id = index.data(Qt::UserRole).toInt();
375 if(1 ==
id && BookmarkType_Folder == type) {
376 QMessageBox::warning(
this, tr(
"Warning"), tr(
"The folder \"%1\" is not delete").arg(name));
381 if (BookmarkType_Bookmark == type) {
382 message = tr(
"Are you sure you want to delete the bookmark \"%1\"?").arg(name);
383 }
else if (BookmarkType_Folder == type) {
384 message = tr(
"Are you sure you want to delete the folder \"%1\"?").arg(name);
389 QMessageBox::StandardButton reply = QMessageBox::question(
390 this, tr(
"Confirm deletion"), message,
391 QMessageBox::Yes | QMessageBox::No,
395 if (reply == QMessageBox::Yes) {
396 if (BookmarkType_Bookmark == type) {
397 m_pDatabase->deleteBookmark(
id);
398 }
else if (BookmarkType_Folder == type) {
399 m_pDatabase->deleteFolder(
id);
405void CFrmBookmark::onSetFavorite()
407 QModelIndex index = m_pTreeView->currentIndex();
408 if (!index.isValid())
return;
410 int type = index.data(Type).toInt();
411 if (type != BookmarkType_Bookmark)
return;
413 int id = index.data(ID).toInt();
415 if (item.id == 0)
return;
417 if (m_pDatabase->updateBookmark(item)) {
422void CFrmBookmark::onImportBookmarks()
424 QString filename = QFileDialog::getOpenFileName(
425 this, tr(
"Import bookmarks"),
426 RabbitCommon::CDir::Instance()->GetDirUserDocument(),
427 tr(
"JSON (*.json);; All files (*.*)"));
429 if (filename.isEmpty())
return;
431 QFileInfo fi(filename);
432 if(0 == fi.suffix().compare(
"json", Qt::CaseInsensitive)) {
433 if (m_pDatabase->ImportFromJsonFile(filename)) {
434 QMessageBox::information(
this, tr(
"Import bookmarks"),
435 tr(
"Successfully imported bookmarks from file: %1").arg(filename));
438 QMessageBox::critical(
this, tr(
"Import bookmarks"),
439 tr(
"Failed to import bookmark from file: %1").arg(filename) +
"\n\n"
440 + tr(
"Error: ") + m_pDatabase->GetError());
445 QMessageBox::warning(
this, tr(
"Import bookmarks"),
446 tr(
"Invalid file: %1").arg(filename) +
"\n\n"
447 + tr(
"Please use html file"));
450void CFrmBookmark::onExportBookmarks()
452 QString filename = QFileDialog::getSaveFileName(
453 this, tr(
"Export bookmarks"),
454 RabbitCommon::CDir::Instance()->GetDirUserDocument(),
455 tr(
"JSON (*.json);; All files (*.*)"));
457 if (filename.isEmpty())
return;
459 QFileInfo fi(filename);
460 if(0 == fi.suffix().compare(
"json", Qt::CaseInsensitive)) {
461 if (m_pDatabase->ExportToJsonFile(filename)) {
462 QMessageBox::information(
this, tr(
"Export bookmarks"),
463 tr(
"Bookmarks successfully exported to file: %1").arg(filename));
465 QMessageBox::critical(
this, tr(
"Export bookmarks"),
466 tr(
"Failed to export bookmark to file: %1").arg(filename) +
"\n\n"
467 + tr(
"Error: ") + m_pDatabase->GetError());
472 QMessageBox::warning(
this, tr(
"Export bookmarks"),
473 tr(
"Invalid file: %1").arg(filename) +
"\n\n"
474 + tr(
"Please use html file"));
477void CFrmBookmark::onSearchTextChanged(
const QString &text)
479 if (text.isEmpty()) {
484 if(!m_pModel)
return;
487 m_folderItems.clear();
489 QList<BookmarkItem> bookmarks = m_pDatabase->searchBookmarks(text);
490 QStandardItem *pRootItem = m_pModel->invisibleRootItem();
491 if(!pRootItem)
return;
493 foreach (
const auto &bookmark, bookmarks) {
494 QStandardItem *item =
new QStandardItem(
495 bookmark.getIcon(), bookmark.title);
496 item->setData(bookmark.id, ID);
497 item->setData(BookmarkType_Bookmark, Type);
498 item->setData(bookmark.url, Url);
500 item->setToolTip(bookmark.url);
502 pRootItem->appendRow(item);
506void CFrmBookmark::onTreeViewDoubleClicked(
const QModelIndex &index)
508 if(!m_pDatabase)
return;
509 int type = index.data(Type).toInt();
510 if (BookmarkType_Bookmark == type) {
511 QString url = index.data(Url).toString();
512 int id = index.data(ID).toInt();
513 if (!url.isEmpty()) {
515 item.lastVisitTime = QDateTime::currentDateTime();
516 m_pDatabase->updateBookmark(item);
517 emit openUrlRequested(url);
523void CFrmBookmark::onCustomContextMenu(
const QPoint &pos)
525 if(!m_pTreeView)
return;
526 QModelIndex index = m_pTreeView->indexAt(pos);
527 if (!index.isValid())
return;
531 int id = index.data(ID).toInt();
532 int type = index.data(Type).toInt();
534 if (BookmarkType_Bookmark == type) {
535 menu.addAction(QIcon::fromTheme(
"document-open"), tr(
"Open"),
this, [
this, index]() {
536 onTreeViewDoubleClicked(index);
539 menu.addAction(QIcon::fromTheme(
"edit"), tr(
"Edit"),
this, &CFrmBookmark::onEditBookmark);
542 QAction *favoriteAction = menu.addAction(QIcon::fromTheme(
"favorites"), tr(
"Favorite"));
543 connect(favoriteAction, &QAction::triggered,
this, &CFrmBookmark::onSetFavorite);
545 menu.addAction(QIcon::fromTheme(
"edit-delete"), tr(
"Delete"),
this, &CFrmBookmark::onDeleteBookmark);
546 }
else if (BookmarkType_Folder == type) {
547 menu.addAction(QIcon::fromTheme(
"Add"), tr(
"Add bookmark"),
this, &CFrmBookmark::onAddBookmark);
548 menu.addAction(QIcon::fromTheme(
"folder-new"), tr(
"Add folder"),
this, &CFrmBookmark::onAddFolder);
550 menu.addAction(QIcon::fromTheme(
"edit"), tr(
"Edit"),
this, &CFrmBookmark::onEditBookmark);
552 menu.addAction(QIcon::fromTheme(
"edit-delete"), tr(
"Delete"),
this, &CFrmBookmark::onDeleteBookmark);
555 menu.exec(m_pTreeView->viewport()->mapToGlobal(pos));
558void CFrmBookmark::refresh()