History Pane rewrite.

The new History Pane features proper mouse and keyboard navigation,
multiple selection and ability to remove the selected entries,
plus a dynamic context menu. Additionaly, the History's size is now
configurable in Preferences.

Use Ctrl+H to show/hide the History Pane.

History Pane's titlebar can be styled via #historyPaneTitleBar, e.g.:

/* Colored header for the History Pane */
  background: lightsteelblue;
  margin: 2px;
}

Closes #162: Make History sidebar independent from the Search Pane
Closes #159: "Send to main window" button from Pop-Up window does nothing when History is shown
Closes #158: Preserve History mode after restart
Closes #157: History with new UI: New words are not added when History is shown
Closes #156: History with new UI: Extra Groups widget in History is shown
Closes #155: History with new UI: Arrow keys navigation in History doesn't work
Closes #154: History with new UI: DEL key does not delete the current history entry
This commit is contained in:
Tvangeste 2013-01-17 10:08:53 +01:00
parent 1fab8c8216
commit 3ed7772996
16 changed files with 542 additions and 151 deletions

View file

@ -10,6 +10,7 @@
/// A widget holding the contents of the 'Dictionaries pane' docklet. /// A widget holding the contents of the 'Dictionaries pane' docklet.
class DictsPaneWidget: public QWidget class DictsPaneWidget: public QWidget
{ {
Q_OBJECT
public: public:
DictsPaneWidget( QWidget * parent = 0 ): QWidget( parent ) DictsPaneWidget( QWidget * parent = 0 ): QWidget( parent )

View file

@ -208,7 +208,9 @@ HEADERS += folding.hh \
zipsounds.hh \ zipsounds.hh \
stylescombobox.hh \ stylescombobox.hh \
extlineedit.hh \ extlineedit.hh \
translatebox.hh translatebox.hh \
historypanewidget.hh
FORMS += groups.ui \ FORMS += groups.ui \
dictgroupwidget.ui \ dictgroupwidget.ui \
mainwindow.ui \ mainwindow.ui \
@ -307,7 +309,9 @@ SOURCES += folding.cc \
zipsounds.cc \ zipsounds.cc \
stylescombobox.cc \ stylescombobox.cc \
extlineedit.cc \ extlineedit.cc \
translatebox.cc translatebox.cc \
historypanewidget.cc
win32 { win32 {
SOURCES += mouseover_win32/ThTypes.c \ SOURCES += mouseover_win32/ThTypes.c \
wordbyauto.cc \ wordbyauto.cc \

View file

@ -5,6 +5,7 @@
#include "config.hh" #include "config.hh"
#include "atomic_rename.hh" #include "atomic_rename.hh"
#include <QFile> #include <QFile>
#include <QDebug>
History::History( unsigned size ): maxSize( size ), History::History( unsigned size ): maxSize( size ),
addingEnabled( true ) addingEnabled( true )
@ -48,8 +49,18 @@ addingEnabled( true )
} }
} }
History::Item History::getItem( int index )
{
if ( index < 0 || index >= items.size() )
{
return Item();
}
return items.at( index );
}
void History::addItem( Item const & item ) void History::addItem( Item const & item )
{ {
// qDebug() << "adding item " << item.word << ", enabled=" << enabled();
if( !enabled() ) if( !enabled() )
return; return;
@ -70,12 +81,37 @@ void History::addItem( Item const & item )
items.push_front( item ); items.push_front( item );
while( items.size() > (int)maxSize ) ensureSizeConstraints();
items.pop_back();
emit itemsChanged(); emit itemsChanged();
} }
bool History::ensureSizeConstraints()
{
bool changed = false;
while( items.size() > (int)maxSize )
{
items.pop_back();
changed = true;
}
return changed;
}
void History::setMaxSize( unsigned maxSize_ )
{
maxSize = maxSize_;
if ( ensureSizeConstraints() )
{
emit itemsChanged();
}
}
int History::size() const
{
return items.size();
}
bool History::save() const bool History::save() const
{ {
QFile file( Config::getHistoryFileName() + ".tmp" ); QFile file( Config::getHistoryFileName() + ".tmp" );

View file

@ -55,9 +55,11 @@ public:
/// item gets removed from the end of the list. /// item gets removed from the end of the list.
void addItem( Item const & ); void addItem( Item const & );
Item getItem( int index );
/// Remove item with given index from list /// Remove item with given index from list
void removeItem( int index ) void removeItem( int index )
{ items.removeAt( index ); } { items.removeAt( index ); emit itemsChanged(); }
/// Attempts saving history. Returns true if succeeded - false otherwise. /// Attempts saving history. Returns true if succeeded - false otherwise.
/// Since history isn't really that valuable, failures can be ignored. /// Since history isn't really that valuable, failures can be ignored.
@ -66,6 +68,9 @@ public:
/// Clears history. /// Clears history.
void clear(); void clear();
/// History size.
int size() const;
/// Gets the current items. The first one is the newest one on the list. /// Gets the current items. The first one is the newest one on the list.
QList< Item > const & getItems() const QList< Item > const & getItems() const
{ return items; } { return items; }
@ -76,6 +81,8 @@ public:
bool enabled() bool enabled()
{ return addingEnabled; } { return addingEnabled; }
void setMaxSize( unsigned maxSize_ );
unsigned getMaxSize() unsigned getMaxSize()
{ return maxSize; } { return maxSize; }
@ -86,9 +93,14 @@ signals:
private: private:
/// Returns true if the items list has been modified
/// in order to fit into the constraints.
bool ensureSizeConstraints();
QList< Item > items; QList< Item > items;
unsigned maxSize; unsigned maxSize;
bool addingEnabled; bool addingEnabled;
}; };
#endif #endif

