[graphics/drawy/gsoc2026] src: feat: add mime handler for html

Abdelhadi Wael <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit 372a6459547f6c842272b19187845527ca74a497 by Abdelhadi Wael.
Committed on 24/07/2026 at 09:34.
Pushed by mlaurent into branch 'gsoc2026'.

feat: add mime handler for html

M  +30   -6    src/gui/item/text.cpp
M  +1    -0    src/gui/item/text.hpp
M  +1    -1    src/gui/serializer/textdeserializer.cpp
M  +12   -10   src/widgets/mime/textmimehandler.cpp

https://invent.kde.org/graphics/drawy/-/commit/372a6459547f6c842272b19187845527ca74a497

diff --git a/src/gui/item/text.cpp b/src/gui/item/text.cpp
index 6f26f9a7..bd2ddc58 100644
--- a/src/gui/item/text.cpp
+++ b/src/gui/item/text.cpp
@@ -170,12 +170,15 @@ void TextItem::scaleTextFragments(const qreal scaleY)
         for (auto it = block.begin(); !it.atEnd(); ++it) {
             const QTextFragment fragment = it.fragment();
             QTextCharFormat fmt = fragment.charFormat();
-            const qreal size = fmt.fontPointSize();
+            const qreal size = getFontSize(fmt);
 
             fmt.setFontPointSize(std::max(1.0, size * scaleY));
+            fmt.setProperty(QTextFormat::FontPixelSize, QVariant());
+            fmt.setProperty(QTextFormat::FontSizeAdjustment, QVariant());
+
             m_cursor.setPosition(fragment.position());
             m_cursor.setPosition(fragment.position() + fragment.length(), QTextCursor::KeepAnchor);
-            m_cursor.setCharFormat(fmt);
+            m_cursor.mergeCharFormat(fmt);
         }
         block = block.next();
     }
@@ -273,6 +276,18 @@ void TextItem::updateBoundingBox()
     setDirty(true);
 }
 
