14#include <QInputDialog>
17#include <QLoggingCategory>
20#include "RabbitCommonDir.h"
21#include "FavoriteMimeData.h"
23#include "FavoriteView.h"
24#include "ParameterGlobal.h"
27static Q_LOGGING_CATEGORY(log,
"Favorite")
32 , m_pDockTitleBar(
nullptr)
33 , m_pTreeView(
nullptr)
35 , m_pDatabase(
nullptr)
36 , m_pStartAction(
nullptr)
37 , m_pEidtStartAction(
nullptr)
38 , m_pAddFolderAction(
nullptr)
39 , m_pEditAction(
nullptr)
40 , m_pDeleteAction(
nullptr)
41 , m_pImportAction(
nullptr)
42 , m_pExportAction(
nullptr)
44 , m_pShowToolbar(
nullptr)
49 setWindowTitle(tr(
"Favorite"));
51 m_pDockTitleBar =
new RabbitCommon::CTitleBar(parent);
53 m_pMenu =
new QMenu(tr(
"Tools"), m_pDockTitleBar);
54 check = connect(m_pMenu, SIGNAL(aboutToShow()),
this, SLOT(slotMenu()));
56 QPushButton* pTools = m_pDockTitleBar->CreateSmallPushButton(
57 QIcon::fromTheme(
"tools"), m_pDockTitleBar);
58 pTools->setToolTip(tr(
"Tools"));
59 pTools->setMenu(m_pMenu);
60 QList<QWidget*> lstWidget;
62 m_pDockTitleBar->AddWidgets(lstWidget);
67CFavoriteView::~CFavoriteView()
71 m_pDatabase =
nullptr;
75void CFavoriteView::setupUI()
77 QVBoxLayout *pMainLayout =
new QVBoxLayout(
this);
78 if(!pMainLayout)
return;
80 setupToolBar(pMainLayout);
82 setupTreeView(pMainLayout);
85void CFavoriteView::setupToolBar(QLayout *layout)
89 QToolBar* pToolBar =
new QToolBar(
this);
91 layout->addWidget(pToolBar);
93 m_pShowToolbar =
new QAction(tr(
"Show tool bar"),
this);
94 m_pShowToolbar->setCheckable(
true);
95 m_pShowToolbar->setChecked(m_pParaApp->GetDockListFavoriteShowToolBar());
96 pToolBar->setVisible(m_pShowToolbar->isChecked());
97 check = connect(m_pShowToolbar, &QAction::triggered,
this, [&, pToolBar]() {
98 if(m_pShowToolbar && m_pParaApp) {
99 pToolBar->setVisible(m_pShowToolbar->isChecked());
100 m_pParaApp->SetDockListFovoriteShowToolBar(m_pShowToolbar->isChecked());
106 m_pStartAction = pToolBar->addAction(
107 QIcon::fromTheme(
"media-playback-start"), tr(
"Start"));
109 m_pStartAction->setToolTip(m_pStartAction->text());
110 m_pStartAction->setStatusTip(m_pStartAction->text());
111 check = connect(m_pStartAction, &QAction::triggered,
112 this, &CFavoriteView::slotStart);
116 m_pEidtStartAction = pToolBar->addAction(
117 QIcon::fromTheme(
"system-settings"), tr(
"Open settings and Start"));
118 if(m_pEidtStartAction) {
119 m_pEidtStartAction->setToolTip(m_pEidtStartAction->text());
120 m_pEidtStartAction->setStatusTip(m_pEidtStartAction->text());
121 check = connect(m_pEidtStartAction, &QAction::triggered,
122 this, &CFavoriteView::slotOpenStart);
126 pToolBar->addSeparator();
128 m_pAddFolderAction = pToolBar->addAction(
129 QIcon::fromTheme(
"folder-new"), tr(
"New group"));
130 if(m_pAddFolderAction) {
131 m_pAddFolderAction->setToolTip(m_pAddFolderAction->text());
132 m_pAddFolderAction->setStatusTip(m_pAddFolderAction->text());
133 check = connect(m_pAddFolderAction, &QAction::triggered,
134 this, &CFavoriteView::slotNewGroup);
138 m_pEditAction = pToolBar->addAction(QIcon::fromTheme(
"edit"), tr(
"Edit"));
140 m_pEditAction->setToolTip(m_pEditAction->text());
141 m_pEditAction->setStatusTip(m_pEditAction->text());
142 check = connect(m_pEditAction, &QAction::triggered,
143 this, &CFavoriteView::slotEdit);
147 m_pDeleteAction = pToolBar->addAction(QIcon::fromTheme(
"edit-delete"), tr(
"Delete"));
148 if(m_pDeleteAction) {
149 m_pDeleteAction->setToolTip(m_pDeleteAction->text());
150 m_pDeleteAction->setStatusTip(m_pDeleteAction->text());
151 check = connect(m_pDeleteAction, &QAction::triggered,
this, &CFavoriteView::slotDelete);
155 pToolBar->addSeparator();
157 m_pImportAction = pToolBar->addAction(QIcon::fromTheme(
"import"), tr(
"Import"));
158 if(m_pImportAction) {
159 m_pImportAction->setToolTip(m_pImportAction->text());
160 m_pImportAction->setStatusTip(m_pImportAction->text());
161 check = connect(m_pImportAction, &QAction::triggered,
this, &CFavoriteView::slotImport);
165 m_pExportAction = pToolBar->addAction(QIcon::fromTheme(
"export"), tr(
"Export"));
166 if(m_pExportAction) {
167 m_pExportAction->setToolTip(m_pExportAction->text());
168 m_pExportAction->setStatusTip(m_pExportAction->text());
169 check = connect(m_pExportAction, &QAction::triggered,
this, &CFavoriteView::slotExport);
173 pToolBar->addSeparator();
174 m_pRefresh = pToolBar->addAction(QIcon::fromTheme(
"view-refresh"), tr(
"Refresh"),
this, [&](){
180void CFavoriteView::setupTreeView(QLayout *layout)
183 m_pTreeView =
new QTreeView(
this);
186 layout->addWidget(m_pTreeView);
190 m_pTreeView->setUniformRowHeights(
true);
191 m_pTreeView->setHeaderHidden(
true);
198 m_pTreeView->setContextMenuPolicy(Qt::CustomContextMenu);
199 bool check = connect(m_pTreeView,
200 SIGNAL(customContextMenuRequested(
const QPoint &)),
201 this, SLOT(slotCustomContextMenu(
const QPoint &)));
203 check = connect(m_pTreeView, SIGNAL(clicked(
const QModelIndex&)),
204 this, SLOT(slotFavrtieClicked(
const QModelIndex&)));
206 check = connect(m_pTreeView, SIGNAL(doubleClicked(
const QModelIndex&)),
207 this, SLOT(slotFavortiedoubleClicked(
const QModelIndex&)));
213int CFavoriteView::Initial()
220 auto pg = m_pParaApp->GetGlobalParameters();
221 bRet = m_pDatabase->
SetDatabase(&pg->m_DatabaseRemote);
226 m_pTreeView->setModel(m_pModel);
233void CFavoriteView::EnableAction(
const QModelIndex &index)
235 if(!m_pModel)
return;
236 if(index.isValid()) {
238 m_pModel->data(index, CFavoriteModel::RoleItem)
240 if(item.isFavorite()) {
241 m_pStartAction->setEnabled(
true);
242 m_pEidtStartAction->setEnabled(
true);
244 m_pStartAction->setEnabled(
false);
245 m_pEidtStartAction->setEnabled(
false);
247 m_pEditAction->setEnabled(
true);
248 m_pDeleteAction->setEnabled(
true);
253 m_pStartAction->setEnabled(
false);
254 if(m_pEidtStartAction)
255 m_pEidtStartAction->setEnabled(
false);
257 m_pEditAction->setEnabled(
false);
259 m_pDeleteAction->setEnabled(
false);
262void CFavoriteView::slotAddToFavorite(
const QString &file,
263 const QString &szName,
264 const QString &szDescription,
268 if(!m_pModel || !m_pTreeView)
return;
273 QString szGroup = tr(
"Root");
274 auto indexes = m_pTreeView->selectionModel()->selectedIndexes();
275 if(!indexes.isEmpty())
277 QModelIndex idx = indexes.at(0);
278 while (idx.isValid()) {
281 if(item.isFolder() && item.id > 0) {
283 szGroup = item.szName;
290 auto item = m_pModel->GetFavorite(szFile);
292 if(item.parentId == parentId) {
293 QMessageBox::information(
294 nullptr, tr(
"Add favorite"),
295 tr(
"\"%1\" already exists in \"%2\"").arg(szName, szGroup));
298 int ret = QMessageBox::warning(
299 nullptr, tr(
"Add favorite"),
300 tr(
"\"%1\" already exists, do you want to move it to \"%2\"?").arg(szName, szGroup),
301 QMessageBox::Ok | QMessageBox::No);
302 if(QMessageBox::Ok != ret)
306 m_pModel->AddFavorite(szFile, szName, icon, szDescription, parentId);
311void CFavoriteView::slotUpdateFavorite(
312 const QString &szFile,
const QString &szName,
313 const QString &szDescription,
const QIcon &icon)
315 if(!m_pModel || !m_pTreeView || szFile.isEmpty())
return;
319void CFavoriteView::slotFavrtieClicked(
const QModelIndex &index)
324void CFavoriteView::slotFavortiedoubleClicked(
const QModelIndex &index)
326 if(!index.isValid())
return;
327 if(m_pTreeView->editTriggers() != QTreeView::NoEditTriggers)
329 QString szFile = m_pModel->data(index, CFavoriteModel::RoleFile).toString();
330 if(!szFile.isEmpty())
334void CFavoriteView::slotDoubleEditNode(
bool bEdit)
337 m_pTreeView->setEditTriggers(QTreeView::DoubleClicked);
339 m_pTreeView->setEditTriggers(QTreeView::NoEditTriggers);
342void CFavoriteView::slotMenu()
348 m_pMenu->addAction(m_pStartAction);
349 m_pMenu->addAction(m_pEidtStartAction);
351 m_pMenu->addSeparator();
352 m_pMenu->addAction(m_pAddFolderAction);
353 m_pMenu->addAction(m_pEditAction);
354 m_pMenu->addAction(m_pDeleteAction);
356 m_pMenu->addSeparator();
357 m_pMenu->addAction(m_pImportAction);
358 m_pMenu->addAction(m_pExportAction);
360 m_pMenu->addSeparator();
361 m_pMenu->addAction(m_pRefresh);
363 m_pMenu->addSeparator();
364 m_pMenu->addAction(m_pShowToolbar);
367void CFavoriteView::slotCustomContextMenu(
const QPoint &pos)
370 m_pMenu->exec(m_pTreeView->mapToGlobal(pos));
373void CFavoriteView::slotStart()
375 auto lstIndex = m_pTreeView->selectionModel()->selectedIndexes();
376 foreach(
auto index, lstIndex)
378 QString szFile = m_pModel->data(index, CFavoriteModel::RoleFile).toString();
379 if(!szFile.isEmpty())
384void CFavoriteView::slotOpenStart()
386 auto lstIndex = m_pTreeView->selectionModel()->selectedIndexes();
387 foreach(
auto index, lstIndex)
389 QString szFile = m_pModel->data(index, CFavoriteModel::RoleFile).toString();
390 if(!szFile.isEmpty())
395void CFavoriteView::slotEdit()
397 auto lstIndex = m_pTreeView->selectionModel()->selectedIndexes();
398 foreach(
auto index, lstIndex)
400 QString szName = m_pModel->data(index).toString();
401 szName = QInputDialog::getText(
402 this, tr(
"Edit"), tr(
"Enter the modified name"), QLineEdit::Normal, szName);
405 m_pModel->setData(index, szName);
409void CFavoriteView::slotDelete()
411 auto lstIndex = m_pTreeView->selectionModel()->selectedIndexes();
412 if(1 == lstIndex.size()) {
414 m_pModel->data(lstIndex.at(0), CFavoriteModel::RoleItem)
417 int ret = QMessageBox::warning(
418 nullptr, tr(
"Delete"), tr(
"Will be delete \"%1\"").arg(item.szName),
419 QMessageBox::Ok|QMessageBox::No);
420 if(QMessageBox::Ok != ret)
424 foreach(
auto index, lstIndex)
425 m_pModel->removeRow(index.row(), index.parent());
428void CFavoriteView::slotNewGroup()
430 if(!m_pModel)
return;
431 QString szGroup = QInputDialog::getText(
432 this, tr(
"New group"), tr(
"Input group name"));
433 if(szGroup.isEmpty())
return;
436 auto lstIndex = m_pTreeView->selectionModel()->selectedIndexes();
437 if(!lstIndex.isEmpty())
440 m_pModel->data(lstIndex.at(0), CFavoriteModel::RoleItem)
442 if(0 < item.id && item.isFolder())
446 m_pModel->AddNode(szGroup, parentId);
449void CFavoriteView::slotRefresh()
455void CFavoriteView::slotImport()
457 QString filename = QFileDialog::getOpenFileName(
458 this, tr(
"Import favorite"),
459 RabbitCommon::CDir::Instance()->GetDirUserDocument(),
460 tr(
"JSON (*.json)"));
462 if (!filename.isEmpty()) {
463 QFileInfo fi(filename);
464 if(0 == fi.suffix().compare(
"json", Qt::CaseInsensitive)) {
465 if (m_pDatabase->ImportFromJsonFile(filename)) {
467 QMessageBox::information(
469 tr(
"Successfully imported favorite from JSON file: %1").arg(filename));
471 QString szErr = tr(
"Failed to import favorite from JSON file: %1").arg(filename) +
"\n";
472 if(!m_pDatabase->GetError().isEmpty())
473 szErr +=
"\n" + tr(
"Error: ") + m_pDatabase->GetError();
474 QMessageBox::critical(
this, tr(
"Failure"), szErr);
478 QMessageBox::warning(
this, tr(
"Import favorite"),
479 tr(
"Invalid file: %1").arg(filename) +
"\n\n"
480 + tr(
"Please use JSON file"));
484void CFavoriteView::slotExport()
486 QString filename = QFileDialog::getSaveFileName(
487 this, tr(
"Export favorite"),
488 RabbitCommon::CDir::Instance()->GetDirUserDocument(),
489 tr(
"JSON (*.json)"));
491 if (!filename.isEmpty()) {
492 QFileInfo fi(filename);
493 if(0 == fi.suffix().compare(
"json", Qt::CaseInsensitive)) {
494 if (m_pDatabase->ExportToJsonFile(filename)) {
495 QMessageBox::information(
497 tr(
"Favorite successfully exported to JSON file: %1").arg(filename));
499 QString szErr = tr(
"Failed to import favorite from JSON file: %1").arg(filename) +
"\n";
500 if(!m_pDatabase->GetError().isEmpty())
501 szErr +=
"\n" + tr(
"Error: ") + m_pDatabase->GetError();
502 QMessageBox::critical(
this, tr(
"Failure"), szErr);
506 QMessageBox::critical(
this, tr(
"Failure"),
507 tr(
"Invalid file: %1").arg(filename) +
"\n\n"
508 + tr(
"Please use JSON file"));
512void CFavoriteView::InitialDragDrop()
514 if(!m_pTreeView || !m_pTreeView->viewport())
517 m_pTreeView->viewport()->installEventFilter(
this);
518 m_pTreeView->setAcceptDrops(
true);
519 m_pTreeView->setDragEnabled(
true);
520 m_pTreeView->setDragDropMode(QTreeView::InternalMove);
521 m_pTreeView->setDefaultDropAction(Qt::MoveAction);
522 m_pTreeView->setDropIndicatorShown(
true);
525void CFavoriteView::dragEnterEvent(QDragEnterEvent *event)
527 qDebug(log) << Q_FUNC_INFO;
528 auto urls =
event->mimeData()->urls();
529 if(event->mimeData()->hasUrls() && urls.length() == 1) {
531 event->acceptProposedAction();
536 qobject_cast<const CFavoriteMimeData*>(event->mimeData());
539 qDebug(log) <<
"dragEnterEvent acceptProposedAction";
540 event->acceptProposedAction();
551void CFavoriteView::dragMoveEvent(QDragMoveEvent *event)
563void CFavoriteView::dropEvent(QDropEvent *event)
565 qDebug(log) << Q_FUNC_INFO <<
"drop action:" <<
event->dropAction();
567 auto urls =
event->mimeData()->urls();
568 foreach(
auto url, urls)
570 if(url.isLocalFile()) {
571 QString filename = url.toLocalFile();
572 if (m_pDatabase->ImportFromJsonFile(filename)) {
574 emit
sigShowMessageBox(tr(
"Success"), tr(
"Successfully imported favorite from JSON file: %1").arg(filename), QMessageBox::Information);
576 QString szErr = tr(
"Failed to import favorite from JSON file: %1").arg(filename) +
"\n";
577 if(!m_pDatabase->GetError().isEmpty())
578 szErr +=
"\n" + tr(
"Error: ") + m_pDatabase->GetError();
586 const CFavoriteMimeData *pData = qobject_cast<const CFavoriteMimeData*>(event->mimeData());
587 if(!pData || pData->m_Items.isEmpty() || !m_pTreeView || !m_pModel) {
592#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
593 auto idxParent = m_pTreeView->indexAt(event->position().toPoint());
595 auto idxParent = m_pTreeView->indexAt(event->pos());
597 QVariant v = m_pModel->data(idxParent, CFavoriteModel::RoleItem);
601 if(0 <= item.id && item.isFolder())
603 foreach(
auto i, pData->m_Items)
606 qWarning(log) <<
"Don't drag, the same node.";
609 if (event->dropAction() == Qt::MoveAction)
610 bRet = m_pModel->Move(i, idxParent);
611 else if (event->dropAction() == Qt::CopyAction)
612 bRet = m_pModel->Copy(i, idxParent);
616 qWarning(log) <<
"Don't group node. the id:" << item.id
617 <<
" Folder:" << item.isFolder();
626void CFavoriteView::mousePressEvent(QMouseEvent *event)
628 qDebug(log) <<
"mousePressEvent";
629 if (m_pTreeView && m_pTreeView->selectionModel()
630 && event->button() == Qt::LeftButton) {
633 QModelIndexList indexes = m_pTreeView->selectionModel()->selectedIndexes();
634 if (!indexes.isEmpty()) {
636#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
637 auto curIndex = m_pTreeView->indexAt(event->position().toPoint());
639 auto curIndex = m_pTreeView->indexAt(event->pos());
641 if(indexes.contains(curIndex)) {
642 QDrag *drag =
new QDrag(
this);
645 m_DragStartPosition =
event->pos();
647 pData->m_Items = indexes;
648 drag->setMimeData(pData);
649 Qt::DropAction dropAction = Qt::MoveAction;
660 drag->exec(dropAction);
667 QWidget::mousePressEvent(event);
670void CFavoriteView::mouseMoveEvent(QMouseEvent *event)
672 qDebug(log) <<
"mouseMoveEvent";
674 if (!(event->buttons() & Qt::LeftButton))
676 if ((event->pos() - m_DragStartPosition).manhattanLength()
677 < QApplication::startDragDistance())
679 qDebug(log) <<
"mouseMoveEvent drag";
683 QWidget::mouseMoveEvent(event);
686bool CFavoriteView::eventFilter(QObject *watched, QEvent *event)
689 if (watched == m_pTreeView->viewport()) {
692 switch (event->type()) {
693 case QEvent::DragEnter:
694 dragEnterEvent(
static_cast<QDragEnterEvent*
>(event));
696 case QEvent::DragMove:
697 dragMoveEvent(
static_cast<QDragMoveEvent*
>(event));
700 dropEvent(
static_cast<QDropEvent*
>(event));
702 case QEvent::MouseButtonPress:
703 mousePressEvent(
static_cast<QMouseEvent*
>(event));
706 case QEvent::MouseMove:
707 mouseMoveEvent(
static_cast<QMouseEvent*
>(event));
715 return QWidget::eventFilter(watched, event);
static QString SetFile(const QString &szFile)
Set the file with file system to the file in database
static QString GetFile(const QString &szFile)
Get the file with file system from the file in database
bool SetDatabase(const CDatabase *db)
Share an existing database
The CFavoriteDatabase class
virtual void sigShowMessageBox(const QString &title, const QString &message, const QMessageBox::Icon &icon)
用消息对话框(QMessageBox)显示信息
virtual int Save(QString szFile=QString(), bool bForce=true)
Save to file