222
historypanewidget.cc Normal file
View file

@ -0,0 +1,222 @@
/* This file is (c) 2013 Tvangeste <i.4m.l33t@yandex.ru>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#include <QDebug>
#include <QApplication>
#include <QDockWidget>
#include <QKeyEvent>
#include "historypanewidget.hh"
void HistoryPaneWidget::setUp( Config::Class * cfg, History * history, QMenu * menu )
{
m_cfg = cfg;
m_history = history;
m_historyList = findChild<QListView*>( "historyList" );
QDockWidget * historyPane = qobject_cast<QDockWidget*>( parentWidget() );
// Delete selected items action
m_deleteSelectedAction = new QAction( this );
m_deleteSelectedAction->setText( tr( "&Delete Selected" ) );
m_deleteSelectedAction->setShortcut( QKeySequence( QKeySequence::Delete ) );
m_deleteSelectedAction->setShortcutContext( Qt::WidgetWithChildrenShortcut );
addAction( m_deleteSelectedAction );
connect( m_deleteSelectedAction, SIGNAL( triggered() ),
this, SLOT( deleteSelectedItems() ) );
// Handle context menu, reusing some of the top-level window's History menu
m_historyMenu = new QMenu( this );
m_separator = m_historyMenu->addSeparator();
QListIterator<QAction *> actionsIter( menu->actions() );
while ( actionsIter.hasNext() )
m_historyMenu->addAction( actionsIter.next() );
// Make the history pane's titlebar
historyLabel.setText( tr( "History:" ) );
historyLabel.setObjectName( "historyLabel" );
historyCountLabel.setObjectName( "historyCountLabel" );
if ( layoutDirection() == Qt::LeftToRight )
{
historyLabel.setAlignment( Qt::AlignLeft );
historyCountLabel.setAlignment( Qt::AlignRight );
}
else
{
historyLabel.setAlignment( Qt::AlignRight );
historyCountLabel.setAlignment( Qt::AlignLeft );
}
updateHistoryCounts();
historyPaneTitleBarLayout.addWidget( &historyLabel );
historyPaneTitleBarLayout.addWidget( &historyCountLabel );
historyPaneTitleBarLayout.setContentsMargins(5, 5, 5, 5);
historyPaneTitleBar.setLayout( &historyPaneTitleBarLayout );
historyPaneTitleBar.setObjectName("historyPaneTitleBar");
historyPane->setTitleBarWidget( &historyPaneTitleBar );
// History list
HistoryModel * historyModel = new HistoryModel( m_history, this );
m_historyList->setModel( historyModel );
m_historyList->setContextMenuPolicy( Qt::CustomContextMenu );
// very important call, for performance reasons:
m_historyList->setUniformItemSizes( true );
m_historyList->setSelectionMode( QAbstractItemView::ExtendedSelection );
m_historyList->installEventFilter( this );
m_historyList->viewport()->installEventFilter( this );
// list selection and keyboard navigation
connect( m_historyList, SIGNAL( clicked( QModelIndex const & ) ),
this, SLOT( onItemClicked( QModelIndex const & ) ) );
connect( m_history, SIGNAL( itemsChanged() ),
this, SLOT( updateHistoryCounts() ) );
connect ( m_historyList->selectionModel(), SIGNAL( selectionChanged ( QItemSelection const & , QItemSelection const & ) ),
this, SLOT( onSelectionChanged( QItemSelection const & ) ) );
connect( m_historyList, SIGNAL( customContextMenuRequested( QPoint const & ) ),
this, SLOT( showCustomMenu( QPoint const & ) ) );
}
void HistoryPaneWidget::deleteSelectedItems()
{
QModelIndexList selectedIdxs = m_historyList->selectionModel()->selectedIndexes();
if ( selectedIdxs.isEmpty() )
{
// nothing to do
return;
}
QList<int> idxsToDelete;
QListIterator<QModelIndex> i( m_historyList->selectionModel()->selectedIndexes() );
while ( i.hasNext() )
{
idxsToDelete << i.next().row();
}
// Need to sort indexes in the decreasing order so that
// the first deletions won't affect the indexes for subsequent deletions.
qSort( idxsToDelete.begin(), idxsToDelete.end(), qGreater<int>() );
QListIterator<int> idxs( idxsToDelete );
while ( idxs.hasNext() )
m_history->removeItem( idxs.next() );
if (idxsToDelete.size() == 1)
{
// We've just removed a single entry,
// keep the selection at the same index.
m_historyList->selectionModel()->select(
selectedIdxs.front(), QItemSelectionModel::Select );
}
else
{
// Too many deletions, better to reset the selection.
m_historyList->selectionModel()->reset();
}
}
bool HistoryPaneWidget::eventFilter( QObject * obj, QEvent * ev )
{
// unused for now
return QWidget::eventFilter( obj, ev );
}
void HistoryPaneWidget::showCustomMenu(QPoint const & pos)
{
bool selectionEmpty = m_historyList->selectionModel()->selection().empty();
m_historyMenu->removeAction( m_deleteSelectedAction );
m_separator->setVisible( !selectionEmpty );
if ( !selectionEmpty )
m_historyMenu->insertAction( m_separator, m_deleteSelectedAction );
m_historyMenu->exec( m_historyList->mapToGlobal( pos ) );
}
void HistoryPaneWidget::emitHistoryItemRequested( QModelIndex const & idx )
{
QVariant value = m_historyList->model()->data( idx );
if ( !value.isNull() )
{
emit historyItemRequested( value.toString() );
}
}
void HistoryPaneWidget::onSelectionChanged( QItemSelection const & selection )
{
// qDebug() << "selectionChanged";
if ( selection.empty() )
return;
itemSelectionChanged = true;
emitHistoryItemRequested( selection.front().bottomRight() );
}
void HistoryPaneWidget::onItemClicked( QModelIndex const & idx )
{
// qDebug() << "clicked";
if ( !itemSelectionChanged )
{
emitHistoryItemRequested( idx );
}
itemSelectionChanged = false;
}
void HistoryPaneWidget::updateHistoryCounts()
{
historyCountLabel.setText( tr( "%1/%2" ).
arg( m_history->size() ).
arg( m_cfg->preferences.maxStringsInHistory ) );
historyCountLabel.setToolTip(
tr( "History size: %1 entries out of maximum %2" ).
arg( m_history->size() ).
arg( m_cfg->preferences.maxStringsInHistory ));
}
HistoryModel::HistoryModel( History * history, QObject * parent )
: QAbstractListModel( parent ), m_history(history)
{
connect( m_history, SIGNAL( itemsChanged() ),
this, SLOT( historyChanged() ) );
}
int HistoryModel::rowCount( QModelIndex const & /*parent*/ ) const
{
return m_history->size();
}
QVariant HistoryModel::data( QModelIndex const & index, int role ) const
{
// qDebug() << "data: " << index;
if ( !index.isValid() || index.row() >= m_history->size() )
{
return QVariant();
}
if ( role == Qt::DisplayRole )
{
return m_history->getItem( index.row() ).word;
}
else
{
return QVariant();
}
}
void HistoryModel::historyChanged()
{
// qDebug() << "History Changed!!";
reset();
}

