diff --git a/src/document/katedocument.h b/src/document/katedocument.h --- a/src/document/katedocument.h +++ b/src/document/katedocument.h @@ -83,15 +83,16 @@ * KTextEditor interfaces. */ class KTEXTEDITOR_EXPORT KTextEditor::DocumentPrivate : public KTextEditor::Document, - public KTextEditor::MarkInterface, + public KTextEditor::MarkInterfaceV2, public KTextEditor::ModificationInterface, public KTextEditor::ConfigInterface, public KTextEditor::AnnotationInterface, public KTextEditor::MovingInterface, private KTextEditor::MovingRangeFeedback { Q_OBJECT Q_INTERFACES(KTextEditor::MarkInterface) + Q_INTERFACES(KTextEditor::MarkInterfaceV2) Q_INTERFACES(KTextEditor::ModificationInterface) Q_INTERFACES(KTextEditor::AnnotationInterface) Q_INTERFACES(KTextEditor::ConfigInterface) @@ -582,10 +583,19 @@ private: QHash m_marks; - QHash m_markPixmaps; + QHash m_markIcons; // QPixmap or QIcon, KF6: remove QPixmap support QHash m_markDescriptions; uint m_editableMarks = markType01; + // + // KTextEditor::MarkInterfaceV2 + // +public Q_SLOTS: + void setMarkIcon(MarkInterface::MarkTypes markType, const QIcon &icon) override; + +public: + QIcon markIcon(MarkInterface::MarkTypes markType) const override; + // KTextEditor::PrintInterface // public Q_SLOTS: diff --git a/src/document/katedocument.cpp b/src/document/katedocument.cpp --- a/src/document/katedocument.cpp +++ b/src/document/katedocument.cpp @@ -2187,7 +2187,7 @@ void KTextEditor::DocumentPrivate::setMarkPixmap(MarkInterface::MarkTypes type, const QPixmap &pixmap) { - m_markPixmaps.insert(type, pixmap); + m_markIcons.insert(type, QVariant::fromValue(pixmap)); } void KTextEditor::DocumentPrivate::setMarkDescription(MarkInterface::MarkTypes type, const QString &description) @@ -2197,7 +2197,8 @@ QPixmap KTextEditor::DocumentPrivate::markPixmap(MarkInterface::MarkTypes type) const { - return m_markPixmaps.value(type, QPixmap()); + auto icon = m_markIcons.value(type, QVariant::fromValue(QPixmap())); + return (static_cast(icon.type()) == QMetaType::QIcon) ? icon.value().pixmap(32) : icon.value(); } QColor KTextEditor::DocumentPrivate::markColor(MarkInterface::MarkTypes type) const @@ -2226,6 +2227,17 @@ } // END +void KTextEditor::DocumentPrivate::setMarkIcon(MarkInterface::MarkTypes markType, const QIcon &icon) +{ + m_markIcons.insert(markType, QVariant::fromValue(icon)); +} + +QIcon KTextEditor::DocumentPrivate::markIcon(MarkInterface::MarkTypes markType) const +{ + auto icon = m_markIcons.value(markType, QVariant::fromValue(QIcon())); + return (static_cast(icon.type()) == QMetaType::QIcon) ? icon.value() : QIcon(icon.value()); +} + // BEGIN KTextEditor::PrintInterface stuff bool KTextEditor::DocumentPrivate::print() { diff --git a/src/include/ktexteditor/markinterface.h b/src/include/ktexteditor/markinterface.h --- a/src/include/ktexteditor/markinterface.h +++ b/src/include/ktexteditor/markinterface.h @@ -27,6 +27,7 @@ #include #include +class QIcon; class QPixmap; class QPoint; class QMenu; @@ -396,8 +397,65 @@ class MarkInterfacePrivate *const d = nullptr; }; +/** + * \brief Mark extension interface for the Document, version 2 + * + * \ingroup kte_group_doc_extensions + * + * \section markextv2_intro Introduction + * + * The MarkInterfaceV2 allows to do the same as MarkInterface + * and additionally + * - (1) set an icon for a mark type instead of just a pixmap + * + * \section markextv2_access Accessing the Interface + * + * The MarkInterfaceV2 is supposed to be an extension interface for a Document, + * i.e. the Document inherits the interface \e provided that the + * KTextEditor library in use implements the interface. Use qobject_cast to access + * the interface: + * \code + * // doc is of type KTextEditor::Document* + * auto iface = qobject_cast(doc); + * + * if (iface) { + * // the implementation supports the interface + * // do stuff + * } else { + * // the implementation does not support the interface + * } + * \endcode + * + * \since 5.69 + */ +class KTEXTEDITOR_EXPORT MarkInterfaceV2 : public MarkInterface +{ + // KF6: Merge KTextEditor::MarkInterfaceV2 into KTextEditor::MarkInterface, drop QPixmap API (kossebau) +public: + virtual ~MarkInterfaceV2() + { + } + + /** + * Set the \p mark's icon to \p icon. + * \param markType mark type to which the icon will be attached + * \param icon new icon + * \see setMarkDescription() + */ + virtual void setMarkIcon(MarkTypes markType, const QIcon &icon) = 0; + + /** + * Get the \p mark's icon. + * \param markType mark type. If the icon does not exist the resulting is null + * (check with QIcon::isNull()). + * \see setMarkDescription() + */ + virtual QIcon markIcon(MarkTypes markType) const = 0; +}; + } Q_DECLARE_INTERFACE(KTextEditor::MarkInterface, "org.kde.KTextEditor.MarkInterface") +Q_DECLARE_INTERFACE(KTextEditor::MarkInterfaceV2, "org.kde.KTextEditor.MarkInterfaceV2") #endif diff --git a/src/search/katesearchbar.cpp b/src/search/katesearchbar.cpp --- a/src/search/katesearchbar.cpp +++ b/src/search/katesearchbar.cpp @@ -903,10 +903,10 @@ // Add ScrollBarMarks if (!m_highlightRanges.empty()) { - KTextEditor::MarkInterface *iface = qobject_cast(m_view->document()); + KTextEditor::MarkInterfaceV2 *iface = qobject_cast(m_view->document()); if (iface) { iface->setMarkDescription(KTextEditor::MarkInterface::SearchMatch, i18n("SearchHighLight")); - iface->setMarkPixmap(KTextEditor::MarkInterface::SearchMatch, QIcon().pixmap(0, 0)); + iface->setMarkIcon(KTextEditor::MarkInterface::SearchMatch, QIcon()); for (const Range &r : m_highlightRanges) { iface->addMark(r.start().line(), KTextEditor::MarkInterface::SearchMatch); } diff --git a/src/view/kateviewhelpers.cpp b/src/view/kateviewhelpers.cpp --- a/src/view/kateviewhelpers.cpp +++ b/src/view/kateviewhelpers.cpp @@ -1426,7 +1426,7 @@ setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum); setMouseTracking(true); m_doc->setMarkDescription(MarkInterface::markType01, i18n("Bookmark")); - m_doc->setMarkPixmap(MarkInterface::markType01, QIcon::fromTheme(QStringLiteral("bookmarks")).pixmap(32, 32)); + m_doc->setMarkIcon(MarkInterface::markType01, QIcon::fromTheme(QStringLiteral("bookmarks"))); connect(m_annotationItemDelegate, &AbstractAnnotationItemDelegate::sizeHintChanged, this, &KateIconBorder::updateAnnotationBorderWidth); @@ -1955,19 +1955,16 @@ for (uint bit = 0; bit < 32; bit++) { MarkInterface::MarkTypes markType = (MarkInterface::MarkTypes)(1 << bit); if (mrk & markType) { - QPixmap px_mark(m_doc->markPixmap(markType)); - px_mark.setDevicePixelRatio(devicePixelRatioF()); + const QIcon markIcon = m_doc->markIcon(markType); - if (!px_mark.isNull() && h > 0 && m_iconAreaWidth > 0) { - // scale up to a usable size - const int s = qMin(m_iconAreaWidth * devicePixelRatioF(), h * devicePixelRatioF()) - 2; - px_mark = px_mark.scaled(s, s, Qt::KeepAspectRatio, Qt::SmoothTransformation); + if (!markIcon.isNull() && h > 0 && m_iconAreaWidth > 0) { + const int s = qMin(m_iconAreaWidth, static_cast(h)) - 2; // center the mark pixmap - int x_px = 0.5 * qMax(m_iconAreaWidth - (s / devicePixelRatioF()), 0.0); - int y_px = 0.5 * qMax(h - (s / devicePixelRatioF()), 0.0); + const int x_px = qMax(m_iconAreaWidth - s, 0) / 2; + const int y_px = qMax(static_cast(h) - s, 0) / 2; - p.drawPixmap(lnX + x_px, y + y_px, px_mark); + markIcon.paint(&p, lnX + x_px, y + y_px, s, s); } } } @@ -2406,7 +2403,7 @@ QAction *mA; QAction *dMA; - const QPixmap icon = m_doc->markPixmap(markType); + const QIcon icon = m_doc->markIcon(markType); if (!m_doc->markDescription(markType).isEmpty()) { mA = markMenu.addAction(icon, m_doc->markDescription(markType)); dMA = selectDefaultMark.addAction(icon, m_doc->markDescription(markType));