From fbbb15ecafa2ec07232c6f8200a48fda568a4710 Mon Sep 17 00:00:00 2001 From: praspra2 Date: Wed, 21 Aug 2024 09:44:19 +0530 Subject: [PATCH 1/4] RichTextBlockItem --- .../AdaptiveCardContext.cpp | 45 ++++--- .../AdaptiveCardContext.h | 4 + .../AdaptiveCardQmlEngine/CMakeLists.txt | 4 +- .../models/CollectionItemModel.cpp | 11 ++ .../models/CollectionItemModel.h | 13 +- .../models/RichTextBlockModel.cpp | 116 ++++++++++++++++++ .../models/RichTextBlockModel.h | 69 +++++++++++ .../qml/CollectionItemDelegate.qml | 2 +- .../qml/RichTextBlockRender.qml | 28 +++++ .../qml/RichTextBlockRender_old.qml | 36 ++++++ .../AdaptiveCardQmlEngine/resourceEngine.qrc | 1 + .../utils/AdaptiveCardEnums.h | 1 + .../AdaptiveCardQmlEngine/utils/Utils.cpp | 20 ++- .../AdaptiveCardQmlEngine/utils/Utils.h | 26 +++- 14 files changed, 345 insertions(+), 31 deletions(-) create mode 100644 source/qml_v2/AdaptiveCardQmlEngine/models/RichTextBlockModel.cpp create mode 100644 source/qml_v2/AdaptiveCardQmlEngine/models/RichTextBlockModel.h create mode 100644 source/qml_v2/AdaptiveCardQmlEngine/qml/RichTextBlockRender.qml create mode 100644 source/qml_v2/AdaptiveCardQmlEngine/qml/RichTextBlockRender_old.qml diff --git a/source/qml_v2/AdaptiveCardQmlEngine/AdaptiveCardContext.cpp b/source/qml_v2/AdaptiveCardQmlEngine/AdaptiveCardContext.cpp index ce33161189..9ad5c46c6b 100644 --- a/source/qml_v2/AdaptiveCardQmlEngine/AdaptiveCardContext.cpp +++ b/source/qml_v2/AdaptiveCardQmlEngine/AdaptiveCardContext.cpp @@ -3,8 +3,7 @@ namespace AdaptiveCardQmlEngine { - AdaptiveCardContext::AdaptiveCardContext() - : mHostConfig(nullptr) + AdaptiveCardContext::AdaptiveCardContext() : mHostConfig(nullptr) { } @@ -14,29 +13,32 @@ namespace AdaptiveCardQmlEngine void AdaptiveCardContext::initAdaptiveCardContext() { - // Initializing Host config and Card config + // Initializing Host config and Card config mCardConfig = std::make_shared(true); - mHostConfig = std::make_shared(AdaptiveCards::HostConfig::DeserializeFromString(DarkConfig::darkConfig)); + mHostConfig = + std::make_shared(AdaptiveCards::HostConfig::DeserializeFromString(DarkConfig::darkConfig)); } void AdaptiveCardContext::setAdaptiveCardTheme(AdaptiveCardEnums::AdaptiveCardTheme theme) { mAdaptiveCardTheme = theme; - // ReInitializing AdaptiveCard and Host config - mCardConfig = std::make_shared(mAdaptiveCardTheme == AdaptiveCardEnums::AdaptiveCardTheme::DarkTheme ? true : false); + // ReInitializing AdaptiveCard and Host config + mCardConfig = + std::make_shared(mAdaptiveCardTheme == AdaptiveCardEnums::AdaptiveCardTheme::DarkTheme ? true : false); if (mAdaptiveCardTheme == AdaptiveCardEnums::AdaptiveCardTheme::DarkTheme) { - mHostConfig = std::make_shared(AdaptiveCards::HostConfig::DeserializeFromString(DarkConfig::darkConfig)); - } + mHostConfig = + std::make_shared(AdaptiveCards::HostConfig::DeserializeFromString(DarkConfig::darkConfig)); + } else { - mHostConfig = std::make_shared(AdaptiveCards::HostConfig::DeserializeFromString(LightConfig::lightConfig)); - } + mHostConfig = std::make_shared( + AdaptiveCards::HostConfig::DeserializeFromString(LightConfig::lightConfig)); + } } - std::shared_ptr AdaptiveCardContext::getHostConfig() { return mHostConfig; @@ -44,12 +46,12 @@ namespace AdaptiveCardQmlEngine std::shared_ptr AdaptiveCardContext::getCardConfig() { - return mCardConfig; + return mCardConfig; } QString AdaptiveCardContext::getColor(AdaptiveCards::ForegroundColor color, bool isSubtle, bool highlight, bool isQml) { - AdaptiveCards::ColorConfig colorConfig; + AdaptiveCards::ColorConfig colorConfig; switch (color) { case AdaptiveCards::ForegroundColor::Accent: @@ -73,8 +75,8 @@ namespace AdaptiveCardQmlEngine default: if (mAdaptiveCardTheme == AdaptiveCardEnums::AdaptiveCardTheme::DarkTheme) { - colorConfig = mRenderArgs.GetForegroundColors().light; - } + colorConfig = mRenderArgs.GetForegroundColors().light; + } break; } @@ -88,6 +90,17 @@ namespace AdaptiveCardQmlEngine const auto color = isSubtle ? colorConfig.subtleColor : colorConfig.defaultColor; return QString::fromStdString(color); } - } + } + + std::string AdaptiveCardContext::getLang() + { + return m_lang; + } + + void AdaptiveCardContext::setLang(const std::string& lang) + { + m_lang = lang; + } + } // namespace AdaptiveCardQmlEngine diff --git a/source/qml_v2/AdaptiveCardQmlEngine/AdaptiveCardContext.h b/source/qml_v2/AdaptiveCardQmlEngine/AdaptiveCardContext.h index 4d820046e0..8b28e6f0d5 100644 --- a/source/qml_v2/AdaptiveCardQmlEngine/AdaptiveCardContext.h +++ b/source/qml_v2/AdaptiveCardQmlEngine/AdaptiveCardContext.h @@ -39,6 +39,9 @@ namespace AdaptiveCardQmlEngine QString getColor(AdaptiveCards::ForegroundColor color, bool isSubtle, bool highlight, bool isQml = true); + std::string getLang(); + void setLang(const std::string& lang); + private: AdaptiveCardContext(); ~AdaptiveCardContext(); @@ -51,5 +54,6 @@ namespace AdaptiveCardQmlEngine std::shared_ptr mHostConfig; std::shared_ptr mCardConfig; AdaptiveCardEnums::AdaptiveCardTheme mAdaptiveCardTheme; + std::string m_lang; }; } diff --git a/source/qml_v2/AdaptiveCardQmlEngine/CMakeLists.txt b/source/qml_v2/AdaptiveCardQmlEngine/CMakeLists.txt index 0cff0beadb..0f3f27a477 100644 --- a/source/qml_v2/AdaptiveCardQmlEngine/CMakeLists.txt +++ b/source/qml_v2/AdaptiveCardQmlEngine/CMakeLists.txt @@ -55,6 +55,7 @@ file(GLOB_RECURSE SOURCES "CollectionItemModel.cpp" "TextBlockModel.cpp" + "RichTextBlockModel.cpp" "AdaptiveCardQmlTypes.h" "AdaptiveCardUtils.cpp" @@ -72,7 +73,8 @@ file(GLOB_RECURSE SOURCES "AdaptiveCardModel.h" "CollectionItemModel.h" - "TextBlockModel.h" + "TextBlockModel.h" + "RichTextBlockModel.h" ) # Setup Library diff --git a/source/qml_v2/AdaptiveCardQmlEngine/models/CollectionItemModel.cpp b/source/qml_v2/AdaptiveCardQmlEngine/models/CollectionItemModel.cpp index 2284009ab6..285efd34f7 100644 --- a/source/qml_v2/AdaptiveCardQmlEngine/models/CollectionItemModel.cpp +++ b/source/qml_v2/AdaptiveCardQmlEngine/models/CollectionItemModel.cpp @@ -1,5 +1,6 @@ #include "CollectionItemModel.h" #include "TextBlockModel.h" +#include "RichTextBlockModel.h" #include "AdaptiveCardEnums.h" CollectionItemModel::CollectionItemModel(std::vector> elements, QObject* parent) @@ -39,6 +40,7 @@ QHash CollectionItemModel::roleNames() const QHash cardListModel; cardListModel[DelegateType] = "delegateType"; cardListModel[TextBlockRole] = "textBlockRole"; + cardListModel[RichTextBlockRole] = "richTextBlockRole"; cardListModel[FillHeightRole] = "fillHeightRole"; return cardListModel; @@ -54,6 +56,9 @@ void CollectionItemModel::populateRowData(std::shared_ptr(element), rowContent); break; + case AdaptiveCards::CardElementType::RichTextBlock: + populateRichTextBlockModel(std::dynamic_pointer_cast(element), rowContent); + break; default: break; } @@ -66,3 +71,9 @@ void CollectionItemModel::populateTextBlockModel(std::shared_ptr richTextBlock, RowContent& rowContent) +{ + rowContent[CollectionModelRole::DelegateType] = QVariant::fromValue(AdaptiveCardEnums::CardElementType::RichTextBlock); + rowContent[CollectionModelRole::RichTextBlockRole] = QVariant::fromValue(new RichTextBlockModel(richTextBlock, nullptr)); +} diff --git a/source/qml_v2/AdaptiveCardQmlEngine/models/CollectionItemModel.h b/source/qml_v2/AdaptiveCardQmlEngine/models/CollectionItemModel.h index 47e7f3e72e..b343bd0648 100644 --- a/source/qml_v2/AdaptiveCardQmlEngine/models/CollectionItemModel.h +++ b/source/qml_v2/AdaptiveCardQmlEngine/models/CollectionItemModel.h @@ -4,23 +4,27 @@ #include #include +#include "RichTextBlock.h" + #include "Enums.h" class TextBlockModel; +class RichTextBlockModel; -class CollectionItemModel : public QAbstractListModel +class CollectionItemModel : public QAbstractListModel { - Q_OBJECT + Q_OBJECT - enum CollectionModelRole + enum CollectionModelRole { DelegateType = Qt::UserRole + 1, TextBlockRole, + RichTextBlockRole, FillHeightRole }; public: - using RowContent = std::unordered_map; + using RowContent = std::unordered_map; explicit CollectionItemModel(std::vector> elements, QObject* parent = nullptr); ~CollectionItemModel(); @@ -36,4 +40,5 @@ class CollectionItemModel : public QAbstractListModel private: void populateRowData(std::shared_ptr element); void populateTextBlockModel(std::shared_ptr textBlock, RowContent& rowContent); + void populateRichTextBlockModel(std::shared_ptr rightTextBlock, RowContent& rowContent); }; diff --git a/source/qml_v2/AdaptiveCardQmlEngine/models/RichTextBlockModel.cpp b/source/qml_v2/AdaptiveCardQmlEngine/models/RichTextBlockModel.cpp new file mode 100644 index 0000000000..70acd733c5 --- /dev/null +++ b/source/qml_v2/AdaptiveCardQmlEngine/models/RichTextBlockModel.cpp @@ -0,0 +1,116 @@ +#include "RichTextBlockModel.h" +#include "SharedAdaptiveCard.h" +#include +#include "Utils.h" +#include "MarkDownParser.h" + +RichTextBlockModel::RichTextBlockModel(std::shared_ptr richTextBlock, QObject* parent) : + QObject(parent) +{ + const auto hostConfig = AdaptiveCardQmlEngine::AdaptiveCardContext::getInstance().getHostConfig(); + const auto rendererConfig = AdaptiveCardQmlEngine::AdaptiveCardContext::getInstance().getCardConfig(); + + // Property values assigned for RichTextBlock + const auto selectionColor = rendererConfig->getCardConfig().textHighlightBackground; + const auto hAlignmentValue = richTextBlock->GetHorizontalAlignment().value_or(AdaptiveCards::HorizontalAlignment::Left); + const auto textType = richTextBlock->GetElementTypeString(); + + QString textrun_all = ""; + auto config = AdaptiveCardQmlEngine::AdaptiveCardContext::getInstance().getCardConfig(); + for (const auto& inlineRun : richTextBlock->GetInlines()) + { + if (AdaptiveCardQmlEngine::Utils::IsInstanceOfSmart(inlineRun)) + { + std::string selectActionId = ""; + auto textRun = std::dynamic_pointer_cast(inlineRun); + textrun_all.append(textRunRender(textRun, selectActionId)); + } + } + + mText = textrun_all; + mTextHorizontalAlignment = static_cast(hAlignmentValue); +} + +QString RichTextBlockModel::textRunRender(const std::shared_ptr& textRun, const std::string& selectaction) +{ + // Handle to Host config + auto config = AdaptiveCardQmlEngine::AdaptiveCardContext::getInstance().getHostConfig(); + + // TextRun properties + const auto textSize = textRun->GetTextSize().value_or(AdaptiveCards::TextSize::Default); + const auto textColor = textRun->GetTextColor().value_or(AdaptiveCards::ForegroundColor::Default); + const auto textIsSubtle = textRun->GetIsSubtle().value_or(false); + const auto textWeight = textRun->GetTextWeight().value_or(AdaptiveCards::TextWeight::Default); + const auto textType = QString::fromStdString(textRun->GetInlineTypeString()); + + const auto fontType = textRun->GetFontType().value_or(AdaptiveCards::FontType::Default); + + // Context & Config properties + const QString fontFamily = QString::fromStdString(config->GetFontFamily(fontType)); + + const int fontSize = config->GetFontSize(fontType, textSize); + const int weight = config->GetFontWeight(fontType, textWeight); + + const QString color = AdaptiveCardQmlEngine::AdaptiveCardContext::getInstance().getColor(textColor, textIsSubtle, false, true); + + int mTextMaxLines{INT_MAX}; + bool mTextWrap = true; + + QString uiTextRun = ""); + + std::string text = AdaptiveCardQmlEngine::TextUtils::applyTextFunctions(textRun->GetText(), AdaptiveCardQmlEngine::AdaptiveCardContext::getInstance().getLang()); + + text = AdaptiveCardQmlEngine::Utils::handleEscapeSequences(text); + const std::string linkColor = AdaptiveCardQmlEngine::AdaptiveCardContext::getInstance().getColor(AdaptiveCards::ForegroundColor::Accent, false, false).toStdString(); + + // CSS Property for underline, striketrhough,etc + std::string textDecoration = "none"; + + text = AdaptiveCardQmlEngine::Utils::formatHtmlUrl(text, linkColor, textDecoration); + + if (textRun->GetSelectAction() != nullptr) + { + const QString styleString = "style=\\\"color:" + QString::fromStdString(linkColor) + ";" + + "text-decoration:" + QString::fromStdString(textDecoration) + ";\\\""; + uiTextRun.append(""); + uiTextRun.append(QString::fromStdString(text)); + uiTextRun.append(""); + } + else + { + uiTextRun.append(QString::fromStdString(text)); + } + uiTextRun.append(""); + + return uiTextRun; +} + +RichTextBlockModel::~RichTextBlockModel() +{ +} diff --git a/source/qml_v2/AdaptiveCardQmlEngine/models/RichTextBlockModel.h b/source/qml_v2/AdaptiveCardQmlEngine/models/RichTextBlockModel.h new file mode 100644 index 0000000000..c85e0950d5 --- /dev/null +++ b/source/qml_v2/AdaptiveCardQmlEngine/models/RichTextBlockModel.h @@ -0,0 +1,69 @@ +#pragma once + +#include +#include +#include + +#include "AdaptiveCardContext.h" +#include "RichTextBlock.h" +#include "TextRun.h" + +class RichTextBlockModel : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString text MEMBER mText CONSTANT) + Q_PROPERTY(int maxLines MEMBER mTextMaxLines CONSTANT) + Q_PROPERTY(bool textWrap MEMBER mTextWrap CONSTANT) + + Q_PROPERTY(QString color MEMBER mColor CONSTANT) + Q_PROPERTY(QString selectionColor MEMBER mSelectionColor CONSTANT) + + Q_PROPERTY(int fontPixelSize MEMBER mFontPixelSize CONSTANT) + Q_PROPERTY(QString fontWeight MEMBER mFontWeight CONSTANT) + Q_PROPERTY(QString fontFamily MEMBER mFontFamily CONSTANT) + + Q_PROPERTY(int horizontalAlignment MEMBER mTextHorizontalAlignment CONSTANT) + Q_PROPERTY(bool isVisible MEMBER mIsVisible CONSTANT) + + Q_PROPERTY(bool isInTabOrder MEMBER mIsInTabOrder CONSTANT) + + Q_PROPERTY(QString textType MEMBER mTextType CONSTANT) + Q_PROPERTY(bool textUnderlineDecoration MEMBER mTextUnderlineDecoration CONSTANT) + Q_PROPERTY(bool textStrikethroughDecoration MEMBER mTextStrikethroughDecoration CONSTANT) + Q_PROPERTY(QString fontStyle MEMBER mFontStyle CONSTANT) + + +public: + explicit RichTextBlockModel(std::shared_ptr richTextBlock, QObject* parent = nullptr); + ~RichTextBlockModel(); + +private: + QString textRunRender ( + const std::shared_ptr& textRun, + const std::string& selectaction); + +private: + QString mText; + int mTextMaxLines{INT_MAX}; + bool mTextWrap; + + QString mColor; + QString mSelectionColor; + QString mBackgroundColor; + + int mFontPixelSize; + QString mFontWeight; + QString mFontFamily; + QString mFontStyle; + + int mTextHorizontalAlignment; + bool mIsVisible; + bool mIsInTabOrder; + + QString mTextType; + QString mTextRun_all; + bool mTextUnderlineDecoration; + bool mTextStrikethroughDecoration; + + bool isFirstElement; +}; diff --git a/source/qml_v2/AdaptiveCardQmlEngine/qml/CollectionItemDelegate.qml b/source/qml_v2/AdaptiveCardQmlEngine/qml/CollectionItemDelegate.qml index 6116fcdff8..2df8d83c11 100644 --- a/source/qml_v2/AdaptiveCardQmlEngine/qml/CollectionItemDelegate.qml +++ b/source/qml_v2/AdaptiveCardQmlEngine/qml/CollectionItemDelegate.qml @@ -7,7 +7,7 @@ Loader { property var parentCardItem - source: "qrc:qml/TextBlockRender.qml" + source: "qrc:qml/RichTextBlockRender.qml" /* { diff --git a/source/qml_v2/AdaptiveCardQmlEngine/qml/RichTextBlockRender.qml b/source/qml_v2/AdaptiveCardQmlEngine/qml/RichTextBlockRender.qml new file mode 100644 index 0000000000..73f01fff32 --- /dev/null +++ b/source/qml_v2/AdaptiveCardQmlEngine/qml/RichTextBlockRender.qml @@ -0,0 +1,28 @@ +import QtQuick 2.15 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.15 +import AdaptiveCardQmlEngine 1.0 +import "JSUtils/AdaptiveCardUtils.js" as AdaptiveCardUtils + +TextEdit { + id: "richTextBlock" + + property var richTextBlockModel: model.richTextBlockRole + + width: implicitWidth + height: implicitHeight + + padding: 0 + clip: true + + visible: richTextBlockModel.isVisible + + text: richTextBlockModel.text + textFormat: Text.RichText + + wrapMode: richTextBlockModel.textWrap ? Text.Wrap : Text.NoWrap + horizontalAlignment : richTextBlockModel.horizontalAlignment === 0 ? Text.AlignLeft : + richTextBlockModel.horizontalAlignment === 1 ? Text.AlignHCenter : Text.AlignRight + + color: richTextBlockModel.color +} diff --git a/source/qml_v2/AdaptiveCardQmlEngine/qml/RichTextBlockRender_old.qml b/source/qml_v2/AdaptiveCardQmlEngine/qml/RichTextBlockRender_old.qml new file mode 100644 index 0000000000..54e3f1ea18 --- /dev/null +++ b/source/qml_v2/AdaptiveCardQmlEngine/qml/RichTextBlockRender_old.qml @@ -0,0 +1,36 @@ +import QtQuick 2.15 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.15 +import AdaptiveCardQmlEngine 1.0 +import "JSUtils/AdaptiveCardUtils.js" as AdaptiveCardUtils + +TextEdit { + id: "richTextBlock" + + property var richTextBlockModel: model.richTextBlockRole + + width: implicitWidth + height: implicitHeight + + padding: 0 + clip: true + + visible: richTextBlockModel.isVisible + text: richTextBlockModel.text + textFormat: Text.RichText + + wrapMode: richTextBlockModel.textWrap ? Text.Wrap : Text.NoWrap + + horizontalAlignment : richTextBlockModel.horizontalAlignment === 0 ? Text.AlignLeft : + richTextBlockModel.horizontalAlignment === 1 ? Text.AlignHCenter : Text.AlignRight + + color: richTextBlockModel.color + + font.pixelSize: richTextBlockModel.fontPixelSize + font.weight: richTextBlockModel.fontWeight === "extraLight" ? Font.ExtraLight : + richTextBlockModel.fontWeight === "bold" ? Font.Bold : Font.Normal + font.family: richTextBlockModel.fontFamily + font.italic: richTextBlockModel.fontStyle == "italic" ? true : false + font.underline: richTextBlockModel.textUnderlineDecoration + font.strikeout: richTextBlockModel.textStrikethroughDecoration +} diff --git a/source/qml_v2/AdaptiveCardQmlEngine/resourceEngine.qrc b/source/qml_v2/AdaptiveCardQmlEngine/resourceEngine.qrc index ec6a6fe71b..5109db63f1 100644 --- a/source/qml_v2/AdaptiveCardQmlEngine/resourceEngine.qrc +++ b/source/qml_v2/AdaptiveCardQmlEngine/resourceEngine.qrc @@ -9,5 +9,6 @@ qml/JSUtils/AdaptiveCardUtils.js qml/JSUtils/ThemeUtils.js qml/CardConstants.qml + qml/RichTextBlockRender.qml diff --git a/source/qml_v2/AdaptiveCardQmlEngine/utils/AdaptiveCardEnums.h b/source/qml_v2/AdaptiveCardQmlEngine/utils/AdaptiveCardEnums.h index 0d2cd9c433..af5575ff6f 100644 --- a/source/qml_v2/AdaptiveCardQmlEngine/utils/AdaptiveCardEnums.h +++ b/source/qml_v2/AdaptiveCardQmlEngine/utils/AdaptiveCardEnums.h @@ -8,6 +8,7 @@ namespace AdaptiveCardEnums enum class CardElementType { AdaptiveCard, TextBlock, + RichTextBlock, Container, Column, ColumnSet, diff --git a/source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.cpp b/source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.cpp index f2f69ec5b2..4400f3373c 100644 --- a/source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.cpp +++ b/source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.cpp @@ -86,9 +86,21 @@ namespace AdaptiveCardQmlEngine return splitElements; } - //------------------------------------------------------------------------------------------------------- + std::string& Utils::replace(std::string& str, char what, char with) + { + if (!with) + { + str.erase(std::remove(str.begin(), str.end(), what), str.end()); + } + else + { + std::replace(str.begin(), str.end(), what, with); + } + return str; + } + + std::regex TextUtils::m_textFunctionRegex(R"xxx(\{\{(DATE|TIME)\(([\d]{4}-[\d]{2}-[\d]{2}T[\d]{2}:[\d]{2}:[\d]{2})(Z|(?:(?:-|\+)\d{2}:\d{2}))(?:,\s*(SHORT|LONG|COMPACT)\s*)??\)\}\})xxx"); - /* std::string TextUtils::applyTextFunctions(const std::string& text, const std::string& lang) { std::smatch oneMatch; @@ -144,7 +156,7 @@ namespace AdaptiveCardQmlEngine ss2.imbue(getValidCultureInfo(lang)); ss2 << std::put_time(<, format.c_str()); - result = Utils::Replace(result, oneMatch[0], ss2.str()); + result = Utils::replace(result, oneMatch[0], ss2.str()); } } } @@ -195,8 +207,6 @@ namespace AdaptiveCardQmlEngine return true; } - */ - } // namespace AdaptiveCardQmlEngine diff --git a/source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.h b/source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.h index dce5bee5f3..157d4560ad 100644 --- a/source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.h +++ b/source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.h @@ -16,13 +16,31 @@ namespace AdaptiveCardQmlEngine static const std::string handleEscapeSequences(std::string& text); static const std::string formatHtmlUrl(std::string& text, const std::string& linkColor, const std::string& textDecoration); static std::vector splitString(const std::string& string, char delimiter); + static std::string& replace(std::string& str, char what, char with); + //static std::string& replace(std::string& str, const std::string& what, const std::string& with); - + template + static bool IsInstanceOfSmart(U u); + + template + static bool IsInstanceOf(U u); + private: Utils() {} }; - /* + template + inline bool Utils::IsInstanceOfSmart(U u) + { + return std::dynamic_pointer_cast(u) != nullptr; + } + + template + inline bool Utils::IsInstanceOf(U u) + { + return dynamic_cast(u) != nullptr; + } + class TextUtils { public: @@ -33,5 +51,5 @@ namespace AdaptiveCardQmlEngine private: static std::regex m_textFunctionRegex; }; - */ -} // namespace AdaptiveCardQmlEngine + +} // namespace AdaptiveCardQmlEngine From 25d8803298a3c0af03f1d7d30842acffea4a6f24 Mon Sep 17 00:00:00 2001 From: praspra2 Date: Wed, 21 Aug 2024 12:58:11 +0530 Subject: [PATCH 2/4] RichTextBlockItem Updated --- source/qml_v2/AdaptiveCardQmlEngine/AdaptiveCardContext.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/source/qml_v2/AdaptiveCardQmlEngine/AdaptiveCardContext.cpp b/source/qml_v2/AdaptiveCardQmlEngine/AdaptiveCardContext.cpp index 9ad5c46c6b..81737e661c 100644 --- a/source/qml_v2/AdaptiveCardQmlEngine/AdaptiveCardContext.cpp +++ b/source/qml_v2/AdaptiveCardQmlEngine/AdaptiveCardContext.cpp @@ -15,8 +15,7 @@ namespace AdaptiveCardQmlEngine { // Initializing Host config and Card config mCardConfig = std::make_shared(true); - mHostConfig = - std::make_shared(AdaptiveCards::HostConfig::DeserializeFromString(DarkConfig::darkConfig)); + mHostConfig = std::make_shared(AdaptiveCards::HostConfig::DeserializeFromString(DarkConfig::darkConfig)); } void AdaptiveCardContext::setAdaptiveCardTheme(AdaptiveCardEnums::AdaptiveCardTheme theme) @@ -24,8 +23,7 @@ namespace AdaptiveCardQmlEngine mAdaptiveCardTheme = theme; // ReInitializing AdaptiveCard and Host config - mCardConfig = - std::make_shared(mAdaptiveCardTheme == AdaptiveCardEnums::AdaptiveCardTheme::DarkTheme ? true : false); + mCardConfig = std::make_shared(mAdaptiveCardTheme == AdaptiveCardEnums::AdaptiveCardTheme::DarkTheme ? true : false); if (mAdaptiveCardTheme == AdaptiveCardEnums::AdaptiveCardTheme::DarkTheme) { From 1a6ca21a0e1dd8a5009750d7bd44f8bcbb24744d Mon Sep 17 00:00:00 2001 From: praspra2 Date: Wed, 21 Aug 2024 16:10:49 +0530 Subject: [PATCH 3/4] RichTextBlockItem Changes --- source/qml_v2/AdaptiveCardQmlEngine/AdaptiveCardContext.cpp | 2 +- source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.h | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/source/qml_v2/AdaptiveCardQmlEngine/AdaptiveCardContext.cpp b/source/qml_v2/AdaptiveCardQmlEngine/AdaptiveCardContext.cpp index 81737e661c..ad5478ce0a 100644 --- a/source/qml_v2/AdaptiveCardQmlEngine/AdaptiveCardContext.cpp +++ b/source/qml_v2/AdaptiveCardQmlEngine/AdaptiveCardContext.cpp @@ -44,7 +44,7 @@ namespace AdaptiveCardQmlEngine std::shared_ptr AdaptiveCardContext::getCardConfig() { - return mCardConfig; + return mCardConfig; } QString AdaptiveCardContext::getColor(AdaptiveCards::ForegroundColor color, bool isSubtle, bool highlight, bool isQml) diff --git a/source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.h b/source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.h index 157d4560ad..d9a3ecd835 100644 --- a/source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.h +++ b/source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.h @@ -17,8 +17,7 @@ namespace AdaptiveCardQmlEngine static const std::string formatHtmlUrl(std::string& text, const std::string& linkColor, const std::string& textDecoration); static std::vector splitString(const std::string& string, char delimiter); static std::string& replace(std::string& str, char what, char with); - //static std::string& replace(std::string& str, const std::string& what, const std::string& with); - + template static bool IsInstanceOfSmart(U u); From 407e98733d031124170fb356df9f3a8411e7dd6b Mon Sep 17 00:00:00 2001 From: praspra2 Date: Wed, 28 Aug 2024 09:45:53 +0530 Subject: [PATCH 4/4] BaseAdaptiveCard Implementation --- .../qml_v2/AdaptiveCardQmlEngine/images/1.jpg | Bin 0 -> 10781 bytes .../models/AdaptiveCardModel.cpp | 73 +++++++++- .../models/AdaptiveCardModel.h | 17 ++- .../qml/AdaptiveCard.qml | 35 ++++- .../qml/CollectionItemDelegate.qml | 2 +- .../AdaptiveCardQmlEngine/resourceEngine.qrc | 2 +- .../AdaptiveCardQmlEngine/utils/Utils.cpp | 128 ++---------------- .../AdaptiveCardQmlEngine/utils/Utils.h | 35 +---- 8 files changed, 131 insertions(+), 161 deletions(-) create mode 100644 source/qml_v2/AdaptiveCardQmlEngine/images/1.jpg diff --git a/source/qml_v2/AdaptiveCardQmlEngine/images/1.jpg b/source/qml_v2/AdaptiveCardQmlEngine/images/1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2703578c631886bf6a35b5ba6132c525eb9a3671 GIT binary patch literal 10781 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 literal 0 HcmV?d00001 diff --git a/source/qml_v2/AdaptiveCardQmlEngine/models/AdaptiveCardModel.cpp b/source/qml_v2/AdaptiveCardQmlEngine/models/AdaptiveCardModel.cpp index 493c9b1fc6..a8c185807c 100644 --- a/source/qml_v2/AdaptiveCardQmlEngine/models/AdaptiveCardModel.cpp +++ b/source/qml_v2/AdaptiveCardQmlEngine/models/AdaptiveCardModel.cpp @@ -1,10 +1,11 @@ #include "AdaptiveCardModel.h" - +#include "Enums.h" AdaptiveCardModel::AdaptiveCardModel(std::shared_ptr mainCard, QObject *parent) : QObject(parent) , mMainCard(mainCard) , mCardBody(nullptr) + , mHasBackgroundImage(false) { populateCardBody(); } @@ -41,7 +42,71 @@ void AdaptiveCardModel::populateCardBody() break; } - // Card Background color - auto hostConfig = AdaptiveCardQmlEngine::AdaptiveCardContext::getInstance().getHostConfig(); - mBackgroundColor = QString::fromStdString(hostConfig->GetContainerStyles().defaultPalette.backgroundColor); + setupBaseCardProperties(); +} + +void AdaptiveCardModel::setupBaseCardProperties() +{ + auto hostConfig = AdaptiveCardQmlEngine::AdaptiveCardContext::getInstance().getHostConfig(); + + mBackgroundColor = QString::fromStdString(hostConfig->GetContainerStyles().defaultPalette.backgroundColor); + + mHasBackgroundImage = false; + mBackgroundImageSource = ""; + + if (mMainCard->GetBackgroundImage() != nullptr && mMainCard->GetBackgroundImage()->GetUrl() != "") + { + mHasBackgroundImage = true; + mBackgroundImageSource = getImagePath(mMainCard->GetBackgroundImage()->GetUrl()); + + mImageHorizontalAlignment = QString::fromStdString(AdaptiveCards::EnumHelpers::getHorizontalAlignmentEnum().toString(mMainCard->GetBackgroundImage()->GetHorizontalAlignment())); + mImageVerticalAlignment = QString::fromStdString(AdaptiveCards::EnumHelpers::getVerticalAlignmentEnum().toString(mMainCard->GetBackgroundImage()->GetVerticalAlignment())); + + const auto fillMode = mMainCard->GetBackgroundImage()->GetFillMode(); + switch (fillMode) + { + case AdaptiveCards::ImageFillMode::Cover: + { + mFillMode = "PreserveAspectCrop"; + break; + } + case AdaptiveCards::ImageFillMode::RepeatHorizontally: + { + mFillMode = "TileHorizontally"; + break; + } + case AdaptiveCards::ImageFillMode::RepeatVertically: + { + mFillMode = "TileVertically"; + break; + } + case AdaptiveCards::ImageFillMode::Repeat: + { + mFillMode = "Tile"; + break; + } + default: + break; + } + + }; +} + +QString AdaptiveCardModel::getImagePath(const std::string url) +{ + // To Do: Need to download the file and save it in a local forder called "images" first. + // For now images are saved manually prior to render the image from local path. + + // Extracting the file name from the url + QString newUrl = QString::fromStdString(url); + const auto imageName = newUrl.split("://").at(1).split("/").last().split(".").first() + ".jpg"; + + // Setting up the local path for the image + QString file_path = __FILE__; + QString dir_path = file_path.left(file_path.lastIndexOf("\\models")); + dir_path.append("\\images\\" + imageName); + std::replace(dir_path.begin(), dir_path.end(), '\\', '/'); + dir_path = "file:/" + dir_path; + + return dir_path; } diff --git a/source/qml_v2/AdaptiveCardQmlEngine/models/AdaptiveCardModel.h b/source/qml_v2/AdaptiveCardQmlEngine/models/AdaptiveCardModel.h index ebbd98da24..5dd0884bc0 100644 --- a/source/qml_v2/AdaptiveCardQmlEngine/models/AdaptiveCardModel.h +++ b/source/qml_v2/AdaptiveCardQmlEngine/models/AdaptiveCardModel.h @@ -16,19 +16,32 @@ class AdaptiveCardModel : public QObject Q_PROPERTY(int minHeight MEMBER mMinHeight CONSTANT) Q_PROPERTY(Qt::AlignmentFlag verticalAlignment MEMBER mVerticalAlignment CONSTANT) Q_PROPERTY(QString backgroundColor MEMBER mBackgroundColor CONSTANT) + Q_PROPERTY(bool hasBackgroundImage MEMBER mHasBackgroundImage CONSTANT) + Q_PROPERTY(QString backgroundImageSource MEMBER mBackgroundImageSource CONSTANT) Q_PROPERTY(CollectionItemModel* cardBodyModel MEMBER mCardBody CONSTANT) - - + Q_PROPERTY(QString fillMode MEMBER mFillMode CONSTANT) + Q_PROPERTY(QString imageHorizontalAlignment MEMBER mImageHorizontalAlignment CONSTANT) + Q_PROPERTY(QString imageVerticalAlignment MEMBER mImageVerticalAlignment CONSTANT) + public: explicit AdaptiveCardModel(std::shared_ptr mainCard, QObject* parent = nullptr); ~AdaptiveCardModel(); private: void populateCardBody(); + void setupBaseCardProperties(); + + QString AdaptiveCardModel::getImagePath(const std::string url); private: int mMinHeight; + QString mBackgroundColor; + QString mBackgroundImageSource; + bool mHasBackgroundImage; + QString mFillMode; + QString mImageHorizontalAlignment; + QString mImageVerticalAlignment; Qt::AlignmentFlag mVerticalAlignment; std::shared_ptr mMainCard; diff --git a/source/qml_v2/AdaptiveCardQmlEngine/qml/AdaptiveCard.qml b/source/qml_v2/AdaptiveCardQmlEngine/qml/AdaptiveCard.qml index d5e6e13f8a..43fbc1c73f 100644 --- a/source/qml_v2/AdaptiveCardQmlEngine/qml/AdaptiveCard.qml +++ b/source/qml_v2/AdaptiveCardQmlEngine/qml/AdaptiveCard.qml @@ -24,7 +24,7 @@ Rectangle { // Card body model ----- property var cardBodyModel: cardRootModel.cardBodyModel - + // Properties for the main card ----- property string cardJSON property int cardTheme @@ -35,14 +35,35 @@ Rectangle { radius: 8 color : cardRootModel.backgroundColor - Image { - id: backGroundImage + // Background image container rect. + Rectangle { + id: imageRect + + width: parent.width + height: parent.height + visible : cardRootModel.hasBackgroundImage + + color: "transparent" - width: parent.width - height: parent.height + Image { + id: backGroundImage + + anchors.fill: parent - visible : false - source: "" + visible: parent.visible + source: cardRootModel.backgroundImageSource + + fillMode: cardRootModel.fillMode == "Cover" ? Image.PreserveAspectCrop : cardRootModel.fillMode == "Tile" ? Image.Tile : cardRootModel.fillMode == "TileHorizontally" ? Image.TileHorizontally : cardRootModel.fillMode == "TileVertically" ? Image.TileVertically : Image.PreserveAspectFit + + anchors { + top : cardRootModel.imageVerticalAlignment == "top" ? parent.top : undefined + verticalCenter : cardRootModel.imageVerticalAlignment == "center" ? parent.verticalCenter : undefined + bottom : cardRootModel.imageVerticalAlignment == "bottom" ? parent.bottom : undefined + left : cardRootModel.imageHorizontalAlignment == "left" ? parent.left : undefined + horizontalCenter : cardRootModel.imageHorizontalAlignment == "center" ? parent.horizontalCenter : undefined + right : cardRootModel.imageHorizontalAlignment == "right" ? parent.right : undefined + } + } } Component.onCompleted: { diff --git a/source/qml_v2/AdaptiveCardQmlEngine/qml/CollectionItemDelegate.qml b/source/qml_v2/AdaptiveCardQmlEngine/qml/CollectionItemDelegate.qml index 2df8d83c11..6116fcdff8 100644 --- a/source/qml_v2/AdaptiveCardQmlEngine/qml/CollectionItemDelegate.qml +++ b/source/qml_v2/AdaptiveCardQmlEngine/qml/CollectionItemDelegate.qml @@ -7,7 +7,7 @@ Loader { property var parentCardItem - source: "qrc:qml/RichTextBlockRender.qml" + source: "qrc:qml/TextBlockRender.qml" /* { diff --git a/source/qml_v2/AdaptiveCardQmlEngine/resourceEngine.qrc b/source/qml_v2/AdaptiveCardQmlEngine/resourceEngine.qrc index 5109db63f1..b4f44fbfa2 100644 --- a/source/qml_v2/AdaptiveCardQmlEngine/resourceEngine.qrc +++ b/source/qml_v2/AdaptiveCardQmlEngine/resourceEngine.qrc @@ -9,6 +9,6 @@ qml/JSUtils/AdaptiveCardUtils.js qml/JSUtils/ThemeUtils.js qml/CardConstants.qml - qml/RichTextBlockRender.qml + images/1.jpg diff --git a/source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.cpp b/source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.cpp index 4400f3373c..749259e10a 100644 --- a/source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.cpp +++ b/source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.cpp @@ -86,126 +86,24 @@ namespace AdaptiveCardQmlEngine return splitElements; } - std::string& Utils::replace(std::string& str, char what, char with) + std::string Utils::GetHorizontalAlignment(std::string alignType) { - if (!with) - { - str.erase(std::remove(str.begin(), str.end(), what), str.end()); - } + if (alignType.compare("center") == 0) + return "Qt.AlignHCenter"; + else if (alignType.compare("right") == 0) + return "Qt.AlignRight"; else - { - std::replace(str.begin(), str.end(), what, with); - } - return str; - } - - std::regex TextUtils::m_textFunctionRegex(R"xxx(\{\{(DATE|TIME)\(([\d]{4}-[\d]{2}-[\d]{2}T[\d]{2}:[\d]{2}:[\d]{2})(Z|(?:(?:-|\+)\d{2}:\d{2}))(?:,\s*(SHORT|LONG|COMPACT)\s*)??\)\}\})xxx"); - - std::string TextUtils::applyTextFunctions(const std::string& text, const std::string& lang) - { - std::smatch oneMatch; - std::string result = text; - std::string::const_iterator searchLoc(text.cbegin()); - while (std::regex_search(searchLoc, text.cend(), oneMatch, m_textFunctionRegex)) - { - if (oneMatch[1] == "DATE" || oneMatch[1] == "TIME") - { - std::tm utcTm = {}; - std::stringstream tmss(oneMatch[2]); - tmss >> std::get_time(&utcTm, "%Y-%m-%dT%H:%M:%S"); - - if (!tmss.fail()) - { - std::tm lt = {}; - if (getLocalTime(oneMatch[3], utcTm, lt)) - { - std::string format = "%x"; - if (oneMatch[1] == "DATE") - { - // Check if date before 1970 - auto date_split = Utils::splitString(oneMatch[2], '-'); - if (date_split.empty() || std::stoi(date_split[0]) < 1970) - { - return result; - } - - if (oneMatch[4] == "LONG") - { - format = "%A, %B %d, %Y"; // There is no equivalent for C# "D" format in C++ - } - else if (oneMatch[4] == "SHORT") - { - format = "%a, %b %d, %Y"; - } - else - { - format = "%x"; - } - } - else if (oneMatch[1] == "TIME") - { - if (oneMatch[4] != "") - { - searchLoc = oneMatch.suffix().first; - continue; - } - format = "%I:%M %p"; - } - - std::stringstream ss2; - ss2.imbue(getValidCultureInfo(lang)); - ss2 << std::put_time(<, format.c_str()); - - result = Utils::replace(result, oneMatch[0], ss2.str()); - } - } - } - searchLoc = oneMatch.suffix().first; - } - return result; + return "Qt.AlignLeft"; } - std::locale TextUtils::getValidCultureInfo(const std::string& lang) + std::string Utils::GetVerticalAlignment(std::string alignType) { - return std::locale("en_US"); - } - - bool TextUtils::getLocalTime(const std::string& tzOffset, std::tm& utcTm, std::tm& lt) - { - lt = {}; - std::stringstream tzss(tzOffset); - char offsetType; - tzss >> offsetType; - - time_t tzt = 0; - if (offsetType != 'Z' && !tzss.fail()) - { - std::tm tzm = {}; - tzss >> std::get_time(&tzm, "%H:%M"); - if (!tzss.fail()) - { - tzt = (tzm.tm_hour * 60 * 60) + (tzm.tm_min * 60) + tzm.tm_sec; - if (offsetType == '-') - { - tzt = -tzt; - } - } - } - - if (tzss.fail()) - { - return false; - } - -#ifdef _WIN32 - const time_t utct = _mkgmtime(&utcTm) - tzt; - localtime_s(<, &utct); -#else - const time_t utct = timegm(&utcTm) - tzt; - localtime_r(&utct, <); -#endif - - return true; + if (alignType.compare("center") == 0) + return "Qt.AlignVCenter"; + else if (alignType.compare("bottom") == 0) + return "Qt.AlignBottom"; + else + return "Qt.AlignTop"; } } // namespace AdaptiveCardQmlEngine diff --git a/source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.h b/source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.h index d9a3ecd835..bd79cd84f4 100644 --- a/source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.h +++ b/source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.h @@ -16,39 +16,12 @@ namespace AdaptiveCardQmlEngine static const std::string handleEscapeSequences(std::string& text); static const std::string formatHtmlUrl(std::string& text, const std::string& linkColor, const std::string& textDecoration); static std::vector splitString(const std::string& string, char delimiter); - static std::string& replace(std::string& str, char what, char with); - - template - static bool IsInstanceOfSmart(U u); - - template - static bool IsInstanceOf(U u); + static std::string GetHorizontalAlignment(std::string alignType); + static std::string GetVerticalAlignment(std::string alignType); + private: Utils() {} }; - template - inline bool Utils::IsInstanceOfSmart(U u) - { - return std::dynamic_pointer_cast(u) != nullptr; - } - - template - inline bool Utils::IsInstanceOf(U u) - { - return dynamic_cast(u) != nullptr; - } - - class TextUtils - { - public: - static std::string applyTextFunctions(const std::string& text, const std::string& lang); - static std::locale getValidCultureInfo(const std::string& lang); - static bool getLocalTime(const std::string& tzOffset, std::tm& tm, std::tm& lt); - - private: - static std::regex m_textFunctionRegex; - }; - -} // namespace AdaptiveCardQmlEngine +} // namespace AdaptiveCardQmlEngine