Merge pull request #2094 from aws-lumberyard-dev/cgalvan/gitflow_210712
Merged stabilization/2106 to development
This commit is contained in:
@@ -47,8 +47,7 @@ set(ENABLED_GEMS
|
||||
LmbrCentral
|
||||
LyShine
|
||||
HttpRequestor
|
||||
Atom_AtomBridge
|
||||
PythonCoverage
|
||||
Atom
|
||||
AWSCore
|
||||
AWSClientAuth
|
||||
AWSMetrics
|
||||
|
||||
@@ -51,4 +51,18 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
AutomatedTesting.GameLauncher
|
||||
AutomatedTesting.Assets
|
||||
)
|
||||
|
||||
ly_add_pytest(
|
||||
NAME AutomatedTesting::GameLauncherWithGPU
|
||||
TEST_SUITE sandbox
|
||||
TEST_REQUIRES gpu
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/test_GameLauncher_EnterExitGameMode_Works.py
|
||||
TIMEOUT 100
|
||||
RUNTIME_DEPENDENCIES
|
||||
AZ::AssetProcessor
|
||||
AZ::PythonBindingsExample
|
||||
Legacy::Editor
|
||||
AutomatedTesting.GameLauncher
|
||||
AutomatedTesting.Assets
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -111,7 +111,6 @@ ly_add_target(
|
||||
AZ::AzCore
|
||||
AZ::AzToolsFramework
|
||||
Gem::LmbrCentral.Static
|
||||
Legacy::NewsShared
|
||||
AZ::AWSNativeSDKInit
|
||||
AZ::AtomCore
|
||||
Gem::Atom_RPI.Edit
|
||||
|
||||
@@ -458,25 +458,7 @@ void EditorViewportWidget::Update()
|
||||
SetFOV(cameraState.m_fovOrZoom);
|
||||
m_Camera.SetZRange(cameraState.m_nearClip, cameraState.m_farClip);
|
||||
}
|
||||
else if (!ed_useNewCameraSystem)
|
||||
{
|
||||
m_renderViewport->GetViewportContext()->SetCameraTransform(LYTransformToAZTransform(m_Camera.GetMatrix()));
|
||||
}
|
||||
|
||||
// Don't override the game mode FOV
|
||||
if (!GetIEditor()->IsInGameMode())
|
||||
{
|
||||
AZ::Matrix4x4 clipMatrix;
|
||||
AZ::MakePerspectiveFovMatrixRH(
|
||||
clipMatrix,
|
||||
GetFOV(),
|
||||
aznumeric_cast<float>(width()) / aznumeric_cast<float>(height()),
|
||||
m_Camera.GetNearPlane(),
|
||||
m_Camera.GetFarPlane(),
|
||||
true
|
||||
);
|
||||
m_renderViewport->GetViewportContext()->SetCameraProjectionMatrix(clipMatrix);
|
||||
}
|
||||
// Reset the camera update flag now that we're finished updating our viewport context
|
||||
m_updateCameraPositionNextTick = false;
|
||||
|
||||
@@ -632,7 +614,6 @@ void EditorViewportWidget::SetViewEntity(const AZ::EntityId& viewEntityId, bool
|
||||
void EditorViewportWidget::ResetToViewSourceType(const ViewSourceType& viewSourceType)
|
||||
{
|
||||
LockCameraMovement(true);
|
||||
m_pCameraFOVVariable = nullptr;
|
||||
m_viewEntityId.SetInvalid();
|
||||
m_cameraObjectId = GUID_NULL;
|
||||
m_viewSourceType = viewSourceType;
|
||||
@@ -2547,13 +2528,26 @@ void EditorViewportWidget::CenterOnSliceInstance()
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void EditorViewportWidget::SetFOV(float fov)
|
||||
{
|
||||
if (m_pCameraFOVVariable)
|
||||
if (m_viewEntityId.IsValid())
|
||||
{
|
||||
m_pCameraFOVVariable->Set(fov);
|
||||
Camera::CameraRequestBus::Event(m_viewEntityId, &Camera::CameraComponentRequests::SetFov, AZ::RadToDeg(fov));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_camFOV = fov;
|
||||
// Set the active camera's FOV
|
||||
{
|
||||
AZ::Matrix4x4 clipMatrix;
|
||||
AZ::MakePerspectiveFovMatrixRH(
|
||||
clipMatrix,
|
||||
GetFOV(),
|
||||
aznumeric_cast<float>(width()) / aznumeric_cast<float>(height()),
|
||||
m_Camera.GetNearPlane(),
|
||||
m_Camera.GetFarPlane(),
|
||||
true
|
||||
);
|
||||
m_renderViewport->GetViewportContext()->SetCameraProjectionMatrix(clipMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_viewPane)
|
||||
@@ -2580,13 +2574,7 @@ float EditorViewportWidget::GetFOV() const
|
||||
}
|
||||
}
|
||||
|
||||
if (m_pCameraFOVVariable)
|
||||
{
|
||||
float fov;
|
||||
m_pCameraFOVVariable->Get(fov);
|
||||
return fov;
|
||||
}
|
||||
else if (m_viewEntityId.IsValid())
|
||||
if (m_viewEntityId.IsValid())
|
||||
{
|
||||
float fov = AZ::RadToDeg(m_camFOV);
|
||||
Camera::CameraRequestBus::EventResult(fov, m_viewEntityId, &Camera::CameraComponentRequests::GetFov);
|
||||
|
||||
@@ -506,7 +506,6 @@ protected:
|
||||
|
||||
CPredefinedAspectRatios m_predefinedAspectRatios;
|
||||
|
||||
IVariable* m_pCameraFOVVariable = nullptr;
|
||||
bool m_bCursorHidden = false;
|
||||
|
||||
void OnMenuResolutionCustom();
|
||||
|
||||
@@ -41,6 +41,7 @@ AZ_POP_DISABLE_WARNING
|
||||
|
||||
// AzToolsFramework
|
||||
#include <AzToolsFramework/Application/Ticker.h>
|
||||
#include <AzToolsFramework/API/EditorWindowRequestBus.h>
|
||||
#include <AzToolsFramework/API/EditorAnimationSystemRequestBus.h>
|
||||
#include <AzToolsFramework/SourceControl/QtSourceControlNotificationHandler.h>
|
||||
#include <AzToolsFramework/PythonTerminal/ScriptTermDialog.h>
|
||||
@@ -93,6 +94,8 @@ AZ_POP_DISABLE_WARNING
|
||||
#include "AssetEditor/AssetEditorWindow.h"
|
||||
#include "ActionManager.h"
|
||||
|
||||
#include <ImGuiBus.h>
|
||||
|
||||
using namespace AZ;
|
||||
using namespace AzQtComponents;
|
||||
using namespace AzToolsFramework;
|
||||
@@ -489,6 +492,16 @@ void MainWindow::Initialize()
|
||||
ActionOverrideRequestBus::Event(
|
||||
GetEntityContextId(), &ActionOverrideRequests::SetupActionOverrideHandler, this);
|
||||
|
||||
if (auto imGuiManager = AZ::Interface<ImGui::IImGuiManager>::Get())
|
||||
{
|
||||
auto handleImGuiStateChangeFn = [](bool enabled)
|
||||
{
|
||||
EditorWindowUIRequestBus::Broadcast(&EditorWindowUIRequests::SetEditorUiEnabled, enabled);
|
||||
};
|
||||
m_handleImGuiStateChangeHandler = ImGui::IImGuiManager::ImGuiSetEnabledEvent::Handler(handleImGuiStateChangeFn);
|
||||
imGuiManager->ConnectImGuiSetEnabledChangedHandler(m_handleImGuiStateChangeHandler);
|
||||
}
|
||||
|
||||
AzToolsFramework::EditorEventsBus::Broadcast(&AzToolsFramework::EditorEvents::NotifyMainWindowInitialized, this);
|
||||
}
|
||||
|
||||
|
||||
@@ -249,6 +249,7 @@ private:
|
||||
|
||||
QPointer<ToolbarCustomizationDialog> m_toolbarCustomizationDialog;
|
||||
QScopedPointer<AzToolsFramework::QtSourceControlNotificationHandler> m_sourceControlNotifHandler;
|
||||
AZ::Event<bool>::Handler m_handleImGuiStateChangeHandler;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
static MainWindow* m_instance;
|
||||
|
||||
@@ -27,6 +27,7 @@ ly_add_target(
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
3rdParty::Qt::Core
|
||||
3rdParty::Qt::Widgets
|
||||
AZ::AzCore
|
||||
AZ::AzToolsFramework
|
||||
Legacy::CryCommon
|
||||
|
||||
+2
@@ -66,3 +66,5 @@ namespace EntityOutliner
|
||||
emit OnOptionToggled(DisplayOption::AutoExpand, checked);
|
||||
}
|
||||
}
|
||||
|
||||
#include <UI/Outliner/moc_OutlinerDisplayOptionsMenu.cpp>
|
||||
|
||||
+18
-1
@@ -32,7 +32,24 @@ bool OutlinerSortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelI
|
||||
|
||||
bool OutlinerSortFilterProxyModel::lessThan(const QModelIndex& leftIndex, const QModelIndex& rightIndex) const
|
||||
{
|
||||
return sourceModel()->data(leftIndex).toString() < sourceModel()->data(rightIndex).toString();
|
||||
if (leftIndex.isValid() && rightIndex.isValid())
|
||||
{
|
||||
QVariant leftData = sourceModel()->data(leftIndex);
|
||||
QVariant rightData = sourceModel()->data(rightIndex);
|
||||
|
||||
// make sure to compare the correct data types for sorting the current column
|
||||
AZ_Assert(leftData.type() == rightData.type(), "OutlinerSortFilterProxyModel::lessThan types do not agree!");
|
||||
if (static_cast<QMetaType::Type>(leftData.type()) == QMetaType::QString)
|
||||
{
|
||||
return leftData.toString() < rightData.toString();
|
||||
}
|
||||
else if (static_cast<QMetaType::Type>(leftData.type()) == QMetaType::ULongLong)
|
||||
{
|
||||
return leftData.toULongLong() < rightData.toULongLong();
|
||||
}
|
||||
AZ_Error("Editor", false, "Error! Unhandled type \"%s\" in OutlinerSortFilterProxyModel::lessThan", leftData.typeName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void OutlinerSortFilterProxyModel::sort(int /*column*/, Qt::SortOrder /*order*/)
|
||||
|
||||
@@ -269,10 +269,12 @@ OutlinerWidget::OutlinerWidget(QWidget* pParent, Qt::WindowFlags flags)
|
||||
AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusConnect(
|
||||
AzToolsFramework::GetEntityContextId());
|
||||
AzToolsFramework::EditorEntityInfoNotificationBus::Handler::BusConnect();
|
||||
AzToolsFramework::EditorWindowUIRequestBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
OutlinerWidget::~OutlinerWidget()
|
||||
{
|
||||
AzToolsFramework::EditorWindowUIRequestBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::EditorEntityInfoNotificationBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::EditorPickModeNotificationBus::Handler::BusDisconnect();
|
||||
@@ -1321,16 +1323,25 @@ static void SetEntityOutlinerState(Ui::OutlinerWidgetUI* entityOutlinerUi, const
|
||||
AzQtComponents::SetWidgetInteractEnabled(entityOutlinerUi->m_searchWidget, on);
|
||||
}
|
||||
|
||||
void OutlinerWidget::EnableUi(bool enable)
|
||||
{
|
||||
SetEntityOutlinerState(m_gui, enable);
|
||||
setEnabled(enable);
|
||||
}
|
||||
|
||||
void OutlinerWidget::SetEditorUiEnabled(bool enable)
|
||||
{
|
||||
EnableUi(enable);
|
||||
}
|
||||
|
||||
void OutlinerWidget::EnteredComponentMode([[maybe_unused]] const AZStd::vector<AZ::Uuid>& componentModeTypes)
|
||||
{
|
||||
SetEntityOutlinerState(m_gui, false);
|
||||
setEnabled(false);
|
||||
EnableUi(false);
|
||||
}
|
||||
|
||||
void OutlinerWidget::LeftComponentMode([[maybe_unused]] const AZStd::vector<AZ::Uuid>& componentModeTypes)
|
||||
{
|
||||
setEnabled(true);
|
||||
SetEntityOutlinerState(m_gui, true);
|
||||
EnableUi(true);
|
||||
}
|
||||
|
||||
void OutlinerWidget::OnSliceInstantiated(const AZ::Data::AssetId& /*sliceAssetId*/, AZ::SliceComponent::SliceInstanceAddress& sliceAddress, const AzFramework::SliceInstantiationTicket& /*ticket*/)
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/base.h>
|
||||
#include <AzToolsFramework/API/EditorWindowRequestBus.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
|
||||
@@ -57,6 +58,7 @@ class OutlinerWidget
|
||||
, private AzToolsFramework::SliceEditorEntityOwnershipServiceNotificationBus::Handler
|
||||
, private AzToolsFramework::EditorEntityInfoNotificationBus::Handler
|
||||
, private AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler
|
||||
, private AzToolsFramework::EditorWindowUIRequestBus::Handler
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
@@ -106,6 +108,9 @@ private:
|
||||
void EnteredComponentMode(const AZStd::vector<AZ::Uuid>& componentModeTypes) override;
|
||||
void LeftComponentMode(const AZStd::vector<AZ::Uuid>& componentModeTypes) override;
|
||||
|
||||
// EditorWindowUIRequestBus overrides
|
||||
void SetEditorUiEnabled(bool enable) override;
|
||||
|
||||
// Build a selection object from the given entities. Entities already in the Widget's selection buffers are ignored.
|
||||
template <class EntityIdCollection>
|
||||
QItemSelection BuildSelectionFromEntities(const EntityIdCollection& entityIds);
|
||||
@@ -171,6 +176,7 @@ private:
|
||||
AZ::EntityId GetEntityIdFromIndex(const QModelIndex& index) const;
|
||||
QModelIndex GetIndexFromEntityId(const AZ::EntityId& entityId) const;
|
||||
void ExtractEntityIdsFromSelection(const QItemSelection& selection, AzToolsFramework::EntityIdList& entityIdList) const;
|
||||
void EnableUi(bool enable);
|
||||
|
||||
// AzToolsFramework::OutlinerModelNotificationBus::Handler
|
||||
// Receive notification from the outliner model that we should scroll
|
||||
|
||||
@@ -23,6 +23,7 @@ ly_add_target(
|
||||
.
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
3rdParty::Qt::Core
|
||||
AZ::AzCore
|
||||
Legacy::CryCommon
|
||||
Legacy::EditorLib
|
||||
|
||||
@@ -17,19 +17,8 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <platform.h>
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// STL
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CRY Stuff ////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#include <ISystem.h>
|
||||
#include "Util/EditorUtils.h"
|
||||
#include "EditorCoreAPI.h"
|
||||
|
||||
@@ -31,6 +31,8 @@ ly_add_target(
|
||||
.
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
3rdParty::Qt::Core
|
||||
3rdParty::Qt::Widgets
|
||||
AZ::AzCore
|
||||
Legacy::CryCommon
|
||||
Legacy::EditorLib
|
||||
|
||||
@@ -525,6 +525,7 @@ QtViewPaneManager::QtViewPaneManager(QObject* parent)
|
||||
|
||||
// view pane manager is interested when we enter/exit ComponentMode
|
||||
m_componentModeNotifications.BusConnect(AzToolsFramework::GetEntityContextId());
|
||||
m_windowRequest.BusConnect();
|
||||
|
||||
m_componentModeNotifications.SetEnteredComponentModeFunc(
|
||||
[this](const AZStd::vector<AZ::Uuid>& /*componentModeTypes*/)
|
||||
@@ -545,10 +546,23 @@ QtViewPaneManager::QtViewPaneManager(QObject* parent)
|
||||
AzQtComponents::SetWidgetInteractEnabled(widget, on);
|
||||
});
|
||||
});
|
||||
|
||||
m_windowRequest.SetEnableEditorUiFunc(
|
||||
[this](bool enable)
|
||||
{
|
||||
// gray out panels when entering ImGui mode
|
||||
SetDefaultActionsEnabled(
|
||||
enable, m_registeredPanes,
|
||||
[](QWidget* widget, bool on)
|
||||
{
|
||||
AzQtComponents::SetWidgetInteractEnabled(widget, on);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
QtViewPaneManager::~QtViewPaneManager()
|
||||
{
|
||||
m_windowRequest.BusDisconnect();
|
||||
m_componentModeNotifications.BusDisconnect();
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <AzQtComponents/Components/StyledDockWidget.h>
|
||||
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
|
||||
#include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
|
||||
#include <AzToolsFramework/API/EditorWindowRequestBus.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
@@ -249,8 +250,12 @@ private:
|
||||
QPointer<AzQtComponents::FancyDocking> m_advancedDockManager;
|
||||
|
||||
using EditorComponentModeNotificationBusImpl = AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBusImpl;
|
||||
EditorComponentModeNotificationBusImpl m_componentModeNotifications; /**< Helper for EditorComponentModeNotificationBus so
|
||||
* QtViewPaneManager does not need to inherit directly from it. */
|
||||
EditorComponentModeNotificationBusImpl m_componentModeNotifications; //!< Helper for EditorComponentModeNotificationBus so
|
||||
//!< QtViewPaneManager does not need to inherit directly from it. */
|
||||
|
||||
using EditorWindowRequestBusImpl = AzToolsFramework::EditorWindowRequestBusImpl;
|
||||
EditorWindowRequestBusImpl m_windowRequest; //!< Helper for EditorWindowRequestBus so
|
||||
//!< QtViewPaneManager does not need to inherit directly from it. */
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
@@ -27,11 +27,17 @@ namespace AZ
|
||||
template <typename... Params>
|
||||
EventHandler<Params...>::EventHandler(const EventHandler& rhs)
|
||||
: m_callback(rhs.m_callback)
|
||||
, m_event(rhs.m_event)
|
||||
{
|
||||
// Copy the callback function, then perform a Connect with the new event
|
||||
if (rhs.m_event)
|
||||
// Copy the callback and event, then perform a Connect to the event
|
||||
if (m_callback && m_event)
|
||||
{
|
||||
rhs.m_event->Connect(*this);
|
||||
m_event->Connect(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// It was not possible to connect to the event, set it to nullptr
|
||||
m_event = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,9 +71,16 @@ namespace AZ
|
||||
{
|
||||
Disconnect();
|
||||
m_callback = rhs.m_callback;
|
||||
if (rhs.m_event)
|
||||
m_event = rhs.m_event;
|
||||
// Copy the callback and event, then perform a Connect to the event
|
||||
if (m_callback && m_event)
|
||||
{
|
||||
rhs.m_event->Connect(*this);
|
||||
m_event->Connect(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// It was not possible to connect to the event, set it to nullptr
|
||||
m_event = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,15 @@ namespace AZ
|
||||
{
|
||||
if (m_hashes.size() < m_hashes.max_size())
|
||||
{
|
||||
constexpr size_t MaxTagSize = TagName{}.max_size();
|
||||
if (specialization.size() > MaxTagSize)
|
||||
{
|
||||
AZ_Error("Settings Registry", false, R"(Cannot append Specialization tag of "%.*s.")"
|
||||
" It is longer than the MaxTagNameSize of %zu", AZ_STRING_ARG(specialization),
|
||||
MaxTagSize);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_names.push_back(TagName{ specialization });
|
||||
TagName& tag = m_names.back();
|
||||
AZStd::to_lower(tag.begin(), tag.end());
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace AZ
|
||||
class Specializations
|
||||
{
|
||||
public:
|
||||
static constexpr size_t MaxTagNameSize = 32;
|
||||
static constexpr size_t MaxTagNameSize = 64;
|
||||
static constexpr size_t MaxCount = 15;
|
||||
static constexpr size_t NotFound = static_cast<size_t>(-1);
|
||||
using TagName = AZStd::fixed_string<MaxTagNameSize>;
|
||||
|
||||
@@ -146,7 +146,7 @@ namespace AZ {
|
||||
AZStd::mutex g_dbgLoadingMutex;
|
||||
HANDLE g_currentProcess = 0; /// We deal with only one process for now.
|
||||
CRITICAL_SECTION g_csDbgHelpDll; /// All dbg help functions are single threaded, so we need to control the access.
|
||||
AZStd::fixed_vector<SymbolStorage::ModuleInfo, 256> g_moduleInfo;
|
||||
AZStd::fixed_vector<SymbolStorage::ModuleInfo, 2048> g_moduleInfo;
|
||||
|
||||
// reserve 4k of scratch space so that we can get some callstack information without any allocations and as little stack frame usage as possible.
|
||||
const size_t g_scratchSpaceSize = 2048;
|
||||
|
||||
@@ -257,6 +257,48 @@ namespace UnitTest
|
||||
EXPECT_FALSE(testEvent1.HasHandlerConnected());
|
||||
EXPECT_TRUE(testEvent2.HasHandlerConnected());
|
||||
}
|
||||
|
||||
TEST_F(EventTests, TestHandlerCopyConstructorOperator)
|
||||
{
|
||||
int32_t invokedCounter = 0;
|
||||
|
||||
AZ::Event<> testEvent;
|
||||
AZ::Event<>::Handler testHandler([&invokedCounter]() { invokedCounter++; });
|
||||
|
||||
testHandler.Connect(testEvent);
|
||||
|
||||
AZ::Event<>::Handler testHandler2(testHandler);
|
||||
|
||||
EXPECT_TRUE(testHandler.IsConnected());
|
||||
EXPECT_TRUE(testHandler2.IsConnected());
|
||||
|
||||
EXPECT_TRUE(invokedCounter == 0);
|
||||
testEvent.Signal();
|
||||
EXPECT_TRUE(invokedCounter == 2);
|
||||
}
|
||||
|
||||
TEST_F(EventTests, TestHandlerCopyAssignmentOperator)
|
||||
{
|
||||
int32_t invokedCounter = 0;
|
||||
|
||||
AZ::Event<> testEvent;
|
||||
AZ::Event<>::Handler testHandler([&invokedCounter]() { invokedCounter++; });
|
||||
|
||||
testHandler.Connect(testEvent);
|
||||
|
||||
AZ::Event<>::Handler testHandler2;
|
||||
|
||||
EXPECT_TRUE(testHandler.IsConnected());
|
||||
EXPECT_FALSE(testHandler2.IsConnected());
|
||||
|
||||
testHandler2 = testHandler;
|
||||
|
||||
EXPECT_TRUE(testHandler2.IsConnected());
|
||||
|
||||
EXPECT_TRUE(invokedCounter == 0);
|
||||
testEvent.Signal();
|
||||
EXPECT_TRUE(invokedCounter == 2);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HAVE_BENCHMARK)
|
||||
|
||||
@@ -12,5 +12,5 @@
|
||||
#define AZ_TRAIT_AZFRAMEWORK_USE_ERRNO_T_TYPEDEF 1
|
||||
#define AZ_TRAIT_AZFRAMEWORK_USE_POSIX_LOCALTIME_R 0
|
||||
#define AZ_TRAIT_AZFRAMEWORK_PYTHON_SHELL "python.sh"
|
||||
#define AZ_TRAIT_AZFRAMEWORK_USE_PROJECT_MANAGER 0
|
||||
#define AZ_TRAIT_AZFRAMEWORK_USE_PROJECT_MANAGER 1
|
||||
#define AZ_TRAIT_AZFRAMEWORK_PROCESSLAUNCH_DEFAULT 0
|
||||
|
||||
@@ -12,5 +12,5 @@
|
||||
#define AZ_TRAIT_AZFRAMEWORK_USE_ERRNO_T_TYPEDEF 0
|
||||
#define AZ_TRAIT_AZFRAMEWORK_USE_POSIX_LOCALTIME_R 1
|
||||
#define AZ_TRAIT_AZFRAMEWORK_PYTHON_SHELL "python.sh"
|
||||
#define AZ_TRAIT_AZFRAMEWORK_USE_PROJECT_MANAGER 0
|
||||
#define AZ_TRAIT_AZFRAMEWORK_USE_PROJECT_MANAGER 1
|
||||
#define AZ_TRAIT_AZFRAMEWORK_PROCESSLAUNCH_DEFAULT 0
|
||||
|
||||
@@ -36,8 +36,47 @@ namespace AzToolsFramework
|
||||
/// Retrieve the main application window.
|
||||
virtual QWidget* GetAppMainWindow() { return nullptr; }
|
||||
};
|
||||
|
||||
using EditorWindowRequestBus = AZ::EBus<EditorWindowRequests>;
|
||||
|
||||
class EditorWindowUIRequests : public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
using Bus = AZ::EBus<EditorWindowUIRequests>;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Enable/Disable the Editor UI.
|
||||
virtual void SetEditorUiEnabled([[maybe_unused]] bool enable) {}
|
||||
};
|
||||
using EditorWindowUIRequestBus = AZ::EBus<EditorWindowUIRequests>;
|
||||
|
||||
using EnableUiFunction = AZStd::function<void(bool)>;
|
||||
|
||||
/// Helper for EditorWindowRequests to be used as a
|
||||
/// member instead of inheriting from EBus directly.
|
||||
class EditorWindowRequestBusImpl
|
||||
: public EditorWindowUIRequestBus::Handler
|
||||
{
|
||||
public:
|
||||
/// Set the function to be called when entering ImGui Mode.
|
||||
void SetEnableEditorUiFunc(const EnableUiFunction enableEditorUiFunc)
|
||||
{
|
||||
m_enableEditorUiFunc = AZStd::move(enableEditorUiFunc);
|
||||
}
|
||||
|
||||
private:
|
||||
// EditorWindowRequestBus
|
||||
void SetEditorUiEnabled( [[maybe_unused]] bool enable) override
|
||||
{
|
||||
m_enableEditorUiFunc(enable);
|
||||
}
|
||||
|
||||
EnableUiFunction m_enableEditorUiFunc; ///< Function to call when entering ImGui Mode.
|
||||
};
|
||||
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
#endif // AZTOOLSFRAMEWORK_EDITORWINDOWREQUESTBUS_H
|
||||
|
||||
+18
-1
@@ -34,7 +34,24 @@ namespace AzToolsFramework
|
||||
|
||||
bool EntityOutlinerSortFilterProxyModel::lessThan(const QModelIndex& leftIndex, const QModelIndex& rightIndex) const
|
||||
{
|
||||
return sourceModel()->data(leftIndex).toString() < sourceModel()->data(rightIndex).toString();
|
||||
if (leftIndex.isValid() && rightIndex.isValid())
|
||||
{
|
||||
QVariant leftData = sourceModel()->data(leftIndex);
|
||||
QVariant rightData = sourceModel()->data(rightIndex);
|
||||
|
||||
// make sure to compare the correct data types for sorting the current column
|
||||
AZ_Assert(leftData.type() == rightData.type(), "EntityOutlinerSortFilterProxyModel::lessThan types do not agree!");
|
||||
if (static_cast<QMetaType::Type>(leftData.type()) == QMetaType::QString)
|
||||
{
|
||||
return leftData.toString() < rightData.toString();
|
||||
}
|
||||
else if (static_cast<QMetaType::Type>(leftData.type()) == QMetaType::ULongLong)
|
||||
{
|
||||
return leftData.toULongLong() < rightData.toULongLong();
|
||||
}
|
||||
AZ_Error("Editor", false, "Error! Unhandled type \"%s\" in EntityOutlinerSortFilterProxyModel::lessThan", leftData.typeName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void EntityOutlinerSortFilterProxyModel::sort(int /*column*/, Qt::SortOrder /*order*/)
|
||||
|
||||
+15
-4
@@ -291,10 +291,12 @@ namespace AzToolsFramework
|
||||
GetEntityContextId());
|
||||
EditorEntityInfoNotificationBus::Handler::BusConnect();
|
||||
Prefab::PrefabPublicNotificationBus::Handler::BusConnect();
|
||||
EditorWindowUIRequestBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
EntityOutlinerWidget::~EntityOutlinerWidget()
|
||||
{
|
||||
EditorWindowUIRequestBus::Handler::BusDisconnect();
|
||||
Prefab::PrefabPublicNotificationBus::Handler::BusDisconnect();
|
||||
ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusDisconnect();
|
||||
EditorEntityInfoNotificationBus::Handler::BusDisconnect();
|
||||
@@ -1106,16 +1108,25 @@ namespace AzToolsFramework
|
||||
AzQtComponents::SetWidgetInteractEnabled(entityOutlinerUi->m_searchWidget, on);
|
||||
}
|
||||
|
||||
void EntityOutlinerWidget::EnableUi(bool enable)
|
||||
{
|
||||
SetEntityOutlinerState(m_gui, enable);
|
||||
setEnabled(enable);
|
||||
}
|
||||
|
||||
void EntityOutlinerWidget::SetEditorUiEnabled(bool enable)
|
||||
{
|
||||
EnableUi(enable);
|
||||
}
|
||||
|
||||
void EntityOutlinerWidget::EnteredComponentMode([[maybe_unused]] const AZStd::vector<AZ::Uuid>& componentModeTypes)
|
||||
{
|
||||
SetEntityOutlinerState(m_gui, false);
|
||||
setEnabled(false);
|
||||
EnableUi(false);
|
||||
}
|
||||
|
||||
void EntityOutlinerWidget::LeftComponentMode([[maybe_unused]] const AZStd::vector<AZ::Uuid>& componentModeTypes)
|
||||
{
|
||||
setEnabled(true);
|
||||
SetEntityOutlinerState(m_gui, true);
|
||||
EnableUi(true);
|
||||
}
|
||||
|
||||
void EntityOutlinerWidget::OnPrefabInstancePropagationBegin()
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/base.h>
|
||||
|
||||
#include <AzToolsFramework/API/EditorWindowRequestBus.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
|
||||
@@ -58,6 +59,7 @@ namespace AzToolsFramework
|
||||
, private EditorEntityInfoNotificationBus::Handler
|
||||
, private ComponentModeFramework::EditorComponentModeNotificationBus::Handler
|
||||
, private Prefab::PrefabPublicNotificationBus::Handler
|
||||
, private EditorWindowUIRequestBus::Handler
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
@@ -105,6 +107,9 @@ namespace AzToolsFramework
|
||||
void OnPrefabInstancePropagationBegin() override;
|
||||
void OnPrefabInstancePropagationEnd() override;
|
||||
|
||||
// EditorWindowUIRequestBus overrides
|
||||
void SetEditorUiEnabled(bool enable) override;
|
||||
|
||||
// Build a selection object from the given entities. Entities already in the Widget's selection buffers are ignored.
|
||||
template <class EntityIdCollection>
|
||||
QItemSelection BuildSelectionFromEntities(const EntityIdCollection& entityIds);
|
||||
@@ -155,6 +160,7 @@ namespace AzToolsFramework
|
||||
AZ::EntityId GetEntityIdFromIndex(const QModelIndex& index) const;
|
||||
QModelIndex GetIndexFromEntityId(const AZ::EntityId& entityId) const;
|
||||
void ExtractEntityIdsFromSelection(const QItemSelection& selection, EntityIdList& entityIdList) const;
|
||||
void EnableUi(bool enable);
|
||||
|
||||
// OutlinerModelNotificationBus::Handler
|
||||
// Receive notification from the outliner model that we should scroll
|
||||
|
||||
+23
@@ -376,6 +376,7 @@ namespace AzToolsFramework
|
||||
ToolsApplicationEvents::Bus::Handler::BusConnect();
|
||||
AZ::EntitySystemBus::Handler::BusConnect();
|
||||
EntityPropertyEditorRequestBus::Handler::BusConnect();
|
||||
EditorWindowUIRequestBus::Handler::BusConnect();
|
||||
m_spacer = nullptr;
|
||||
|
||||
m_emptyIcon = QIcon();
|
||||
@@ -421,6 +422,7 @@ namespace AzToolsFramework
|
||||
{
|
||||
qApp->removeEventFilter(this);
|
||||
|
||||
EditorWindowUIRequestBus::Handler::BusDisconnect();
|
||||
EntityPropertyEditorRequestBus::Handler::BusDisconnect();
|
||||
ToolsApplicationEvents::Bus::Handler::BusDisconnect();
|
||||
AZ::EntitySystemBus::Handler::BusDisconnect();
|
||||
@@ -4961,6 +4963,27 @@ namespace AzToolsFramework
|
||||
EnableDisableComponentActions(widget, actions, false);
|
||||
}
|
||||
|
||||
void EntityPropertyEditor::SetEditorUiEnabled(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
EnableComponentActions(this, m_entityComponentActions);
|
||||
}
|
||||
else
|
||||
{
|
||||
DisableComponentActions(this, m_entityComponentActions);
|
||||
}
|
||||
m_disabled = !enable;
|
||||
SetPropertyEditorState(m_gui, enable);
|
||||
|
||||
for (auto componentEditor : m_componentEditors)
|
||||
{
|
||||
AzQtComponents::SetWidgetInteractEnabled(componentEditor, enable);
|
||||
}
|
||||
// record the selected state after entering/leaving component mode
|
||||
SaveComponentEditorState();
|
||||
}
|
||||
|
||||
void EntityPropertyEditor::EnteredComponentMode(const AZStd::vector<AZ::Uuid>& componentModeTypes)
|
||||
{
|
||||
DisableComponentActions(this, m_entityComponentActions);
|
||||
|
||||
+5
@@ -21,6 +21,7 @@
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
|
||||
#include <AzToolsFramework/Undo/UndoSystem.h>
|
||||
#include <AzToolsFramework/API/EditorWindowRequestBus.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzToolsFramework/API/EntityPropertyEditorRequestsBus.h>
|
||||
#include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
|
||||
@@ -108,6 +109,7 @@ namespace AzToolsFramework
|
||||
, public EditorInspectorComponentNotificationBus::MultiHandler
|
||||
, private AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler
|
||||
, public AZ::EntitySystemBus::Handler
|
||||
, private EditorWindowUIRequestBus::Handler
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
@@ -208,6 +210,9 @@ namespace AzToolsFramework
|
||||
void GetSelectedEntities(EntityIdList& selectedEntityIds) override;
|
||||
void SetNewComponentId(AZ::ComponentId componentId) override;
|
||||
|
||||
// EditorWindowRequestBus overrides
|
||||
void SetEditorUiEnabled(bool enable) override;
|
||||
|
||||
bool IsEntitySelected(const AZ::EntityId& id) const;
|
||||
bool IsSingleEntitySelected(const AZ::EntityId& id) const;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
@@ -277,7 +277,7 @@ void FileWatcherUnitTestRunner::StartTest()
|
||||
UNIT_TEST_EXPECT_TRUE(QDir::toNativeSeparators(fileAddName).toLower() == QDir::toNativeSeparators(newName3).toLower());
|
||||
|
||||
#if !defined(AZ_PLATFORM_LINUX)
|
||||
// final test... make sure that renaming a DIRECTORY works too.
|
||||
// final test... make sure that renaming a DIRECTORY works too.
|
||||
// Note that linux does not get any callbacks if just the directory is renamed (from inotify)
|
||||
QDir renamer;
|
||||
fileAddCalled = false;
|
||||
@@ -312,6 +312,9 @@ void FileWatcherUnitTestRunner::StartTest()
|
||||
Q_EMIT UnitTestPassed();
|
||||
}
|
||||
|
||||
#if !AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
// File operations on Linux behave differently on Linux than Windows.
|
||||
// The system under test doesn't yet handle Linux's file operations, which surfaced as this test arbitrarily passing and failing.
|
||||
// This test is disabled on Linux until the system under test can handle Linux file system behavior correctly.
|
||||
#if !AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS && !defined(AZ_PLATFORM_LINUX)
|
||||
REGISTER_UNIT_TEST(FileWatcherUnitTestRunner)
|
||||
#endif // !AZ_TRAIT_DISABLE_FAILED_ASSET_PROCESSOR_TESTS
|
||||
|
||||
@@ -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>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user