From d24f813f3f2a05c112e803e4256b53535895fc98 Mon Sep 17 00:00:00 2001 From: Jedidiah Barber Date: Wed, 14 Jul 2021 11:49:10 +1200 Subject: Initial mirror commit --- src/main-view/FindPanel.cpp | 258 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 258 insertions(+) create mode 100644 src/main-view/FindPanel.cpp (limited to 'src/main-view/FindPanel.cpp') diff --git a/src/main-view/FindPanel.cpp b/src/main-view/FindPanel.cpp new file mode 100644 index 0000000..755fa50 --- /dev/null +++ b/src/main-view/FindPanel.cpp @@ -0,0 +1,258 @@ +#include "FindPanel.h" + +#include +#include +#include +#include + +#include "DictTableView.h" +#include "MainWindow.h" + +FindPanel::FindPanel( MainWindow* aMainWindow ): + QWidget( aMainWindow ), + m_mainWindow( aMainWindow ), m_direction( 1 ), m_foundOnce(false) + { + m_closeButton = new QToolButton; + m_closeButton->setAutoRaise(true); + m_closeButton->setIcon(QIcon(":/images/gray-cross.png")); + m_closeButton->setToolTip(tr("Close")); + + QLabel* textLabel = new QLabel(tr("Find:", "Title of the find pane")); + + m_textEdit = new QComboBox; + textLabel->setBuddy(m_textEdit); + m_textEdit->setEditable(true); + m_textEdit->setInsertPolicy( QComboBox::NoInsert ); + m_textEdit->setMaxCount( ComboBoxMaxItems ); + m_textEdit->setMinimumWidth( TextEditMinWidth ); + m_textEdit->setFocus(); + + m_findBackwardBtn = new QToolButton; + m_findBackwardBtn->resize(32, 32); + m_findBackwardBtn->setObjectName("backward"); + m_findBackwardBtn->setIcon(QIcon(":/images/1leftarrow.png")); + m_findBackwardBtn->setToolTip(tr("Find previous")); + m_findBackwardBtn->setEnabled(false); + + m_findForwardBtn = new QToolButton; + m_findForwardBtn->setObjectName("forward"); + m_findForwardBtn->setIcon(QIcon(":/images/1rightarrow.png")); + m_findForwardBtn->setToolTip(tr("Find next")); + m_findForwardBtn->setEnabled(false); + + m_caseSensitiveBtn = new QToolButton; + m_caseSensitiveBtn->setAutoRaise(true); + m_caseSensitiveBtn->setCheckable( true ); + m_caseSensitiveBtn->setIcon(QIcon(":/images/Aa.png")); + m_caseSensitiveBtn->setToolTip(tr("Case sensitive")); + + m_wholeWordsBtn = new QToolButton; + m_wholeWordsBtn->setAutoRaise(true); + m_wholeWordsBtn->setCheckable( true ); + m_wholeWordsBtn->setIcon(QIcon(":/images/whole-words.png")); + m_wholeWordsBtn->setToolTip(tr("Whole words")); + + m_regExpBtn = new QToolButton; + m_regExpBtn->setAutoRaise(true); + m_regExpBtn->setCheckable( true ); + m_regExpBtn->setIcon(QIcon(":/images/RX.png")); + m_regExpBtn->setToolTip(tr("Regular expression")); + + m_inSelectionBtn = new QToolButton; + m_inSelectionBtn->setAutoRaise(true); + m_inSelectionBtn->setCheckable( true ); + m_inSelectionBtn->setIcon(QIcon(":/images/selection.png")); + m_inSelectionBtn->setToolTip(tr("In selection")); + + QLabel* infoIconLbl = new QLabel; + infoIconLbl->setPixmap( QPixmap(":/images/warning.png").scaled( + 16, 16, Qt::KeepAspectRatio, Qt::SmoothTransformation ) ); + m_infoLbl = new QLabel(tr("String is not found")); + QHBoxLayout* infoLt = new QHBoxLayout; + infoLt->setContentsMargins( QMargins() ); + infoLt->addWidget( infoIconLbl ); + infoLt->addWidget( m_infoLbl ); + m_infoPane = new QWidget; + m_infoPane->setLayout( infoLt ); + m_infoPane->hide(); + + QHBoxLayout* mainLayout = new QHBoxLayout; + mainLayout->addWidget( m_closeButton ); + mainLayout->addWidget( textLabel ); + mainLayout->addWidget( m_textEdit ); + mainLayout->addWidget( m_findBackwardBtn ); + mainLayout->addWidget( m_findForwardBtn ); + mainLayout->addWidget( m_caseSensitiveBtn ); + mainLayout->addWidget( m_wholeWordsBtn ); + mainLayout->addWidget( m_regExpBtn ); + mainLayout->addWidget( m_inSelectionBtn ); + mainLayout->addSpacing( 50 ); + mainLayout->addWidget( m_infoPane ); + mainLayout->addStretch(); + mainLayout->setContentsMargins( QMargins() ); + setLayout( mainLayout ); + + connect( m_inSelectionBtn, SIGNAL(toggled(bool)), SLOT(updateFindButtons()) ); + connect( m_textEdit, SIGNAL(editTextChanged(const QString&)), SLOT(updateFindButtons()) ); + connect( m_textEdit, SIGNAL(editTextChanged(const QString&)), m_infoPane, SLOT(hide()) ); + connect( m_findForwardBtn, SIGNAL(clicked()), this, SLOT(find()) ); + connect( m_findBackwardBtn, SIGNAL(clicked()), this, SLOT(find()) ); + connect( m_closeButton, SIGNAL(clicked()), this, SLOT(hide()) ); + } + +void FindPanel::show() + { + m_textEdit->setFocus(); + m_textEdit->lineEdit()->selectAll(); + QWidget::show(); + } + +void FindPanel::keyPressEvent( QKeyEvent* event ) + { + if( event->key() == Qt::Key_Return ) + find(); + else + QWidget::keyPressEvent( event ); + } + +/** + @arg aDirection 1 = forward; -1 = backward; 0 = previous direction + */ +void FindPanel::find() + { + // Check controls + QString searchText = m_textEdit->currentText(); + if( searchText.isEmpty() ) + return; + + DictTableView* tableView = const_cast( m_mainWindow->getCurDictView() ); + QModelIndexList rows = tableView->selectionModel()->selectedRows(); + if( rows.size() <= 1 && m_inSelectionBtn->isChecked() ) + m_inSelectionBtn->setChecked( false ); + + // Process search parameters + bool inSelection = m_inSelectionBtn->isChecked(); + bool fromCursor = true; + if( inSelection || (rows.size() == 1 && rows.first().row() == 0 ) ) + fromCursor = false; + + // Process direction + if( sender() ) + { + if( sender()->objectName() == "forward" ) + m_direction = 1; + else if( sender()->objectName() == "backward" ) + m_direction = -1; + } + // For "find again" case, the direction stays the same + + // Save the entered text to combobox + int textIndex = m_textEdit->findText( searchText ); + if( textIndex != 0 ) // Don't re-add the same text at the first line + { + if( textIndex > -1 ) // Remove duplicates + m_textEdit->removeItem( textIndex ); + m_textEdit->insertItem( 0, searchText ); + } + + // Create the search regular expression + QString searchRegExpStr; + if( !m_regExpBtn->isChecked() ) + searchRegExpStr = QRegExp::escape( searchText ); + else + searchRegExpStr = searchText; + if( m_wholeWordsBtn->isChecked() ) + searchRegExpStr = "\\b" + searchText + "\\b"; + + QRegExp searchRegExp = QRegExp( searchRegExpStr, + m_caseSensitiveBtn->isChecked()? Qt::CaseSensitive : Qt::CaseInsensitive); + + // Get sorted search range + QModelIndexList searchRange; + if( inSelection ) + { + searchRange = tableView->selectionModel()->selectedIndexes(); + qSort( searchRange ); + } + else // all indexes + { + QAbstractItemModel* tableModel = tableView->model(); + for(int r=0; r < tableModel->rowCount(); r++) + for(int c=0; c < tableModel->columnCount(); c++) + searchRange << tableModel->index(r, c); + } + + // Get the starting search point (iterator) + QListIterator startingPoint( searchRange ); + if( fromCursor ) + { + bool ok = startingPoint.findNext( tableView->currentIndex() ); + if( !ok ) + startingPoint.toFront(); + if( ok && m_direction < 0 ) + startingPoint.previous(); // Go one item backwards + } + else + if( m_direction < 0 ) + startingPoint.toBack(); + + // Try to find the regexp + bool found = findRegExp( searchRegExp, startingPoint ); + if ( !found && fromCursor ) + { + // Continue searching + m_mainWindow->showContinueSearch(); + if( m_direction > 0 ) + startingPoint.toFront(); + else + startingPoint.toBack(); + if( findRegExp( searchRegExp, startingPoint ) ) + found = true; + } + if( !found ) + m_infoPane->show(); + } + +bool FindPanel::findRegExp( const QRegExp& aSearchRegExp, QListIterator aStartingPoint ) + { + DictTableView* tableView = const_cast( m_mainWindow->getCurDictView() ); + QModelIndex foundIndex; + while( (m_direction > 0)? aStartingPoint.hasNext() : aStartingPoint.hasPrevious() ) + { + QModelIndex index = (m_direction > 0)? aStartingPoint.next() : aStartingPoint.previous(); + QString valueStr = index.data( Qt::EditRole ).toString(); // Search in display, not edit, strings. Matters for . + if( valueStr.contains( aSearchRegExp ) ) + { + foundIndex = index; + break; + } + } + if( foundIndex.isValid() ) + { + tableView->setFocus(); + tableView->setCurrentIndex( foundIndex ); + return true; + } + else + return false; + } + +void FindPanel::updateFindButtons() + { + m_findForwardBtn->setEnabled( !m_textEdit->currentText().isEmpty() ); + m_findBackwardBtn->setEnabled( !m_textEdit->currentText().isEmpty() && !m_inSelectionBtn->isChecked() ); + } + +bool FindPanel::canFindAgain() + { + if( !m_foundOnce ) + return false; + const DictTableView* tableView = m_mainWindow->getCurDictView(); + if( tableView && !m_textEdit->currentText().isEmpty() ) + return true; + else + return false; + } + + + -- cgit