opt: rewrite solo mode in the dictionary bar (#1073)

* action: output new syntax

* opt: dictionary bar modification,Ctrl for solo selection, Shift restore

* opt: only the first Ctrl + Click event store the existed dictionaries

* [autofix.ci] apply automated fixes

* opt: ctrl switch between single and all dictionaries

* doc: add shortcut document about solo mode

---------

Co-authored-by: YiFang Xiao <yifang.xiao@noreply.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
xiaoyifang 2023-08-21 21:04:04 +08:00 committed by GitHub
parent 8cd29d527a
commit 3359f6636a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 74 additions and 55 deletions

View file

@ -13,7 +13,7 @@ DictionaryBar::DictionaryBar( QWidget * parent,
QString const & _editDictionaryCommand,
unsigned short const & maxDictionaryRefsInContextMenu_ ):
QToolBar( tr( "&Dictionary Bar" ), parent ),
mutedDictionaries( 0 ),
mutedDictionaries( nullptr ),
configEvents( events ),
editDictionaryCommand( _editDictionaryCommand ),
maxDictionaryRefsInContextMenu( maxDictionaryRefsInContextMenu_ )
@ -52,16 +52,16 @@ void DictionaryBar::setDictionaries( vector< sptr< Dictionary::Class > > const &
clear();
dictActions.clear();
for ( unsigned x = 0; x < dictionaries.size(); ++x ) {
QIcon icon = dictionaries[ x ]->getIcon();
for ( const auto & dictionary : dictionaries ) {
QIcon icon = dictionary->getIcon();
QString dictName = QString::fromUtf8( dictionaries[ x ]->getName().c_str() );
QString dictName = QString::fromUtf8( dictionary->getName().c_str() );
QAction * action = addAction( icon, elideDictName( dictName ) );
action->setToolTip( dictName ); // Tooltip need not be shortened
QString id = QString::fromStdString( dictionaries[ x ]->getId() );
QString id = QString::fromStdString( dictionary->getId() );
action->setData( id );
@ -91,21 +91,21 @@ void DictionaryBar::showContextMenu( QContextMenuEvent * event, bool extended )
{
QMenu menu( this );
QAction * editAction = menu.addAction( QIcon( ":/icons/bookcase.svg" ), tr( "Edit this group" ) );
const QAction * editAction = menu.addAction( QIcon( ":/icons/bookcase.svg" ), tr( "Edit this group" ) );
QAction * infoAction = NULL;
QAction * headwordsAction = NULL;
QAction * editDictAction = NULL;
QAction * openDictFolderAction = NULL;
const QAction * infoAction = nullptr;
const QAction * headwordsAction = nullptr;
const QAction * editDictAction = nullptr;
const QAction * openDictFolderAction = nullptr;
QString dictFilename;
QAction * dictAction = actionAt( event->x(), event->y() );
const QAction * dictAction = actionAt( event->x(), event->y() );
if ( dictAction ) {
Dictionary::Class * pDict = NULL;
QString id = dictAction->data().toString();
for ( unsigned i = 0; i < allDictionaries.size(); i++ ) {
if ( id.compare( allDictionaries[ i ]->getId().c_str() ) == 0 ) {
pDict = allDictionaries[ i ].get();
Dictionary::Class * pDict = nullptr;
QString const id = dictAction->data().toString();
for ( const auto & dictionary : allDictionaries ) {
if ( id.compare( dictionary->getId().c_str() ) == 0 ) {
pDict = dictionary.get();
break;
}
}
@ -134,7 +134,7 @@ void DictionaryBar::showContextMenu( QContextMenuEvent * event, bool extended )
unsigned refsAdded = 0;
for ( QList< QAction * >::iterator i = dictActions.begin(); i != dictActions.end(); ++i ) {
for ( const auto & dictAction : dictActions ) {
// Enough! Or the menu would become too large.
if ( refsAdded++ >= maxDictionaryRefsInContextMenu && !extended ) {
@ -144,11 +144,11 @@ void DictionaryBar::showContextMenu( QContextMenuEvent * event, bool extended )
}
// We need new action, since the one we have has text elided
QAction * action = menu.addAction( ( *i )->icon(), ( *i )->toolTip() );
QAction * action = menu.addAction( dictAction->icon(), dictAction->toolTip() );
action->setCheckable( true );
action->setChecked( ( *i )->isChecked() );
action->setData( QVariant::fromValue( (void *)*i ) );
action->setChecked( dictAction->isChecked() );
action->setData( QVariant::fromValue( (void *)dictAction ) );
// Force "icon in menu" on all platforms, for
// usability reasons.
action->setIconVisibleInMenu( true );
@ -156,17 +156,16 @@ void DictionaryBar::showContextMenu( QContextMenuEvent * event, bool extended )
connect( this, &DictionaryBar::closePopupMenu, &menu, &QWidget::close );
QAction * result = menu.exec( event->globalPos() );
const QAction * result = menu.exec( event->globalPos() );
if ( result && result == infoAction ) {
QString id = dictAction->data().toString();
QString const id = dictAction->data().toString();
emit showDictionaryInfo( id );
return;
}
if ( result && result == headwordsAction ) {
std::string id = dictAction->data().toString().toStdString();
// TODO: use `Dictionary::class*` instead of `QString id` at action->setData to remove all similar `for` loops
std::string const id = dictAction->data().toString().toStdString();
for ( const auto & dict : allDictionaries ) {
if ( id == dict->getId() ) {
emit showDictionaryHeadwords( dict.get() );
@ -177,14 +176,14 @@ void DictionaryBar::showContextMenu( QContextMenuEvent * event, bool extended )
}
if ( result && result == openDictFolderAction ) {
QString id = dictAction->data().toString();
QString const id = dictAction->data().toString();
emit openDictionaryFolder( id );
return;
}
if ( result && result == editDictAction ) {
QString command( editDictionaryCommand );
command.replace( "%GDDICT%", "\"" + dictFilename + "\"" );
command.replace( "%GDDICT%", QString( R"("%1")" ).arg( dictFilename ) );
if ( !QProcess::startDetached( command, QStringList() ) )
QApplication::beep();
}
@ -212,11 +211,11 @@ void DictionaryBar::mutedDictionariesChanged()
setUpdatesEnabled( false );
for ( QList< QAction * >::iterator i = dictActions.begin(); i != dictActions.end(); ++i ) {
bool isUnmuted = !mutedDictionaries->contains( ( *i )->data().toString() );
for ( const auto & dictAction : dictActions ) {
bool const isUnmuted = !mutedDictionaries->contains( dictAction->data().toString() );
if ( isUnmuted != ( *i )->isChecked() )
( *i )->setChecked( isUnmuted );
if ( isUnmuted != dictAction->isChecked() )
dictAction->setChecked( isUnmuted );
}
setUpdatesEnabled( true );
@ -227,15 +226,14 @@ void DictionaryBar::actionWasTriggered( QAction * action )
if ( !mutedDictionaries )
return;
QString id = action->data().toString();
QString const id = action->data().toString();
if ( id.isEmpty() )
return; // Some weird action, not our button
if ( QApplication::keyboardModifiers() & ( Qt::ControlModifier | Qt::ShiftModifier ) ) {
// Solo mode -- either use the dictionary exclusively, or toggle
// back all dictionaries if we do that already.
// Ctrl ,solo mode with single dictionary
// Shift,toggle back the previous dictionaries
// Are we solo already?
bool isSolo = true;
@ -243,35 +241,41 @@ void DictionaryBar::actionWasTriggered( QAction * action )
// For solo, all dictionaries must be unchecked, since we're handling
// the result of the dictionary being (un)checked, and in case we were
// in solo, now we would end up with no dictionaries being checked at all.
for ( QList< QAction * >::iterator i = dictActions.begin(); i != dictActions.end(); ++i ) {
if ( ( *i )->isChecked() ) {
for ( const auto & dictAction : dictActions ) {
if ( dictAction->isChecked() ) {
isSolo = false;
break;
}
}
if ( isSolo ) {
// Restore or clear all the dictionaries
if ( QApplication::keyboardModifiers() & Qt::ShiftModifier )
if ( QApplication::keyboardModifiers() & Qt::ShiftModifier ) {
if ( enterSoloMode ) {
*mutedDictionaries = storedMutedSet;
else {
for ( QList< QAction * >::iterator i = dictActions.begin(); i != dictActions.end(); ++i )
mutedDictionaries->remove( ( *i )->data().toString() );
storedMutedSet.clear();
enterSoloMode = false;
}
storedMutedSet.clear();
}
else {
// Save dictionaries state
storedMutedSet = *mutedDictionaries;
if ( !enterSoloMode ) {
storedMutedSet = *mutedDictionaries;
enterSoloMode = true;
}
// Make dictionary solo
for ( QList< QAction * >::iterator i = dictActions.begin(); i != dictActions.end(); ++i ) {
QString dictId = ( *i )->data().toString();
if ( isSolo ) {
for ( const auto & dictAction : dictActions )
mutedDictionaries->remove( dictAction->data().toString() );
}
else {
// Make dictionary solo
for ( const auto & dictAction : dictActions ) {
QString const dictId = dictAction->data().toString();
if ( dictId == id )
mutedDictionaries->remove( dictId );
else
mutedDictionaries->insert( dictId );
if ( dictId == id )
mutedDictionaries->remove( dictId );
else
mutedDictionaries->insert( dictId );
}
}
}
configEvents.signalMutedDictionariesChanged();
@ -305,10 +309,10 @@ void DictionaryBar::dictsPaneClicked( const QString & id )
if ( !isVisible() )
return;
for ( QList< QAction * >::iterator i = dictActions.begin(); i != dictActions.end(); ++i ) {
QString dictId = ( *i )->data().toString();
for ( const auto & dictAction : dictActions ) {
QString const dictId = dictAction->data().toString();
if ( dictId == id ) {
( *i )->activate( QAction::Trigger );
dictAction->activate( QAction::Trigger );
break;
}
}

View file

@ -59,6 +59,8 @@ private:
Config::MutedDictionaries * mutedDictionaries;
Config::Events & configEvents;
Config::MutedDictionaries storedMutedSet;
bool enterSoloMode = false;
QString editDictionaryCommand;
// how many dictionaries should be shown in the context menu:
unsigned short const & maxDictionaryRefsInContextMenu;

View file

@ -53,3 +53,16 @@
| F3 | Dictionaries dialog |
| F4 | GoldenDict preferences |
| F12 | Inspector |
# Solo mode in the dictionary bar
Ctrl+Click, Enter solo mode, toggle between single & all dictionaries
Shift+Click, Exit solo mode, restore the previous dictionaries.
For example, there are 4 dictionaries A,B,C,D with ABC selected.
| Cases| Note|
|--------|--------|
| Ctrl+Click A|select A only|
| Ctrl+Click A, Ctrl+Click B | select B only|
| Ctrl+Click A, Ctrl+Click A | A,B,C,D selected(all dictionaries selected)|
| Ctrl+Click A, Shift+Click any dictionary| A,B,C selected |