void TextBase::endHexState(EditData& ed) { TextEditData* ted = static_cast<TextEditData*>(ed.getData(this)); TextCursor* _cursor = &ted->cursor; if (hexState >= 0) { if (hexState > 0) { int c2 = _cursor->column(); int c1 = c2 - (hexState + 1); TextBlock& t = _layout[_cursor->row()]; QString ss = t.remove(c1, hexState + 1); bool ok; int code = ss.mid(1).toInt(&ok, 16); _cursor->setColumn(c1); _cursor->clearSelection(); if (ok) editInsertText(_cursor, QString(code)); else qDebug("cannot convert hex string <%s>, state %d (%d-%d)", qPrintable(ss.mid(1)), hexState, c1, c2); } hexState = -1; } }
void TextBase::movePosition(EditData& ed, QTextCursor::MoveOperation op) { TextEditData* ted = static_cast<TextEditData*>(ed.getData(this)); TextCursor* _cursor = &ted->cursor; _cursor->movePosition(op); score()->addRefresh(canvasBoundingRect()); score()->update(); }
void TextBase::inputTransition(EditData& ed, QInputMethodEvent* ie) { TextEditData* ted = static_cast<TextEditData*>(ed.getData(this)); TextCursor* _cursor = &ted->cursor; // remove preedit string int n = preEdit.size(); while (n--) { if (_cursor->movePosition(QTextCursor::Left)) { TextBlock& l = _cursor->curLine(); l.remove(_cursor->column()); _cursor->text()->triggerLayout(); _cursor->text()->setTextInvalid(); } } qDebug("<%s><%s> len %d start %d, preEdit size %d", qPrintable(ie->commitString()), qPrintable(ie->preeditString()), ie->replacementLength(), ie->replacementStart(), preEdit.size()); if (!ie->commitString().isEmpty()) { _cursor->format()->setPreedit(false); score()->startCmd(); insertText(ed, ie->commitString()); score()->endCmd(); preEdit.clear(); } else { preEdit = ie->preeditString(); if (!preEdit.isEmpty()) { #if 0 for (auto a : ie->attributes()) { switch(a.type) { case QInputMethodEvent::TextFormat: { qDebug(" attribute TextFormat: %d-%d", a.start, a.length); QTextFormat tf = a.value.value<QTextFormat>(); } break; case QInputMethodEvent::Cursor: qDebug(" attribute Cursor at %d", a.start); break; default: qDebug(" attribute %d", a.type); } } #endif _cursor->format()->setPreedit(true); _cursor->updateCursorFormat(); editInsertText(_cursor, preEdit); setTextInvalid(); layout1(); score()->update(); } } ie->accept(); }
void TextBase::endEdit(EditData& ed) { TextEditData* ted = static_cast<TextEditData*>(ed.getData(this)); score()->undoStack()->remove(ted->startUndoIdx); // remove all undo/redo records // replace all undo/redo records collected during text editing with // one property change QString actualText = xmlText(); if (ted->oldXmlText.isEmpty()) { UndoStack* us = score()->undoStack(); UndoCommand* ucmd = us->last(); if (ucmd) { const QList<UndoCommand*>& cl = ucmd->commands(); const UndoCommand* cmd = cl.back(); if (strncmp(cmd->name(), "Add:", 4) == 0) { const AddElement* ae = static_cast<const AddElement*>(cmd); if (ae->getElement() == this) { if (actualText.isEmpty()) { // we just created this empty text, rollback that operation us->rollback(); score()->update(); ed.element = 0; } else { setXmlText(ted->oldXmlText); // reset text to value before editing us->reopen(); // combine undo records of text creation with text editing undoChangeProperty(Pid::TEXT, actualText); layout1(); score()->endCmd(); } return; } } } } if (actualText.isEmpty()) { qDebug("actual text is empty"); score()->startCmd(); score()->undoRemoveElement(this); ed.element = 0; score()->endCmd(); return; } setXmlText(ted->oldXmlText); // reset text to value before editing score()->startCmd(); undoChangeProperty(Pid::TEXT, actualText); // change property to set text to actual value again // this also changes text of linked elements layout1(); triggerLayout(); // force relayout even if text did not change score()->endCmd(); static const qreal w = 2.0; score()->addRefresh(canvasBoundingRect().adjusted(-w, -w, w, w)); }
void TextBase::insertSym(EditData& ed, SymId id) { TextEditData* ted = static_cast<TextEditData*>(ed.getData(this)); TextCursor* _cursor = &ted->cursor; deleteSelectedText(ed); QString s = score()->scoreFont()->toString(id); CharFormat fmt = *_cursor->format(); // save format // uint code = ScoreFont::fallbackFont()->sym(id).code(); _cursor->format()->setFontFamily("ScoreText"); _cursor->format()->setBold(false); _cursor->format()->setItalic(false); score()->undo(new InsertText(_cursor, s), &ed); _cursor->setFormat(fmt); // restore format }
void Image::endEditDrag(EditData& ed) { ImageEditData* ied = static_cast<ImageEditData*>(ed.getData(this)); if (_size != ied->size) score()->undoPropertyChanged(this, Pid::SIZE, ied->size); }
bool TextBase::edit(EditData& ed) { TextEditData* ted = static_cast<TextEditData*>(ed.getData(this)); TextCursor* _cursor = &ted->cursor; // do nothing on Shift, it messes up IME on Windows. See #64046 if (ed.key == Qt::Key_Shift) return false; QString s = ed.s; bool ctrlPressed = ed.modifiers & Qt::ControlModifier; bool shiftPressed = ed.modifiers & Qt::ShiftModifier; QTextCursor::MoveMode mm = shiftPressed ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor; bool wasHex = false; if (hexState >= 0) { if (ed.modifiers == (Qt::ControlModifier | Qt::ShiftModifier | Qt::KeypadModifier)) { switch (ed.key) { case Qt::Key_0: case Qt::Key_1: case Qt::Key_2: case Qt::Key_3: case Qt::Key_4: case Qt::Key_5: case Qt::Key_6: case Qt::Key_7: case Qt::Key_8: case Qt::Key_9: s = QChar::fromLatin1(ed.key); ++hexState; wasHex = true; break; default: break; } } else if (ed.modifiers == (Qt::ControlModifier | Qt::ShiftModifier)) { switch (ed.key) { case Qt::Key_A: case Qt::Key_B: case Qt::Key_C: case Qt::Key_D: case Qt::Key_E: case Qt::Key_F: s = QChar::fromLatin1(ed.key); ++hexState; wasHex = true; break; default: break; } } } if (!wasHex) { // printf("======%x\n", s.isEmpty() ? -1 : s[0].unicode()); switch (ed.key) { case Qt::Key_Z: // happens when the undo stack is empty if (ed.modifiers == Qt::ControlModifier) return true; break; case Qt::Key_Enter: case Qt::Key_Return: deleteSelectedText(ed); score()->undo(new SplitText(_cursor), &ed); return true; case Qt::Key_Delete: if (!deleteSelectedText(ed)) score()->undo(new RemoveText(_cursor, QString(_cursor->currentCharacter())), &ed); return true; case Qt::Key_Backspace: if (!deleteSelectedText(ed)) { if (_cursor->column() == 0 && _cursor->row() != 0) score()->undo(new JoinText(_cursor), &ed); else { if (!_cursor->movePosition(QTextCursor::Left)) return false; score()->undo(new RemoveText(_cursor, QString(_cursor->currentCharacter())), &ed); } } return true; case Qt::Key_Left: if (!_cursor->movePosition(ctrlPressed ? QTextCursor::WordLeft : QTextCursor::Left, mm) && type() == ElementType::LYRICS) return false; s.clear(); break; case Qt::Key_Right: if (!_cursor->movePosition(ctrlPressed ? QTextCursor::NextWord : QTextCursor::Right, mm) && type() == ElementType::LYRICS) return false; s.clear(); break; case Qt::Key_Up: #if defined(Q_OS_MAC) if (!_cursor->movePosition(QTextCursor::Up, mm)) _cursor->movePosition(QTextCursor::StartOfLine, mm); #else _cursor->movePosition(QTextCursor::Up, mm); #endif s.clear(); break; case Qt::Key_Down: #if defined(Q_OS_MAC) if (!_cursor->movePosition(QTextCursor::Down, mm)) _cursor->movePosition(QTextCursor::EndOfLine, mm); #else _cursor->movePosition(QTextCursor::Down, mm); #endif s.clear(); break; case Qt::Key_Home: if (ctrlPressed) _cursor->movePosition(QTextCursor::Start, mm); else _cursor->movePosition(QTextCursor::StartOfLine, mm); s.clear(); break; case Qt::Key_End: if (ctrlPressed) _cursor->movePosition(QTextCursor::End, mm); else _cursor->movePosition(QTextCursor::EndOfLine, mm); s.clear(); break; case Qt::Key_Tab: s = " "; ed.modifiers = 0; break; case Qt::Key_Space: if (ed.modifiers & CONTROL_MODIFIER) s = QString(QChar(0xa0)); // non-breaking space else s = " "; ed.modifiers = 0; break; case Qt::Key_Minus: if (ed.modifiers == 0) s = "-"; break; case Qt::Key_Underscore: if (ed.modifiers == 0) s = "_"; break; case Qt::Key_A: if (ctrlPressed) { selectAll(_cursor); s.clear(); } break; default: break; } if (ctrlPressed && shiftPressed) { switch (ed.key) { case Qt::Key_U: if (hexState == -1) { hexState = 0; s = "u"; } break; case Qt::Key_B: insertSym(ed, SymId::accidentalFlat); return true; case Qt::Key_NumberSign: insertSym(ed, SymId::accidentalSharp); return true; case Qt::Key_H: insertSym(ed, SymId::accidentalNatural); return true; case Qt::Key_Space: insertSym(ed, SymId::space); return true; case Qt::Key_F: insertSym(ed, SymId::dynamicForte); return true; case Qt::Key_M: insertSym(ed, SymId::dynamicMezzo); return true; case Qt::Key_N: insertSym(ed, SymId::dynamicNiente); return true; case Qt::Key_P: insertSym(ed, SymId::dynamicPiano); return true; case Qt::Key_S: insertSym(ed, SymId::dynamicSforzando); return true; case Qt::Key_R: insertSym(ed, SymId::dynamicRinforzando); return true; case Qt::Key_Z: // Ctrl+Z is normally "undo" // but this code gets hit even if you are also holding Shift // so Shift+Ctrl+Z works insertSym(ed, SymId::dynamicZ); return true; } } } if (!s.isEmpty()) { deleteSelectedText(ed); score()->undo(new InsertText(_cursor, s), &ed); } return true; }
void TextBase::insertText(EditData& ed, const QString& s) { TextEditData* ted = static_cast<TextEditData*>(ed.getData(this)); TextCursor* _cursor = &ted->cursor; score()->undo(new InsertText(_cursor, s), &ed); }