Gui: add search box to text editor
This commit is contained in:
@@ -25,9 +25,12 @@
|
||||
#ifndef _PreComp_
|
||||
# include <QAbstractTextDocumentLayout>
|
||||
# include <QApplication>
|
||||
# include <QCheckBox>
|
||||
# include <QClipboard>
|
||||
# include <QDateTime>
|
||||
# include <QHBoxLayout>
|
||||
# include <QVBoxLayout>
|
||||
# include <QLineEdit>
|
||||
# include <QMessageBox>
|
||||
# include <QPainter>
|
||||
# include <QPrinter>
|
||||
@@ -35,10 +38,15 @@
|
||||
# include <QScrollBar>
|
||||
# include <QPlainTextEdit>
|
||||
# include <QPrintPreviewDialog>
|
||||
# include <QSpacerItem>
|
||||
# include <QStyle>
|
||||
# include <QTextBlock>
|
||||
# include <QTextCodec>
|
||||
# include <QTextCursor>
|
||||
# include <QTextDocument>
|
||||
# include <QTextStream>
|
||||
# include <QTimer>
|
||||
# include <QToolButton>
|
||||
#endif
|
||||
|
||||
#include "EditorView.h"
|
||||
@@ -59,6 +67,7 @@ namespace Gui {
|
||||
class EditorViewP {
|
||||
public:
|
||||
QPlainTextEdit* textEdit;
|
||||
SearchBar* searchBar;
|
||||
QString fileName;
|
||||
EditorView::DisplayName displayName;
|
||||
QTimer* activityTimer;
|
||||
@@ -90,19 +99,28 @@ EditorView::EditorView(QPlainTextEdit* editor, QWidget* parent)
|
||||
d->textEdit = editor;
|
||||
d->textEdit->setLineWrapMode(QPlainTextEdit::NoWrap);
|
||||
|
||||
d->searchBar = new SearchBar();
|
||||
d->searchBar->setEditor(editor);
|
||||
|
||||
// update editor actions on request
|
||||
Gui::MainWindow* mw = Gui::getMainWindow();
|
||||
connect(editor, SIGNAL(undoAvailable(bool)), mw, SLOT(updateEditorActions()));
|
||||
connect(editor, SIGNAL(redoAvailable(bool)), mw, SLOT(updateEditorActions()));
|
||||
connect(editor, SIGNAL(copyAvailable(bool)), mw, SLOT(updateEditorActions()));
|
||||
|
||||
connect(editor, SIGNAL(showSearchBar()), d->searchBar, SLOT(activate()));
|
||||
connect(editor, SIGNAL(findNext()), d->searchBar, SLOT(findNext()));
|
||||
connect(editor, SIGNAL(findPrevious()), d->searchBar, SLOT(findPrevious()));
|
||||
|
||||
// Create the layout containing the workspace and a tab bar
|
||||
QFrame* hbox = new QFrame(this);
|
||||
hbox->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
|
||||
QHBoxLayout* layout = new QHBoxLayout();
|
||||
QVBoxLayout* layout = new QVBoxLayout();
|
||||
layout->setMargin(1);
|
||||
layout->addWidget(d->textEdit);
|
||||
layout->addWidget(d->searchBar);
|
||||
d->textEdit->setParent(hbox);
|
||||
d->searchBar->setParent(hbox);
|
||||
hbox->setLayout(layout);
|
||||
setCentralWidget(hbox);
|
||||
|
||||
@@ -650,4 +668,173 @@ void PythonEditorView::hideDebugMarker()
|
||||
_pye->hideDebugMarker();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
SearchBar::SearchBar(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, textEditor(nullptr)
|
||||
{
|
||||
horizontalLayout = new QHBoxLayout(this);
|
||||
horizontalLayout->setSpacing(3);
|
||||
|
||||
closeButton = new QToolButton(this);
|
||||
closeButton->setIcon(style()->standardIcon(QStyle::SP_DialogCloseButton));
|
||||
closeButton->setAutoRaise(true);
|
||||
connect(closeButton, &QToolButton::clicked, this, &SearchBar::deactivate);
|
||||
|
||||
horizontalLayout->addWidget(closeButton);
|
||||
|
||||
searchText = new QLineEdit(this);
|
||||
searchText->setClearButtonEnabled(true);
|
||||
horizontalLayout->addWidget(searchText);
|
||||
connect(searchText, &QLineEdit::returnPressed, this, &SearchBar::findNext);
|
||||
connect(searchText, &QLineEdit::textChanged, this, &SearchBar::findCurrent);
|
||||
connect(searchText, &QLineEdit::textChanged, this, &SearchBar::updateButtons);
|
||||
|
||||
prevButton = new QToolButton(this);
|
||||
prevButton->setIcon(style()->standardIcon(QStyle::SP_ArrowBack));
|
||||
prevButton->setAutoRaise(true);
|
||||
prevButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
||||
horizontalLayout->addWidget(prevButton);
|
||||
connect(prevButton, &QToolButton::clicked, this, &SearchBar::findPrevious);
|
||||
|
||||
nextButton = new QToolButton(this);
|
||||
nextButton->setIcon(style()->standardIcon(QStyle::SP_ArrowForward));
|
||||
nextButton->setAutoRaise(true);
|
||||
nextButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
||||
horizontalLayout->addWidget(nextButton);
|
||||
connect(nextButton, &QToolButton::clicked, this, &SearchBar::findNext);
|
||||
|
||||
matchCase = new QCheckBox(this);
|
||||
horizontalLayout->addWidget(matchCase);
|
||||
connect(matchCase, &QCheckBox::toggled, this, &SearchBar::findCurrent);
|
||||
|
||||
matchWord = new QCheckBox(this);
|
||||
horizontalLayout->addWidget(matchWord);
|
||||
connect(matchWord, &QCheckBox::toggled, this, &SearchBar::findCurrent);
|
||||
|
||||
horizontalSpacer = new QSpacerItem(192, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
horizontalLayout->addItem(horizontalSpacer);
|
||||
|
||||
retranslateUi();
|
||||
|
||||
setMinimumWidth(minimumSizeHint().width());
|
||||
updateButtons();
|
||||
hide();
|
||||
}
|
||||
|
||||
void SearchBar::setEditor(QPlainTextEdit* textEdit)
|
||||
{
|
||||
textEditor = textEdit;
|
||||
}
|
||||
|
||||
void SearchBar::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
if (event->key() == Qt::Key_Escape) {
|
||||
hide();
|
||||
return;
|
||||
}
|
||||
|
||||
QWidget::keyPressEvent(event);
|
||||
}
|
||||
|
||||
void SearchBar::retranslateUi()
|
||||
{
|
||||
prevButton->setText(tr("Previous"));
|
||||
nextButton->setText(tr("Next"));
|
||||
matchCase->setText(tr("Case sensitive"));
|
||||
matchWord->setText(tr("Whole words"));
|
||||
}
|
||||
|
||||
void SearchBar::activate()
|
||||
{
|
||||
show();
|
||||
searchText->selectAll();
|
||||
searchText->setFocus(Qt::ShortcutFocusReason);
|
||||
}
|
||||
|
||||
void SearchBar::deactivate()
|
||||
{
|
||||
if (textEditor)
|
||||
textEditor->setFocus();
|
||||
hide();
|
||||
}
|
||||
|
||||
void SearchBar::findPrevious()
|
||||
{
|
||||
findText(true, false, searchText->text());
|
||||
}
|
||||
|
||||
void SearchBar::findNext()
|
||||
{
|
||||
findText(true, true, searchText->text());
|
||||
}
|
||||
|
||||
void SearchBar::findCurrent()
|
||||
{
|
||||
findText(false, true, searchText->text());
|
||||
}
|
||||
|
||||
void SearchBar::findText(bool skip, bool next, const QString& str)
|
||||
{
|
||||
if (!textEditor)
|
||||
return;
|
||||
|
||||
QTextCursor cursor = textEditor->textCursor();
|
||||
QTextDocument *doc = textEditor->document();
|
||||
if (!doc || cursor.isNull())
|
||||
return;
|
||||
|
||||
if (cursor.hasSelection())
|
||||
cursor.setPosition((skip && next) ? cursor.position() : cursor.anchor());
|
||||
|
||||
bool found = true;
|
||||
QTextCursor newCursor = cursor;
|
||||
if (!str.isEmpty()) {
|
||||
QTextDocument::FindFlags options;
|
||||
if (!next)
|
||||
options |= QTextDocument::FindBackward;
|
||||
if (matchCase->isChecked())
|
||||
options |= QTextDocument::FindCaseSensitively;
|
||||
if (matchWord->isChecked())
|
||||
options |= QTextDocument::FindWholeWords;
|
||||
|
||||
newCursor = doc->find(str, cursor, options);
|
||||
if (newCursor.isNull()) {
|
||||
QTextCursor ac(doc);
|
||||
ac.movePosition(options & QTextDocument::FindBackward ? QTextCursor::End : QTextCursor::Start);
|
||||
newCursor = doc->find(str, ac, options);
|
||||
if (newCursor.isNull()) {
|
||||
found = false;
|
||||
newCursor = cursor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isVisible())
|
||||
show();
|
||||
|
||||
textEditor->setTextCursor(newCursor);
|
||||
|
||||
QPalette palette;
|
||||
palette.setColor(QPalette::Active, QPalette::Base, found ? Qt::white : QColor(255, 80, 80));
|
||||
searchText->setPalette(palette);
|
||||
}
|
||||
|
||||
void SearchBar::updateButtons()
|
||||
{
|
||||
bool empty = searchText->text().isEmpty();
|
||||
prevButton->setDisabled(empty);
|
||||
nextButton->setDisabled(empty);
|
||||
}
|
||||
|
||||
void SearchBar::changeEvent(QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::LanguageChange) {
|
||||
retranslateUi();
|
||||
}
|
||||
|
||||
QWidget::changeEvent(event);
|
||||
}
|
||||
|
||||
#include "moc_EditorView.cpp"
|
||||
|
||||
@@ -30,6 +30,10 @@
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QPlainTextEdit;
|
||||
class QPrinter;
|
||||
class QHBoxLayout;
|
||||
class QToolButton;
|
||||
class QCheckBox;
|
||||
class QSpacerItem;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Gui {
|
||||
@@ -132,6 +136,43 @@ private:
|
||||
PythonEditor* _pye;
|
||||
};
|
||||
|
||||
class SearchBar : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SearchBar(QWidget* parent = nullptr);
|
||||
|
||||
void setEditor(QPlainTextEdit *textEdit);
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent*);
|
||||
void changeEvent(QEvent*);
|
||||
|
||||
public Q_SLOTS:
|
||||
void activate();
|
||||
void deactivate();
|
||||
void findPrevious();
|
||||
void findNext();
|
||||
void findCurrent();
|
||||
|
||||
private:
|
||||
void retranslateUi();
|
||||
void findText(bool skip, bool next, const QString& str);
|
||||
void updateButtons();
|
||||
|
||||
private:
|
||||
QPlainTextEdit* textEditor;
|
||||
QHBoxLayout* horizontalLayout;
|
||||
QSpacerItem* horizontalSpacer;
|
||||
QToolButton* closeButton;
|
||||
QLineEdit* searchText;
|
||||
QToolButton* prevButton;
|
||||
QToolButton* nextButton;
|
||||
QCheckBox* matchCase;
|
||||
QCheckBox* matchWord;
|
||||
};
|
||||
|
||||
} // namespace Gui
|
||||
|
||||
#endif // GUI_EDITORVIEW_H
|
||||
|
||||
@@ -48,6 +48,21 @@ TextEdit::TextEdit(QWidget* parent)
|
||||
shortcut->setKey(Qt::CTRL+Qt::Key_Space);
|
||||
shortcut->setContext(Qt::WidgetShortcut);
|
||||
connect(shortcut, SIGNAL(activated()), this, SLOT(complete()));
|
||||
|
||||
QShortcut* shortcutFind = new QShortcut(this);
|
||||
shortcutFind->setKey(QKeySequence::Find);
|
||||
shortcutFind->setContext(Qt::WidgetShortcut);
|
||||
connect(shortcutFind, SIGNAL(activated()), this, SIGNAL(showSearchBar()));
|
||||
|
||||
QShortcut* shortcutNext = new QShortcut(this);
|
||||
shortcutNext->setKey(QKeySequence::FindNext);
|
||||
shortcutNext->setContext(Qt::WidgetShortcut);
|
||||
connect(shortcutNext, SIGNAL(activated()), this, SIGNAL(findNext()));
|
||||
|
||||
QShortcut* shortcutPrev = new QShortcut(this);
|
||||
shortcutPrev->setKey(QKeySequence::FindPrevious);
|
||||
shortcutPrev->setContext(Qt::WidgetShortcut);
|
||||
connect(shortcutPrev, SIGNAL(activated()), this, SIGNAL(findPrevious()));
|
||||
}
|
||||
|
||||
/** Destroys the object and frees any allocated resources */
|
||||
|
||||
@@ -64,6 +64,11 @@ public:
|
||||
private Q_SLOTS:
|
||||
void complete();
|
||||
|
||||
Q_SIGNALS:
|
||||
void showSearchBar();
|
||||
void findNext();
|
||||
void findPrevious();
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user