diff --git a/icons/star_blue_other.svg b/icons/star_blue_other.svg new file mode 100644 index 000000000..2cd5e4fb3 --- /dev/null +++ b/icons/star_blue_other.svg @@ -0,0 +1,127 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/star_other.svg b/icons/star_other.svg new file mode 100644 index 000000000..8c2e8d5a0 --- /dev/null +++ b/icons/star_other.svg @@ -0,0 +1,167 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources.qrc b/resources.qrc index 3120262bc..b31b35f50 100644 --- a/resources.qrc +++ b/resources.qrc @@ -75,6 +75,8 @@ icons/sources.png icons/star.svg icons/star_blue.svg + icons/star_other.svg + icons/star_blue_other.svg icons/system-search.svg icons/windows-list.svg icons/wizard.svg diff --git a/src/common/globalbroadcaster.hh b/src/common/globalbroadcaster.hh index 0be64a5c2..e8a241f48 100644 --- a/src/common/globalbroadcaster.hh +++ b/src/common/globalbroadcaster.hh @@ -39,7 +39,8 @@ public: QString translateLineText{}; //hold the dictionary id; QSet< QString > collapsedDicts; - QMap< QString, QSet< QString > > folderFavoritesMap; + //key hold the headword, value holds the folders. + QMap< QString, QSet< QString > > wordFavoriteFolderMap; QMap< unsigned, QString > groupFolderMap; PronounceEngine pronounce_engine; QString getAbbrName( QString const & text ); diff --git a/src/ui/favoritemanager.cc b/src/ui/favoritemanager.cc new file mode 100644 index 000000000..e5afd1de7 --- /dev/null +++ b/src/ui/favoritemanager.cc @@ -0,0 +1,28 @@ +// +// Created by xiaoyifang on 2025/2/21. +// + +#include "favoritemanager.hh" +#include "globalbroadcaster.hh" +FavoriteType FavoriteManager::determineFavoriteType( const QString & word, unsigned groupId ) +{ + QString folder = GlobalBroadcaster::instance()->groupFolderMap[ groupId ]; + return determineFavoriteType( word, folder ); +} + +FavoriteType FavoriteManager::determineFavoriteType( const QString & word, const QString & folder ) +{ + if ( !GlobalBroadcaster::instance()->wordFavoriteFolderMap.contains( word ) ) { + return FavoriteType::EMPTY; + } + + if ( GlobalBroadcaster::instance()->wordFavoriteFolderMap[ word ].contains( folder ) ) { + if ( GlobalBroadcaster::instance()->wordFavoriteFolderMap[ word ].size() == 1 ) { + return FavoriteType::FULL; + } + else { + return FavoriteType::FULL_OTHER; + } + } + return FavoriteType::EMPTY_OTHER; +} diff --git a/src/ui/favoritemanager.hh b/src/ui/favoritemanager.hh new file mode 100644 index 000000000..58c6e4817 --- /dev/null +++ b/src/ui/favoritemanager.hh @@ -0,0 +1,21 @@ +/* This file is (c) 2025 gd-ng community +* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */ + +#pragma once + +#include +enum class FavoriteType { + EMPTY, + //current group is empty while other group is not empty + EMPTY_OTHER, + FULL, + FULL_OTHER +}; + +class FavoriteManager +{ + +public: + static FavoriteType determineFavoriteType( QString const & word, unsigned group ); + static FavoriteType determineFavoriteType( const QString & word, const QString & folder ); +}; diff --git a/src/ui/favoritespanewidget.cc b/src/ui/favoritespanewidget.cc index f9b80d8e1..ef412f76f 100644 --- a/src/ui/favoritespanewidget.cc +++ b/src/ui/favoritespanewidget.cc @@ -274,12 +274,12 @@ void FavoritesPaneWidget::clearAllItems() void FavoritesPaneWidget::addHeadword( QString const & path, QString const & headword ) { m_favoritesModel->addNewHeadword( path, headword ); - GlobalBroadcaster::instance()->folderFavoritesMap[ path ].insert( headword ); + GlobalBroadcaster::instance()->wordFavoriteFolderMap[ headword ].insert( path ); } bool FavoritesPaneWidget::removeHeadword( QString const & path, QString const & headword ) { - GlobalBroadcaster::instance()->folderFavoritesMap[ path ].remove( headword ); + GlobalBroadcaster::instance()->wordFavoriteFolderMap[ headword ].remove( path ); return m_favoritesModel->removeHeadword( path, headword ); } @@ -761,7 +761,7 @@ void FavoritesModel::addFolder( TreeItem * parent, QDomNode & node ) } parent->appendChild( new TreeItem( word, parent, TreeItem::Word ) ); - GlobalBroadcaster::instance()->folderFavoritesMap[ parent->data().toString() ].insert( word ); + GlobalBroadcaster::instance()->wordFavoriteFolderMap[ word ].insert( parent->data().toString() ); } } dirty = true; diff --git a/src/ui/mainwindow.cc b/src/ui/mainwindow.cc index 5d6606e94..9b782414a 100644 --- a/src/ui/mainwindow.cc +++ b/src/ui/mainwindow.cc @@ -54,6 +54,7 @@ #include #include "globalregex.hh" +#include "favoritemanager.hh" #ifdef Q_OS_MAC #include "macos/macmouseover.hh" @@ -176,8 +177,10 @@ MainWindow::MainWindow( Config::Class & cfg_ ): headwordsDlg( nullptr ), ftsIndexing( dictionaries ), ftsDlg( nullptr ), - starIcon( ":/icons/star.svg" ), - blueStarIcon( ":/icons/star_blue.svg" ) + emptyStarIcon( ":/icons/star.svg" ), + fullStarIcon( ":/icons/star_blue.svg" ), + emptyOtherStarIcon( ":/icons/star_other.svg" ), + fullOtherStarIcon( ":/icons/star_blue_other.svg" ) { if ( QThreadPool::globalInstance()->maxThreadCount() < MIN_THREAD_COUNT ) { QThreadPool::globalInstance()->setMaxThreadCount( MIN_THREAD_COUNT ); @@ -298,7 +301,7 @@ MainWindow::MainWindow( Config::Class & cfg_ ): navToolbar->widgetForAction( navToolbar->addSeparator() )->setObjectName( "separatorBeforeAddToFavorites" ); - addToFavorites = navToolbar->addAction( starIcon, tr( "Add current tab to Favorites" ) ); + addToFavorites = navToolbar->addAction( emptyStarIcon, tr( "Add current tab to Favorites" ) ); navToolbar->widgetForAction( addToFavorites )->setObjectName( "addToFavoritesButton" ); connect( addToFavorites, &QAction::triggered, this, &MainWindow::handleAddToFavoritesButton ); @@ -1997,18 +2000,33 @@ void MainWindow::titleChanged( ArticleView * view, QString const & title ) if ( index == ui.tabWidget->currentIndex() ) { // Set icon for "Add to Favorites" action - if ( isWordPresentedInFavorites( title, cfg.lastMainGroupId ) ) { - addToFavorites->setIcon( blueStarIcon ); - addToFavorites->setToolTip( tr( "Remove current tab from Favorites" ) ); - } - else { - addToFavorites->setIcon( starIcon ); - addToFavorites->setToolTip( tr( "Add current tab to Favorites" ) ); - } + updateFavoriteIcon( title ); updateWindowTitle(); } } +void MainWindow::updateFavoriteIcon( const QString & title ) +{ + auto favoriteType = FavoriteManager::determineFavoriteType( title, this->cfg.lastMainGroupId ); + switch ( favoriteType ) { + case FavoriteType::EMPTY: + this->addToFavorites->setIcon( this->emptyStarIcon ); + this->addToFavorites->setToolTip( tr( "Add current tab to Favorites" ) ); + break; + case FavoriteType::FULL: + this->addToFavorites->setIcon( this->fullStarIcon ); + this->addToFavorites->setToolTip( tr( "Remove current tab from Favorites" ) ); + break; + case FavoriteType::EMPTY_OTHER: + this->addToFavorites->setIcon( this->emptyOtherStarIcon ); + this->addToFavorites->setToolTip( tr( "Add current tab to Favorites" ) ); + break; + case FavoriteType::FULL_OTHER: + this->addToFavorites->setIcon( this->fullOtherStarIcon ); + this->addToFavorites->setToolTip( tr( "Remove current tab from Favorites" ) ); + break; + } +} void MainWindow::iconChanged( ArticleView * view, QIcon const & icon ) { @@ -2066,14 +2084,7 @@ void MainWindow::tabSwitched( int ) if ( view ) { headword = view->getCurrentWord(); } - if ( isWordPresentedInFavorites( headword, cfg.lastMainGroupId ) ) { - addToFavorites->setIcon( blueStarIcon ); - addToFavorites->setToolTip( tr( "Remove current tab from Favorites" ) ); - } - else { - addToFavorites->setIcon( starIcon ); - addToFavorites->setToolTip( tr( "Add current tab to Favorites" ) ); - } + updateFavoriteIcon( headword ); if ( view ) { groupList->setCurrentGroup( view->getCurrentGroupId() ); @@ -4259,7 +4270,7 @@ void MainWindow::addCurrentTabToFavorites() ui.favoritesPaneWidget->addHeadword( folder, headword ); - addToFavorites->setIcon( blueStarIcon ); + addToFavorites->setIcon( fullStarIcon ); addToFavorites->setToolTip( tr( "Remove current tab from Favorites" ) ); } @@ -4275,8 +4286,9 @@ void MainWindow::handleAddToFavoritesButton() return; } auto headword = view->getCurrentWord(); + auto favoriteType = FavoriteManager::determineFavoriteType( headword, folder ); - if ( ui.favoritesPaneWidget->isHeadwordPresent( folder, headword ) ) { + if ( favoriteType == FavoriteType::FULL || favoriteType == FavoriteType::FULL_OTHER ) { QMessageBox mb( QMessageBox::Question, "GoldenDict", tr( "Remove headword \"%1\" from Favorites?" ).arg( headword ), @@ -4284,14 +4296,24 @@ void MainWindow::handleAddToFavoritesButton() this ); if ( mb.exec() == QMessageBox::Yes ) { if ( ui.favoritesPaneWidget->removeHeadword( folder, headword ) ) { - addToFavorites->setIcon( starIcon ); + if ( favoriteType == FavoriteType::FULL ) { + addToFavorites->setIcon( emptyStarIcon ); + } + else { + addToFavorites->setIcon( emptyOtherStarIcon ); + } addToFavorites->setToolTip( tr( "Add current tab to Favorites" ) ); } } } else { ui.favoritesPaneWidget->addHeadword( folder, headword ); - addToFavorites->setIcon( blueStarIcon ); + if ( favoriteType == FavoriteType::EMPTY ) { + addToFavorites->setIcon( fullStarIcon ); + } + else { + addToFavorites->setIcon( fullOtherStarIcon ); + } addToFavorites->setToolTip( tr( "Remove current tab from Favorites" ) ); } } @@ -4341,7 +4363,7 @@ void MainWindow::addAllTabsToFavorites() auto headword = view->getCurrentWord(); ui.favoritesPaneWidget->addHeadword( folder, headword ); } - addToFavorites->setIcon( blueStarIcon ); + addToFavorites->setIcon( fullStarIcon ); addToFavorites->setToolTip( tr( "Remove current tab from Favorites" ) ); } diff --git a/src/ui/mainwindow.hh b/src/ui/mainwindow.hh index 4c805138a..81f9efca4 100644 --- a/src/ui/mainwindow.hh +++ b/src/ui/mainwindow.hh @@ -170,7 +170,7 @@ private: FTS::FullTextSearchDialog * ftsDlg; - QIcon starIcon, blueStarIcon; + QIcon emptyStarIcon, fullStarIcon, emptyOtherStarIcon, fullOtherStarIcon; LocalSchemeHandler * localSchemeHandler; IframeSchemeHandler * iframeSchemeHandler; @@ -266,6 +266,7 @@ private: bool isWordPresentedInFavorites( QString const & word, unsigned groupId ); void errorMessageOnStatusBar( const QString & errStr ); int getIconSize(); + void updateFavoriteIcon( const QString & title ); private slots: diff --git a/src/ui/scanpopup.cc b/src/ui/scanpopup.cc index 112232ae2..284f7a245 100644 --- a/src/ui/scanpopup.cc +++ b/src/ui/scanpopup.cc @@ -15,6 +15,7 @@ #define MouseOver MacMouseOver #endif #include "base_type.hh" +#include "favoritemanager.hh" static const Qt::WindowFlags defaultUnpinnedWindowFlags = @@ -1118,9 +1119,24 @@ void ScanPopup::on_sendWordToFavoritesButton_clicked() return; } unsigned groupId = ui.groupList->getCurrentGroup(); - auto current_exist = isWordPresentedInFavorites( definition->getTitle(), groupId ); - //if current_exist=false( not exist ), after click ,the word should be in the favorite which is blueStar - ui.sendWordToFavoritesButton->setIcon( !current_exist ? blueStarIcon : starIcon ); + auto favoriteType = FavoriteManager::determineFavoriteType( definition->getTitle(), groupId ); + bool current_exist = false; + switch ( favoriteType ) { + case FavoriteType::EMPTY: + ui.sendWordToFavoritesButton->setIcon( fullIcon ); + break; + case FavoriteType::EMPTY_OTHER: + ui.sendWordToFavoritesButton->setIcon( fullFullIcon ); + break; + case FavoriteType::FULL: + current_exist = true; + ui.sendWordToFavoritesButton->setIcon( emptyIcon ); + break; + case FavoriteType::FULL_OTHER: + current_exist = true; + ui.sendWordToFavoritesButton->setIcon( emptyFullIcon ); + break; + } emit sendWordToFavorites( definition->getTitle(), cfg.lastPopupGroupId, current_exist ); } @@ -1202,14 +1218,30 @@ void ScanPopup::titleChanged( ArticleView *, QString const & title ) const unsigned groupId = ui.groupList->getCurrentGroup(); // Set icon for "Add to Favorites" button - ui.sendWordToFavoritesButton->setIcon( isWordPresentedInFavorites( title, groupId ) ? blueStarIcon : starIcon ); + + auto favoriteType = FavoriteManager::determineFavoriteType( title, groupId ); + switch ( favoriteType ) { + case FavoriteType::EMPTY: + ui.sendWordToFavoritesButton->setIcon( emptyIcon ); + + break; + case FavoriteType::EMPTY_OTHER: + ui.sendWordToFavoritesButton->setIcon( emptyFullIcon ); + break; + case FavoriteType::FULL: + ui.sendWordToFavoritesButton->setIcon( fullIcon ); + break; + case FavoriteType::FULL_OTHER: + ui.sendWordToFavoritesButton->setIcon( fullFullIcon ); + break; + } } bool ScanPopup::isWordPresentedInFavorites( QString const & word, unsigned groupId ) const { QString folder = GlobalBroadcaster::instance()->groupFolderMap[ groupId ]; - return GlobalBroadcaster::instance()->folderFavoritesMap[ folder ].contains( word ); + return GlobalBroadcaster::instance()->wordFavoriteFolderMap[ word ].contains( folder ); } #ifdef HAVE_X11 diff --git a/src/ui/scanpopup.hh b/src/ui/scanpopup.hh index b5df0ab8c..9d8111254 100644 --- a/src/ui/scanpopup.hh +++ b/src/ui/scanpopup.hh @@ -160,8 +160,10 @@ private: QTimer mouseGrabPollTimer; - QIcon starIcon = QIcon( ":/icons/star.svg" ); - QIcon blueStarIcon = QIcon( ":/icons/star_blue.svg" ); + QIcon emptyIcon = QIcon( ":/icons/star.svg" ); + QIcon fullIcon = QIcon( ":/icons/star_blue.svg" ); + QIcon emptyFullIcon = QIcon( ":/icons/star_other.svg" ); + QIcon fullFullIcon = QIcon( ":/icons/star_blue_other.svg" ); void handleInputWord( QString const &, bool forcePopup = false ); void engagePopup( bool forcePopup, bool giveFocus = false );