PropertyImagePreview.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include "PropertyImagePreview.h"
  9. #include "DefaultImageValidator.h"
  10. #include "PlatformSettings_common.h"
  11. #include "Utils.h"
  12. #include "ValidationHandler.h"
  13. #include "ValidatorBus.h"
  14. #include <QBoxLayout>
  15. #include <QDir>
  16. #include <QLineEdit>
  17. namespace ProjectSettingsTool
  18. {
  19. // Max width/length of preview in pixels
  20. static const int maxPreviewDim = 96;
  21. PropertyImagePreviewCtrl::PropertyImagePreviewCtrl(QWidget* parent)
  22. : PropertyFuncValBrowseEditCtrl(parent)
  23. , m_defaultImagePreview(nullptr)
  24. , m_defaultPath("")
  25. {
  26. QLayout* myLayout = layout();
  27. QBoxLayout* boxLayout = qobject_cast<QBoxLayout*>(myLayout);
  28. m_preview = new QLabel(this);
  29. m_preview->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
  30. m_preview->setFixedSize(QSize(maxPreviewDim, maxPreviewDim));
  31. if (boxLayout != nullptr)
  32. {
  33. boxLayout->insertWidget(0, m_preview);
  34. }
  35. else
  36. {
  37. AZ_Assert(false, "Expected QBoxLayout type not found in lineedit control.");
  38. myLayout->addWidget(m_preview);
  39. }
  40. connect(this->m_browseEdit, &AzQtComponents::BrowseEdit::attachedButtonTriggered, this, [this]()
  41. {
  42. QString path = SelectImageFromFileDialog(browseEdit()->text());
  43. if (!path.isEmpty())
  44. {
  45. SetValueUser(path);
  46. }
  47. });
  48. connect(browseEdit(), &AzQtComponents::BrowseEdit::textChanged, this, &PropertyImagePreviewCtrl::LoadPreview);
  49. }
  50. void PropertyImagePreviewCtrl::SetValue(const QString& path)
  51. {
  52. browseEdit()->setText(path);
  53. // Preview will not be shown if path is set to empty because it has not changed so call it here
  54. LoadPreview();
  55. }
  56. const QString& PropertyImagePreviewCtrl::DefaultImagePath() const
  57. {
  58. return m_defaultPath;
  59. }
  60. void PropertyImagePreviewCtrl::SetDefaultImagePath(const QString& newPath)
  61. {
  62. m_defaultPath = newPath;
  63. }
  64. void PropertyImagePreviewCtrl::SetDefaultImagePreview(PropertyImagePreviewCtrl* imageSelect)
  65. {
  66. if (m_defaultImagePreview == nullptr)
  67. {
  68. m_defaultImagePreview = imageSelect;
  69. connect(imageSelect, &PropertyFuncValBrowseEditCtrl::ValueChangedByUser, this, &PropertyImagePreviewCtrl::LoadPreview);
  70. }
  71. else
  72. {
  73. AZ_Assert(false, "Default image preview already set.");
  74. }
  75. }
  76. PropertyImagePreviewCtrl* PropertyImagePreviewCtrl::DefaultImagePreview() const
  77. {
  78. return m_defaultImagePreview;
  79. }
  80. void PropertyImagePreviewCtrl::AddOverrideToValidator(PropertyImagePreviewCtrl* preview)
  81. {
  82. qobject_cast<DefaultImageValidator*>(m_validator)->AddOverride(preview);
  83. connect(browseEdit(), &AzQtComponents::BrowseEdit::textChanged, this, &PropertyImagePreviewCtrl::ForceValidate);
  84. }
  85. void PropertyImagePreviewCtrl::LoadPreview()
  86. {
  87. QString currentPath = browseEdit()->text();
  88. const QString* imagePath = nullptr;
  89. if (!currentPath.isEmpty())
  90. {
  91. imagePath = &currentPath;
  92. }
  93. else
  94. {
  95. if (m_defaultImagePreview != nullptr)
  96. {
  97. currentPath = browseEdit()->text();
  98. }
  99. if (!currentPath.isEmpty())
  100. {
  101. imagePath = &currentPath;
  102. }
  103. else
  104. {
  105. imagePath = &m_defaultPath;
  106. }
  107. }
  108. QDir dirPath(*imagePath);
  109. // Keeps image from showing when no extension is given
  110. if (!imagePath->isEmpty() && dirPath.isReadable())
  111. {
  112. // Image loaded from file
  113. QImage originalImage;
  114. // Scaled image
  115. QImage processedImage;
  116. // The image to be displayed
  117. QImage* finalImage;
  118. bool validImage = originalImage.load(*imagePath);
  119. if (validImage)
  120. {
  121. //Scale down any images larger than 128 on either dimension
  122. if (originalImage.height() > maxPreviewDim || originalImage.width() > maxPreviewDim)
  123. {
  124. processedImage = originalImage.scaled(maxPreviewDim, maxPreviewDim,
  125. Qt::KeepAspectRatio, Qt::SmoothTransformation);
  126. finalImage = &processedImage;
  127. }
  128. else
  129. {
  130. finalImage = &originalImage;
  131. }
  132. m_preview->setPixmap(QPixmap::fromImage(*finalImage));
  133. }
  134. // Failed to load image so set the preview to nothing
  135. else
  136. {
  137. m_preview->setPixmap(QPixmap());
  138. }
  139. }
  140. // Nothing valid set preview to nothing
  141. else
  142. {
  143. m_preview->setPixmap(QPixmap());
  144. }
  145. }
  146. void PropertyImagePreviewCtrl::UpgradeToDefaultValidator()
  147. {
  148. DefaultImageValidator* newValidator = new DefaultImageValidator(*m_validator);
  149. SetValidator(newValidator);
  150. // Track the memory allocated for this validator so its deleted
  151. ValidatorBus::Broadcast(
  152. &ValidatorBus::Handler::TrackValidator,
  153. newValidator);
  154. }
  155. void PropertyImagePreviewCtrl::ConsumeAttribute(AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName)
  156. {
  157. if (attrib == Attributes::DefaultPath)
  158. {
  159. AZStd::string path;
  160. if (attrValue->Read<AZStd::string>(path))
  161. {
  162. m_defaultPath = path.data();
  163. }
  164. }
  165. else
  166. {
  167. PropertyFuncValBrowseEditCtrl::ConsumeAttribute(attrib, attrValue, debugName);
  168. }
  169. }
  170. // Handler ///////////////////////////////////////////////////////////////////
  171. PropertyImagePreviewHandler::PropertyImagePreviewHandler(ValidationHandler* valHdlr)
  172. : AzToolsFramework::PropertyHandler<AZStd::string, PropertyImagePreviewCtrl>()
  173. , m_validationHandler(valHdlr)
  174. {}
  175. AZ::u32 PropertyImagePreviewHandler::GetHandlerName(void) const
  176. {
  177. return Handlers::ImagePreview;
  178. }
  179. QWidget* PropertyImagePreviewHandler::CreateGUI(QWidget* pParent)
  180. {
  181. PropertyImagePreviewCtrl* ctrl = aznew PropertyImagePreviewCtrl(pParent);
  182. m_validationHandler->AddValidatorCtrl(ctrl);
  183. return ctrl;
  184. }
  185. void PropertyImagePreviewHandler::ConsumeAttribute(PropertyImagePreviewCtrl* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName)
  186. {
  187. //This means we are using this as a default image preview
  188. if (attrib == Attributes::PropertyIdentfier)
  189. {
  190. AZStd::string ident;
  191. if (attrValue->Read<AZStd::string>(ident))
  192. {
  193. GUI->UpgradeToDefaultValidator();
  194. m_identToCtrl.insert(AZStd::pair<AZStd::string, PropertyImagePreviewCtrl*>(ident, GUI));
  195. }
  196. }
  197. else if (attrib == Attributes::DefaultImagePreview)
  198. {
  199. AZStd::string ident;
  200. if (attrValue->Read<AZStd::string>(ident))
  201. {
  202. auto defaultPreview = m_identToCtrl.find(ident);
  203. if (defaultPreview != m_identToCtrl.end())
  204. {
  205. defaultPreview->second->AddOverrideToValidator(GUI);
  206. GUI->SetDefaultImagePreview(defaultPreview->second);
  207. }
  208. else
  209. {
  210. AZ_Assert(false, "Default image select \"%s\" not found.", ident.data());
  211. }
  212. }
  213. }
  214. else
  215. {
  216. GUI->ConsumeAttribute(attrib, attrValue, debugName);
  217. }
  218. }
  219. void PropertyImagePreviewHandler::WriteGUIValuesIntoProperty([[maybe_unused]] size_t index, PropertyImagePreviewCtrl* GUI, property_t& instance, [[maybe_unused]] AzToolsFramework::InstanceDataNode* node)
  220. {
  221. instance = GUI->GetValue().toUtf8().data();
  222. }
  223. bool PropertyImagePreviewHandler::ReadValuesIntoGUI([[maybe_unused]] size_t index, PropertyImagePreviewCtrl* GUI, const property_t& instance, [[maybe_unused]] AzToolsFramework::InstanceDataNode* node)
  224. {
  225. GUI->SetValue(instance.data());
  226. GUI->ForceValidate();
  227. return true;
  228. }
  229. PropertyImagePreviewHandler* PropertyImagePreviewHandler::Register(ValidationHandler* valHdlr)
  230. {
  231. PropertyImagePreviewHandler* handler = aznew PropertyImagePreviewHandler(valHdlr);
  232. AzToolsFramework::PropertyTypeRegistrationMessages::Bus::Broadcast(
  233. &AzToolsFramework::PropertyTypeRegistrationMessages::Bus::Handler::RegisterPropertyType,
  234. handler);
  235. return handler;
  236. }
  237. } // namespace ProjectSettingsTool
  238. #include <moc_PropertyImagePreview.cpp>