From eaab820d8be1e06862c32d1233ae6c857b0c7234 Mon Sep 17 00:00:00 2001 From: Le Tan Date: Sat, 31 Dec 2016 22:02:01 +0800 Subject: [PATCH] add find and replace dialog Logic is not implemented yet. Signed-off-by: Le Tan --- src/dialog/vfindreplacedialog.cpp | 103 ++++++++++++++++++++++++++++++ src/dialog/vfindreplacedialog.h | 38 +++++++++++ src/resources/icons/close.svg | 10 +++ src/resources/vnote.qss | 24 ++++++- src/src.pro | 6 +- src/veditarea.cpp | 16 +++-- src/veditarea.h | 8 +++ src/vmainwindow.cpp | 11 ++++ src/vmainwindow.h | 1 + src/vmdeditoperations.cpp | 62 +++++++++++++----- src/vmdeditoperations.h | 1 + src/vnote.qrc | 1 + 12 files changed, 258 insertions(+), 23 deletions(-) create mode 100644 src/dialog/vfindreplacedialog.cpp create mode 100644 src/dialog/vfindreplacedialog.h create mode 100644 src/resources/icons/close.svg diff --git a/src/dialog/vfindreplacedialog.cpp b/src/dialog/vfindreplacedialog.cpp new file mode 100644 index 00000000..30781c36 --- /dev/null +++ b/src/dialog/vfindreplacedialog.cpp @@ -0,0 +1,103 @@ +#include "vfindreplacedialog.h" +#include + +VFindReplaceDialog::VFindReplaceDialog(QWidget *p_parent) + : QWidget(p_parent) +{ + setupUI(); +} + +void VFindReplaceDialog::setupUI() +{ + QLabel *titleLabel = new QLabel(tr("Find/Replace")); + titleLabel->setProperty("TitleLabel", true); + m_closeBtn = new QPushButton(QIcon(":/resources/icons/close.svg"), ""); + m_closeBtn->setProperty("TitleBtn", true); + QHBoxLayout *titleLayout = new QHBoxLayout(); + titleLayout->addWidget(titleLabel); + titleLayout->addWidget(m_closeBtn); + titleLayout->setStretch(0, 1); + titleLayout->setStretch(1, 0); + titleLayout->setContentsMargins(0, 0, 0, 0); + titleLayout->setSpacing(0); + + // Find + QLabel *findLabel = new QLabel(tr("&Find:")); + m_findEdit = new QLineEdit(); + findLabel->setBuddy(m_findEdit); + m_findNextBtn = new QPushButton(tr("Find Next")); + m_findNextBtn->setProperty("FlatBtn", true); + m_findNextBtn->setDefault(true); + m_findPrevBtn = new QPushButton(tr("Find Previous")); + m_findPrevBtn->setProperty("FlatBtn", true); + + // Replace + QLabel *replaceLabel = new QLabel(tr("&Replace with:")); + m_replaceEdit = new QLineEdit(); + replaceLabel->setBuddy(m_replaceEdit); + m_replaceBtn = new QPushButton(tr("Replace")); + m_replaceBtn->setProperty("FlatBtn", true); + m_replaceFindBtn = new QPushButton(tr("Replace && Find")); + m_replaceFindBtn->setProperty("FlatBtn", true); + m_replaceAllBtn = new QPushButton(tr("Replace All")); + m_replaceAllBtn->setProperty("FlatBtn", true); + m_advancedBtn = new QPushButton(tr("Advanced")); + m_advancedBtn->setProperty("FlatBtn", true); + + QGridLayout *gridLayout = new QGridLayout(); + gridLayout->addWidget(findLabel, 0, 0); + gridLayout->addWidget(m_findEdit, 0, 1); + gridLayout->addWidget(m_findNextBtn, 0, 2); + gridLayout->addWidget(m_findPrevBtn, 0, 3); + gridLayout->addWidget(replaceLabel, 1, 0); + gridLayout->addWidget(m_replaceEdit, 1, 1); + gridLayout->addWidget(m_replaceBtn, 1, 2); + gridLayout->addWidget(m_replaceFindBtn, 1, 3); + gridLayout->addWidget(m_replaceAllBtn, 1, 4); + gridLayout->addWidget(m_advancedBtn, 1, 5); + gridLayout->setColumnStretch(0, 0); + gridLayout->setColumnStretch(1, 4); + gridLayout->setColumnStretch(2, 1); + gridLayout->setColumnStretch(3, 1); + gridLayout->setColumnStretch(4, 1); + gridLayout->setColumnStretch(5, 1); + gridLayout->setColumnStretch(6, 3); + QMargins margin = gridLayout->contentsMargins(); + margin.setLeft(3); + gridLayout->setContentsMargins(margin); + + QVBoxLayout *mainLayout = new QVBoxLayout(); + mainLayout->addLayout(titleLayout); + mainLayout->addLayout(gridLayout); + mainLayout->setContentsMargins(0, 0, 0, 0); + + setLayout(mainLayout); + + // Signals + connect(m_closeBtn, &QPushButton::clicked, + this, &VFindReplaceDialog::closeDialog); +} + +void VFindReplaceDialog::closeDialog() +{ + if (this->isVisible()) { + this->hide(); + emit dialogClosed(); + } +} + +void VFindReplaceDialog::showEvent(QShowEvent *event) +{ + m_findEdit->selectAll(); + QWidget::showEvent(event); +} + +void VFindReplaceDialog::keyPressEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_Escape) { + event->accept(); + closeDialog(); + return; + } + QWidget::keyPressEvent(event); +} diff --git a/src/dialog/vfindreplacedialog.h b/src/dialog/vfindreplacedialog.h new file mode 100644 index 00000000..ff8fc91d --- /dev/null +++ b/src/dialog/vfindreplacedialog.h @@ -0,0 +1,38 @@ +#ifndef VFINDREPLACEDIALOG_H +#define VFINDREPLACEDIALOG_H + +#include + +class QLineEdit; +class QPushButton; + +class VFindReplaceDialog : public QWidget +{ + Q_OBJECT +public: + explicit VFindReplaceDialog(QWidget *p_parent = 0); + +signals: + void dialogClosed(); + +protected: + void showEvent(QShowEvent *event) Q_DECL_OVERRIDE; + void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE; + +public slots: + void closeDialog(); + +private: + void setupUI(); + QLineEdit *m_findEdit; + QLineEdit *m_replaceEdit; + QPushButton *m_findNextBtn; + QPushButton *m_findPrevBtn; + QPushButton *m_replaceBtn; + QPushButton *m_replaceFindBtn; + QPushButton *m_replaceAllBtn; + QPushButton *m_advancedBtn; + QPushButton *m_closeBtn; +}; + +#endif // VFINDREPLACEDIALOG_H diff --git a/src/resources/icons/close.svg b/src/resources/icons/close.svg new file mode 100644 index 00000000..2e111a9e --- /dev/null +++ b/src/resources/icons/close.svg @@ -0,0 +1,10 @@ + + + + + + diff --git a/src/resources/vnote.qss b/src/resources/vnote.qss index a6565aff..5aeac35e 100644 --- a/src/resources/vnote.qss +++ b/src/resources/vnote.qss @@ -1,5 +1,5 @@ QPushButton[CornerBtn="true"] { - padding: 0px; + padding: 4px 0px 4px 0px; margin: 0px; border: none; background-color: transparent; @@ -13,6 +13,28 @@ QPushButton[CornerBtn="true"]::hover { background-color: @hover-color; } +QPushButton[FlatBtn="true"] { + padding: 4px; + margin: 0px; + border: none; + background-color: transparent; +} + +QPushButton[FlatBtn="true"]::hover { + background-color: @hover-color; +} + +QPushButton[TitleBtn="true"] { + padding: 4px; + margin: 0px; + border: none; + background-color: @base-color; +} + +QPushButton[TitleBtn="true"]::hover { + background-color: @hover-color; +} + QToolBar { border: none; } diff --git a/src/src.pro b/src/src.pro index 05a2c8d1..1c9a7b9b 100644 --- a/src/src.pro +++ b/src/src.pro @@ -48,7 +48,8 @@ SOURCES += main.cpp\ vnotebookselector.cpp \ vnofocusitemdelegate.cpp \ vavatar.cpp \ - vmdedit.cpp + vmdedit.cpp \ + dialog/vfindreplacedialog.cpp HEADERS += vmainwindow.h \ vdirectorytree.h \ @@ -85,7 +86,8 @@ HEADERS += vmainwindow.h \ vnotebookselector.h \ vnofocusitemdelegate.h \ vavatar.h \ - vmdedit.h + vmdedit.h \ + dialog/vfindreplacedialog.h RESOURCES += \ vnote.qrc diff --git a/src/veditarea.cpp b/src/veditarea.cpp index 39cc40be..e6bb6d23 100644 --- a/src/veditarea.cpp +++ b/src/veditarea.cpp @@ -5,26 +5,33 @@ #include "vnote.h" #include "vconfigmanager.h" #include "vfile.h" +#include "dialog/vfindreplacedialog.h" VEditArea::VEditArea(VNote *vnote, QWidget *parent) : QWidget(parent), vnote(vnote), curWindowIndex(-1) { setupUI(); + + insertSplitWindow(0); + setCurrentWindow(0, false); } void VEditArea::setupUI() { splitter = new QSplitter(this); + m_findReplace = new VFindReplaceDialog(this); - insertSplitWindow(0); - setCurrentWindow(0, false); - - QHBoxLayout *mainLayout = new QHBoxLayout(); + QVBoxLayout *mainLayout = new QVBoxLayout(); mainLayout->addWidget(splitter); + mainLayout->addWidget(m_findReplace); mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->setSpacing(0); + mainLayout->setStretch(0, 1); + mainLayout->setStretch(1, 0); setLayout(mainLayout); + + m_findReplace->hide(); } void VEditArea::insertSplitWindow(int idx) @@ -308,7 +315,6 @@ void VEditArea::handleRemoveSplitRequest(VEditWindow *curWindow) void VEditArea::mousePressEvent(QMouseEvent *event) { - qDebug() << "VEditArea press event" << event; QPoint pos = event->pos(); int nrWin = splitter->count(); for (int i = 0; i < nrWin; ++i) { diff --git a/src/veditarea.h b/src/veditarea.h index 0e1b8ae6..263942ef 100644 --- a/src/veditarea.h +++ b/src/veditarea.h @@ -17,6 +17,7 @@ class VNote; class VFile; class VDirectory; +class VFindReplaceDialog; class VEditArea : public QWidget { @@ -38,6 +39,7 @@ public: // @p_widget has been removed from the original window. // If fail, just delete the p_widget. void moveTab(QWidget *p_widget, int p_fromIdx, int p_toIdx); + inline VFindReplaceDialog *getFindReplaceDialog() const; signals: void curTabStatusChanged(const VFile *p_file, const VEditTab *p_editTab, bool p_editMode); @@ -81,6 +83,7 @@ private: // Splitter holding multiple split windows QSplitter *splitter; + VFindReplaceDialog *m_findReplace; }; inline VEditWindow* VEditArea::getWindow(int windowIndex) const @@ -94,4 +97,9 @@ inline int VEditArea::windowCount() const return splitter->count(); } +inline VFindReplaceDialog *VEditArea::getFindReplaceDialog() const +{ + return m_findReplace; +} + #endif // VEDITAREA_H diff --git a/src/vmainwindow.cpp b/src/vmainwindow.cpp index 9e3dbdcf..ae47139b 100644 --- a/src/vmainwindow.cpp +++ b/src/vmainwindow.cpp @@ -10,6 +10,7 @@ #include "voutline.h" #include "vnotebookselector.h" #include "vavatar.h" +#include "dialog/vfindreplacedialog.h" extern VConfigManager vconfig; @@ -727,6 +728,16 @@ void VMainWindow::resizeEvent(QResizeEvent *event) QMainWindow::resizeEvent(event); } +void VMainWindow::keyPressEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_Escape) { + editArea->getFindReplaceDialog()->closeDialog(); + event->accept(); + return; + } + QMainWindow::keyPressEvent(event); +} + void VMainWindow::repositionAvatar() { int diameter = mainSplitter->pos().y(); diff --git a/src/vmainwindow.h b/src/vmainwindow.h index 06e9df22..73000b25 100644 --- a/src/vmainwindow.h +++ b/src/vmainwindow.h @@ -59,6 +59,7 @@ private slots: protected: void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; + void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE; private: void setupUI(); diff --git a/src/vmdeditoperations.cpp b/src/vmdeditoperations.cpp index 5da3ad09..48351f4a 100644 --- a/src/vmdeditoperations.cpp +++ b/src/vmdeditoperations.cpp @@ -260,11 +260,12 @@ bool VMdEditOperations::handleKeyPressEvent(QKeyEvent *p_event) case Qt::Key_BracketLeft: { - if (p_event->modifiers() != Qt::ControlModifier) { - break; + if (handleKeyBracketLeft(p_event)) { + return true; } - // Ctrl+[, Fall through. + break; } + case Qt::Key_Escape: { if (handleKeyEsc(p_event)) { @@ -281,6 +282,28 @@ bool VMdEditOperations::handleKeyPressEvent(QKeyEvent *p_event) return false; } +bool VMdEditOperations::handleKeyBracketLeft(QKeyEvent *p_event) +{ + // 1. If it is not in Normal state, just go back to Normal state; + // 2. If it is already Normal state, try to clear selection; + // 3. Anyway, we accept this event. + if (p_event->modifiers() == Qt::ControlModifier) { + if (m_keyState != KeyState::Normal) { + m_pendingTimer->stop(); + setKeyState(KeyState::Normal); + m_pendingKey.clear(); + } else { + QTextCursor cursor = m_editor->textCursor(); + if (cursor.hasSelection()) { + cursor.clearSelection(); + m_editor->setTextCursor(cursor); + } + } + } + p_event->accept(); + return true; +} + bool VMdEditOperations::handleKeyTab(QKeyEvent *p_event) { QTextDocument *doc = m_editor->document(); @@ -520,17 +543,27 @@ bool VMdEditOperations::handleKeyW(QKeyEvent *p_event) bool VMdEditOperations::handleKeyEsc(QKeyEvent *p_event) { - // Esc, clear any Vim mode, clear selection. - QTextCursor cursor = m_editor->textCursor(); - cursor.clearSelection(); - m_editor->setTextCursor(cursor); - - m_pendingTimer->stop(); - setKeyState(KeyState::Normal); - m_pendingKey.clear(); - - p_event->accept(); - return true; + // 1. If it is not in Normal state, just go back to Normal state; + // 2. If it is already Normal state, try to clear selection; + // 3. Otherwise, ignore this event and let parent handles it. + bool accept = false; + if (m_keyState != KeyState::Normal) { + m_pendingTimer->stop(); + setKeyState(KeyState::Normal); + m_pendingKey.clear(); + accept = true; + } else { + QTextCursor cursor = m_editor->textCursor(); + if (cursor.hasSelection()) { + cursor.clearSelection(); + m_editor->setTextCursor(cursor); + accept = true; + } + } + if (accept) { + p_event->accept(); + } + return accept; } bool VMdEditOperations::handleKeyPressVim(QKeyEvent *p_event) @@ -925,4 +958,3 @@ void VMdEditOperations::setKeyState(KeyState p_state) m_keyState = p_state; emit keyStateChanged(m_keyState); } - diff --git a/src/vmdeditoperations.h b/src/vmdeditoperations.h index 1acc96ee..b293e1f6 100644 --- a/src/vmdeditoperations.h +++ b/src/vmdeditoperations.h @@ -40,6 +40,7 @@ private: bool handleKeyW(QKeyEvent *p_event); bool handleKeyEsc(QKeyEvent *p_event); bool handleKeyPressVim(QKeyEvent *p_event); + bool handleKeyBracketLeft(QKeyEvent *p_event); bool shouldTriggerVimMode(QKeyEvent *p_event); int keySeqToNumber(const QList &p_seq); bool suffixNumAllowed(const QList &p_seq); diff --git a/src/vnote.qrc b/src/vnote.qrc index b44b2617..599fe364 100644 --- a/src/vnote.qrc +++ b/src/vnote.qrc @@ -81,5 +81,6 @@ resources/icons/move_tab_right.svg resources/icons/corner_menu_cur.svg resources/icons/corner_tablist_cur.svg + resources/icons/close.svg