Merge pull request #2007 from aws-lumberyard-dev/daimini/NewsBuilder/removal
Remove NewsBuilder project from Editor solution.
This commit is contained in:
@@ -111,7 +111,6 @@ ly_add_target(
|
||||
AZ::AzCore
|
||||
AZ::AzToolsFramework
|
||||
Gem::LmbrCentral.Static
|
||||
Legacy::NewsShared
|
||||
AZ::AWSNativeSDKInit
|
||||
AZ::AtomCore
|
||||
Gem::Atom_RPI.Edit
|
||||
|
||||
@@ -40,10 +40,6 @@
|
||||
#include "CryEdit.h"
|
||||
#include "LevelFileDialog.h"
|
||||
|
||||
// NewsShared
|
||||
#include <NewsShared/ResourceManagement/ResourceManifest.h> // for News::ResourceManifest
|
||||
#include <NewsShared/Qt/ArticleViewContainer.h> // for News::ArticleViewContainer
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
#include <WelcomeScreen/ui_WelcomeScreenDialog.h>
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QDialog>
|
||||
#include "NewsShared/LogType.h"
|
||||
#include "NewsShared/ErrorCodes.h"
|
||||
#endif
|
||||
|
||||
namespace News {
|
||||
@@ -62,9 +60,6 @@ private:
|
||||
void OnRecentLevelTableItemClicked(const QModelIndex& index);
|
||||
void OnCloseBtnClicked(bool checked);
|
||||
|
||||
void SyncFail(News::ErrorCode error);
|
||||
void SyncSuccess();
|
||||
|
||||
private Q_SLOTS:
|
||||
void previewAreaScrolled();
|
||||
};
|
||||
|
||||
@@ -10,7 +10,6 @@ add_subdirectory(AssetProcessor)
|
||||
add_subdirectory(AWSNativeSDKInit)
|
||||
add_subdirectory(AzTestRunner)
|
||||
add_subdirectory(CrashHandler)
|
||||
add_subdirectory(News)
|
||||
add_subdirectory(PythonBindingsExample)
|
||||
add_subdirectory(RemoteConsole)
|
||||
add_subdirectory(DeltaCataloger)
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
#
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
#
|
||||
|
||||
add_subdirectory(NewsBuilder)
|
||||
|
||||
if (NOT PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
return()
|
||||
endif()
|
||||
|
||||
ly_add_target(
|
||||
NAME NewsShared STATIC
|
||||
NAMESPACE Legacy
|
||||
AUTOMOC
|
||||
AUTOUIC
|
||||
AUTORCC
|
||||
FILES_CMAKE
|
||||
news_shared_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PUBLIC
|
||||
.
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
3rdParty::Qt::Core
|
||||
3rdParty::Qt::Network
|
||||
3rdParty::Qt::Widgets
|
||||
AZ::AzQtComponents
|
||||
)
|
||||
@@ -1,38 +0,0 @@
|
||||
#
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
#
|
||||
|
||||
ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME})
|
||||
|
||||
include(${pal_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake)
|
||||
|
||||
if (NOT PAL_TRAIT_BUILD_NEWSBUILDER_SUPPORTED OR NOT PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
return()
|
||||
endif()
|
||||
|
||||
ly_add_target(
|
||||
NAME NewsBuilder EXECUTABLE
|
||||
NAMESPACE Legacy
|
||||
AUTOMOC
|
||||
AUTOUIC
|
||||
AUTORCC
|
||||
FILES_CMAKE
|
||||
news_builder_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PUBLIC
|
||||
.
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
3rdParty::Qt::Core
|
||||
3rdParty::Qt::Widgets
|
||||
3rdParty::AWSNativeSDK::Dependencies
|
||||
3rdParty::AWSNativeSDK::Core
|
||||
3rdParty::AWSNativeSDK::S3
|
||||
Legacy::NewsShared
|
||||
AZ::AzCore
|
||||
AZ::AzQtComponents
|
||||
AZ::AzFramework
|
||||
)
|
||||
@@ -1,212 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "EndpointManager.h"
|
||||
#include <NewsShared/ResourceManagement/ResourceManifest.h>
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QCoreApplication>
|
||||
|
||||
namespace News
|
||||
{
|
||||
|
||||
Endpoint::Endpoint(QString name, QString awsProfile, QString url, QString bucket)
|
||||
: m_name(name)
|
||||
, m_awsProfile(awsProfile)
|
||||
, m_url(url)
|
||||
, m_bucket(bucket)
|
||||
{}
|
||||
|
||||
Endpoint::Endpoint(const QJsonObject& json)
|
||||
: Endpoint(json["name"].toString(),
|
||||
json["awsProfile"].toString(),
|
||||
json["url"].toString(),
|
||||
json["bucket"].toString())
|
||||
{
|
||||
}
|
||||
|
||||
Endpoint::~Endpoint() {}
|
||||
|
||||
void Endpoint::Write(QJsonObject& json) const
|
||||
{
|
||||
json["name"] = m_name;
|
||||
json["awsProfile"] = m_awsProfile;
|
||||
json["url"] = m_url;
|
||||
json["bucket"] = m_bucket;
|
||||
}
|
||||
|
||||
QString Endpoint::GetName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void Endpoint::SetName(const QString& name)
|
||||
{
|
||||
m_name = QString(name);
|
||||
}
|
||||
|
||||
QString Endpoint::GetAwsProfile() const
|
||||
{
|
||||
return m_awsProfile;
|
||||
}
|
||||
|
||||
void Endpoint::SetAwsProfile(const QString& awsProfile)
|
||||
{
|
||||
m_awsProfile = QString(awsProfile);
|
||||
}
|
||||
|
||||
QString Endpoint::GetUrl() const
|
||||
{
|
||||
return m_url;
|
||||
}
|
||||
|
||||
void Endpoint::SetUrl(const QString& url)
|
||||
{
|
||||
m_url = QString(url);
|
||||
}
|
||||
|
||||
QString Endpoint::GetBucket() const
|
||||
{
|
||||
return m_bucket;
|
||||
}
|
||||
|
||||
void Endpoint::SetBucket(const QString& bucket)
|
||||
{
|
||||
m_bucket = bucket;
|
||||
}
|
||||
|
||||
EndpointManager::EndpointManager()
|
||||
{
|
||||
Load();
|
||||
}
|
||||
|
||||
EndpointManager::~EndpointManager()
|
||||
{
|
||||
ClearEndpoints();
|
||||
}
|
||||
|
||||
void EndpointManager::Load()
|
||||
{
|
||||
ClearEndpoints();
|
||||
QFile file("newsBuilderConfig.txt");
|
||||
if (file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
QTextStream in(&file);
|
||||
QString str = in.readAll().trimmed();
|
||||
QByteArray array(str.toStdString().c_str());
|
||||
QJsonDocument doc(QJsonDocument::fromJson(array));
|
||||
QJsonObject json = doc.object();
|
||||
QJsonArray endpointArray = json["endpoints"].toArray();
|
||||
for (auto endpointDoc : endpointArray)
|
||||
{
|
||||
m_endpoints.append(new Endpoint(endpointDoc.toObject()));
|
||||
}
|
||||
int endpointIndex = json["currentEndpointIndex"].toInt();
|
||||
if (endpointIndex >= 0 && m_endpoints.count() > endpointIndex)
|
||||
{
|
||||
m_selectedEndpoint = m_endpoints[endpointIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_selectedEndpoint = nullptr;
|
||||
}
|
||||
file.close();
|
||||
|
||||
SaveUrl();
|
||||
}
|
||||
}
|
||||
|
||||
void EndpointManager::Save()
|
||||
{
|
||||
QFile file("newsBuilderConfig.txt");
|
||||
if (file.open(QIODevice::WriteOnly))
|
||||
{
|
||||
QJsonObject json;
|
||||
QJsonArray endpointArray;
|
||||
for (auto endpoint : m_endpoints)
|
||||
{
|
||||
QJsonObject endpointObject;
|
||||
endpoint->Write(endpointObject);
|
||||
endpointArray.append(endpointObject);
|
||||
}
|
||||
json["endpoints"] = endpointArray;
|
||||
json["currentEndpointIndex"] = m_endpoints.indexOf(m_selectedEndpoint);
|
||||
QTextStream out(&file);
|
||||
QJsonDocument doc(json);
|
||||
out << doc.toJson(QJsonDocument::Compact);
|
||||
file.close();
|
||||
|
||||
SaveUrl();
|
||||
}
|
||||
}
|
||||
|
||||
void EndpointManager::SelectEndpoint(Endpoint* endpoint)
|
||||
{
|
||||
m_selectedEndpoint = endpoint;
|
||||
}
|
||||
|
||||
void EndpointManager::AddEndpoint(Endpoint* endpoint)
|
||||
{
|
||||
m_endpoints.append(endpoint);
|
||||
}
|
||||
|
||||
void EndpointManager::RemoveEndpoint(Endpoint* endpoint)
|
||||
{
|
||||
if (endpoint == m_selectedEndpoint)
|
||||
{
|
||||
m_selectedEndpoint = nullptr;
|
||||
}
|
||||
m_endpoints.removeAll(endpoint);
|
||||
delete endpoint;
|
||||
}
|
||||
|
||||
Endpoint* EndpointManager::GetSelectedEndpoint() const
|
||||
{
|
||||
return m_selectedEndpoint;
|
||||
}
|
||||
|
||||
QList<Endpoint*>::const_iterator EndpointManager::begin() const
|
||||
{
|
||||
return m_endpoints.begin();
|
||||
}
|
||||
|
||||
QList<Endpoint*>::const_iterator EndpointManager::end() const
|
||||
{
|
||||
return m_endpoints.end();
|
||||
}
|
||||
|
||||
void EndpointManager::ClearEndpoints()
|
||||
{
|
||||
for (auto endpoint : m_endpoints)
|
||||
{
|
||||
delete endpoint;
|
||||
}
|
||||
m_endpoints.clear();
|
||||
}
|
||||
|
||||
void EndpointManager::SaveUrl() const
|
||||
{
|
||||
if (!m_selectedEndpoint)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Editor looks for config file in /dev folder, so this file is placed in parent directory
|
||||
QFile file(QCoreApplication::applicationDirPath() + "/newsConfig.txt");
|
||||
if (file.open(QIODevice::WriteOnly))
|
||||
{
|
||||
QTextStream out(&file);
|
||||
out << m_selectedEndpoint->GetUrl();
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QList>
|
||||
#include <qobjectdefs.h>
|
||||
|
||||
class QJsonObject;
|
||||
|
||||
namespace News
|
||||
{
|
||||
//! Endpoint represents a location of news data
|
||||
class Endpoint
|
||||
{
|
||||
public:
|
||||
Endpoint(QString name, QString awsProfile, QString url, QString bucket);
|
||||
explicit Endpoint(const QJsonObject& json);
|
||||
~Endpoint();
|
||||
|
||||
void Write(QJsonObject& json) const;
|
||||
|
||||
QString GetName() const;
|
||||
void SetName(const QString& name);
|
||||
|
||||
QString GetAwsProfile() const;
|
||||
void SetAwsProfile(const QString& awsProfile);
|
||||
|
||||
QString GetUrl() const;
|
||||
void SetUrl(const QString& url);
|
||||
|
||||
QString GetBucket() const;
|
||||
void SetBucket(const QString& bucket);
|
||||
|
||||
private:
|
||||
//! name of endpoint to distinguish with others
|
||||
QString m_name;
|
||||
//! name of aws credentials file
|
||||
QString m_awsProfile;
|
||||
//! url location of news data (e.g. cloudfront url)
|
||||
QString m_url;
|
||||
//! name of s3 bucket where news data resides
|
||||
QString m_bucket;
|
||||
};
|
||||
|
||||
//! EndpointManager handles endpoint collection
|
||||
class EndpointManager
|
||||
{
|
||||
public:
|
||||
EndpointManager();
|
||||
~EndpointManager();
|
||||
|
||||
//! Load endpoints file
|
||||
void Load();
|
||||
//! Save endpoints file
|
||||
void Save();
|
||||
void SelectEndpoint(Endpoint* endpoint);
|
||||
void AddEndpoint(Endpoint* endpoint);
|
||||
void RemoveEndpoint(Endpoint* endpoint);
|
||||
Endpoint* GetSelectedEndpoint() const;
|
||||
|
||||
QList<Endpoint*>::const_iterator begin() const;
|
||||
QList<Endpoint*>::const_iterator end() const;
|
||||
|
||||
private:
|
||||
QList<Endpoint*> m_endpoints;
|
||||
Endpoint* m_selectedEndpoint = nullptr;
|
||||
|
||||
void ClearEndpoints();
|
||||
//! Saves news config file which is used by LY Editor to determine news location
|
||||
void SaveUrl() const;
|
||||
};
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
#
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
#
|
||||
|
||||
set(PAL_TRAIT_BUILD_NEWSBUILDER_SUPPORTED FALSE)
|
||||
@@ -1,8 +0,0 @@
|
||||
#
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
#
|
||||
|
||||
set(PAL_TRAIT_BUILD_NEWSBUILDER_SUPPORTED FALSE)
|
||||
@@ -1,8 +0,0 @@
|
||||
#
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
#
|
||||
|
||||
set(PAL_TRAIT_BUILD_NEWSBUILDER_SUPPORTED FALSE)
|
||||
@@ -1,8 +0,0 @@
|
||||
#
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
#
|
||||
|
||||
set(PAL_TRAIT_BUILD_NEWSBUILDER_SUPPORTED TRUE)
|
||||
@@ -1,8 +0,0 @@
|
||||
#
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
#
|
||||
|
||||
set(PAL_TRAIT_BUILD_NEWSBUILDER_SUPPORTED FALSE)
|
||||
@@ -1,295 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ArticleDetails.h"
|
||||
#include "SelectImage.h"
|
||||
#include <NewsShared/ResourceManagement/Resource.h>
|
||||
#include "ResourceManagement/BuilderResourceManifest.h"
|
||||
#include "ResourceManagement/ImageDescriptor.h"
|
||||
#include "NewsShared/ErrorCodes.h"
|
||||
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
|
||||
#include <QButtonGroup>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QTimer>
|
||||
|
||||
#include "Qt/ui_ArticleDetails.h"
|
||||
|
||||
namespace News
|
||||
{
|
||||
|
||||
ArticleDetails::ArticleDetails(QWidget* parent,
|
||||
Resource& resource,
|
||||
BuilderResourceManifest& manifest)
|
||||
: QWidget(parent)
|
||||
, m_ui(new Ui::ArticleDetailsWidget)
|
||||
, m_filename("")
|
||||
, m_article(resource)
|
||||
, m_manifest(manifest)
|
||||
, m_imageIdOriginal("")
|
||||
, m_imageId("")
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
m_ui->uidLabel->setText(QString("Article: %1").arg(m_article.GetResource().GetId()));
|
||||
|
||||
resizePreviewImage();
|
||||
|
||||
//! try to load image icon
|
||||
auto pImageResource = m_manifest.FindById(m_article.GetImageId());
|
||||
if (pImageResource)
|
||||
{
|
||||
m_imageIdOriginal = pImageResource->GetId();
|
||||
SetImage(*pImageResource);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetNoImage();
|
||||
}
|
||||
|
||||
m_ui->titleText->setText(m_article.GetTitle());
|
||||
m_ui->descriptionText->setPlainText(m_article.GetBody());
|
||||
|
||||
connect(m_ui->fromFileButton, &QPushButton::clicked, this, &ArticleDetails::OpenImageFromFile);
|
||||
connect(m_ui->fromResourceButton, &QPushButton::clicked, this, &ArticleDetails::OpenImageFromResource);
|
||||
connect(m_ui->clearImageButton, &QPushButton::clicked, this, &ArticleDetails::ClearImage);
|
||||
connect(m_ui->updateButton, &QPushButton::clicked, this, &ArticleDetails::UpdateArticle);
|
||||
connect(m_ui->deleteButton, &QPushButton::clicked, this, &ArticleDetails::DeleteArticle);
|
||||
connect(m_ui->cancelButton, &QPushButton::clicked, this, &ArticleDetails::Close);
|
||||
connect(m_ui->upButton, &QPushButton::clicked, this, &ArticleDetails::MoveUp);
|
||||
connect(m_ui->downButton, &QPushButton::clicked, this, &ArticleDetails::MoveDown);
|
||||
}
|
||||
|
||||
ArticleDetails::~ArticleDetails() {}
|
||||
|
||||
void ArticleDetails::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
QWidget::resizeEvent(event);
|
||||
resizePreviewImage();
|
||||
}
|
||||
|
||||
void ArticleDetails::resizePreviewImage()
|
||||
{
|
||||
// Resize the imagePreview to keep the proportions
|
||||
int newHeight = aznumeric_cast<int>(m_imageRatio * width());
|
||||
m_ui->imagePreview->setFixedHeight(newHeight);
|
||||
}
|
||||
|
||||
ArticleDescriptor& ArticleDetails::GetArticle()
|
||||
{
|
||||
return m_article;
|
||||
}
|
||||
|
||||
QString ArticleDetails::GetId() const
|
||||
{
|
||||
return m_article.GetResource().GetId();
|
||||
}
|
||||
|
||||
void ArticleDetails::OpenImageFromFile()
|
||||
{
|
||||
m_filename = QFileDialog::getOpenFileName(this,
|
||||
"Open Image", ".", "Image Files (*.png *.jpg *.bmp)");
|
||||
SetImage(m_filename);
|
||||
}
|
||||
|
||||
void ArticleDetails::OpenImageFromResource()
|
||||
{
|
||||
m_pSelectImage = new SelectImage(m_manifest);
|
||||
if (m_pSelectImage->exec() == QDialog::DialogCode::Accepted)
|
||||
{
|
||||
auto pSelectedResource = m_pSelectImage->GetSelected();
|
||||
if (!pSelectedResource)
|
||||
{
|
||||
QMessageBox msgBox(QMessageBox::Critical,
|
||||
"Error",
|
||||
"No resource pSelectedResource",
|
||||
QMessageBox::Ok,
|
||||
this);
|
||||
msgBox.exec();
|
||||
return;
|
||||
}
|
||||
SetImage(*pSelectedResource);
|
||||
}
|
||||
delete m_pSelectImage;
|
||||
}
|
||||
|
||||
//! once the Update button is clicked, article resource is updated in this function
|
||||
void ArticleDetails::UpdateArticle()
|
||||
{
|
||||
//! this flag remains false if no new changes are detected, thus avoiding unnecessary
|
||||
//! re-uploading unchanged resources
|
||||
bool updated = false;
|
||||
|
||||
m_imageId = LoadImage();
|
||||
if (m_imageId.compare(m_imageIdOriginal) != 0)
|
||||
{
|
||||
m_article.SetImageId(m_imageId);
|
||||
m_filename = "";
|
||||
m_imageIdOriginal = m_imageId;
|
||||
m_ui->imagePathLabel->setText(QString("Image: %1").arg(m_imageId));
|
||||
updated = true;
|
||||
}
|
||||
|
||||
QString newTitle = m_ui->titleText->text();
|
||||
if (m_article.GetTitle().compare(newTitle))
|
||||
{
|
||||
m_article.SetTitle(newTitle);
|
||||
updated = true;
|
||||
}
|
||||
QString newBody = m_ui->descriptionText->toPlainText();
|
||||
if (m_article.GetBody().compare(newBody) != 0)
|
||||
{
|
||||
m_article.SetBody(newBody);
|
||||
updated = true;
|
||||
}
|
||||
|
||||
QString newStyle = m_ui->articleStyleButtonGroup->checkedButton()->property("style").toString();
|
||||
if (m_article.GetArticleStyle() != newStyle)
|
||||
{
|
||||
m_article.SetArticleStyle(newStyle);
|
||||
updated = true;
|
||||
}
|
||||
|
||||
if (updated)
|
||||
{
|
||||
m_article.Update();
|
||||
m_manifest.UpdateResource(&m_article.GetResource());
|
||||
emit logSignal(QString("Article %1 updated")
|
||||
.arg(m_article.GetResource().GetId()), LogOk);
|
||||
}
|
||||
else
|
||||
{
|
||||
emit logSignal("Nothing to update", LogWarning);
|
||||
}
|
||||
emit updateArticleSignal();
|
||||
}
|
||||
|
||||
//! try to load an image either from filename or from another resource,
|
||||
//! update resource manifest accordingly
|
||||
QString ArticleDetails::LoadImage() const
|
||||
{
|
||||
if (!m_filename.isEmpty())
|
||||
{
|
||||
if (!m_imageIdOriginal.isEmpty())
|
||||
{
|
||||
m_manifest.FreeResource(m_imageIdOriginal);
|
||||
}
|
||||
auto pResource = m_manifest.AddImage(m_filename);
|
||||
if (pResource)
|
||||
{
|
||||
return pResource->GetId();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
if (m_imageId.compare(m_imageIdOriginal) != 0)
|
||||
{
|
||||
if (!m_imageIdOriginal.isEmpty())
|
||||
{
|
||||
m_manifest.FreeResource(m_imageIdOriginal);
|
||||
}
|
||||
if (!m_imageId.isEmpty())
|
||||
{
|
||||
m_manifest.UseResource(m_imageId);
|
||||
}
|
||||
return m_imageId;
|
||||
}
|
||||
|
||||
return m_imageIdOriginal;
|
||||
}
|
||||
|
||||
void ArticleDetails::SetImage(Resource& resource)
|
||||
{
|
||||
m_ui->imagePathLabel->setText(QString("Image: %1").arg(resource.GetId()));
|
||||
|
||||
QPixmap pixmap;
|
||||
if (pixmap.loadFromData(resource.GetData()))
|
||||
{
|
||||
m_ui->imagePreview->setPixmap(pixmap);
|
||||
m_imageId = resource.GetId();
|
||||
}
|
||||
else
|
||||
{
|
||||
SetNoImage();
|
||||
emit logSignal(QString("Failed to load image: %1.").arg(m_imageId));
|
||||
}
|
||||
}
|
||||
|
||||
void ArticleDetails::SetImage([[maybe_unused]] QString& filename)
|
||||
{
|
||||
m_ui->imagePathLabel->setText(QString("Image: %1").arg(m_filename));
|
||||
|
||||
QPixmap pixmap;
|
||||
if (pixmap.load(m_filename))
|
||||
{
|
||||
m_ui->imagePreview->setPixmap(pixmap);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetNoImage();
|
||||
emit logSignal(QString("Failed to load image: %1.").arg(m_filename));
|
||||
}
|
||||
}
|
||||
|
||||
void ArticleDetails::SetNoImage() const
|
||||
{
|
||||
m_ui->imagePreview->setPixmap(QPixmap(":/images/Resources/missing-image.png"));
|
||||
m_ui->imagePathLabel->setText("no image");
|
||||
}
|
||||
|
||||
void ArticleDetails::ClearImage()
|
||||
{
|
||||
m_imageId = "";
|
||||
m_filename = "";
|
||||
SetNoImage();
|
||||
}
|
||||
|
||||
void ArticleDetails::DeleteArticle()
|
||||
{
|
||||
if (!m_article.GetImageId().isEmpty())
|
||||
{
|
||||
m_manifest.FreeResource(m_article.GetImageId());
|
||||
}
|
||||
m_manifest.FreeResource(m_article.GetResource().GetId());
|
||||
emit deleteArticleSignal();
|
||||
}
|
||||
|
||||
void ArticleDetails::Close()
|
||||
{
|
||||
emit closeArticleSignal();
|
||||
}
|
||||
|
||||
void ArticleDetails::MoveUp()
|
||||
{
|
||||
ErrorCode error;
|
||||
if (!m_manifest.UpdateArticleOrder(m_article.GetResource().GetId(), 1, error))
|
||||
{
|
||||
emit logSignal(GetErrorMessage(error));
|
||||
}
|
||||
else
|
||||
{
|
||||
emit orderChangedSignal(m_article.GetResource().GetId(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
void ArticleDetails::MoveDown()
|
||||
{
|
||||
ErrorCode error;
|
||||
if (!m_manifest.UpdateArticleOrder(m_article.GetResource().GetId(), 0, error))
|
||||
{
|
||||
emit logSignal(GetErrorMessage(error));
|
||||
}
|
||||
else
|
||||
{
|
||||
emit orderChangedSignal(m_article.GetResource().GetId(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
#include "Qt/moc_ArticleDetails.cpp"
|
||||
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <NewsShared/ResourceManagement/ArticleDescriptor.h>
|
||||
#include "ResourceManagement/BuilderResourceManifest.h"
|
||||
|
||||
#include <QWidget>
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class ArticleDetailsWidget;
|
||||
}
|
||||
|
||||
namespace News {
|
||||
class SelectImage;
|
||||
class ResourceManifest;
|
||||
class Resource;
|
||||
|
||||
//! Control that allows to modify all parameters of a single article
|
||||
class ArticleDetails
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ArticleDetails(QWidget* parent,
|
||||
Resource& resource,
|
||||
BuilderResourceManifest& manifest);
|
||||
~ArticleDetails();
|
||||
ArticleDescriptor& GetArticle();
|
||||
QString GetId() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void logSignal(QString text, LogType logType = LogInfo);
|
||||
void deleteArticleSignal();
|
||||
void updateArticleSignal();
|
||||
void closeArticleSignal();
|
||||
void orderChangedSignal(QString id, bool direction);
|
||||
|
||||
private:
|
||||
QScopedPointer<Ui::ArticleDetailsWidget> m_ui;
|
||||
QString m_filename;
|
||||
ArticleDescriptor m_article;
|
||||
BuilderResourceManifest& m_manifest;
|
||||
SelectImage* m_pSelectImage;
|
||||
QString m_imageIdOriginal;
|
||||
QString m_imageId;
|
||||
float m_imageRatio = 184.0f / 430.0f;
|
||||
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
void resizePreviewImage();
|
||||
|
||||
void OpenImageFromFile();
|
||||
void OpenImageFromResource();
|
||||
QString LoadImage() const;
|
||||
void SetImage(Resource& resource);
|
||||
void SetImage(QString& filename);
|
||||
void SetNoImage() const;
|
||||
void ClearImage();
|
||||
|
||||
void UpdateArticle();
|
||||
void DeleteArticle();
|
||||
void Close();
|
||||
void MoveUp();
|
||||
void MoveDown();
|
||||
};
|
||||
} // namespace News
|
||||
@@ -1,406 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ArticleDetailsWidget</class>
|
||||
<widget class="QWidget" name="ArticleDetailsWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>250</width>
|
||||
<height>420</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>420</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>640</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWidget" name="globalLayout" native="true">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="AzQtComponents::ExtendedLabel" name="imagePreview">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="newsbuilder.qrc">:/images/Resources/missing-image.png</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="pixmapSize" stdset="0">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="imageLayout" native="true">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>140</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="imagePathLabel">
|
||||
<property name="text">
|
||||
<string>Image:</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="imageLayoutInner" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="clearImageButton">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Clear</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="fromResourceButton">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Library...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="fromFileButton">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Load...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="Title" native="true">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>1280</width>
|
||||
<height>1280</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="uidLabel">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Article: 0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="articleStyleLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="defaultStyleRadioButton">
|
||||
<property name="text">
|
||||
<string>Default Style</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="style" stdset="0">
|
||||
<string>default</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">articleStyleButtonGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="pinnedStyleRadioButton">
|
||||
<property name="text">
|
||||
<string>Pinned Style</string>
|
||||
</property>
|
||||
<property name="style" stdset="0">
|
||||
<string>pinned</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">articleStyleButtonGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Title:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="titleText">
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="Description">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Description:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="descriptionText"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="deleteButton">
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cancelButton">
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="updateButton">
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="upButton">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Move Up</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="downButton">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Move Down</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>AzQtComponents::ExtendedLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>AzQtComponents/Components/ExtendedLabel.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="newsbuilder.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
<buttongroups>
|
||||
<buttongroup name="articleStyleButtonGroup"/>
|
||||
</buttongroups>
|
||||
</ui>
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ArticleDetailsContainer.h"
|
||||
#include "ResourceManagement/BuilderResourceManifest.h"
|
||||
#include "ArticleDetails.h"
|
||||
#include "Qt/ui_ArticleDetailsContainer.h"
|
||||
|
||||
namespace News
|
||||
{
|
||||
|
||||
ArticleDetailsContainer::ArticleDetailsContainer(
|
||||
QWidget* parent,
|
||||
BuilderResourceManifest& manifest)
|
||||
: QWidget(parent)
|
||||
, m_ui(new Ui::ArticleDetailsContainerWidget)
|
||||
, m_manifest(manifest)
|
||||
, m_articleDetails(nullptr)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
}
|
||||
|
||||
ArticleDetailsContainer::~ArticleDetailsContainer() {}
|
||||
|
||||
//! When article is selected, old articleDetails control is removed, new one is created
|
||||
void ArticleDetailsContainer::SelectArticle(const QString& id)
|
||||
{
|
||||
closeArticleSlot();
|
||||
|
||||
if (!id.isEmpty())
|
||||
{
|
||||
auto article = m_manifest.FindById(id);
|
||||
if (article)
|
||||
{
|
||||
m_articleDetails = new ArticleDetails(
|
||||
m_ui->scrollAreaWidgetContents,
|
||||
*article,
|
||||
m_manifest);
|
||||
m_ui->scrollAreaWidgetContents->layout()->addWidget(m_articleDetails);
|
||||
connect(m_articleDetails, &ArticleDetails::updateArticleSignal,
|
||||
this, &ArticleDetailsContainer::updateArticleSlot);
|
||||
connect(m_articleDetails, &ArticleDetails::deleteArticleSignal,
|
||||
this, &ArticleDetailsContainer::deleteArticleSlot);
|
||||
connect(m_articleDetails, &ArticleDetails::closeArticleSignal,
|
||||
this, &ArticleDetailsContainer::closeArticleSlot);
|
||||
connect(m_articleDetails, SIGNAL(logSignal(QString, LogType)),
|
||||
this, SIGNAL(logSignal(QString, LogType)));
|
||||
connect(m_articleDetails, SIGNAL(orderChangedSignal(QString, bool)),
|
||||
this, SIGNAL(orderChangedSignal(QString, bool)));
|
||||
m_selectedId = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ArticleDetailsContainer::Reset()
|
||||
{
|
||||
SelectArticle(m_selectedId);
|
||||
}
|
||||
|
||||
void ArticleDetailsContainer::updateArticleSlot()
|
||||
{
|
||||
emit updateArticleSignal(m_articleDetails->GetId());
|
||||
}
|
||||
|
||||
void ArticleDetailsContainer::deleteArticleSlot()
|
||||
{
|
||||
emit deleteArticleSignal(m_articleDetails->GetId());
|
||||
closeArticleSlot();
|
||||
}
|
||||
|
||||
void ArticleDetailsContainer::closeArticleSlot()
|
||||
{
|
||||
if (m_articleDetails)
|
||||
{
|
||||
emit closeArticleSignal(m_selectedId);
|
||||
delete m_articleDetails;
|
||||
m_articleDetails = nullptr;
|
||||
m_selectedId = "";
|
||||
}
|
||||
}
|
||||
|
||||
#include "Qt/moc_ArticleDetailsContainer.cpp"
|
||||
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QWidget>
|
||||
#include <NewsShared/LogType.h>
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class ArticleDetailsContainerWidget;
|
||||
}
|
||||
|
||||
namespace News
|
||||
{
|
||||
class ArticleDetails;
|
||||
class BuilderResourceManifest;
|
||||
class SelectImage;
|
||||
class ResourceManifest;
|
||||
class Resource;
|
||||
|
||||
//! Control that manages articleDetails control
|
||||
class ArticleDetailsContainer
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ArticleDetailsContainer(QWidget* parent, BuilderResourceManifest& manifest);
|
||||
~ArticleDetailsContainer();
|
||||
|
||||
void SelectArticle(const QString& id);
|
||||
void Reset();
|
||||
|
||||
Q_SIGNALS:
|
||||
void logSignal(QString text, LogType logType = LogInfo);
|
||||
void updateArticleSignal(QString id);
|
||||
void deleteArticleSignal(QString id);
|
||||
void closeArticleSignal(QString id);
|
||||
void orderChangedSignal(QString id, bool direction);
|
||||
|
||||
private:
|
||||
QScopedPointer<Ui::ArticleDetailsContainerWidget> m_ui;
|
||||
BuilderResourceManifest& m_manifest;
|
||||
ArticleDetails* m_articleDetails = nullptr;
|
||||
QString m_selectedId;
|
||||
|
||||
private Q_SLOTS:
|
||||
void updateArticleSlot();
|
||||
void deleteArticleSlot();
|
||||
void closeArticleSlot();
|
||||
};
|
||||
} // namespace News
|
||||
@@ -1,100 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ArticleDetailsContainerWidget</class>
|
||||
<widget class="QWidget" name="ArticleDetailsContainerWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>250</width>
|
||||
<height>386</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>640</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>ArticleDetailsContainer</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>248</width>
|
||||
<height>384</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,102 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>176</width>
|
||||
<height>137</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>AWS Key Id:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="textKeyId"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>AWS Secret Key:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="textKeyId_2"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -1,157 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "BuilderArticleViewContainer.h"
|
||||
#include "ResourceManagement/BuilderResourceManifest.h"
|
||||
#include "ArticleDetails.h"
|
||||
#include <NewsShared/ResourceManagement/Resource.h>
|
||||
#include <NewsShared/Qt/ArticleViewContainer.h>
|
||||
#include <NewsShared/Qt/ArticleView.h>
|
||||
#include "Qt/ui_BuilderArticleViewContainer.h"
|
||||
|
||||
#include <AzQtComponents/Components/Style.h>
|
||||
|
||||
#include "QCustomMessageBox.h"
|
||||
|
||||
namespace News
|
||||
{
|
||||
|
||||
BuilderArticleViewContainer::BuilderArticleViewContainer(
|
||||
QWidget* parent,
|
||||
BuilderResourceManifest& manifest)
|
||||
: QWidget(parent)
|
||||
, m_ui(new Ui::BuilderArticleViewContainerWidget)
|
||||
, m_container(new ArticleViewContainer(this, manifest))
|
||||
, m_manifest(manifest)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
m_ui->ArticleViewContainerRoot->layout()->addWidget(m_container);
|
||||
connect(m_container, SIGNAL(articleSelectedSignal(QString)),
|
||||
this, SLOT(articleSelectedSlot(QString)));
|
||||
}
|
||||
|
||||
BuilderArticleViewContainer::~BuilderArticleViewContainer(){}
|
||||
|
||||
void BuilderArticleViewContainer::AddArticle()
|
||||
{
|
||||
auto pArticleResource = static_cast<BuilderResourceManifest&>(m_manifest).AddArticle();
|
||||
if (pArticleResource)
|
||||
{
|
||||
m_container->AddArticleView(ArticleDescriptor(*pArticleResource));
|
||||
SelectArticle(pArticleResource->GetId());
|
||||
}
|
||||
}
|
||||
|
||||
void BuilderArticleViewContainer::SelectArticle(QString id)
|
||||
{
|
||||
if (m_selectedArticleId.compare(id) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UnselectArticle();
|
||||
m_selectedArticleId = id;
|
||||
auto article = m_container->FindById(id);
|
||||
if (article)
|
||||
{
|
||||
m_container->ScrollToView(article);
|
||||
emit articleSelectedSignal(id);
|
||||
|
||||
// Add class and refresh style
|
||||
AzQtComponents::Style::addClass(article, m_selectedArticleClass);
|
||||
article->style()->unpolish(qApp);
|
||||
article->style()->polish(qApp);
|
||||
}
|
||||
}
|
||||
|
||||
void BuilderArticleViewContainer::Sync()
|
||||
{
|
||||
emit logSignal("Starting sync");
|
||||
|
||||
m_manifest.Sync();
|
||||
}
|
||||
|
||||
void BuilderArticleViewContainer::UpdateArticle(QString& id) const
|
||||
{
|
||||
auto view = m_container->FindById(id);
|
||||
if (view)
|
||||
{
|
||||
view->Update();
|
||||
m_container->ForceRefreshArticleView(view);
|
||||
}
|
||||
}
|
||||
|
||||
void BuilderArticleViewContainer::DeleteArticle(QString& id) const
|
||||
{
|
||||
auto view = m_container->FindById(id);
|
||||
if (view)
|
||||
{
|
||||
m_container->DeleteArticleView(view);
|
||||
}
|
||||
}
|
||||
|
||||
//possibly support multiple selection in future?
|
||||
void BuilderArticleViewContainer::CloseArticle(QString& id)
|
||||
{
|
||||
if (m_selectedArticleId == id)
|
||||
{
|
||||
UnselectArticle();
|
||||
}
|
||||
}
|
||||
|
||||
void BuilderArticleViewContainer::UpdateArticleOrder(QString& id, bool direction) const
|
||||
{
|
||||
auto view = m_container->FindById(id);
|
||||
if (view)
|
||||
{
|
||||
m_container->UpdateArticleOrder(view, direction);
|
||||
}
|
||||
}
|
||||
|
||||
void BuilderArticleViewContainer::PopulateArticles()
|
||||
{
|
||||
m_container->PopulateArticles();
|
||||
|
||||
if (!m_selectedArticleId.isEmpty())
|
||||
{
|
||||
SelectArticle(m_selectedArticleId);
|
||||
}
|
||||
}
|
||||
|
||||
void BuilderArticleViewContainer::AddErrorMessage() const
|
||||
{
|
||||
m_container->AddErrorMessage();
|
||||
}
|
||||
|
||||
void BuilderArticleViewContainer::UnselectArticle()
|
||||
{
|
||||
if (m_selectedArticleId.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto article = m_container->FindById(m_selectedArticleId);
|
||||
|
||||
// Remove class and refresh style
|
||||
if (article)
|
||||
{
|
||||
AzQtComponents::Style::removeClass(article, m_selectedArticleClass);
|
||||
article->style()->unpolish(qApp);
|
||||
article->style()->polish(qApp);
|
||||
}
|
||||
|
||||
m_selectedArticleId = "";
|
||||
}
|
||||
|
||||
void BuilderArticleViewContainer::articleSelectedSlot(QString id)
|
||||
{
|
||||
SelectArticle(id);
|
||||
}
|
||||
|
||||
#include "Qt/moc_BuilderArticleViewContainer.cpp"
|
||||
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QWidget>
|
||||
#include <NewsShared/LogType.h>
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class BuilderArticleViewContainerWidget;
|
||||
}
|
||||
|
||||
namespace News
|
||||
{
|
||||
class ArticleViewContainer;
|
||||
class BuilderResourceManifest;
|
||||
|
||||
//! BuilderArticleViewContainer is a Builder container for ArticleViewContainer.
|
||||
/*!
|
||||
It is a wrapper with additional builder functionality for displaying articles
|
||||
*/
|
||||
class BuilderArticleViewContainer
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
BuilderArticleViewContainer(QWidget* parent, BuilderResourceManifest& manifest);
|
||||
~BuilderArticleViewContainer();
|
||||
|
||||
void UpdateArticle(QString& id) const;
|
||||
void DeleteArticle(QString& id) const;
|
||||
void CloseArticle(QString& id);
|
||||
void UpdateArticleOrder(QString& id, bool direction) const;
|
||||
void PopulateArticles();
|
||||
void AddErrorMessage() const;
|
||||
void AddArticle();
|
||||
|
||||
Q_SIGNALS:
|
||||
void logSignal(QString text, LogType logType = LogInfo);
|
||||
void articleSelectedSignal(QString id);
|
||||
|
||||
private:
|
||||
QScopedPointer<Ui::BuilderArticleViewContainerWidget> m_ui;
|
||||
ArticleViewContainer* m_container;
|
||||
QString m_selectedArticleId;
|
||||
QString m_selectedArticleClass = "SelectedArticle";
|
||||
BuilderResourceManifest& m_manifest;
|
||||
|
||||
void Sync();
|
||||
void SelectArticle(QString id);
|
||||
void UnselectArticle();
|
||||
|
||||
|
||||
private Q_SLOTS:
|
||||
void articleSelectedSlot(QString id);
|
||||
};
|
||||
} // namespace News
|
||||
@@ -1,57 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BuilderArticleViewContainerWidget</class>
|
||||
<widget class="QWidget" name="BuilderArticleViewContainerWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>250</width>
|
||||
<height>500</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWidget" name="ArticleViewContainerRoot" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "EndpointEntryView.h"
|
||||
#include "Qt/ui_EndpointEntryView.h"
|
||||
#include <EndpointManager.h>
|
||||
#include <QToolButton>
|
||||
|
||||
namespace News
|
||||
{
|
||||
|
||||
const char* EndpointEntryView::SELECTED_CSS =
|
||||
"background-color: rgb(60, 100, 60);\ncolor: white;";
|
||||
const char* EndpointEntryView::UNSELECTED_CSS =
|
||||
"background-color: rgb(60, 60, 60);\ncolor: white;";
|
||||
|
||||
EndpointEntryView::EndpointEntryView(QWidget* parent, Endpoint* pEndpoint)
|
||||
: QWidget(parent)
|
||||
, m_ui(new Ui::EndpointEntryViewWidget)
|
||||
, m_pEndpoint(pEndpoint)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
m_ui->labelName->setText(pEndpoint->GetName());
|
||||
|
||||
connect(m_ui->labelName, &AzQtComponents::ExtendedLabel::clicked, this, &EndpointEntryView::selectSlot);
|
||||
connect(m_ui->buttonDelete, &QToolButton::clicked, this, &EndpointEntryView::deleteSlot);
|
||||
}
|
||||
|
||||
EndpointEntryView::~EndpointEntryView() {}
|
||||
|
||||
void EndpointEntryView::SetSelected(bool selected)
|
||||
{
|
||||
setStyleSheet(selected ? SELECTED_CSS : UNSELECTED_CSS);
|
||||
}
|
||||
|
||||
Endpoint* EndpointEntryView::GetEndpoint() const
|
||||
{
|
||||
return m_pEndpoint;
|
||||
}
|
||||
|
||||
void EndpointEntryView::selectSlot()
|
||||
{
|
||||
emit selectSignal(this);
|
||||
}
|
||||
|
||||
void EndpointEntryView::deleteSlot()
|
||||
{
|
||||
emit deleteSignal(this);
|
||||
}
|
||||
|
||||
#include "Qt/moc_EndpointEntryView.cpp"
|
||||
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QWidget>
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class EndpointEntryViewWidget;
|
||||
}
|
||||
|
||||
namespace News
|
||||
{
|
||||
class Endpoint;
|
||||
|
||||
//! Qt widget representing a single endpoint entry
|
||||
class EndpointEntryView
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
EndpointEntryView(QWidget* parent, Endpoint* pEndpoint);
|
||||
~EndpointEntryView();
|
||||
|
||||
void SetSelected(bool selected);
|
||||
|
||||
Endpoint* GetEndpoint() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void selectSignal(EndpointEntryView* pEndpointView);
|
||||
void deleteSignal(EndpointEntryView* pEndpointView);
|
||||
|
||||
private:
|
||||
static const char* SELECTED_CSS;
|
||||
static const char* UNSELECTED_CSS;
|
||||
|
||||
QScopedPointer<Ui::EndpointEntryViewWidget> m_ui;
|
||||
Endpoint* m_pEndpoint = nullptr;
|
||||
|
||||
private Q_SLOTS:
|
||||
void selectSlot();
|
||||
void deleteSlot();
|
||||
};
|
||||
} // namespace News
|
||||
@@ -1,87 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>EndpointEntryViewWidget</class>
|
||||
<widget class="QWidget" name="EndpointEntryViewWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>356</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>23</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>23</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="AzQtComponents::ExtendedLabel" name="labelName">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="buttonDelete">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>25</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>25</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: red;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>X</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>AzQtComponents::ExtendedLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>AzQtComponents/Components/ExtendedLabel.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,221 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "EndpointManagerView.h"
|
||||
#include "EndpointManager.h"
|
||||
#include "EndpointEntryView.h"
|
||||
#include "Qt/ui_EndpointManagerView.h"
|
||||
#include "Qt/QCustomMessageBox.h"
|
||||
#include "ResourceManagement/BuilderResourceManifest.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
|
||||
namespace News
|
||||
{
|
||||
|
||||
EndpointManagerView::EndpointManagerView(QWidget* parent,
|
||||
BuilderResourceManifest& manifest)
|
||||
: QDialog(parent)
|
||||
, m_ui(new Ui::EndpointManagerViewWidget)
|
||||
, m_pManager(manifest.GetEndpointManager())
|
||||
, m_manifest(manifest)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
for (auto endpoint : *m_pManager)
|
||||
{
|
||||
auto endpointView = AddEndpointEntry(endpoint);
|
||||
if (m_pManager->GetSelectedEndpoint() == endpoint)
|
||||
{
|
||||
selectEndpointSlot(endpointView);
|
||||
}
|
||||
}
|
||||
|
||||
connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
connect(m_ui->buttonAdd, &QPushButton::clicked, this, &EndpointManagerView::addEndpointSlot);
|
||||
}
|
||||
|
||||
EndpointManagerView::~EndpointManagerView() {}
|
||||
|
||||
EndpointEntryView* EndpointManagerView::AddEndpointEntry(Endpoint* pEndpoint)
|
||||
{
|
||||
auto endpointView = new EndpointEntryView(m_ui->endpointListContents, pEndpoint);
|
||||
auto layout = static_cast<QVBoxLayout*>(m_ui->endpointListContents->layout());
|
||||
layout->insertWidget(layout->count() - 2, endpointView);
|
||||
m_endpoints.append(endpointView);
|
||||
connect(endpointView, SIGNAL(selectSignal(EndpointEntryView*)),
|
||||
this, SLOT(selectEndpointSlot(EndpointEntryView*)));
|
||||
connect(endpointView, SIGNAL(deleteSignal(EndpointEntryView*)),
|
||||
this, SLOT(deleteEndpointSlot(EndpointEntryView*)));
|
||||
// this lets us modify newly-added widget in the same function
|
||||
qApp->processEvents();
|
||||
return endpointView;
|
||||
}
|
||||
|
||||
void EndpointManagerView::Update() const
|
||||
{
|
||||
if (m_pSelectedEndpoint)
|
||||
{
|
||||
auto pEndpoint = m_pSelectedEndpoint->GetEndpoint();
|
||||
pEndpoint->SetName(m_ui->nameText->text());
|
||||
pEndpoint->SetAwsProfile(m_ui->awsProfileText->text());
|
||||
pEndpoint->SetUrl(m_ui->urlText->text());
|
||||
pEndpoint->SetBucket(m_ui->bucketText->text());
|
||||
m_pManager->SelectEndpoint(m_pSelectedEndpoint->GetEndpoint());
|
||||
}
|
||||
m_pManager->Save();
|
||||
}
|
||||
|
||||
void EndpointManagerView::accept()
|
||||
{
|
||||
enum SyncResponse
|
||||
{
|
||||
Merge, ReplaceLocal, ReplaceRemote, Cancel
|
||||
};
|
||||
enum YesNoResponse
|
||||
{
|
||||
Yes, No
|
||||
};
|
||||
|
||||
QCustomMessageBox msgBox(
|
||||
QCustomMessageBox::Question,
|
||||
tr("Pull data from Endpoint"),
|
||||
tr("You are changing an endpoint. "
|
||||
"What would you like to do with the data on the current endpoint?\n\n"
|
||||
"Merge - merge resources from the endpoint\n"
|
||||
"Replace Local - overwrite local resources with endpoint resources\n"
|
||||
"Replace Endpoint - overwrite endpoint resources with local resources\n"
|
||||
"Cancel - undo endpoint selection"
|
||||
),
|
||||
this);
|
||||
msgBox.AddButton(tr("Merge"), Merge);
|
||||
msgBox.AddButton(tr("Replace Local"), ReplaceLocal);
|
||||
msgBox.AddButton(tr("Replace Endpoint"), ReplaceRemote);
|
||||
msgBox.AddButton(tr("Cancel"), Cancel);
|
||||
|
||||
switch (msgBox.exec())
|
||||
{
|
||||
case Merge:
|
||||
{
|
||||
m_manifest.SetSyncType(SyncType::Merge);
|
||||
m_manifest.PersistLocalResources();
|
||||
}
|
||||
break;
|
||||
case ReplaceLocal:
|
||||
{
|
||||
if (m_manifest.HasChanges())
|
||||
{
|
||||
QCustomMessageBox msgBoxWarning(
|
||||
QCustomMessageBox::Critical,
|
||||
tr("Unsaved changes"),
|
||||
tr("Local resources were modified but not published."
|
||||
"Changing endpoints will cause unpublished work to be lost.\n\n"
|
||||
"Would you like to proceed?"),
|
||||
this);
|
||||
msgBoxWarning.AddButton(tr("Yes"), Yes);
|
||||
msgBoxWarning.AddButton(tr("No"), No);
|
||||
if (msgBoxWarning.exec() == No)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_manifest.SetSyncType(SyncType::Merge);
|
||||
m_manifest.Reset();
|
||||
}
|
||||
break;
|
||||
case ReplaceRemote:
|
||||
{
|
||||
QCustomMessageBox msgBoxWarning2(
|
||||
QCustomMessageBox::Critical,
|
||||
tr("Warning"),
|
||||
tr("This operation will IRREVERSABLY replace ALL resources on ") +
|
||||
m_pSelectedEndpoint->GetEndpoint()->GetName() +
|
||||
tr(" endpoint with local data.\n\n"
|
||||
"Are you sure you'd like to proceed?"),
|
||||
this);
|
||||
msgBoxWarning2.AddButton(tr("Yes"), Yes);
|
||||
msgBoxWarning2.AddButton(tr("No"), No);
|
||||
if (msgBoxWarning2.exec() == No)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_manifest.SetSyncType(SyncType::Overwrite);
|
||||
m_manifest.PersistLocalResources();
|
||||
}
|
||||
break;
|
||||
case Cancel:
|
||||
return;
|
||||
}
|
||||
|
||||
Update();
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void EndpointManagerView::addEndpointSlot()
|
||||
{
|
||||
auto pEndpoint = new Endpoint(
|
||||
QObject::tr("New endpoint"),
|
||||
QObject::tr("Enter AWS profile name"),
|
||||
QObject::tr("Enter root URL"),
|
||||
QObject::tr("Enter s3 bucket name"));
|
||||
m_pManager->AddEndpoint(pEndpoint);
|
||||
auto endpointView = AddEndpointEntry(pEndpoint);
|
||||
selectEndpointSlot(endpointView);
|
||||
}
|
||||
|
||||
void EndpointManagerView::selectEndpointSlot(EndpointEntryView* pEndpointView)
|
||||
{
|
||||
m_pSelectedEndpoint = pEndpointView;
|
||||
|
||||
for (auto view : m_endpoints)
|
||||
{
|
||||
view->SetSelected(view == pEndpointView);
|
||||
}
|
||||
|
||||
if (pEndpointView)
|
||||
{
|
||||
auto pEndpoint = pEndpointView->GetEndpoint();
|
||||
m_ui->nameText->setText(pEndpoint->GetName());
|
||||
m_ui->awsProfileText->setText(pEndpoint->GetAwsProfile());
|
||||
m_ui->urlText->setText(pEndpoint->GetUrl());
|
||||
m_ui->bucketText->setText(pEndpoint->GetBucket());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ui->nameText->setText("");
|
||||
m_ui->awsProfileText->setText("");
|
||||
m_ui->urlText->setText("");
|
||||
m_ui->bucketText->setText("");
|
||||
}
|
||||
}
|
||||
|
||||
void EndpointManagerView::deleteEndpointSlot(EndpointEntryView* pEndpointView)
|
||||
{
|
||||
m_pManager->RemoveEndpoint(pEndpointView->GetEndpoint());
|
||||
m_endpoints.removeAll(pEndpointView);
|
||||
|
||||
if (pEndpointView == m_pSelectedEndpoint)
|
||||
{
|
||||
if (m_endpoints.count() > 0)
|
||||
{
|
||||
selectEndpointSlot(m_endpoints[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
selectEndpointSlot(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
delete pEndpointView;
|
||||
}
|
||||
|
||||
|
||||
#include "Qt/moc_EndpointManagerView.cpp"
|
||||
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QDialog>
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class EndpointManagerViewWidget;
|
||||
}
|
||||
|
||||
namespace News
|
||||
{
|
||||
class BuilderResourceManifest;
|
||||
class Endpoint;
|
||||
class EndpointEntryView;
|
||||
class EndpointManager;
|
||||
|
||||
//! Qt dialog for managing endpoints
|
||||
class EndpointManagerView
|
||||
: public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
EndpointManagerView(QWidget* parent,
|
||||
BuilderResourceManifest& manifest);
|
||||
~EndpointManagerView();
|
||||
|
||||
private:
|
||||
QScopedPointer<Ui::EndpointManagerViewWidget> m_ui;
|
||||
EndpointManager* m_pManager = nullptr;
|
||||
EndpointEntryView* m_pSelectedEndpoint = nullptr;
|
||||
QList<EndpointEntryView*> m_endpoints;
|
||||
BuilderResourceManifest& m_manifest;
|
||||
|
||||
EndpointEntryView* AddEndpointEntry(Endpoint* pEndpoint);
|
||||
void Update() const;
|
||||
|
||||
private Q_SLOTS:
|
||||
void accept() override;
|
||||
void addEndpointSlot();
|
||||
void selectEndpointSlot(EndpointEntryView* pEndpoint);
|
||||
void deleteEndpointSlot(EndpointEntryView* pEndpoint);
|
||||
};
|
||||
} // namespace News
|
||||
@@ -1,224 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>EndpointManagerViewWidget</class>
|
||||
<widget class="QDialog" name="EndpointManagerViewWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>350</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>350</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>350</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Change Endpoint</string>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOn</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="endpointListContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>363</width>
|
||||
<height>189</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonAdd">
|
||||
<property name="text">
|
||||
<string>+</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="nameText">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_1">
|
||||
<property name="text">
|
||||
<string>AWS Profile Name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="awsProfileText">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>URL:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="urlText">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>S3 Bucket</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="bucketText">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ImageItem.h"
|
||||
#include "NewsShared/ResourceManagement/Resource.h"
|
||||
|
||||
#include "Qt/ui_ImageItem.h"
|
||||
|
||||
namespace News
|
||||
{
|
||||
|
||||
const char* ImageItem::SELECTED_CSS =
|
||||
"border: 4px solid; border-color: white; background-color: rgb(45, 45, 45);";
|
||||
const char* ImageItem::UN_SELECTED_CSS =
|
||||
"background-color: rgb(45, 45, 45);";
|
||||
|
||||
ImageItem::ImageItem(Resource& resource)
|
||||
: QWidget()
|
||||
, m_ui(new Ui::ImageItemWidget)
|
||||
, m_resource(resource)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
QPixmap pixmap;
|
||||
pixmap.loadFromData(m_resource.GetData());
|
||||
m_ui->ImageLabel->setPixmap(pixmap);
|
||||
|
||||
connect(m_ui->ImageLabel, &AzQtComponents::ExtendedLabel::clicked, this, &ImageItem::imageClickedSlot);
|
||||
}
|
||||
|
||||
void ImageItem::imageClickedSlot()
|
||||
{
|
||||
emit selectSignal(this);
|
||||
}
|
||||
|
||||
ImageItem::~ImageItem() {}
|
||||
|
||||
void ImageItem::SetSelect(bool selected) const
|
||||
{
|
||||
m_ui->ImageLabel->setStyleSheet(selected ? SELECTED_CSS : UN_SELECTED_CSS);
|
||||
}
|
||||
|
||||
Resource& ImageItem::GetResource() const
|
||||
{
|
||||
return m_resource;
|
||||
}
|
||||
|
||||
#include "Qt/moc_ImageItem.cpp"
|
||||
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QWidget>
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class ImageItemWidget;
|
||||
}
|
||||
|
||||
namespace News {
|
||||
class Resource;
|
||||
|
||||
//! A clickable image in selectImage control
|
||||
class ImageItem
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ImageItem(Resource& resource);
|
||||
~ImageItem();
|
||||
|
||||
void SetSelect(bool selected) const;
|
||||
Resource& GetResource() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void selectSignal(ImageItem* imageItem);
|
||||
|
||||
private:
|
||||
QScopedPointer<Ui::ImageItemWidget> m_ui;
|
||||
const static char* SELECTED_CSS;
|
||||
const static char* UN_SELECTED_CSS;
|
||||
|
||||
Resource& m_resource;
|
||||
private Q_SLOTS:
|
||||
void imageClickedSlot();
|
||||
};
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ImageItemWidget</class>
|
||||
<widget class="QWidget" name="ImageItemWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>200</width>
|
||||
<height>200</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>200</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>200</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>20</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>20</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>20</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>20</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="AzQtComponents::ExtendedLabel" name="ImageLabel">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmapSize" stdset="0">
|
||||
<size>
|
||||
<width>160</width>
|
||||
<height>90</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>AzQtComponents::ExtendedLabel1</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>AzQtComponents/Components/ExtendedLabel.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "LogContainer.h"
|
||||
|
||||
#include "Qt/ui_LogContainer.h"
|
||||
|
||||
namespace News
|
||||
{
|
||||
|
||||
LogContainer::LogContainer(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_ui(new Ui::LogContainerWidget)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
}
|
||||
|
||||
LogContainer::~LogContainer() {}
|
||||
|
||||
void LogContainer::AddLog(QString text, LogType logType) const {
|
||||
QString color;
|
||||
switch (logType)
|
||||
{
|
||||
case LogOk:
|
||||
color = "green";
|
||||
break;
|
||||
case LogInfo:
|
||||
color = "white";
|
||||
break;
|
||||
case LogError:
|
||||
color = "red";
|
||||
break;
|
||||
case LogWarning:
|
||||
color = "yellow";
|
||||
break;
|
||||
default:
|
||||
color = "white";
|
||||
break;
|
||||
}
|
||||
auto fullText = QString("<span style=\" color:%1; \"><XMP>%2</XMP></span><br>").arg(color).arg(text);
|
||||
m_ui->logText->setTextFormat(Qt::RichText);
|
||||
m_ui->logText->setText(QString("%2%1").arg(m_ui->logText->text()).arg(fullText));
|
||||
}
|
||||
|
||||
#include "Qt/moc_LogContainer.cpp"
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QWidget>
|
||||
#include <NewsShared/LogType.h>
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class LogContainerWidget;
|
||||
}
|
||||
|
||||
namespace News
|
||||
{
|
||||
//! A control for displaying log
|
||||
class LogContainer
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LogContainer(QWidget* parent);
|
||||
~LogContainer();
|
||||
|
||||
void AddLog(QString text, LogType logType) const;
|
||||
|
||||
private:
|
||||
QScopedPointer<Ui::LogContainerWidget> m_ui;
|
||||
};
|
||||
} // namespace News
|
||||
@@ -1,131 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>LogContainerWidget</class>
|
||||
<widget class="QWidget" name="LogContainerWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>547</width>
|
||||
<height>125</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>LogContainer</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="logArea_3">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents_3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>545</width>
|
||||
<height>123</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="logText">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(45, 45, 45);</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,243 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/PlatformDef.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include "NewsBuilder.h"
|
||||
#include "Qt/ArticleDetails.h"
|
||||
#include "Qt/BuilderArticleViewContainer.h"
|
||||
#include "NewsShared/Qt/ArticleViewContainer.h"
|
||||
#include "NewsShared/ResourceManagement/Resource.h"
|
||||
#include "ResourceManagement/BuilderResourceManifest.h"
|
||||
#include "ArticleDetailsContainer.h"
|
||||
#include "LogContainer.h"
|
||||
#include "EndpointManagerView.h"
|
||||
#include "EndpointManager.h"
|
||||
#include "Qt/QCustomMessageBox.h"
|
||||
|
||||
#include <AzQtComponents/Components/StyleManager.h>
|
||||
#include <AzQtComponents/Utilities/QtPluginPaths.h>
|
||||
|
||||
AZ_PUSH_DISABLE_WARNING(4251 4996, "-Wunknown-warning-option")
|
||||
#include <aws/core/utils/HashingUtils.h>
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
#include <QImage>
|
||||
#include <QFileDialog>
|
||||
#include <QSignalMapper>
|
||||
#include <QTextDocument>
|
||||
|
||||
#include "Qt/ui_Newsbuilder.h"
|
||||
|
||||
namespace News
|
||||
{
|
||||
NewsBuilder::NewsBuilder(QWidget* parent, const AZ::IO::PathView& engineRootPath)
|
||||
: QMainWindow(parent)
|
||||
, m_ui(new Ui::NewsBuilderClass())
|
||||
, m_manifest(new BuilderResourceManifest(
|
||||
std::bind(&NewsBuilder::SyncSuccess, this),
|
||||
std::bind(&NewsBuilder::SyncFail, this, std::placeholders::_1),
|
||||
std::bind(&NewsBuilder::SyncUpdate, this, std::placeholders::_1, std::placeholders::_2)))
|
||||
, m_articleDetailsContainer(new ArticleDetailsContainer(this, *m_manifest))
|
||||
, m_articleViewContainer(new BuilderArticleViewContainer(this, *m_manifest))
|
||||
, m_logContainer(new LogContainer(this))
|
||||
{
|
||||
|
||||
AzQtComponents::StyleManager* m_styleSheet = new AzQtComponents::StyleManager(this);
|
||||
m_styleSheet->initialize(qApp, engineRootPath);
|
||||
|
||||
m_ui->setupUi(this);
|
||||
|
||||
QDir rootDir = QString::fromUtf8(engineRootPath.Native().data(), aznumeric_cast<int>(engineRootPath.Native().size()));
|
||||
const auto pathOnDisk = rootDir.absoluteFilePath("Code/Tools/News/NewsBuilder/Resources");
|
||||
const auto qrcPath = QStringLiteral(":/NewsBuilder");
|
||||
AzQtComponents::StyleManager::addSearchPaths("newsbuilder", pathOnDisk, qrcPath, engineRootPath);
|
||||
|
||||
AzQtComponents::StyleManager::setStyleSheet(this, QStringLiteral("newsbuilder:NewsBuilder.qss"));
|
||||
|
||||
UpdateEndpointLabel();
|
||||
|
||||
m_ui->articleViewContainerRoot->layout()->addWidget(m_articleViewContainer);
|
||||
m_ui->articleDetailsContainerRoot->layout()->addWidget(m_articleDetailsContainer);
|
||||
m_ui->dockWidgetContents->layout()->addWidget(m_logContainer);
|
||||
|
||||
connect(m_articleViewContainer, SIGNAL(articleSelectedSignal(QString)),
|
||||
this, SLOT(selectArticleSlot(QString)));
|
||||
connect(m_articleViewContainer, SIGNAL(logSignal(QString, LogType)),
|
||||
this, SLOT(addLogSlot(QString, LogType)));
|
||||
|
||||
connect(m_articleDetailsContainer, &ArticleDetailsContainer::updateArticleSignal,
|
||||
this, &NewsBuilder::updateArticleSlot);
|
||||
connect(m_articleDetailsContainer, &ArticleDetailsContainer::deleteArticleSignal,
|
||||
this, &NewsBuilder::deleteArticleSlot);
|
||||
connect(m_articleDetailsContainer, &ArticleDetailsContainer::orderChangedSignal,
|
||||
this, &NewsBuilder::orderChangedSlot);
|
||||
connect(m_articleDetailsContainer, &ArticleDetailsContainer::closeArticleSignal,
|
||||
this, &NewsBuilder::closeArticleSlot);
|
||||
connect(m_articleDetailsContainer, SIGNAL(logSignal(QString, LogType)),
|
||||
this, SLOT(addLogSlot(QString, LogType)));
|
||||
|
||||
m_manifest->SetSyncType(SyncType::Merge);
|
||||
m_manifest->Sync();
|
||||
|
||||
// Sync Console pane with View menu
|
||||
connect(m_ui->actionConsole, &QAction::triggered, this, &NewsBuilder::OnViewLogWindow);
|
||||
connect(m_ui->dockWidget, &QDockWidget::visibilityChanged, this, &NewsBuilder::OnViewVisibilityChanged);
|
||||
}
|
||||
|
||||
NewsBuilder::~NewsBuilder() {}
|
||||
|
||||
void NewsBuilder::selectArticleSlot(const QString& id) const
|
||||
{
|
||||
m_articleDetailsContainer->SelectArticle(id);
|
||||
}
|
||||
|
||||
void NewsBuilder::addLogSlot(QString text, LogType logType) const
|
||||
{
|
||||
AddLog(text, logType);
|
||||
}
|
||||
|
||||
void NewsBuilder::addArticleToBottomSlot() const
|
||||
{
|
||||
m_articleViewContainer->AddArticle();
|
||||
}
|
||||
|
||||
void NewsBuilder::updateArticleSlot(QString id) const
|
||||
{
|
||||
m_articleViewContainer->UpdateArticle(id);
|
||||
}
|
||||
|
||||
void NewsBuilder::deleteArticleSlot(QString id) const
|
||||
{
|
||||
m_articleViewContainer->DeleteArticle(id);
|
||||
}
|
||||
|
||||
void NewsBuilder::closeArticleSlot(QString id) const
|
||||
{
|
||||
m_articleViewContainer->CloseArticle(id);
|
||||
}
|
||||
|
||||
void NewsBuilder::orderChangedSlot(QString id, bool direction) const
|
||||
{
|
||||
m_articleViewContainer->UpdateArticleOrder(id, direction);
|
||||
}
|
||||
|
||||
void NewsBuilder::openSlot()
|
||||
{
|
||||
EndpointManagerView endpointManagerView(
|
||||
m_ui->centralWidget,
|
||||
*m_manifest);
|
||||
if (endpointManagerView.exec() == QDialog::Accepted)
|
||||
{
|
||||
m_manifest->Sync();
|
||||
}
|
||||
UpdateEndpointLabel();
|
||||
}
|
||||
|
||||
void NewsBuilder::publishSlot()
|
||||
{
|
||||
if (!m_manifest->HasChanges())
|
||||
{
|
||||
QCustomMessageBox msgBox(
|
||||
QCustomMessageBox::Information,
|
||||
tr("Nothing to publish"),
|
||||
tr("No local changes were made, nothing to publish."),
|
||||
this);
|
||||
msgBox.AddButton(tr("Good"), 0);
|
||||
msgBox.exec();
|
||||
return;
|
||||
}
|
||||
|
||||
enum Response
|
||||
{
|
||||
Yes, No
|
||||
};
|
||||
|
||||
QCustomMessageBox msgBox(
|
||||
QCustomMessageBox::Critical,
|
||||
tr("Publish resources"),
|
||||
tr("You are about to overwrite the current Open 3D Engine Welcome Message. Are you sure you want to publish?"),
|
||||
this);
|
||||
msgBox.AddButton("Yes", Yes);
|
||||
msgBox.AddButton("No", No);
|
||||
if (msgBox.exec() == Yes)
|
||||
{
|
||||
m_manifest->SetSyncType(SyncType::Verify);
|
||||
m_manifest->Sync();
|
||||
}
|
||||
}
|
||||
|
||||
void NewsBuilder::OnViewVisibilityChanged([[maybe_unused]] bool visibility)
|
||||
{
|
||||
UpdateViewMenu();
|
||||
}
|
||||
|
||||
void NewsBuilder::UpdateViewMenu()
|
||||
{
|
||||
if (m_ui->actionConsole->isChecked() != m_ui->dockWidget->isVisible())
|
||||
{
|
||||
QSignalBlocker signalBlocker(m_ui->actionConsole);
|
||||
m_ui->actionConsole->setChecked(m_ui->dockWidget->isVisible());
|
||||
}
|
||||
}
|
||||
|
||||
void NewsBuilder::OnViewLogWindow()
|
||||
{
|
||||
if (m_ui->dockWidget)
|
||||
{
|
||||
m_ui->dockWidget->toggleViewAction()->trigger();
|
||||
}
|
||||
}
|
||||
|
||||
void NewsBuilder::UpdateEndpointLabel()
|
||||
{
|
||||
auto pEndpoint = m_manifest->GetEndpointManager()->GetSelectedEndpoint();
|
||||
if (pEndpoint)
|
||||
{
|
||||
this->setWindowTitle("News Builder (" + pEndpoint->GetName() + ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
this->setWindowTitle("News Builder (No endpoint selected)");
|
||||
}
|
||||
}
|
||||
|
||||
void NewsBuilder::AddLog(QString text, LogType logType) const
|
||||
{
|
||||
m_logContainer->AddLog(text, logType);
|
||||
}
|
||||
|
||||
void NewsBuilder::SyncUpdate(const QString& message, LogType logType) const
|
||||
{
|
||||
AddLog(message, logType);
|
||||
}
|
||||
|
||||
void NewsBuilder::SyncFail(ErrorCode error)
|
||||
{
|
||||
const char* errorMessage = GetErrorMessage(error);
|
||||
AddLog(tr("Sync failed: %1").arg(errorMessage), LogError);
|
||||
QCustomMessageBox msgBoxSyncFail(
|
||||
QCustomMessageBox::Critical,
|
||||
tr("Sync failed"),
|
||||
errorMessage,
|
||||
this);
|
||||
msgBoxSyncFail.AddButton("Ok", 0);
|
||||
msgBoxSyncFail.exec();
|
||||
|
||||
m_articleViewContainer->PopulateArticles();
|
||||
m_articleDetailsContainer->Reset();
|
||||
}
|
||||
|
||||
void NewsBuilder::SyncSuccess() const
|
||||
{
|
||||
AddLog("Sync completed", LogOk);
|
||||
m_articleViewContainer->PopulateArticles();
|
||||
m_articleDetailsContainer->Reset();
|
||||
}
|
||||
#include "Qt/moc_NewsBuilder.cpp"
|
||||
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QMainWindow>
|
||||
|
||||
#include "NewsShared/LogType.h"
|
||||
#include "NewsShared/ErrorCodes.h"
|
||||
|
||||
#include <AzCore/IO/Path/Path_fwd.h>
|
||||
#endif
|
||||
|
||||
class QSignalMapper;
|
||||
class QPushButton;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class NewsBuilderClass;
|
||||
}
|
||||
|
||||
namespace News
|
||||
{
|
||||
class BuilderArticleViewContainer;
|
||||
class LogContainer;
|
||||
class BuilderResourceManifest;
|
||||
class ArticleDetailsContainer;
|
||||
|
||||
//! A central control of News Builder.
|
||||
class NewsBuilder
|
||||
: public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NewsBuilder(QWidget* parent, const AZ::IO::PathView& engineRootPath);
|
||||
~NewsBuilder();
|
||||
|
||||
private:
|
||||
QScopedPointer<Ui::NewsBuilderClass> m_ui;
|
||||
BuilderResourceManifest* m_manifest = nullptr;
|
||||
ArticleDetailsContainer* m_articleDetailsContainer = nullptr;
|
||||
BuilderArticleViewContainer* m_articleViewContainer = nullptr;
|
||||
LogContainer* m_logContainer = nullptr;
|
||||
|
||||
void UpdateEndpointLabel();
|
||||
void AddLog(QString text, LogType logType = LogInfo) const;
|
||||
|
||||
void SyncUpdate(const QString& message, LogType logType) const;
|
||||
void SyncFail(ErrorCode error);
|
||||
void SyncSuccess() const;
|
||||
|
||||
void OnViewVisibilityChanged(bool visibility);
|
||||
void UpdateViewMenu();
|
||||
void OnViewLogWindow();
|
||||
|
||||
private Q_SLOTS:
|
||||
void selectArticleSlot(const QString& id) const;
|
||||
void addLogSlot(QString text, LogType logType) const;
|
||||
void addArticleToBottomSlot() const;
|
||||
void updateArticleSlot(QString id) const;
|
||||
void deleteArticleSlot(QString id) const;
|
||||
void closeArticleSlot(QString id) const;
|
||||
void orderChangedSlot(QString id, bool direction) const;
|
||||
void openSlot();
|
||||
void publishSlot();
|
||||
};
|
||||
} // namespace News
|
||||
@@ -1,5 +0,0 @@
|
||||
<RCC>
|
||||
<qresource prefix="images">
|
||||
<file>../Resources/missing-image.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -1,326 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>NewsBuilderClass</class>
|
||||
<widget class="QMainWindow" name="NewsBuilderClass">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>540</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>480</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>1024</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>News Builder</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWidget" name="verticalLayout1" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>800</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWidget" name="articleViewContainerRoot" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>480</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="articleDetailsContainerRoot" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menuBar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
<property name="title">
|
||||
<string>File</string>
|
||||
</property>
|
||||
<addaction name="actionOpen"/>
|
||||
<addaction name="actionPublish"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuArticle">
|
||||
<property name="title">
|
||||
<string>Article</string>
|
||||
</property>
|
||||
<addaction name="actionAdd_New"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuView">
|
||||
<property name="title">
|
||||
<string>View</string>
|
||||
</property>
|
||||
<addaction name="actionConsole"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuArticle"/>
|
||||
<addaction name="menuView"/>
|
||||
</widget>
|
||||
<widget class="AzQtComponents::StyledDockWidget" name="dockWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>63</width>
|
||||
<height>66</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="features">
|
||||
<set>QDockWidget::DockWidgetClosable</set>
|
||||
</property>
|
||||
<property name="allowedAreas">
|
||||
<set>Qt::BottomDockWidgetArea</set>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Console</string>
|
||||
</property>
|
||||
<attribute name="dockWidgetArea">
|
||||
<number>8</number>
|
||||
</attribute>
|
||||
<widget class="QWidget" name="dockWidgetContents">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<action name="actionOpen">
|
||||
<property name="text">
|
||||
<string>Change Endpoint</string>
|
||||
</property>
|
||||
<property name="autoRepeat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPublish">
|
||||
<property name="text">
|
||||
<string>Publish Resources</string>
|
||||
</property>
|
||||
<property name="autoRepeat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAdd_New">
|
||||
<property name="text">
|
||||
<string>Add to Bottom</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDelete_Selected">
|
||||
<property name="text">
|
||||
<string>Delete Selected</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionConsole">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Console</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="0" margin="0"/>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>AzQtComponents::StyledDockWidget</class>
|
||||
<extends>QDockWidget</extends>
|
||||
<header>AzQtComponents/Components/StyledDockWidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="newsbuilder.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>actionOpen</sender>
|
||||
<signal>triggered()</signal>
|
||||
<receiver>NewsBuilderClass</receiver>
|
||||
<slot>openSlot()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>-1</x>
|
||||
<y>-1</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>399</x>
|
||||
<y>269</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>actionPublish</sender>
|
||||
<signal>triggered()</signal>
|
||||
<receiver>NewsBuilderClass</receiver>
|
||||
<slot>publishSlot()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>-1</x>
|
||||
<y>-1</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>399</x>
|
||||
<y>269</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>actionAdd_New</sender>
|
||||
<signal>triggered()</signal>
|
||||
<receiver>NewsBuilderClass</receiver>
|
||||
<slot>addArticleToBottomSlot()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>-1</x>
|
||||
<y>-1</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>399</x>
|
||||
<y>269</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "QCustomMessageBox.h"
|
||||
#include "Qt/ui_QCustomMessageBox.h"
|
||||
|
||||
#include <QSignalMapper>
|
||||
#include <QPushButton>
|
||||
#include <QStyle>
|
||||
|
||||
namespace News
|
||||
{
|
||||
|
||||
QCustomMessageBox::QCustomMessageBox(
|
||||
Icon icon,
|
||||
const QString& title,
|
||||
const QString& text,
|
||||
QWidget* parent)
|
||||
: QDialog(parent, Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint)
|
||||
, m_ui(new Ui::CustomMessageBoxDialog)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
m_signalMapper = new QSignalMapper(this);
|
||||
|
||||
this->setWindowTitle(title);
|
||||
m_ui->labelText->setText(text);
|
||||
|
||||
QStyle* style = QApplication::style();
|
||||
QIcon tmpIcon;
|
||||
switch (icon)
|
||||
{
|
||||
case Information:
|
||||
tmpIcon = style->standardIcon(QStyle::SP_MessageBoxInformation);
|
||||
break;
|
||||
case Warning:
|
||||
tmpIcon = style->standardIcon(QStyle::SP_MessageBoxWarning);
|
||||
break;
|
||||
case Critical:
|
||||
tmpIcon = style->standardIcon(QStyle::SP_MessageBoxCritical);
|
||||
break;
|
||||
case Question:
|
||||
tmpIcon = style->standardIcon(QStyle::SP_MessageBoxQuestion);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!tmpIcon.isNull())
|
||||
{
|
||||
QLabel* iconLabel = new QLabel(this);
|
||||
iconLabel->setPixmap(tmpIcon.pixmap(64, 64));
|
||||
m_ui->bodyLayout->insertWidget(0, iconLabel);
|
||||
}
|
||||
|
||||
connect(m_signalMapper, SIGNAL(mapped(int)),
|
||||
this, SLOT(clickedSlot(int)));
|
||||
}
|
||||
|
||||
QCustomMessageBox::~QCustomMessageBox()
|
||||
{
|
||||
delete m_signalMapper;
|
||||
}
|
||||
|
||||
void QCustomMessageBox::AddButton(const QString& name, int result)
|
||||
{
|
||||
auto button = new QPushButton(name, this);
|
||||
connect(button, SIGNAL(clicked()), m_signalMapper, SLOT(map()));
|
||||
m_signalMapper->setMapping(button, result);
|
||||
m_ui->buttonLayout->layout()->addWidget(button);
|
||||
}
|
||||
|
||||
void QCustomMessageBox::clickedSlot(int result)
|
||||
{
|
||||
done(result);
|
||||
}
|
||||
|
||||
#include "Qt/moc_QCustomMessageBox.cpp"
|
||||
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QDialog>
|
||||
#endif
|
||||
|
||||
class QSignalMapper;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class CustomMessageBoxDialog;
|
||||
}
|
||||
|
||||
namespace News
|
||||
{
|
||||
class ArticleDetails;
|
||||
class BuilderResourceManifest;
|
||||
class SelectImage;
|
||||
class ResourceManifest;
|
||||
class Resource;
|
||||
|
||||
//! Allows to add custom buttons which is not well-supported by default QMessageBox
|
||||
class QCustomMessageBox
|
||||
: public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Icon {
|
||||
NoIcon = 0,
|
||||
Information = 1,
|
||||
Warning = 2,
|
||||
Critical = 3,
|
||||
Question = 4
|
||||
};
|
||||
|
||||
QCustomMessageBox(
|
||||
Icon,
|
||||
const QString& title,
|
||||
const QString& text,
|
||||
QWidget* parent);
|
||||
~QCustomMessageBox();
|
||||
|
||||
void AddButton(const QString& name, int result);
|
||||
|
||||
private:
|
||||
QScopedPointer<Ui::CustomMessageBoxDialog> m_ui;
|
||||
QSignalMapper* m_signalMapper = nullptr;
|
||||
|
||||
private Q_SLOTS:
|
||||
void clickedSlot(int result);
|
||||
};
|
||||
} // namespace News
|
||||
@@ -1,84 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CustomMessageBoxDialog</class>
|
||||
<widget class="QDialog" name="CustomMessageBoxDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>102</width>
|
||||
<height>43</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Message Title</string>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="bodyLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelText">
|
||||
<property name="text">
|
||||
<string>Message text</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="buttonLayout">
|
||||
<property name="spacing">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "SelectImage.h"
|
||||
#include "ImageItem.h"
|
||||
#include "NewsShared/ResourceManagement/Resource.h"
|
||||
#include "ResourceManagement/BuilderResourceManifest.h"
|
||||
|
||||
#include "Qt/ui_SelectImage.h"
|
||||
|
||||
namespace News
|
||||
{
|
||||
|
||||
const int SelectImage::MAX_COLS = 2;
|
||||
|
||||
SelectImage::SelectImage(const ResourceManifest& manifest)
|
||||
: QDialog()
|
||||
, m_ui(new Ui::SelectImageDialog)
|
||||
, m_manifest(manifest)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
auto layout = static_cast<QGridLayout*>(m_ui->scrollAreaContents->layout());
|
||||
layout->setAlignment(Qt::AlignTop | Qt::AlignLeft);
|
||||
int row = 0;
|
||||
int col = 0;
|
||||
//! read all image resources and populate the container
|
||||
for (auto pResource : m_manifest)
|
||||
{
|
||||
if (pResource->GetType().compare("image") == 0)
|
||||
{
|
||||
auto imageItem = new ImageItem(*pResource);
|
||||
connect(imageItem, &ImageItem::selectSignal, this, &SelectImage::ImageSelected);
|
||||
layout->addWidget(imageItem, row, col, Qt::AlignLeft);
|
||||
m_images.append(imageItem);
|
||||
col++;
|
||||
if (col >= MAX_COLS)
|
||||
{
|
||||
col = 0;
|
||||
row++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
}
|
||||
|
||||
SelectImage::~SelectImage() {}
|
||||
|
||||
Resource* SelectImage::GetSelected() const
|
||||
{
|
||||
return m_pSelected;
|
||||
}
|
||||
|
||||
void SelectImage::ImageSelected(ImageItem* imageItem)
|
||||
{
|
||||
for (auto image : m_images)
|
||||
{
|
||||
image->SetSelect(image == imageItem);
|
||||
}
|
||||
if (imageItem)
|
||||
{
|
||||
m_pSelected = &imageItem->GetResource();
|
||||
}
|
||||
}
|
||||
|
||||
#include "Qt/moc_SelectImage.cpp"
|
||||
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QDialog>
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class SelectImageDialog;
|
||||
}
|
||||
|
||||
namespace News {
|
||||
class ImageItem;
|
||||
class Resource;
|
||||
class ResourceManifest;
|
||||
|
||||
//! Allows to select existing images for multiple messages without re-uploading same one
|
||||
class SelectImage
|
||||
: public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SelectImage(const ResourceManifest& manifest);
|
||||
~SelectImage();
|
||||
|
||||
void Select();
|
||||
void Close();
|
||||
Resource* GetSelected() const;
|
||||
|
||||
private:
|
||||
const static int MAX_COLS;
|
||||
QScopedPointer<Ui::SelectImageDialog> m_ui;
|
||||
const ResourceManifest& m_manifest;
|
||||
QList<ImageItem*> m_images;
|
||||
Resource* m_pSelected = nullptr;
|
||||
|
||||
void ImageSelected(ImageItem* imageItem);
|
||||
};
|
||||
} // namespace News
|
||||
@@ -1,106 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SelectImageDialog</class>
|
||||
<widget class="QDialog" name="SelectImageDialog">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::ApplicationModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>439</width>
|
||||
<height>406</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Select Image</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>437</width>
|
||||
<height>379</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,497 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "BuilderResourceManifest.h"
|
||||
#include "NewsShared/ResourceManagement/QtDownloadManager.h"
|
||||
#include "NewsBuilder/S3Connector.h"
|
||||
#include "UidGenerator.h"
|
||||
#include "NewsShared/ResourceManagement/Resource.h"
|
||||
#include "NewsBuilder/ResourceManagement/UploadDescriptor.h"
|
||||
#include "NewsBuilder/ResourceManagement/DeleteDescriptor.h"
|
||||
#include "NewsShared/ResourceManagement/ArticleDescriptor.h"
|
||||
#include "NewsBuilder/ResourceManagement/ImageDescriptor.h"
|
||||
#include "EndpointManager.h"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QByteArray>
|
||||
|
||||
#include <aws/core/utils/memory/stl/AwsStringStream.h>
|
||||
#include <QMessageBox>
|
||||
|
||||
namespace News {
|
||||
|
||||
BuilderResourceManifest::BuilderResourceManifest(
|
||||
std::function<void()> syncSuccessCallback,
|
||||
std::function<void(ErrorCode)> syncFailCallback,
|
||||
std::function<void(QString, LogType)> syncUpdateCallback)
|
||||
: ResourceManifest(syncSuccessCallback, syncFailCallback, syncUpdateCallback)
|
||||
, m_s3Connector(new S3Connector)
|
||||
, m_uidGenerator(new UidGenerator)
|
||||
, m_endpointManager(new EndpointManager) {}
|
||||
|
||||
|
||||
Resource* BuilderResourceManifest::AddArticle()
|
||||
{
|
||||
auto pResource = new Resource(
|
||||
QString("%1").arg(m_uidGenerator->GenerateUid()),
|
||||
"article");
|
||||
QJsonObject json;
|
||||
json["title"] = "New Article";
|
||||
json["body"] = "Enter article body here";
|
||||
json["imageId"] = "0";
|
||||
QJsonDocument doc(json);
|
||||
QByteArray data = doc.toJson(QJsonDocument::Compact).toStdString().data();
|
||||
pResource->SetData(data);
|
||||
m_toUpload.push(pResource);
|
||||
AppendResource(pResource);
|
||||
m_order.append(pResource->GetId());
|
||||
return pResource;
|
||||
}
|
||||
|
||||
Resource* BuilderResourceManifest::AddImage(const QString& filename)
|
||||
{
|
||||
auto pResource = new Resource(
|
||||
QString("%1").arg(m_uidGenerator->GenerateUid()),
|
||||
"image");
|
||||
ImageDescriptor descriptor(*pResource);
|
||||
QString error;
|
||||
if (!descriptor.Read(filename, error))
|
||||
{
|
||||
m_syncUpdateCallback(error, LogError);
|
||||
delete pResource;
|
||||
return nullptr;
|
||||
}
|
||||
m_toUpload.push(pResource);
|
||||
AppendResource(pResource);
|
||||
return pResource;
|
||||
}
|
||||
|
||||
void BuilderResourceManifest::UpdateResource(Resource* pResource)
|
||||
{
|
||||
if (!m_toUpload.contains(pResource))
|
||||
{
|
||||
pResource->SetVersion(pResource->GetVersion() + 1);
|
||||
m_toUpload.push(pResource);
|
||||
}
|
||||
}
|
||||
|
||||
void BuilderResourceManifest::UseResource(const QString& id)
|
||||
{
|
||||
auto pResource = FindById(id, m_resources);
|
||||
if (!pResource)
|
||||
{
|
||||
return;
|
||||
}
|
||||
pResource->SetRefCount(pResource->GetRefCount() + 1);
|
||||
UpdateResource(pResource);
|
||||
}
|
||||
|
||||
void BuilderResourceManifest::FreeResource(const QString& id)
|
||||
{
|
||||
auto pResource = FindById(id, m_resources);
|
||||
if (!pResource)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (m_toDelete.contains(pResource))
|
||||
{
|
||||
return;
|
||||
}
|
||||
pResource->SetRefCount(pResource->GetRefCount() - 1);
|
||||
if (pResource->GetRefCount() <= 0)
|
||||
{
|
||||
m_toDelete.push(pResource);
|
||||
RemoveResource(pResource);
|
||||
m_toUpload.removeAll(pResource);
|
||||
|
||||
if (pResource->GetType().compare("article") == 0)
|
||||
{
|
||||
m_order.removeAll(pResource->GetId());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_toUpload.push(pResource);
|
||||
}
|
||||
}
|
||||
|
||||
bool BuilderResourceManifest::UpdateArticleOrder(const QString& id, bool direction, ErrorCode& error)
|
||||
{
|
||||
int index = m_order.indexOf(id);
|
||||
if (index == -1)
|
||||
{
|
||||
m_syncUpdateCallback(QString("Couldn't find article: %1").arg(id), LogError);
|
||||
error = ErrorCode::MissingArticle;
|
||||
return false;
|
||||
}
|
||||
m_order.removeAll(id);
|
||||
|
||||
index = index + (direction ? -1 : 1);
|
||||
if (index < 0)
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
if (index > m_order.count())
|
||||
{
|
||||
index = m_order.count();
|
||||
}
|
||||
m_order.insert(index, id);
|
||||
return true;
|
||||
}
|
||||
|
||||
EndpointManager* BuilderResourceManifest::GetEndpointManager() const
|
||||
{
|
||||
return m_endpointManager;
|
||||
}
|
||||
|
||||
void BuilderResourceManifest::Sync()
|
||||
{
|
||||
if (!m_endpointManager->GetSelectedEndpoint())
|
||||
{
|
||||
FailSync(ErrorCode::NoEndpoint);
|
||||
return;
|
||||
}
|
||||
if (!InitS3Connector())
|
||||
{
|
||||
FailSync(ErrorCode::S3Fail);
|
||||
return;
|
||||
}
|
||||
ResourceManifest::Sync();
|
||||
}
|
||||
|
||||
void BuilderResourceManifest::Reset()
|
||||
{
|
||||
if (s_syncing)
|
||||
{
|
||||
m_syncUpdateCallback("Sync is already running", LogError);
|
||||
return;
|
||||
}
|
||||
|
||||
m_toUpload.clear();
|
||||
|
||||
for (auto pResource : m_toDelete)
|
||||
{
|
||||
delete pResource;
|
||||
}
|
||||
m_toDelete.clear();
|
||||
|
||||
m_uidGenerator->Clear();
|
||||
|
||||
ResourceManifest::Reset();
|
||||
}
|
||||
|
||||
void BuilderResourceManifest::PersistLocalResources()
|
||||
{
|
||||
// we are switching to another manifest here, while having the local data still present
|
||||
// so we need to explicitly mark it for uploading so that it does not get deleted
|
||||
for (auto pResource : m_resources)
|
||||
{
|
||||
if (!m_toUpload.contains(pResource))
|
||||
{
|
||||
m_toUpload.push(pResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BuilderResourceManifest::SetSyncType(SyncType syncType)
|
||||
{
|
||||
m_syncType = syncType;
|
||||
}
|
||||
|
||||
bool BuilderResourceManifest::HasChanges() const
|
||||
{
|
||||
return m_toUpload.count() > 0 || m_toDelete.count() > 0;
|
||||
}
|
||||
|
||||
void BuilderResourceManifest::AppendResource(Resource* pResource)
|
||||
{
|
||||
m_uidGenerator->AddUid(pResource->GetId().toInt());
|
||||
ResourceManifest::AppendResource(pResource);
|
||||
}
|
||||
|
||||
void BuilderResourceManifest::RemoveResource(Resource* pResource)
|
||||
{
|
||||
m_uidGenerator->RemoveUid(pResource->GetId().toInt());
|
||||
ResourceManifest::RemoveResource(pResource);
|
||||
}
|
||||
|
||||
void BuilderResourceManifest::OnDownloadFail()
|
||||
{
|
||||
QMessageBox msgBox(QMessageBox::Critical,
|
||||
"Sync failed",
|
||||
QString("%1\n\n%2")
|
||||
.arg(GetErrorMessage(ErrorCode::ManifestDownloadFail))
|
||||
.arg(QObject::tr("Overwrite resource manifest?")),
|
||||
QMessageBox::Yes | QMessageBox::No);
|
||||
if (msgBox.exec() == QMessageBox::Yes)
|
||||
{
|
||||
if (!UploadManifest())
|
||||
{
|
||||
m_failed = true;
|
||||
m_errorCode = ErrorCode::ManifestUploadFail;
|
||||
}
|
||||
}
|
||||
ResourceManifest::OnDownloadFail();
|
||||
}
|
||||
|
||||
//! This function overrides ResourceManifest Read and tries to do some minimal version checking
|
||||
//! NOTE: version checking is not done yet, this needs a lot more work to version check properly
|
||||
ErrorCode BuilderResourceManifest::Read(const QJsonObject& json)
|
||||
{
|
||||
int version = json["version"].toInt();
|
||||
if (version > m_version && m_syncType == SyncType::Verify)
|
||||
{
|
||||
return ErrorCode::OutOfSync;
|
||||
}
|
||||
|
||||
m_version = version;
|
||||
QJsonArray resourceArray = json["resources"].toArray();
|
||||
|
||||
// initially mark ALL existing resource for deletion
|
||||
QList<Resource*> toDelete = m_resources;
|
||||
|
||||
for (auto resourceDoc : resourceArray)
|
||||
{
|
||||
auto pNewResource = new Resource(resourceDoc.toObject());
|
||||
// find local resource with the same id as new resource
|
||||
auto pOldResource = FindById(pNewResource->GetId(), m_resources);
|
||||
// if resource with the same id already exists then check its version
|
||||
if (pOldResource)
|
||||
{
|
||||
// local resource is outdated, keep its in delete list, and download new one instead
|
||||
if (pNewResource->GetVersion() > pOldResource->GetVersion())
|
||||
{
|
||||
if (m_syncType == SyncType::Merge)
|
||||
{
|
||||
m_toDownload.push(pNewResource);
|
||||
}
|
||||
else if (m_syncType == SyncType::Overwrite)
|
||||
{
|
||||
m_toDelete.push(pNewResource);
|
||||
}
|
||||
}
|
||||
// local resource is newer or same version, keep it (remove from toDelete list)
|
||||
// and don't need to download new one
|
||||
else
|
||||
{
|
||||
delete pNewResource;
|
||||
toDelete.removeAll(pOldResource);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// if remote resource was NOT deleted locally then download it
|
||||
if (!FindById(pNewResource->GetId(), m_toDelete))
|
||||
{
|
||||
if (m_syncType == SyncType::Merge)
|
||||
{
|
||||
m_toDownload.push(pNewResource);
|
||||
}
|
||||
else if (m_syncType == SyncType::Overwrite)
|
||||
{
|
||||
m_toDelete.push(pNewResource);
|
||||
}
|
||||
}
|
||||
// otherwise user deleted it... needs version check here
|
||||
else
|
||||
{
|
||||
delete pNewResource;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto pResource : m_toUpload)
|
||||
{
|
||||
toDelete.removeAll(pResource);
|
||||
}
|
||||
|
||||
for (auto pResource : toDelete)
|
||||
{
|
||||
RemoveResource(pResource);
|
||||
m_toDelete.removeAll(pResource);
|
||||
delete pResource;
|
||||
}
|
||||
|
||||
//! Sync article display order
|
||||
//! this is more complex to implement because articles may have been added or deleted
|
||||
//! remotely by another developer while newsbuilder was running
|
||||
//! for now just overwrite s3 version
|
||||
QJsonArray orderArray = json["order"].toArray();
|
||||
for (auto idObject : orderArray)
|
||||
{
|
||||
QString id = idObject.toString();
|
||||
if (FindById(id, m_toDownload) && !m_order.contains(id))
|
||||
{
|
||||
m_order.append(id);
|
||||
}
|
||||
}
|
||||
return ErrorCode::None;
|
||||
}
|
||||
|
||||
//! Write resource manifest to JSON
|
||||
void BuilderResourceManifest::Write(QJsonObject& json) const
|
||||
{
|
||||
QJsonArray resourceArray;
|
||||
foreach(auto pResource, m_resources)
|
||||
{
|
||||
QJsonObject resourceObject;
|
||||
pResource->Write(resourceObject);
|
||||
resourceArray.append(resourceObject);
|
||||
}
|
||||
json["resources"] = resourceArray;
|
||||
|
||||
QJsonArray orderArray;
|
||||
foreach(auto id, m_order)
|
||||
{
|
||||
orderArray.append(id);
|
||||
}
|
||||
json["order"] = orderArray;
|
||||
json["version"] = m_version;
|
||||
}
|
||||
|
||||
//! Figure out how many resources need to be synced
|
||||
void BuilderResourceManifest::PrepareForSync()
|
||||
{
|
||||
// if resource is locally marked for deletion, then we don't need to upload/download it
|
||||
for (auto pResource : m_toDelete)
|
||||
{
|
||||
m_toDownload.removeAll(pResource);
|
||||
m_toUpload.removeAll(pResource);
|
||||
}
|
||||
|
||||
m_syncLeft =
|
||||
m_toDownload.size() +
|
||||
m_toUpload.size() +
|
||||
m_toDelete.size();
|
||||
}
|
||||
|
||||
void BuilderResourceManifest::SyncResources()
|
||||
{
|
||||
ResourceManifest::SyncResources();
|
||||
UploadResources();
|
||||
DeleteResources();
|
||||
}
|
||||
|
||||
void BuilderResourceManifest::UploadResources()
|
||||
{
|
||||
QStack<Resource*> failures;
|
||||
while (m_toUpload.count() > 0)
|
||||
{
|
||||
m_syncUpdateCallback(
|
||||
QString("Uploading: %1 resources left").arg(m_toUpload.count()),
|
||||
LogInfo);
|
||||
|
||||
auto pResource = m_toUpload.pop();
|
||||
|
||||
auto uploadDescriptor = UploadDescriptor(*pResource);
|
||||
uploadDescriptor.Upload(*m_s3Connector,
|
||||
[&](QString url)
|
||||
{
|
||||
UpdateSync();
|
||||
},
|
||||
[&, pResource](QString error)
|
||||
{
|
||||
failures.push(pResource);
|
||||
m_failed = true;
|
||||
UpdateSync();
|
||||
m_syncUpdateCallback(
|
||||
error,
|
||||
LogError);
|
||||
});
|
||||
}
|
||||
while (failures.count() > 0)
|
||||
{
|
||||
m_toUpload.push(failures.pop());
|
||||
}
|
||||
}
|
||||
|
||||
void BuilderResourceManifest::DeleteResources()
|
||||
{
|
||||
while (m_toDelete.count() > 0)
|
||||
{
|
||||
m_syncUpdateCallback(
|
||||
QString("Deleting: %1 resources left").arg(m_toDelete.count()),
|
||||
LogInfo);
|
||||
|
||||
auto pResource = m_toDelete.pop();
|
||||
|
||||
auto deleteDescriptor = DeleteDescriptor(*pResource);
|
||||
deleteDescriptor.Delete(*m_s3Connector,
|
||||
[&, pResource]()
|
||||
{
|
||||
delete pResource;
|
||||
UpdateSync();
|
||||
},
|
||||
[&, pResource](QString error)
|
||||
{
|
||||
m_failed = true;
|
||||
delete pResource;
|
||||
UpdateSync();
|
||||
m_syncUpdateCallback(
|
||||
QString("Failed to delete resource: %1").arg(error),
|
||||
LogError);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void BuilderResourceManifest::FinishSync()
|
||||
{
|
||||
if (!m_failed)
|
||||
{
|
||||
QString error;
|
||||
if (!UploadManifest())
|
||||
{
|
||||
m_failed = true;
|
||||
m_errorCode = ErrorCode::ManifestUploadFail;
|
||||
}
|
||||
}
|
||||
ResourceManifest::FinishSync();
|
||||
}
|
||||
|
||||
bool BuilderResourceManifest::UploadManifest()
|
||||
{
|
||||
m_syncUpdateCallback(QObject::tr("%1 to %2")
|
||||
.arg("Uploading manifest")
|
||||
.arg(m_endpointManager->GetSelectedEndpoint()->GetBucket()),
|
||||
LogInfo);
|
||||
m_version++;
|
||||
Aws::String awsError;
|
||||
QJsonObject manifestObject;
|
||||
Write(manifestObject);
|
||||
QJsonDocument doc(manifestObject);
|
||||
auto ss = Aws::MakeShared<Aws::StringStream>(
|
||||
S3Connector::ALLOCATION_TAG,
|
||||
std::ios::in | std::ios::out | std::ios::binary);
|
||||
*ss << QString(doc.toJson(QJsonDocument::Compact)).toStdString();
|
||||
Aws::String url;
|
||||
if (!m_s3Connector->PutObject("resourceManifest", ss, url, awsError))
|
||||
{
|
||||
m_syncUpdateCallback(QObject::tr(awsError.c_str()), LogError);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BuilderResourceManifest::InitS3Connector() const
|
||||
{
|
||||
auto awsProfileName =
|
||||
m_endpointManager->GetSelectedEndpoint()->GetAwsProfile();
|
||||
auto bucketName =
|
||||
m_endpointManager->GetSelectedEndpoint()->GetBucket();
|
||||
Aws::String awsError;
|
||||
if (!m_s3Connector->Init(
|
||||
awsProfileName.toStdString().c_str(),
|
||||
bucketName.toStdString().c_str(),
|
||||
awsError))
|
||||
{
|
||||
m_syncUpdateCallback(QObject::tr(awsError.c_str()), LogError);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "NewsShared/ResourceManagement/ResourceManifest.h"
|
||||
|
||||
#include <QStack>
|
||||
|
||||
class QJsonObject;
|
||||
|
||||
namespace News
|
||||
{
|
||||
class EndpointManager;
|
||||
class ArticleDescriptor;
|
||||
class UidGenerator;
|
||||
class S3Connector;
|
||||
class QtDownloadManager;
|
||||
class Descriptor;
|
||||
class DownloadDescriptor;
|
||||
class Resource;
|
||||
|
||||
//! Type of sync behavior
|
||||
enum class SyncType
|
||||
{
|
||||
Merge, // merge resources from both endpoints, i.e. replacing outdated and appending missing (also normal sync behavior)
|
||||
Overwrite, // overwrite resources on new endpoint with old endpoint
|
||||
Verify // attempt to publish changes but abort if out of sync
|
||||
};
|
||||
|
||||
//! Adds news-builder functionality layer to resource manager
|
||||
class BuilderResourceManifest
|
||||
: public ResourceManifest
|
||||
{
|
||||
public:
|
||||
explicit BuilderResourceManifest(
|
||||
std::function<void()> syncSuccessCallback,
|
||||
std::function<void(ErrorCode)> syncFailCallback,
|
||||
std::function<void(QString, LogType)> syncUpdateCallback);
|
||||
|
||||
//! Create new article resource
|
||||
/*!
|
||||
Create new article with default parameters,
|
||||
Add it to resource collection,
|
||||
Mark it for upload.
|
||||
|
||||
\retval Resource * - a pointer to an article Resource
|
||||
*/
|
||||
Resource* AddArticle();
|
||||
|
||||
//! Create new image resource
|
||||
/*!
|
||||
Create new image from file,
|
||||
add it to resource collection,
|
||||
mark it for upload.
|
||||
|
||||
\param filename - path to an image on hard drive
|
||||
\retval Resource * - a pointer to an image Resource
|
||||
*/
|
||||
Resource* AddImage(const QString& filename);
|
||||
|
||||
//! If resource was modified, add it to upload list and increment its version
|
||||
void UpdateResource(Resource* resource);
|
||||
|
||||
//! When resource is used by several other resources, this function is called
|
||||
//! to increment its ref count
|
||||
void UseResource(const QString& id);
|
||||
|
||||
//! When resource is no longer used by another resource
|
||||
//! decrement refCount,
|
||||
//! if nothing else is using it, then mark for delete
|
||||
void FreeResource(const QString& id);
|
||||
|
||||
//! Move article either up or down in order queue
|
||||
bool UpdateArticleOrder(const QString& id, bool direction, ErrorCode& error);
|
||||
|
||||
EndpointManager* GetEndpointManager() const;
|
||||
|
||||
void Sync() override;
|
||||
|
||||
void Reset() override;
|
||||
|
||||
//! When switching endpoints Merge allows to persist resources to another endpoint,
|
||||
//! thus copying news from one location to another upon next Sync
|
||||
void PersistLocalResources();
|
||||
|
||||
void SetSyncType(SyncType syncType);
|
||||
|
||||
//! Are there local changes
|
||||
bool HasChanges() const;
|
||||
|
||||
protected:
|
||||
void AppendResource(Resource* pResource) override;
|
||||
void RemoveResource(Resource* pResource) override;
|
||||
void OnDownloadFail() override;
|
||||
void FinishSync() override;
|
||||
|
||||
private:
|
||||
S3Connector* m_s3Connector = nullptr;
|
||||
UidGenerator* m_uidGenerator = nullptr;
|
||||
EndpointManager* m_endpointManager = nullptr;
|
||||
SyncType m_syncType = SyncType::Merge;
|
||||
|
||||
QStack<Resource*> m_toUpload;
|
||||
QStack<Resource*> m_toDelete;
|
||||
|
||||
ErrorCode Read(const QJsonObject& json) override;
|
||||
void Write(QJsonObject& json) const;
|
||||
|
||||
void PrepareForSync() override;
|
||||
void SyncResources() override;
|
||||
|
||||
void UploadResources();
|
||||
void DeleteResources();
|
||||
|
||||
bool UploadManifest();
|
||||
|
||||
//! Initializes S3 connector with selected endpoint
|
||||
bool InitS3Connector() const;
|
||||
};
|
||||
} // namespace News
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "DeleteDescriptor.h"
|
||||
#include "NewsBuilder/S3Connector.h"
|
||||
#include "NewsShared/ResourceManagement/Resource.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace News
|
||||
{
|
||||
|
||||
DeleteDescriptor::DeleteDescriptor(Resource& resource)
|
||||
: Descriptor(resource) {}
|
||||
|
||||
void DeleteDescriptor::Delete(S3Connector& s3Connector,
|
||||
std::function<void()> deleteSuccessCallback,
|
||||
std::function<void(QString)> deleteFailCallback) const
|
||||
{
|
||||
Aws::String error;
|
||||
if (!s3Connector.DeleteObject(
|
||||
m_resource.GetId().toStdString().c_str(),
|
||||
error))
|
||||
{
|
||||
deleteFailCallback(QString("Error deleting resource %1: %2")
|
||||
.arg(m_resource.GetId())
|
||||
.arg(error.c_str()));
|
||||
}
|
||||
else
|
||||
{
|
||||
deleteSuccessCallback();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "NewsShared/ResourceManagement/Descriptor.h"
|
||||
|
||||
#include <QString>
|
||||
#include <functional>
|
||||
|
||||
namespace News
|
||||
{
|
||||
class S3Connector;
|
||||
|
||||
class DeleteDescriptor
|
||||
: public Descriptor
|
||||
{
|
||||
public:
|
||||
explicit DeleteDescriptor(Resource& resource);
|
||||
|
||||
void Delete(S3Connector& s3Connector,
|
||||
std::function<void()> deleteSuccessCallback,
|
||||
std::function<void(QString)> deleteFailCallback) const;
|
||||
};
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ImageDescriptor.h"
|
||||
#include "NewsShared/ResourceManagement/Resource.h"
|
||||
|
||||
#include <QImageReader>
|
||||
#include <QBuffer>
|
||||
#include <QPixmap>
|
||||
#include <QVariant>
|
||||
#include <QFile>
|
||||
|
||||
namespace News
|
||||
{
|
||||
|
||||
ImageDescriptor::ImageDescriptor(
|
||||
Resource& resource)
|
||||
: Descriptor(resource)
|
||||
{
|
||||
}
|
||||
|
||||
bool ImageDescriptor::Read(const QString& filename, QString& error) const
|
||||
{
|
||||
QImageReader reader(filename);
|
||||
if (!reader.canRead())
|
||||
{
|
||||
error = reader.errorString();
|
||||
return false;
|
||||
}
|
||||
QImage image = reader.read();
|
||||
|
||||
QPixmap pixmap(filename);
|
||||
QByteArray data;
|
||||
QBuffer buffer(&data);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
QFile test("test.png");
|
||||
if (pixmap.save(&buffer, "PNG"))
|
||||
{
|
||||
m_resource.SetData(data);
|
||||
return true;
|
||||
}
|
||||
error = QString("failed to save image %1").arg(filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <NewsShared/ResourceManagement/Descriptor.h>
|
||||
|
||||
class QString;
|
||||
|
||||
namespace News
|
||||
{
|
||||
class ImageDescriptor
|
||||
: public Descriptor
|
||||
{
|
||||
public:
|
||||
explicit ImageDescriptor(Resource& resource);
|
||||
|
||||
bool Read(const QString& filename, QString& error) const;
|
||||
};
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "NewsBuilder/S3Connector.h"
|
||||
#include "UploadDescriptor.h"
|
||||
#include "NewsShared/ResourceManagement/Resource.h"
|
||||
|
||||
#include <functional>
|
||||
#include <aws/core/utils/memory/stl/AwsStringStream.h>
|
||||
#include <aws/core/utils/memory/stl/AWSStreamFwd.h>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace News
|
||||
{
|
||||
|
||||
UploadDescriptor::UploadDescriptor(Resource& resource)
|
||||
: Descriptor(resource) {}
|
||||
|
||||
void UploadDescriptor::Upload(S3Connector& s3Connector,
|
||||
std::function<void(QString)> uploadSuccessCallback,
|
||||
std::function<void(QString)> uploadFailCallback) const
|
||||
{
|
||||
Aws::String error;
|
||||
|
||||
auto ss =
|
||||
Aws::MakeShared<Aws::StringStream>(S3Connector::ALLOCATION_TAG,
|
||||
std::ios::in | std::ios::out | std::ios::binary);
|
||||
auto* pbuf = ss->rdbuf();
|
||||
pbuf->sputn(m_resource.GetData().data(), m_resource.GetData().size());
|
||||
Aws::String awsUrl;
|
||||
|
||||
if (!s3Connector.PutObject(
|
||||
m_resource.GetId().toStdString().c_str(),
|
||||
ss,
|
||||
m_resource.GetData().size(),
|
||||
awsUrl,
|
||||
error))
|
||||
{
|
||||
uploadFailCallback(QObject::tr("Error uploading resource %1: %2")
|
||||
.arg(m_resource.GetId())
|
||||
.arg(error.c_str()));
|
||||
}
|
||||
else
|
||||
{
|
||||
uploadSuccessCallback(QString(awsUrl.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "NewsShared/ResourceManagement/Descriptor.h"
|
||||
|
||||
#include <QString>
|
||||
#include <functional>
|
||||
|
||||
namespace News
|
||||
{
|
||||
class S3Connector;
|
||||
|
||||
class UploadDescriptor
|
||||
: public Descriptor
|
||||
{
|
||||
public:
|
||||
explicit UploadDescriptor(Resource& resource);
|
||||
|
||||
void Upload(S3Connector& s3Connector,
|
||||
std::function<void(QString)> uploadSuccessCallback,
|
||||
std::function<void(QString)> uploadFailCallback) const;
|
||||
};
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
QLabel
|
||||
{
|
||||
font-size: 12px;
|
||||
color: #FFFFFF;
|
||||
line-height: 20px;
|
||||
background-color: transparent;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
QLabel#titleLabel
|
||||
{
|
||||
font-size: 22px;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
QLabel#bodyLabel
|
||||
{
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
QFrame#viewContainer[articleStyle="pinned"]
|
||||
{
|
||||
background: rgba(180,139,255,5%);
|
||||
border: 1px solid #B48BFF;
|
||||
box-shadow: 0 0 4px 0 rgba(0,0,0,50%);
|
||||
}
|
||||
|
||||
QWidget#articleViewContainerRoot
|
||||
{
|
||||
background: #222222;
|
||||
}
|
||||
|
||||
QScrollArea#previewArea,
|
||||
QWidget#articleViewContents,
|
||||
QFrame#imageFrame
|
||||
{
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
News--ArticleView.SelectedArticle > QWidget
|
||||
{
|
||||
background: #333333;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4255a25636d77a54809592bc98bef47fa9044be03cd65d73daa821711489e00f
|
||||
size 7379
|
||||
@@ -1,173 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "S3Connector.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <AzFramework/AzFramework_Traits_Platform.h>
|
||||
|
||||
|
||||
AZ_PUSH_DISABLE_WARNING(4251 4819, "-Wunknown-warning-option") // Invalid character not in default code page
|
||||
#include <aws/core/auth/AWSCredentialsProviderChain.h>
|
||||
#include <aws/core/utils/Outcome.h>
|
||||
#include <aws/s3/model/PutObjectRequest.h>
|
||||
#include <aws/s3/model/GetObjectRequest.h>
|
||||
#include <aws/s3/model/DeleteObjectRequest.h>
|
||||
#include <aws/core/utils/memory/stl/AwsStringStream.h>
|
||||
#include <aws/core/utils/HashingUtils.h>
|
||||
#include <aws/core/Aws.h>
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
namespace News
|
||||
{
|
||||
const char* S3Connector::ALLOCATION_TAG = "NewsBuilder";
|
||||
|
||||
S3Connector::S3Connector()
|
||||
: m_s3Client(nullptr)
|
||||
, m_limiter(nullptr)
|
||||
, m_valid(false)
|
||||
{
|
||||
}
|
||||
|
||||
S3Connector::~S3Connector() {}
|
||||
|
||||
bool S3Connector::Init(const char* awsProfileName, const char* bucket, Aws::String& error)
|
||||
{
|
||||
Aws::SDKOptions options;
|
||||
options.loggingOptions.logLevel = Aws::Utils::Logging::LogLevel::Trace;
|
||||
Aws::InitAPI(options);
|
||||
|
||||
Aws::Client::ClientConfiguration config;
|
||||
config.enableTcpKeepAlive = AZ_TRAIT_AZFRAMEWORK_AWS_ENABLE_TCP_KEEP_ALIVE_SUPPORTED;
|
||||
config.scheme = Aws::Http::Scheme::HTTPS;
|
||||
config.connectTimeoutMs = 30000;
|
||||
config.requestTimeoutMs = 30000;
|
||||
config.readRateLimiter = m_limiter;
|
||||
config.writeRateLimiter = m_limiter;
|
||||
|
||||
auto provider =
|
||||
Aws::MakeShared<Aws::Auth::ProfileConfigFileAWSCredentialsProvider>(
|
||||
ALLOCATION_TAG,
|
||||
awsProfileName);
|
||||
|
||||
auto accessKeyId = provider->GetAWSCredentials().GetAWSAccessKeyId();
|
||||
|
||||
//! verify that credential file exists
|
||||
if (accessKeyId.empty())
|
||||
{
|
||||
error = "LY_NEWS_DEVELOPER AWS credentials not found. Add credentials in LY Editor AWS->ClientManager";
|
||||
m_valid = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_bucket = Aws::String(bucket);
|
||||
m_s3Client = Aws::MakeShared<Aws::S3::S3Client>(
|
||||
ALLOCATION_TAG,
|
||||
provider,
|
||||
config);
|
||||
|
||||
m_valid = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool S3Connector::GetObject(const char* key,
|
||||
Aws::String& data,
|
||||
Aws::String& url,
|
||||
Aws::String& error) const
|
||||
{
|
||||
if (!m_valid)
|
||||
{
|
||||
error = "Client not initialized";
|
||||
return false;
|
||||
}
|
||||
|
||||
Aws::S3::Model::GetObjectRequest getObjectRequest;
|
||||
getObjectRequest.SetBucket(m_bucket);
|
||||
getObjectRequest.SetKey(key);
|
||||
auto outcome = m_s3Client->GetObject(getObjectRequest);
|
||||
if (!outcome.IsSuccess())
|
||||
{
|
||||
error = outcome.GetError().GetMessage();
|
||||
return false;
|
||||
}
|
||||
url = m_s3Client->GeneratePresignedUrl(m_bucket, key, Aws::Http::HttpMethod::HTTP_GET);
|
||||
Aws::StringStream ss;
|
||||
ss << outcome.GetResult().GetBody().rdbuf();
|
||||
data = ss.str();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool S3Connector::PutObject(const char* key,
|
||||
STREAM_PTR stream,
|
||||
Aws::String& url,
|
||||
Aws::String& error) const
|
||||
{
|
||||
return PutObject(key, stream, GetStreamLength(stream), url, error);
|
||||
}
|
||||
|
||||
bool S3Connector::PutObject(const char* key,
|
||||
STREAM_PTR stream,
|
||||
int length,
|
||||
Aws::String& url,
|
||||
Aws::String& error) const
|
||||
{
|
||||
if (!m_valid)
|
||||
{
|
||||
error = "Client not initialized";
|
||||
return false;
|
||||
}
|
||||
|
||||
Aws::S3::Model::PutObjectRequest putObjectRequest;
|
||||
putObjectRequest.SetBucket(m_bucket);
|
||||
putObjectRequest.SetBody(stream);
|
||||
putObjectRequest.SetContentLength(length);
|
||||
putObjectRequest.SetContentMD5(
|
||||
Aws::Utils::HashingUtils::Base64Encode(
|
||||
Aws::Utils::HashingUtils::CalculateMD5(*putObjectRequest.GetBody())));
|
||||
putObjectRequest.SetContentType(Aws::String("binary/octet-stream"));
|
||||
putObjectRequest.SetKey(key);
|
||||
putObjectRequest.SetACL(Aws::S3::Model::ObjectCannedACL::public_read);
|
||||
auto outcome = m_s3Client->PutObject(putObjectRequest);
|
||||
if (!outcome.IsSuccess())
|
||||
{
|
||||
error = outcome.GetError().GetMessage();
|
||||
return false;
|
||||
}
|
||||
url = m_s3Client->GeneratePresignedUrl(m_bucket, key, Aws::Http::HttpMethod::HTTP_GET);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool S3Connector::DeleteObject(const char* key, Aws::String& error) const
|
||||
{
|
||||
if (!m_valid)
|
||||
{
|
||||
error = "Client not initialized";
|
||||
return false;
|
||||
}
|
||||
|
||||
Aws::S3::Model::DeleteObjectRequest deleteObjectRequest;
|
||||
deleteObjectRequest.SetBucket(m_bucket);
|
||||
deleteObjectRequest.SetKey(key);
|
||||
auto outcome = m_s3Client->DeleteObject(deleteObjectRequest);
|
||||
if (!outcome.IsSuccess())
|
||||
{
|
||||
error = outcome.GetError().GetMessage();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int S3Connector::GetStreamLength(STREAM_PTR stream)
|
||||
{
|
||||
stream->seekg(0, std::ios::end);
|
||||
auto length = stream->tellg();
|
||||
stream->seekg(0, std::ios::beg);
|
||||
return static_cast<int>(length);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/PlatformDef.h>
|
||||
#include <memory>
|
||||
AZ_PUSH_DISABLE_WARNING(4251 4355 4996, "-Wunknown-warning-option") // <future> includes ppltasks.h which throws a C4355 warning: 'this' used in base member initializer list
|
||||
#include <aws/s3/S3Client.h>
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
typedef std::shared_ptr<Aws::IOStream> STREAM_PTR;
|
||||
|
||||
namespace News
|
||||
{
|
||||
//! A light wrapper around AWS SDK
|
||||
class S3Connector
|
||||
{
|
||||
public:
|
||||
static const char* ALLOCATION_TAG;
|
||||
|
||||
S3Connector();
|
||||
~S3Connector();
|
||||
|
||||
//! Make s3 client using credentials stored in [user]/.aws/credentials file
|
||||
/*!
|
||||
\param awsProfileName - name of AWS credentials
|
||||
\param bucket - name of s3 bucket to use for AWS operations
|
||||
\param error - error string
|
||||
\retval bool - true if success else false
|
||||
*/
|
||||
bool Init(const char* awsProfileName, const char* bucket, Aws::String& error);
|
||||
|
||||
bool GetObject(const char* key,
|
||||
Aws::String& data,
|
||||
Aws::String& url,
|
||||
Aws::String& error) const;
|
||||
|
||||
bool PutObject(const char* key,
|
||||
STREAM_PTR stream,
|
||||
Aws::String& url,
|
||||
Aws::String& error) const;
|
||||
|
||||
bool PutObject(const char* key,
|
||||
STREAM_PTR stream,
|
||||
int length,
|
||||
Aws::String& url,
|
||||
Aws::String& error) const;
|
||||
|
||||
bool DeleteObject(const char* key,
|
||||
Aws::String& error) const;
|
||||
|
||||
private:
|
||||
Aws::String m_bucket;
|
||||
std::shared_ptr<Aws::S3::S3Client> m_s3Client;
|
||||
std::shared_ptr<Aws::Utils::RateLimits::RateLimiterInterface> m_limiter;
|
||||
bool m_valid;
|
||||
|
||||
static int GetStreamLength(STREAM_PTR stream);
|
||||
};
|
||||
} // namespace News
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "UidGenerator.h"
|
||||
|
||||
#include <ctime>
|
||||
|
||||
namespace News
|
||||
{
|
||||
|
||||
UidGenerator::UidGenerator()
|
||||
{
|
||||
srand(static_cast<int>(time(nullptr)));
|
||||
}
|
||||
|
||||
int UidGenerator::GenerateUid()
|
||||
{
|
||||
int uid;
|
||||
do
|
||||
{
|
||||
uid = rand();
|
||||
}
|
||||
while (std::find(m_uids.begin(), m_uids.end(), uid) != m_uids.end());
|
||||
m_uids.push_back(uid);
|
||||
return uid;
|
||||
}
|
||||
|
||||
int UidGenerator::AddUid(int uid)
|
||||
{
|
||||
if (std::find(m_uids.begin(), m_uids.end(), uid) == m_uids.end())
|
||||
{
|
||||
m_uids.push_back(uid);
|
||||
}
|
||||
return uid;
|
||||
}
|
||||
|
||||
void UidGenerator::RemoveUid(int uid)
|
||||
{
|
||||
auto it = std::find(m_uids.begin(), m_uids.end(), uid);
|
||||
if (it != m_uids.end())
|
||||
{
|
||||
m_uids.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void UidGenerator::Clear()
|
||||
{
|
||||
m_uids.clear();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace News
|
||||
{
|
||||
//! A simple unique id generator.
|
||||
class UidGenerator
|
||||
{
|
||||
public:
|
||||
UidGenerator();
|
||||
int GenerateUid();
|
||||
int AddUid(int uid);
|
||||
void RemoveUid(int uid);
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
std::vector<int> m_uids;
|
||||
};
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <QApplication>
|
||||
|
||||
#include "Qt/NewsBuilder.h"
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Component/ComponentApplication.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// Must be set before QApplication is initialized, so that we support HighDpi monitors, like the Retina displays
|
||||
// on Windows 10
|
||||
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||
|
||||
QApplication a(argc, argv);
|
||||
AZ::IO::FixedMaxPath engineRootPath;
|
||||
{
|
||||
AZ::ComponentApplication componentApplication;
|
||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
||||
settingsRegistry->Get(engineRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder);
|
||||
}
|
||||
News::NewsBuilder w(nullptr, engineRootPath);
|
||||
w.show();
|
||||
return a.exec();
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource>
|
||||
<file>Resources/NewsBuilder.qss</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -1,64 +0,0 @@
|
||||
#
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
#
|
||||
|
||||
set(FILES
|
||||
main.cpp
|
||||
S3Connector.cpp
|
||||
S3Connector.h
|
||||
UidGenerator.cpp
|
||||
UidGenerator.h
|
||||
EndpointManager.cpp
|
||||
EndpointManager.h
|
||||
Qt/ArticleDetails.cpp
|
||||
Qt/ArticleDetails.h
|
||||
Qt/ArticleDetails.ui
|
||||
Qt/ArticleDetailsContainer.cpp
|
||||
Qt/ArticleDetailsContainer.h
|
||||
Qt/ArticleDetailsContainer.ui
|
||||
Qt/AwsDialog.ui
|
||||
Qt/BuilderArticleViewContainer.cpp
|
||||
Qt/BuilderArticleViewContainer.h
|
||||
Qt/BuilderArticleViewContainer.ui
|
||||
Qt/EndpointEntryView.cpp
|
||||
Qt/EndpointEntryView.h
|
||||
Qt/EndpointEntryView.ui
|
||||
Qt/EndpointManagerView.cpp
|
||||
Qt/EndpointManagerView.h
|
||||
Qt/EndpointManagerView.ui
|
||||
Qt/ImageItem.cpp
|
||||
Qt/ImageItem.h
|
||||
Qt/ImageItem.ui
|
||||
Qt/LogContainer.cpp
|
||||
Qt/LogContainer.h
|
||||
Qt/LogContainer.ui
|
||||
Qt/NewsBuilder.cpp
|
||||
Qt/NewsBuilder.h
|
||||
Qt/Newsbuilder.qrc
|
||||
Qt/Newsbuilder.ui
|
||||
Qt/QCustomMessageBox.cpp
|
||||
Qt/QCustomMessageBox.h
|
||||
Qt/QCustomMessageBox.ui
|
||||
Qt/SelectImage.cpp
|
||||
Qt/SelectImage.h
|
||||
Qt/SelectImage.ui
|
||||
ResourceManagement/BuilderResourceManifest.cpp
|
||||
ResourceManagement/BuilderResourceManifest.h
|
||||
ResourceManagement/DeleteDescriptor.cpp
|
||||
ResourceManagement/DeleteDescriptor.h
|
||||
ResourceManagement/ImageDescriptor.cpp
|
||||
ResourceManagement/ImageDescriptor.h
|
||||
ResourceManagement/UploadDescriptor.cpp
|
||||
ResourceManagement/UploadDescriptor.h
|
||||
)
|
||||
|
||||
set(SKIP_UNITY_BUILD_INCLUSION_FILES
|
||||
# Fix for unity causing the 'News::BuilderResourceManifest::UpdateResourceA' symbol to be unresolved
|
||||
Qt/ArticleDetails.cpp
|
||||
# Fix for unity causing the ' Aws::S3::S3Client::GetObjectA' symbol to be unresolved
|
||||
S3Connector.cpp
|
||||
|
||||
)
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
|
||||
namespace News
|
||||
{
|
||||
enum class ErrorCode : int
|
||||
{
|
||||
None,
|
||||
OutOfSync,
|
||||
ManifestDownloadFail,
|
||||
FailedToSync,
|
||||
AlreadySyncing,
|
||||
FailedToParseManifest,
|
||||
MissingArticle,
|
||||
NoEndpoint,
|
||||
ManifestUploadFail,
|
||||
S3Fail
|
||||
};
|
||||
|
||||
inline extern const char* GetErrorMessage(ErrorCode errorCode)
|
||||
{
|
||||
static const char* errors[]
|
||||
{
|
||||
"",
|
||||
"Your manifest is out of sync. Reopen the same endpoint and sync to resolve the conflict and try again.",
|
||||
"Failed to download resource manifest",
|
||||
"Failed to sync resources",
|
||||
"Sync is already running",
|
||||
"Failed to parse resource manifest",
|
||||
"Could not find article, try syncing again",
|
||||
"Missing or incorrect endpoint selected",
|
||||
"Failed to upload resource manifest",
|
||||
"Failed to init S3 connection"
|
||||
};
|
||||
int errorCount = sizeof errors / sizeof errors[0];
|
||||
int typeIndex = static_cast<int>(errorCode);
|
||||
if (typeIndex < 0 || typeIndex >= errorCount)
|
||||
{
|
||||
return "Invalid error code";
|
||||
}
|
||||
return errors[typeIndex];
|
||||
}
|
||||
} // namespace News
|
||||
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace News {
|
||||
enum LogType
|
||||
{
|
||||
LogOk,
|
||||
LogInfo,
|
||||
LogError,
|
||||
LogWarning
|
||||
};
|
||||
} // namespace News
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ArticleErrorView.h"
|
||||
#include "NewsShared/Qt/ui_ArticleErrorView.h"
|
||||
|
||||
using namespace News;
|
||||
|
||||
ArticleErrorView::ArticleErrorView(
|
||||
QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_ui(new Ui::ArticleErrorViewWidget())
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
}
|
||||
|
||||
ArticleErrorView::~ArticleErrorView(){}
|
||||
|
||||
#include "NewsShared/Qt/moc_ArticleErrorView.cpp"
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QWidget>
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class ArticleErrorViewWidget;
|
||||
}
|
||||
|
||||
namespace AzQtComponents
|
||||
{
|
||||
class ExtendedLabel;
|
||||
}
|
||||
|
||||
namespace News
|
||||
{
|
||||
class ArticleErrorView
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ArticleErrorView(QWidget* parent);
|
||||
~ArticleErrorView();
|
||||
|
||||
private:
|
||||
QScopedPointer<Ui::ArticleErrorViewWidget> m_ui;
|
||||
};
|
||||
}
|
||||
@@ -1,239 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ArticleErrorViewWidget</class>
|
||||
<widget class="QWidget" name="ArticleErrorViewWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>192</width>
|
||||
<height>228</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>ArticleView</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: none; text-align: left;</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">border: none;</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>14</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>14</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="AzQtComponents::ExtendedLabel" name="label">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>160</width>
|
||||
<height>90</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="NewsShared.qrc">:/images/Resources/ErrorImage.jpg</pixmap>
|
||||
</property>
|
||||
<property name="pixmapSize" stdset="0">
|
||||
<size>
|
||||
<width>160</width>
|
||||
<height>90</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="titleLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Open Sans</family>
|
||||
<pointsize>8</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">a { text-decoration: underline; color: red }</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>We couldn’t connect to the network or access our news database. To see the latest Open 3D Engine news, blogs, tutorials, and more, please visit the <a href="http://aws.amazon.com/lumberyard/">Lumberyard website</a>.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>14</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>AzQtComponents::ExtendedLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>AzQtComponents/Components/ExtendedLabel.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="NewsShared.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,154 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ArticleView.h"
|
||||
|
||||
#include <AzQtComponents/Components/ExtendedLabel.h>
|
||||
|
||||
AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 4251: '...' needs to have dll-interface to be used by clients of class '...'
|
||||
#include "NewsShared/ResourceManagement/ArticleDescriptor.h"
|
||||
#include "NewsShared/Qt/ui_ArticleView.h"
|
||||
#include "NewsShared/Qt/ui_PinnedArticleView.h"
|
||||
#include "NewsShared/ResourceManagement/ResourceManifest.h"
|
||||
#include "NewsShared/ResourceManagement/Resource.h"
|
||||
|
||||
|
||||
#include <QDesktopServices>
|
||||
#include <QUrl>
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
using namespace News;
|
||||
|
||||
ArticleView::ArticleView(
|
||||
QWidget* parent,
|
||||
const ArticleDescriptor& article,
|
||||
const ResourceManifest& manifest)
|
||||
: QWidget(parent)
|
||||
, m_pArticle(new ArticleDescriptor(article))
|
||||
, m_manifest(manifest)
|
||||
, m_icon(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ArticleView::Update()
|
||||
{
|
||||
Q_ASSERT(m_widgetImageFrame && m_widgetTitle && m_widgetBody);
|
||||
|
||||
auto pResource = m_manifest.FindById(m_pArticle->GetResource().GetId());
|
||||
m_pArticle.reset();
|
||||
if (pResource)
|
||||
{
|
||||
m_pArticle = QSharedPointer<ArticleDescriptor>(new ArticleDescriptor(*pResource));
|
||||
m_widgetTitle->setText(m_pArticle->GetTitle());
|
||||
m_widgetBody->setText(m_pArticle->GetBody());
|
||||
auto pImageResource = m_manifest.FindById(m_pArticle->GetImageId());
|
||||
if (pImageResource)
|
||||
{
|
||||
QPixmap pixmap;
|
||||
if (pixmap.loadFromData(pImageResource->GetData()))
|
||||
{
|
||||
if (!m_icon)
|
||||
{
|
||||
m_icon = new AzQtComponents::ExtendedLabel(this);
|
||||
m_icon->setStyleSheet("border: none;");
|
||||
m_icon->setAlignment(Qt::AlignCenter);
|
||||
static_cast<QVBoxLayout*>(
|
||||
m_widgetImageFrame->layout())->insertWidget(0, m_icon);
|
||||
connect(m_icon, &AzQtComponents::ExtendedLabel::clicked, this, &ArticleView::articleSelectedSlot);
|
||||
}
|
||||
m_icon->setPixmap(pixmap.scaled(m_widgetImageFrame->minimumWidth(),
|
||||
m_widgetImageFrame->minimumHeight(),
|
||||
Qt::KeepAspectRatioByExpanding));
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveIcon();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveIcon();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ArticleView::mousePressEvent([[maybe_unused]] QMouseEvent* event)
|
||||
{
|
||||
articleSelectedSlot();
|
||||
}
|
||||
|
||||
void ArticleView::RemoveIcon()
|
||||
{
|
||||
if (m_icon)
|
||||
{
|
||||
delete m_icon;
|
||||
m_icon = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void ArticleView::linkActivatedSlot(const QString& link)
|
||||
{
|
||||
QDesktopServices::openUrl(QUrl(link));
|
||||
Q_EMIT linkActivatedSignal(link);
|
||||
}
|
||||
|
||||
void ArticleView::articleSelectedSlot()
|
||||
{
|
||||
Q_EMIT articleSelectedSignal(m_pArticle->GetResource().GetId());
|
||||
}
|
||||
|
||||
QSharedPointer<const ArticleDescriptor> ArticleView::GetArticle() const
|
||||
{
|
||||
return m_pArticle;
|
||||
}
|
||||
|
||||
void ArticleView::SetupViewWidget(QFrame* widgetImageFrame, AzQtComponents::ExtendedLabel* widgetTitle, AzQtComponents::ExtendedLabel* widgetBody)
|
||||
{
|
||||
Q_ASSERT(m_widgetImageFrame == nullptr && m_widgetTitle == nullptr && m_widgetBody == nullptr);
|
||||
|
||||
m_widgetImageFrame = widgetImageFrame;
|
||||
m_widgetTitle = widgetTitle;
|
||||
m_widgetBody = widgetBody;
|
||||
|
||||
connect(m_widgetTitle, &QLabel::linkActivated, this, &ArticleView::linkActivatedSlot);
|
||||
connect(m_widgetBody, &QLabel::linkActivated, this, &ArticleView::linkActivatedSlot);
|
||||
connect(m_widgetTitle, &AzQtComponents::ExtendedLabel::clicked, this, &ArticleView::articleSelectedSlot);
|
||||
connect(m_widgetBody, &AzQtComponents::ExtendedLabel::clicked, this, &ArticleView::articleSelectedSlot);
|
||||
|
||||
Q_ASSERT(m_widgetImageFrame && m_widgetTitle && m_widgetBody);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ArticleViewDefaultWidget
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
ArticleViewDefaultWidget::ArticleViewDefaultWidget(QWidget* parent,
|
||||
const ArticleDescriptor& article,
|
||||
const ResourceManifest& manifest)
|
||||
: ArticleView(parent, article, manifest)
|
||||
, m_ui(new Ui::ArticleViewWidget())
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
SetupViewWidget(m_ui->imageFrame, m_ui->titleLabel, m_ui->bodyLabel);
|
||||
Update();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ArticleViewPinnedWidget
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
ArticleViewPinnedWidget::ArticleViewPinnedWidget(QWidget* parent,
|
||||
const ArticleDescriptor& article,
|
||||
const ResourceManifest& manifest)
|
||||
: ArticleView(parent, article, manifest)
|
||||
, m_ui(new Ui::PinnedArticleViewWidget())
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
SetupViewWidget(m_ui->imageFrame, m_ui->titleLabel, m_ui->bodyLabel);
|
||||
Update();
|
||||
}
|
||||
|
||||
#include "NewsShared/Qt/moc_ArticleView.cpp"
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QWidget>
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class ArticleViewWidget;
|
||||
class PinnedArticleViewWidget;
|
||||
}
|
||||
|
||||
namespace AzQtComponents
|
||||
{
|
||||
class ExtendedLabel;
|
||||
}
|
||||
|
||||
class QFrame;
|
||||
|
||||
namespace News
|
||||
{
|
||||
class ArticleDescriptor;
|
||||
class ResourceManifest;
|
||||
|
||||
class ArticleView
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ArticleView(QWidget* parent,
|
||||
const ArticleDescriptor& article,
|
||||
const ResourceManifest& manifest);
|
||||
~ArticleView() = default;
|
||||
|
||||
void Update();
|
||||
QSharedPointer<const ArticleDescriptor> GetArticle() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void articleSelectedSignal(QString resourceId);
|
||||
void linkActivatedSignal(const QString& link);
|
||||
|
||||
protected:
|
||||
void SetupViewWidget(QFrame* widgetImageFrame, AzQtComponents::ExtendedLabel* widgetTitle, AzQtComponents::ExtendedLabel* widgetBody);
|
||||
void mousePressEvent(QMouseEvent* event);
|
||||
|
||||
private:
|
||||
|
||||
QFrame* m_widgetImageFrame = nullptr;
|
||||
AzQtComponents::ExtendedLabel* m_widgetTitle = nullptr;
|
||||
AzQtComponents::ExtendedLabel* m_widgetBody = nullptr;
|
||||
AzQtComponents::ExtendedLabel* m_icon = nullptr;
|
||||
|
||||
QSharedPointer<const ArticleDescriptor> m_pArticle;
|
||||
const ResourceManifest& m_manifest;
|
||||
|
||||
void RemoveIcon();
|
||||
|
||||
private Q_SLOTS:
|
||||
void linkActivatedSlot(const QString& link);
|
||||
void articleSelectedSlot();
|
||||
};
|
||||
|
||||
class ArticleViewDefaultWidget : public ArticleView
|
||||
{
|
||||
public:
|
||||
ArticleViewDefaultWidget(QWidget* parent,
|
||||
const ArticleDescriptor& article,
|
||||
const ResourceManifest& manifest);
|
||||
~ArticleViewDefaultWidget() = default;
|
||||
|
||||
private:
|
||||
Ui::ArticleViewWidget* m_ui = nullptr;
|
||||
};
|
||||
|
||||
class ArticleViewPinnedWidget : public ArticleView
|
||||
{
|
||||
public:
|
||||
ArticleViewPinnedWidget(QWidget* parent,
|
||||
const ArticleDescriptor& article,
|
||||
const ResourceManifest& manifest);
|
||||
~ArticleViewPinnedWidget() = default;
|
||||
|
||||
private:
|
||||
Ui::PinnedArticleViewWidget* m_ui = nullptr;
|
||||
};
|
||||
}
|
||||
@@ -1,244 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ArticleViewWidget</class>
|
||||
<widget class="QWidget" name="ArticleViewWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>430</width>
|
||||
<height>376</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>430</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>430</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>ArticleView</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="viewContainer">
|
||||
<property name="articleStyle" stdset="0">
|
||||
<string>default</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="imageFrame">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>430</width>
|
||||
<height>184</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>430</width>
|
||||
<height>184</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="AzQtComponents::ExtendedLabel" name="titleLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Open Sans</family>
|
||||
<pointsize>14</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Title:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>12</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="AzQtComponents::ExtendedLabel" name="bodyLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Open Sans</family>
|
||||
<pointsize>8</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Body</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="indent">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>AzQtComponents::ExtendedLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>AzQtComponents/Components/ExtendedLabel.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,266 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ArticleViewContainer.h"
|
||||
#include "ArticleView.h"
|
||||
#include "NewsShared/ResourceManagement/ResourceManifest.h"
|
||||
#include "NewsShared/ResourceManagement/ArticleDescriptor.h"
|
||||
#include "NewsShared/ResourceManagement/Resource.h"
|
||||
#include "NewsShared/Qt/ArticleErrorView.h"
|
||||
#include "NewsShared/Qt/KeepInTouchView.h"
|
||||
#include "NewsShared/Qt/ui_ArticleViewContainer.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QMap>
|
||||
|
||||
namespace News
|
||||
{
|
||||
|
||||
ArticleViewContainer::ArticleViewContainer(QWidget* parent, ResourceManifest& manifest)
|
||||
: QWidget(parent)
|
||||
, m_ui(new Ui::ArticleViewContainerWidget)
|
||||
, m_manifest(manifest)
|
||||
, m_loadingLabel(nullptr)
|
||||
, m_errorMessage(nullptr)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
AddLoadingMessage();
|
||||
|
||||
m_keepInTouchViewWidget = new KeepInTouchView(this);
|
||||
m_keepInTouchViewWidget->setVisible(false);
|
||||
connect(m_keepInTouchViewWidget, &KeepInTouchView::linkActivatedSignal,
|
||||
this, &ArticleViewContainer::linkActivatedSignal);
|
||||
}
|
||||
|
||||
ArticleViewContainer::~ArticleViewContainer() {}
|
||||
|
||||
void ArticleViewContainer::PopulateArticles()
|
||||
{
|
||||
Clear();
|
||||
|
||||
bool articlesFound = false;
|
||||
for (auto id : m_manifest.GetOrder())
|
||||
{
|
||||
auto pResource = m_manifest.FindById(id);
|
||||
if (pResource && pResource->GetType().compare("article") == 0)
|
||||
{
|
||||
AddArticleView(ArticleDescriptor(*pResource));
|
||||
articlesFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!articlesFound)
|
||||
{
|
||||
AddErrorMessage();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto layout = static_cast<QVBoxLayout*>(m_ui->articleViewContents->layout());
|
||||
layout->insertWidget(layout->count() - 1, m_keepInTouchViewWidget);
|
||||
m_keepInTouchViewWidget->setVisible(true);
|
||||
}
|
||||
|
||||
qApp->processEvents();
|
||||
}
|
||||
|
||||
ArticleView* ArticleViewContainer::FindById(const QString& id)
|
||||
{
|
||||
auto it = std::find_if(
|
||||
m_articles.begin(),
|
||||
m_articles.end(),
|
||||
[id](ArticleView* articleView) -> bool
|
||||
{
|
||||
if (!articleView)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return articleView->GetArticle()->GetResource().GetId().compare(id) == 0;
|
||||
});
|
||||
if (it == m_articles.end())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return *it;
|
||||
}
|
||||
|
||||
void ArticleViewContainer::AddArticleView(const ArticleDescriptor& articleDesc, int articlePosition)
|
||||
{
|
||||
ClearError();
|
||||
|
||||
ArticleView* view = CreateArticleView(articleDesc);
|
||||
if (view == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_articles.append(view);
|
||||
|
||||
connect(view, &ArticleView::articleSelectedSignal,
|
||||
this, &ArticleViewContainer::articleSelectedSlot);
|
||||
connect(view, &ArticleView::linkActivatedSignal,
|
||||
this, &ArticleViewContainer::linkActivatedSignal);
|
||||
|
||||
auto layout = static_cast<QVBoxLayout*>(m_ui->articleViewContents->layout());
|
||||
if (articlePosition == -1)
|
||||
{
|
||||
articlePosition = layout->count() - 1;
|
||||
}
|
||||
|
||||
layout->insertWidget(articlePosition, view);
|
||||
qApp->processEvents();
|
||||
}
|
||||
|
||||
void ArticleViewContainer::DeleteArticleView(ArticleView* view)
|
||||
{
|
||||
m_articles.removeAll(view);
|
||||
m_ui->articleViewContents->layout()->removeWidget(view);
|
||||
delete view;
|
||||
}
|
||||
|
||||
void ArticleViewContainer::ForceRefreshArticleView(ArticleView* articleView)
|
||||
{
|
||||
if (articleView == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QSharedPointer<const ArticleDescriptor> articleDesc = articleView->GetArticle();
|
||||
auto layout = static_cast<QVBoxLayout*>(m_ui->articleViewContents->layout());
|
||||
const int viewIndex = layout->indexOf(articleView);
|
||||
|
||||
DeleteArticleView(articleView);
|
||||
AddArticleView(*articleDesc, viewIndex);
|
||||
}
|
||||
|
||||
void ArticleViewContainer::ScrollToView(ArticleView* view) const
|
||||
{
|
||||
m_ui->previewArea->ensureWidgetVisible(view);
|
||||
}
|
||||
|
||||
void ArticleViewContainer::ClearError()
|
||||
{
|
||||
//delete loading label
|
||||
if (m_loadingLabel)
|
||||
{
|
||||
delete m_loadingLabel;
|
||||
m_loadingLabel = nullptr;
|
||||
}
|
||||
|
||||
//delete error message
|
||||
if (m_errorMessage)
|
||||
{
|
||||
delete m_errorMessage;
|
||||
m_errorMessage = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void ArticleViewContainer::articleSelectedSlot(QString id)
|
||||
{
|
||||
emit articleSelectedSignal(id);
|
||||
}
|
||||
|
||||
void ArticleViewContainer::UpdateArticleOrder(ArticleView* view, bool direction) const
|
||||
{
|
||||
QVBoxLayout* layout = qobject_cast<QVBoxLayout*>(m_ui->articleViewContents->layout());
|
||||
|
||||
const int index = layout->indexOf(view);
|
||||
|
||||
if (direction && index == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!direction && index == layout->count() - 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const int newIndex = direction ? index - 1 : index + 1;
|
||||
layout->removeWidget(view);
|
||||
layout->insertWidget(newIndex, view);
|
||||
}
|
||||
|
||||
void ArticleViewContainer::AddLoadingMessage()
|
||||
{
|
||||
if (m_errorMessage)
|
||||
{
|
||||
delete m_errorMessage;
|
||||
m_errorMessage = nullptr;
|
||||
}
|
||||
|
||||
if (!m_loadingLabel)
|
||||
{
|
||||
m_loadingLabel = new QLabel(this);
|
||||
m_loadingLabel->setText("Retrieving news...");
|
||||
auto layout = static_cast<QVBoxLayout*>(m_ui->articleViewContents->layout());
|
||||
layout->insertWidget(0, m_loadingLabel);
|
||||
}
|
||||
}
|
||||
|
||||
void ArticleViewContainer::AddErrorMessage()
|
||||
{
|
||||
if (m_loadingLabel)
|
||||
{
|
||||
delete m_loadingLabel;
|
||||
m_loadingLabel = nullptr;
|
||||
}
|
||||
|
||||
if (!m_errorMessage)
|
||||
{
|
||||
m_errorMessage = new ArticleErrorView(this);
|
||||
auto layout = static_cast<QVBoxLayout*>(m_ui->articleViewContents->layout());
|
||||
layout->insertWidget(0, m_errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
void ArticleViewContainer::Clear()
|
||||
{
|
||||
ClearError();
|
||||
|
||||
for (auto articleView : m_articles)
|
||||
{
|
||||
delete articleView;
|
||||
}
|
||||
|
||||
m_articles.clear();
|
||||
}
|
||||
|
||||
ArticleViewContainer::ArticleStyle ArticleViewContainer::GetArticleStyleEnumFromString(const QString& articleStyleStr) const
|
||||
{
|
||||
static const QMap<QString, ArticleStyle> articleStyleStringEnumMap = {
|
||||
{ "default", ArticleStyle::Default },
|
||||
{ "pinned", ArticleStyle::Pinned }
|
||||
};
|
||||
|
||||
if (articleStyleStringEnumMap.contains(articleStyleStr) == false)
|
||||
{
|
||||
Q_ASSERT(false);
|
||||
return ArticleStyle::Default;
|
||||
}
|
||||
|
||||
return articleStyleStringEnumMap.value(articleStyleStr);
|
||||
}
|
||||
|
||||
ArticleView* ArticleViewContainer::CreateArticleView(const ArticleDescriptor& articleDesc)
|
||||
{
|
||||
ArticleStyle articleStyle = GetArticleStyleEnumFromString(articleDesc.GetArticleStyle());
|
||||
|
||||
switch(articleStyle)
|
||||
{
|
||||
case ArticleStyle::Default:
|
||||
return new ArticleViewDefaultWidget(this, articleDesc, m_manifest);
|
||||
case ArticleStyle::Pinned:
|
||||
return new ArticleViewPinnedWidget(this, articleDesc, m_manifest);
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "NewsShared/Qt/moc_ArticleViewContainer.cpp"
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include "NewsShared/LogType.h"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QList>
|
||||
#endif
|
||||
|
||||
class QLabel;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class ArticleViewContainerWidget;
|
||||
}
|
||||
|
||||
namespace News
|
||||
{
|
||||
class Resource;
|
||||
class ArticleView;
|
||||
class ArticleDescriptor;
|
||||
class ResourceManifest;
|
||||
class ArticleErrorView;
|
||||
class KeepInTouchView;
|
||||
|
||||
class ArticleViewContainer
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
enum ArticleStyle
|
||||
{
|
||||
Default,
|
||||
Pinned
|
||||
};
|
||||
|
||||
public:
|
||||
explicit ArticleViewContainer(QWidget* parent, ResourceManifest& manifest);
|
||||
~ArticleViewContainer();
|
||||
|
||||
virtual void PopulateArticles();
|
||||
ArticleView* FindById(const QString& id);
|
||||
void AddArticleView(const ArticleDescriptor& articleDesc, int articlePosition = -1);
|
||||
void DeleteArticleView(ArticleView* view);
|
||||
void ForceRefreshArticleView(ArticleView* articleView);
|
||||
void ScrollToView(ArticleView* view) const;
|
||||
void UpdateArticleOrder(ArticleView* view, bool direction) const;
|
||||
void AddLoadingMessage();
|
||||
void AddErrorMessage();
|
||||
void Clear();
|
||||
|
||||
Q_SIGNALS:
|
||||
void articleSelectedSignal(QString resourceId);
|
||||
void addArticle(Resource* article);
|
||||
void logSignal(QString text, LogType logType = LogInfo);
|
||||
void scrolled();
|
||||
void linkActivatedSignal(const QString& link);
|
||||
|
||||
private:
|
||||
QScopedPointer<Ui::ArticleViewContainerWidget> m_ui;
|
||||
QList<ArticleView*> m_articles;
|
||||
ResourceManifest& m_manifest;
|
||||
QLabel* m_loadingLabel;
|
||||
ArticleErrorView* m_errorMessage;
|
||||
KeepInTouchView* m_keepInTouchViewWidget = nullptr;
|
||||
|
||||
void ClearError();
|
||||
ArticleStyle GetArticleStyleEnumFromString(const QString& articleStyleStr) const;
|
||||
ArticleView* CreateArticleView(const ArticleDescriptor& articleDesc);
|
||||
|
||||
private Q_SLOTS:
|
||||
virtual void articleSelectedSlot(QString id);
|
||||
};
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ArticleViewContainerWidget</class>
|
||||
<widget class="QWidget" name="ArticleViewContainerWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>606</width>
|
||||
<height>753</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="previewArea">
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOn</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignHCenter|Qt::AlignTop</set>
|
||||
</property>
|
||||
<widget class="QWidget" name="articleViewContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>589</width>
|
||||
<height>753</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>16</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>15</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>15</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>15</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>15</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "KeepInTouchView.h"
|
||||
#include "NewsShared/Qt/ui_KeepInTouchView.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QUrl>
|
||||
#include <QString>
|
||||
#include <QDesktopServices>
|
||||
|
||||
namespace News
|
||||
{
|
||||
KeepInTouchView::KeepInTouchView(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_ui(new Ui::KeepInTouchViewWidget())
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
m_ui->twich_container->setCursor(Qt::PointingHandCursor);
|
||||
m_ui->twitter_container->setCursor(Qt::PointingHandCursor);
|
||||
m_ui->youtube_container->setCursor(Qt::PointingHandCursor);
|
||||
m_ui->facebook_container->setCursor(Qt::PointingHandCursor);
|
||||
|
||||
m_ui->twich_container->installEventFilter(this);
|
||||
m_ui->twitter_container->installEventFilter(this);
|
||||
m_ui->youtube_container->installEventFilter(this);
|
||||
m_ui->facebook_container->installEventFilter(this);
|
||||
}
|
||||
|
||||
bool KeepInTouchView::eventFilter(QObject *watched, QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::MouseButtonRelease)
|
||||
{
|
||||
if (watched == m_ui->twich_container)
|
||||
{
|
||||
return LaunchSocialMediaUrl(SocialMediaType::Twitch);
|
||||
}
|
||||
else if (watched == m_ui->twitter_container)
|
||||
{
|
||||
return LaunchSocialMediaUrl(SocialMediaType::Twitter);
|
||||
}
|
||||
else if (watched == m_ui->youtube_container)
|
||||
{
|
||||
return LaunchSocialMediaUrl(SocialMediaType::YouTube);
|
||||
}
|
||||
else if (watched == m_ui->facebook_container)
|
||||
{
|
||||
return LaunchSocialMediaUrl(SocialMediaType::Facebook);
|
||||
}
|
||||
}
|
||||
|
||||
return QWidget::eventFilter(watched, event);
|
||||
}
|
||||
|
||||
bool KeepInTouchView::LaunchSocialMediaUrl(SocialMediaType type)
|
||||
{
|
||||
static const QMap<SocialMediaType, const char*> socialMediaTypeToUrlMap =
|
||||
{
|
||||
{ SocialMediaType::Twitch, m_twitchUrl },
|
||||
{ SocialMediaType::Twitter, m_twitterUrl },
|
||||
{ SocialMediaType::YouTube, m_youtubeUrl },
|
||||
{ SocialMediaType::Facebook, m_facebookUrl }
|
||||
};
|
||||
|
||||
if (socialMediaTypeToUrlMap.contains(type) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QString link = socialMediaTypeToUrlMap[type];
|
||||
Q_EMIT linkActivatedSignal(link);
|
||||
|
||||
return QDesktopServices::openUrl(QUrl(link));
|
||||
}
|
||||
}
|
||||
|
||||
#include "NewsShared/Qt/moc_KeepInTouchView.cpp"
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QWidget>
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class KeepInTouchViewWidget;
|
||||
}
|
||||
|
||||
namespace News
|
||||
{
|
||||
class KeepInTouchView
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
enum class SocialMediaType
|
||||
{
|
||||
Twitch,
|
||||
Twitter,
|
||||
YouTube,
|
||||
Facebook
|
||||
};
|
||||
|
||||
public:
|
||||
KeepInTouchView(QWidget* parent);
|
||||
~KeepInTouchView() = default;
|
||||
|
||||
bool eventFilter(QObject *watched, QEvent *event);
|
||||
|
||||
Q_SIGNALS:
|
||||
void linkActivatedSignal(const QString& link);
|
||||
|
||||
private:
|
||||
bool LaunchSocialMediaUrl(SocialMediaType type);
|
||||
|
||||
Ui::KeepInTouchViewWidget* m_ui = nullptr;
|
||||
|
||||
const char* m_twitchUrl = "https://docs.aws.amazon.com/console/lumberyard/twitch";
|
||||
const char* m_twitterUrl = "https://docs.aws.amazon.com/console/lumberyard/twitter";
|
||||
const char* m_youtubeUrl = "https://docs.aws.amazon.com/console/lumberyard/youtube";
|
||||
const char* m_facebookUrl = "https://docs.aws.amazon.com/console/lumberyard/facebook";
|
||||
};
|
||||
}
|
||||
@@ -1,423 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>KeepInTouchViewWidget</class>
|
||||
<widget class="QWidget" name="KeepInTouchViewWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>430</width>
|
||||
<height>336</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>430</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>430</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>ArticleView</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item alignment="Qt::AlignTop">
|
||||
<widget class="QFrame" name="viewContainer">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>430</width>
|
||||
<height>184</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>430</width>
|
||||
<height>184</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="NewsShared.qrc">:/images/Resources/KeepInTouchBanner.jpg</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="AzQtComponents::ExtendedLabel" name="titleLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Open Sans</family>
|
||||
<pointsize>14</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Keep in touch!</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>12</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="AzQtComponents::ExtendedLabel" name="bodyLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Open Sans</family>
|
||||
<pointsize>8</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Want to know the latest news at AmazonGameDev? Sign up for our newsletter and use the following links to find us!</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="indent">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="socialMediaContainer" native="true">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background: transparent;</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>20</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWidget" name="twich_container" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="twitch_icon">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="NewsShared.qrc">:/images/Resources/icon_twitch.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="twitch_label">
|
||||
<property name="text">
|
||||
<string>Twitch</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="twitter_container" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="twitter_icon">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="NewsShared.qrc">:/images/Resources/icon_twitter.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="twitter_label">
|
||||
<property name="text">
|
||||
<string>Twitter</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item alignment="Qt::AlignVCenter">
|
||||
<widget class="QWidget" name="youtube_container" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<property name="spacing">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="youtube_icon">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="NewsShared.qrc">:/images/Resources/icon_youtube.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="youtube_label">
|
||||
<property name="text">
|
||||
<string>Youtube</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item alignment="Qt::AlignLeft">
|
||||
<widget class="QWidget" name="facebook_container" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<property name="spacing">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="facebook_icon">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="NewsShared.qrc">:/images/Resources/icon_facebook.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="facebook_label">
|
||||
<property name="text">
|
||||
<string>Facebook</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>AzQtComponents::ExtendedLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>AzQtComponents/Components/ExtendedLabel.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="NewsShared.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,10 +0,0 @@
|
||||
<RCC>
|
||||
<qresource prefix="images">
|
||||
<file>../Resources/ErrorImage.jpg</file>
|
||||
<file>../Resources/KeepInTouchBanner.jpg</file>
|
||||
<file>../Resources/icon_facebook.png</file>
|
||||
<file>../Resources/icon_twitch.png</file>
|
||||
<file>../Resources/icon_twitter.png</file>
|
||||
<file>../Resources/icon_youtube.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -1,260 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>PinnedArticleViewWidget</class>
|
||||
<widget class="QWidget" name="PinnedArticleViewWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>430</width>
|
||||
<height>376</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>430</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>430</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>ArticleView</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="viewContainer">
|
||||
<property name="articleStyle" stdset="0">
|
||||
<string>pinned</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>16</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>16</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>16</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>16</number>
|
||||
</property>
|
||||
<item alignment="Qt::AlignTop">
|
||||
<widget class="QFrame" name="frame_2">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>128</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>128</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: transparent;</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="imageFrame">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>128</width>
|
||||
<height>96</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>128</width>
|
||||
<height>96</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item alignment="Qt::AlignTop">
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: transparent;</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="AzQtComponents::ExtendedLabel" name="titleLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Open Sans</family>
|
||||
<pointsize>14</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Title:</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse</set>
|
||||
</property>
|
||||
<property name="fontStyle" stdset="0">
|
||||
<string>sectionTitle</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="AzQtComponents::ExtendedLabel" name="bodyLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Open Sans</family>
|
||||
<pointsize>8</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Body</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>AzQtComponents::ExtendedLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>AzQtComponents/Components/ExtendedLabel.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ArticleDescriptor.h"
|
||||
#include "Resource.h"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
|
||||
using namespace News;
|
||||
|
||||
ArticleDescriptor::ArticleDescriptor(
|
||||
Resource& resource)
|
||||
: JsonDescriptor(resource)
|
||||
, m_imageId(m_json["image"].toString())
|
||||
, m_title(m_json["title"].toString())
|
||||
, m_body(m_json["body"].toString())
|
||||
, m_order(m_json["order"].toInt())
|
||||
{
|
||||
if (m_json.contains("articleStyle") == true)
|
||||
{
|
||||
m_articleStyle = m_json["articleStyle"].toString();
|
||||
}
|
||||
}
|
||||
|
||||
void ArticleDescriptor::Update() const
|
||||
{
|
||||
QJsonObject json;
|
||||
json["image"] = m_imageId;
|
||||
json["title"] = m_title;
|
||||
json["body"] = m_body;
|
||||
json["order"] = m_order;
|
||||
json["articleStyle"] = m_articleStyle;
|
||||
QJsonDocument doc(json);
|
||||
QByteArray data = doc.toJson(QJsonDocument::Compact).toStdString().data();
|
||||
m_resource.SetData(data);
|
||||
}
|
||||
|
||||
const QString& ArticleDescriptor::GetArticleStyle() const
|
||||
{
|
||||
return m_articleStyle;
|
||||
}
|
||||
|
||||
void ArticleDescriptor::SetArticleStyle(const QString& style)
|
||||
{
|
||||
m_articleStyle = style;
|
||||
}
|
||||
|
||||
const QString& ArticleDescriptor::GetImageId() const
|
||||
{
|
||||
return m_imageId;
|
||||
}
|
||||
|
||||
void ArticleDescriptor::SetImageId(const QString& imageId)
|
||||
{
|
||||
m_imageId = imageId;
|
||||
}
|
||||
|
||||
const QString& ArticleDescriptor::GetTitle() const
|
||||
{
|
||||
return m_title;
|
||||
}
|
||||
|
||||
void ArticleDescriptor::SetTitle(const QString& title)
|
||||
{
|
||||
m_title = title;
|
||||
}
|
||||
|
||||
const QString& ArticleDescriptor::GetBody() const
|
||||
{
|
||||
return m_body;
|
||||
}
|
||||
|
||||
void ArticleDescriptor::SetBody(const QString& body)
|
||||
{
|
||||
m_body = body;
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonDescriptor.h"
|
||||
|
||||
#include <QJsonObject>
|
||||
|
||||
namespace News
|
||||
{
|
||||
class Resource;
|
||||
|
||||
//! ArticleDescriptor represents Resource as an article
|
||||
class ArticleDescriptor
|
||||
: public JsonDescriptor
|
||||
{
|
||||
public:
|
||||
explicit ArticleDescriptor(Resource& resource);
|
||||
|
||||
//! If article was modified, call this to update resource data
|
||||
void Update() const;
|
||||
|
||||
const QString& GetArticleStyle() const;
|
||||
|
||||
void SetArticleStyle(const QString& style);
|
||||
|
||||
const QString& GetImageId() const;
|
||||
|
||||
void SetImageId(const QString& imageId);
|
||||
|
||||
const QString& GetTitle() const;
|
||||
|
||||
void SetTitle(const QString& title);
|
||||
|
||||
const QString& GetBody() const;
|
||||
|
||||
void SetBody(const QString& body);
|
||||
|
||||
private:
|
||||
QString m_articleStyle = "default";
|
||||
QString m_imageId;
|
||||
QString m_title;
|
||||
QString m_body;
|
||||
int m_order;
|
||||
};
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Descriptor.h"
|
||||
|
||||
using namespace News;
|
||||
|
||||
Descriptor::Descriptor(Resource& resource)
|
||||
: m_resource(resource) {}
|
||||
|
||||
Descriptor::~Descriptor() {}
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace News
|
||||
{
|
||||
class Resource;
|
||||
|
||||
//! Descriptor is a simple solution to add additional functionality to a Resource
|
||||
/*!
|
||||
Some descriptors can only work with certain resource types, like AerticleDescriptor
|
||||
*/
|
||||
class Descriptor
|
||||
{
|
||||
public:
|
||||
explicit Descriptor(Resource& resource);
|
||||
virtual ~Descriptor();
|
||||
|
||||
Resource& GetResource() const
|
||||
{
|
||||
return m_resource;
|
||||
}
|
||||
|
||||
protected:
|
||||
Resource& m_resource;
|
||||
};
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "JsonDescriptor.h"
|
||||
#include "Resource.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
|
||||
using namespace News;
|
||||
|
||||
JsonDescriptor::JsonDescriptor(Resource& resource)
|
||||
: Descriptor(resource)
|
||||
, m_doc(QJsonDocument::fromJson(m_resource.GetData()))
|
||||
, m_json(m_doc.object())
|
||||
{
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Descriptor.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
namespace News
|
||||
{
|
||||
//! JsonDescriptor assumes Resource is a JSON file
|
||||
class JsonDescriptor
|
||||
: public Descriptor
|
||||
{
|
||||
public:
|
||||
explicit JsonDescriptor(Resource& resource);
|
||||
|
||||
protected:
|
||||
QJsonDocument m_doc;
|
||||
QJsonObject m_json;
|
||||
};
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "QtDownloadManager.h"
|
||||
#include "QtDownloader.h"
|
||||
|
||||
namespace News
|
||||
{
|
||||
|
||||
QtDownloadManager::QtDownloadManager()
|
||||
: QObject()
|
||||
, m_worker(new QtDownloader) // this will start the thread which does downloads
|
||||
{
|
||||
// make sure the response handlers are queued connections as the worker runs in a different thread
|
||||
connect(m_worker, &QtDownloader::failed, this, &QtDownloadManager::failedReply, Qt::QueuedConnection);
|
||||
connect(m_worker, &QtDownloader::successfullyFinished, this, &QtDownloadManager::successfulReply, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
QtDownloadManager::~QtDownloadManager()
|
||||
{
|
||||
// NOTE: we don't delete the QtDownloader; it deletes itself.
|
||||
// We just tell it to stop
|
||||
m_worker->Finish();
|
||||
}
|
||||
|
||||
void QtDownloadManager::Download(const QString& url,
|
||||
std::function<void(QByteArray)> downloadSuccessCallback,
|
||||
std::function<void()> downloadFailCallback)
|
||||
{
|
||||
int downloadId = m_worker->Download(url);
|
||||
m_downloads[downloadId] = { downloadSuccessCallback, downloadFailCallback };
|
||||
}
|
||||
|
||||
void QtDownloadManager::Abort()
|
||||
{
|
||||
m_worker->Abort();
|
||||
m_downloads.clear();
|
||||
}
|
||||
|
||||
void QtDownloadManager::successfulReply(int downloadId, QByteArray data)
|
||||
{
|
||||
m_downloads[downloadId].downloadSuccessCallback(data);
|
||||
m_downloads.remove(downloadId);
|
||||
}
|
||||
|
||||
void QtDownloadManager::failedReply(int downloadId)
|
||||
{
|
||||
m_downloads[downloadId].downloadFailCallback();
|
||||
m_downloads.remove(downloadId);
|
||||
}
|
||||
|
||||
} // namespace News
|
||||
|
||||
#include "NewsShared/ResourceManagement/moc_QtDownloadManager.cpp"
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <mutex>
|
||||
#include <functional>
|
||||
|
||||
#include <QObject>
|
||||
#include <QMap>
|
||||
#endif
|
||||
|
||||
namespace News
|
||||
{
|
||||
class QtDownloader;
|
||||
|
||||
//! QtDownloadManager handles multiple asynchronous downloads
|
||||
class QtDownloadManager
|
||||
: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QtDownloadManager();
|
||||
~QtDownloadManager();
|
||||
|
||||
//! Asynchronously download a file from the input url and return it as QByteArray via the success callback
|
||||
/*!
|
||||
\param url - file url to download
|
||||
\param downloadSuccessCallback - if download is successful pass file's data as QByteArray
|
||||
\param downloadFailCallback - if download failed, pass error message
|
||||
*/
|
||||
void Download(const QString& url,
|
||||
std::function<void(QByteArray)> downloadSuccessCallback,
|
||||
std::function<void()> downloadFailCallback);
|
||||
|
||||
//! Aborts all currently active downloads. Success/failure callbacks will not be called.
|
||||
void Abort();
|
||||
|
||||
private:
|
||||
void successfulReply(int downloadId, QByteArray data);
|
||||
void failedReply(int downloadId);
|
||||
|
||||
QtDownloader* m_worker = nullptr;
|
||||
|
||||
struct DownloadResponses
|
||||
{
|
||||
std::function<void(QByteArray)> downloadSuccessCallback;
|
||||
std::function<void()> downloadFailCallback;
|
||||
};
|
||||
QMap<int, DownloadResponses> m_downloads;
|
||||
};
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "QtDownloader.h"
|
||||
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QThread>
|
||||
|
||||
|
||||
namespace News
|
||||
{
|
||||
QtDownloader::QtDownloader()
|
||||
: m_thread(new QThread())
|
||||
{
|
||||
// make sure that everything that QObject::connects to us knows we're running in a different thread
|
||||
moveToThread(m_thread);
|
||||
|
||||
// handle clean up of both ourselves and of our thread.
|
||||
// We manage thread clean up so that it can keep running and be cleaned up later, regardless of what
|
||||
// the thing that created the QtDownloader does
|
||||
connect(m_thread, &QThread::finished, m_thread, [this] {
|
||||
m_thread->deleteLater();
|
||||
deleteLater();
|
||||
});
|
||||
|
||||
auto abortDownloadsHandler = [this] {
|
||||
auto replies = m_downloads.keys();
|
||||
for (QNetworkReply* reply : replies)
|
||||
{
|
||||
reply->abort();
|
||||
}
|
||||
|
||||
m_downloads.clear();
|
||||
};
|
||||
|
||||
auto queueDownloadHandler = [this](int downloadId, QString url) {
|
||||
if (m_networkManager)
|
||||
{
|
||||
QNetworkReply* reply = m_networkManager->get(QNetworkRequest(QUrl(url)));
|
||||
m_downloads.insert(reply, downloadId);
|
||||
}
|
||||
};
|
||||
|
||||
auto createNetworkManagerHandler = [this] {
|
||||
m_networkManager = new QNetworkAccessManager;
|
||||
connect(m_networkManager, &QNetworkAccessManager::finished, this, &QtDownloader::downloadFinished);
|
||||
};
|
||||
|
||||
auto deleteNetworkManagerHandler = [this] {
|
||||
delete m_networkManager;
|
||||
m_networkManager = nullptr;
|
||||
};
|
||||
|
||||
auto quitHandler = [this] {
|
||||
// call quit via this callback, so that it executes in the running thread.
|
||||
// QThread::quit() is actually blocking and waits until everything finishes, so
|
||||
// we don't want to call it in the main thread
|
||||
m_thread->quit();
|
||||
};
|
||||
|
||||
// make sure the response handlers are queued connections as the worker runs in one thread, but these triggers
|
||||
// will be emitted from the main thread
|
||||
connect(this, &QtDownloader::triggerAbortAll, this, abortDownloadsHandler, Qt::QueuedConnection);
|
||||
connect(this, &QtDownloader::triggerDownload, this, queueDownloadHandler, Qt::QueuedConnection);
|
||||
connect(this, &QtDownloader::triggerQuit, this, quitHandler, Qt::QueuedConnection);
|
||||
|
||||
// create/delete the QNetworkAccessManager in our thread, to ensure that any slowdowns caused by
|
||||
// having to create network connectors / load drivers are done in our non-ui thread.
|
||||
// make sure that these connections are direct so that network requests can't predate the network engine itself
|
||||
connect(m_thread, &QThread::started, this, createNetworkManagerHandler, Qt::DirectConnection);
|
||||
connect(m_thread, &QThread::finished, this, deleteNetworkManagerHandler, Qt::DirectConnection);
|
||||
|
||||
m_thread->start();
|
||||
}
|
||||
|
||||
QtDownloader::~QtDownloader()
|
||||
{
|
||||
}
|
||||
|
||||
int QtDownloader::Download(const QString& url)
|
||||
{
|
||||
// create a unique id for this download
|
||||
int downloadId = m_lastId++;
|
||||
|
||||
// trigger a download running in our worker thread
|
||||
Q_EMIT triggerDownload(downloadId, url);
|
||||
|
||||
return downloadId;
|
||||
}
|
||||
|
||||
void QtDownloader::Abort()
|
||||
{
|
||||
// trigger an abort in our worker thread
|
||||
Q_EMIT triggerAbortAll();
|
||||
}
|
||||
|
||||
void QtDownloader::Finish()
|
||||
{
|
||||
// trigger a quit in our worker thread
|
||||
Q_EMIT triggerQuit();
|
||||
}
|
||||
|
||||
void QtDownloader::downloadFinished(QNetworkReply* reply)
|
||||
{
|
||||
// Note: this will run in our worker thread
|
||||
int downloadId = m_downloads[reply];
|
||||
|
||||
// emit the signal back to the main thread indicating that we're finished, either
|
||||
// successfully or unsuccessfully
|
||||
if (reply->error() == QNetworkReply::NoError)
|
||||
{
|
||||
Q_EMIT successfullyFinished(downloadId, reply->readAll());
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_EMIT failed(downloadId);
|
||||
}
|
||||
|
||||
// clean up the reply; have to do this later, according to the Qt docs
|
||||
reply->deleteLater();
|
||||
|
||||
// make sure to remove our reference to this reply from our list of active downloads
|
||||
m_downloads.remove(reply);
|
||||
}
|
||||
|
||||
#include "NewsShared/ResourceManagement/moc_QtDownloader.cpp"
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <mutex>
|
||||
#include <functional>
|
||||
#include <QObject>
|
||||
#include <QMap>
|
||||
#endif
|
||||
|
||||
class QNetworkAccessManager;
|
||||
class QNetworkReply;
|
||||
class QThread;
|
||||
|
||||
namespace News
|
||||
{
|
||||
//! QtDownloader is a wrapper around Qt's file download functions
|
||||
/*!
|
||||
The QtDownloader spins up another thread and does all downloads in that thread.
|
||||
The public slot methods (Finish, Download and Abort) can all be called from any thread.
|
||||
The response signals (successfullyFinished and failed) should be QObject::connect to with
|
||||
Qt::QueuedConnection, as they will be emitted from the worker thread.
|
||||
*/
|
||||
class QtDownloader
|
||||
: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QtDownloader();
|
||||
~QtDownloader();
|
||||
|
||||
public Q_SLOTS:
|
||||
void Finish();
|
||||
|
||||
int Download(const QString& url);
|
||||
void Abort();
|
||||
|
||||
Q_SIGNALS:
|
||||
void successfullyFinished(int downloadId, QByteArray data);
|
||||
void failed(int downloadId);
|
||||
|
||||
// ***********************************************
|
||||
// private - DO NOT CONNECT TO outside of the class!
|
||||
// (qt signals can't be made private)
|
||||
void triggerAbortAll();
|
||||
void triggerDownload(int downloadId, QString url);
|
||||
void triggerQuit();
|
||||
// ***********************************************
|
||||
|
||||
private:
|
||||
void downloadFinished(QNetworkReply* reply);
|
||||
|
||||
int m_lastId = 0;
|
||||
|
||||
QMap<QNetworkReply*, int> m_downloads;
|
||||
QNetworkAccessManager* m_networkManager = nullptr;
|
||||
QThread* m_thread;
|
||||
};
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Resource.h"
|
||||
|
||||
#include <QJsonObject>
|
||||
|
||||
using namespace News;
|
||||
|
||||
Resource::Resource(const QJsonObject& json)
|
||||
: Resource(
|
||||
json["id"].toString(),
|
||||
QByteArray(),
|
||||
json["url"].toString(),
|
||||
json["type"].toString(),
|
||||
json["refCount"].toInt(),
|
||||
json["version"].toInt()) {}
|
||||
|
||||
Resource::Resource(const QString& id, const QString& type)
|
||||
: Resource(
|
||||
id,
|
||||
QByteArray(),
|
||||
"",
|
||||
type,
|
||||
1,
|
||||
0) {}
|
||||
|
||||
Resource::Resource(const QString& id,
|
||||
const QByteArray& data,
|
||||
[[maybe_unused]] const QString& url,
|
||||
const QString& type,
|
||||
int refCount,
|
||||
int version)
|
||||
: m_id(id)
|
||||
, m_data(data)
|
||||
, m_type(type)
|
||||
, m_refCount(refCount)
|
||||
, m_version(version) {}
|
||||
|
||||
Resource::~Resource() {}
|
||||
|
||||
void Resource::Write(QJsonObject& json) const
|
||||
{
|
||||
json["id"] = m_id;
|
||||
json["type"] = m_type;
|
||||
json["refCount"] = m_refCount;
|
||||
json["version"] = m_version;
|
||||
}
|
||||
|
||||
QString Resource::GetId() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
void Resource::SetId(const QString& id)
|
||||
{
|
||||
m_id = id;
|
||||
}
|
||||
|
||||
QByteArray Resource::GetData() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
void Resource::SetData(QByteArray data)
|
||||
{
|
||||
m_data = data;
|
||||
}
|
||||
|
||||
QString Resource::GetType() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
int Resource::GetRefCount() const
|
||||
{
|
||||
return m_refCount;
|
||||
}
|
||||
|
||||
void Resource::SetRefCount(int refCount)
|
||||
{
|
||||
m_refCount = refCount;
|
||||
}
|
||||
|
||||
int Resource::GetVersion() const
|
||||
{
|
||||
return m_version;
|
||||
}
|
||||
|
||||
void Resource::SetVersion(int version)
|
||||
{
|
||||
m_version = version;
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
|
||||
class QJsonObject;
|
||||
|
||||
namespace News
|
||||
{
|
||||
class Descriptor;
|
||||
|
||||
//! Resource is a central element of in-editor messages
|
||||
//! It represents articles, images, and anything else that is part of news feed
|
||||
class Resource
|
||||
{
|
||||
public:
|
||||
//! resources are stored as json objects in \ref News::ResourceManifest
|
||||
//! this creates resource with empty data array, that can be downloaded later
|
||||
//! by calling News::ResourceManifest::Sync
|
||||
explicit Resource(const QJsonObject& json);
|
||||
|
||||
explicit Resource(const QString& id,
|
||||
const QString& type);
|
||||
|
||||
Resource(const QString& id,
|
||||
const QByteArray& data,
|
||||
const QString& url,
|
||||
const QString& type,
|
||||
int refCount,
|
||||
int version);
|
||||
|
||||
~Resource();
|
||||
|
||||
//! Saves resource's description to a json file
|
||||
void Write(QJsonObject& json) const;
|
||||
|
||||
QString GetId() const;
|
||||
|
||||
void SetId(const QString& id);
|
||||
|
||||
QByteArray GetData() const;
|
||||
|
||||
void SetData(QByteArray data);
|
||||
|
||||
QString GetType() const;
|
||||
|
||||
int GetRefCount() const;
|
||||
|
||||
void SetRefCount(int refCount);
|
||||
|
||||
int GetVersion() const;
|
||||
|
||||
void SetVersion(int version);
|
||||
|
||||
private:
|
||||
QString m_id;
|
||||
QByteArray m_data;
|
||||
QString m_type;
|
||||
int m_refCount;
|
||||
int m_version;
|
||||
};
|
||||
}
|
||||
@@ -1,349 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ResourceManifest.h"
|
||||
#include "NewsShared/ResourceManagement/QtDownloadManager.h"
|
||||
#include "NewsShared/ResourceManagement/Resource.h"
|
||||
#include "NewsShared/ResourceManagement/ArticleDescriptor.h"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QByteArray>
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
#include <QCoreApplication>
|
||||
|
||||
namespace News
|
||||
{
|
||||
|
||||
const QString ResourceManifest::MANIFEST_NAME = "resourceManifest";
|
||||
bool ResourceManifest::s_syncing = false;
|
||||
|
||||
ResourceManifest::ResourceManifest(
|
||||
std::function<void()> syncSuccessCallback,
|
||||
std::function<void(ErrorCode)> syncFailCallback,
|
||||
std::function<void(QString, LogType)> syncUpdateCallback)
|
||||
: m_downloader(new QtDownloadManager)
|
||||
, m_syncSuccessCallback(syncSuccessCallback)
|
||||
, m_syncFailCallback(syncFailCallback)
|
||||
, m_syncUpdateCallback(syncUpdateCallback)
|
||||
{
|
||||
}
|
||||
|
||||
ResourceManifest::~ResourceManifest()
|
||||
{
|
||||
// clean everything up
|
||||
DeleteResources();
|
||||
|
||||
delete m_downloader;
|
||||
}
|
||||
|
||||
Resource* ResourceManifest::FindById(const QString& id) const
|
||||
{
|
||||
return FindById(id, m_resources);
|
||||
}
|
||||
|
||||
Resource* ResourceManifest::FindById(const QString& id, const QList<Resource*>& resources)
|
||||
{
|
||||
auto it = std::find_if(
|
||||
resources.begin(),
|
||||
resources.end(),
|
||||
[id](Resource* resource) -> bool
|
||||
{
|
||||
return resource->GetId().compare(id) == 0;
|
||||
});
|
||||
if (it == resources.end())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return *it;
|
||||
}
|
||||
|
||||
Resource* ResourceManifest::FindById(const QString& id,
|
||||
const QStack<Resource*>& resources)
|
||||
{
|
||||
auto it = std::find_if(
|
||||
resources.begin(),
|
||||
resources.end(),
|
||||
[id](Resource* resource) -> bool
|
||||
{
|
||||
return resource->GetId().compare(id) == 0;
|
||||
});
|
||||
if (it == resources.end())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return *it;
|
||||
}
|
||||
|
||||
void ResourceManifest::Sync()
|
||||
{
|
||||
if (s_syncing)
|
||||
{
|
||||
FailSync(ErrorCode::AlreadySyncing);
|
||||
return;
|
||||
}
|
||||
s_syncing = true;
|
||||
m_failed = false;
|
||||
|
||||
m_syncUpdateCallback("Starting sync", LogInfo);
|
||||
|
||||
ReadConfig();
|
||||
|
||||
// first download the manifest json
|
||||
m_syncUpdateCallback("Downloading manifest", LogInfo);
|
||||
m_downloader->Download(QString(m_url).append(MANIFEST_NAME),
|
||||
std::bind(&ResourceManifest::OnDownloadSuccess, this, std::placeholders::_1),
|
||||
std::bind(&ResourceManifest::OnDownloadFail, this));
|
||||
}
|
||||
|
||||
void ResourceManifest::Abort()
|
||||
{
|
||||
m_aborted = true;
|
||||
m_downloader->Abort();
|
||||
}
|
||||
|
||||
void ResourceManifest::Reset()
|
||||
{
|
||||
if (s_syncing)
|
||||
{
|
||||
m_syncUpdateCallback("Sync is already running", LogError);
|
||||
return;
|
||||
}
|
||||
|
||||
m_aborted = false;
|
||||
m_failed = false;
|
||||
m_version = -1;
|
||||
|
||||
DeleteResources();
|
||||
|
||||
m_order.clear();
|
||||
}
|
||||
|
||||
QList<Resource*>::const_iterator ResourceManifest::begin() const
|
||||
{
|
||||
return m_resources.constBegin();
|
||||
}
|
||||
|
||||
QList<Resource*>::const_iterator ResourceManifest::end() const
|
||||
{
|
||||
return m_resources.constEnd();
|
||||
}
|
||||
|
||||
QList<QString> ResourceManifest::GetOrder() const
|
||||
{
|
||||
return m_order;
|
||||
}
|
||||
|
||||
void ResourceManifest::OnDownloadSuccess(QByteArray data)
|
||||
{
|
||||
QJsonDocument doc(QJsonDocument::fromJson(data));
|
||||
if (doc.isNull())
|
||||
{
|
||||
FailSync(ErrorCode::FailedToParseManifest);
|
||||
return;
|
||||
}
|
||||
|
||||
ErrorCode error = Read(doc.object());
|
||||
if (error != ErrorCode::None)
|
||||
{
|
||||
FailSync(error);
|
||||
return;
|
||||
}
|
||||
|
||||
// check how many resources to sync
|
||||
PrepareForSync();
|
||||
// if there is anything to sync, do that
|
||||
if (m_syncLeft > 0)
|
||||
{
|
||||
m_syncUpdateCallback("Syncing resources", LogInfo);
|
||||
SyncResources();
|
||||
}
|
||||
// otherwise just finish sync
|
||||
else
|
||||
{
|
||||
m_syncUpdateCallback("No new resources to sync", LogInfo);
|
||||
FinishSync();
|
||||
}
|
||||
}
|
||||
|
||||
void ResourceManifest::OnDownloadFail()
|
||||
{
|
||||
FailSync(ErrorCode::ManifestDownloadFail);
|
||||
}
|
||||
|
||||
ErrorCode ResourceManifest::Read(const QJsonObject& json)
|
||||
{
|
||||
m_version = json["version"].toInt();
|
||||
QJsonArray resourceArray = json["resources"].toArray();
|
||||
// initially mark ALL existing resource for deletion
|
||||
QList<Resource*> toDelete = m_resources;
|
||||
|
||||
for (auto resourceDoc : resourceArray)
|
||||
{
|
||||
auto pNewResource = new Resource(resourceDoc.toObject());
|
||||
// find local resource with the same id as new resource
|
||||
auto pOldResource = FindById(pNewResource->GetId(), m_resources);
|
||||
// if resource with the same id already exists then check its version
|
||||
if (pOldResource)
|
||||
{
|
||||
// local resource is outdated, keep it in delete list, and download new one instead
|
||||
if (pNewResource->GetVersion() > pOldResource->GetVersion())
|
||||
{
|
||||
m_toDownload.push(pNewResource);
|
||||
}
|
||||
// local resource is newer or same version, keep it (remove from toDelete list)
|
||||
// and don't need to download new one
|
||||
else
|
||||
{
|
||||
delete pNewResource;
|
||||
toDelete.removeAll(pOldResource);
|
||||
}
|
||||
}
|
||||
// resource with same id not found
|
||||
else
|
||||
{
|
||||
m_toDownload.push(pNewResource);
|
||||
}
|
||||
}
|
||||
|
||||
// delete everything that's not in s3
|
||||
for (auto pResource : toDelete)
|
||||
{
|
||||
RemoveResource(pResource);
|
||||
delete pResource;
|
||||
}
|
||||
|
||||
// parse order of articles
|
||||
m_order.clear();
|
||||
QJsonArray orderArray = json["order"].toArray();
|
||||
for (auto idObject : orderArray)
|
||||
{
|
||||
m_order.append(idObject.toString());
|
||||
}
|
||||
return ErrorCode::None;
|
||||
}
|
||||
|
||||
void ResourceManifest::PrepareForSync()
|
||||
{
|
||||
if (m_aborted)
|
||||
{
|
||||
m_syncLeft = 0;
|
||||
}
|
||||
|
||||
m_syncLeft = m_toDownload.count();
|
||||
}
|
||||
|
||||
void ResourceManifest::SyncResources()
|
||||
{
|
||||
DownloadResources();
|
||||
}
|
||||
|
||||
void ResourceManifest::DownloadResources()
|
||||
{
|
||||
while (m_toDownload.count() > 0)
|
||||
{
|
||||
m_syncUpdateCallback(
|
||||
QString("Downloading: %1 resources left").arg(m_toDownload.count()),
|
||||
LogInfo);
|
||||
|
||||
auto pResource = m_toDownload.pop();
|
||||
|
||||
m_downloader->Download(QString(m_url).append(pResource->GetId()),
|
||||
//download success
|
||||
[&, pResource](QByteArray data)
|
||||
{
|
||||
pResource->SetData(data);
|
||||
AppendResource(pResource);
|
||||
UpdateSync();
|
||||
},
|
||||
//download fail
|
||||
[&, pResource]()
|
||||
{
|
||||
m_failed = true;
|
||||
delete pResource;
|
||||
m_syncUpdateCallback("Failed to download resource", LogError);
|
||||
UpdateSync();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void ResourceManifest::ReadConfig()
|
||||
{
|
||||
QFile file(QCoreApplication::applicationDirPath() + "/newsConfig.txt");
|
||||
if (file.exists())
|
||||
{
|
||||
if (file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
QTextStream in(&file);
|
||||
m_url = in.readAll().trimmed();
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ResourceManifest::DeleteResources()
|
||||
{
|
||||
for (auto pResource : m_toDownload)
|
||||
{
|
||||
delete pResource;
|
||||
}
|
||||
m_toDownload.clear();
|
||||
|
||||
for (auto pResource : m_resources)
|
||||
{
|
||||
delete pResource;
|
||||
}
|
||||
m_resources.clear();
|
||||
}
|
||||
|
||||
void ResourceManifest::UpdateSync()
|
||||
{
|
||||
m_syncLeft--;
|
||||
if (m_syncLeft == 0)
|
||||
{
|
||||
if (!m_failed)
|
||||
{
|
||||
FinishSync();
|
||||
}
|
||||
else
|
||||
{
|
||||
FailSync(ErrorCode::FailedToSync);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ResourceManifest::FinishSync()
|
||||
{
|
||||
if (!m_failed)
|
||||
{
|
||||
m_syncSuccessCallback();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_syncFailCallback(m_errorCode);
|
||||
}
|
||||
s_syncing = false;
|
||||
}
|
||||
|
||||
void ResourceManifest::FailSync(ErrorCode error)
|
||||
{
|
||||
m_failed = true;
|
||||
m_errorCode = error;
|
||||
FinishSync();
|
||||
}
|
||||
|
||||
void ResourceManifest::AppendResource(Resource* pResource)
|
||||
{
|
||||
m_resources.append(pResource);
|
||||
}
|
||||
|
||||
void ResourceManifest::RemoveResource(Resource* pResource)
|
||||
{
|
||||
m_resources.removeAll(pResource);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QList>
|
||||
#include <QStack>
|
||||
#include <functional>
|
||||
|
||||
#include "NewsShared/LogType.h"
|
||||
#include "NewsShared/ErrorCodes.h"
|
||||
|
||||
class QJsonObject;
|
||||
|
||||
namespace News
|
||||
{
|
||||
class ArticleDescriptor;
|
||||
class UidGenerator;
|
||||
class S3Connector;
|
||||
class QtDownloadManager;
|
||||
class Descriptor;
|
||||
class DownloadDescriptor;
|
||||
class Resource;
|
||||
|
||||
//! ResourceManifest manages resources.
|
||||
/*!
|
||||
Manifest contains information on resources, it handles syncing resources with s3
|
||||
*/
|
||||
class ResourceManifest
|
||||
{
|
||||
public:
|
||||
//! ResourceManifest ctor
|
||||
/*!
|
||||
\param syncSuccessCallback - called once when everything is synced
|
||||
\param syncFailCallback - called once when sync failed
|
||||
\param syncUpdateCallback - called multiple times to update information on sync process
|
||||
*/
|
||||
explicit ResourceManifest(
|
||||
std::function<void()> syncSuccessCallback,
|
||||
std::function<void(ErrorCode)> syncFailCallback,
|
||||
std::function<void(QString, LogType)> syncUpdateCallback);
|
||||
virtual ~ResourceManifest();
|
||||
|
||||
//! Find a resource that matches id
|
||||
/*!
|
||||
\retval Resource * - a pointer to a Resource with matching id, if none found return nullptr
|
||||
*/
|
||||
Resource* FindById(const QString& id) const;
|
||||
static Resource* FindById(const QString& id, const QList<Resource*>& resources);
|
||||
static Resource* FindById(const QString& id, const QStack<Resource*>& resources);
|
||||
|
||||
//! Sync resources with s3
|
||||
/*
|
||||
1) First download resource manifest file
|
||||
2) Parse manifest
|
||||
3) Determine which resources need to be downloaded, updated, or deleted
|
||||
4) Download missing resources or resource that are out of date
|
||||
5) Call m_syncSuccessCallback
|
||||
*/
|
||||
virtual void Sync();
|
||||
|
||||
//! Gracegully stop sync process
|
||||
/*!
|
||||
Aborting works differently depending at what point during sync porocess it is called
|
||||
If called before resources started to download, then skip download altogether
|
||||
Otherwise gracefully abort all downloads and call m_syncFailCallback
|
||||
*/
|
||||
void Abort();
|
||||
|
||||
//! Called when switching endpoints to reset resource manifest to a clean state
|
||||
virtual void Reset();
|
||||
|
||||
QList<Resource*>::const_iterator begin() const;
|
||||
QList<Resource*>::const_iterator end() const;
|
||||
|
||||
//! Get order of article resources, so they can be displayed properly in ArticleViewContainer
|
||||
QList<QString> GetOrder() const;
|
||||
|
||||
protected:
|
||||
//! The root location of cloudfront resources
|
||||
QString m_url = "https://lumberyard-data.amazon.com/";
|
||||
//! Name of resourceManifest file that links all other resources
|
||||
static const QString MANIFEST_NAME;
|
||||
//! Identifies whether syncing is in progress
|
||||
static bool s_syncing;
|
||||
//! Manifest Version
|
||||
int m_version = -1;
|
||||
//! Number of resources left to sync
|
||||
int m_syncLeft = 0;
|
||||
//! Identifies whether sync process was aborted
|
||||
bool m_aborted = false;
|
||||
//! Indentifies whether sync process has failed
|
||||
bool m_failed = false;
|
||||
ErrorCode m_errorCode = ErrorCode::None;
|
||||
|
||||
QtDownloadManager* m_downloader = nullptr;
|
||||
|
||||
QList<Resource*> m_resources;
|
||||
QList<QString> m_order;
|
||||
QStack<Resource*> m_toDownload;
|
||||
|
||||
std::function<void()> m_syncSuccessCallback;
|
||||
std::function<void(ErrorCode)> m_syncFailCallback;
|
||||
std::function<void(QString, LogType)> m_syncUpdateCallback;
|
||||
|
||||
//! Parse resource manifest json, and figure out which resources need to be downloaded
|
||||
virtual ErrorCode Read(const QJsonObject& json);
|
||||
|
||||
//! Executed before sync to figure out how many resources need to be synced
|
||||
virtual void PrepareForSync();
|
||||
//! Actual sync function
|
||||
virtual void SyncResources();
|
||||
//! Check whether everything is synced, if so call ResourceManifest::FinishSync
|
||||
void UpdateSync();
|
||||
//! Notify that everything is synced
|
||||
virtual void FinishSync();
|
||||
void FailSync(ErrorCode error);
|
||||
|
||||
virtual void AppendResource(Resource* pResource);
|
||||
virtual void RemoveResource(Resource* pResource);
|
||||
|
||||
virtual void OnDownloadSuccess(QByteArray data);
|
||||
virtual void OnDownloadFail();
|
||||
virtual void DownloadResources();
|
||||
|
||||
private:
|
||||
void ReadConfig();
|
||||
void DeleteResources();
|
||||
};
|
||||
} // namespace News
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0a7430d63820b3b00e03b4a8ec73b5e8e3946659031e3aeeb355b632acca4122
|
||||
size 8857
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:09c1733f116c11b56c54f7c3b6b4462884116db06605ca3cdfa23c45a3695385
|
||||
size 68024
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f8b5493c81354b6757a21bea6baedd5665b8cb9ca19a6ff4fbd40afef534f35f
|
||||
size 1257
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2882aad73e2ecf310934ec3eacd0c1fa0a6ff012a4c3c9cf4ca96a72cef2fb8c
|
||||
size 514
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:046e14f1d90f77bb6ea0fe700bb10049748b46bb84c8ac3620642d4bca9df533
|
||||
size 954
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3abaf8b178763441ac6812ae518c2f8cbea9b228aa1f84052a65836b33dc980c
|
||||
size 976
|
||||
@@ -1,45 +0,0 @@
|
||||
#
|
||||
# Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
#
|
||||
#
|
||||
|
||||
set(FILES
|
||||
NewsShared/LogType.h
|
||||
NewsShared/ErrorCodes.h
|
||||
NewsShared/Qt/ArticleErrorView.cpp
|
||||
NewsShared/Qt/ArticleErrorView.h
|
||||
NewsShared/Qt/ArticleErrorView.ui
|
||||
NewsShared/Qt/ArticleView.cpp
|
||||
NewsShared/Qt/ArticleView.h
|
||||
NewsShared/Qt/ArticleView.ui
|
||||
NewsShared/Qt/PinnedArticleView.ui
|
||||
NewsShared/Qt/ArticleViewContainer.cpp
|
||||
NewsShared/Qt/ArticleViewContainer.h
|
||||
NewsShared/Qt/ArticleViewContainer.ui
|
||||
NewsShared/Qt/KeepInTouchView.cpp
|
||||
NewsShared/Qt/KeepInTouchView.h
|
||||
NewsShared/Qt/KeepInTouchView.ui
|
||||
NewsShared/Qt/NewsShared.qrc
|
||||
NewsShared/ResourceManagement/ArticleDescriptor.cpp
|
||||
NewsShared/ResourceManagement/ArticleDescriptor.h
|
||||
NewsShared/ResourceManagement/Descriptor.cpp
|
||||
NewsShared/ResourceManagement/Descriptor.h
|
||||
NewsShared/ResourceManagement/JsonDescriptor.cpp
|
||||
NewsShared/ResourceManagement/JsonDescriptor.h
|
||||
NewsShared/ResourceManagement/QtDownloader.cpp
|
||||
NewsShared/ResourceManagement/QtDownloader.h
|
||||
NewsShared/ResourceManagement/QtDownloadManager.cpp
|
||||
NewsShared/ResourceManagement/QtDownloadManager.h
|
||||
NewsShared/ResourceManagement/Resource.cpp
|
||||
NewsShared/ResourceManagement/Resource.h
|
||||
NewsShared/ResourceManagement/ResourceManifest.cpp
|
||||
NewsShared/ResourceManagement/ResourceManifest.h
|
||||
NewsShared/Resources/ErrorImage.jpg
|
||||
NewsShared/Resources/KeepInTouchBanner.jpg
|
||||
NewsShared/Resources/icon_facebook.png
|
||||
NewsShared/Resources/icon_twitch.png
|
||||
NewsShared/Resources/icon_twitter.png
|
||||
NewsShared/Resources/icon_youtube.png
|
||||
)
|
||||
Reference in New Issue
Block a user