goldendict-ng/dictionarybar.cc

247 lines
6.2 KiB
C++
Raw Normal View History

#include "dictionarybar.hh"
#include <QAction>
#include <QApplication>
#include <QMenu>
#include <QContextMenuEvent>
#include "dprintf.hh"
using std::vector;
DictionaryBar::DictionaryBar( QWidget * parent,
Config::MutedDictionaries & mutedDictionaries_,
Config::Events & events ):
QToolBar( tr( "Dictionary Bar" ), parent ),
mutedDictionaries( mutedDictionaries_ ),
configEvents( events )
{
setObjectName( "dictionaryBar" );
connect( &events, SIGNAL( mutedDictionariesChanged() ),
this, SLOT( mutedDictionariesChanged() ) );
connect( this, SIGNAL(actionTriggered(QAction*)),
this, SLOT(actionWasTriggered(QAction*)) );
}
static QString elideDictName( QString const & name )
{
// Some names are way too long -- we insert an ellipsis in the middle of those
int const maxSize = 33;
if ( name.size() <= maxSize )
return name;
int const pieceSize = maxSize / 2 - 1;
return name.left( pieceSize ) + QChar( 0x2026 ) + name.right( pieceSize );
}
void DictionaryBar::setDictionaries( vector< sptr< Dictionary::Class > >
const & dictionaries )
{
setUpdatesEnabled( false );
clear();
dictActions.clear();
bool use14x21 = false;
for( unsigned x = 0; x < dictionaries.size(); ++x )
{
QIcon icon = dictionaries[ x ]->getNativeIcon();
QString dictName = QString::fromUtf8( dictionaries[ x ]->
getName().c_str() );
QAction * action = addAction( icon, elideDictName( dictName ) );
action->setToolTip( dictName ); // Tooltip need not be shortened
QString id = QString::fromStdString( dictionaries[ x ]->getId() );
action->setData( id );
action->setCheckable( true );
action->setChecked( !mutedDictionaries.contains( id ) );
QList< QSize > sizes = icon.availableSizes();
for( QList< QSize >::iterator i = sizes.begin(); i != sizes.end();
++i )
if ( i->width() == 14 && i->height() == 21 )
use14x21 = true;
dictActions.append( action );
}
setIconSize( use14x21 ? QSize( 14, 21 ) : QSize( 21, 21 ) );
setUpdatesEnabled( true );
}
void DictionaryBar::contextMenuEvent( QContextMenuEvent * event )
{
QMenu menu( this );
for( QList< QAction * >::iterator i = dictActions.begin();
i != dictActions.end(); ++i )
{
// We need new action, since the one we have has text elided
QAction * action = menu.addAction( (*i)->icon(), (*i)->toolTip() );
action->setCheckable( true );
action->setChecked( (*i)->isChecked() );
action->setData( QVariant::fromValue( (void *)*i ) );
// Force "icon in menu" on all platforms, for
// usability reasons.
action->setIconVisibleInMenu( true );
}
if ( !menu.isEmpty() )
menu.addSeparator();
QAction * editAction =
menu.addAction( QIcon( ":/icons/bookcase.png" ), tr( "Edit this group" ) );
QAction * infoAction = NULL;
QAction * dictAction = actionAt( event->x(), event->y() );
if( dictAction )
infoAction = menu.addAction( tr( "Dictionary info" ) );
connect( this, SIGNAL( closePopupMenu() ), &menu, SLOT( close() ) );
QAction * result = menu.exec( event->globalPos() );
if( result && result == infoAction )
{
QString id = dictAction->data().toString();
emit showDictionaryInfo( id );
return;
}
if ( result == editAction )
emit editGroupRequested();
else
if ( result && result->data().value< void * >() )
( ( QAction * )( result->data().value< void * >() ) )->trigger();
event->accept();
}
void DictionaryBar::mutedDictionariesChanged()
{
//DPRINTF( "Muted dictionaries changed\n" );
// Update actions
setUpdatesEnabled( false );
for( QList< QAction * >::iterator i = dictActions.begin();
i != dictActions.end(); ++i )
{
bool isUnmuted = !mutedDictionaries.contains( (*i)->data().toString() );
if ( isUnmuted != (*i)->isChecked() )
(*i)->setChecked( isUnmuted );
}
setUpdatesEnabled( true );
}
void DictionaryBar::actionWasTriggered( QAction * action )
{
QString 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.
// Are we solo already?
bool isSolo = true;
// 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() )
{
isSolo = false;
break;
}
}
if ( isSolo )
{
// Toggle back all the dictionaries
for( QList< QAction * >::iterator i = dictActions.begin();
i != dictActions.end(); ++i )
mutedDictionaries.remove( (*i)->data().toString() );
}
else
{
// Make dictionary solo
for( QList< QAction * >::iterator i = dictActions.begin();
i != dictActions.end(); ++i )
{
QString dictId = (*i)->data().toString();
if ( dictId == id )
mutedDictionaries.remove( dictId );
else
mutedDictionaries.insert( dictId );
}
}
configEvents.signalMutedDictionariesChanged();
}
else
{
// Normal mode
if ( action->isChecked() )
{
// Unmute the dictionary
if ( mutedDictionaries.contains( id ) )
{
mutedDictionaries.remove( id );
configEvents.signalMutedDictionariesChanged();
}
}
else
{
// Mute the dictionary
if ( !mutedDictionaries.contains( id ) )
{
mutedDictionaries.insert( id );
configEvents.signalMutedDictionariesChanged();
}
}
}
}
void DictionaryBar::dictsPaneClicked( const QString & id )
{
for( QList< QAction * >::iterator i = dictActions.begin();
i != dictActions.end(); ++i )
{
QString dictId = (*i)->data().toString();
if ( dictId == id )
{
(*i)->activate( QAction::Trigger );
break;
}
}
}