+qreal TextItem::getFontSize(const QTextCharFormat &fmt)
+{
+    qreal size = fmt.fontPointSize();
+    if (size <= 0) {
+        size = fmt.font().pointSizeF();
+    }
+    if (size <= 0) {
+        size = fmt.font().pixelSize() * 72.0 / 96.0;
+    }
+    return std::max(size, 1.0);
+}
+
 QFont TextItem::getFont() const
 {
     QFont font;
@@ -394,12 +409,15 @@ Property TextItem::property(const Property::Type propertyType) const
 
     switch (propertyType) {
     case Property::Type::StrokeColor: {
+        if (!cursor.charFormat().hasProperty(QTextFormat::ForegroundBrush)) {
+            return Item::property(Property::Type::StrokeColor);
+        }
         const QColor color = cursor.charFormat().foreground().color();
         return Property{color, Property::Type::StrokeColor};
     }
     case Property::Type::FontSize: {
-        const qreal size = cursor.charFormat().font().pointSize();
-        return Property{static_cast<int>(size), Property::Type::FontSize};
+        const qreal size = getFontSize(cursor.charFormat());
+        return Property{qRound(size), Property::Type::FontSize};
     }
     case Property::Type::FontFamily: {
         const QString font = cursor.charFormat().font().family();
@@ -445,6 +463,7 @@ bool TextItem::needsPropertyUpdate(const Property &property) const
 
     cursor.setPosition(start + 1);
     const QTextCharFormat firstFormat = cursor.charFormat();
+    const qreal firstSize = getFontSize(firstFormat);
 
     QTextBlock block = m_document.findBlock(start);
     while (block.isValid() && block.position() < end) {
@@ -465,11 +484,12 @@ bool TextItem::needsPropertyUpdate(const Property &property) const
                     return true;
                 }
                 break;
-            case Property::Type::FontSize:
-                if (fmt.font().pointSize() != firstFormat.font().pointSize()) {
+            case Property::Type::FontSize: {
+                if (qRound(getFontSize(fmt)) != qRound(firstSize)) {
                     return true;
                 }
                 break;
+            }
             case Property::Type::FontFamily:
                 if (fmt.font().family() != firstFormat.font().family()) {
                     return true;
@@ -493,6 +513,10 @@ void TextItem::setProperty(const Property::Type propertyType, const Property new
         break;
     case Property::Type::FontSize:
         fmt.setFontPointSize(newObj.value<int>());
+
+        // these properties take priority over point size preventing size change
+        fmt.setProperty(QTextFormat::FontPixelSize, QVariant());
+        fmt.setProperty(QTextFormat::FontSizeAdjustment, QVariant());
         break;
     case Property::Type::FontFamily:
         fmt.setFontFamilies(QStringList{newObj.value<QString>()});
diff --git a/src/gui/item/text.hpp b/src/gui/item/text.hpp
index 4240e6ef..93922d94 100644
--- a/src/gui/item/text.hpp
+++ b/src/gui/item/text.hpp
@@ -74,6 +74,7 @@ protected:
     void drawItem(QPainter &painter, const QPointF &offset) const override;
 
 private:
+    [[nodiscard]] LIBDRAWYGUI_NO_EXPORT static qreal getFontSize(const QTextCharFormat &fmt);
     [[nodiscard]] LIBDRAWYGUI_NO_EXPORT QFont getFont() const;
     [[nodiscard]] LIBDRAWYGUI_NO_EXPORT QTextOption getTextOptions() const;
 
diff --git a/src/gui/serializer/textdeserializer.cpp b/src/gui/serializer/textdeserializer.cpp
index ed5c8966..78c717de 100644
--- a/src/gui/serializer/textdeserializer.cpp
+++ b/src/gui/serializer/textdeserializer.cpp
@@ -26,7 +26,7 @@ void TextDeserializer::deserialize(const QJsonObject &obj)
     }
 
     if (obj.contains(u"html"_s)) {
-        textItem->cursor().insertHtml(value(obj, u"html"_s).toString());
+        textItem->setHtml(value(obj, u"html"_s).toString());
     } else {
         textItem->cursor().insertText(text);
     }
diff --git a/src/widgets/mime/textmimehandler.cpp b/src/widgets/mime/textmimehandler.cpp
index b664f5c4..3b826b7e 100644
--- a/src/widgets/mime/textmimehandler.cpp
+++ b/src/widgets/mime/textmimehandler.cpp
@@ -10,20 +10,21 @@
 
 QList<std::shared_ptr<Item>> TextMimeHandler::tryReadData(const QMimeData &mimeData)
 {
-    if (!mimeData.hasText()) {
-        return {};
+    if (mimeData.hasHtml() && !mimeData.html().trimmed().isEmpty()) {
+        const auto text = std::make_shared<TextItem>();
+        text->createTextBox({0, 0});
+        text->cursor().insertHtml(mimeData.html());
+        return {text};
     }
 
-    if (mimeData.text().trimmed().isEmpty()) {
-        return {};
+    if (mimeData.hasText() && !mimeData.text().trimmed().isEmpty()) {
+        const auto text = std::make_shared<TextItem>();
+        text->createTextBox({0, 0});
+        text->cursor().insertText(mimeData.text());
+        return {text};
     }
 
-    const std::shared_ptr<TextItem> text = std::make_shared<TextItem>();
-
-    text->createTextBox({0, 0});
-    text->cursor().insertText(mimeData.text());
-
-    return {text};
+    return {};
 }
 
 void TextMimeHandler::contributeData(QMimeData &mimeData, const QList<std::shared_ptr<Item>> &selectedItems)
@@ -35,4 +36,5 @@ void TextMimeHandler::contributeData(QMimeData &mimeData, const QList<std::share
     const TextItem *item = static_cast<TextItem *>(&*selectedItems[0]);
 
     mimeData.setText(item->text());
+    mimeData.setHtml(item->html());
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.