Skip to content

Base Adaptive Card property #422

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 24 additions & 13 deletions source/qml_v2/AdaptiveCardQmlEngine/AdaptiveCardContext.cpp
Original file line number Diff line number Diff line change
@@ -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<AdaptiveCardQmlEngine::AdaptiveCardConfig>(true);
mHostConfig = std::make_shared<AdaptiveCards::HostConfig>(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<AdaptiveCardConfig>(mAdaptiveCardTheme == AdaptiveCardEnums::AdaptiveCardTheme::DarkTheme ? true : false);

if (mAdaptiveCardTheme == AdaptiveCardEnums::AdaptiveCardTheme::DarkTheme)
{
mHostConfig = std::make_shared<AdaptiveCards::HostConfig>(AdaptiveCards::HostConfig::DeserializeFromString(DarkConfig::darkConfig));
}
mHostConfig =
std::make_shared<AdaptiveCards::HostConfig>(AdaptiveCards::HostConfig::DeserializeFromString(DarkConfig::darkConfig));
}
else
{
mHostConfig = std::make_shared<AdaptiveCards::HostConfig>(AdaptiveCards::HostConfig::DeserializeFromString(LightConfig::lightConfig));
}
mHostConfig = std::make_shared<AdaptiveCards::HostConfig>(
AdaptiveCards::HostConfig::DeserializeFromString(LightConfig::lightConfig));
}
}


std::shared_ptr<AdaptiveCards::HostConfig> 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

4 changes: 4 additions & 0 deletions source/qml_v2/AdaptiveCardQmlEngine/AdaptiveCardContext.h
Original file line number Diff line number Diff line change
@@ -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<AdaptiveCards::HostConfig> mHostConfig;
std::shared_ptr<AdaptiveCardConfig> mCardConfig;
AdaptiveCardEnums::AdaptiveCardTheme mAdaptiveCardTheme;
std::string m_lang;
};
}
4 changes: 3 additions & 1 deletion source/qml_v2/AdaptiveCardQmlEngine/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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
Binary file added source/qml_v2/AdaptiveCardQmlEngine/images/1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
73 changes: 69 additions & 4 deletions source/qml_v2/AdaptiveCardQmlEngine/models/AdaptiveCardModel.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
#include "AdaptiveCardModel.h"

#include "Enums.h"

AdaptiveCardModel::AdaptiveCardModel(std::shared_ptr<AdaptiveCards::AdaptiveCard> 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;
}
17 changes: 15 additions & 2 deletions source/qml_v2/AdaptiveCardQmlEngine/models/AdaptiveCardModel.h
Original file line number Diff line number Diff line change
@@ -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<AdaptiveCards::AdaptiveCard> 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<AdaptiveCards::AdaptiveCard> mMainCard;
11 changes: 11 additions & 0 deletions source/qml_v2/AdaptiveCardQmlEngine/models/CollectionItemModel.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "CollectionItemModel.h"
#include "TextBlockModel.h"
#include "RichTextBlockModel.h"
#include "AdaptiveCardEnums.h"

CollectionItemModel::CollectionItemModel(std::vector<std::shared_ptr<AdaptiveCards::BaseCardElement>> elements, QObject* parent)
@@ -39,6 +40,7 @@ QHash<int, QByteArray> CollectionItemModel::roleNames() const
QHash<int, QByteArray> 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<AdaptiveCards::BaseCar
case AdaptiveCards::CardElementType::TextBlock:
populateTextBlockModel(std::dynamic_pointer_cast<AdaptiveCards::TextBlock>(element), rowContent);
break;
case AdaptiveCards::CardElementType::RichTextBlock:
populateRichTextBlockModel(std::dynamic_pointer_cast<AdaptiveCards::RichTextBlock>(element), rowContent);
break;
default:
break;
}
@@ -66,3 +71,9 @@ void CollectionItemModel::populateTextBlockModel(std::shared_ptr<AdaptiveCards::
rowContent[CollectionModelRole::DelegateType] = QVariant::fromValue(AdaptiveCardEnums::CardElementType::TextBlock);
rowContent[CollectionModelRole::TextBlockRole] = QVariant::fromValue(new TextBlockModel(textBlock, nullptr));
}

void CollectionItemModel::populateRichTextBlockModel(std::shared_ptr<AdaptiveCards::RichTextBlock> richTextBlock, RowContent& rowContent)
{
rowContent[CollectionModelRole::DelegateType] = QVariant::fromValue(AdaptiveCardEnums::CardElementType::RichTextBlock);
rowContent[CollectionModelRole::RichTextBlockRole] = QVariant::fromValue(new RichTextBlockModel(richTextBlock, nullptr));
}
13 changes: 9 additions & 4 deletions source/qml_v2/AdaptiveCardQmlEngine/models/CollectionItemModel.h
Original file line number Diff line number Diff line change
@@ -4,23 +4,27 @@
#include <SharedAdaptiveCard.h>

