diff options
Diffstat (limited to 'kjots/kjotsedit.cpp')
-rw-r--r-- | kjots/kjotsedit.cpp | 483 |
1 files changed, 478 insertions, 5 deletions
diff --git a/kjots/kjotsedit.cpp b/kjots/kjotsedit.cpp index 2b78698..b2ffe89 100644 --- a/kjots/kjotsedit.cpp +++ b/kjots/kjotsedit.cpp @@ -25,8 +25,13 @@ #include <tqcursor.h> #include <tdepopupmenu.h> -#include <keditcl.h> +#include <kfind.h> +#include <kfinddialog.h> +#include <kreplace.h> +#include <kreplacedialog.h> +#include <kstringhandler.h> #include <tdelocale.h> +#include <tdemessagebox.h> #include <kopenwith.h> #include <kprinter.h> @@ -37,8 +42,12 @@ // MYMULTIEDIT //---------------------------------------------------------------------- KJotsEdit::KJotsEdit (TQWidget* parent, const char* name) - : KEdit(parent, name), - m_entry(0) + : KTextEdit(parent, name) + , m_entry(nullptr) + , m_find(nullptr) + , m_findDialog(nullptr) + , m_replace(nullptr) + , m_replaceDialog(nullptr) { // no rich text until printing and other such issues are worked out setTextFormat(TQt::PlainText); @@ -50,7 +59,8 @@ KJotsEdit::KJotsEdit (TQWidget* parent, const char* name) KJotsEdit::~KJotsEdit() { - + delete m_find; + delete m_replace; } void KJotsEdit::mousePressEvent( TQMouseEvent *e ) @@ -67,7 +77,7 @@ void KJotsEdit::mousePressEvent( TQMouseEvent *e ) } } - KEdit::mousePressEvent(e); + KTextEdit::mousePressEvent(e); } void KJotsEdit::openUrl() @@ -121,6 +131,441 @@ void KJotsEdit::print(TQString title) } } +void KJotsEdit::slotFindHighlight(const TQString& text, int matchIndex, int matchLength) +{ + // tqDebug("KJotsEdit::slotFindHighlight"); + + Q_UNUSED(text); + + const bool inSelection = m_find->options() & KFindDialog::SelectedText; + + // Ensure we are offsetting the selection for the first line of the selection + // so we don't highlight the wrong text. + if (inSelection && (m_findCursor.paragraph == m_selectionStart.paragraph)) + { + setSelection(m_findCursor.paragraph, m_selectionStart.paragraphIndex + matchIndex, m_findCursor.paragraph, + m_selectionStart.paragraphIndex + matchIndex + matchLength); + } + else + { + setSelection(m_findCursor.paragraph, matchIndex, m_findCursor.paragraph, matchIndex + matchLength); + } +} + +void KJotsEdit::slotReplaceHighlight(const TQString& text, int matchIndex, int matchLength) +{ + // tqDebug("KJotsEdit::slotReplaceHighlight"); + + Q_UNUSED(text); + + setSelection(m_replaceCursor.paragraph, matchIndex, m_replaceCursor.paragraph, matchIndex + matchLength); +} + +void KJotsEdit::replace() +{ + // tqDebug("KJotsEdit::replace"); + + if (length() == 0) + { + return; + } + + if (m_replaceDialog) + { + m_replaceDialog->setActiveWindow(); + } + else + { + m_replaceDialog = new KReplaceDialog(this, "m_replaceDialog", KReplaceDialog::PromptOnReplace); + connect(m_replaceDialog, TQ_SIGNAL(okClicked()), this, TQ_SLOT(slotDoReplace())); + } + + if (hasSelectedText()) + { + m_replaceDialog->setHasSelection(true); + m_replaceDialog->setOptions(m_replaceDialog->options() | KReplaceDialog::SelectedText); + } + else + { + m_replaceDialog->setHasSelection(false); + m_replaceDialog->setOptions(m_replaceDialog->options() & ~KReplaceDialog::SelectedText); + } + + m_replaceDialog->show(); +} + +void KJotsEdit::slotDoReplace() +{ + // tqDebug("KJotsEdit::slotDoReplace"); + + /* Performing a new replacement, so we need to remove the previous + * KReplace, set up a new one and the 'replaceNext' functionality. */ + + delete m_replace; + m_replace = nullptr; + + if (!m_replaceDialog) + { + // tqDebug("KJotsEdit::slotDoReplace: no replaceDialog"); + return; + } + + m_replace = new KReplace(m_replaceDialog->pattern(), m_replaceDialog->replacement(), m_replaceDialog->options()); + + if ((m_replace->options() & KReplaceDialog::SelectedText)) + { + const bool backwards = m_replace->options() & KFindDialog::FindBackwards; + + getSelection(&m_selectionStart.paragraph, &m_selectionStart.paragraphIndex, &m_selectionEnd.paragraph, + &m_selectionEnd.paragraphIndex); + m_replaceCursor.paragraph = backwards ? m_selectionEnd.paragraph : m_selectionStart.paragraph; + m_replaceCursor.paragraphIndex = backwards ? m_selectionEnd.paragraphIndex : m_selectionStart.paragraphIndex; + } + else + { + setupCursor(&m_replaceCursor, m_replace); + } + + connect(m_replace, TQ_SIGNAL(highlight(const TQString&, int, int)), this, + TQ_SLOT(slotReplaceHighlight(const TQString&, int, int))); + connect(m_replace, TQ_SIGNAL(findNext()), this, TQ_SLOT(slotReplaceNext())); + connect(m_replace, TQ_SIGNAL(replace(const TQString&, int, int, int)), this, + TQ_SLOT(slotReplace(const TQString&, int, int, int))); + + m_replaceDialog->close(); + slotReplaceNext(); +} + +void KJotsEdit::slotReplace(const TQString& replaceText, int replacementIndex, int replacementLength, int matchedLength) +{ + // tqDebug("KJotsEdit::slotReplace"); + + // Ensure the selection only matches the replacement. + // Prevents an issue where all the text is selected before replacing (since we remove the selection below). + setSelection(m_replaceCursor.paragraph, replacementIndex, m_replaceCursor.paragraph, + replacementIndex + matchedLength); + + const auto replacement = replaceText.mid(replacementIndex, replacementLength); + removeSelectedText(); + insertAt(replacement, m_replaceCursor.paragraph, replacementIndex); + setModified(true); +} + +void KJotsEdit::slotReplaceNext() +{ + // tqDebug("KJotsEdit::slotReplaceNext"); + + if (!m_replace) + { + return; + } + + const bool backwards = (m_replace->options() & KReplaceDialog::FindBackwards); + const bool useSelection = (m_replace->options() & KReplaceDialog::SelectedText); + + if (m_replace->needData()) + { + if (useSelection && backwards) + { + m_replace->setData(text(m_selectionEnd.paragraph), m_selectionEnd.paragraphIndex); + } + else if (useSelection) + { + m_replace->setData(text(m_selectionStart.paragraph), m_selectionStart.paragraphIndex); + } + else + { + m_replace->setData(text(m_replaceCursor.paragraph), m_replaceCursor.paragraphIndex); + } + } + + KReplace::Result res = KReplace::NoMatch; + + do + { + res = m_replace->replace(); + if (res == KReplace::Match) + { + return; + } + + m_replaceCursor.paragraph += (backwards ? -1 : 1); + m_replaceCursor.paragraphIndex = (backwards ? paragraphLength(m_replaceCursor.paragraph) : 0); + m_replace->setData(text(m_replaceCursor.paragraph), m_replaceCursor.paragraphIndex); + + if (useSelection && m_replaceCursor.paragraph > m_selectionEnd.paragraph) + { + break; + } + + if (useSelection && backwards && m_replaceCursor.paragraph < m_selectionStart.paragraph) + { + break; + } + } while (backwards ? (m_replaceCursor.paragraph >= 0) : (m_replaceCursor.paragraph < paragraphs())); + + Q_ASSERT(res != KReplace::Match); + + if ((m_replace->options() & KReplaceDialog::FromCursor) && m_replace->shouldRestart(true)) + { + // tqDebug("KJotsEdit::slotReplaceNext restarting"); + m_replaceCursor.paragraph = backwards ? (paragraphs() - 1) : 0; + m_replaceCursor.paragraphIndex = backwards ? (paragraphLength(m_replaceCursor.paragraph)) : 0; + m_replace->setData(text(m_replaceCursor.paragraph), m_replaceCursor.paragraphIndex); + m_replace->resetCounts(); + slotReplaceNext(); + return; + } + + m_replace->displayFinalDialog(); + m_replace->disconnect(this, TQ_SLOT(slotReplaceHighlight(const TQString&, int, int))); + m_replace->deleteLater(); + m_replace = nullptr; +} + +void KJotsEdit::find() +{ + // tqDebug("KJotsEdit::find"); + + if (length() == 0) + { + return; + } + + if (m_findDialog) + { + m_findDialog->setActiveWindow(); + } + else + { + m_findDialog = new KFindDialog(this, "m_findDialog"); + connect(m_findDialog, TQ_SIGNAL(okClicked()), this, TQ_SLOT(slotDoFind())); + } + + if (hasSelectedText()) + { + m_findDialog->setHasSelection(true); + m_findDialog->setOptions(m_findDialog->options() | KFindDialog::SelectedText); + } + else + { + m_findDialog->setHasSelection(false); + m_findDialog->setOptions(m_findDialog->options() & ~KFindDialog::SelectedText); + } + + + m_findDialog->show(); +} + +void KJotsEdit::findNext() +{ + // tqDebug("KJotsEdit::findNext"); + + if (!m_find) + { + find(); + return; + } + + const bool backwards = (m_find->options() & KFindDialog::FindBackwards); + const bool fromCursor = (m_find->options() & KFindDialog::FromCursor); + const bool inSelection = (m_find->options() & KFindDialog::SelectedText); + + if (m_find->needData()) + { + if (inSelection) + { + if (m_selectionStart.paragraph == m_selectionEnd.paragraph) + { + // Same line, ensure we only inlcude the selection. + auto selectionLength = m_selectionEnd.paragraphIndex - m_selectionStart.paragraphIndex; + auto data = text(m_findCursor.paragraph).mid(m_selectionStart.paragraphIndex, selectionLength); + m_find->setData(data); + } + else if (backwards) + { + m_findCursor.paragraph = m_selectionEnd.paragraph; + m_findCursor.paragraphIndex = -1; + m_find->setData(text(m_findCursor.paragraph).left(m_selectionEnd.paragraphIndex)); + } + else + { + m_findCursor.paragraph = m_selectionStart.paragraph; + m_findCursor.paragraphIndex = 0; + auto offset = (paragraphLength(m_findCursor.paragraph)) - m_selectionStart.paragraphIndex+1; + m_find->setData(text(m_findCursor.paragraph).right(offset), m_findCursor.paragraphIndex); + } + } + else + { + m_find->setData(text(m_findCursor.paragraph), m_findCursor.paragraphIndex); + } + } + + KFind::Result res = KFind::NoMatch; + + do + { + res = m_find->find(); + if (res == KFind::Match) + { + return; + } + + m_findCursor.paragraph += (backwards ? -1 : 1); + m_findCursor.paragraphIndex = -1; // SOL or EOL depending on `backwards`. + + if (m_findCursor.paragraph == m_selectionStart.paragraph) + { + auto offset = (paragraphLength(m_findCursor.paragraph)) - m_selectionStart.paragraphIndex+1; + m_find->setData(text(m_findCursor.paragraph).right(offset), m_findCursor.paragraphIndex); + } + else if (m_findCursor.paragraph == m_selectionEnd.paragraph) + { + m_find->setData(text(m_findCursor.paragraph).left(m_selectionEnd.paragraphIndex), m_findCursor.paragraphIndex); + } + else + { + m_findCursor.paragraphIndex = -1; + m_find->setData(text(m_findCursor.paragraph), m_findCursor.paragraphIndex); + } + + if (inSelection && backwards && m_findCursor.paragraph < m_selectionStart.paragraph) + { + break; + } + + if (inSelection && m_findCursor.paragraph > m_selectionEnd.paragraph) + { + break; + } + } while (backwards ? (m_findCursor.paragraph >= 0) : (m_findCursor.paragraph < paragraphs())); + + Q_ASSERT(res != KFind::Match); + + // If there were no matches, and we were checking from the start of the text, + // then we do not want to prompt to search again, since we already know there + // is nothing. + + if (m_find->numMatches() == 0 && !fromCursor) + { + KMessageBox::sorry(this, + i18n("Search string '%1' was not found!").arg(KStringHandler::csqueeze(m_find->pattern()))); + // Reset the cursor in case more text is added between calls to findNext() + m_findCursor = m_selectionStart; + m_find->setData(text(m_selectionStart.paragraph) + .mid(m_selectionStart.paragraphIndex, + m_selectionEnd.paragraphIndex - m_selectionStart.paragraphIndex)); + return; + } + + if (m_find->shouldRestart(/* forceAsking */ true, /* showNumMatches */ false)) + { + if (inSelection) + { + if (m_selectionStart.paragraph == m_selectionEnd.paragraph) + { + m_findCursor.paragraph = m_selectionStart.paragraph; + m_findCursor.paragraphIndex = m_selectionStart.paragraphIndex; + auto selectionLength = m_selectionEnd.paragraphIndex - m_selectionStart.paragraphIndex; + auto data = text(m_findCursor.paragraph).mid(m_findCursor.paragraphIndex, selectionLength); + m_find->setData(data); + } + else if (backwards) + { + m_findCursor = m_selectionEnd; + m_find->setData(text(m_findCursor.paragraph).left(m_findCursor.paragraphIndex)); + } + else + { + m_findCursor.paragraph = m_selectionStart.paragraph; + m_findCursor.paragraphIndex = -1; + auto offset = (paragraphLength(m_findCursor.paragraph)) - m_selectionStart.paragraphIndex+1; + m_find->setData(text(m_findCursor.paragraph).right(offset), m_findCursor.paragraphIndex); + } + } + else + { + m_findCursor.paragraph = backwards ? (paragraphs() - 1) : 0; + m_findCursor.paragraphIndex = backwards ? (paragraphLength(m_findCursor.paragraph)) : 0; + m_find->setData(text(m_findCursor.paragraph), m_findCursor.paragraphIndex); + } + + m_find->resetCounts(); + findNext(); + } +} + +void KJotsEdit::findPrev() +{ + if (!m_find) + { + find(); + return; + } + + m_find->setOptions(m_find->options() ^ KFindDialog::FindBackwards); + findNext(); + + // Check as pressing 'stop' will delete m_find. + if (m_find) + { + m_find->setOptions(m_find->options() ^ KFindDialog::FindBackwards); + } +} + +void KJotsEdit::slotDoFind() +{ + // tqDebug("KJotsEdit::slotDoFind"); + + /* Performing a new search, ensure the previous search is invalidated. */ + + delete m_find; + m_find = nullptr; + + if (!m_findDialog) + { + // tqDebug("KJotsEdit::slotDoFind: find dialog not set up"); + return; + } + + if (m_findDialog->pattern().isEmpty()) + { + // tqDebug("KJotsEdit::slotDoFind: empty pattern."); + return; + } + + // tqDebug("findDialog->pattern = %s", m_findDialog->pattern().local8Bit().data()); + + m_find = new KFind(m_findDialog->pattern(), m_findDialog->options(), this); + + if (m_find->options() & KFindDialog::SelectedText) + { + const bool backwards = m_find->options() & KFindDialog::FindBackwards; + + getSelection(&m_selectionStart.paragraph, &m_selectionStart.paragraphIndex, &m_selectionEnd.paragraph, + &m_selectionEnd.paragraphIndex); + m_findCursor.paragraph = backwards ? m_selectionEnd.paragraph : m_selectionStart.paragraph; + m_findCursor.paragraphIndex = backwards ? m_selectionEnd.paragraphIndex : m_selectionStart.paragraphIndex; + } + else + { + setupCursor(&m_findCursor, m_find); + // Reset selection so slotFindHighlight works correctly. + m_selectionStart = {0, 0}; + m_selectionEnd = {0, 0}; + } + + connect(m_find, TQ_SIGNAL(highlight(const TQString&, int, int)), this, + TQ_SLOT(slotFindHighlight(const TQString&, int, int))); + connect(m_find, TQ_SIGNAL(findNext()), this, TQ_SLOT(findNext())); + + m_findDialog->close(); + m_find->closeFindNextDialog(); + + findNext(); +} + void KJotsEdit::setEntry (KJotsPage *entry) { //tell the old entry to take a hike @@ -144,6 +589,34 @@ void KJotsEdit::setEntry (KJotsPage *entry) } m_entry = entry; + + // Reset the find & replace dialog for the new entry. + delete m_find; + delete m_replace; + m_find = nullptr; + m_replace = nullptr; +} + +void KJotsEdit::setupCursor(KJotsEdit::CursorPosition* cursor, const KFind* find) +{ + if (!cursor) + { + tqWarning("WARNING: Attempting to setup a NULL cursor: %s (%d)", __FILE__, __LINE__); + return; + } + + cursor->paragraph = 0; + cursor->paragraphIndex = 0; + + if (find->options() & KFindDialog::FromCursor) + { + getCursorPosition(&cursor->paragraph, &cursor->paragraphIndex); + } + else if (find->options() & KFindDialog::FindBackwards) + { + cursor->paragraph = paragraphs(); + cursor->paragraphIndex = paragraphLength(cursor->paragraph); + } } #include "kjotsedit.moc" |