83
historypanewidget.hh Normal file
View file

@ -0,0 +1,83 @@
/* This file is (c) 2013 Tvangeste <i.4m.l33t@yandex.ru>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#ifndef __HISTORYPANEWIDGET_HH_INCLUDED__
#define __HISTORYPANEWIDGET_HH_INCLUDED__
#include <QWidget>
#include <QSize>
#include <QAbstractListModel>
#include <QListView>
#include <QLabel>
#include <QHBoxLayout>
#include <QMenu>
#include <config.hh>
#include "history.hh"
/// A widget holding the contents of the 'History' docklet.
class HistoryPaneWidget : public QWidget
{
Q_OBJECT
public:
explicit HistoryPaneWidget( QWidget * parent = 0 ): QWidget( parent ),
itemSelectionChanged( false )
{}
virtual QSize sizeHint() const
{ return QSize( 204, 204 ); }
void setUp( Config::Class * cfg, History * history, QMenu * menu );
signals:
void historyItemRequested( QString const & word );
public slots:
void updateHistoryCounts();
private slots:
void emitHistoryItemRequested(QModelIndex const &);
void onSelectionChanged(QItemSelection const & selection);
void onItemClicked(QModelIndex const & idx);
void showCustomMenu(QPoint const & pos);
void deleteSelectedItems();
private:
virtual bool eventFilter( QObject *, QEvent * );
Config::Class * m_cfg ;
History * m_history;
QListView * m_historyList;
QMenu * m_historyMenu;
QAction * m_deleteSelectedAction;
QAction * m_separator;
QWidget historyPaneTitleBar;
QHBoxLayout historyPaneTitleBarLayout;
QLabel historyLabel;
QLabel historyCountLabel;
/// needed to avoid multiple notifications
/// when selecting history items via mouse and keyboard
bool itemSelectionChanged;
};
class HistoryModel : public QAbstractListModel
{
Q_OBJECT
public:
explicit HistoryModel( History * history , QObject * parent = 0 );
int rowCount( QModelIndex const & parent = QModelIndex() ) const;
QVariant data( QModelIndex const & index, int role = Qt::DisplayRole ) const;
private slots:
void historyChanged();
private:
History * m_history;
};
#endif // HISTORYPANEWIDGET_HH

View file

@ -23,6 +23,7 @@
#include "dictinfo.hh" #include "dictinfo.hh"
#include "fsencoding.hh" #include "fsencoding.hh"
#include <QProcess> #include <QProcess>
#include "historypanewidget.hh"
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
#include "lionsupport.h" #include "lionsupport.h"
@ -45,7 +46,6 @@ using std::pair;
MainWindow::MainWindow( Config::Class & cfg_ ): MainWindow::MainWindow( Config::Class & cfg_ ):
commitDataCompleted( false ), commitDataCompleted( false ),
showHistory( false ),
trayIcon( 0 ), trayIcon( 0 ),
groupLabel( &searchPaneTitleBar ), groupLabel( &searchPaneTitleBar ),
foundInDictsLabel( &dictsPaneTitleBar ), foundInDictsLabel( &dictsPaneTitleBar ),
@ -299,12 +299,14 @@ MainWindow::MainWindow( Config::Class & cfg_ ):
ui.centralWidget->addAction( &escAction ); ui.centralWidget->addAction( &escAction );
ui.dictsPane->addAction( &escAction ); ui.dictsPane->addAction( &escAction );
ui.searchPaneWidget->addAction( &escAction ); ui.searchPaneWidget->addAction( &escAction );
ui.historyPane->addAction( &escAction );
groupList->addAction( &escAction ); groupList->addAction( &escAction );
translateBox->addAction( &escAction ); translateBox->addAction( &escAction );
ui.centralWidget->addAction( &focusTranslateLineAction ); ui.centralWidget->addAction( &focusTranslateLineAction );
ui.dictsPane->addAction( &focusTranslateLineAction ); ui.dictsPane->addAction( &focusTranslateLineAction );
ui.searchPaneWidget->addAction( &focusTranslateLineAction ); ui.searchPaneWidget->addAction( &focusTranslateLineAction );
ui.historyPane->addAction( &focusTranslateLineAction );
groupList->addAction( &focusTranslateLineAction ); groupList->addAction( &focusTranslateLineAction );
addTabAction.setShortcutContext( Qt::WidgetWithChildrenShortcut ); addTabAction.setShortcutContext( Qt::WidgetWithChildrenShortcut );
@ -407,10 +409,13 @@ MainWindow::MainWindow( Config::Class & cfg_ ):
// Populate 'View' menu // Populate 'View' menu
ui.menuView->addAction( &toggleMenuBarAction ); ui.menuView->addAction( &toggleMenuBarAction );
ui.menuView->addSeparator();
ui.menuView->addAction( ui.searchPane->toggleViewAction() ); ui.menuView->addAction( ui.searchPane->toggleViewAction() );
ui.searchPane->toggleViewAction()->setShortcut( QKeySequence( "Ctrl+S" ) ); ui.searchPane->toggleViewAction()->setShortcut( QKeySequence( "Ctrl+S" ) );
ui.menuView->addAction( ui.dictsPane->toggleViewAction() ); ui.menuView->addAction( ui.dictsPane->toggleViewAction() );
ui.dictsPane->toggleViewAction()->setShortcut( QKeySequence( "Ctrl+R" ) ); ui.dictsPane->toggleViewAction()->setShortcut( QKeySequence( "Ctrl+R" ) );
ui.menuView->addAction( ui.historyPane->toggleViewAction() );
ui.historyPane->toggleViewAction()->setShortcut( QKeySequence( "Ctrl+H" ) );
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() );
@ -462,8 +467,18 @@ MainWindow::MainWindow( Config::Class & cfg_ ):
this, SLOT( showDictionaryInfo( QString const & ) ) ); this, SLOT( showDictionaryInfo( QString const & ) ) );
// History // History
ui.historyPaneWidget->setUp( &cfg, &history, ui.menuHistory );
history.enableAdd( cfg.preferences.storeHistory ); history.enableAdd( cfg.preferences.storeHistory );
connect( ui.historyPaneWidget, SIGNAL( historyItemRequested( QString const & ) ),
this, SLOT( showHistoryItem( QString const & ) ) );
connect( ui.historyPane, SIGNAL( visibilityChanged( bool ) ),
this, SLOT( updateHistoryMenu() ) );
connect( ui.menuHistory, SIGNAL( aboutToShow() ),
this, SLOT( updateHistoryMenu() ) );
// Show tray icon early so the user would be happy. It won't be functional // Show tray icon early so the user would be happy. It won't be functional
// though until the program inits fully. // though until the program inits fully.
@ -591,6 +606,8 @@ MainWindow::MainWindow( Config::Class & cfg_ ):
//tabWidget doesn't propagate Ctrl+Tab to the parent widget unless event filter is installed //tabWidget doesn't propagate Ctrl+Tab to the parent widget unless event filter is installed
ui.tabWidget->installEventFilter( this ); ui.tabWidget->installEventFilter( this );
ui.historyList->installEventFilter( this );
if ( cfg.mainWindowGeometry.size() ) if ( cfg.mainWindowGeometry.size() )
restoreGeometry( cfg.mainWindowGeometry ); restoreGeometry( cfg.mainWindowGeometry );
@ -1609,7 +1626,6 @@ void MainWindow::editPreferences()
Config::Preferences p = preferences.getPreferences(); Config::Preferences p = preferences.getPreferences();
// These parameters are not set in dialog // These parameters are not set in dialog
p.maxStringsInHistory = cfg.preferences.maxStringsInHistory;
p.zoomFactor = cfg.preferences.zoomFactor; p.zoomFactor = cfg.preferences.zoomFactor;
p.wordsZoomLevel = cfg.preferences.wordsZoomLevel; p.wordsZoomLevel = cfg.preferences.wordsZoomLevel;
p.hideMenubar = cfg.preferences.hideMenubar; p.hideMenubar = cfg.preferences.hideMenubar;
@ -1666,6 +1682,8 @@ void MainWindow::editPreferences()
prepareNewReleaseChecks(); prepareNewReleaseChecks();
history.enableAdd( cfg.preferences.storeHistory ); history.enableAdd( cfg.preferences.storeHistory );
history.setMaxSize( cfg.preferences.maxStringsInHistory );
ui.historyPaneWidget->updateHistoryCounts();
Config::save( cfg ); Config::save( cfg );
} }
@ -1699,12 +1717,8 @@ void MainWindow::currentGroupChanged( QString const & )
updateDictionaryBar(); updateDictionaryBar();
// Update word search results // Update word search results
if( !showHistory )
{
translateInputChanged( translateLine->text() ); translateInputChanged( translateLine->text() );
translateInputFinished( false ); translateInputFinished( false );
}
updateCurrentGroupProperty(); updateCurrentGroupProperty();
} }
@ -1829,6 +1843,11 @@ void MainWindow::focusTranslateLine()
if ( ui.searchPane->isFloating() ) if ( ui.searchPane->isFloating() )
ui.searchPane->activateWindow(); ui.searchPane->activateWindow();
} }
else
{
if ( !isActiveWindow() )
activateWindow();
}
translateLine->setFocus(); translateLine->setFocus();
translateLine->selectAll(); translateLine->selectAll();
@ -1926,7 +1945,6 @@ void MainWindow::updateMatchResults( bool finished )
void MainWindow::applyMutedDictionariesState() void MainWindow::applyMutedDictionariesState()
{ {
// Redo the current search request // Redo the current search request
if( !showHistory )
translateInputChanged( translateLine->text() ); translateInputChanged( translateLine->text() );
ArticleView *view = getCurrentArticleView(); ArticleView *view = getCurrentArticleView();
@ -1955,6 +1973,17 @@ bool MainWindow::handleBackForwardMouseButtons ( QMouseEvent * event) {
bool MainWindow::eventFilter( QObject * obj, QEvent * ev ) bool MainWindow::eventFilter( QObject * obj, QEvent * ev )
{ {
// Handle Ctrl+H to show the History Pane.
if ( ev->type() == QEvent::ShortcutOverride) {
QKeyEvent * ke = static_cast<QKeyEvent*>( ev );
if ( ke->key() == Qt::Key_H && ke->modifiers() == Qt::ControlModifier )
{
on_showHideHistory_triggered();
ev->accept();
return true;
}
}
// when the main window is moved or resized, hide the word list suggestions // when the main window is moved or resized, hide the word list suggestions
if ( obj == this && ( ev->type() == QEvent::Move || ev->type() == QEvent::Resize ) ) if ( obj == this && ( ev->type() == QEvent::Move || ev->type() == QEvent::Resize ) )
{ {
@ -2052,24 +2081,6 @@ bool MainWindow::eventFilter( QObject * obj, QEvent * ev )
return cfg.preferences.searchInDock; return cfg.preferences.searchInDock;
} }
if( showHistory && keyEvent->matches( QKeySequence::Delete ) && ui.wordList->count() )
{
// Delete word from history
QList<QListWidgetItem *> selectedItems = ui.wordList->selectedItems();
if( selectedItems.size() )
{
int index = ui.wordList->row( selectedItems.at( 0 ) );
history.removeItem( index );
QListWidgetItem *item = ui.wordList->takeItem( index );
if( item )
delete item;
}
return true;
}
// Handle typing events used to initiate new lookups // Handle typing events used to initiate new lookups
// TODO: refactor to eliminate duplication (see below) // TODO: refactor to eliminate duplication (see below)
@ -2232,6 +2243,20 @@ void MainWindow::mutedDictionariesChanged()
applyMutedDictionariesState(); applyMutedDictionariesState();
} }
void MainWindow::showHistoryItem( QString const & word )
{
// qDebug() << "Showing history item" << word;
translateBox->setPopupEnabled( false );
history.enableAdd( false );
translateLine->setText( word );
showTranslationFor( word );
translateBox->setPopupEnabled( true );
history.enableAdd( cfg.preferences.storeHistory );
}
void MainWindow::showTranslationFor( QString const & inWord, void MainWindow::showTranslationFor( QString const & inWord,
unsigned inGroup ) unsigned inGroup )
{ {
@ -2711,9 +2736,6 @@ void MainWindow::on_clearHistory_triggered()
{ {
history.clear(); history.clear();
history.save(); history.save();
if( showHistory )
ui.wordList->clear();
} }
void MainWindow::on_newTab_triggered() void MainWindow::on_newTab_triggered()
@ -3000,82 +3022,27 @@ ArticleView * MainWindow::getCurrentArticleView()
void MainWindow::wordReceived( const QString & word) void MainWindow::wordReceived( const QString & word)
{ {
if( showHistory && cfg.preferences.searchInDock )
return;
toggleMainWindow( true ); toggleMainWindow( true );
translateLine->setText( word ); translateLine->setText( word );
translateInputFinished(); translateInputFinished();
} }
void MainWindow::on_showHideHistory_triggered() void MainWindow::updateHistoryMenu()
{ {
static bool needHideSearchPane; if ( ui.historyPane->toggleViewAction()->isChecked() )
if( showHistory )
{ {
if( needHideSearchPane ) ui.showHideHistory->setText( tr( "&Hide" ) );
{
ui.searchPane->hide();
needHideSearchPane = false;
ui.searchPane->toggleViewAction()->setChecked( false );
}
ui.searchPane->toggleViewAction()->setEnabled( true );
ui.showHideHistory->setText( tr( "&Show" ) );
showHistory = false;
disconnect( &focusTranslateLineAction, SIGNAL( triggered() ),
this, SLOT( focusWordList() ) );
connect( &focusTranslateLineAction, SIGNAL( triggered() ),
this, SLOT( focusTranslateLine() ) );
connect( ui.translateLine, SIGNAL( textChanged( QString const & ) ),
this, SLOT( translateInputChanged( QString const & ) ) );
ui.translateLine->clear();
ui.translateLine->setEnabled( true );
ui.translateLine->setProperty( "noResults", false );
focusTranslateLine();
setStyleSheet( styleSheet() );
ui.wordList->clear();
history.enableAdd( cfg.preferences.storeHistory );
} }
else else
{ {
history.enableAdd( false ); ui.showHideHistory->setText( tr( "&Show" ) );
disconnect( ui.translateLine, SIGNAL( textChanged( QString const & ) ),
this, SLOT( translateInputChanged( QString const & ) ) );
disconnect( &focusTranslateLineAction, SIGNAL( triggered() ),
this, SLOT( focusTranslateLine() ) );
connect( &focusTranslateLineAction, SIGNAL( triggered() ),
this, SLOT( focusWordList() ) );
if( !ui.searchPane->isVisible() )
{
ui.searchPane->show();
ui.searchPane->toggleViewAction()->setChecked( true );
needHideSearchPane = true;
} }
ui.searchPane->toggleViewAction()->setEnabled( false ); }
ui.showHideHistory->setText( tr( "&Hide" ) ); void MainWindow::on_showHideHistory_triggered()
showHistory = true; {
ui.historyPane->toggleViewAction()->trigger();
ui.translateLine->setEnabled( false ); ui.historyPane->raise(); // useful when the Pane is tabbed.
ui.translateLine->setText( tr( "History view mode" ) );
ui.translateLine->setProperty( "noResults", true );
setStyleSheet( styleSheet() );
fillWordListFromHistory();
focusWordList();
}
} }
void MainWindow::on_exportHistory_triggered() void MainWindow::on_exportHistory_triggered()
@ -3139,6 +3106,7 @@ void MainWindow::on_exportHistory_triggered()
mainStatusBar->showMessage( errStr, 10000, QPixmap( ":/icons/error.png" ) ); mainStatusBar->showMessage( errStr, 10000, QPixmap( ":/icons/error.png" ) );
} }
// TODO: consider moving parts of this method into History class.
void MainWindow::on_importHistory_triggered() void MainWindow::on_importHistory_triggered()
{ {
QString importPath; QString importPath;
@ -3189,15 +3157,10 @@ void MainWindow::on_importHistory_triggered()
} while( !fileStream.atEnd() && itemList.size() < (int)history.getMaxSize() ); } while( !fileStream.atEnd() && itemList.size() < (int)history.getMaxSize() );
history.enableAdd( true ); history.enableAdd( true );
for( QList< QString >::const_iterator i = itemList.constBegin(); i != itemList.constEnd(); ++i ) for( QList< QString >::const_iterator i = itemList.constBegin(); i != itemList.constEnd(); ++i )
history.addItem( History::Item( 1, *i ) ); history.addItem( History::Item( 1, *i ) );
if( showHistory )
{
history.enableAdd( false );
fillWordListFromHistory();
ui.translateLine->setText( tr( "Imported from file: " ) + fileInfo.fileName() );
}
else
history.enableAdd( cfg.preferences.storeHistory ); history.enableAdd( cfg.preferences.storeHistory );
if( file.error() != QFile::NoError ) if( file.error() != QFile::NoError )
@ -3245,43 +3208,13 @@ void MainWindow::focusWordList()
void MainWindow::addWordToHistory( const QString & word ) void MainWindow::addWordToHistory( const QString & word )
{ {
if( !showHistory )
{
history.addItem( History::Item( 1, word.trimmed() ) ); history.addItem( History::Item( 1, word.trimmed() ) );
}
} }
void MainWindow::forceAddWordToHistory( const QString & word ) void MainWindow::forceAddWordToHistory( const QString & word )
{ {
history.enableAdd( true ); history.enableAdd( true );
history.addItem( History::Item( 1, word.trimmed() ) ); history.addItem( History::Item( 1, word.trimmed() ) );
if( showHistory )
{
int index = ui.wordList->currentRow();
QListWidgetItem *item = ui.wordList->item( index );
QString currentWord;
if( item )
currentWord = item->text();
if( index < (int) history.getMaxSize() - 1 )
index += 1;
fillWordListFromHistory();
if( index < 0 || index >= ui.wordList->count() )
index = 0;
if( index && currentWord.compare( ui.wordList->item( index )->text() ) != 0 )
index = currentWord.compare( ui.wordList->item( index - 1 )->text() ) == 0 ? index - 1 : 0;
if( index )
disconnect( ui.wordList, SIGNAL( itemSelectionChanged() ),
this, SLOT( wordListSelectionChanged() ) );
ui.wordList->setCurrentRow( index, QItemSelectionModel::Select );
if( index )
connect( ui.wordList, SIGNAL( itemSelectionChanged() ),
this, SLOT( wordListSelectionChanged() ) );
}
history.enableAdd( cfg.preferences.storeHistory ); history.enableAdd( cfg.preferences.storeHistory );
} }

View file

@ -76,8 +76,6 @@ private:
void commitData(); void commitData();
bool commitDataCompleted; bool commitDataCompleted;
bool showHistory;
QSystemTrayIcon * trayIcon; QSystemTrayIcon * trayIcon;
Ui::MainWindow ui; Ui::MainWindow ui;
@ -339,6 +337,8 @@ private slots:
void showTranslationFor( QString const &, unsigned inGroup = 0 ); void showTranslationFor( QString const &, unsigned inGroup = 0 );
void showHistoryItem( QString const & );
void trayIconActivated( QSystemTrayIcon::ActivationReason ); void trayIconActivated( QSystemTrayIcon::ActivationReason );
void scanEnableToggled( bool ); void scanEnableToggled( bool );
@ -379,6 +379,8 @@ private slots:
void updateSearchPaneAndBar( bool searchInDock ); void updateSearchPaneAndBar( bool searchInDock );
void updateHistoryMenu();
/// Add word to history /// Add word to history
void addWordToHistory( const QString & word ); void addWordToHistory( const QString & word );
/// Add word to history even if history is disabled in options /// Add word to history even if history is disabled in options

View file

@ -280,6 +280,36 @@
</layout> </layout>
</widget> </widget>
</widget> </widget>
<widget class="QDockWidget" name="historyPane">
<property name="windowTitle">
<string>&amp;History Pane</string>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
</attribute>
<widget class="HistoryPaneWidget" name="historyPaneWidget">
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>2</number>
</property>
<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="QListView" name="historyList"/>
</item>
</layout>
</widget>
</widget>
<action name="dictionaries"> <action name="dictionaries">
<property name="icon"> <property name="icon">
<iconset resource="resources.qrc"> <iconset resource="resources.qrc">
@ -478,6 +508,12 @@
<header>maintabwidget.hh</header> <header>maintabwidget.hh</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
<customwidget>
<class>HistoryPaneWidget</class>
<extends>QWidget</extends>
<header>historypanewidget.hh</header>
<container>1</container>
</customwidget>
</customwidgets> </customwidgets>
<tabstops> <tabstops>
<tabstop>translateLine</tabstop> <tabstop>translateLine</tabstop>

View file

@ -128,6 +128,7 @@ Preferences::Preferences( QWidget * parent, Config::Preferences const & p ):
ui.scanPopupUseGDMessage->setChecked( p.scanPopupUseGDMessage ); ui.scanPopupUseGDMessage->setChecked( p.scanPopupUseGDMessage );
ui.storeHistory->setChecked( p.storeHistory ); ui.storeHistory->setChecked( p.storeHistory );
ui.historyMaxSizeField->setValue( p.maxStringsInHistory );
ui.alwaysExpandOptionalParts->setChecked( p.alwaysExpandOptionalParts ); ui.alwaysExpandOptionalParts->setChecked( p.alwaysExpandOptionalParts );
// Different platforms have different keys available // Different platforms have different keys available
@ -256,6 +257,7 @@ Config::Preferences Preferences::getPreferences()
p.scanPopupUseGDMessage = ui.scanPopupUseGDMessage->isChecked(); p.scanPopupUseGDMessage = ui.scanPopupUseGDMessage->isChecked();
p.storeHistory = ui.storeHistory->isChecked(); p.storeHistory = ui.storeHistory->isChecked();
p.maxStringsInHistory = ui.historyMaxSizeField->text().toUInt();
p.alwaysExpandOptionalParts = ui.alwaysExpandOptionalParts->isChecked(); p.alwaysExpandOptionalParts = ui.alwaysExpandOptionalParts->isChecked();
p.pronounceOnLoadMain = ui.pronounceOnLoadMain->isChecked(); p.pronounceOnLoadMain = ui.pronounceOnLoadMain->isChecked();

View file

@ -1119,7 +1119,7 @@ It is not needed to select this option if you don't use such programs.</string>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QGroupBox" name="groupBox_5"> <widget class="QGroupBox" name="historyBox">
<property name="title"> <property name="title">
<string>History</string> <string>History</string>
</property> </property>
@ -1132,8 +1132,54 @@ It is not needed to select this option if you don't use such programs.</string>
<property name="text"> <property name="text">
<string>Store &amp;history</string> <string>Store &amp;history</string>
</property> </property>
<property name="checked">
<bool>true</bool>
</property>
</widget> </widget>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="historySizeLabel">
<property name="toolTip">
<string>Specify the maximum number of entries to keep in history.</string>
</property>
<property name="text">
<string>Maximum history size:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="historyMaxSizeField">
<property name="accelerated">
<bool>true</bool>
</property>
<property name="maximum">
<number>9999</number>
</property>
<property name="value">
<number>500</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_8">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>

View file

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

View file

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

View file

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

View file

@ -53,7 +53,7 @@ bool CompletionList::acceptCurrentEntry()
} }
TranslateBox::TranslateBox(QWidget *parent) : QWidget(parent), TranslateBox::TranslateBox(QWidget *parent) : QWidget(parent),
word_list(new CompletionList(this)) word_list(new CompletionList(this)), m_popupEnabled(true)
{ {
// initially hidden // initially hidden
word_list->hide(); word_list->hide();
@ -185,6 +185,11 @@ bool TranslateBox::eventFilter(QObject *obj, QEvent *event)
return QWidget::eventFilter(obj, event); return QWidget::eventFilter(obj, event);
} }
void TranslateBox::setPopupEnabled( bool enable )
{
m_popupEnabled = enable;
}
void TranslateBox::showPopup() void TranslateBox::showPopup()
{ {
// completer->setCompletionPrefix( m_fileLineEdit->text() ); // completer->setCompletionPrefix( m_fileLineEdit->text() );
@ -202,6 +207,11 @@ void TranslateBox::showPopup()
return; return;
} }
if ( !m_popupEnabled )
{
word_list->hide();
return;
}
const QSize size(width(), word_list->preferredHeight()); const QSize size(width(), word_list->preferredHeight());

View file

@ -42,6 +42,7 @@ public:
signals: signals:
public slots: public slots:
void setPopupEnabled(bool enable);
private slots: private slots:
void showPopup(); void showPopup();
@ -51,6 +52,7 @@ private:
bool eventFilter(QObject *obj, QEvent *event); bool eventFilter(QObject *obj, QEvent *event);
CompletionList * word_list; CompletionList * word_list;
ExtLineEdit * translate_line; ExtLineEdit * translate_line;
bool m_popupEnabled;
// QCompleter * completer; // disabled for now // QCompleter * completer; // disabled for now
}; };