Implemented Dictionaries Pane, to show dicts in which results were found.

It is a separate detacheable pane, which could also be enabled/disabled,
it tracks the current tab's contains, and lists those dictionaries that
contributed their content to the current translation.

Clicking on dictionary name jumps to the appropriate article from
this dictionary, which improves the navigation flow.

The Dictionaries Pane:
  * Shows both dictionaries' names and icons.
  * Does not consume resources when hidden.
  * Properly styled.
  * Properly handles app-wide shortcuts
    (Esc, Ctrl-L, Alt-D, Enter, Alt-Up/Down).
This commit is contained in:
Tvangeste 2011-06-05 13:49:50 +02:00
parent ade15f5d41
commit 3762f22e76
9 changed files with 218 additions and 9 deletions

View file

@ -366,6 +366,32 @@ QString ArticleView::getCurrentArticle()
return QString(); return QString();
} }
void ArticleView::jumpToDictionary(QString const & dictName)
{
// Find the dictionary with the specified name
for( unsigned x = allDictionaries.size(); x--; )
{
if ( QString::fromUtf8( allDictionaries[ x ]->getName().c_str()) == dictName )
{
// Check that one of the articles belongs to the specified dictionary.
QStringList ids = getArticlesList();
for( QStringList::const_iterator i = ids.constBegin(); i != ids.constEnd(); ++i )
{
if ( allDictionaries[ x ]->getId() == i->toUtf8().data() ) {
setCurrentArticle( "gdfrom-" + *i, true );
break;
}
}
break;
}
}
}
void ArticleView::setCurrentArticle( QString const & id, bool moveToIt ) void ArticleView::setCurrentArticle( QString const & id, bool moveToIt )
{ {
if ( !id.startsWith( "gdfrom-" ) ) if ( !id.startsWith( "gdfrom-" ) )

View file

@ -142,7 +142,15 @@ public:
/// Closes search if it's open and returns true. Returns false if it /// Closes search if it's open and returns true. Returns false if it
/// wasn't open. /// wasn't open.
bool closeSearch(); bool closeSearch();
/// Jumps to the article specified by the dictionary name,
/// by executing a javascript code.
void jumpToDictionary( QString const & );
/// Returns all articles current present in view, as a list of dictionary
/// string ids.
QStringList getArticlesList();
signals: signals:
void iconChanged( ArticleView *, QIcon const & icon ); void iconChanged( ArticleView *, QIcon const & icon );
@ -201,9 +209,6 @@ private:
/// returns 0. /// returns 0.
unsigned getGroup( QUrl const & ); unsigned getGroup( QUrl const & );
/// Returns all articles current present in view, as a list of dictionary
/// string ids.
QStringList getArticlesList();
/// Returns current article in the view, in the form of "gdfrom-xxx" id. /// Returns current article in the view, in the form of "gdfrom-xxx" id.
QString getCurrentArticle(); QString getCurrentArticle();

23
dictspanewidget.hh Normal file
View file

@ -0,0 +1,23 @@
/* This file is (c) 2008-2011 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#ifndef __DICTSPANEWIDGET_HH_INCLUDED__
#define __DICTSPANEWIDGET_HH_INCLUDED__
#include <QWidget>
#include <QSize>
/// A widget holding the contents of the 'Dictionaries pane' docklet.
class DictsPaneWidget: public QWidget
{
public:
DictsPaneWidget( QWidget * parent = 0 ): QWidget( parent )
{}
virtual QSize sizeHint() const
{ return QSize( 204, 204 ); }
};
#endif

View file

@ -161,7 +161,8 @@ HEADERS += folding.hh \
country.hh \ country.hh \
about.hh \ about.hh \
programs.hh \ programs.hh \
parsecmdline.hh parsecmdline.hh \
dictspanewidget.hh
FORMS += groups.ui \ FORMS += groups.ui \
dictgroupwidget.ui \ dictgroupwidget.ui \
mainwindow.ui \ mainwindow.ui \

View file

@ -26,6 +26,7 @@ MainWindow::MainWindow( Config::Class & cfg_ ):
trayIcon( 0 ), trayIcon( 0 ),
groupLabel( &searchPaneTitleBar ), groupLabel( &searchPaneTitleBar ),
groupList( &searchPaneTitleBar ), groupList( &searchPaneTitleBar ),
foundInDictsLabel( &dictsPaneTitleBar ),
escAction( this ), escAction( this ),
focusTranslateLineAction( this ), focusTranslateLineAction( this ),
addTabAction( this ), addTabAction( this ),
@ -68,6 +69,15 @@ MainWindow::MainWindow( Config::Class & cfg_ ):
ui.searchPane->setTitleBarWidget( &searchPaneTitleBar ); ui.searchPane->setTitleBarWidget( &searchPaneTitleBar );
// Make the dictionaries pane's titlebar
foundInDictsLabel.setText( tr( "Found in Dictionaries:" ) );
dictsPaneTitleBarLayout.addWidget( &foundInDictsLabel );
dictsPaneTitleBar.setLayout( &dictsPaneTitleBarLayout );
ui.dictsPane->setTitleBarWidget( &dictsPaneTitleBar );
connect( ui.dictsPane, SIGNAL( visibilityChanged( bool ) ),
this, SLOT( dictsPaneVisibilityChanged ( bool ) ) );
// Make the toolbar // Make the toolbar
navToolbar = addToolBar( tr( "Navigation" ) ); navToolbar = addToolBar( tr( "Navigation" ) );
navToolbar->setObjectName( "navToolbar" ); navToolbar->setObjectName( "navToolbar" );
@ -154,9 +164,12 @@ MainWindow::MainWindow( Config::Class & cfg_ ):
this, SLOT( focusTranslateLine() ) ); this, SLOT( focusTranslateLine() ) );
ui.centralWidget->addAction( &escAction ); ui.centralWidget->addAction( &escAction );
ui.dictsPane->addAction( &escAction );
ui.searchPaneWidget->addAction( &escAction ); ui.searchPaneWidget->addAction( &escAction );
groupList.addAction( &escAction ); groupList.addAction( &escAction );
ui.centralWidget->addAction( &focusTranslateLineAction ); ui.centralWidget->addAction( &focusTranslateLineAction );
ui.dictsPane->addAction( &focusTranslateLineAction );
ui.searchPaneWidget->addAction( &focusTranslateLineAction ); ui.searchPaneWidget->addAction( &focusTranslateLineAction );
groupList.addAction( &focusTranslateLineAction ); groupList.addAction( &focusTranslateLineAction );
@ -239,6 +252,7 @@ MainWindow::MainWindow( Config::Class & cfg_ ):
// Populate 'View' menu // Populate 'View' menu
ui.menuView->addAction( ui.searchPane->toggleViewAction() ); ui.menuView->addAction( ui.searchPane->toggleViewAction() );
ui.menuView->addAction( ui.dictsPane->toggleViewAction() );
ui.menuView->addSeparator(); ui.menuView->addSeparator();
ui.menuView->addAction( dictionaryBar.toggleViewAction() ); ui.menuView->addAction( dictionaryBar.toggleViewAction() );
ui.menuView->addAction( navToolbar->toggleViewAction() ); ui.menuView->addAction( navToolbar->toggleViewAction() );
@ -350,6 +364,9 @@ MainWindow::MainWindow( Config::Class & cfg_ ):
connect( ui.wordList, SIGNAL( itemSelectionChanged() ), connect( ui.wordList, SIGNAL( itemSelectionChanged() ),
this, SLOT( wordListSelectionChanged() ) ); this, SLOT( wordListSelectionChanged() ) );
connect( ui.dictsList, SIGNAL( itemSelectionChanged() ),
this, SLOT( dictsListSelectionChanged() ) );
connect( &wordFinder, SIGNAL( updated() ), connect( &wordFinder, SIGNAL( updated() ),
this, SLOT( prefixMatchUpdated() ) ); this, SLOT( prefixMatchUpdated() ) );
connect( &wordFinder, SIGNAL( finished() ), connect( &wordFinder, SIGNAL( finished() ),
@ -360,6 +377,7 @@ MainWindow::MainWindow( Config::Class & cfg_ ):
ui.translateLine->installEventFilter( this ); ui.translateLine->installEventFilter( this );
ui.wordList->installEventFilter( this ); ui.wordList->installEventFilter( this );
ui.dictsList->installEventFilter(this);
if ( cfg.mainWindowGeometry.size() ) if ( cfg.mainWindowGeometry.size() )
restoreGeometry( cfg.mainWindowGeometry ); restoreGeometry( cfg.mainWindowGeometry );
@ -961,11 +979,14 @@ void MainWindow::pageLoaded( ArticleView * view )
if ( cfg.preferences.pronounceOnLoadMain ) if ( cfg.preferences.pronounceOnLoadMain )
pronounce( view ); pronounce( view );
updateFoundInDictsList();
} }
void MainWindow::tabSwitched( int ) void MainWindow::tabSwitched( int )
{ {
updatePronounceAvailability(); updatePronounceAvailability();
updateFoundInDictsList();
} }
void MainWindow::tabMenuRequested(QPoint pos) void MainWindow::tabMenuRequested(QPoint pos)
@ -995,6 +1016,53 @@ void MainWindow::pronounce( ArticleView * view )
dynamic_cast< ArticleView & >( *( ui.tabWidget->currentWidget() ) ).playSound(); dynamic_cast< ArticleView & >( *( ui.tabWidget->currentWidget() ) ).playSound();
} }
void MainWindow::dictsPaneVisibilityChanged( bool visible )
{
if (visible) {
updateFoundInDictsList();
}
}
void MainWindow::updateFoundInDictsList()
{
if (!ui.dictsList->isVisible())
{
// nothing to do, the list is not visible
return;
}
ui.dictsList->clear();
if ( QWidget * cw = ui.tabWidget->currentWidget() )
{
ArticleView & view = dynamic_cast< ArticleView & >( *( cw ) );
QStringList ids = view.getArticlesList();
for( QStringList::const_iterator i = ids.constBegin(); i != ids.constEnd(); ++i)
{
// Find this dictionary
for( unsigned x = dictionaries.size(); x--; )
{
if ( dictionaries[ x ]->getId() == i->toUtf8().data() )
{
QString dictName = QString::fromUtf8( dictionaries[ x ]->getName().c_str() );
QListWidgetItem * item =
new QListWidgetItem(
dictionaries[ x ]->getIcon(),
dictName,
ui.dictsList, QListWidgetItem::Type );
item->setToolTip(dictName);
ui.dictsList->addItem( item );
break;
}
}
}
}
}
void MainWindow::updatePronounceAvailability() void MainWindow::updatePronounceAvailability()
{ {
bool pronounceEnabled = ui.tabWidget->count() > 0 && bool pronounceEnabled = ui.tabWidget->count() > 0 &&
@ -1343,7 +1411,34 @@ bool MainWindow::eventFilter( QObject * obj, QEvent * ev )
// Handle typing events used to initiate new lookups // Handle typing events used to initiate new lookups
if ( keyEvent->modifiers() & if ( keyEvent->modifiers() &
( Qt::ControlModifier | Qt::ShiftModifier | Qt::AltModifier | Qt::MetaModifier ) ) ( Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier ) )
return false; // A non-typing modifier is pressed
if ( keyEvent->key() == Qt::Key_Space ||
keyEvent->key() == Qt::Key_Backspace ||
keyEvent->key() == Qt::Key_Tab )
return false; // Those key have other uses than to start typing
// or don't make sense
QString text = keyEvent->text();
if ( text.size() )
{
typingEvent( text );
return true;
}
}
}
else
if (obj == ui.dictsList) {
if ( ev->type() == /*QEvent::KeyPress*/ 6 )
{
QKeyEvent * keyEvent = static_cast< QKeyEvent * >( ev );
// Handle typing events used to initiate new lookups
if ( keyEvent->modifiers() &
( Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier ) )
return false; // A non-typing modifier is pressed return false; // A non-typing modifier is pressed
if ( keyEvent->key() == Qt::Key_Space || if ( keyEvent->key() == Qt::Key_Space ||
@ -1380,6 +1475,20 @@ void MainWindow::wordListSelectionChanged()
wordListItemActivated( selected.front() ); wordListItemActivated( selected.front() );
} }
void MainWindow::dictsListItemActivated( QListWidgetItem * item )
{
ArticleView & view = dynamic_cast< ArticleView & >( *( ui.tabWidget->currentWidget() ) );
view.jumpToDictionary( item->text() );
}
void MainWindow::dictsListSelectionChanged()
{
QList< QListWidgetItem * > selected = ui.dictsList->selectedItems();
if ( selected.size() )
dictsListItemActivated( selected.front() );
}
void MainWindow::openLinkInNewTab( QUrl const & url, void MainWindow::openLinkInNewTab( QUrl const & url,
QUrl const & referrer, QUrl const & referrer,
QString const & fromArticle, QString const & fromArticle,
@ -1404,7 +1513,7 @@ void MainWindow::typingEvent( QString const & t )
focusTranslateLine(); focusTranslateLine();
else else
{ {
if ( ui.searchPane->isFloating() ) if ( ui.searchPane->isFloating() || ui.dictsPane->isFloating() )
ui.searchPane->activateWindow(); ui.searchPane->activateWindow();
ui.translateLine->setText( t ); ui.translateLine->setText( t );
@ -1434,6 +1543,7 @@ void MainWindow::showTranslationFor( QString const & inWord,
view.showDefinition( inWord, group ); view.showDefinition( inWord, group );
updatePronounceAvailability(); updatePronounceAvailability();
updateFoundInDictsList();
// Add to history // Add to history

View file

@ -58,6 +58,10 @@ private:
QLabel groupLabel; QLabel groupLabel;
GroupComboBox groupList; GroupComboBox groupList;
QWidget dictsPaneTitleBar;
QHBoxLayout dictsPaneTitleBarLayout;
QLabel foundInDictsLabel;
/// Fonts saved before words zooming is in effect, so it could be reset back. /// Fonts saved before words zooming is in effect, so it could be reset back.
QFont wordListDefaultFont, translateLineDefaultFont; QFont wordListDefaultFont, translateLineDefaultFont;
@ -120,6 +124,8 @@ private:
void updatePronounceAvailability(); void updatePronounceAvailability();
void updateFoundInDictsList();
/// Updates word search request and active article view in response to /// Updates word search request and active article view in response to
/// muting or unmuting dictionaries, or showing/hiding dictionary bar. /// muting or unmuting dictionaries, or showing/hiding dictionary bar.
void applyMutedDictionariesState(); void applyMutedDictionariesState();
@ -232,6 +238,11 @@ private slots:
void wordListItemActivated( QListWidgetItem * ); void wordListItemActivated( QListWidgetItem * );
void wordListSelectionChanged(); void wordListSelectionChanged();
void dictsListItemActivated( QListWidgetItem * );
void dictsListSelectionChanged();
void dictsPaneVisibilityChanged ( bool );
/// Creates a new tab, which is to be populated then with some content. /// Creates a new tab, which is to be populated then with some content.
ArticleView * createNewTab( bool switchToIt, ArticleView * createNewTab( bool switchToIt,
QString const & name ); QString const & name );

View file

@ -244,6 +244,33 @@
</layout> </layout>
</widget> </widget>
</widget> </widget>
<widget class="QDockWidget" name="dictsPane">
<property name="windowTitle">
<string>Dictionaries Pane</string>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
</attribute>
<widget class="DictsPaneWidget" name="dictsPaneWidget">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>1</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>1</number>
</property>
<item>
<widget class="QListWidget" name="dictsList"/>
</item>
</layout>
</widget>
</widget>
<action name="dictionaries"> <action name="dictionaries">
<property name="icon"> <property name="icon">
<iconset resource="resources.qrc"> <iconset resource="resources.qrc">
@ -381,6 +408,12 @@
<header>searchpanewidget.hh</header> <header>searchpanewidget.hh</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
<customwidget>
<class>DictsPaneWidget</class>
<extends>QWidget</extends>
<header>dictspanewidget.hh</header>
<container>1</container>
</customwidget>
</customwidgets> </customwidgets>
<tabstops> <tabstops>
<tabstop>translateLine</tabstop> <tabstop>translateLine</tabstop>

View file

@ -1,4 +1,4 @@
MainWindow #searchPane #translateLine, MainWindow #searchPane #wordList MainWindow #searchPane #translateLine, MainWindow #searchPane #wordList, MainWindow #dictsPane #dictsList
{ {
background: white; background: white;
} }

View file

@ -1,4 +1,4 @@
MainWindow #searchPane #translateLine, MainWindow #searchPane #wordList MainWindow #searchPane #translateLine, MainWindow #searchPane #wordList, MainWindow #dictsPane #dictsList
{ {
background: #fefdeb; background: #fefdeb;
color: black; color: black;