Commit 688a42d9 authored by Martin Küttler's avatar Martin Küttler
Browse files

Searching and replacing works, with one button not yet operating.

There currently is no way to select in which entries to search, because
I am not yet sure about the ui for that. Apart from that, searching
seems to be ok.
parent ad43f7d8
......@@ -119,17 +119,20 @@ CantorPart::CantorPart( QWidget *parentWidget, QObject *parent, const QVariantLi
savePlain->setIcon(KIcon("document-save"));
connect(savePlain, SIGNAL(triggered()), this, SLOT(fileSavePlain()));
KAction* find=new KAction(i18n("Find"), actionCollection());
KAction* find=KStandardAction::find(this, SLOT(showSearchBar()),
actionCollection());
find->setPriority(QAction::LowPriority);
actionCollection()->addAction("edit_find", find);
find->setIcon(KIcon("edit-find"));
connect(find, SIGNAL(triggered()), this, SLOT(showSearchBar()));
KAction* replace=new KAction(i18n("Replace"), actionCollection());
KAction* replace=KStandardAction::replace(this, SLOT(showExtendedSearchBar()),
actionCollection());
replace->setPriority(QAction::LowPriority);
actionCollection()->addAction("edit_find_replace", replace);
replace->setIcon(KIcon("edit-find-replace"));
connect(replace, SIGNAL(triggered()), this, SLOT(showExtendedSearchBar()));
m_findNext = KStandardAction::findNext(this, SLOT(findNext()),
actionCollection());
m_findNext->setEnabled(false);
m_findPrev = KStandardAction::findPrev(this, SLOT(findPrev()),
actionCollection());
m_findPrev->setEnabled(false);
KAction* latexExport=new KAction(i18n("Export to LaTeX"), actionCollection());
actionCollection()->addAction("file_export_latex", latexExport);
......@@ -586,6 +589,9 @@ void CantorPart::showSearchBar()
this, SLOT(searchBarDeleted()));
}
m_findNext->setEnabled(true);
m_findPrev->setEnabled(true);
m_searchBar->showStandard();
m_searchBar->setFocus();
}
......@@ -599,13 +605,30 @@ void CantorPart::showExtendedSearchBar()
this, SLOT(searchBarDeleted()));
}
m_findNext->setEnabled(true);
m_findPrev->setEnabled(true);
m_searchBar->showExtended();
m_searchBar->setFocus();
}
void CantorPart::findNext()
{
if (m_searchBar)
m_searchBar->next();
}
void CantorPart::findPrev()
{
if (m_searchBar)
m_searchBar->prev();
}
void CantorPart::searchBarDeleted()
{
m_searchBar = 0;
m_findNext->setEnabled(false);
m_findPrev->setEnabled(false);
}
void CantorPart::adjustGuiToSession()
......
......@@ -129,6 +129,8 @@ protected slots:
void showSearchBar();
void showExtendedSearchBar();
void findNext();
void findPrev();
void searchBarDeleted();
/** sets the status message, or cached it, if the StatusBar is blocked.
......@@ -156,6 +158,8 @@ private:
KProgressDialog* m_initProgressDlg;
KAction* m_evaluate;
KAction* m_save;
KAction* m_findNext;
KAction* m_findPrev;
KToggleAction* m_typeset;
KToggleAction* m_highlight;
KToggleAction* m_completion;
......
......@@ -727,6 +727,37 @@ QPoint CommandEntry::toGlobalPosition(const QPointF& localPos)
return worksheetView()->viewport()->mapToGlobal(viewportPos);
}
WorksheetCursor CommandEntry::search(QString pattern, unsigned flags,
QTextDocument::FindFlags qt_flags,
const WorksheetCursor& pos)
{
if (pos.isValid() && pos.entry() != this)
return WorksheetCursor();
QTextCursor cursor;
if (flags & WorksheetEntry::SearchCommand) {
cursor = m_commandItem->search(pattern, flags, qt_flags, pos);
if (!cursor.isNull())
return WorksheetCursor(this, m_commandItem, cursor);
}
if (m_errorItem && flags & WorksheetEntry::SearchError) {
cursor = m_errorItem->search(pattern, flags, qt_flags, pos);
if (!cursor.isNull())
return WorksheetCursor(this, m_errorItem, cursor);
}
WorksheetTextItem* textResult = dynamic_cast<WorksheetTextItem*>
(m_resultItem);
if (textResult && flags & WorksheetEntry::SearchResult) {
cursor = textResult->search(pattern, flags, qt_flags, pos);
if (!cursor.isNull())
return WorksheetCursor(this, textResult, cursor);
}
return WorksheetCursor();
}
void CommandEntry::layOutForWidth(double w, bool force)
{
if (w == size().width() && !force)
......
......@@ -81,6 +81,10 @@ class CommandEntry : public WorksheetEntry
WorksheetTextItem* highlightItem();
WorksheetCursor search(QString pattern, unsigned flags,
QTextDocument::FindFlags qt_flags,
const WorksheetCursor& pos = WorksheetCursor());
public slots:
bool evaluate(int evalOp = 0);
bool evaluateCommand(int evalOp = 0);
......@@ -142,7 +146,7 @@ class CommandEntry : public WorksheetEntry
Cantor::CompletionObject* m_completionObject;
QPointer<KCompletionBox> m_completionBox;
Cantor::SyntaxHelpObject* m_syntaxHelpObject;
int m_evaluationFlag;
};
......
......@@ -292,6 +292,45 @@ bool LatexEntry::isOneImageOnly()
return (cursor.selectionEnd() == 1 && cursor.selectedText() == QString(QChar::ObjectReplacementCharacter));
}
WorksheetCursor LatexEntry::search(QString pattern, unsigned flags,
QTextDocument::FindFlags qt_flags,
const WorksheetCursor& pos)
{
if (!(flags & WorksheetEntry::SearchLaTeX))
return WorksheetCursor();
if (pos.isValid() && (pos.entry() != this || pos.textItem() != m_textItem))
return WorksheetCursor();
QString text = latexCode();
Qt::CaseSensitivity caseSensitivity;
if (qt_flags & QTextDocument::FindCaseSensitively)
caseSensitivity = Qt::CaseSensitive;
else
caseSensitivity = Qt::CaseInsensitive;
int position;
if (pos.isValid()) {
if (qt_flags & QTextDocument::FindBackward)
position = text.lastIndexOf(pattern, pos.textCursor().position(),
caseSensitivity);
else
position = text.indexOf(pattern, pos.textCursor().position(),
caseSensitivity);
} else {
if (qt_flags & QTextDocument::FindBackward)
position = text.lastIndexOf(pattern, -1, caseSensitivity);
else
position = text.indexOf(pattern, 0, caseSensitivity);
}
QTextCursor cursor = m_textItem->textCursor();
if (position >= 0)
cursor.setPosition(position);
else
cursor = QTextCursor();
return WorksheetCursor(this, m_textItem, cursor);
}
void LatexEntry::layOutForWidth(double w, bool force)
{
if (size().width() == w && !force)
......
......@@ -41,7 +41,7 @@ class LatexEntry : public WorksheetEntry
bool acceptRichText();
bool focusEntry(int pos = WorksheetTextItem::TopLeft, qreal xCoord = 0);
void setContent(const QString& content);
void setContent(const QDomElement& content, const KZip& file);
......@@ -52,6 +52,10 @@ class LatexEntry : public WorksheetEntry
void layOutForWidth(double w, bool force = false);
WorksheetCursor search(QString pattern, unsigned flags,
QTextDocument::FindFlags qt_flags,
const WorksheetCursor& pos = WorksheetCursor());
public slots:
bool evaluate(int evalOp = 0);
void resolveImagesAtCursor();
......
......@@ -33,8 +33,15 @@ SearchBar::SearchBar(QWidget* parent, Worksheet* worksheet) : QWidget(parent)
m_stdUi = new Ui::StandardSearchBar();
m_extUi = 0;
setupStdUi();
m_qtFlags = 0;
m_startCursor = worksheet->worksheetCursor();
m_searchFlags = WorksheetEntry::SearchText;
m_currentCursor = m_startCursor;
m_atBeginning = false;
m_atEnd = false;
m_notFound = false;
m_searchFlags = WorksheetEntry::SearchCommand |
WorksheetEntry::SearchError | WorksheetEntry::SearchResult |
WorksheetEntry::SearchText | WorksheetEntry::SearchLaTeX;
}
SearchBar::~SearchBar()
......@@ -49,7 +56,7 @@ void SearchBar::showStandard()
{
if (m_stdUi)
return;
delete m_extUi;
m_extUi = 0;
foreach(QObject* child, children()) {
......@@ -64,7 +71,7 @@ void SearchBar::showExtended()
{
if (m_extUi)
return;
delete m_stdUi;
m_stdUi = 0;
foreach(QObject* child, children()) {
......@@ -73,41 +80,114 @@ void SearchBar::showExtended()
delete layout();
m_extUi = new Ui::ExtendedSearchBar();
setupExtUi();
}
void SearchBar::next()
{
if (!m_currentCursor.isValid() && !m_atEnd)
return;
searchForward(true);
}
void SearchBar::prev()
{
if (!m_currentCursor.isValid() && !m_atBeginning)
return;
searchBackward(true);
}
void SearchBar::search()
void SearchBar::searchBackward(bool skipFirstChar)
{
WorksheetCursor result;
WorksheetEntry* entry;
if (m_startCursor.isValid()) {
result = m_startCursor.entry()->search(m_pattern, m_searchFlags,
m_startCursor);
entry = m_startCursor.entry()->next();
worksheet()->setWorksheetCursor(WorksheetCursor());
QTextDocument::FindFlags f = m_qtFlags | QTextDocument::FindBackward;
if (m_currentCursor.isValid()) {
bool atBeginningOfEntry = false;
if (skipFirstChar) {
QTextCursor c = m_currentCursor.textCursor();
c.movePosition(QTextCursor::PreviousCharacter);
atBeginningOfEntry = (c == m_currentCursor.textCursor());
m_currentCursor = WorksheetCursor(m_currentCursor.entry(),
m_currentCursor.textItem(), c);
}
if (!atBeginningOfEntry)
result = m_currentCursor.entry()->search(m_pattern, m_searchFlags,
f, m_currentCursor);
entry = m_currentCursor.entry()->previous();
} else {
entry = worksheet()->lastEntry();
}
m_currentCursor = WorksheetCursor();
while (!result.isValid() && entry) {
result = entry->search(m_pattern, m_searchFlags, f);
entry = entry->previous();
}
if (result.isValid()) {
m_atBeginning = false;
QTextCursor c = result.textCursor();
if (result.textCursor().hasSelection())
c.setPosition(result.textCursor().selectionStart());
m_currentCursor = WorksheetCursor(result.entry(), result.textItem(), c);
clearStatus();
worksheet()->setWorksheetCursor(result);
} else {
if (m_atBeginning) {
m_notFound = true;
setStatus(i18n("Not found"));
} else {
m_atBeginning = true;
setStatus(i18n("Reached beginning of worksheet"));
}
worksheet()->setWorksheetCursor(m_startCursor);
}
}
void SearchBar::searchForward(bool skipFirstChar)
{
WorksheetCursor result;
WorksheetEntry* entry;
worksheet()->setWorksheetCursor(WorksheetCursor());
if (m_currentCursor.isValid()) {
if (skipFirstChar) {
QTextCursor c = m_currentCursor.textCursor();
c.movePosition(QTextCursor::NextCharacter);
kDebug() << c.position();
m_currentCursor = WorksheetCursor(m_currentCursor.entry(),
m_currentCursor.textItem(), c);
}
result = m_currentCursor.entry()->search(m_pattern, m_searchFlags,
m_qtFlags, m_currentCursor);
entry = m_currentCursor.entry()->next();
} else {
entry = worksheet()->firstEntry();
}
m_currentCursor = WorksheetCursor();
while (!result.isValid() && entry) {
result = entry->search(m_pattern, m_searchFlags);
result = entry->search(m_pattern, m_searchFlags, m_qtFlags);
entry = entry->next();
}
if (result.isValid()) {
m_currentCursor = result;
m_atEnd = false;
QTextCursor c = result.textCursor();
if (result.textCursor().hasSelection())
c.setPosition(result.textCursor().selectionStart());
m_currentCursor = WorksheetCursor(result.entry(), result.textItem(), c);
clearStatus();
worksheet()->setWorksheetCursor(result);
} else {
setStatus(i18n("Not found"));
if (m_atEnd) {
m_notFound = true;
setStatus(i18n("Not found"));
} else {
m_atEnd = true;
setStatus(i18n("Reached end of worksheet"));
}
worksheet()->setWorksheetCursor(m_startCursor);
}
}
......@@ -126,24 +206,69 @@ void SearchBar::on_openStandard_clicked()
showStandard();
}
void SearchBar::on_next_clicked()
{
next();
}
void SearchBar::on_previous_clicked()
{
prev();
}
void SearchBar::on_replace_clicked()
{
if (!m_currentCursor.isValid())
return;
QTextCursor cursor = m_currentCursor.textCursor();
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor,
m_pattern.length());
cursor.insertText(m_replacement);
next();
}
void SearchBar::on_replaceAll_clicked()
{
int count = 0;
WorksheetEntry* entry = worksheet()->firstEntry();
WorksheetCursor cursor;
for (; entry; entry = entry->next()) {
cursor = entry->search(m_pattern, m_searchFlags, m_qtFlags);
while (cursor.isValid()) {
cursor.textCursor().insertText(m_replacement);
cursor = entry->search(m_pattern, m_searchFlags, m_qtFlags,
cursor);
++count;
}
}
setStatus(i18n("Replaced %1 instances").arg(count));
}
void SearchBar::on_pattern_textChanged(const QString& p)
{
worksheet()->setWorksheetCursor(WorksheetCursor());
m_atBeginning = m_atEnd = m_notFound = false;
if (!p.startsWith(m_pattern))
m_currentCursor = m_startCursor;
m_pattern = p;
if (!m_pattern.isEmpty())
search();
searchForward();
else
worksheet()->setWorksheetCursor(m_startCursor);
}
void SearchBar::on_replace_textChanged(const QString& r)
void SearchBar::on_replacement_textChanged(const QString& r)
{
m_replace = r;
m_replacement = r;
}
void SearchBar::on_matchCase_toggled(bool b)
{
m_matchCase = b;
m_qtFlags &= ~QTextDocument::FindCaseSensitively;
if (b)
m_qtFlags |= QTextDocument::FindCaseSensitively;
searchForward();
}
void SearchBar::setStatus(QString message)
......@@ -171,10 +296,10 @@ void SearchBar::setupStdUi()
m_stdUi->close->setIcon(KIcon("dialog-close"));
m_stdUi->openExtended->setIcon(KIcon("arrow-up-double"));
m_stdUi->pattern->setText(m_pattern);
m_stdUi->matchCase->setChecked(m_matchCase);
m_stdUi->matchCase->setChecked(m_qtFlags & QTextDocument::FindCaseSensitively);
m_stdUi->next->setIcon(KIcon("go-down-search"));
m_stdUi->previous->setIcon(KIcon("go-up-search"));
setFocusProxy(m_stdUi->pattern);
}
......@@ -187,8 +312,8 @@ void SearchBar::setupExtUi()
m_extUi->close->setIcon(KIcon("dialog-close"));
m_extUi->openStandard->setIcon(KIcon("arrow-down-double"));
m_extUi->pattern->setText(m_pattern);
m_extUi->replace->setText(m_replace);
m_extUi->matchCase->setChecked(m_matchCase);
m_extUi->replacement->setText(m_replacement);
m_extUi->matchCase->setChecked(m_qtFlags & QTextDocument::FindCaseSensitively);
m_extUi->next->setIcon(KIcon("go-down-search"));
m_extUi->previous->setIcon(KIcon("go-up-search"));
// ...
......
......@@ -23,6 +23,7 @@
#include <QWidget>
#include <QList>
#include <QTextDocument>
#include "ui_standardsearchbar.h"
#include "ui_extendedsearchbar.h"
......@@ -46,14 +47,19 @@ class SearchBar : public QWidget
void next();
void prev();
void search();
void searchForward(bool skipFirstChar = false);
void searchBackward(bool skipFirstChar = false);
public slots:
void on_close_clicked();
void on_openExtended_clicked();
void on_openStandard_clicked();
void on_next_clicked();
void on_previous_clicked();
void on_replace_clicked();
void on_replaceAll_clicked();
void on_pattern_textChanged(const QString& p);
void on_replace_textChanged(const QString& r);
void on_replacement_textChanged(const QString& r);
void on_matchCase_toggled(bool b);
private:
......@@ -74,9 +80,13 @@ class SearchBar : public QWidget
Worksheet* m_worksheet;
QString m_pattern;
QString m_replace;
bool m_matchCase;
QString m_replacement;
QTextDocument::FindFlags m_qtFlags;
unsigned int m_searchFlags;
bool m_atBeginning;
bool m_atEnd;
bool m_notFound;
};
#endif // SEARCHBAR_H
......
......@@ -170,7 +170,7 @@ QString TextEntry::toPlain(const QString& commandSep, const QString& commentStar
if (!commentEndingSeq.isEmpty())
return commentStartingSeq + text + commentEndingSeq + "\n";
return commentStartingSeq + text.replace("\n", "\n" + commentStartingSeq) + "\n";
}
void TextEntry::interruptEvaluation()
......@@ -285,24 +285,19 @@ QString TextEntry::showLatexCode(QTextCursor cursor)
return latexCode;
}
WorksheetCursor TextEntry::search(QString pattern, unsigned flags,
WorksheetCursor TextEntry::search(QString pattern, unsigned flags,
QTextDocument::FindFlags qt_flags,
const WorksheetCursor& pos)
{
if (!(flags & WorksheetEntry::SearchText))
return WorksheetCursor();
if (pos.isValid() && (pos.entry() != this || pos.textItem() != m_textItem))
if (!(flags & WorksheetEntry::SearchText) ||
(pos.isValid() && pos.entry() != this))
return WorksheetCursor();
QTextDocument* doc = m_textItem->document();
QTextCursor cursor;
if (pos.isValid())
cursor = doc->find(pattern, pos.textCursor());
else
cursor = doc->find(pattern);
QTextCursor cursor = m_textItem->search(pattern, flags, qt_flags, pos);
if (cursor.isNull())
return WorksheetCursor();
return WorksheetCursor(this, m_textItem, cursor);
else
return WorksheetCursor(this, m_textItem, cursor);
}
......
......@@ -61,7 +61,8 @@ class TextEntry : public WorksheetEntry
void layOutForWidth(double w, bool force = false);
WorksheetCursor search(QString pattern, unsigned flags,
WorksheetCursor search(QString pattern, unsigned flags,
QTextDocument::FindFlags qt_flags,
const WorksheetCursor& pos = WorksheetCursor());
public slots:
......
......@@ -213,6 +213,17 @@ void Worksheet::setWorksheetCursor(const WorksheetCursor& cursor)
if (!cursor.isValid())
return;
QGraphicsItem* item = m_focusItem;
while (item && item->type() != WorksheetTextItem::Type)
item = item->parentItem();
WorksheetTextItem* oldItem = qgraphicsitem_cast<WorksheetTextItem*>(item);
if (oldItem)
oldItem->clearSelection();
m_focusItem = cursor.textItem();
cursor.textItem()->setTextCursor(cursor.textCursor());
}
......
......@@ -158,6 +158,18 @@ Worksheet* WorksheetEntry::worksheet()
return qobject_cast<Worksheet*>(scene());
}
WorksheetCursor WorksheetEntry::search(QString pattern, unsigned flags,
QTextDocument::FindFlags qt_flags,
const WorksheetCursor& pos)
{
Q_UNUSED(pattern);
Q_UNUSED(flags);
Q_UNUSED(qt_flags);
Q_UNUSED(pos);
return WorksheetCursor();
}
void WorksheetEntry::keyPressEvent(QKeyEvent* event)
{
// This event is used in Entries that set the ItemIsFocusable flag
......
......@@ -97,10 +97,12 @@ class WorksheetEntry : public QGraphicsObject
virtual WorksheetTextItem* highlightItem();
enum SearchFlag {SearchText=1, SearchCommand=2, SearchResult=4};
enum SearchFlag {SearchCommand=1, SearchResult=2, SearchError=4,
SearchText=8, SearchLaTeX=16};
virtual WorksheetCursor search(QString pattern, unsigned flags,
const WorksheetCursor& pos = WorksheetCursor()) /*=0*/ {return WorksheetCursor();};
virtual WorksheetCursor search(QString pattern, unsigned flags,
QTextDocument::FindFlags qt_flags,