diff --git a/src/textentry.cpp b/src/textentry.cpp index 614bc773..3dc74348 100644 --- a/src/textentry.cpp +++ b/src/textentry.cpp @@ -1,300 +1,301 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2009 Alexander Rieder Copyright (C) 2012 Martin Kuettler */ #include "textentry.h" #include "worksheettextitem.h" #include "animationhandler.h" #include "epsrenderer.h" #include "latexrenderer.h" #include #include #include #include TextEntry::TextEntry(Worksheet* worksheet) : WorksheetEntry(worksheet), m_textItem(new WorksheetTextItem(this, Qt::TextEditorInteraction)) { + m_textItem->enableRichText(true); connect(m_textItem, SIGNAL(moveToPrevious(int, qreal)), this, SLOT(moveToPreviousEntry(int, qreal))); connect(m_textItem, SIGNAL(moveToNext(int, qreal)), this, SLOT(moveToNextEntry(int, qreal))); connect(m_textItem, SIGNAL(execute()), this, SLOT(evaluate())); connect(m_textItem, SIGNAL(doubleClick()), this, SLOT(resolveImagesAtCursor())); } TextEntry::~TextEntry() { } void TextEntry::populateMenu(KMenu *menu, const QPointF& pos) { bool imageSelected = false; QTextCursor cursor = m_textItem->textCursor(); const QChar repl = QChar::ObjectReplacementCharacter; if (cursor.hasSelection()) { QString selection = m_textItem->textCursor().selectedText(); imageSelected = selection.contains(repl); } else { // we need to try both the current cursor and the one after the that cursor = m_textItem->cursorForPosition(pos); kDebug() << cursor.position(); for (int i = 2; i; --i) { int p = cursor.position(); if (m_textItem->document()->characterAt(p-1) == repl && cursor.charFormat().hasProperty(EpsRenderer::CantorFormula)) { m_textItem->setTextCursor(cursor); imageSelected = true; break; } cursor.movePosition(QTextCursor::NextCharacter); } } if (imageSelected) { menu->addAction(i18n("Show LaTeX code"), this, SLOT(resolveImagesAtCursor())); menu->addSeparator(); } WorksheetEntry::populateMenu(menu, pos); } bool TextEntry::isEmpty() { return m_textItem->document()->isEmpty(); } int TextEntry::type() const { return Type; } bool TextEntry::acceptRichText() { return true; } bool TextEntry::focusEntry(int pos, qreal xCoord) { if (aboutToBeRemoved()) return false; m_textItem->setFocusAt(pos, xCoord); return true; } void TextEntry::setContent(const QString& content) { m_textItem->setPlainText(content); } void TextEntry::setContent(const QDomElement& content, const KZip& file) { Q_UNUSED(file); if(content.firstChildElement("body").isNull()) return; QDomDocument doc = QDomDocument(); QDomNode n = doc.importNode(content.firstChildElement("body"), true); doc.appendChild(n); QString html = doc.toString(); kDebug() << html; m_textItem->setHtml(html); } QDomElement TextEntry::toXml(QDomDocument& doc, KZip* archive) { Q_UNUSED(archive); bool needsEval=false; //make sure that the latex code is shown instead of the rendered formulas QTextCursor cursor = m_textItem->document()->find(QString(QChar::ObjectReplacementCharacter)); while(!cursor.isNull()) { QTextCharFormat format = cursor.charFormat(); if (format.hasProperty(EpsRenderer::CantorFormula)) { showLatexCode(cursor); needsEval=true; } cursor = m_textItem->document()->find(QString(QChar::ObjectReplacementCharacter), cursor); } const QString& html = m_textItem->toHtml(); kDebug() << html; QDomElement el = doc.createElement("Text"); QDomDocument myDoc = QDomDocument(); myDoc.setContent(html); el.appendChild(myDoc.documentElement().firstChildElement("body")); if (needsEval) evaluate(false); return el; } QString TextEntry::toPlain(const QString& commandSep, const QString& commentStartingSeq, const QString& commentEndingSeq) { Q_UNUSED(commandSep); if (commentStartingSeq.isEmpty()) return QString(); /* // whould this be plain enought? QTextCursor cursor = m_textItem->textCursor(); cursor.movePosition(QTextCursor::Start); cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor); QString text = m_textItem->resolveImages(cursor); text.replace(QChar::ParagraphSeparator, '\n'); text.replace(QChar::LineSeparator, '\n'); */ QString text = m_textItem->toPlainText(); if (!commentEndingSeq.isEmpty()) return commentStartingSeq + text + commentEndingSeq + "\n"; return commentStartingSeq + text.replace("\n", "\n" + commentStartingSeq) + "\n"; } void TextEntry::interruptEvaluation() { } bool TextEntry::evaluate(int evalOp) { QTextCursor cursor = findLatexCode(); while (!cursor.isNull()) { QString latexCode = cursor.selectedText(); kDebug()<<"found latex: "<setLatexCode(latexCode); renderer->setEquationOnly(true); renderer->setEquationType(Cantor::LatexRenderer::InlineEquation); renderer->setMethod(Cantor::LatexRenderer::LatexMethod); renderer->renderBlocking(); bool success; QTextImageFormat formulaFormat; if (renderer->renderingSuccessful()) { EpsRenderer* epsRend = worksheet()->epsRenderer(); formulaFormat = epsRend->render(m_textItem->document(), renderer); success = !formulaFormat.name().isEmpty(); } else { success = false; } kDebug()<<"rendering successfull? "<document()->find(QString(QChar::ObjectReplacementCharacter)); while(!cursor.isNull()) { QTextCharFormat format = cursor.charFormat(); if (format.hasProperty(EpsRenderer::CantorFormula)) { kDebug() << "found a formula... rendering the eps..."; QUrl url=qVariantValue(format.property(EpsRenderer::ImagePath)); QSizeF s = worksheet()->epsRenderer()->renderToResource(m_textItem->document(), url); kDebug() << "rendering successfull? " << s.isValid(); //cursor.deletePreviousChar(); //cursor.insertText(QString(QChar::ObjectReplacementCharacter), format); } cursor = m_textItem->document()->find(QString(QChar::ObjectReplacementCharacter), cursor); } } void TextEntry::resolveImagesAtCursor() { QTextCursor cursor = m_textItem->textCursor(); if (!cursor.hasSelection()) cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor); cursor.insertText(m_textItem->resolveImages(cursor)); } QTextCursor TextEntry::findLatexCode(QTextCursor cursor) const { QTextDocument *doc = m_textItem->document(); QTextCursor startCursor; if (cursor.isNull()) startCursor = doc->find("$$"); else startCursor = doc->find("$$", cursor); if (startCursor.isNull()) return startCursor; const QTextCursor endCursor = doc->find("$$", startCursor); if (endCursor.isNull()) return endCursor; startCursor.setPosition(startCursor.selectionStart()); startCursor.setPosition(endCursor.position(), QTextCursor::KeepAnchor); return startCursor; } QString TextEntry::showLatexCode(QTextCursor cursor) { QString latexCode = qVariantValue(cursor.charFormat().property(EpsRenderer::Code)); cursor.deletePreviousChar(); latexCode = "$$"+latexCode+"$$"; cursor.insertText(latexCode); return latexCode; } void TextEntry::layOutForWidth(double w, bool force) { if (size().width() == w && !force) return; m_textItem->setPos(0,0); m_textItem->setTextWidth(w); setSize(QSizeF(w, m_textItem->height() + VerticalMargin)); } bool TextEntry::wantToEvaluate() { return !findLatexCode().isNull(); } diff --git a/src/worksheettextitem.cpp b/src/worksheettextitem.cpp index 75b3aa2a..93b9991b 100644 --- a/src/worksheettextitem.cpp +++ b/src/worksheettextitem.cpp @@ -1,554 +1,596 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2012 Martin Kuettler */ #include "worksheettextitem.h" #include "worksheet.h" #include "worksheetentry.h" #include "epsrenderer.h" #include #include #include #include #include #include #include #include #include #include #include #include WorksheetTextItem::WorksheetTextItem(QGraphicsObject* parent, Qt::TextInteractionFlags ti) : QGraphicsTextItem(parent) { setTextInteractionFlags(ti); if (ti & Qt::TextEditable) connect(this, SIGNAL(sizeChanged()), parent, SLOT(recalculateSize())); m_completionEnabled = false; m_completionActive = false; m_draggingEnabled = false; + m_richTextEnabled = false; m_height = 0; setAcceptDrops(true); setFont(KGlobalSettings::fixedFont()); connect(document(), SIGNAL(contentsChange(int, int, int)), this, SLOT(setHeight())); connect(document(), SIGNAL(contentsChanged()), this, SLOT(testHeight())); connect(this, SIGNAL(menuCreated(KMenu*, const QPointF&)), parent, SLOT(populateMenu(KMenu*, const QPointF&)), Qt::DirectConnection); connect(this, SIGNAL(deleteEntry()), parent, SLOT(startRemoving())); connect(this, SIGNAL(appendCommandEntry()), worksheet(), SLOT(insertCommandEntry())); } WorksheetTextItem::~WorksheetTextItem() { } int WorksheetTextItem::type() const { return Type; } void WorksheetTextItem::setHeight() { m_height = height(); } void WorksheetTextItem::testHeight() { if (m_height != height()) emit sizeChanged(); } void WorksheetTextItem::populateMenu(KMenu *menu, const QPointF& pos) { kDebug() << "populate Menu"; KAction* cut = KStandardAction::cut(this, SLOT(cut()), menu); KAction* copy = KStandardAction::copy(this, SLOT(copy()), menu); KAction* paste = KStandardAction::paste(this, SLOT(paste()), menu); if (!textCursor().hasSelection()) { cut->setEnabled(false); copy->setEnabled(false); } if (QApplication::clipboard()->text().isEmpty()) { paste->setEnabled(false); } if (isEditable()) menu->addAction(cut); if (!m_draggingEnabled) menu->addAction(copy); if (isEditable()) menu->addAction(paste); menu->addSeparator(); emit menuCreated(menu, mapToParent(pos)); } +QKeyEvent* WorksheetTextItem::eventForStandardAction(KStandardAction::StandardAction actionID) +{ + // there must be a better way to get the shortcut... + KAction* action = KStandardAction::create(actionID, this, 0, this); + QKeySequence keySeq = action->shortcut().primary(); + // we do not support key sequences with multiple keys here + int code = keySeq[0]; + const int ModMask = Qt::ShiftModifier | Qt::ControlModifier | + Qt::AltModifier | Qt::MetaModifier; + const int KeyMask = ~ModMask; + QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, code & KeyMask, + QFlags(code & ModMask)); + delete action; + return event; +} + void WorksheetTextItem::cut() { - copy(); - textCursor().removeSelectedText(); + if (richTextEnabled()) { + QKeyEvent* event = eventForStandardAction(KStandardAction::Cut); + QApplication::sendEvent(worksheet(), event); + delete event; + } else { + copy(); + textCursor().removeSelectedText(); + } } void WorksheetTextItem::paste() { - textCursor().insertText(QApplication::clipboard()->text()); + if (richTextEnabled()) { + QKeyEvent* event = eventForStandardAction(KStandardAction::Paste); + QApplication::sendEvent(worksheet(), event); + delete event; + } else { + textCursor().insertText(QApplication::clipboard()->text()); + } } void WorksheetTextItem::copy() { - if (!textCursor().hasSelection()) - return; - QApplication::clipboard()->setText(resolveImages(textCursor())); + if (richTextEnabled()) { + QKeyEvent* event = eventForStandardAction(KStandardAction::Copy); + QApplication::sendEvent(worksheet(), event); + delete event; + } else { + if (!textCursor().hasSelection()) + return; + QApplication::clipboard()->setText(resolveImages(textCursor())); + } } QString WorksheetTextItem::resolveImages(const QTextCursor& cursor) { int start = cursor.selectionStart(); int end = cursor.selectionEnd(); const QString repl = QString(QChar::ObjectReplacementCharacter); QString result; QTextCursor cursor1 = textCursor(); cursor1.setPosition(start); QTextCursor cursor2 = document()->find(repl, cursor1); for (; !cursor2.isNull() && cursor2.selectionEnd() <= end; cursor2 = document()->find(repl, cursor1)) { cursor1.setPosition(cursor2.selectionStart(), QTextCursor::KeepAnchor); result += cursor1.selectedText(); QVariant var = cursor2.charFormat().property(EpsRenderer::Delimiter); QString delim; if (var.isValid()) delim = qVariantValue(var); else delim = ""; result += delim + qVariantValue(cursor2.charFormat().property(EpsRenderer::Code)) + delim; cursor1.setPosition(cursor2.selectionEnd()); } cursor1.setPosition(end, QTextCursor::KeepAnchor); result += cursor1.selectedText(); return result; } void WorksheetTextItem::setCursorPosition(const QPointF& pos) { QTextCursor cursor = cursorForPosition(pos); setTextCursor(cursor); emit cursorPositionChanged(cursor); //setLocalCursorPosition(mapFromParent(pos)); } QPointF WorksheetTextItem::cursorPosition() const { return mapToParent(localCursorPosition()); } void WorksheetTextItem::setLocalCursorPosition(const QPointF& pos) { int p = document()->documentLayout()->hitTest(pos, Qt::FuzzyHit); QTextCursor cursor = textCursor(); cursor.setPosition(p); setTextCursor(cursor); emit cursorPositionChanged(cursor); } QPointF WorksheetTextItem::localCursorPosition() const { QTextCursor cursor = textCursor(); QTextBlock block = cursor.block(); int p = cursor.position() - block.position(); QTextLine line = block.layout()->lineForTextPosition(p); if (!line.isValid()) // can this happen? return block.layout()->position(); return QPointF(line.cursorToX(p), line.y() + line.height()); } QTextCursor WorksheetTextItem::cursorForPosition(const QPointF& pos) const { QPointF lpos = mapFromParent(pos); int p = document()->documentLayout()->hitTest(lpos, Qt::FuzzyHit); QTextCursor cursor = textCursor(); cursor.setPosition(p); return cursor; } -/* -void WorksheetTextItem::setEditable(bool e) +bool WorksheetTextItem::isEditable() { - if (e) - setTextInteractionFlags(Qt::TextEditorInteraction); - else - setTextInteractionFlags(Qt::TextSelectableByMouse); + return textInteractionFlags() & Qt::TextEditable; } -*/ -bool WorksheetTextItem::isEditable() +bool WorksheetTextItem::richTextEnabled() { - return textInteractionFlags() & Qt::TextEditable; + return m_richTextEnabled; } void WorksheetTextItem::enableCompletion(bool b) { m_completionEnabled = b; } void WorksheetTextItem::activateCompletion(bool b) { m_completionActive = b; } void WorksheetTextItem::enableDragging(bool b) { m_draggingEnabled = b; } +void WorksheetTextItem::enableRichText(bool b) +{ + m_richTextEnabled = b; +} + void WorksheetTextItem::setFocusAt(int pos, qreal xCoord) { QTextCursor cursor = textCursor(); if (pos == TopLeft) { cursor.movePosition(QTextCursor::Start); } else if (pos == BottomRight) { cursor.movePosition(QTextCursor::End); } else { QTextLine line; if (pos == TopCoord) { line = document()->firstBlock().layout()->lineAt(0); } else { QTextLayout* layout = document()->lastBlock().layout(); kDebug() << document()->blockCount() << "blocks"; kDebug() << document()->lastBlock().lineCount() << "lines in last block"; line = layout->lineAt(document()->lastBlock().lineCount()-1); } qreal x = mapFromScene(xCoord, 0).x(); int p = line.xToCursor(x); cursor.setPosition(p); // Hack: The code for selecting the last line above does not work. // This is a workaround if (pos == BottomCoord) while (cursor.movePosition(QTextCursor::Down)) ; } setTextCursor(cursor); emit cursorPositionChanged(cursor); setFocus(); } Cantor::Session* WorksheetTextItem::session() { return worksheet()->session(); } void WorksheetTextItem::keyPressEvent(QKeyEvent *event) { if (event->key() == Qt::Key_C && event->modifiers() == Qt::ControlModifier) { - copy(); + if (!richTextEnabled()) + copy(); + else + QGraphicsTextItem::keyPressEvent(event); return; } if (!isEditable()) return; switch (event->key()) { case Qt::Key_Left: if (event->modifiers() == Qt::NoModifier && textCursor().atStart()) { emit moveToPrevious(BottomRight, 0); kDebug()<<"Reached leftmost valid position"; return; } break; case Qt::Key_Right: if (event->modifiers() == Qt::NoModifier && textCursor().atEnd()) { emit moveToNext(TopLeft, 0); kDebug()<<"Reached rightmost valid position"; return; } break; case Qt::Key_Up: if (event->modifiers() == Qt::NoModifier && !textCursor().movePosition(QTextCursor::Up)) { qreal x = mapToScene(localCursorPosition()).x(); emit moveToPrevious(BottomCoord, x); kDebug()<<"Reached topmost valid position" << localCursorPosition().x(); return; } break; case Qt::Key_Down: if (event->modifiers() == Qt::NoModifier && !textCursor().movePosition(QTextCursor::Down)) { qreal x = mapToScene(localCursorPosition()).x(); emit moveToNext(TopCoord, x); kDebug()<<"Reached bottommost valid position" << localCursorPosition().x(); return; } break; case Qt::Key_Enter: case Qt::Key_Return: if (event->modifiers() == Qt::ShiftModifier) { emit execute(); return; } else if (event->modifiers() == Qt::ControlModifier) { emit appendCommandEntry(); return; } else if (event->modifiers() == Qt::NoModifier && m_completionActive) { emit applyCompletion(); return; } break; case Qt::Key_Delete: if (event->modifiers() == Qt::ShiftModifier) { emit deleteEntry(); return; } break; - /* call our custom functions for cut and paste */ + /* Call our custom functions for cut and paste, unless richtext is + enabled */ case Qt::Key_X: - if (event->modifiers() == Qt::ControlModifier) { + if (event->modifiers() == Qt::ControlModifier && !richTextEnabled()) { cut(); return; } break; case Qt::Key_V: - if (event->modifiers() == Qt::ControlModifier) { + if (event->modifiers() == Qt::ControlModifier && !richTextEnabled()) { paste(); return; } break; default: break; } int p = textCursor().position(); QGraphicsTextItem::keyPressEvent(event); if (p != textCursor().position()) emit cursorPositionChanged(textCursor()); } bool WorksheetTextItem::sceneEvent(QEvent *event) { // QGraphicsTextItem's TabChangesFocus feature prevents calls to // keyPressEvent for Tab, even when it's turned off. So we got to catch // that here. if (event->type() == QEvent::KeyPress) { QKeyEvent* kev = dynamic_cast(event); if (kev->key() == Qt::Key_Tab && kev->modifiers() == Qt::NoModifier) { QTextCursor cursor = textCursor(); // maybe we can do something smart with selections here, // but for now we just ignore them. cursor.clearSelection(); cursor.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor); QString sel = cursor.selectedText(); bool spacesOnly = true; for (QString::iterator it = sel.begin(); it != sel.end(); ++it) { if (*it != ' ') { spacesOnly = false; break; } } if (spacesOnly || !worksheet()->completionEnabled()) { cursor.setPosition(cursor.selectionEnd()); while (document()->characterAt(cursor.position()) == ' ') cursor.movePosition(QTextCursor::NextCharacter); setTextCursor(cursor); insertTab(); } else if (m_completionEnabled) { emit tabPressed(); } return true; } else if ((kev->key() == Qt::Key_Tab && kev->modifiers() == Qt::ShiftModifier) || kev->key() == Qt::Key_Backtab) { emit backtabPressed(); return true; } } return QGraphicsTextItem::sceneEvent(event); } void WorksheetTextItem::focusInEvent(QFocusEvent *event) { QGraphicsTextItem::focusInEvent(event); parentItem()->ensureVisible(); emit receivedFocus(this); } void WorksheetTextItem::focusOutEvent(QFocusEvent *event) { if (event->reason() == Qt::MouseFocusReason || event->reason() == Qt::OtherFocusReason) { QTextCursor cursor = textCursor(); cursor.clearSelection(); setTextCursor(cursor); } QGraphicsTextItem::focusOutEvent(event); emit cursorPositionChanged(QTextCursor()); } void WorksheetTextItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { int p = textCursor().position(); QGraphicsTextItem::mousePressEvent(event); if (isEditable() && event->button() == Qt::MiddleButton && QApplication::clipboard()->supportsSelection() && !event->isAccepted()) event->accept(); if (p != textCursor().position()) emit cursorPositionChanged(textCursor()); } void WorksheetTextItem::mouseMoveEvent(QGraphicsSceneMouseEvent* event) { const QPointF buttonDownPos = event->buttonDownPos(Qt::LeftButton); if (m_draggingEnabled && event->button() == Qt::LeftButton && contains(buttonDownPos) && (event->pos() - buttonDownPos).manhattanLength() >= QApplication::startDragDistance()) { emit drag(mapToParent(buttonDownPos), mapToParent(event->pos())); } else { QGraphicsTextItem::mouseMoveEvent(event); } } void WorksheetTextItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { kDebug() << "mouse released"; int p = textCursor().position(); // custom middle-click paste that does not copy rich text if (isEditable() && event->button() == Qt::MiddleButton && - QApplication::clipboard()->supportsSelection() /* && - isPlainText() */) { + QApplication::clipboard()->supportsSelection() && + !richTextEnabled()) { setLocalCursorPosition(mapFromScene(event->scenePos())); const QString& text = QApplication::clipboard()->text(QClipboard::Selection); textCursor().insertText(text); } else { QGraphicsTextItem::mouseReleaseEvent(event); } if (p != textCursor().position()) emit cursorPositionChanged(textCursor()); } void WorksheetTextItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { QTextCursor cursor = textCursor(); const QChar repl = QChar::ObjectReplacementCharacter; if (!cursor.hasSelection()) { // We look at the current cursor and the next cursor for a // ObjectReplacementCharacter for (int i = 2; i; --i) { if (document()->characterAt(cursor.position()-1) == repl) { setTextCursor(cursor); emit doubleClick(); return; } cursor.movePosition(QTextCursor::NextCharacter); } } else if (cursor.selectedText().contains(repl)) { emit doubleClick(); return; } QGraphicsTextItem::mouseDoubleClickEvent(event); } void WorksheetTextItem::dragEnterEvent(QGraphicsSceneDragDropEvent* event) { if (isEditable() && event->mimeData()->hasFormat("text/plain")) { if (event->proposedAction() & (Qt::CopyAction | Qt::MoveAction)) { event->acceptProposedAction(); } else if (event->possibleActions() & Qt::CopyAction) { event->setDropAction(Qt::CopyAction); event->accept(); } else if (event->possibleActions() & Qt::MoveAction) { event->setDropAction(Qt::MoveAction); event->accept(); } else { event->ignore(); } } else { event->ignore(); } } void WorksheetTextItem::dragMoveEvent(QGraphicsSceneDragDropEvent* event) { if (isEditable() && event->mimeData()->hasFormat("text/plain")) setLocalCursorPosition(mapFromScene(event->scenePos())); } void WorksheetTextItem::dropEvent(QGraphicsSceneDragDropEvent* event) { if (isEditable()) { - textCursor().insertText(event->mimeData()->text()); + if (richTextEnabled() && event->mimeData()->hasFormat("text/html")) + textCursor().insertHtml(event->mimeData()->html()); + else + textCursor().insertText(event->mimeData()->text()); event->accept(); } } void WorksheetTextItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { KMenu *menu = worksheet()->createContextMenu(); populateMenu(menu, event->pos()); menu->popup(event->screenPos()); } void WorksheetTextItem::insertTab() { QTextLayout *layout = textCursor().block().layout(); QTextCursor cursor = textCursor(); if (!layout) { cursor.insertText(" "); } else { cursor.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor); int i = cursor.selectionEnd() - cursor.selectionStart(); i = ((i+4) & (~3)) - i; cursor.setPosition(cursor.selectionEnd()); cursor.insertText(QString(' ').repeated(i)); } // without this line subsequent cursor movement up or down uses the old // position setTextCursor(cursor); emit cursorPositionChanged(textCursor()); } double WorksheetTextItem::width() { return document()->size().width(); } double WorksheetTextItem::height() { return document()->size().height(); } Worksheet* WorksheetTextItem::worksheet() { return qobject_cast(scene()); } #include "worksheettextitem.moc" diff --git a/src/worksheettextitem.h b/src/worksheettextitem.h index e9a626c5..5c06e6ec 100644 --- a/src/worksheettextitem.h +++ b/src/worksheettextitem.h @@ -1,121 +1,126 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2012 Martin Kuettler */ #ifndef WORKSHEET_TEXT_ITEM_H #define WORKSHEET_TEXT_ITEM_H #include #include +#include class Worksheet; namespace Cantor { class Session; } class WorksheetTextItem : public QGraphicsTextItem { Q_OBJECT public: WorksheetTextItem(QGraphicsObject* parent, Qt::TextInteractionFlags ti = Qt::NoTextInteraction); ~WorksheetTextItem(); void setCursorPosition(const QPointF& pos); QPointF cursorPosition() const; QTextCursor cursorForPosition(const QPointF& pos) const; enum {TopLeft, BottomRight, TopCoord, BottomCoord}; enum {Type = UserType + 100}; int type() const; void setFocusAt(int pos = TopLeft, qreal xCoord = 0); void enableCompletion(bool b); void activateCompletion(bool b); void enableDragging(bool b); + void enableRichText(bool b); virtual void populateMenu(KMenu *menu, const QPointF& pos); QString resolveImages(const QTextCursor& cursor); bool isEditable(); + bool richTextEnabled(); double width(); double height(); Worksheet* worksheet(); signals: void moveToPrevious(int pos, qreal xCoord); void moveToNext(int pos, qreal xCoord); void cursorPositionChanged(QTextCursor); void receivedFocus(WorksheetTextItem*); void tabPressed(); void backtabPressed(); void applyCompletion(); void doubleClick(); void execute(); void appendCommandEntry(); void deleteEntry(); void sizeChanged(); void menuCreated(KMenu*, const QPointF&); void drag(const QPointF&, const QPointF&); public slots: void insertTab(); void cut(); void copy(); void paste(); protected: void keyPressEvent(QKeyEvent *event); void focusInEvent(QFocusEvent *event); void focusOutEvent(QFocusEvent *event); void mousePressEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); void mouseMoveEvent(QGraphicsSceneMouseEvent* event); void contextMenuEvent(QGraphicsSceneContextMenuEvent *event); void dragEnterEvent(QGraphicsSceneDragDropEvent* event); //void dragLeaveEvent(QGraphicsSceneDragDropEvent* event); void dragMoveEvent(QGraphicsSceneDragDropEvent* event); void dropEvent(QGraphicsSceneDragDropEvent* event); bool sceneEvent(QEvent *event); private slots: void setHeight(); void testHeight(); private: void setLocalCursorPosition(const QPointF& pos); QPointF localCursorPosition() const; + QKeyEvent* eventForStandardAction(KStandardAction::StandardAction actionID); Cantor::Session* session(); private: bool m_completionEnabled; bool m_completionActive; bool m_draggingEnabled; + bool m_richTextEnabled; qreal m_height; }; #endif // WORKSHEET_TEXT_ITEM_H