diff --git a/src/widgets/dcrumbedit.cpp b/src/widgets/dcrumbedit.cpp index fdd8ff4bd..c4b50d765 100644 --- a/src/widgets/dcrumbedit.cpp +++ b/src/widgets/dcrumbedit.cpp @@ -26,6 +26,10 @@ #include #include #include +#include +#include +#include +#include #include DWIDGET_BEGIN_NAMESPACE @@ -190,6 +194,57 @@ class DCrumbEditPrivate : public DCORE_NAMESPACE::DObjectPrivate return true; } + QByteArray crumbMapToData(const QList &list) const + { + QJsonArray array; + + for (const DCrumbTextFormat &f : list) { + if (!f.isValid() || f.isEmpty()) + continue; + + QJsonObject object; + object["text"] = f.text(); + + if (f.tagColor().isValid()) + object["tag color"] = f.tagColor().name(); + + array.append(QJsonValue(object)); + } + + QJsonDocument document; + document.setArray(array); + + return document.toJson(QJsonDocument::Compact); + } + + QList crumbListFromData(const QByteArray &format) const + { + const QJsonDocument &document = QJsonDocument::fromJson(format); + const QJsonArray &array = document.array(); + + QList list; + + D_QC(DCrumbEdit); + + for (const QJsonValue &v : array) { + const QJsonObject &object = v.toObject(); + + if (object.isEmpty()) + continue; + + DCrumbTextFormat format = q->makeTextFormat(); + + format.setText(object["text"].toString()); + + if (object.contains("tag color")) + format.setTagColor(QColor(object["tag color"].toString())); + + list << format; + } + + return list; + } + void _q_onDocumentLayoutChanged() { D_Q(DCrumbEdit); @@ -228,6 +283,7 @@ class DCrumbEditPrivate : public DCORE_NAMESPACE::DObjectPrivate int last_pos = 0; cursor.setPosition(0); + formatList.clear(); while (!cursor.atEnd()) { cursor.setPosition(last_pos + 1); @@ -244,6 +300,7 @@ class DCrumbEditPrivate : public DCORE_NAMESPACE::DObjectPrivate if (!text.isEmpty()) { crumbList << text; + formatList << text; if (!formats.contains(text)) { formats[text] = format; @@ -271,6 +328,7 @@ class DCrumbEditPrivate : public DCORE_NAMESPACE::DObjectPrivate CrumbObjectInterface *object; int objectType; bool crumbReadOnly = false; + QStringList formatList; QMap formats; }; @@ -346,9 +404,7 @@ bool DCrumbEdit::insertCrumb(const DCrumbTextFormat &format, int pos) QTextCursor cursor = textCursor(); - if (pos < 0) - cursor.movePosition(QTextCursor::End); - else + if (pos >= 0) cursor.setPosition(pos); cursor.insertText(QString(QChar::ObjectReplacementCharacter), format); @@ -356,21 +412,40 @@ bool DCrumbEdit::insertCrumb(const DCrumbTextFormat &format, int pos) return true; } -void DCrumbEdit::insertCrumb(const QString &text, int pos) +bool DCrumbEdit::appendCrumb(const DCrumbTextFormat &format) +{ + if (format.text().isEmpty()) + return false; + + D_DC(DCrumbEdit); + + if (!d->canAddCrumb(format.text())) + return false; + + QTextCursor cursor = textCursor(); + + cursor.movePosition(QTextCursor::End); + cursor.insertText(QString(QChar::ObjectReplacementCharacter), format); + + return true; +} + +bool DCrumbEdit::insertCrumb(const QString &text, int pos) { DCrumbTextFormat format = makeTextFormat(); format.setText(text); - insertCrumb(format, pos); + + return insertCrumb(format, pos); } -void DCrumbEdit::appendCrumb(const QString &text) +bool DCrumbEdit::appendCrumb(const QString &text) { - QTextCursor crusor = textCursor(); + DCrumbTextFormat format = makeTextFormat(); + + format.setText(text); - crusor.movePosition(QTextCursor::End); - setTextCursor(crusor); - insertCrumb(text); + return appendCrumb(text); } bool DCrumbEdit::containCrumb(const QString &text) const @@ -384,7 +459,7 @@ QStringList DCrumbEdit::crumbList() const { D_DC(DCrumbEdit); - return d->formats.keys(); + return d->formatList; } DCrumbTextFormat DCrumbEdit::crumbTextFormat(const QString &text) const @@ -531,6 +606,103 @@ void DCrumbEdit::focusOutEvent(QFocusEvent *event) QTextEdit::focusOutEvent(event); } +QMimeData *DCrumbEdit::createMimeDataFromSelection() const +{ + D_DC(DCrumbEdit); + + QMimeData *mime = new QMimeData(); + const QTextCursor &cursor = textCursor(); + QStringList::const_iterator current_format = d->formatList.constBegin(); + + const QString &plain_text = toPlainText(); + const QString &selected_text = cursor.selectedText(); + int pos = -1; + QString text; + QList format_list; + + for (const QChar &ch : plain_text) { + ++pos; + + if (pos >= cursor.selectionEnd()) + break; + + if (ch == QChar::ObjectReplacementCharacter) { + if (pos < cursor.selectionStart()) { + ++current_format; + continue; + } + + const DCrumbTextFormat &f = d->formats.value(*current_format); + + ++current_format; + + if (f.text().isEmpty()) + continue; + + if (!text.isEmpty()) + text.append(" ").append(f.text()); + else + text.append(f.text()); + + format_list << f; + } else if (pos < cursor.selectionStart()) { + text.append(ch); + } + } + + mime->setText(text); + mime->setData("deepin/dtkwidget-DCrumbTextFormat-data", selected_text.toUtf8()); + mime->setData("deepin/dtkwidget-DCrumbTextFormat-list", d->crumbMapToData(format_list)); + + return mime; +} + +bool DCrumbEdit::canInsertFromMimeData(const QMimeData *source) const +{ + if (source->hasFormat("deepin/dtkwidget-DCrumbTextFormat-data")) + return true; + + return QTextEdit::canInsertFromMimeData(source); +} + +void DCrumbEdit::insertFromMimeData(const QMimeData *source) +{ + if (!source->hasFormat("deepin/dtkwidget-DCrumbTextFormat-data")) + QTextEdit::insertFromMimeData(source); + + const QString &plain_text = QString::fromUtf8(source->data("deepin/dtkwidget-DCrumbTextFormat-data")); + + if (plain_text.isEmpty()) + return; + + D_DC(DCrumbEdit); + + const QList &list = d->crumbListFromData(source->data("deepin/dtkwidget-DCrumbTextFormat-list")); + QList::const_iterator current_format = list.constBegin(); + QString text; + + textCursor().beginEditBlock(); + + for (const QChar &ch : plain_text) { + if (ch == QChar::ObjectReplacementCharacter) { + if (!text.isEmpty()) { + textCursor().insertText(text); + text.clear(); + } + + insertCrumb(*current_format); + ++current_format; + } else { + text.append(ch); + } + } + + if (!text.isEmpty()) + textCursor().insertText(text); + + textCursor().endEditBlock(); +} + DWIDGET_END_NAMESPACE #include "moc_dcrumbedit.cpp" diff --git a/src/widgets/dcrumbedit.h b/src/widgets/dcrumbedit.h index 965c76534..82c52f81a 100644 --- a/src/widgets/dcrumbedit.h +++ b/src/widgets/dcrumbedit.h @@ -81,8 +81,9 @@ class DCrumbEdit : public QTextEdit, public DCORE_NAMESPACE::DObject explicit DCrumbEdit(QWidget *parent = 0); bool insertCrumb(const DCrumbTextFormat &format, int pos = -1); - void insertCrumb(const QString &text, int pos = -1); - void appendCrumb(const QString &text); + bool insertCrumb(const QString &text, int pos = -1); + bool appendCrumb(const DCrumbTextFormat &format); + bool appendCrumb(const QString &text); bool containCrumb(const QString &text) const; QStringList crumbList() const; @@ -107,6 +108,10 @@ public Q_SLOTS: void mouseDoubleClickEvent(QMouseEvent *event) override; void focusOutEvent(QFocusEvent *event) override; + QMimeData *createMimeDataFromSelection() const override; + bool canInsertFromMimeData(const QMimeData *source) const override; + void insertFromMimeData(const QMimeData *source) override; + private: using QTextEdit::setDocument; using QTextEdit::document;