From 06420dccad3dd1f4abcd6a4e5fea5ecdb3ea4f77 Mon Sep 17 00:00:00 2001 From: zhangjiaping Date: Sat, 27 Feb 2021 17:32:41 +0800 Subject: [PATCH] feat(frontend): Connect with the latest API for app search. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Description: 对接应用搜索新接口 Log: 对接应用搜索新接口 --- src/content-widget.cpp | 139 ++++++++++++++++------------- src/content-widget.h | 8 +- src/control/home-page-item.cpp | 7 -- src/control/option-view.cpp | 49 ++++++++-- src/control/option-view.h | 8 +- src/control/search-detail-view.cpp | 68 ++++++++++---- src/control/search-detail-view.h | 3 + src/control/search-list-view.cpp | 18 ++-- src/control/search-list-view.h | 2 + src/mainwindow.cpp | 42 +++++---- src/mainwindow.h | 3 +- src/model/search-item-model.cpp | 33 ++++++- src/model/search-item-model.h | 3 + src/model/search-item.cpp | 90 +++++++++++++++---- src/model/search-item.h | 7 ++ src/search-app-thread.cpp | 54 +++++++++++ src/search-app-thread.h | 25 ++++++ src/src.pro | 2 + translations/ukui-search/bo.ts | 115 ++++++++++++------------ translations/ukui-search/tr.ts | 115 ++++++++++++------------ translations/ukui-search/zh_CN.ts | 115 ++++++++++++------------ 21 files changed, 602 insertions(+), 304 deletions(-) create mode 100644 src/search-app-thread.cpp create mode 100644 src/search-app-thread.h diff --git a/src/content-widget.cpp b/src/content-widget.cpp index 72e7566..01b4d32 100644 --- a/src/content-widget.cpp +++ b/src/content-widget.cpp @@ -248,7 +248,7 @@ void ContentWidget::setupConnect(SearchListView * listview) { } else if (type == SearchItem::SearchType::Best && !m_bestContent.isEmpty() && listview->currentIndex().row() == listview->getLength() - 1) { m_detailView->setContent(m_bestContent, m_keyword); m_detailView->isContent = true; - m_detailView->setupWidget(type == SearchItem::SearchType::Contents, path); + m_detailView->setupWidget(SearchItem::SearchType::Contents, path); listview->is_current_list = true; Q_EMIT this->currentItemChanged(); listview->is_current_list = false; @@ -258,6 +258,15 @@ void ContentWidget::setupConnect(SearchListView * listview) { } if (type == SearchItem::SearchType::Web) { m_detailView->setWebWidget(this->m_keyword); + } else if (type == SearchItem::SearchType::Apps) { + int index = listview->currentIndex().row(); + m_detailView->setAppWidget(m_appList.at(index), m_appPathList.at(index), m_appIconList.at(index)); + } else if (type == SearchItem::SearchType::Best) { + if (m_bestList.at(listview->currentIndex().row()).first == SearchItem::SearchType::Apps) { + m_detailView->setAppWidget(m_appList.at(0), m_appPathList.at(0), m_appIconList.at(0)); + } else { + m_detailView->setupWidget(m_bestList.at(listview->currentIndex().row()).first, m_bestList.at(listview->currentIndex().row()).second); + } } else { m_detailView->setupWidget(type, path); } @@ -326,6 +335,13 @@ void ContentWidget::resetListHeight() m_resultList->setFixedHeight(height); } +void ContentWidget::appendBestItem(const int &type, const QString &path) +{ + m_bestList.append(QPair(type, path)); + m_bestListView->appendBestItem(QPair(type, path)); + appendSearchItem(SearchItem::SearchType::Best, path); +} + /** * @brief ContentWidget::initHomePage 向homepage填充内容 * @param lists 三个列表:常用,最近,快捷 @@ -416,10 +432,10 @@ int ContentWidget::currentPage() { } /** - * @brief ContentWidget::refreshSearchList 刷新/构建搜索结果列表 - * @param lists 获取到的应用与设置结果列表,list.at(0)是应用, list.at(1)是设置 + * @brief ContentWidget::resetSearchList 在构建新的搜索结果列表前,先重置所有控件 */ -void ContentWidget::refreshSearchList(const QVector& lists) { +void ContentWidget::resetSearchList() +{ this->hideListView(); if (m_fileListView) { m_fileListView->hide(); @@ -480,6 +496,7 @@ void ContentWidget::refreshSearchList(const QVector& lists) { m_fileShowMoreLabel->resetLabel(); m_contentShowMoreLabel->resetLabel(); + m_bestList.clear(); if (! m_appList.isEmpty()) m_appList.clear(); if (! m_settingList.isEmpty()) @@ -490,34 +507,62 @@ void ContentWidget::refreshSearchList(const QVector& lists) { m_fileList.clear(); if (! m_contentList.isEmpty()) m_contentList.clear(); + if (! m_appPathList.isEmpty()) + m_appPathList.clear(); + if (! m_appIconList.isEmpty()) + m_appIconList.clear(); +} - if (!lists.at(0).isEmpty()) { - m_appList = lists.at(0); - qDebug()<<"Append a best item into list: "<show(); - m_appTitleLabel->show(); - m_appListView->isHidden = false; - if (m_appList.length() <= 5) { - m_appListView->setList(m_appList); - } else { - m_appShowMoreLabel->show(); - m_appListView->setList(m_appList.mid(0, 5)); - } +/** + * @brief ContentWidget::setSettingList 插入设置项搜索结果列表 + * @param settingList + */ +void ContentWidget::setSettingList(const QStringList & settingList) +{ + if (settingList.isEmpty()) + return; + m_settingList = settingList; + qDebug()<<"Append a best item into list: "<appendBestItem(SearchItem::SearchType::Settings, settingList.at(0)); + m_settingListView->show(); + m_settingTitleLabel->show(); + m_settingListView->isHidden = false; + if (m_settingList.length() <= 5) { + m_settingListView->setList(m_settingList); + } else { + m_settingShowMoreLabel->show(); + m_settingListView->setList(m_settingList.mid(0, 5)); } - if (!lists.at(1).isEmpty()) { - m_settingList = lists.at(1); - qDebug()<<"Append a best item into list: "<show(); - m_settingTitleLabel->show(); - m_settingListView->isHidden = false; - if (m_settingList.length() <= 5) { - m_settingListView->setList(m_settingList); - } else { - m_settingShowMoreLabel->show(); - m_settingListView->setList(m_settingList.mid(0, 5)); - } + this->resetListHeight(); +} + +/** + * @brief ContentWidget::setAppList 插入应用搜索结果 + * @param appList QVector + */ +void ContentWidget::setAppList(const QVector& appList) { + if (appList.at(0).isEmpty()) + return; + m_appList = appList.at(0); + m_appPathList = appList.at(1); + m_appIconList = appList.at(2); + m_appListView->setAppList(m_appPathList, m_appIconList); + qDebug()<<"Append a best item into list: "<(m_bestListView->model()); + if (appList.at(1).at(0).isEmpty() || appList.at(1).at(0) == "") { + model->setBestAppIcon(appList.at(2).at(0), false); + } else { + model->setBestAppIcon(appList.at(2).at(0), true); + } + this->appendBestItem(SearchItem::SearchType::Apps, appList.at(0).at(0)); + m_appListView->show(); + m_appTitleLabel->show(); + m_appListView->isHidden = false; + if (m_appList.length() <= 5) { + m_appListView->setList(m_appList); + } else { + m_appShowMoreLabel->show(); + m_appListView->setList(m_appList.mid(0, 5)); } this->resetListHeight(); } @@ -542,40 +587,12 @@ void ContentWidget::appendSearchItem(const int& type, const QString& path, QStri } break; } -// case SearchItem::SearchType::Apps: { -// if (m_appListView->isHidden) { -// m_appListView->show(); -// m_appTitleLabel->show(); -// m_appListView->isHidden = false; -// if (!m_detailView->isEmpty() && m_detailView->getType() > type) { -// m_appListView->setCurrentIndex(m_appListView->model()->index(0, 0, QModelIndex())); -// } -// } -// m_appListView->appendItem(path); -// currentList = m_appListView; - -// this->resetListHeight(); -// break; -// } -// case SearchItem::SearchType::Settings: { -// if (m_settingListView->isHidden) { -// m_settingListView->show(); -// m_settingTitleLabel->show(); -// m_settingListView->isHidden = false; -// if (!m_detailView->isEmpty() && m_detailView->getType() > type) { -// m_settingListView->setCurrentIndex(m_settingListView->model()->index(0, 0, QModelIndex())); -// } -// } -// m_settingListView->appendItem(path); -// currentList = m_settingListView; -// break; -// } case SearchItem::SearchType::Files: { if (m_fileListView->isHidden) { m_fileListView->show(); m_fileTitleLabel->show(); m_fileListView->isHidden = false; - appendSearchItem(SearchItem::SearchType::Best, path); + this->appendBestItem(SearchItem::SearchType::Files, path); } if (m_fileListView->getLength() < 5) { //当已搜索结果列表少于5项,直接将搜索结果添加到列表中 m_fileListView->appendItem(path); @@ -592,7 +609,7 @@ void ContentWidget::appendSearchItem(const int& type, const QString& path, QStri m_dirListView->show(); m_dirTitleLabel->show(); m_dirListView->isHidden = false; - appendSearchItem(SearchItem::SearchType::Best, path); + this->appendBestItem(SearchItem::SearchType::Dirs, path); } if (m_dirListView->getLength() < 5) { m_dirListView->appendItem(path); @@ -615,7 +632,7 @@ void ContentWidget::appendSearchItem(const int& type, const QString& path, QStri m_bestContent.append("\n"); } } - appendSearchItem(SearchItem::SearchType::Best, path); + this->appendBestItem(SearchItem::SearchType::Contents, path); } if (m_contentListView->getLength() < 5) { m_contentListView->appendItem(path); diff --git a/src/content-widget.h b/src/content-widget.h index 83390df..aa4afb1 100644 --- a/src/content-widget.h +++ b/src/content-widget.h @@ -39,7 +39,9 @@ public: void setPage(const int&); int currentPage(); - void refreshSearchList(const QVector&); + void resetSearchList(); + void setSettingList(const QStringList&); + void setAppList(const QVector&); void appendSearchItem(const int& type, const QString& path, QStringList contents = QStringList()); void initHomePage(); void setContentList(const QStringList&); @@ -53,6 +55,7 @@ private: void setupConnect(SearchListView *); void clearHomepage(); void resetListHeight(); + void appendBestItem(const int&, const QString&); QString m_keyword; QStringList m_contentDetailList; QWidget * m_homePage = nullptr; @@ -93,6 +96,9 @@ private: QStringList m_fileList; QStringList m_contentList; QStringList m_quicklyOpenList; + QStringList m_appPathList; + QStringList m_appIconList; + QList> m_bestList; QString m_bestContent; //最佳匹配有文件内容搜索结果的时候,以此变量传递 diff --git a/src/control/home-page-item.cpp b/src/control/home-page-item.cpp index 8f386eb..3f2f75d 100644 --- a/src/control/home-page-item.cpp +++ b/src/control/home-page-item.cpp @@ -121,17 +121,10 @@ void HomePageItem::setupUi(const int& type, const QString& path) { m_hlayout->addStretch(); return; } else if (type == ItemType::Quick) { - if (SearchListView::getResType(path) == SearchListView::ResType::Setting) { - QIcon icon = FileUtils::getSettingIcon(path, true); - m_iconlabel->setPixmap(icon.pixmap(icon.actualSize(QSize(48, 48)))); - m_namelabel->setText(FileUtils::getSettingName(path)); - this->setToolTip(FileUtils::getSettingName(path)); - } else { QIcon icon = FileUtils::getAppIcon(path); m_iconlabel->setPixmap(icon.pixmap(icon.actualSize(QSize(48, 48)))); m_namelabel->setText(FileUtils::getAppName(path)); this->setToolTip(FileUtils::getAppName(path)); - } } else { QIcon icon = FileUtils::getAppIcon(path); m_iconlabel->setPixmap(icon.pixmap(icon.actualSize(QSize(48, 48)))); diff --git a/src/control/option-view.cpp b/src/control/option-view.cpp index 8cb6965..d29b855 100644 --- a/src/control/option-view.cpp +++ b/src/control/option-view.cpp @@ -53,17 +53,22 @@ OptionView::~OptionView() delete m_copyPathLabel; m_copyPathLabel = NULL; } + if (m_installLabel) { + delete m_installLabel; + m_installLabel = NULL; + } } /** * @brief OptionView::initComponent 构建可用选项表 * @param type 详情页类型 + * @param is_appInstalled 如果是应用详情页,应用是否已安装 */ -void OptionView::setupOptions(const int& type) { +void OptionView::setupOptions(const int& type, bool is_appInstalled) { this->hideOptions(); switch (type) { case SearchListView::ResType::App : { - setupAppOptions(); + setupAppOptions(is_appInstalled); break; } case SearchListView::ResType::Content: @@ -127,6 +132,13 @@ void OptionView::initUI() m_copyPathLabel->installEventFilter(this); m_optionLyt->addWidget(m_copyPathLabel); + m_installLabel = new QLabel(m_optionFrame); + m_installLabel->setText(tr("Install")); //复制所在路径 + m_installLabel->setStyleSheet("QLabel{font-size: 14px; color: #3790FA}"); + m_installLabel->setCursor(QCursor(Qt::PointingHandCursor)); + m_installLabel->installEventFilter(this); + m_optionLyt->addWidget(m_installLabel); + m_optionLyt->addStretch(); m_optionFrame->setLayout(m_optionLyt); m_mainLyt->addWidget(m_optionFrame); @@ -159,6 +171,10 @@ void OptionView::setupOptionLabel(const int& opt) { m_copyPathLabel->show(); break; } + case Options::Install: { + m_installLabel->show(); + break; + } default: break; } @@ -171,15 +187,21 @@ void OptionView::hideOptions() m_panelLabel->hide(); m_openPathLabel->hide(); m_copyPathLabel->hide(); + m_installLabel->hide(); } /** * @brief OptionView::setupAppOptions 为应用类型的详情页构建选项表 + * @param is_installed 应用是否已安装 */ -void OptionView::setupAppOptions() { - setupOptionLabel(Options::Open); - setupOptionLabel(Options::Shortcut); - setupOptionLabel(Options::Panel); +void OptionView::setupAppOptions(bool is_installed) { + if (is_installed) { + setupOptionLabel(Options::Open); + setupOptionLabel(Options::Shortcut); + setupOptionLabel(Options::Panel); + } else { + setupOptionLabel(Options::Install); + } } /** @@ -289,6 +311,21 @@ bool OptionView::eventFilter(QObject *watched, QEvent *event){ m_copyPathLabel->setStyleSheet("QLabel{font-size: 14px; color: #3790FA}"); return true; } + } else if (m_installLabel && watched == m_installLabel) { + if (event->type() == QEvent::MouseButtonPress) { + m_installLabel->setStyleSheet("QLabel{font-size: 14px; color: #296CD9;}"); + return true; + } else if (event->type() == QEvent::MouseButtonRelease) { + m_installLabel->setStyleSheet("QLabel{font-size: 14px; color: #3790FA}"); + Q_EMIT this->onOptionClicked(Options::Install); + return true; + } else if (event->type() == QEvent::Enter) { + m_installLabel->setStyleSheet("QLabel{font-size: 14px; color: #40A9FB;}"); + return true; + } else if (event->type() == QEvent::Leave) { + m_installLabel->setStyleSheet("QLabel{font-size: 14px; color: #3790FA}"); + return true; + } } return QObject::eventFilter(watched, event); } diff --git a/src/control/option-view.h b/src/control/option-view.h index ca71092..03bc57a 100644 --- a/src/control/option-view.h +++ b/src/control/option-view.h @@ -34,14 +34,15 @@ class OptionView : public QWidget public: explicit OptionView(QWidget *); ~OptionView(); - void setupOptions(const int&); + void setupOptions(const int&, bool is_appInstalled = true); enum Options { Open, Shortcut, Panel, OpenPath, - CopyPath + CopyPath, + Install }; protected: @@ -49,7 +50,7 @@ protected: private: void initUI(); - void setupAppOptions(); + void setupAppOptions(bool); void setupFileOptions(); void setupDirOptions(); void setupSettingOptions(); @@ -66,6 +67,7 @@ private: QLabel * m_panelLabel = nullptr; QLabel * m_openPathLabel = nullptr; QLabel * m_copyPathLabel = nullptr; + QLabel * m_installLabel = nullptr; Q_SIGNALS: void onOptionClicked(const int&); diff --git a/src/control/search-detail-view.cpp b/src/control/search-detail-view.cpp index 496b567..c8e7912 100644 --- a/src/control/search-detail-view.cpp +++ b/src/control/search-detail-view.cpp @@ -173,6 +173,43 @@ void SearchDetailView::setWebWidget(const QString& keyword) m_webView->show(); } +void SearchDetailView::setAppWidget(const QString &appname, const QString &path, const QString &iconpath) +{ + m_type = SearchListView::ResType::App; + m_path = path; + m_name = appname; + m_isEmpty = false; + clearLayout(); + m_iconLabel->show(); + m_nameFrame->show(); + m_nameLabel->show(); + m_typeLabel->show(); + m_hLine->show(); + + QIcon icon; + if (path.isEmpty() || path == "") { + icon = QIcon(iconpath); + m_optionView->setupOptions(m_type, false); + } else { + m_optionView->setupOptions(m_type, true); + if (QIcon::fromTheme(iconpath).isNull()) { + icon = QIcon(":/res/icons/desktop.png"); + } else { + icon = QIcon::fromTheme(iconpath); + } + } + m_optionView->show(); + + m_iconLabel->setPixmap(icon.pixmap(icon.actualSize(QSize(96, 96)))); + QFontMetrics fontMetrics = m_nameLabel->fontMetrics(); + QString showname = fontMetrics.elidedText(appname, Qt::ElideRight, 215); //当字体长度超过215时显示为省略号 + m_nameLabel->setText(showname); + if (QString::compare(showname, appname)) { + m_nameLabel->setToolTip(appname); + } + m_typeLabel->setText(tr("Application")); +} + void SearchDetailView::closeWebWidget() { if (m_webView) { @@ -234,7 +271,7 @@ void SearchDetailView::setupWidget(const int& type, const QString& path) { m_hLine->show(); //文件和文件夹有一个额外的详情区域 - if (type == SearchListView::ResType::Dir || type == SearchListView::ResType::File || type == SearchListView::ResType::Content || type == SearchListView::ResType::Best) { + if (type == SearchListView::ResType::Dir || type == SearchListView::ResType::File || type == SearchListView::ResType::Content) { m_detailFrame->show(); if (isContent) { //文件内容区域 m_contentLabel->show(); @@ -276,21 +313,7 @@ void SearchDetailView::setupWidget(const int& type, const QString& path) { //根据不同类型的搜索结果切换加载图片和名称的方式 switch (type) { - case SearchListView::ResType::App : { - QIcon icon = FileUtils::getAppIcon(path); - m_iconLabel->setPixmap(icon.pixmap(icon.actualSize(QSize(96, 96)))); - QFontMetrics fontMetrics = m_nameLabel->fontMetrics(); - QString wholeName = FileUtils::getAppName(path); - QString name = fontMetrics.elidedText(wholeName, Qt::ElideRight, 215); //当字体长度超过215时显示为省略号 - m_nameLabel->setText(name); - if (QString::compare(name, wholeName)) { - m_nameLabel->setToolTip(wholeName); - } - m_typeLabel->setText(tr("Application")); - break; - } case SearchListView::ResType::Content: - case SearchListView::ResType::Best: case SearchListView::ResType::Dir : case SearchListView::ResType::File : { QIcon icon = FileUtils::getFileIcon(QString("file://%1").arg(path)); @@ -347,6 +370,9 @@ void SearchDetailView::execActions(const int& type, const int& option, const QSt copyPathAction(path); break; } + case OptionView::Options::Install: { + installAppAction(m_name); //未安装应用点击此选项,不使用路径作为参数,而是使用软件名 + } default: break; } @@ -552,6 +578,18 @@ bool SearchDetailView::copyPathAction(const QString& path) { return true; } +/** + * @brief SearchDetailView::installAppAction 执行打开软件商店操作 + * @param name + * @return + */ +bool SearchDetailView::installAppAction(const QString & name) +{ + //打开软件商店下载此软件 + QProcess process; + process.startDetached(QString("kylin-software-center -find %1").arg(name)); +} + void SearchDetailView::paintEvent(QPaintEvent *event) { Q_UNUSED(event) diff --git a/src/control/search-detail-view.h b/src/control/search-detail-view.h index 4e9ab8b..bb2b658 100644 --- a/src/control/search-detail-view.h +++ b/src/control/search-detail-view.h @@ -44,6 +44,7 @@ public: int getType(); bool isContent = false; void setWebWidget(const QString&); + void setAppWidget(const QString &name, const QString &path, const QString &icon); void closeWebWidget(); protected: @@ -58,12 +59,14 @@ private: bool addPanelShortcut(const QString&); bool openPathAction(const QString&); bool copyPathAction(const QString&); + bool installAppAction(const QString&); QString getHtmlText(const QString&, const QString&); QString escapeHtml(const QString&); bool writeConfigFile(const QString&); bool m_isEmpty = true; int m_type = 0; QString m_path = 0; + QString m_name = 0; //目前只有未安装应用在打开软件商店时需要此参数 void initUI(); QLabel * m_iconLabel = nullptr; diff --git a/src/control/search-list-view.cpp b/src/control/search-list-view.cpp index 9922615..6a4da7f 100644 --- a/src/control/search-list-view.cpp +++ b/src/control/search-list-view.cpp @@ -88,6 +88,16 @@ void SearchListView::setList(QStringList list) this->setFixedHeight(m_item->getCurrentSize() * rowheight + 4); } +void SearchListView::setAppList(const QStringList &pathlist, const QStringList &iconlist) +{ + m_model->setAppList(pathlist, iconlist); +} + +void SearchListView::appendBestItem(const QPair &pair) +{ + m_model->appendBestItem(pair); +} + /** * @brief SearchListView::removeItem */ @@ -153,7 +163,8 @@ int SearchListView::getCurrentType() { case SearchItem::SearchType::Web: return ResType::Web; default: //All或者Best的情况,需要自己判断文件类型 - return getResType(m_item->m_pathlist.at(this->currentIndex().row())); +// return getResType(m_item->m_pathlist.at(this->currentIndex().row())); + return ResType::Best; break; } } @@ -165,17 +176,12 @@ int SearchListView::getCurrentType() { */ int SearchListView::getResType(const QString& path) { if (path.endsWith(".desktop")) { -// qDebug()<<"qDebug: One row selected, its path is "<&); void removeItem(QString); void clear(); void setKeyword(QString); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 474ea3f..f0ec91b 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -96,19 +96,25 @@ MainWindow::MainWindow(QWidget *parent) : m_search_result_dir = new QQueue; m_search_result_content = new QQueue>; m_search_result_thread = new SearchResult(this); + m_seach_app_thread = new SearchAppThread(this); // m_search_result_thread->start(); connect(m_search_result_thread, &SearchResult::searchResultFile, this, [ = ](QString path) { - qDebug()<<"Append a file into list: "<appendSearchItem(SearchItem::SearchType::Files, path); }); connect(m_search_result_thread, &SearchResult::searchResultDir, this, [ = ](QString path) { - qDebug()<<"Append a dir into list: "<appendSearchItem(SearchItem::SearchType::Dirs, path); }); connect(m_search_result_thread, &SearchResult::searchResultContent, this, [ = ](QPair pair) { - qDebug()<<"Append a file content into list: "<appendSearchItem(SearchItem::SearchType::Contents, pair.first, pair.second); }); + qRegisterMetaType>("QVector"); + connect(m_seach_app_thread, &SearchAppThread::searchResultApp, this, [ = ](const QVector& applist) { + qDebug()<<"Append applist: "<setAppList(applist); + }); m_sys_tray_icon = new QSystemTrayIcon(this); m_sys_tray_icon->setIcon(QIcon::fromTheme("system-search-symbolic")); @@ -219,6 +225,7 @@ void MainWindow::initUi() m_search_result_thread->requestInterruption(); m_search_result_thread->quit(); } + m_seach_app_thread->stop(); m_contentFrame->setCurrentIndex(0); } else { m_contentFrame->setCurrentIndex(1); @@ -291,27 +298,22 @@ void MainWindow::primaryScreenChangedSlot(QScreen *screen) * @brief searchContent 搜索关键字 * @param searchcontent */ -void MainWindow::searchContent(QString searchcontent){ - m_app_setting_lists.clear(); - m_contentFrame->setKeyword(searchcontent); +void MainWindow::searchContent(QString keyword){ + m_contentFrame->setKeyword(keyword); -// m_search_result_file->clear(); -// m_search_result_dir->clear(); -// m_search_result_content->clear(); - - AppMatch * appMatchor = new AppMatch(this); + //设置搜索 SettingsMatch * settingMatchor = new SettingsMatch(this); - //应用与设置搜索 - QStringList appList; - appList = appMatchor->startMatchApp(searchcontent); QStringList settingList; - settingList = settingMatchor->startMatchApp(searchcontent); - m_app_setting_lists.append(appList); - m_app_setting_lists.append(settingList); - m_contentFrame->refreshSearchList(m_app_setting_lists); + settingList = settingMatchor->startMatchApp(keyword); + m_contentFrame->resetSearchList(); + m_contentFrame->setSettingList(settingList); + + //应用搜索 + m_seach_app_thread->stop(); + m_seach_app_thread->startSearch(keyword); //文件、文件夹、内容搜索 - this->m_searcher->onKeywordSearch(searchcontent, m_search_result_file, m_search_result_dir, m_search_result_content); + this->m_searcher->onKeywordSearch(keyword, m_search_result_file, m_search_result_dir, m_search_result_content); } /** @@ -385,6 +387,7 @@ bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, long *r m_contentFrame->closeWebView(); m_search_result_thread->requestInterruption(); m_search_result_thread->quit(); + m_seach_app_thread->stop(); break; } @@ -398,6 +401,7 @@ void MainWindow::keyPressEvent(QKeyEvent *event) m_contentFrame->closeWebView(); m_search_result_thread->requestInterruption(); m_search_result_thread->quit(); + m_seach_app_thread->stop(); } return QWidget::keyPressEvent(event); } diff --git a/src/mainwindow.h b/src/mainwindow.h index d291317..ce0d67e 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -48,6 +48,7 @@ #include "index/index-generator.h" #include "settings-widget.h" #include "libsearch.h" +#include "search-app-thread.h" class SearchResult; class MainWindow : public QMainWindow @@ -87,13 +88,13 @@ private: QGSettings * m_transparency_gsettings = nullptr; double getTransparentData(); - QVector m_app_setting_lists; QStringList m_dirList; QQueue *m_search_result_file = nullptr; QQueue *m_search_result_dir = nullptr; QQueue> *m_search_result_content = nullptr; SearchResult * m_search_result_thread = nullptr; + SearchAppThread * m_seach_app_thread = nullptr; FileSearcher* m_searcher = nullptr; QSystemTrayIcon *m_sys_tray_icon; diff --git a/src/model/search-item-model.cpp b/src/model/search-item-model.cpp index d9e46ac..90e4e2e 100644 --- a/src/model/search-item-model.cpp +++ b/src/model/search-item-model.cpp @@ -145,7 +145,7 @@ void SearchItemModel::appendItem(QString path) { this->beginResetModel(); m_item->m_pathlist << path; this->endResetModel(); -// this->insertRow(rowCount(QModelIndex()) - 1); + // this->insertRow(rowCount(QModelIndex()) - 1); } /** @@ -159,6 +159,23 @@ void SearchItemModel::setList(QStringList list) this->endResetModel(); } +void SearchItemModel::setAppList(const QStringList &pathlist, const QStringList &iconlist) +{ + this->beginResetModel(); + m_item->m_app_pathlist = pathlist; + m_item->m_app_iconlist = iconlist; + this->endResetModel(); +} + +/** + * @brief SearchItemModel::insertBestItem 向最佳匹配列表添加一项 + * @param pair <类型,路径或名称> + */ +void SearchItemModel::appendBestItem(const QPair & pair) +{ + m_item->m_bestList.append(pair); +} + /** * @brief SearchItemModel::removeItem */ @@ -172,3 +189,17 @@ void SearchItemModel::clear() m_item->clear(); this->endResetModel(); } + +/** + * @brief SearchItemModel::setBestAppIcon 设置最佳匹配应用的图标 + * @param str 图标名称或路径,应用安装时为图标名,未安装时为路径 + * @param is_installed 应用是否已安装 + */ +void SearchItemModel::setBestAppIcon(const QString &str, const bool & is_installed) +{ + if (is_installed) { + m_item->m_bestAppIcon = QIcon::fromTheme(str); + } else { + m_item->m_bestAppIcon = QIcon(str); + } +} diff --git a/src/model/search-item-model.h b/src/model/search-item-model.h index 3c0cc13..1b6b285 100644 --- a/src/model/search-item-model.h +++ b/src/model/search-item-model.h @@ -54,8 +54,11 @@ public: void appendItem(QString); void setList(QStringList); + void setAppList(const QStringList&, const QStringList&); + void appendBestItem(const QPair&); void removeItem(QString); void clear(); + void setBestAppIcon(const QString &, const bool &); private : SearchItem * m_item = nullptr; diff --git a/src/model/search-item.cpp b/src/model/search-item.cpp index e4dece7..dedafe5 100644 --- a/src/model/search-item.cpp +++ b/src/model/search-item.cpp @@ -45,18 +45,23 @@ QIcon SearchItem::getIcon(int index) { case Dirs : case Files : //文件,返回文件图标 return FileUtils::getFileIcon(QString("file://%1").arg(m_pathlist.at(index))); - case Apps : //应用,返回应用图标 - return FileUtils::getAppIcon(m_pathlist.at(index)); - case Best : {//最佳匹配,含全部类型,需要自己判断,返回不同类型的图标 -// return QIcon(":/res/icons/edit-find-symbolic.svg"); - if (m_pathlist.at(index).endsWith(".desktop")) { - return FileUtils::getAppIcon(m_pathlist.at(index)); - } else if (QFileInfo(m_pathlist.at(index)).isFile() || QFileInfo(m_pathlist.at(index)).isDir()) { - return FileUtils::getFileIcon(QString("file://%1").arg(m_pathlist.at(index))); + case Apps : {//应用,返回应用图标 +// return FileUtils::getAppIcon(m_pathlist.at(index)); + if (m_app_pathlist.length() > index && m_app_pathlist.at(index) == "") { //未安装,存储的是图标路径 + return QIcon(m_app_iconlist.at(index)); + } else if (m_app_pathlist.length() > index) { //已安装,存储的是图标名 + if (QIcon::fromTheme(m_app_iconlist.at(index)).isNull()) { + return QIcon(":/res/icons/desktop.png"); + } else { + return QIcon::fromTheme(m_app_iconlist.at(index)); + } } else { - return FileUtils::getSettingIcon(m_pathlist.at(index), false); + return QIcon(":/res/icons/desktop.png"); } } + case Best : {//最佳匹配,含全部类型,需要自己判断,返回不同类型的图标 + return getBestIcon(index); + } default: return QIcon(":/res/icons/edit-find-symbolic.svg"); } @@ -77,22 +82,66 @@ QString SearchItem::getName(int index) { case Dirs : case Files : //文件,返回文件名 return FileUtils::getFileName(m_pathlist.at(index)); - case Apps : //应用,返回应用名 - return FileUtils::getAppName(m_pathlist.at(index)); + case Apps : {//应用,返回应用名 + return m_pathlist.at(index); + } case Best : //最佳匹配,含全部类型,需要自己判断,返回不同类型的名称 -// return m_pathlist.at(index); - if (m_pathlist.at(index).endsWith(".desktop")) { - return FileUtils::getAppName(m_pathlist.at(index)); - } else if (QFileInfo(m_pathlist.at(index)).isFile() || QFileInfo(m_pathlist.at(index)).isDir()) { - return FileUtils::getFileName(m_pathlist.at(index)); - } else { - return FileUtils::getSettingName(m_pathlist.at(index)); - } + return getBestName(index); default: return m_pathlist.at(index); } } +/** + * @brief SearchItem::getBestIcon 获取最佳匹配结果的图标 + * @param index 索引行 + * @return + */ +QIcon SearchItem::getBestIcon(const int &index) +{ +// if (m_pathlist.at(index).endsWith(".desktop")) { +// return FileUtils::getAppIcon(m_pathlist.at(index)); +// } else if (QFileInfo(m_pathlist.at(index)).isFile() || QFileInfo(m_pathlist.at(index)).isDir()) { +// return FileUtils::getFileIcon(QString("file://%1").arg(m_pathlist.at(index))); +// } else { +// return FileUtils::getSettingIcon(m_pathlist.at(index), false); +// } + if (m_bestList.isEmpty() || !m_bestList.length() > index) return QIcon::fromTheme("unknown"); + switch(m_bestList.at(index).first) { + case Apps: { + return this->m_bestAppIcon; +// return FileUtils::getAppIcon(m_pathlist.at(index)); + } + case Settings: { + return FileUtils::getSettingIcon(m_pathlist.at(index), false); + } + default: { + return FileUtils::getFileIcon(QString("file://%1").arg(m_pathlist.at(index))); + } + } +} + +/** + * @brief SearchItem::getBestName 获取最佳匹配结果的名称 + * @param index 索引行 + * @return + */ +QString SearchItem::getBestName(const int &index) +{ + if (m_bestList.isEmpty() || !m_bestList.length() > index) return ""; + switch(m_bestList.at(index).first) { + case Apps: { + return m_bestList.at(index).second; + } + case Settings: { + return FileUtils::getSettingName(m_pathlist.at(index)); + } + default: { + return FileUtils::getFileName(m_pathlist.at(index)); + } + } +} + /** * @brief SearchItem::setSearchList 存入搜索结果列表 * @param type 搜索类型 @@ -117,4 +166,7 @@ int SearchItem::getCurrentSize() { void SearchItem::clear() { m_pathlist.clear(); + m_app_pathlist.clear(); + m_app_iconlist.clear(); + m_bestList.clear(); } diff --git a/src/model/search-item.h b/src/model/search-item.h index 2cd48c2..f3b5b4f 100644 --- a/src/model/search-item.h +++ b/src/model/search-item.h @@ -56,9 +56,16 @@ private: int m_searchtype = 0; QStringList m_pathlist; + QStringList m_app_pathlist; + QStringList m_app_iconlist; + QList> m_bestList; + + QIcon m_bestAppIcon = QIcon::fromTheme("unknown"); //由于未安装应用与已安装应用获取图标方式不一致,故引入此变量直接存储最佳匹配应用图标 QIcon getIcon(int); QString getName(int); + QIcon getBestIcon(const int &); + QString getBestName(const int &); Q_SIGNALS: diff --git a/src/search-app-thread.cpp b/src/search-app-thread.cpp new file mode 100644 index 0000000..bdd4399 --- /dev/null +++ b/src/search-app-thread.cpp @@ -0,0 +1,54 @@ +#include "search-app-thread.h" + +SearchAppThread::SearchAppThread(QObject * parent) : QThread(parent) +{ + m_appMatch = new AppMatch(this); +} + +SearchAppThread::~SearchAppThread() +{ + if (m_appMatch) { + delete m_appMatch; + m_appMatch = NULL; + } +} + +/** + * @brief SearchAppThread::startSearch 激活线程 + * @param keyword 关键词 + */ +void SearchAppThread::startSearch(const QString & keyword) +{ + m_keyword = keyword; + m_stop = false; + this->start(); +} + +void SearchAppThread::stop() +{ + m_stop = true; + this->quit(); + this->wait(); +} + +void SearchAppThread::run() +{ + //nameList:应用名,pathList:已安装的是.desktop路径,未安装为空,iconList:已安装的是图标名,未安装的是图标路径 + QStringList nameList, pathList, iconList; + QVector applist; + QMap> appList; + appList = m_appMatch->startMatchApp(m_keyword); + QMapIterator> iter(appList); + while(iter.hasNext()) + { + iter.next(); + nameList << iter.key(); + pathList << iter.value().at(0); + iconList << iter.value().at(1); + } + applist.append(nameList); + applist.append(pathList); + applist.append(iconList); + if (!m_stop) + Q_EMIT this->searchResultApp(applist); +} diff --git a/src/search-app-thread.h b/src/search-app-thread.h new file mode 100644 index 0000000..4ef40de --- /dev/null +++ b/src/search-app-thread.h @@ -0,0 +1,25 @@ +#ifndef SEARCHAPPTHREAD_H +#define SEARCHAPPTHREAD_H +#include +#include "libsearch.h" + +class SearchAppThread : public QThread +{ + Q_OBJECT + +public: + SearchAppThread(QObject * parent = nullptr); + ~SearchAppThread(); + void startSearch(const QString&); + void stop(); +protected: + void run() override; +private: + AppMatch * m_appMatch = nullptr; + QString m_keyword; + bool m_stop = false; +Q_SIGNALS: + void searchResultApp(const QVector&); +}; + +#endif // SEARCHAPPTHREAD_H diff --git a/src/src.pro b/src/src.pro index 3c463b9..5e44f23 100644 --- a/src/src.pro +++ b/src/src.pro @@ -29,6 +29,7 @@ SOURCES += \ input-box.cpp \ main.cpp \ mainwindow.cpp \ + search-app-thread.cpp \ search-result.cpp \ settings-widget.cpp \ xatom-helper.cpp @@ -38,6 +39,7 @@ HEADERS += \ content-widget.h \ input-box.h \ mainwindow.h \ + search-app-thread.h \ search-result.h \ settings-widget.h \ xatom-helper.h diff --git a/translations/ukui-search/bo.ts b/translations/ukui-search/bo.ts index bf83c5a..877541e 100644 --- a/translations/ukui-search/bo.ts +++ b/translations/ukui-search/bo.ts @@ -4,57 +4,57 @@ ContentWidget - + Recently Opened - + Open Quickly - + Commonly Used - + Apps - + Settings - + Files - + Dirs - + File Contents - + Best Matches - + Web Pages - + Unknown @@ -75,12 +75,12 @@ - + Global Search - + Search @@ -88,35 +88,40 @@ OptionView - + Open - + Add Shortcut to Desktop - + Add Shortcut to Panel - + Open path - + Copy path + + + Install + + QObject - + ukui-search is already running! @@ -132,22 +137,22 @@ SearchDetailView - + Path - + Last time modified - + Application - + Document @@ -155,55 +160,55 @@ SettingsWidget - - - + + + Search - - + + ... - + Following folders will not be searched. You can set it by adding and removing folders. - + Add ignored folders - + Please select search engine you preferred. - + baidu - + sougou - + 360 - + Cancel - + Creating ... @@ -213,97 +218,97 @@ - + <h2>Settings</h2> - + <h3>Index State</h3> - + <h3>File Index Settings</h3> - + <h3>Search Engine Settings</h3> - + Whether to delete this directory? - + Yes - + No - + Done - + Index Entry: %1 - + Directories - + select blocked folder - + Select - + Position: - + FileName: - + FileType: - + Choosen path is Empty! - + Choosen path is not in "home"! - + Its' parent folder has been blocked! - + Set blocked folder failed! diff --git a/translations/ukui-search/tr.ts b/translations/ukui-search/tr.ts index e37d96b..ff70791 100644 --- a/translations/ukui-search/tr.ts +++ b/translations/ukui-search/tr.ts @@ -4,57 +4,57 @@ ContentWidget - + Recently Opened Yeni Açılan - + Open Quickly Hızlı Aç - + Commonly Used Genel olarak kullanılan - + Apps Uygulamalar - + Settings Ayarlar - + Files Dosyalar - + Dirs Dizinler - + File Contents Dosya İçeriği - + Best Matches En İyi Eşleşen - + Web Pages - + Unknown Bilinmeyen @@ -75,12 +75,12 @@ ukui-ara - + Global Search Genel Arama - + Search Ara @@ -88,35 +88,40 @@ OptionView - + Open - + Add Shortcut to Desktop Masaüstüne Kısayol Ekle - + Add Shortcut to Panel Panele Kısayol Ekle - + Open path Yolu aç - + Copy path Yolu kopyala + + + Install + + QObject - + ukui-search is already running! ukui-bul zaten çalışıyor! @@ -132,22 +137,22 @@ SearchDetailView - + Path Yol - + Last time modified Son değiştirilme zamanı - + Application Uygulama - + Document Belge @@ -155,55 +160,55 @@ SettingsWidget - - - + + + Search Ara - - + + ... ... - + Following folders will not be searched. You can set it by adding and removing folders. Aşağıdaki klasörler aranmayacaktır. Klasör ekleyip kaldırarak ayarlayabilirsiniz. - + Add ignored folders Göz ardı edilen klasörleri ekleyin - + Please select search engine you preferred. Lütfen tercih ettiğiniz arama motorunu seçin. - + baidu - + sougou - + 360 - + Cancel İptal - + Creating ... Oluşturuluyor... @@ -213,97 +218,97 @@ ukui-bul - + <h2>Settings</h2> <h2>Ayarlar</h2> - + <h3>Index State</h3> <h3>Dizin Durumu</h3> - + <h3>File Index Settings</h3> <h3>Dosya Dizini Ayarları</h3> - + <h3>Search Engine Settings</h3> <h3>SArama Motoru Ayarları</h3> - + Whether to delete this directory? Bu dizini silinsin mi? - + Yes - + No - + Done Tamam - + Index Entry: %1 Dizin Girişi: %1 - + Directories Dizinler - + select blocked folder engellenen klasörü seç - + Select Seç - + Position: Pozisyon: - + FileName: Dosya Adı: - + FileType: Dosya Türü: - + Choosen path is Empty! - + Choosen path is not in "home"! - + Its' parent folder has been blocked! - + Set blocked folder failed! diff --git a/translations/ukui-search/zh_CN.ts b/translations/ukui-search/zh_CN.ts index 21cb8c7..50347d5 100644 --- a/translations/ukui-search/zh_CN.ts +++ b/translations/ukui-search/zh_CN.ts @@ -4,57 +4,57 @@ ContentWidget - + Recently Opened 最近 - + Open Quickly 快速 - + Commonly Used 常用 - + Apps 应用 - + Settings 配置项 - + Files 文件 - + Dirs 文件夹 - + File Contents 文件内容 - + Best Matches 最佳匹配 - + Web Pages 网页 - + Unknown 未知 @@ -75,12 +75,12 @@ 搜索 - + Global Search 搜索 - + Search 搜索 @@ -88,35 +88,40 @@ OptionView - + Open 打开 - + Add Shortcut to Desktop 添加到桌面快捷方式 - + Add Shortcut to Panel 添加到任务栏快捷方式 - + Open path 打开文件所在路径 - + Copy path 复制文件路径 + + + Install + 安装 + QObject - + ukui-search is already running! @@ -132,22 +137,22 @@ SearchDetailView - + Path 路径 - + Last time modified 上次修改时间 - + Application 应用 - + Document 文件 @@ -155,110 +160,110 @@ SettingsWidget - - - + + + Search 搜索 - + <h2>Settings</h2> <h2>设置</h2> - + <h3>Index State</h3> <h3>索引状态</h3> - - + + ... - + <h3>File Index Settings</h3> <h3>文件索引设置</h3> - + Following folders will not be searched. You can set it by adding and removing folders. 搜索将不再查看以下文件夹。通过增加和删除文件夹可进行文件索引设置。 - + Add ignored folders 添加文件夹至黑名单 - + <h3>Search Engine Settings</h3> <h3>搜索引擎设置</h3> - + Please select search engine you preferred. 设置互联网搜索引擎 - + baidu 百度 - + sougou 搜狗 - + 360 360 - + Whether to delete this directory? 是否要删除此目录 - + Yes 是(Y) - + No 否(N) - + Cancel 取消 - + Choosen path is Empty! 选择的路径不存在! - + Choosen path is not in "home"! 请选择家目录下的文件夹! - + Its' parent folder has been blocked! 父文件夹已被屏蔽! - + Set blocked folder failed! - + Creating ... 正在索引 @@ -268,42 +273,42 @@ 搜索 - + Done 索引完成 - + Index Entry: %1 索引项: %1 - + Directories 文件夹 - + select blocked folder 选择屏蔽文件夹 - + Select 选择 - + Position: 位置: - + FileName: 名称: - + FileType: 类型: