diff --git a/source/qml_v2/AdaptiveCardQmlEngine/AdaptiveCardContext.cpp b/source/qml_v2/AdaptiveCardQmlEngine/AdaptiveCardContext.cpp index ce33161189..ad5478ce0a 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,7 +13,7 @@ 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)); } @@ -23,20 +22,21 @@ namespace AdaptiveCardQmlEngine { mAdaptiveCardTheme = theme; - // ReInitializing AdaptiveCard and Host config + // 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; @@ -49,7 +49,7 @@ namespace AdaptiveCardQmlEngine 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 +73,8 @@ namespace AdaptiveCardQmlEngine default: if (mAdaptiveCardTheme == AdaptiveCardEnums::AdaptiveCardTheme::DarkTheme) { - colorConfig = mRenderArgs.GetForegroundColors().light; - } + colorConfig = mRenderArgs.GetForegroundColors().light; + } break; } @@ -88,6 +88,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/images/1.jpg b/source/qml_v2/AdaptiveCardQmlEngine/images/1.jpg new file mode 100644 index 0000000000..2703578c63 Binary files /dev/null and b/source/qml_v2/AdaptiveCardQmlEngine/images/1.jpg differ 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/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/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/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..b4f44fbfa2 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 + images/1.jpg 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..749259e10a 100644 --- a/source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.cpp +++ b/source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.cpp @@ -86,118 +86,26 @@ namespace AdaptiveCardQmlEngine return splitElements; } - //------------------------------------------------------------------------------------------------------- - - /* - std::string TextUtils::applyTextFunctions(const std::string& text, const std::string& lang) + std::string Utils::GetHorizontalAlignment(std::string alignType) { - 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; + if (alignType.compare("center") == 0) + return "Qt.AlignHCenter"; + else if (alignType.compare("right") == 0) + return "Qt.AlignRight"; + else + return "Qt.AlignLeft"; } - std::locale TextUtils::getValidCultureInfo(const std::string& lang) + std::string Utils::GetVerticalAlignment(std::string alignType) { - return std::locale("en_US"); + if (alignType.compare("center") == 0) + return "Qt.AlignVCenter"; + else if (alignType.compare("bottom") == 0) + return "Qt.AlignBottom"; + else + return "Qt.AlignTop"; } - 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; - } - */ - - } // namespace AdaptiveCardQmlEngine diff --git a/source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.h b/source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.h index dce5bee5f3..bd79cd84f4 100644 --- a/source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.h +++ b/source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.h @@ -16,22 +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 GetHorizontalAlignment(std::string alignType); + static std::string GetVerticalAlignment(std::string alignType); private: Utils() {} }; - /* - 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