diff --git a/toonz/sources/include/toonzqt/schematicnode.h b/toonz/sources/include/toonzqt/schematicnode.h index d276279..e456440 100644 --- a/toonz/sources/include/toonzqt/schematicnode.h +++ b/toonz/sources/include/toonzqt/schematicnode.h @@ -19,6 +19,15 @@ class SchematicName final : public QGraphicsTextItem { Q_OBJECT double m_width; double m_height; + bool m_refocus; + QString m_defName; + QString m_curName; + QMenu *popup; + QAction *actionCut; + QAction *actionCopy; + QAction *actionPaste; + QAction *actionDelete; + QAction *actionSelectAll; public: SchematicName(QGraphicsItem *parent, double width, double height); @@ -26,7 +35,8 @@ public: bool eventFilter(QObject *object, QEvent *event) override; - void setName(const QString &name); + void setName(const QString &name); // Act as default name + void acceptName(const QString &name); protected: void focusInEvent(QFocusEvent *fe) override; @@ -40,6 +50,12 @@ signals: protected slots: void onContentsChanged(); + void onPopupHide(); + void onCut(); + void onCopy(); + void onPaste(); + void onDelete(); + void onSelectAll(); }; //======================================================== diff --git a/toonz/sources/toonzqt/schematicnode.cpp b/toonz/sources/toonzqt/schematicnode.cpp index 8283cf5..415ce13 100644 --- a/toonz/sources/toonzqt/schematicnode.cpp +++ b/toonz/sources/toonzqt/schematicnode.cpp @@ -15,10 +15,17 @@ #include #include #include +#include #include "tundo.h" #include "toonzqt/menubarcommand.h" #include "toonzqt/gutil.h" +#define ACCEL_KEY(k) \ + (!QCoreApplication::testAttribute(Qt::AA_DontShowShortcutsInContextMenus) \ + ? QLatin1Char('\t') + \ + QKeySequence(k).toString(QKeySequence::NativeText) \ + : QString()) + //======================================================== // // StageSchematicName @@ -26,22 +33,65 @@ //======================================================== SchematicName::SchematicName(QGraphicsItem *parent, double width, double height) - : QGraphicsTextItem("", parent), m_width(width), m_height(height) { + : QGraphicsTextItem("", parent) + , m_width(width) + , m_height(height) + , m_defName("") + , m_curName("") + , m_refocus(false) { setFlag(QGraphicsItem::ItemIsSelectable, true); setFlag(QGraphicsItem::ItemIsFocusable, true); setTextInteractionFlags(Qt::TextEditorInteraction); + popup = new QMenu(); + popup->setObjectName(QLatin1String("qt_edit_menu")); + + actionCut = popup->addAction(tr("Cu&t") + ACCEL_KEY(QKeySequence::Cut), + this, SLOT(onCut())); + actionCut->setObjectName(QStringLiteral("edit-cut")); + + actionCopy = popup->addAction(tr("&Copy") + ACCEL_KEY(QKeySequence::Copy), + this, SLOT(onCopy())); + actionCopy->setObjectName(QStringLiteral("edit-copy")); + + actionPaste = popup->addAction( + tr("&Paste") + ACCEL_KEY(QKeySequence::Paste), this, SLOT(onPaste())); + actionPaste->setObjectName(QStringLiteral("edit-paste")); + + actionDelete = popup->addAction( + tr("&Delete") + ACCEL_KEY(QKeySequence::Delete), this, SLOT(onDelete())); + actionDelete->setObjectName(QStringLiteral("edit-delete")); + + popup->addSeparator(); + + actionSelectAll = + popup->addAction(tr("Select &All") + ACCEL_KEY(QKeySequence::SelectAll), + this, SLOT(onSelectAll())); + actionSelectAll->setObjectName(QStringLiteral("select-all")); + connect(document(), SIGNAL(contentsChanged()), this, SLOT(onContentsChanged())); + connect(popup, SIGNAL(aboutToHide()), this, SLOT(onPopupHide())); } //-------------------------------------------------------- -SchematicName::~SchematicName() {} +SchematicName::~SchematicName() { delete popup; } //-------------------------------------------------------- -void SchematicName::setName(const QString &name) { setPlainText(name); } +void SchematicName::setName(const QString &name) { + m_defName = name; + setPlainText(name); +} + +//-------------------------------------------------------- + +void SchematicName::acceptName(const QString &name) { + m_curName = name; + m_curName.remove(QRegExp("[\\n\\r]")); // remove all newlines + setPlainText(m_curName); +} //-------------------------------------------------------- @@ -51,7 +101,8 @@ void SchematicName::onContentsChanged() { int position = cursor.position(); if (position > 0 && text.at(position - 1) == '\n') { text.remove("\n"); - setPlainText(text); + if (text.isEmpty()) text = m_defName; + acceptName(text); ; emit focusOut(); } @@ -61,7 +112,10 @@ void SchematicName::onContentsChanged() { void SchematicName::focusOutEvent(QFocusEvent *fe) { qApp->removeEventFilter(this); - if (fe->reason() == Qt::MouseFocusReason) emit focusOut(); + if (fe->reason() == Qt::MouseFocusReason) { + acceptName(toPlainText()); + emit focusOut(); + } } //-------------------------------------------------------- @@ -75,6 +129,9 @@ void SchematicName::keyPressEvent(QKeyEvent *ke) { else cursor.setPosition(currentPos + 1); setTextCursor(cursor); + } else if (ke->key() == Qt::Key_Escape) { + setPlainText(m_curName); + emit focusOut(); } else QGraphicsTextItem::keyPressEvent(ke); } @@ -97,15 +154,121 @@ bool SchematicName::eventFilter(QObject *object, QEvent *event) { void SchematicName::focusInEvent(QFocusEvent *fe) { QGraphicsTextItem::focusInEvent(fe); qApp->installEventFilter(this); - QTextDocument *doc = document(); - QTextCursor cursor(doc->begin()); - cursor.select(QTextCursor::Document); + if (!m_refocus) { + QTextDocument *doc = document(); + QTextCursor cursor(doc->begin()); + cursor.select(QTextCursor::Document); + setTextCursor(cursor); + m_curName = toPlainText(); + } +} + +//-------------------------------------------------------- + +void SchematicName::contextMenuEvent(QGraphicsSceneContextMenuEvent *cme) { + QClipboard *clipboard = QApplication::clipboard(); + QTextCursor cursor = textCursor(); + + actionCut->setEnabled(cursor.hasSelection()); + actionCopy->setEnabled(cursor.hasSelection()); + actionPaste->setEnabled(!clipboard->text().isEmpty()); + actionDelete->setEnabled(cursor.hasSelection()); + actionSelectAll->setEnabled(cursor.selectedText() != toPlainText()); + + popup->popup(cme->screenPos()); +} + +//-------------------------------------------------------- + +void SchematicName::onPopupHide() { + m_refocus = true; + setFocus(); + m_refocus = false; +} + +//-------------------------------------------------------- + +void SchematicName::onCut() { + QClipboard *clipboard = QApplication::clipboard(); + QTextCursor cursor = textCursor(); + QString plainText = toPlainText(); + + if (cursor.hasSelection()) { + int p = cursor.selectionStart(); + int n = cursor.selectionEnd() - p; + QString selection = plainText.mid(p, n); + clipboard->setText(selection); + plainText.remove(p, n); + acceptName(plainText); + cursor.setPosition(p); + setTextCursor(cursor); + } +} + +//-------------------------------------------------------- + +void SchematicName::onCopy() { + QClipboard *clipboard = QApplication::clipboard(); + QTextCursor cursor = textCursor(); + QString plainText = toPlainText(); + + if (cursor.hasSelection()) { + int p = cursor.selectionStart(); + int n = cursor.selectionEnd() - p; + clipboard->setText(plainText.mid(p, n)); + } else { + clipboard->setText(plainText); + } +} + +//-------------------------------------------------------- + +void SchematicName::onPaste() { + QClipboard *clipboard = QApplication::clipboard(); + QTextCursor cursor = textCursor(); + QString plainText = toPlainText(); + QString clipboardText = clipboard->text(); + clipboardText.remove(QRegExp("[\\n\\r]")); // remove all newlines + + int n, p = cursor.position(); + if (cursor.hasSelection()) { + p = cursor.selectionStart(); + n = cursor.selectionEnd() - p; + plainText.remove(p, n); + plainText.insert(p, clipboardText); + } else { + plainText.insert(p, clipboardText); + } + acceptName(plainText); + cursor.setPosition(p + clipboardText.length()); setTextCursor(cursor); } //-------------------------------------------------------- -void SchematicName::contextMenuEvent(QGraphicsSceneContextMenuEvent *cme) {} +void SchematicName::onDelete() { + QClipboard *clipboard = QApplication::clipboard(); + QTextCursor cursor = textCursor(); + QString plainText = toPlainText(); + + if (cursor.hasSelection()) { + int p = cursor.selectionStart(); + int n = cursor.selectionEnd() - p; + plainText.remove(p, n); + acceptName(plainText); + cursor.setPosition(p); + setTextCursor(cursor); + } +} + +//-------------------------------------------------------- + +void SchematicName::onSelectAll() { + QTextDocument *doc = document(); + QTextCursor cursor(doc->begin()); + cursor.select(QTextCursor::Document); + setTextCursor(cursor); +} //======================================================== //