mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 22:09:52 +08:00
1315 lines
37 KiB
C++
1315 lines
37 KiB
C++
#include "veditarea.h"
|
|
|
|
#include <QtWidgets>
|
|
|
|
#include "veditwindow.h"
|
|
#include "vedittab.h"
|
|
#include "vnote.h"
|
|
#include "vconfigmanager.h"
|
|
#include "vfile.h"
|
|
#include "dialog/vfindreplacedialog.h"
|
|
#include "utils/vutils.h"
|
|
#include "vfilesessioninfo.h"
|
|
#include "vmainwindow.h"
|
|
#include "vcaptain.h"
|
|
#include "vfilelist.h"
|
|
#include "vmathjaxpreviewhelper.h"
|
|
#include "vmdtab.h"
|
|
#include "vmdeditor.h"
|
|
|
|
extern VConfigManager *g_config;
|
|
|
|
extern VNote *g_vnote;
|
|
|
|
extern VMainWindow *g_mainWin;
|
|
|
|
VEditArea::VEditArea(QWidget *parent)
|
|
: QWidget(parent),
|
|
VNavigationMode(),
|
|
curWindowIndex(-1)
|
|
{
|
|
setupUI();
|
|
|
|
insertSplitWindow(0);
|
|
setCurrentWindow(0, false);
|
|
|
|
registerCaptainTargets();
|
|
|
|
initShortcuts();
|
|
|
|
QTimer *timer = new QTimer(this);
|
|
timer->setSingleShot(false);
|
|
timer->setInterval(g_config->getFileTimerInterval());
|
|
connect(timer, &QTimer::timeout,
|
|
this, &VEditArea::handleFileTimerTimeout);
|
|
|
|
timer->start();
|
|
|
|
m_autoSave = g_config->getEnableAutoSave();
|
|
|
|
m_mathPreviewHelper = new VMathJaxPreviewHelper(this, this);
|
|
}
|
|
|
|
void VEditArea::setupUI()
|
|
{
|
|
splitter = new QSplitter(this);
|
|
m_findReplace = new VFindReplaceDialog(this);
|
|
m_findReplace->setOption(FindOption::CaseSensitive,
|
|
g_config->getFindCaseSensitive());
|
|
m_findReplace->setOption(FindOption::WholeWordOnly,
|
|
g_config->getFindWholeWordOnly());
|
|
m_findReplace->setOption(FindOption::RegularExpression,
|
|
g_config->getFindRegularExpression());
|
|
m_findReplace->setOption(FindOption::IncrementalSearch,
|
|
g_config->getFindIncrementalSearch());
|
|
|
|
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);
|
|
|
|
connect(m_findReplace, &VFindReplaceDialog::findTextChanged,
|
|
this, &VEditArea::handleFindTextChanged);
|
|
connect(m_findReplace, &VFindReplaceDialog::findOptionChanged,
|
|
this, &VEditArea::handleFindOptionChanged);
|
|
connect(m_findReplace, SIGNAL(findNext(const QString &, uint, bool)),
|
|
this, SLOT(handleFindNext(const QString &, uint, bool)));
|
|
connect(m_findReplace,
|
|
SIGNAL(replace(const QString &, uint, const QString &, bool)),
|
|
this,
|
|
SLOT(handleReplace(const QString &, uint, const QString &, bool)));
|
|
connect(m_findReplace,
|
|
SIGNAL(replaceAll(const QString &, uint, const QString &)),
|
|
this,
|
|
SLOT(handleReplaceAll(const QString &, uint, const QString &)));
|
|
connect(m_findReplace, &VFindReplaceDialog::dialogClosed,
|
|
this, &VEditArea::handleFindDialogClosed);
|
|
m_findReplace->hide();
|
|
|
|
// Shortcut Ctrl+Shift+T to open last closed file.
|
|
QString keySeq = g_config->getShortcutKeySequence("LastClosedFile");
|
|
qDebug() << "set LastClosedFile shortcut to" << keySeq;
|
|
QShortcut *lastClosedFileShortcut = new QShortcut(QKeySequence(keySeq), this);
|
|
lastClosedFileShortcut->setContext(Qt::ApplicationShortcut);
|
|
connect(lastClosedFileShortcut, &QShortcut::activated,
|
|
this, [this]() {
|
|
if (!m_lastClosedFiles.isEmpty()) {
|
|
const VFileSessionInfo &file = m_lastClosedFiles.top();
|
|
QVector<VFileSessionInfo> files(1, file);
|
|
m_lastClosedFiles.pop();
|
|
|
|
openFiles(files);
|
|
}
|
|
});
|
|
}
|
|
|
|
void VEditArea::initShortcuts()
|
|
{
|
|
QString keySeq = g_config->getShortcutKeySequence("ActivateNextTab");
|
|
qDebug() << "set ActivateNextTab shortcut to" << keySeq;
|
|
QShortcut *activateNextTab = new QShortcut(QKeySequence(keySeq), this);
|
|
activateNextTab->setContext(Qt::ApplicationShortcut);
|
|
connect(activateNextTab, &QShortcut::activated,
|
|
this, [this]() {
|
|
VEditWindow *win = getCurrentWindow();
|
|
if (win) {
|
|
win->focusNextTab(true);
|
|
}
|
|
});
|
|
|
|
keySeq = g_config->getShortcutKeySequence("ActivatePreviousTab");
|
|
qDebug() << "set ActivatePreviousTab shortcut to" << keySeq;
|
|
QShortcut *activatePreviousTab = new QShortcut(QKeySequence(keySeq), this);
|
|
activatePreviousTab->setContext(Qt::ApplicationShortcut);
|
|
connect(activatePreviousTab, &QShortcut::activated,
|
|
this, [this]() {
|
|
VEditWindow *win = getCurrentWindow();
|
|
if (win) {
|
|
win->focusNextTab(false);
|
|
}
|
|
});
|
|
|
|
keySeq = g_config->getShortcutKeySequence("NextMatch");
|
|
qDebug() << "set NextMatch shortcut to" << keySeq;
|
|
QShortcut *nextMatchSC = new QShortcut(QKeySequence(keySeq), this);
|
|
connect(nextMatchSC, &QShortcut::activated,
|
|
this, [this]() {
|
|
nextMatch(true);
|
|
});
|
|
|
|
keySeq = g_config->getShortcutKeySequence("PreviousMatch");
|
|
qDebug() << "set PreviousMatch shortcut to" << keySeq;
|
|
QShortcut *previousMatchSC = new QShortcut(QKeySequence(keySeq), this);
|
|
connect(previousMatchSC, &QShortcut::activated,
|
|
this, [this]() {
|
|
nextMatch(false);
|
|
});
|
|
}
|
|
|
|
void VEditArea::insertSplitWindow(int idx)
|
|
{
|
|
VEditWindow *win = new VEditWindow(this);
|
|
splitter->insertWidget(idx, win);
|
|
connect(win, &VEditWindow::tabStatusUpdated,
|
|
this, &VEditArea::handleWindowTabStatusUpdated);
|
|
connect(win, &VEditWindow::requestSplitWindow,
|
|
this, &VEditArea::splitWindow);
|
|
connect(win, &VEditWindow::requestRemoveSplit,
|
|
this, &VEditArea::handleRemoveSplitRequest);
|
|
connect(win, &VEditWindow::getFocused,
|
|
this, &VEditArea::handleWindowFocused);
|
|
connect(win, &VEditWindow::outlineChanged,
|
|
this, &VEditArea::handleWindowOutlineChanged);
|
|
connect(win, &VEditWindow::currentHeaderChanged,
|
|
this, &VEditArea::handleWindowCurrentHeaderChanged);
|
|
connect(win, &VEditWindow::statusMessage,
|
|
this, &VEditArea::handleWindowStatusMessage);
|
|
connect(win, &VEditWindow::vimStatusUpdated,
|
|
this, &VEditArea::handleWindowVimStatusUpdated);
|
|
}
|
|
|
|
void VEditArea::handleWindowTabStatusUpdated(const VEditTabInfo &p_info)
|
|
{
|
|
if (splitter->widget(curWindowIndex) == sender()) {
|
|
emit tabStatusUpdated(p_info);
|
|
}
|
|
}
|
|
|
|
void VEditArea::handleWindowStatusMessage(const QString &p_msg)
|
|
{
|
|
if (splitter->widget(curWindowIndex) == sender()) {
|
|
emit statusMessage(p_msg);
|
|
}
|
|
}
|
|
|
|
void VEditArea::handleWindowVimStatusUpdated(const VVim *p_vim)
|
|
{
|
|
if (splitter->widget(curWindowIndex) == sender()) {
|
|
emit vimStatusUpdated(p_vim);
|
|
}
|
|
}
|
|
|
|
void VEditArea::removeSplitWindow(VEditWindow *win)
|
|
{
|
|
if (!win) {
|
|
return;
|
|
}
|
|
|
|
win->hide();
|
|
win->setParent(this);
|
|
disconnect(win, 0, this, 0);
|
|
// Should be deleted later
|
|
win->deleteLater();
|
|
}
|
|
|
|
VEditTab *VEditArea::openFile(VFile *p_file, OpenFileMode p_mode, bool p_forceMode)
|
|
{
|
|
if (!p_file) {
|
|
return NULL;
|
|
}
|
|
|
|
// Update auto save settings.
|
|
m_autoSave = g_config->getEnableAutoSave();
|
|
|
|
// If it is DocType::Unknown, open it using system default method.
|
|
if (p_file->getDocType() == DocType::Unknown) {
|
|
QUrl url = QUrl::fromLocalFile(p_file->fetchPath());
|
|
QDesktopServices::openUrl(url);
|
|
return NULL;
|
|
}
|
|
|
|
// Find if it has been opened already
|
|
int winIdx, tabIdx;
|
|
bool existFile = false;
|
|
bool setFocus = false;
|
|
auto tabs = findTabsByFile(p_file);
|
|
if (!tabs.empty()) {
|
|
// Current window first
|
|
winIdx = tabs[0].first;
|
|
tabIdx = tabs[0].second;
|
|
for (int i = 0; i < tabs.size(); ++i) {
|
|
if (tabs[i].first == curWindowIndex) {
|
|
winIdx = tabs[i].first;
|
|
tabIdx = tabs[i].second;
|
|
break;
|
|
}
|
|
}
|
|
|
|
setFocus = true;
|
|
existFile = true;
|
|
goto out;
|
|
}
|
|
|
|
// Open it in current window
|
|
if (curWindowIndex == -1) {
|
|
// insert a new split
|
|
insertSplitWindow(0);
|
|
curWindowIndex = 0;
|
|
}
|
|
|
|
winIdx = curWindowIndex;
|
|
tabIdx = openFileInWindow(winIdx, p_file, p_mode);
|
|
|
|
out:
|
|
VEditTab *tab = getTab(winIdx, tabIdx);
|
|
|
|
setCurrentTab(winIdx, tabIdx, setFocus);
|
|
|
|
if (existFile && p_forceMode) {
|
|
if (p_mode == OpenFileMode::Read) {
|
|
readFile();
|
|
} else if (p_mode == OpenFileMode::Edit) {
|
|
editFile();
|
|
}
|
|
}
|
|
|
|
return tab;
|
|
}
|
|
|
|
QVector<QPair<int, int> > VEditArea::findTabsByFile(const VFile *p_file)
|
|
{
|
|
QVector<QPair<int, int> > tabs;
|
|
int nrWin = splitter->count();
|
|
for (int winIdx = 0; winIdx < nrWin; ++winIdx) {
|
|
VEditWindow *win = getWindow(winIdx);
|
|
int tabIdx = win->findTabByFile(p_file);
|
|
if (tabIdx != -1) {
|
|
QPair<int, int> match;
|
|
match.first = winIdx;
|
|
match.second = tabIdx;
|
|
tabs.append(match);
|
|
}
|
|
}
|
|
return tabs;
|
|
}
|
|
|
|
int VEditArea::openFileInWindow(int windowIndex, VFile *p_file, OpenFileMode p_mode)
|
|
{
|
|
Q_ASSERT(windowIndex < splitter->count());
|
|
VEditWindow *win = getWindow(windowIndex);
|
|
return win->openFile(p_file, p_mode);
|
|
}
|
|
|
|
void VEditArea::setCurrentTab(int windowIndex, int tabIndex, bool setFocus)
|
|
{
|
|
VEditWindow *win = getWindow(windowIndex);
|
|
win->setCurrentIndex(tabIndex);
|
|
|
|
setCurrentWindow(windowIndex, setFocus);
|
|
}
|
|
|
|
void VEditArea::setCurrentWindow(int windowIndex, bool setFocus)
|
|
{
|
|
int nrWin = splitter->count();
|
|
curWindowIndex = windowIndex;
|
|
|
|
for (int i = 0; i < nrWin; ++i) {
|
|
getWindow(i)->setCurrentWindow(false);
|
|
}
|
|
if (curWindowIndex > -1) {
|
|
getWindow(curWindowIndex)->setCurrentWindow(true);
|
|
if (setFocus) {
|
|
getWindow(curWindowIndex)->focusWindow();
|
|
}
|
|
}
|
|
// Update status
|
|
updateWindowStatus();
|
|
}
|
|
|
|
void VEditArea::updateWindowStatus()
|
|
{
|
|
if (curWindowIndex == -1) {
|
|
Q_ASSERT(splitter->count() == 0);
|
|
|
|
emit tabStatusUpdated(VEditTabInfo());
|
|
emit outlineChanged(VTableOfContent());
|
|
emit currentHeaderChanged(VHeaderPointer());
|
|
return;
|
|
}
|
|
|
|
VEditWindow *win = getWindow(curWindowIndex);
|
|
win->updateTabStatus();
|
|
}
|
|
|
|
bool VEditArea::closeFile(const VFile *p_file, bool p_forced)
|
|
{
|
|
if (!p_file) {
|
|
return true;
|
|
}
|
|
bool ret = false;
|
|
int i = 0;
|
|
while (i < splitter->count()) {
|
|
VEditWindow *win = getWindow(i);
|
|
int nrWin = splitter->count();
|
|
ret = ret || win->closeFile(p_file, p_forced);
|
|
if (nrWin == splitter->count()) {
|
|
++i;
|
|
}
|
|
}
|
|
updateWindowStatus();
|
|
return ret;
|
|
}
|
|
|
|
bool VEditArea::closeFile(const VDirectory *p_dir, bool p_forced)
|
|
{
|
|
if (!p_dir) {
|
|
return true;
|
|
}
|
|
int i = 0;
|
|
while (i < splitter->count()) {
|
|
VEditWindow *win = getWindow(i);
|
|
if (!p_forced) {
|
|
setCurrentWindow(i, false);
|
|
}
|
|
int nrWin = splitter->count();
|
|
if (!win->closeFile(p_dir, p_forced)) {
|
|
return false;
|
|
}
|
|
// win may be removed after closeFile()
|
|
if (nrWin == splitter->count()) {
|
|
++i;
|
|
}
|
|
}
|
|
updateWindowStatus();
|
|
return true;
|
|
}
|
|
|
|
bool VEditArea::closeFile(const VNotebook *p_notebook, bool p_forced)
|
|
{
|
|
if (!p_notebook) {
|
|
return true;
|
|
}
|
|
int i = 0;
|
|
while (i < splitter->count()) {
|
|
VEditWindow *win = getWindow(i);
|
|
if (!p_forced) {
|
|
setCurrentWindow(i, false);
|
|
}
|
|
int nrWin = splitter->count();
|
|
if (!win->closeFile(p_notebook, p_forced)) {
|
|
return false;
|
|
}
|
|
// win may be removed after closeFile()
|
|
if (nrWin == splitter->count()) {
|
|
++i;
|
|
}
|
|
}
|
|
updateWindowStatus();
|
|
return true;
|
|
}
|
|
|
|
bool VEditArea::closeAllFiles(bool p_forced)
|
|
{
|
|
int i = 0;
|
|
while (i < splitter->count()) {
|
|
VEditWindow *win = getWindow(i);
|
|
if (!p_forced) {
|
|
setCurrentWindow(i, false);
|
|
}
|
|
int nrWin = splitter->count();
|
|
if (!win->closeAllFiles(p_forced)) {
|
|
return false;
|
|
}
|
|
if (nrWin == splitter->count()) {
|
|
++i;
|
|
}
|
|
}
|
|
updateWindowStatus();
|
|
return true;
|
|
}
|
|
|
|
void VEditArea::editFile()
|
|
{
|
|
VEditWindow *win = getWindow(curWindowIndex);
|
|
win->editFile();
|
|
}
|
|
|
|
void VEditArea::saveFile()
|
|
{
|
|
VEditWindow *win = getWindow(curWindowIndex);
|
|
win->saveFile();
|
|
}
|
|
|
|
void VEditArea::readFile(bool p_discard)
|
|
{
|
|
VEditWindow *win = getWindow(curWindowIndex);
|
|
win->readFile(p_discard);
|
|
}
|
|
|
|
void VEditArea::saveAndReadFile()
|
|
{
|
|
VEditWindow *win = getWindow(curWindowIndex);
|
|
win->saveAndReadFile();
|
|
}
|
|
|
|
void VEditArea::splitWindow(VEditWindow *p_window, bool p_right)
|
|
{
|
|
if (!p_window) {
|
|
return;
|
|
}
|
|
|
|
int idx = splitter->indexOf(p_window);
|
|
Q_ASSERT(idx > -1);
|
|
if (p_right) {
|
|
++idx;
|
|
} else {
|
|
--idx;
|
|
if (idx < 0) {
|
|
idx = 0;
|
|
}
|
|
}
|
|
|
|
insertSplitWindow(idx);
|
|
setCurrentWindow(idx, true);
|
|
|
|
distributeSplits();
|
|
}
|
|
|
|
void VEditArea::splitCurrentWindow()
|
|
{
|
|
if (curWindowIndex > -1) {
|
|
splitWindow(getWindow(curWindowIndex));
|
|
}
|
|
}
|
|
|
|
void VEditArea::handleRemoveSplitRequest(VEditWindow *curWindow)
|
|
{
|
|
if (!curWindow || splitter->count() <= 1) {
|
|
return;
|
|
}
|
|
int idx = splitter->indexOf(curWindow);
|
|
|
|
// curWindow will be deleted later
|
|
removeSplitWindow(curWindow);
|
|
|
|
if (idx >= splitter->count()) {
|
|
idx = splitter->count() - 1;
|
|
}
|
|
setCurrentWindow(idx, true);
|
|
}
|
|
|
|
void VEditArea::removeCurrentWindow()
|
|
{
|
|
if (curWindowIndex > -1) {
|
|
handleRemoveSplitRequest(getWindow(curWindowIndex));
|
|
}
|
|
}
|
|
|
|
void VEditArea::mousePressEvent(QMouseEvent *event)
|
|
{
|
|
QPoint pos = event->pos();
|
|
int nrWin = splitter->count();
|
|
for (int i = 0; i < nrWin; ++i) {
|
|
VEditWindow *win = getWindow(i);
|
|
if (win->geometry().contains(pos, true)) {
|
|
setCurrentWindow(i, true);
|
|
break;
|
|
}
|
|
}
|
|
QWidget::mousePressEvent(event);
|
|
}
|
|
|
|
void VEditArea::handleWindowFocused()
|
|
{
|
|
QObject *winObject = sender();
|
|
int nrWin = splitter->count();
|
|
for (int i = 0; i < nrWin; ++i) {
|
|
if (splitter->widget(i) == winObject) {
|
|
setCurrentWindow(i, false);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void VEditArea::handleWindowOutlineChanged(const VTableOfContent &p_outline)
|
|
{
|
|
QObject *winObject = sender();
|
|
if (splitter->widget(curWindowIndex) == winObject) {
|
|
emit outlineChanged(p_outline);
|
|
}
|
|
}
|
|
|
|
void VEditArea::handleWindowCurrentHeaderChanged(const VHeaderPointer &p_header)
|
|
{
|
|
QObject *winObject = sender();
|
|
if (splitter->widget(curWindowIndex) == winObject) {
|
|
emit currentHeaderChanged(p_header);
|
|
}
|
|
}
|
|
|
|
void VEditArea::scrollToHeader(const VHeaderPointer &p_header)
|
|
{
|
|
VEditWindow *win = getCurrentWindow();
|
|
if (win) {
|
|
win->scrollToHeader(p_header);
|
|
}
|
|
}
|
|
|
|
bool VEditArea::isFileOpened(const VFile *p_file)
|
|
{
|
|
return !findTabsByFile(p_file).isEmpty();
|
|
}
|
|
|
|
void VEditArea::handleFileUpdated(const VFile *p_file, UpdateAction p_act)
|
|
{
|
|
int nrWin = splitter->count();
|
|
for (int i = 0; i < nrWin; ++i) {
|
|
getWindow(i)->updateFileInfo(p_file, p_act);
|
|
}
|
|
}
|
|
|
|
void VEditArea::handleDirectoryUpdated(const VDirectory *p_dir, UpdateAction p_act)
|
|
{
|
|
int nrWin = splitter->count();
|
|
for (int i = 0; i < nrWin; ++i) {
|
|
getWindow(i)->updateDirectoryInfo(p_dir, p_act);
|
|
}
|
|
}
|
|
|
|
void VEditArea::handleNotebookUpdated(const VNotebook *p_notebook)
|
|
{
|
|
int nrWin = splitter->count();
|
|
for (int i = 0; i < nrWin; ++i) {
|
|
getWindow(i)->updateNotebookInfo(p_notebook);
|
|
}
|
|
}
|
|
|
|
VEditTab *VEditArea::getCurrentTab() const
|
|
{
|
|
if (curWindowIndex == -1) {
|
|
return NULL;
|
|
}
|
|
|
|
VEditWindow *win = getWindow(curWindowIndex);
|
|
return win->getCurrentTab();
|
|
}
|
|
|
|
VEditTab *VEditArea::getTab(int p_winIdx, int p_tabIdx) const
|
|
{
|
|
VEditWindow *win = getWindow(p_winIdx);
|
|
if (!win) {
|
|
return NULL;
|
|
}
|
|
|
|
return win->getTab(p_tabIdx);
|
|
}
|
|
|
|
VEditTab *VEditArea::getTab(const VFile *p_file) const
|
|
{
|
|
int nrWin = splitter->count();
|
|
for (int winIdx = 0; winIdx < nrWin; ++winIdx) {
|
|
VEditWindow *win = getWindow(winIdx);
|
|
int tabIdx = win->findTabByFile(p_file);
|
|
if (tabIdx != -1) {
|
|
return win->getTab(tabIdx);
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
QVector<VEditTabInfo> VEditArea::getAllTabsInfo() const
|
|
{
|
|
QVector<VEditTabInfo> tabs;
|
|
int nrWin = splitter->count();
|
|
for (int i = 0; i < nrWin; ++i) {
|
|
tabs.append(getWindow(i)->getAllTabsInfo());
|
|
}
|
|
|
|
return tabs;
|
|
}
|
|
|
|
int VEditArea::windowIndex(const VEditWindow *p_window) const
|
|
{
|
|
int nrWin = splitter->count();
|
|
for (int i = 0; i < nrWin; ++i) {
|
|
if (p_window == getWindow(i)) {
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void VEditArea::moveTab(QWidget *p_widget, int p_fromIdx, int p_toIdx)
|
|
{
|
|
int nrWin = splitter->count();
|
|
if (!p_widget || p_fromIdx < 0 || p_fromIdx >= nrWin
|
|
|| p_toIdx < 0 || p_toIdx >= nrWin) {
|
|
return;
|
|
}
|
|
qDebug() << "move widget" << p_widget << "from" << p_fromIdx << "to" << p_toIdx;
|
|
if (!getWindow(p_toIdx)->addEditTab(p_widget)) {
|
|
delete p_widget;
|
|
}
|
|
}
|
|
|
|
// Only propogate the search in the IncrementalSearch case.
|
|
void VEditArea::handleFindTextChanged(const QString &p_text, uint p_options)
|
|
{
|
|
VEditTab *tab = getCurrentTab();
|
|
if (tab) {
|
|
if (p_options & FindOption::IncrementalSearch) {
|
|
tab->findText(p_text, p_options, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
void VEditArea::handleFindOptionChanged(uint p_options)
|
|
{
|
|
qDebug() << "find option changed" << p_options;
|
|
g_config->setFindCaseSensitive(p_options & FindOption::CaseSensitive);
|
|
g_config->setFindWholeWordOnly(p_options & FindOption::WholeWordOnly);
|
|
g_config->setFindRegularExpression(p_options & FindOption::RegularExpression);
|
|
g_config->setFindIncrementalSearch(p_options & FindOption::IncrementalSearch);
|
|
}
|
|
|
|
void VEditArea::handleFindNext(const QString &p_text, uint p_options,
|
|
bool p_forward)
|
|
{
|
|
qDebug() << "find next" << p_text << p_options << p_forward;
|
|
VEditTab *tab = getCurrentTab();
|
|
if (tab) {
|
|
tab->findText(p_text, p_options, false, p_forward);
|
|
}
|
|
}
|
|
|
|
void VEditArea::handleReplace(const QString &p_text, uint p_options,
|
|
const QString &p_replaceText, bool p_findNext)
|
|
{
|
|
qDebug() << "replace" << p_text << p_options << "with" << p_replaceText
|
|
<< p_findNext;
|
|
VEditTab *tab = getCurrentTab();
|
|
if (tab) {
|
|
tab->replaceText(p_text, p_options, p_replaceText, p_findNext);
|
|
}
|
|
}
|
|
|
|
void VEditArea::handleReplaceAll(const QString &p_text, uint p_options,
|
|
const QString &p_replaceText)
|
|
{
|
|
qDebug() << "replace all" << p_text << p_options << "with" << p_replaceText;
|
|
VEditTab *tab = getCurrentTab();
|
|
if (tab) {
|
|
tab->replaceTextAll(p_text, p_options, p_replaceText);
|
|
}
|
|
}
|
|
|
|
// Let VEditArea get focus after VFindReplaceDialog is closed.
|
|
void VEditArea::handleFindDialogClosed()
|
|
{
|
|
if (curWindowIndex == -1) {
|
|
setFocus();
|
|
} else {
|
|
getWindow(curWindowIndex)->focusWindow();
|
|
}
|
|
|
|
// Clear all the search highlight.
|
|
int nrWin = splitter->count();
|
|
for (int i = 0; i < nrWin; ++i) {
|
|
getWindow(i)->clearSearchedWordHighlight();
|
|
}
|
|
}
|
|
|
|
QString VEditArea::getSelectedText()
|
|
{
|
|
VEditTab *tab = getCurrentTab();
|
|
if (tab) {
|
|
return tab->getSelectedText();
|
|
} else {
|
|
return QString();
|
|
}
|
|
}
|
|
|
|
int VEditArea::focusNextWindow(int p_biaIdx)
|
|
{
|
|
if (p_biaIdx == 0) {
|
|
return curWindowIndex;
|
|
}
|
|
int newIdx = curWindowIndex + p_biaIdx;
|
|
if (newIdx < 0) {
|
|
newIdx = 0;
|
|
} else if (newIdx >= splitter->count()) {
|
|
newIdx = splitter->count() - 1;
|
|
}
|
|
if (newIdx >= 0 && newIdx < splitter->count()) {
|
|
setCurrentWindow(newIdx, true);
|
|
} else {
|
|
newIdx = -1;
|
|
}
|
|
return newIdx;
|
|
}
|
|
|
|
void VEditArea::moveCurrentTabOneSplit(bool p_right)
|
|
{
|
|
getWindow(curWindowIndex)->moveCurrentTabOneSplit(p_right);
|
|
}
|
|
|
|
VEditWindow *VEditArea::getCurrentWindow() const
|
|
{
|
|
if (curWindowIndex < 0) {
|
|
return NULL;
|
|
}
|
|
|
|
return getWindow(curWindowIndex);
|
|
}
|
|
|
|
void VEditArea::registerNavigation(QChar p_majorKey)
|
|
{
|
|
m_majorKey = p_majorKey;
|
|
V_ASSERT(m_keyMap.empty());
|
|
V_ASSERT(m_naviLabels.empty());
|
|
}
|
|
|
|
void VEditArea::showNavigation()
|
|
{
|
|
// Clean up.
|
|
m_keyMap.clear();
|
|
for (auto label : m_naviLabels) {
|
|
delete label;
|
|
}
|
|
|
|
m_naviLabels.clear();
|
|
|
|
if (!isVisible()) {
|
|
return;
|
|
}
|
|
|
|
// Generate labels for VEDitTab.
|
|
int charIdx = 0;
|
|
for (int i = 0; charIdx < 26 && i < splitter->count(); ++i) {
|
|
VEditWindow *win = getWindow(i);
|
|
QVector<TabNavigationInfo> tabInfos = win->getTabsNavigationInfo();
|
|
for (int j = 0; charIdx < 26 && j < tabInfos.size(); ++j, ++charIdx) {
|
|
QChar key('a' + charIdx);
|
|
m_keyMap[key] = tabInfos[j].m_tab;
|
|
QString str = QString(m_majorKey) + key;
|
|
QLabel *label = new QLabel(str, win);
|
|
label->setStyleSheet(g_vnote->getNavigationLabelStyle(str));
|
|
label->show();
|
|
label->move(tabInfos[j].m_topLeft);
|
|
m_naviLabels.append(label);
|
|
}
|
|
}
|
|
}
|
|
|
|
void VEditArea::hideNavigation()
|
|
{
|
|
m_keyMap.clear();
|
|
for (auto label : m_naviLabels) {
|
|
delete label;
|
|
}
|
|
|
|
m_naviLabels.clear();
|
|
}
|
|
|
|
bool VEditArea::handleKeyNavigation(int p_key, bool &p_succeed)
|
|
{
|
|
static bool secondKey = false;
|
|
bool ret = false;
|
|
p_succeed = false;
|
|
QChar keyChar = VUtils::keyToChar(p_key);
|
|
if (secondKey && !keyChar.isNull()) {
|
|
secondKey = false;
|
|
p_succeed = true;
|
|
auto it = m_keyMap.find(keyChar);
|
|
if (it != m_keyMap.end()) {
|
|
ret = true;
|
|
static_cast<VEditTab *>(it.value())->focusTab();
|
|
}
|
|
} else if (keyChar == m_majorKey) {
|
|
// Major key pressed.
|
|
// Need second key if m_keyMap is not empty.
|
|
if (m_keyMap.isEmpty()) {
|
|
p_succeed = true;
|
|
} else {
|
|
secondKey = true;
|
|
}
|
|
ret = true;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int VEditArea::openFiles(const QVector<VFileSessionInfo> &p_files, bool p_oneByOne)
|
|
{
|
|
VFile *curFile = NULL;
|
|
int nrOpened = 0;
|
|
for (auto const & info : p_files) {
|
|
QString filePath = VUtils::validFilePathToOpen(info.m_file);
|
|
if (filePath.isEmpty()) {
|
|
continue;
|
|
}
|
|
|
|
VFile *file = g_vnote->getFile(filePath);
|
|
if (!file) {
|
|
continue;
|
|
}
|
|
|
|
VEditTab *tab = openFile(file, info.m_mode, true);
|
|
++nrOpened;
|
|
|
|
if (info.m_active) {
|
|
curFile = file;
|
|
}
|
|
|
|
VEditTabInfo tabInfo;
|
|
tabInfo.m_editTab = tab;
|
|
info.toEditTabInfo(&tabInfo);
|
|
|
|
tab->tryRestoreFromTabInfo(tabInfo);
|
|
|
|
if (p_oneByOne) {
|
|
QCoreApplication::sendPostedEvents();
|
|
}
|
|
}
|
|
|
|
if (curFile) {
|
|
openFile(curFile, OpenFileMode::Read, false);
|
|
}
|
|
|
|
return nrOpened;
|
|
}
|
|
|
|
void VEditArea::registerCaptainTargets()
|
|
{
|
|
using namespace std::placeholders;
|
|
|
|
VCaptain *captain = g_mainWin->getCaptain();
|
|
|
|
captain->registerCaptainTarget(tr("ActivateTab1"),
|
|
g_config->getCaptainShortcutKeySequence("ActivateTab1"),
|
|
this,
|
|
std::bind(activateTabByCaptain, _1, _2, 1));
|
|
captain->registerCaptainTarget(tr("ActivateTab2"),
|
|
g_config->getCaptainShortcutKeySequence("ActivateTab2"),
|
|
this,
|
|
std::bind(activateTabByCaptain, _1, _2, 2));
|
|
captain->registerCaptainTarget(tr("ActivateTab3"),
|
|
g_config->getCaptainShortcutKeySequence("ActivateTab3"),
|
|
this,
|
|
std::bind(activateTabByCaptain, _1, _2, 3));
|
|
captain->registerCaptainTarget(tr("ActivateTab4"),
|
|
g_config->getCaptainShortcutKeySequence("ActivateTab4"),
|
|
this,
|
|
std::bind(activateTabByCaptain, _1, _2, 4));
|
|
captain->registerCaptainTarget(tr("ActivateTab5"),
|
|
g_config->getCaptainShortcutKeySequence("ActivateTab5"),
|
|
this,
|
|
std::bind(activateTabByCaptain, _1, _2, 5));
|
|
captain->registerCaptainTarget(tr("ActivateTab6"),
|
|
g_config->getCaptainShortcutKeySequence("ActivateTab6"),
|
|
this,
|
|
std::bind(activateTabByCaptain, _1, _2, 6));
|
|
captain->registerCaptainTarget(tr("ActivateTab7"),
|
|
g_config->getCaptainShortcutKeySequence("ActivateTab7"),
|
|
this,
|
|
std::bind(activateTabByCaptain, _1, _2, 7));
|
|
captain->registerCaptainTarget(tr("ActivateTab8"),
|
|
g_config->getCaptainShortcutKeySequence("ActivateTab8"),
|
|
this,
|
|
std::bind(activateTabByCaptain, _1, _2, 8));
|
|
captain->registerCaptainTarget(tr("ActivateTab9"),
|
|
g_config->getCaptainShortcutKeySequence("ActivateTab9"),
|
|
this,
|
|
std::bind(activateTabByCaptain, _1, _2, 9));
|
|
captain->registerCaptainTarget(tr("AlternateTab"),
|
|
g_config->getCaptainShortcutKeySequence("AlternateTab"),
|
|
this,
|
|
alternateTabByCaptain);
|
|
captain->registerCaptainTarget(tr("OpenedFileList"),
|
|
g_config->getCaptainShortcutKeySequence("OpenedFileList"),
|
|
this,
|
|
showOpenedFileListByCaptain);
|
|
captain->registerCaptainTarget(tr("ActivateSplitLeft"),
|
|
g_config->getCaptainShortcutKeySequence("ActivateSplitLeft"),
|
|
this,
|
|
activateSplitLeftByCaptain);
|
|
captain->registerCaptainTarget(tr("ActivateSplitRight"),
|
|
g_config->getCaptainShortcutKeySequence("ActivateSplitRight"),
|
|
this,
|
|
activateSplitRightByCaptain);
|
|
captain->registerCaptainTarget(tr("MoveTabSplitLeft"),
|
|
g_config->getCaptainShortcutKeySequence("MoveTabSplitLeft"),
|
|
this,
|
|
moveTabSplitLeftByCaptain);
|
|
captain->registerCaptainTarget(tr("MoveTabSplitRight"),
|
|
g_config->getCaptainShortcutKeySequence("MoveTabSplitRight"),
|
|
this,
|
|
moveTabSplitRightByCaptain);
|
|
captain->registerCaptainTarget(tr("ActivateNextTab"),
|
|
g_config->getCaptainShortcutKeySequence("ActivateNextTab"),
|
|
this,
|
|
activateNextTabByCaptain);
|
|
captain->registerCaptainTarget(tr("ActivatePreviousTab"),
|
|
g_config->getCaptainShortcutKeySequence("ActivatePreviousTab"),
|
|
this,
|
|
activatePreviousTabByCaptain);
|
|
captain->registerCaptainTarget(tr("VerticalSplit"),
|
|
g_config->getCaptainShortcutKeySequence("VerticalSplit"),
|
|
this,
|
|
verticalSplitByCaptain);
|
|
captain->registerCaptainTarget(tr("RemoveSplit"),
|
|
g_config->getCaptainShortcutKeySequence("RemoveSplit"),
|
|
this,
|
|
removeSplitByCaptain);
|
|
captain->registerCaptainTarget(tr("MaximizeSplit"),
|
|
g_config->getCaptainShortcutKeySequence("MaximizeSplit"),
|
|
this,
|
|
maximizeSplitByCaptain);
|
|
captain->registerCaptainTarget(tr("DistributeSplits"),
|
|
g_config->getCaptainShortcutKeySequence("DistributeSplits"),
|
|
this,
|
|
distributeSplitsByCaptain);
|
|
captain->registerCaptainTarget(tr("MagicWord"),
|
|
g_config->getCaptainShortcutKeySequence("MagicWord"),
|
|
this,
|
|
evaluateMagicWordsByCaptain);
|
|
captain->registerCaptainTarget(tr("ApplySnippet"),
|
|
g_config->getCaptainShortcutKeySequence("ApplySnippet"),
|
|
this,
|
|
applySnippetByCaptain);
|
|
captain->registerCaptainTarget(tr("LivePreview"),
|
|
g_config->getCaptainShortcutKeySequence("LivePreview"),
|
|
this,
|
|
toggleLivePreviewByCaptain);
|
|
captain->registerCaptainTarget(tr("ExpandLivePreview"),
|
|
g_config->getCaptainShortcutKeySequence("ExpandLivePreview"),
|
|
this,
|
|
expandLivePreviewByCaptain);
|
|
captain->registerCaptainTarget(tr("ParseAndPaste"),
|
|
g_config->getCaptainShortcutKeySequence("ParseAndPaste"),
|
|
this,
|
|
parseAndPasteByCaptain);
|
|
}
|
|
|
|
bool VEditArea::activateTabByCaptain(void *p_target, void *p_data, int p_idx)
|
|
{
|
|
Q_UNUSED(p_data);
|
|
VEditArea *obj = static_cast<VEditArea *>(p_target);
|
|
VEditWindow *win = obj->getCurrentWindow();
|
|
if (win) {
|
|
if (win->activateTab(p_idx)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool VEditArea::alternateTabByCaptain(void *p_target, void *p_data)
|
|
{
|
|
Q_UNUSED(p_data);
|
|
VEditArea *obj = static_cast<VEditArea *>(p_target);
|
|
VEditWindow *win = obj->getCurrentWindow();
|
|
if (win) {
|
|
if (win->alternateTab()) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool VEditArea::showOpenedFileListByCaptain(void *p_target, void *p_data)
|
|
{
|
|
Q_UNUSED(p_data);
|
|
VEditArea *obj = static_cast<VEditArea *>(p_target);
|
|
VEditWindow *win = obj->getCurrentWindow();
|
|
if (win) {
|
|
if (win->showOpenedFileList()) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool VEditArea::activateSplitLeftByCaptain(void *p_target, void *p_data)
|
|
{
|
|
Q_UNUSED(p_data);
|
|
VEditArea *obj = static_cast<VEditArea *>(p_target);
|
|
if (obj->focusNextWindow(-1) > -1) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool VEditArea::activateSplitRightByCaptain(void *p_target, void *p_data)
|
|
{
|
|
Q_UNUSED(p_data);
|
|
VEditArea *obj = static_cast<VEditArea *>(p_target);
|
|
if (obj->focusNextWindow(1) > -1) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool VEditArea::moveTabSplitLeftByCaptain(void *p_target, void *p_data)
|
|
{
|
|
Q_UNUSED(p_data);
|
|
VEditArea *obj = static_cast<VEditArea *>(p_target);
|
|
obj->moveCurrentTabOneSplit(false);
|
|
return true;
|
|
}
|
|
|
|
bool VEditArea::moveTabSplitRightByCaptain(void *p_target, void *p_data)
|
|
{
|
|
Q_UNUSED(p_data);
|
|
VEditArea *obj = static_cast<VEditArea *>(p_target);
|
|
obj->moveCurrentTabOneSplit(true);
|
|
return true;
|
|
}
|
|
|
|
bool VEditArea::activateNextTabByCaptain(void *p_target, void *p_data)
|
|
{
|
|
Q_UNUSED(p_data);
|
|
VEditArea *obj = static_cast<VEditArea *>(p_target);
|
|
VEditWindow *win = obj->getCurrentWindow();
|
|
if (win) {
|
|
win->focusNextTab(true);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool VEditArea::activatePreviousTabByCaptain(void *p_target, void *p_data)
|
|
{
|
|
Q_UNUSED(p_data);
|
|
VEditArea *obj = static_cast<VEditArea *>(p_target);
|
|
VEditWindow *win = obj->getCurrentWindow();
|
|
if (win) {
|
|
win->focusNextTab(false);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool VEditArea::verticalSplitByCaptain(void *p_target, void *p_data)
|
|
{
|
|
Q_UNUSED(p_data);
|
|
VEditArea *obj = static_cast<VEditArea *>(p_target);
|
|
obj->splitCurrentWindow();
|
|
return false;
|
|
}
|
|
|
|
bool VEditArea::removeSplitByCaptain(void *p_target, void *p_data)
|
|
{
|
|
Q_UNUSED(p_data);
|
|
VEditArea *obj = static_cast<VEditArea *>(p_target);
|
|
obj->removeCurrentWindow();
|
|
|
|
QWidget *nextFocus = obj->getCurrentTab();
|
|
if (nextFocus) {
|
|
nextFocus->setFocus();
|
|
} else {
|
|
g_mainWin->getFileList()->setFocus();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool VEditArea::maximizeSplitByCaptain(void *p_target, void *p_data)
|
|
{
|
|
Q_UNUSED(p_data);
|
|
VEditArea *obj = static_cast<VEditArea *>(p_target);
|
|
|
|
obj->maximizeCurrentSplit();
|
|
return true;
|
|
}
|
|
|
|
bool VEditArea::distributeSplitsByCaptain(void *p_target, void *p_data)
|
|
{
|
|
Q_UNUSED(p_data);
|
|
VEditArea *obj = static_cast<VEditArea *>(p_target);
|
|
|
|
obj->distributeSplits();
|
|
return true;
|
|
}
|
|
|
|
bool VEditArea::evaluateMagicWordsByCaptain(void *p_target, void *p_data)
|
|
{
|
|
VEditArea *obj = static_cast<VEditArea *>(p_target);
|
|
CaptainData *data = static_cast<CaptainData *>(p_data);
|
|
|
|
VEditTab *tab = obj->getCurrentTab();
|
|
if (tab
|
|
&& (data->m_focusWidgetBeforeCaptain == tab
|
|
|| tab->isAncestorOf(data->m_focusWidgetBeforeCaptain))) {
|
|
tab->evaluateMagicWords();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool VEditArea::applySnippetByCaptain(void *p_target, void *p_data)
|
|
{
|
|
VEditArea *obj = static_cast<VEditArea *>(p_target);
|
|
CaptainData *data = static_cast<CaptainData *>(p_data);
|
|
|
|
VEditTab *tab = obj->getCurrentTab();
|
|
if (tab
|
|
&& (data->m_focusWidgetBeforeCaptain == tab
|
|
|| tab->isAncestorOf(data->m_focusWidgetBeforeCaptain))) {
|
|
tab->applySnippet();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool VEditArea::toggleLivePreviewByCaptain(void *p_target, void *p_data)
|
|
{
|
|
Q_UNUSED(p_data);
|
|
VEditArea *obj = static_cast<VEditArea *>(p_target);
|
|
|
|
VMdTab *tab = dynamic_cast<VMdTab *>(obj->getCurrentTab());
|
|
if (tab) {
|
|
if (tab->toggleLivePreview()) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool VEditArea::expandLivePreviewByCaptain(void *p_target, void *p_data)
|
|
{
|
|
Q_UNUSED(p_data);
|
|
VEditArea *obj = static_cast<VEditArea *>(p_target);
|
|
|
|
VMdTab *tab = dynamic_cast<VMdTab *>(obj->getCurrentTab());
|
|
if (tab) {
|
|
if (tab->expandRestorePreviewArea()) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool VEditArea::parseAndPasteByCaptain(void *p_target, void *p_data)
|
|
{
|
|
Q_UNUSED(p_data);
|
|
VEditArea *obj = static_cast<VEditArea *>(p_target);
|
|
|
|
const VMdTab *tab = dynamic_cast<const VMdTab *>(obj->getCurrentTab());
|
|
if (tab && tab->isEditMode()) {
|
|
VMdEditor *editor = tab->getEditor();
|
|
editor->parseAndPaste();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void VEditArea::recordClosedFile(const VFileSessionInfo &p_file)
|
|
{
|
|
for (auto it = m_lastClosedFiles.begin(); it != m_lastClosedFiles.end(); ++it) {
|
|
if (it->m_file == p_file.m_file) {
|
|
// Remove it.
|
|
m_lastClosedFiles.erase(it);
|
|
break;
|
|
}
|
|
}
|
|
|
|
m_lastClosedFiles.push(p_file);
|
|
|
|
emit fileClosed(p_file.m_file);
|
|
}
|
|
|
|
void VEditArea::handleFileTimerTimeout()
|
|
{
|
|
int nrWin = splitter->count();
|
|
for (int i = 0; i < nrWin; ++i) {
|
|
// Check whether opened files have been changed outside.
|
|
VEditWindow *win = getWindow(i);
|
|
win->checkFileChangeOutside();
|
|
|
|
if (m_autoSave) {
|
|
win->saveAll();
|
|
}
|
|
}
|
|
}
|
|
|
|
QRect VEditArea::editAreaRect() const
|
|
{
|
|
QRect rt = rect();
|
|
int nrWin = splitter->count();
|
|
if (nrWin > 0) {
|
|
rt.setTopLeft(QPoint(0, getWindow(0)->tabBarHeight()));
|
|
}
|
|
|
|
return rt;
|
|
}
|
|
|
|
void VEditArea::maximizeCurrentSplit()
|
|
{
|
|
if (splitter->count() <= 1 || curWindowIndex == -1) {
|
|
return;
|
|
}
|
|
|
|
const int MinSplitWidth = 20 * VUtils::calculateScaleFactor();
|
|
|
|
auto sizes = splitter->sizes();
|
|
int totalWidth = 0;
|
|
for (auto sz : sizes) {
|
|
totalWidth += sz;
|
|
}
|
|
|
|
int newWidth = totalWidth - MinSplitWidth * (sizes.size() - 1);
|
|
if (newWidth <= 0) {
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < sizes.size(); ++i) {
|
|
sizes[i] = (i == curWindowIndex) ? newWidth : MinSplitWidth;
|
|
}
|
|
|
|
splitter->setSizes(sizes);
|
|
}
|
|
|
|
void VEditArea::distributeSplits()
|
|
{
|
|
if (splitter->count() <= 1) {
|
|
return;
|
|
}
|
|
|
|
auto sizes = splitter->sizes();
|
|
int totalWidth = 0;
|
|
for (auto sz : sizes) {
|
|
totalWidth += sz;
|
|
}
|
|
|
|
int newWidth = totalWidth / sizes.size();
|
|
if (newWidth <= 0) {
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < sizes.size(); ++i) {
|
|
sizes[i] = newWidth;
|
|
}
|
|
|
|
splitter->setSizes(sizes);
|
|
}
|
|
|
|
void VEditArea::nextMatch(bool p_forward)
|
|
{
|
|
VEditTab *tab = getCurrentTab();
|
|
if (!tab) {
|
|
return;
|
|
}
|
|
|
|
Q_ASSERT(m_findReplace);
|
|
|
|
tab->nextMatch(m_findReplace->textToFind(),
|
|
m_findReplace->options(),
|
|
p_forward);
|
|
}
|