Merge branch 'development' into Prefab/BestEffortPatching

Signed-off-by: srikappa <srikappa@amazon.com>
This commit is contained in:
srikappa
2021-07-13 11:52:07 -07:00
263 changed files with 6733 additions and 11736 deletions
+1 -2
View File
@@ -47,8 +47,7 @@ set(ENABLED_GEMS
LmbrCentral
LyShine
HttpRequestor
Atom_AtomBridge
PythonCoverage
Atom
AWSCore
AWSClientAuth
AWSMetrics
@@ -77,7 +77,6 @@ class TestAllComponentsIndepthTests(object):
unexpected_lines=unexpected_lines,
halt_on_unexpected=True,
cfg_args=[level],
auto_test_mode=False,
null_renderer=False,
)
@@ -60,24 +60,7 @@ class TestEditMenuOptions(EditorTestHelper):
("Modify", "Transform Mode", "Rotate"),
("Modify", "Transform Mode", "Scale"),
("Editor Settings", "Global Preferences"),
("Editor Settings", "Graphics Settings"),
("Editor Settings", "Editor Settings Manager"),
("Editor Settings", "Graphics Performance", "PC", "Very High"),
("Editor Settings", "Graphics Performance", "PC", "High"),
("Editor Settings", "Graphics Performance", "PC", "Medium"),
("Editor Settings", "Graphics Performance", "PC", "Low"),
("Editor Settings", "Graphics Performance", "OSX Metal", "Very High"),
("Editor Settings", "Graphics Performance", "OSX Metal", "High"),
("Editor Settings", "Graphics Performance", "OSX Metal", "Medium"),
("Editor Settings", "Graphics Performance", "OSX Metal", "Low"),
("Editor Settings", "Graphics Performance", "Android", "Very High"),
("Editor Settings", "Graphics Performance", "Android", "High"),
("Editor Settings", "Graphics Performance", "Android", "Medium"),
("Editor Settings", "Graphics Performance", "Android", "Low"),
("Editor Settings", "Graphics Performance", "iOS", "Very High"),
("Editor Settings", "Graphics Performance", "iOS", "High"),
("Editor Settings", "Graphics Performance", "iOS", "Medium"),
("Editor Settings", "Graphics Performance", "iOS", "Low"),
("Editor Settings", "Keyboard Customization", "Customize Keyboard"),
("Editor Settings", "Keyboard Customization", "Export Keyboard Settings"),
("Editor Settings", "Keyboard Customization", "Import Keyboard Settings"),
@@ -55,12 +55,7 @@ class TestMenus(object):
"Rotate Action triggered",
"Scale Action triggered",
"Global Preferences Action triggered",
"Graphics Settings Action triggered",
"Editor Settings Manager Action triggered",
"Very High Action triggered",
"High Action triggered",
"Medium Action triggered",
"Low Action triggered",
"Customize Keyboard Action triggered",
"Export Keyboard Settings Action triggered",
"Import Keyboard Settings Action triggered",
@@ -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()
-2
View File
@@ -111,7 +111,6 @@ ly_add_target(
AZ::AzCore
AZ::AzToolsFramework
Gem::LmbrCentral.Static
Legacy::NewsShared
AZ::AWSNativeSDKInit
AZ::AtomCore
Gem::Atom_RPI.Edit
@@ -139,7 +138,6 @@ ly_add_source_properties(
ly_add_source_properties(
SOURCES
Core/LevelEditorMenuHandler.cpp
GraphicsSettingsDialog.cpp
MainWindow.cpp
PROPERTY COMPILE_DEFINITIONS
VALUES ${LY_PAL_TOOLS_DEFINES}
+7 -41
View File
@@ -497,9 +497,15 @@ void LevelEditorMenuHandler::PopulateEditMenu(ActionManager::MenuWrapper& editMe
// Hide Selection
editMenu.AddAction(AzToolsFramework::HideSelection);
// Unhide All
// Show All
editMenu.AddAction(AzToolsFramework::ShowAll);
// Lock Selection
editMenu.AddAction(AzToolsFramework::LockSelection);
// UnLock All
editMenu.AddAction(AzToolsFramework::UnlockAll);
/*
* The following block of code is part of the feature "Isolation Mode" and is temporarily
* disabled for 1.10 release.
@@ -552,49 +558,9 @@ void LevelEditorMenuHandler::PopulateEditMenu(ActionManager::MenuWrapper& editMe
// Global Preferences...
editorSettingsMenu.AddAction(ID_TOOLS_PREFERENCES);
// Graphics Settings...
editorSettingsMenu.AddAction(ID_GRAPHICS_SETTINGS);
// Editor Settings Manager
AddOpenViewPaneAction(editorSettingsMenu, LyViewPane::EditorSettingsManager);
// Graphics Performance
auto graphicPerformanceSubMenu = editorSettingsMenu.AddMenu(QObject::tr("Graphics Performance"));
auto pcMenu = graphicPerformanceSubMenu.AddMenu(tr("PC"));
pcMenu.AddAction(ID_GAME_PC_ENABLEVERYHIGHSPEC);
pcMenu.AddAction(ID_GAME_PC_ENABLEHIGHSPEC);
pcMenu.AddAction(ID_GAME_PC_ENABLEMEDIUMSPEC);
pcMenu.AddAction(ID_GAME_PC_ENABLELOWSPEC);
auto osxmetalMenu = graphicPerformanceSubMenu.AddMenu(tr("OSX Metal"));
osxmetalMenu.AddAction(ID_GAME_OSXMETAL_ENABLEVERYHIGHSPEC);
osxmetalMenu.AddAction(ID_GAME_OSXMETAL_ENABLEHIGHSPEC);
osxmetalMenu.AddAction(ID_GAME_OSXMETAL_ENABLEMEDIUMSPEC);
osxmetalMenu.AddAction(ID_GAME_OSXMETAL_ENABLELOWSPEC);
auto androidMenu = graphicPerformanceSubMenu.AddMenu(tr("Android"));
androidMenu.AddAction(ID_GAME_ANDROID_ENABLEVERYHIGHSPEC);
androidMenu.AddAction(ID_GAME_ANDROID_ENABLEHIGHSPEC);
androidMenu.AddAction(ID_GAME_ANDROID_ENABLEMEDIUMSPEC);
androidMenu.AddAction(ID_GAME_ANDROID_ENABLELOWSPEC);
auto iosMenu = graphicPerformanceSubMenu.AddMenu(tr("iOS"));
iosMenu.AddAction(ID_GAME_IOS_ENABLEVERYHIGHSPEC);
iosMenu.AddAction(ID_GAME_IOS_ENABLEHIGHSPEC);
iosMenu.AddAction(ID_GAME_IOS_ENABLEMEDIUMSPEC);
iosMenu.AddAction(ID_GAME_IOS_ENABLELOWSPEC);
#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
#define AZ_RESTRICTED_PLATFORM_EXPANSION(CodeName, CODENAME, codename, PrivateName, PRIVATENAME, privatename, PublicName, PUBLICNAME, publicname, PublicAuxName1, PublicAuxName2, PublicAuxName3)\
auto publicname##Menu = graphicPerformanceSubMenu.AddMenu(tr(PublicAuxName2));\
publicname##Menu.AddAction(ID_GAME_##CODENAME##_ENABLEHIGHSPEC);\
publicname##Menu.AddAction(ID_GAME_##CODENAME##_ENABLEMEDIUMSPEC);\
publicname##Menu.AddAction(ID_GAME_##CODENAME##_ENABLELOWSPEC);
AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS
#undef AZ_RESTRICTED_PLATFORM_EXPANSION
#endif
// Keyboard Customization
auto keyboardCustomizationMenu = editorSettingsMenu.AddMenu(tr("Keyboard Customization"));
keyboardCustomizationMenu.AddAction(ID_TOOLS_CUSTOMIZEKEYBOARD);
-102
View File
@@ -111,7 +111,6 @@ AZ_POP_DISABLE_WARNING
#include "ToolBox.h"
#include "LevelInfo.h"
#include "EditorPreferencesDialog.h"
#include "GraphicsSettingsDialog.h"
#include "AnimationContext.h"
#include "GotoPositionDlg.h"
@@ -440,7 +439,6 @@ void CCryEditApp::RegisterActionHandlers()
ON_COMMAND(ID_CLEAR_REGISTRY, OnClearRegistryData)
ON_COMMAND(ID_VALIDATELEVEL, OnValidatelevel)
ON_COMMAND(ID_TOOLS_PREFERENCES, OnToolsPreferences)
ON_COMMAND(ID_GRAPHICS_SETTINGS, OnGraphicsSettings)
ON_COMMAND(ID_SWITCHCAMERA_DEFAULTCAMERA, OnSwitchToDefaultCamera)
ON_COMMAND(ID_SWITCHCAMERA_SEQUENCECAMERA, OnSwitchToSequenceCamera)
ON_COMMAND(ID_SWITCHCAMERA_SELECTEDCAMERA, OnSwitchToSelectedcamera)
@@ -453,14 +451,6 @@ void CCryEditApp::RegisterActionHandlers()
ON_COMMAND(ID_OPEN_TRACKVIEW, OnOpenTrackView)
ON_COMMAND(ID_OPEN_UICANVASEDITOR, OnOpenUICanvasEditor)
ON_COMMAND_RANGE(ID_GAME_PC_ENABLELOWSPEC, ID_GAME_PC_ENABLEVERYHIGHSPEC, OnChangeGameSpec)
ON_COMMAND_RANGE(ID_GAME_OSXMETAL_ENABLELOWSPEC, ID_GAME_OSXMETAL_ENABLEVERYHIGHSPEC, OnChangeGameSpec)
ON_COMMAND_RANGE(ID_GAME_ANDROID_ENABLELOWSPEC, ID_GAME_ANDROID_ENABLEVERYHIGHSPEC, OnChangeGameSpec)
ON_COMMAND_RANGE(ID_GAME_IOS_ENABLELOWSPEC, ID_GAME_IOS_ENABLEVERYHIGHSPEC, OnChangeGameSpec)
#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
#define AZ_RESTRICTED_PLATFORM_EXPANSION(CodeName, CODENAME, codename, PrivateName, PRIVATENAME, privatename, PublicName, PUBLICNAME, publicname, PublicAuxName1, PublicAuxName2, PublicAuxName3)\
ON_COMMAND_RANGE(ID_GAME_##CODENAME##_ENABLELOWSPEC, ID_GAME_##CODENAME##_ENABLEHIGHSPEC, OnChangeGameSpec)
@@ -3674,13 +3664,6 @@ void CCryEditApp::OnToolsPreferences()
dlg.exec();
}
//////////////////////////////////////////////////////////////////////////
void CCryEditApp::OnGraphicsSettings()
{
GraphicsSettingsDialog dlg(MainWindow::instance());
dlg.exec();
}
//////////////////////////////////////////////////////////////////////////
void CCryEditApp::OnSwitchToDefaultCamera()
{
@@ -3815,91 +3798,6 @@ void CCryEditApp::OnOpenUICanvasEditor()
QtViewPaneManager::instance()->OpenPane(LyViewPane::UiEditor);
}
//////////////////////////////////////////////////////////////////////////
void CCryEditApp::SetGameSpecCheck(ESystemConfigSpec spec, ESystemConfigPlatform platform, int &nCheck, bool &enable)
{
if (GetIEditor()->GetEditorConfigSpec() == spec && GetIEditor()->GetEditorConfigPlatform() == platform)
{
nCheck = 1;
}
enable = spec <= GetIEditor()->GetSystem()->GetMaxConfigSpec();
}
//////////////////////////////////////////////////////////////////////////
void CCryEditApp::OnUpdateGameSpec(QAction* action)
{
Q_ASSERT(action->isCheckable());
int nCheck = 0;
bool enable = true;
switch (action->data().toInt())
{
case ID_GAME_PC_ENABLELOWSPEC:
SetGameSpecCheck(CONFIG_LOW_SPEC, CONFIG_PC, nCheck, enable);
break;
case ID_GAME_PC_ENABLEMEDIUMSPEC:
SetGameSpecCheck(CONFIG_MEDIUM_SPEC, CONFIG_PC, nCheck, enable);
break;
case ID_GAME_PC_ENABLEHIGHSPEC:
SetGameSpecCheck(CONFIG_HIGH_SPEC, CONFIG_PC, nCheck, enable);
break;
case ID_GAME_PC_ENABLEVERYHIGHSPEC:
SetGameSpecCheck(CONFIG_VERYHIGH_SPEC, CONFIG_PC, nCheck, enable);
break;
case ID_GAME_OSXMETAL_ENABLELOWSPEC:
SetGameSpecCheck(CONFIG_LOW_SPEC, CONFIG_OSX_METAL, nCheck, enable);
break;
case ID_GAME_OSXMETAL_ENABLEMEDIUMSPEC:
SetGameSpecCheck(CONFIG_MEDIUM_SPEC, CONFIG_OSX_METAL, nCheck, enable);
break;
case ID_GAME_OSXMETAL_ENABLEHIGHSPEC:
SetGameSpecCheck(CONFIG_HIGH_SPEC, CONFIG_OSX_METAL, nCheck, enable);
break;
case ID_GAME_OSXMETAL_ENABLEVERYHIGHSPEC:
SetGameSpecCheck(CONFIG_VERYHIGH_SPEC, CONFIG_OSX_METAL, nCheck, enable);
break;
case ID_GAME_ANDROID_ENABLELOWSPEC:
SetGameSpecCheck(CONFIG_LOW_SPEC, CONFIG_ANDROID, nCheck, enable);
break;
case ID_GAME_ANDROID_ENABLEMEDIUMSPEC:
SetGameSpecCheck(CONFIG_MEDIUM_SPEC, CONFIG_ANDROID, nCheck, enable);
break;
case ID_GAME_ANDROID_ENABLEHIGHSPEC:
SetGameSpecCheck(CONFIG_HIGH_SPEC, CONFIG_ANDROID, nCheck, enable);
break;
case ID_GAME_ANDROID_ENABLEVERYHIGHSPEC:
SetGameSpecCheck(CONFIG_VERYHIGH_SPEC, CONFIG_ANDROID, nCheck, enable);
break;
case ID_GAME_IOS_ENABLELOWSPEC:
SetGameSpecCheck(CONFIG_LOW_SPEC, CONFIG_IOS, nCheck, enable);
break;
case ID_GAME_IOS_ENABLEMEDIUMSPEC:
SetGameSpecCheck(CONFIG_MEDIUM_SPEC, CONFIG_IOS, nCheck, enable);
break;
case ID_GAME_IOS_ENABLEHIGHSPEC:
SetGameSpecCheck(CONFIG_HIGH_SPEC, CONFIG_IOS, nCheck, enable);
break;
case ID_GAME_IOS_ENABLEVERYHIGHSPEC:
SetGameSpecCheck(CONFIG_VERYHIGH_SPEC, CONFIG_IOS, nCheck, enable);
break;
#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
#define AZ_RESTRICTED_PLATFORM_EXPANSION(CodeName, CODENAME, codename, PrivateName, PRIVATENAME, privatename, PublicName, PUBLICNAME, publicname, PublicAuxName1, PublicAuxName2, PublicAuxName3)\
case ID_GAME_##CODENAME##_ENABLELOWSPEC:\
SetGameSpecCheck(CONFIG_LOW_SPEC, CONFIG_##CODENAME, nCheck, enable);\
break;\
case ID_GAME_##CODENAME##_ENABLEMEDIUMSPEC:\
SetGameSpecCheck(CONFIG_MEDIUM_SPEC, CONFIG_##CODENAME, nCheck, enable);\
break;\
case ID_GAME_##CODENAME##_ENABLEHIGHSPEC:\
SetGameSpecCheck(CONFIG_HIGH_SPEC, CONFIG_##CODENAME, nCheck, enable);\
break;
AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS
#undef AZ_RESTRICTED_PLATFORM_EXPANSION
#endif
}
action->setChecked(nCheck);
action->setEnabled(enable);
}
//////////////////////////////////////////////////////////////////////////
RecentFileList* CCryEditApp::GetRecentFileList()
{
-4
View File
@@ -403,7 +403,6 @@ private:
void OnClearRegistryData();
void OnValidatelevel();
void OnToolsPreferences();
void OnGraphicsSettings();
void OnSwitchToDefaultCamera();
void OnUpdateSwitchToDefaultCamera(QAction* action);
void OnSwitchToSequenceCamera();
@@ -416,9 +415,6 @@ private:
void OnOpenTrackView();
void OnOpenAudioControlsEditor();
void OnOpenUICanvasEditor();
void OnChangeGameSpec(UINT nID);
void SetGameSpecCheck(ESystemConfigSpec spec, ESystemConfigPlatform platform, int &nCheck, bool &enable);
void OnUpdateGameSpec(QAction* action);
void OnOpenQuickAccessBar();
public:
-72
View File
@@ -407,78 +407,6 @@ inline namespace Commands
}
}
//////////////////////////////////////////////////////////////////////////
void CCryEditApp::OnChangeGameSpec(UINT nID)
{
switch (nID)
{
case ID_GAME_PC_ENABLELOWSPEC:
Commands::PySetConfigSpec(CONFIG_LOW_SPEC, CONFIG_PC);
break;
case ID_GAME_PC_ENABLEMEDIUMSPEC:
Commands::PySetConfigSpec(CONFIG_MEDIUM_SPEC, CONFIG_PC);
break;
case ID_GAME_PC_ENABLEHIGHSPEC:
Commands::PySetConfigSpec(CONFIG_HIGH_SPEC, CONFIG_PC);
break;
case ID_GAME_PC_ENABLEVERYHIGHSPEC:
Commands::PySetConfigSpec(CONFIG_VERYHIGH_SPEC, CONFIG_PC);
break;
case ID_GAME_OSXMETAL_ENABLELOWSPEC:
Commands::PySetConfigSpec(CONFIG_LOW_SPEC, CONFIG_OSX_METAL);
break;
case ID_GAME_OSXMETAL_ENABLEMEDIUMSPEC:
Commands::PySetConfigSpec(CONFIG_MEDIUM_SPEC, CONFIG_OSX_METAL);
break;
case ID_GAME_OSXMETAL_ENABLEHIGHSPEC:
Commands::PySetConfigSpec(CONFIG_HIGH_SPEC, CONFIG_OSX_METAL);
break;
case ID_GAME_OSXMETAL_ENABLEVERYHIGHSPEC:
Commands::PySetConfigSpec(CONFIG_VERYHIGH_SPEC, CONFIG_OSX_METAL);
break;
case ID_GAME_ANDROID_ENABLELOWSPEC:
Commands::PySetConfigSpec(CONFIG_LOW_SPEC, CONFIG_ANDROID);
break;
case ID_GAME_ANDROID_ENABLEMEDIUMSPEC:
Commands::PySetConfigSpec(CONFIG_MEDIUM_SPEC, CONFIG_ANDROID);
break;
case ID_GAME_ANDROID_ENABLEHIGHSPEC:
Commands::PySetConfigSpec(CONFIG_HIGH_SPEC, CONFIG_ANDROID);
break;
case ID_GAME_ANDROID_ENABLEVERYHIGHSPEC:
Commands::PySetConfigSpec(CONFIG_VERYHIGH_SPEC, CONFIG_ANDROID);
break;
case ID_GAME_IOS_ENABLELOWSPEC:
Commands::PySetConfigSpec(CONFIG_LOW_SPEC, CONFIG_IOS);
break;
case ID_GAME_IOS_ENABLEMEDIUMSPEC:
Commands::PySetConfigSpec(CONFIG_MEDIUM_SPEC, CONFIG_IOS);
break;
case ID_GAME_IOS_ENABLEHIGHSPEC:
Commands::PySetConfigSpec(CONFIG_HIGH_SPEC, CONFIG_IOS);
break;
case ID_GAME_IOS_ENABLEVERYHIGHSPEC:
Commands::PySetConfigSpec(CONFIG_VERYHIGH_SPEC, CONFIG_IOS);
break;
#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
#define AZ_RESTRICTED_PLATFORM_EXPANSION(CodeName, CODENAME, codename, PrivateName, PRIVATENAME, privatename, PublicName, PUBLICNAME, publicname, PublicAuxName1, PublicAuxName2, PublicAuxName3)\
case ID_GAME_##CODENAME##_ENABLELOWSPEC:\
Commands::PySetConfigSpec(CONFIG_LOW_SPEC, CONFIG_##CODENAME);\
break;\
case ID_GAME_##CODENAME##_ENABLEMEDIUMSPEC:\
Commands::PySetConfigSpec(CONFIG_MEDIUM_SPEC, CONFIG_##CODENAME);\
break;\
case ID_GAME_##CODENAME##_ENABLEHIGHSPEC:\
Commands::PySetConfigSpec(CONFIG_HIGH_SPEC, CONFIG_##CODENAME);\
break;
AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS
#undef AZ_RESTRICTED_PLATFORM_EXPANSION
#endif
}
}
namespace AzToolsFramework
{
void CryEditPythonHandler::Reflect(AZ::ReflectContext* context)
+16 -28
View File
@@ -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);
-1
View File
@@ -506,7 +506,6 @@ protected:
CPredefinedAspectRatios m_predefinedAspectRatios;
IVariable* m_pCameraFOVVariable = nullptr;
bool m_bCursorHidden = false;
void OnMenuResolutionCustom();
File diff suppressed because it is too large Load Diff
-284
View File
@@ -1,284 +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>
#include <QTreeView>
#include <QStandardItemModel>
#include <QHeaderView>
#include <AzQtComponents/Components/Widgets/SpinBox.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/any.h>
#include <ISystem.h>
#endif
class QGridLayout;
class QLabel;
namespace Ui
{
class GraphicsSettingsDialog;
}
// Description:
// Status of cvar for a specifc platform and spec level
// editedValue - current setting within Graphics Settings Dialog box
// overwrittenValue - original setting from platform config file (set to originalValue if not found)
// originalValue - original settings from sys_spec config file index
struct CVarFileStatus
{
AZStd::any editedValue;
AZStd::any overwrittenValue;
AZStd::any originalValue;
CVarFileStatus(AZStd::any edit, AZStd::any over, AZStd::any orig) : editedValue(edit), overwrittenValue(over), originalValue(orig) {}
};
// Description:
// Status of specific cvar for Editor mapping
// type - CVAR_INT / CVAR_FLOAT / CVAR_STRING
// cvarGroup - source of cvar (sys_spec_particles, sys_spec_physics, etc.) or "miscellaneous" if only specified in platform config file
// fileVals = CVarFileStatus for each spec level of a specific platform
struct CVarInfo
{
int type;
AZStd::string cvarGroup;
AZStd::vector<CVarFileStatus> fileVals;
};
enum class GraphicsSettings
{
GameEffects,
Light,
ObjectDetail,
Particles,
Physics,
PostProcessing,
Quality,
Shading,
Shadows,
Sound,
Texture,
TextureResolution,
VolumetricEffects,
Water,
Miscellaneous,
numSettings
};
class GraphicsSettingsHeaderView;
class GraphicsSettingsTreeView
: public QTreeView
{
Q_OBJECT
public:
GraphicsSettingsTreeView(QWidget* parent = nullptr);
};
class GraphicsSettingsModel
: public QStandardItemModel
{
Q_OBJECT
public:
explicit GraphicsSettingsModel(QObject* parent = 0);
Qt::ItemFlags flags(const QModelIndex& index) const override;
};
class GraphicsSettingsDialog
: public QDialog,
public ILoadConfigurationEntrySink
{
Q_OBJECT
public:
explicit GraphicsSettingsDialog(QWidget* parent = nullptr);
virtual ~GraphicsSettingsDialog();
bool IsCustom(void) { return m_showCustomSpec; }
void UnloadCustomSpec(int specLevel);
// ILoadConfigurationEntrySink
void OnLoadConfigurationEntry(const char* szKey, const char* szValue, const char* szGroup) override;
public slots:
//Accept and reject
void reject() override;
void accept() override;
private slots:
//Update UIs
void PlatformChanged(const QString& platform);
bool CVarChanged(AZStd::any val, const char* cvarName, int specLevel);
void CVarChanged(int i);
void CVarChanged(double d);
void CVarChanged(const QString& s);
private:
// The struct ParameterWidget is used to store the parameter widget
// m_parameterName will be the name of the parameter the widget represent.
struct ParameterWidget
{
ParameterWidget(QWidget* widget, QString parameterName = "");
QString GetToolTip() const;
const char* PARAMETER_TOOLTIP = "The variable will update render parameter \"%1\".";
QWidget* m_widget;
QString m_parameterName;
};
struct CollapseGroup
{
QString m_groupName;
QStandardItem* m_groupRow;
QTreeView* m_treeView;
bool m_isCollapsed;
CollapseGroup(QTreeView* treeView);
void ToggleCollapsed();
};
void OpenCustomSpecDialog();
void ApplyCustomSpec(const QString& customFilePath);
bool IsCustomSpecAlreadyLoaded(const AZStd::string& filename) const;
void SetSettingsTree(int numColumns);
void SetCollapsed(const QModelIndex& index, bool flag);
enum CVarStateComparison
{
EDITED_OVERWRITTEN_COMPARE = 1,
EDITED_ORIGINAL_COMPARE = 2,
OVERWRITTEN_ORIGINAL_COMPARE = 3,
END_CVARSTATE_COMPARE,
};
bool CheckCVarStatesForDiff(AZStd::pair<AZStd::string, CVarInfo>* it, int cfgFileIndex, CVarStateComparison cmp);
// Save out settings into project-level cfg files
void SaveSystemSettings();
// Load in project-level cfg files for current platform
void LoadPlatformConfigurations();
// Build UI column for spec level of current platform
void BuildColumn(int specLevel);
// Initial UI building
void BuildUI();
// Cleaning out UI before loading new platform information
void CleanUI();
// Shows/hides custom spec option
void ShowCustomSpecOption(bool show);
// Shows/hides category labels and dropdowns
void ShowCategories(bool show);
// Warns about unsaved changes (returns true if accepted)
bool SendUnsavedChangesWarning(bool cancel);
void LoadCVarGroupDirectory(const AZStd::string& path);
/////////////////////////////////////////////
// UI help functions
// Setup collapsed buttons
void SetCollapsedLayout(const QString& groupName, QStandardItem* groupItem);
// Sets the platform entry index for the given platform
void SetPlatformEntry(ESystemConfigPlatform platform);
// Gets the platform enum given the platform name
ESystemConfigPlatform GetConfigPlatformFromName(const AZStd::string& platformName);
////////////////////////////////////////////
// Members
// Qt values
const int INPUT_MIN_WIDTH = 100;
const int INPUT_MIN_HEIGHT = 20;
const int INPUT_ROW_SPAN = 1;
const int INPUT_COLUMN_SPAN = 1;
const int CVAR_ROW_OFFSET = 2;
const int CVAR_VALUE_COLUMN_OFFSET = 1;
const int PLATFORM_LABEL_ROW = 1;
const int CVAR_LABEL_COLUMN = 1;
// Tool tips
const QString SETTINGS_FILE_PATH = "Config/spec/";
const char* CFG_FILEFILTER = "Cfg File(*.cfg);;All files(*)";
const int m_numSpecLevels = 4;
bool m_showCustomSpec;
bool m_showCategories;
GraphicsSettingsModel* m_graphicsSettingsModel;
GraphicsSettingsHeaderView* m_headerView;
int m_numColumns{ 0 };
const char* m_cvarGroupsFolder = "Config/CVarGroups";
QScopedPointer<Ui::GraphicsSettingsDialog> m_ui;
QVector<CollapseGroup*> m_uiCollapseGroup;
QVector<ParameterWidget*> m_parameterWidgets;
AZStd::string m_currentConfigFilename;
size_t m_currentSpecIndex;
// cvar name --> pair(type, CVarStatus for each file)
AZStd::unordered_map<AZStd::string, CVarInfo> m_cVarTracker;
AZStd::unordered_map<ESystemConfigPlatform, AZStd::vector<AZStd::string> > m_cfgFiles;
AZStd::vector<AZStd::pair<AZStd::string, ESystemConfigPlatform> > m_platformStrings;
struct CVarGroupInfo
{
QVector<QLabel*> m_platformLabels;
QVector<QLabel*> m_cvarLabels;
QVector<AzQtComponents::SpinBox*> m_cvarSpinBoxes;
QVector<AzQtComponents::DoubleSpinBox*> m_cvarDoubleSpinBoxes;
QVector<QLineEdit*> m_cvarLineEdits;
QVector<QToolButton*> m_specFileArea;
QVector<QWidget*> m_widgetInsertOrder;
QStandardItem* m_treeRowItem;
int m_currentRow;
};
AZStd::unordered_map<AZStd::string, CVarGroupInfo> m_cvarGroupData;
AZStd::vector<AZStd::string> m_cvarGroupOrder;
ESystemConfigPlatform m_currentPlatform;
int m_dirtyCVarCount;
};
class GraphicsSettingsHeaderView
: public QHeaderView
{
Q_OBJECT
public:
GraphicsSettingsHeaderView(GraphicsSettingsDialog* dialog, Qt::Orientation orientation, QWidget* parent = nullptr);
private:
bool event(QEvent* e) override;
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
GraphicsSettingsDialog* m_dialog;
int m_index{ -1 };
};
+13 -44
View File
@@ -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);
}
@@ -674,49 +687,6 @@ void MainWindow::InitActions()
am->AddAction(ID_FILE_PROJECT_MANAGER_SETTINGS, tr("Edit Project Settings..."));
am->AddAction(ID_FILE_PROJECT_MANAGER_NEW, tr("New Project..."));
am->AddAction(ID_FILE_PROJECT_MANAGER_OPEN, tr("Open Project..."));
am->AddAction(ID_GAME_PC_ENABLEVERYHIGHSPEC, tr("Very High")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_PC_ENABLEHIGHSPEC, tr("High")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_PC_ENABLEMEDIUMSPEC, tr("Medium")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_PC_ENABLELOWSPEC, tr("Low")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_OSXMETAL_ENABLEVERYHIGHSPEC, tr("Very High")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_OSXMETAL_ENABLEHIGHSPEC, tr("High")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_OSXMETAL_ENABLEMEDIUMSPEC, tr("Medium")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_OSXMETAL_ENABLELOWSPEC, tr("Low")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_ANDROID_ENABLEVERYHIGHSPEC, tr("Very High")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_ANDROID_ENABLEHIGHSPEC, tr("High")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_ANDROID_ENABLEMEDIUMSPEC, tr("Medium")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_ANDROID_ENABLELOWSPEC, tr("Low")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_IOS_ENABLEVERYHIGHSPEC, tr("Very High")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_IOS_ENABLEHIGHSPEC, tr("High")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_IOS_ENABLEMEDIUMSPEC, tr("Medium")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_IOS_ENABLELOWSPEC, tr("Low")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
#if defined(TOOLS_SUPPORT_JASPER)
#include AZ_RESTRICTED_FILE_EXPLICIT(MainWindow_cpp, jasper)
#endif
#if defined(TOOLS_SUPPORT_PROVO)
#include AZ_RESTRICTED_FILE_EXPLICIT(MainWindow_cpp, provo)
#endif
#if defined(TOOLS_SUPPORT_SALEM)
#include AZ_RESTRICTED_FILE_EXPLICIT(MainWindow_cpp, salem)
#endif
#endif
am->AddAction(ID_TOOLS_CUSTOMIZEKEYBOARD, tr("Customize &Keyboard..."))
.Connect(&QAction::triggered, this, &MainWindow::ShowKeyboardCustomization);
am->AddAction(ID_TOOLS_EXPORT_SHORTCUTS, tr("&Export Keyboard Settings..."))
@@ -724,7 +694,6 @@ void MainWindow::InitActions()
am->AddAction(ID_TOOLS_IMPORT_SHORTCUTS, tr("&Import Keyboard Settings..."))
.Connect(&QAction::triggered, this, &MainWindow::ImportKeyboardShortcuts);
am->AddAction(ID_TOOLS_PREFERENCES, tr("Global Preferences..."));
am->AddAction(ID_GRAPHICS_SETTINGS, tr("&Graphics Settings..."));
for (int i = ID_FILE_MRU_FIRST; i <= ID_FILE_MRU_LAST; ++i)
{
+1
View File
@@ -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
@@ -66,3 +66,5 @@ namespace EntityOutliner
emit OnOptionToggled(DisplayOption::AutoExpand, checked);
}
}
#include <UI/Outliner/moc_OutlinerDisplayOptionsMenu.cpp>
@@ -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
+14
View File
@@ -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();
}
+7 -2
View File
@@ -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
};
-26
View File
@@ -187,7 +187,6 @@
#define ID_SWITCHCAMERA_SEQUENCECAMERA 33701
#define ID_SWITCHCAMERA_SELECTEDCAMERA 33702
#define ID_TV_RECORD_AUTO 33703
#define ID_GRAPHICS_SETTINGS 33705
#define ID_VIEW_OPENVIEWPANE 33709
#define ID_VIEW_OPENPANE_FIRST 33712
#define ID_VIEW_OPENPANE_LAST 33811
@@ -219,10 +218,6 @@
#define ID_SPLINE_SNAP_GRID_X 33933
#define ID_SPLINE_SNAP_GRID_Y 33934
#define ID_FREEZE_TANGENTS 33935
#define ID_GAME_PC_ENABLELOWSPEC 33960
#define ID_GAME_PC_ENABLEMEDIUMSPEC 33961
#define ID_GAME_PC_ENABLEHIGHSPEC 33962
#define ID_GAME_PC_ENABLEVERYHIGHSPEC 33963
#define ID_PANEL_VEG_CREATE_SEL 33990
#define ID_TOOLS_UPDATEPROCEDURALVEGETATION 33999
#define ID_DISPLAY_GOTOPOSITION 34004
@@ -287,14 +282,6 @@
#define ID_CLEAR_REGISTRY 34470
#define ID_SOUND_STOPALLSOUNDS 34476
#define ID_AUDIO_REFRESH_AUDIO_SYSTEM 34477
#define ID_GAME_ANDROID_ENABLELOWSPEC 34490
#define ID_GAME_ANDROID_ENABLEMEDIUMSPEC 34491
#define ID_GAME_ANDROID_ENABLEHIGHSPEC 34492
#define ID_GAME_ANDROID_ENABLEVERYHIGHSPEC 34493
#define ID_GAME_IOS_ENABLELOWSPEC 34494
#define ID_GAME_IOS_ENABLEMEDIUMSPEC 34495
#define ID_GAME_IOS_ENABLEHIGHSPEC 34496
#define ID_GAME_IOS_ENABLEVERYHIGHSPEC 34497
#define ID_OPEN_AUDIO_CONTROLS_BROWSER 34580
#define ID_CREATE_GLOBAL_FG_MODULE_FROM_SELECTION 35076
#define ID_CREATE_LEVEL_FG_MODULE_FROM_SELECTION 35077
@@ -324,19 +311,6 @@
#define ID_DOCUMENTATION_FEEDBACK 36043
#define ID_OPEN_SUBSTANCE_EDITOR 36060
#define ID_IMPORT_ASSET 36069
#define ID_GAME_PROVO_ENABLELOWSPEC 34603
#define ID_GAME_PROVO_ENABLEMEDIUMSPEC 34604
#define ID_GAME_PROVO_ENABLEHIGHSPEC 34605
#define ID_GAME_OSXMETAL_ENABLELOWSPEC 34606
#define ID_GAME_OSXMETAL_ENABLEMEDIUMSPEC 34607
#define ID_GAME_OSXMETAL_ENABLEHIGHSPEC 34608
#define ID_GAME_OSXMETAL_ENABLEVERYHIGHSPEC 34609
#define ID_GAME_SALEM_ENABLELOWSPEC 34610
#define ID_GAME_SALEM_ENABLEMEDIUMSPEC 34611
#define ID_GAME_SALEM_ENABLEHIGHSPEC 34612
#define ID_GAME_JASPER_ENABLELOWSPEC 34613
#define ID_GAME_JASPER_ENABLEMEDIUMSPEC 34614
#define ID_GAME_JASPER_ENABLEHIGHSPEC 34615
#define ID_FILE_RESAVESLICES 36210
#define FIRST_QT_ACTION 50000
#define ID_VIEW_CONSOLEWINDOW 50001
@@ -1,25 +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
*
*/
#GraphicsSettingsDialog QHeaderView::section
{
background: #2D2D2D;
}
#GraphicsSettingsDialog QHeaderView::down-arrow
{
width: 14px;
height: 14px;
image: url(:/Gallery/Delete.svg);
}
#GraphicsSettingsDialog QHeaderView::up-arrow
{
width: 14px;
height: 14px;
image: url(:/Gallery/Delete.svg);
}
-1
View File
@@ -3,6 +3,5 @@
<file alias="Assets/Editor/Style/Editor.qss">Editor.qss</file>
<file alias="Assets/Editor/Style/EditorPreferencesDialog.qss">EditorPreferencesDialog.qss</file>
<file alias="Assets/Editor/Style/LayoutConfigDialog.qss">LayoutConfigDialog.qss</file>
<file alias="Assets/Editor/Style/GraphicsSettingsDialog.qss">GraphicsSettingsDialog.qss</file>
</qresource>
</RCC>
@@ -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();
};
-3
View File
@@ -583,9 +583,6 @@ set(FILES
SettingsManager.h
SettingsManagerDialog.h
SettingsManagerDialog.ui
GraphicsSettingsDialog.h
GraphicsSettingsDialog.cpp
graphicssettingsdialog.ui
AboutDialog.cpp
ErrorReportTableModel.h
ErrorReportTableModel.cpp
-270
View File
@@ -1,270 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GraphicsSettingsDialog</class>
<widget class="QDialog" name="GraphicsSettingsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1292</width>
<height>565</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>800</width>
<height>400</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="windowTitle">
<string>Graphics Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QGridLayout" name="m_generalLayout">
<property name="horizontalSpacing">
<number>0</number>
</property>
<property name="verticalSpacing">
<number>6</number>
</property>
<item row="2" column="3">
<widget class="QWidget" name="m_platform" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>20</height>
</size>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<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="QComboBox" name="m_platformEntry"/>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="m_selectCustomSpecButton">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>Add Resource</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="m_platformLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>60</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>Platform</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="Line" name="m_lineSpacer">
<property name="minimumSize">
<size>
<width>13</width>
<height>0</height>
</size>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QScrollArea" name="m_scrollArea">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="m_scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1272</width>
<height>452</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="GraphicsSettingsTreeView" name="m_graphicsSettingsTreeView">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="indentation">
<number>8</number>
</property>
<attribute name="headerStretchLastSection">
<bool>false</bool>
</attribute>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="m_horizontalLayout">
<item>
<spacer name="m_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="QPushButton" name="m_applyButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">background-color: rgb(233, 118, 17);</string>
</property>
<property name="text">
<string>Save</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="m_cancelButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
<zorder>line</zorder>
<zorder>m_scrollArea</zorder>
<zorder>line_2</zorder>
<zorder>widget</zorder>
</widget>
<customwidgets>
<customwidget>
<class>GraphicsSettingsTreeView</class>
<extends>QTreeView</extends>
<header>GraphicsSettingsDialog.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>m_cancelButton</tabstop>
<tabstop>m_applyButton</tabstop>
<tabstop>m_scrollArea</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>
+18 -5
View File
@@ -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
@@ -41,7 +41,7 @@ namespace AzNetworking
void TcpSocketManager::ProcessEvents(AZ::TimeMs maxBlockMs, const SocketEventCallback& readCallback, const SocketEventCallback& writeCallback)
{
if(static_cast<int32_t>(m_maxFd) <= 0 && m_socketFds.empty())
if(static_cast<int32_t>(m_maxFd) <= 0 || m_socketFds.empty())
{
// There are no available sockets to process
return;
@@ -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
@@ -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*/)
@@ -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
@@ -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);
@@ -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;
@@ -22,11 +22,11 @@ namespace AzToolsFramework
/// @name Reverse URLs.
/// Used to identify common actions and override them when necessary.
//@{
static const AZ::Crc32 s_backAction = AZ_CRC("com.amazon.action.common.back", 0xd772a2af);
static const AZ::Crc32 s_deleteAction = AZ_CRC("com.amazon.action.common.delete", 0x5731f6cb);
static const AZ::Crc32 s_duplicateAction = AZ_CRC("com.amazon.action.common.duplicate", 0x08ccf461);
static const AZ::Crc32 s_nextComponentMode = AZ_CRC("com.amazon.action.common.nextComponentMode", 0xcc26094f);
static const AZ::Crc32 s_previousComponentMode = AZ_CRC("com.amazon.action.common.previousComponentMode", 0x0d18ff39);
static const AZ::Crc32 s_backAction = AZ_CRC("com.o3de.action.common.back", 0xd772a2af);
static const AZ::Crc32 s_deleteAction = AZ_CRC("com.o3de.action.common.delete", 0x5731f6cb);
static const AZ::Crc32 s_duplicateAction = AZ_CRC("com.o3de.action.common.duplicate", 0x08ccf461);
static const AZ::Crc32 s_nextComponentMode = AZ_CRC("com.o3de.action.common.nextComponentMode", 0xcc26094f);
static const AZ::Crc32 s_previousComponentMode = AZ_CRC("com.o3de.action.common.previousComponentMode", 0x0d18ff39);
//@}
/// Specific Action properties to be sent to a type implementing
@@ -98,7 +98,7 @@ namespace AzToolsFramework
{
}
AZ::Crc32 m_uri; //!< Unique identifier for the Action. (In the form 'com.amazon.action.---").
AZ::Crc32 m_uri; //!< Unique identifier for the Action. (In the form 'com.o3de.action.---").
AZStd::vector<AZStd::function<void()>> m_callbacks; //!< Callbacks associated with this Action (note: with multi-selections
//!< there will be a callback per Entity/Component).
AZStd::unique_ptr<QAction> m_action; //!< The QAction associated with the overrideWidget for all ComponentMode actions.
@@ -196,7 +196,7 @@ namespace AzToolsFramework
AZStd::vector<AzToolsFramework::ActionOverride> PlaceHolderComponentMode::PopulateActionsImpl()
{
const AZ::Crc32 placeHolderComponentModeAction = AZ_CRC_CE("com.amazon.action.placeholder.test");
const AZ::Crc32 placeHolderComponentModeAction = AZ_CRC_CE("com.o3de.action.placeholder.test");
return AZStd::vector<AzToolsFramework::ActionOverride>
{
@@ -25,6 +25,8 @@ namespace AWSNativeSDKInit
#if defined(PLATFORM_SUPPORTS_AWS_NATIVE_SDK)
void CustomizeSDKOptions(Aws::SDKOptions& options);
void CustomizeShutdown();
void CopyCaCertBundle();
#endif
}
@@ -44,6 +46,8 @@ namespace AWSNativeSDKInit
void InitializationManager::InitAwsApi()
{
s_initManager = AZ::Environment::CreateVariable<InitializationManager>(initializationManagerTag);
Platform::CopyCaCertBundle();
}
void InitializationManager::Shutdown()
@@ -0,0 +1,89 @@
/*
* 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>
// The AWS Native SDK AWSAllocator triggers a warning due to accessing members of std::allocator directly.
// AWSAllocator.h(70): warning C4996: 'std::allocator<T>::pointer': warning STL4010: Various members of std::allocator are deprecated in
// C++17. Use std::allocator_traits instead of accessing these members directly. You can define
// _SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received
// this warning.
AZ_PUSH_DISABLE_WARNING(4251 4996, "-Wunknown-warning-option")
#include <aws/core/utils/memory/stl/AWSString.h>
AZ_POP_DISABLE_WARNING
#include <AzCore/Android/Utils.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/std/containers/vector.h>
namespace AWSNativeSDKInit
{
namespace Platform
{
void CopyCaCertBundle()
{
AZStd::vector<char> contents;
AZStd::string certificatePath = "@assets@/certificates/aws/cacert.pem";
AZStd::string publicStoragePath = AZ::Android::Utils::GetAppPublicStoragePath();
publicStoragePath.append("/certificates/aws/cacert.pem");
AZ::IO::FileIOBase* fileBase = AZ::IO::FileIOBase::GetInstance();
if (!fileBase->Exists(certificatePath.c_str()))
{
AZ_Error("AWSNativeSDKInit", false, "Certificate File(%s) does not exist.\n", certificatePath.c_str());
}
AZ::IO::HandleType fileHandle;
AZ::IO::Result fileResult = fileBase->Open(certificatePath.c_str(), AZ::IO::OpenMode::ModeRead, fileHandle);
if (!fileResult)
{
AZ_Error("AWSNativeSDKInit", false, "Failed to open certificate file with result %i\n", fileResult.GetResultCode());
}
AZ::u64 fileSize = 0;
fileBase->Size(fileHandle, fileSize);
if (fileSize == 0)
{
AZ_Error("AWSNativeSDKInit", false, "Given empty file(%s) as the certificate bundle.\n", certificatePath.c_str());
}
contents.resize(fileSize + 1);
fileResult = fileBase->Read(fileHandle, contents.data(), fileSize);
if (!fileResult)
{
AZ_Error(
"AWSNativeSDKInit", false, "Failed to read from the certificate bundle(%s) with result code(%i).\n", certificatePath.c_str(),
fileResult.GetResultCode());
}
AZ_Printf("AWSNativeSDKInit", "Certificate bundle is read successfully from %s", certificatePath.c_str());
AZ::IO::HandleType outFileHandle;
AZ::IO::Result outFileResult = fileBase->Open(publicStoragePath.c_str(), AZ::IO::OpenMode::ModeWrite, outFileHandle);
if (!outFileResult)
{
AZ_Error("AWSNativeSDKInit", false, "Failed to open the certificate bundle with result %i\n", fileResult.GetResultCode());
}
AZ::IO::Result writeFileResult = fileBase->Write(outFileHandle, contents.data(), fileSize);
if (!writeFileResult)
{
AZ_Error("AWSNativeSDKInit", false, "Failed to write the certificate bundle with result %i\n", writeFileResult.GetResultCode());
}
fileBase->Close(fileHandle);
fileBase->Close(outFileHandle);
AZ_Printf("AWSNativeSDKInit", "Certificate bundle successfully copied to %s", publicStoragePath.c_str());
}
} // namespace Platform
}
@@ -7,4 +7,5 @@
set(FILES
../Common/Default/AWSNativeSDKInit_Default.cpp
InitializeCerts_Android.cpp
)
@@ -1,18 +1,16 @@
/*
* 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
/*
* 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
*
*/
namespace AWSNativeSDKInit
{
namespace Platform
{
void CopyCaCertBundle()
{
}
} // namespace Platform
} // namespace AWSCore
@@ -7,4 +7,5 @@
set(FILES
../Common/Default/AWSNativeSDKInit_Default.cpp
../Common/Default/InitializeCerts_Null.cpp
)
@@ -7,4 +7,5 @@
set(FILES
../Common/Default/AWSNativeSDKInit_Default.cpp
../Common/Default/InitializeCerts_Null.cpp
)
@@ -7,4 +7,5 @@
set(FILES
../Common/Default/AWSNativeSDKInit_Default.cpp
../Common/Default/InitializeCerts_Null.cpp
)
@@ -7,4 +7,5 @@
set(FILES
../Common/Default/AWSNativeSDKInit_Default.cpp
../Common/Default/InitializeCerts_Null.cpp
)
@@ -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
-1
View File
@@ -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)
-31
View File
@@ -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,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>
-102
View File
@@ -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();
}
}
}

Some files were not shown because too many files have changed in this diff Show More