2013-01-17 09:08:53 +00:00
|
|
|
/* This file is (c) 2013 Tvangeste <i.4m.l33t@yandex.ru>
|
|
|
|
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
|
|
|
|
|
|
|
|
#include <QApplication>
|
|
|
|
#include <QDockWidget>
|
|
|
|
#include <QKeyEvent>
|
2013-01-17 13:03:16 +00:00
|
|
|
#include <QClipboard>
|
2021-02-01 15:00:31 +00:00
|
|
|
#include <algorithm>
|
|
|
|
#include <functional>
|
2013-01-17 09:08:53 +00:00
|
|
|
|
|
|
|
#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 );
|
2022-12-26 02:08:17 +00:00
|
|
|
connect( m_deleteSelectedAction, &QAction::triggered, this, &HistoryPaneWidget::deleteSelectedItems );
|
2013-01-17 09:08:53 +00:00
|
|
|
|
2013-01-17 13:03:16 +00:00
|
|
|
// Copy selected items to clipboard
|
|
|
|
m_copySelectedToClipboard = new QAction( this );
|
|
|
|
m_copySelectedToClipboard->setText( tr( "Copy Selected" ) );
|
|
|
|
m_copySelectedToClipboard->setShortcut( QKeySequence( QKeySequence::Copy ) );
|
|
|
|
m_copySelectedToClipboard->setShortcutContext( Qt::WidgetWithChildrenShortcut );
|
|
|
|
addAction( m_copySelectedToClipboard );
|
2022-12-26 02:08:17 +00:00
|
|
|
connect( m_copySelectedToClipboard, &QAction::triggered, this, &HistoryPaneWidget::copySelectedItems );
|
2013-01-17 13:03:16 +00:00
|
|
|
|
|
|
|
|
2013-01-17 09:08:53 +00:00
|
|
|
// 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
|
2022-12-26 02:08:17 +00:00
|
|
|
connect( m_historyList, &QAbstractItemView::clicked, this, &HistoryPaneWidget::onItemClicked );
|
|
|
|
connect( m_history, &History::itemsChanged, this, &HistoryPaneWidget::updateHistoryCounts );
|
2013-01-17 09:08:53 +00:00
|
|
|
connect ( m_historyList->selectionModel(), SIGNAL( selectionChanged ( QItemSelection const & , QItemSelection const & ) ),
|
|
|
|
this, SLOT( onSelectionChanged( QItemSelection const & ) ) );
|
|
|
|
|
2022-12-26 02:08:17 +00:00
|
|
|
connect( m_historyList, &QWidget::customContextMenuRequested, this, &HistoryPaneWidget::showCustomMenu );
|
2013-01-17 09:08:53 +00:00
|
|
|
|
2013-07-06 15:31:31 +00:00
|
|
|
listItemDelegate = new WordListItemDelegate( m_historyList->itemDelegate() );
|
|
|
|
m_historyList->setItemDelegate( listItemDelegate );
|
|
|
|
}
|
|
|
|
|
|
|
|
HistoryPaneWidget::~HistoryPaneWidget()
|
|
|
|
{
|
|
|
|
if( listItemDelegate )
|
|
|
|
delete listItemDelegate;
|
2013-01-17 09:08:53 +00:00
|
|
|
}
|
|
|
|
|
2013-01-17 13:03:16 +00:00
|
|
|
void HistoryPaneWidget::copySelectedItems()
|
|
|
|
{
|
|
|
|
QModelIndexList selectedIdxs = m_historyList->selectionModel()->selectedIndexes();
|
|
|
|
|
|
|
|
if ( selectedIdxs.isEmpty() )
|
|
|
|
{
|
|
|
|
// nothing to do
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QStringList selectedStrings;
|
|
|
|
QListIterator<QModelIndex> i( selectedIdxs );
|
|
|
|
while ( i.hasNext() )
|
|
|
|
{
|
|
|
|
selectedStrings << m_historyList->model()->data( i.next() ).toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
QApplication::clipboard()->setText( selectedStrings.join( QString::fromLatin1( "\n" ) ) );
|
|
|
|
}
|
|
|
|
|
2013-01-17 09:08:53 +00:00
|
|
|
void HistoryPaneWidget::deleteSelectedItems()
|
|
|
|
{
|
|
|
|
QModelIndexList selectedIdxs = m_historyList->selectionModel()->selectedIndexes();
|
|
|
|
|
|
|
|
if ( selectedIdxs.isEmpty() )
|
|
|
|
{
|
|
|
|
// nothing to do
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QList<int> idxsToDelete;
|
|
|
|
|
2013-01-17 13:03:16 +00:00
|
|
|
QListIterator<QModelIndex> i( selectedIdxs );
|
2013-01-17 09:08:53 +00:00
|
|
|
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.
|
2021-02-01 15:00:31 +00:00
|
|
|
std::sort( idxsToDelete.begin(), idxsToDelete.end(), std::greater<int>() );
|
2013-01-17 09:08:53 +00:00
|
|
|
|
|
|
|
QListIterator<int> idxs( idxsToDelete );
|
|
|
|
while ( idxs.hasNext() )
|
|
|
|
m_history->removeItem( idxs.next() );
|
|
|
|
|
2013-01-17 15:11:06 +00:00
|
|
|
if ( idxsToDelete.size() == 1 )
|
2013-01-17 09:08:53 +00:00
|
|
|
{
|
|
|
|
// We've just removed a single entry,
|
|
|
|
// keep the selection at the same index.
|
2013-01-17 15:11:06 +00:00
|
|
|
m_historyList->setCurrentIndex(selectedIdxs.front());
|
2013-01-17 09:08:53 +00:00
|
|
|
m_historyList->selectionModel()->select(
|
2013-01-17 15:11:06 +00:00
|
|
|
selectedIdxs.front(), QItemSelectionModel::SelectCurrent );
|
2013-01-17 09:08:53 +00:00
|
|
|
}
|
|
|
|
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();
|
|
|
|
|
2013-01-17 13:03:16 +00:00
|
|
|
m_historyMenu->removeAction( m_copySelectedToClipboard );
|
2013-01-17 09:08:53 +00:00
|
|
|
m_historyMenu->removeAction( m_deleteSelectedAction );
|
2013-01-17 13:03:16 +00:00
|
|
|
|
2013-01-17 09:08:53 +00:00
|
|
|
m_separator->setVisible( !selectionEmpty );
|
|
|
|
|
|
|
|
if ( !selectionEmpty )
|
2013-01-17 13:03:16 +00:00
|
|
|
{
|
|
|
|
m_historyMenu->insertAction( m_separator, m_copySelectedToClipboard );
|
2013-01-17 09:08:53 +00:00
|
|
|
m_historyMenu->insertAction( m_separator, m_deleteSelectedAction );
|
2013-01-17 13:03:16 +00:00
|
|
|
}
|
2013-01-17 09:08:53 +00:00
|
|
|
|
|
|
|
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;
|
2022-12-01 02:19:48 +00:00
|
|
|
emitHistoryItemRequested( selection.front().topLeft() );
|
2013-01-17 09:08:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void HistoryPaneWidget::onItemClicked( QModelIndex const & idx )
|
|
|
|
{
|
|
|
|
// qDebug() << "clicked";
|
|
|
|
|
2022-12-01 02:19:48 +00:00
|
|
|
if ( !itemSelectionChanged )
|
2013-01-17 09:08:53 +00:00
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
|
2022-12-26 02:08:17 +00:00
|
|
|
connect( m_history, &History::itemsChanged, this, &HistoryModel::historyChanged );
|
2013-01-17 09:08:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2013-01-17 14:24:13 +00:00
|
|
|
if ( role == Qt::DisplayRole || role == Qt::ToolTipRole )
|
2013-01-17 09:08:53 +00:00
|
|
|
{
|
|
|
|
return m_history->getItem( index.row() ).word;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return QVariant();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void HistoryModel::historyChanged()
|
|
|
|
{
|
|
|
|
// qDebug() << "History Changed!!";
|
|
|
|
|
2013-05-30 13:24:21 +00:00
|
|
|
beginResetModel();
|
|
|
|
endResetModel();
|
2013-01-17 09:08:53 +00:00
|
|
|
}
|