#include <TextBlock.h>
#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<int, QVariant>;
using RowContent = std::unordered_map<int, QVariant>;

explicit CollectionItemModel(std::vector<std::shared_ptr<AdaptiveCards::BaseCardElement>> elements, QObject* parent = nullptr);
~CollectionItemModel();
@@ -36,4 +40,5 @@ class CollectionItemModel : public QAbstractListModel
private:
void populateRowData(std::shared_ptr<AdaptiveCards::BaseCardElement> element);
void populateTextBlockModel(std::shared_ptr<AdaptiveCards::TextBlock> textBlock, RowContent& rowContent);
void populateRichTextBlockModel(std::shared_ptr<AdaptiveCards::RichTextBlock> rightTextBlock, RowContent& rowContent);
};
116 changes: 116 additions & 0 deletions source/qml_v2/AdaptiveCardQmlEngine/models/RichTextBlockModel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#include "RichTextBlockModel.h"
#include "SharedAdaptiveCard.h"
#include <QDebug.h>
#include "Utils.h"
#include "MarkDownParser.h"

RichTextBlockModel::RichTextBlockModel(std::shared_ptr<AdaptiveCards::RichTextBlock> 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<AdaptiveCards::TextRun>(inlineRun))
{
std::string selectActionId = "";
auto textRun = std::dynamic_pointer_cast<AdaptiveCards::TextRun>(inlineRun);
textrun_all.append(textRunRender(textRun, selectActionId));
}
}

mText = textrun_all;
mTextHorizontalAlignment = static_cast<int>(hAlignmentValue);
}

QString RichTextBlockModel::textRunRender(const std::shared_ptr<AdaptiveCards::TextRun>& 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 = "<span style='";
uiTextRun.append(QString("font-family:") + QString("\\\"") + fontFamily + QString("\\\"") + QString(";"));
uiTextRun.append(QString("color:") + color + QString(";"));
uiTextRun.append(QString("font-size:") + QString::number(fontSize) + QString("px") + QString(";"));
uiTextRun.append(QString("font-weight:") + QString::number(weight) + QString(";"));

if (textRun->GetHighlight())
{
uiTextRun.append("background-color:" + QString("yellow")) + ";" ;
}

if (textRun->GetItalic())
{
uiTextRun.append("font-style:").append("italic").append(";");
}

if (textRun->GetUnderline())
{
uiTextRun.append("text-decoration:").append("underline").append(";");
}

if (textRun->GetStrikethrough())
{
uiTextRun.append("text-decoration:").append("line-through").append(";");
}

uiTextRun.append("'>");

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("<a href='" + QString::fromStdString(selectaction) + "'" + styleString + " >");
uiTextRun.append(QString::fromStdString(text));
uiTextRun.append("</a>");
}
else
{
uiTextRun.append(QString::fromStdString(text));
}
uiTextRun.append("</span>");

return uiTextRun;
}

RichTextBlockModel::~RichTextBlockModel()
{
}
69 changes: 69 additions & 0 deletions source/qml_v2/AdaptiveCardQmlEngine/models/RichTextBlockModel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#pragma once

#include <QObject>
#include <QColor>
#include <QFont>

#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<AdaptiveCards::RichTextBlock> richTextBlock, QObject* parent = nullptr);
~RichTextBlockModel();

private:
QString textRunRender (
const std::shared_ptr<AdaptiveCards::TextRun>& 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;
};
35 changes: 28 additions & 7 deletions source/qml_v2/AdaptiveCardQmlEngine/qml/AdaptiveCard.qml
Original file line number Diff line number Diff line change
@@ -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: {
28 changes: 28 additions & 0 deletions source/qml_v2/AdaptiveCardQmlEngine/qml/RichTextBlockRender.qml
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
@@ -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
}
1 change: 1 addition & 0 deletions source/qml_v2/AdaptiveCardQmlEngine/resourceEngine.qrc
Original file line number Diff line number Diff line change
@@ -9,5 +9,6 @@
<file>qml/JSUtils/AdaptiveCardUtils.js</file>
<file>qml/JSUtils/ThemeUtils.js</file>
<file>qml/CardConstants.qml</file>
<file>images/1.jpg</file>
</qresource>
</RCC>
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ namespace AdaptiveCardEnums
enum class CardElementType {
AdaptiveCard,
TextBlock,
RichTextBlock,
Container,
Column,
ColumnSet,
120 changes: 14 additions & 106 deletions source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.cpp
Original file line number Diff line number Diff line change
@@ -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(&lt, 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(&lt, &utct);
#else
const time_t utct = timegm(&utcTm) - tzt;
localtime_r(&utct, &lt);
#endif
return true;
}
*/


} // namespace AdaptiveCardQmlEngine


16 changes: 3 additions & 13 deletions source/qml_v2/AdaptiveCardQmlEngine/utils/Utils.h
Original file line number Diff line number Diff line change
@@ -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<std::string> 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