Added addressLabelType to HexViewerWidgetSettings
This commit is contained in:
@@ -6,7 +6,7 @@ namespace Bloom
|
|||||||
const Targets::TargetMemoryDescriptor& memoryDescriptor,
|
const Targets::TargetMemoryDescriptor& memoryDescriptor,
|
||||||
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
|
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
|
||||||
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
|
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
|
||||||
const Widgets::HexViewerWidgetSettings& settings,
|
Widgets::HexViewerWidgetSettings& settings,
|
||||||
Widgets::Label* hoveredAddressLabel
|
Widgets::Label* hoveredAddressLabel
|
||||||
)
|
)
|
||||||
: memoryDescriptor(memoryDescriptor)
|
: memoryDescriptor(memoryDescriptor)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace Bloom
|
|||||||
const Targets::TargetMemoryDescriptor& memoryDescriptor,
|
const Targets::TargetMemoryDescriptor& memoryDescriptor,
|
||||||
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
|
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
|
||||||
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
|
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
|
||||||
const Widgets::HexViewerWidgetSettings& settings,
|
Widgets::HexViewerWidgetSettings& settings,
|
||||||
Widgets::Label* hoveredAddressLabel
|
Widgets::Label* hoveredAddressLabel
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ namespace Bloom
|
|||||||
const Targets::TargetMemoryDescriptor& memoryDescriptor;
|
const Targets::TargetMemoryDescriptor& memoryDescriptor;
|
||||||
std::vector<FocusedMemoryRegion>& focusedMemoryRegions;
|
std::vector<FocusedMemoryRegion>& focusedMemoryRegions;
|
||||||
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions;
|
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions;
|
||||||
const Widgets::HexViewerWidgetSettings& settings;
|
Widgets::HexViewerWidgetSettings& settings;
|
||||||
Widgets::Label* hoveredAddressLabel;
|
Widgets::Label* hoveredAddressLabel;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
namespace Bloom::Widgets
|
namespace Bloom::Widgets
|
||||||
{
|
{
|
||||||
|
ByteAddressContainer::ByteAddressContainer(const HexViewerWidgetSettings& settings)
|
||||||
|
: settings(settings)
|
||||||
|
{}
|
||||||
|
|
||||||
void ByteAddressContainer::adjustAddressLabels(
|
void ByteAddressContainer::adjustAddressLabels(
|
||||||
const std::map<std::size_t, std::vector<ByteItem*>>& byteItemsByRowIndex
|
const std::map<std::size_t, std::vector<ByteItem*>>& byteItemsByRowIndex
|
||||||
) {
|
) {
|
||||||
@@ -15,7 +19,7 @@ namespace Bloom::Widgets
|
|||||||
|
|
||||||
ByteAddressItem* addressLabel = nullptr;
|
ByteAddressItem* addressLabel = nullptr;
|
||||||
if (static_cast<int>(rowIndex) > layoutItemMaxIndex) {
|
if (static_cast<int>(rowIndex) > layoutItemMaxIndex) {
|
||||||
addressLabel = new ByteAddressItem(rowIndex, byteItemsByRowIndex, this);
|
addressLabel = new ByteAddressItem(rowIndex, byteItemsByRowIndex, this->settings.addressLabelType, this);
|
||||||
this->addressItemsByRowIndex.emplace(rowIndex, addressLabel);
|
this->addressItemsByRowIndex.emplace(rowIndex, addressLabel);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "ByteItem.hpp"
|
#include "ByteItem.hpp"
|
||||||
#include "ByteAddressItem.hpp"
|
#include "ByteAddressItem.hpp"
|
||||||
|
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/HexViewerWidgetSettings.hpp"
|
||||||
|
|
||||||
namespace Bloom::Widgets
|
namespace Bloom::Widgets
|
||||||
{
|
{
|
||||||
@@ -17,7 +18,7 @@ namespace Bloom::Widgets
|
|||||||
public:
|
public:
|
||||||
static constexpr int WIDTH = 88;
|
static constexpr int WIDTH = 88;
|
||||||
|
|
||||||
ByteAddressContainer() = default;
|
ByteAddressContainer(const HexViewerWidgetSettings& settings);
|
||||||
|
|
||||||
[[nodiscard]] QRectF boundingRect() const override {
|
[[nodiscard]] QRectF boundingRect() const override {
|
||||||
return QRectF(
|
return QRectF(
|
||||||
@@ -28,10 +29,11 @@ namespace Bloom::Widgets
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override;
|
|
||||||
void adjustAddressLabels(const std::map<std::size_t, std::vector<ByteItem*>>& byteItemsByRowIndex);
|
void adjustAddressLabels(const std::map<std::size_t, std::vector<ByteItem*>>& byteItemsByRowIndex);
|
||||||
|
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const HexViewerWidgetSettings& settings;
|
||||||
std::map<std::size_t, ByteAddressItem*> addressItemsByRowIndex;
|
std::map<std::size_t, ByteAddressItem*> addressItemsByRowIndex;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,12 @@ namespace Bloom::Widgets
|
|||||||
ByteAddressItem::ByteAddressItem(
|
ByteAddressItem::ByteAddressItem(
|
||||||
std::size_t rowIndex,
|
std::size_t rowIndex,
|
||||||
const std::map<std::size_t, std::vector<ByteItem*>>& byteItemsByRowIndex,
|
const std::map<std::size_t, std::vector<ByteItem*>>& byteItemsByRowIndex,
|
||||||
|
const AddressType& addressType,
|
||||||
QGraphicsItem* parent
|
QGraphicsItem* parent
|
||||||
)
|
)
|
||||||
: rowIndex(rowIndex)
|
: rowIndex(rowIndex)
|
||||||
, byteItemsByRowIndex(byteItemsByRowIndex)
|
, byteItemsByRowIndex(byteItemsByRowIndex)
|
||||||
|
, addressType(addressType)
|
||||||
, QGraphicsItem(parent)
|
, QGraphicsItem(parent)
|
||||||
{
|
{
|
||||||
this->setCacheMode(
|
this->setCacheMode(
|
||||||
@@ -36,7 +38,9 @@ namespace Bloom::Widgets
|
|||||||
painter->drawText(
|
painter->drawText(
|
||||||
widgetRect,
|
widgetRect,
|
||||||
Qt::AlignLeft,
|
Qt::AlignLeft,
|
||||||
this->byteItemsByRowIndex.at(this->rowIndex)[0]->relativeAddressHex
|
this->addressType == AddressType::RELATIVE
|
||||||
|
? this->byteItemsByRowIndex.at(this->rowIndex)[0]->relativeAddressHex
|
||||||
|
: this->byteItemsByRowIndex.at(this->rowIndex)[0]->addressHex
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
#include "ByteItem.hpp"
|
#include "ByteItem.hpp"
|
||||||
|
|
||||||
|
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/AddressType.hpp"
|
||||||
|
|
||||||
namespace Bloom::Widgets
|
namespace Bloom::Widgets
|
||||||
{
|
{
|
||||||
class ByteAddressItem: public QGraphicsItem
|
class ByteAddressItem: public QGraphicsItem
|
||||||
@@ -19,6 +21,7 @@ namespace Bloom::Widgets
|
|||||||
explicit ByteAddressItem(
|
explicit ByteAddressItem(
|
||||||
std::size_t rowIndex,
|
std::size_t rowIndex,
|
||||||
const std::map<std::size_t, std::vector<ByteItem*>>& byteItemsByRowIndex,
|
const std::map<std::size_t, std::vector<ByteItem*>>& byteItemsByRowIndex,
|
||||||
|
const AddressType& addressType,
|
||||||
QGraphicsItem* parent
|
QGraphicsItem* parent
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -35,5 +38,6 @@ namespace Bloom::Widgets
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
const std::map<std::size_t, std::vector<ByteItem*>>& byteItemsByRowIndex;
|
const std::map<std::size_t, std::vector<ByteItem*>>& byteItemsByRowIndex;
|
||||||
|
const AddressType& addressType;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace Bloom::Widgets
|
|||||||
const TargetMemoryDescriptor& targetMemoryDescriptor,
|
const TargetMemoryDescriptor& targetMemoryDescriptor,
|
||||||
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
|
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
|
||||||
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
|
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
|
||||||
const HexViewerWidgetSettings& settings,
|
HexViewerWidgetSettings& settings,
|
||||||
Label* hoveredAddressLabel
|
Label* hoveredAddressLabel
|
||||||
) {
|
) {
|
||||||
auto* constructSceneTask = new ConstructHexViewerByteItemScene(
|
auto* constructSceneTask = new ConstructHexViewerByteItemScene(
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace Bloom::Widgets
|
|||||||
const Targets::TargetMemoryDescriptor& targetMemoryDescriptor,
|
const Targets::TargetMemoryDescriptor& targetMemoryDescriptor,
|
||||||
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
|
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
|
||||||
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
|
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
|
||||||
const HexViewerWidgetSettings& settings,
|
HexViewerWidgetSettings& settings,
|
||||||
Label* hoveredAddressLabel
|
Label* hoveredAddressLabel
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace Bloom::Widgets
|
|||||||
const TargetMemoryDescriptor& targetMemoryDescriptor,
|
const TargetMemoryDescriptor& targetMemoryDescriptor,
|
||||||
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
|
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
|
||||||
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
|
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
|
||||||
const HexViewerWidgetSettings& settings,
|
HexViewerWidgetSettings& settings,
|
||||||
Label* hoveredAddressLabel,
|
Label* hoveredAddressLabel,
|
||||||
QGraphicsView* parent
|
QGraphicsView* parent
|
||||||
)
|
)
|
||||||
@@ -25,7 +25,7 @@ namespace Bloom::Widgets
|
|||||||
{
|
{
|
||||||
this->setObjectName("byte-widget-container");
|
this->setObjectName("byte-widget-container");
|
||||||
|
|
||||||
this->byteAddressContainer = new ByteAddressContainer();
|
this->byteAddressContainer = new ByteAddressContainer(this->settings);
|
||||||
this->addItem(this->byteAddressContainer);
|
this->addItem(this->byteAddressContainer);
|
||||||
|
|
||||||
// Construct ByteWidget objects
|
// Construct ByteWidget objects
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ namespace Bloom::Widgets
|
|||||||
const Targets::TargetMemoryDescriptor& targetMemoryDescriptor,
|
const Targets::TargetMemoryDescriptor& targetMemoryDescriptor,
|
||||||
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
|
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
|
||||||
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
|
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
|
||||||
const HexViewerWidgetSettings& settings,
|
HexViewerWidgetSettings& settings,
|
||||||
Label* hoveredAddressLabel,
|
Label* hoveredAddressLabel,
|
||||||
QGraphicsView* parent
|
QGraphicsView* parent
|
||||||
);
|
);
|
||||||
@@ -91,7 +91,7 @@ namespace Bloom::Widgets
|
|||||||
Targets::TargetState targetState = Targets::TargetState::UNKNOWN;
|
Targets::TargetState targetState = Targets::TargetState::UNKNOWN;
|
||||||
|
|
||||||
const QMargins margins = QMargins(10, 10, 10, 10);
|
const QMargins margins = QMargins(10, 10, 10, 10);
|
||||||
const HexViewerWidgetSettings& settings;
|
HexViewerWidgetSettings& settings;
|
||||||
|
|
||||||
Label* hoveredAddressLabel = nullptr;
|
Label* hoveredAddressLabel = nullptr;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/AddressType.hpp"
|
||||||
|
|
||||||
namespace Bloom::Widgets
|
namespace Bloom::Widgets
|
||||||
{
|
{
|
||||||
struct HexViewerWidgetSettings
|
struct HexViewerWidgetSettings
|
||||||
@@ -9,5 +11,7 @@ namespace Bloom::Widgets
|
|||||||
bool highlightHoveredRowAndCol = true;
|
bool highlightHoveredRowAndCol = true;
|
||||||
bool displayAsciiValues = false;
|
bool displayAsciiValues = false;
|
||||||
bool displayAnnotations = true;
|
bool displayAnnotations = true;
|
||||||
|
|
||||||
|
AddressType addressLabelType = AddressType::ABSOLUTE;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -184,6 +184,12 @@ namespace Bloom
|
|||||||
hexViewerSettings.displayAnnotations =
|
hexViewerSettings.displayAnnotations =
|
||||||
hexViewerSettingsObj.value("displayAnnotations").toBool();
|
hexViewerSettingsObj.value("displayAnnotations").toBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hexViewerSettingsObj.contains("addressLabelType")) {
|
||||||
|
hexViewerSettings.addressLabelType = InsightProjectSettings::addressTypesByName.valueAt(
|
||||||
|
hexViewerSettingsObj.value("addressLabelType").toString()
|
||||||
|
).value_or(hexViewerSettings.addressLabelType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jsonObject.contains("focusedRegions")) {
|
if (jsonObject.contains("focusedRegions")) {
|
||||||
@@ -218,7 +224,7 @@ namespace Bloom
|
|||||||
|
|
||||||
region.createdDate.setSecsSinceEpoch(regionObj.find("createdTimestamp")->toInteger());
|
region.createdDate.setSecsSinceEpoch(regionObj.find("createdTimestamp")->toInteger());
|
||||||
|
|
||||||
const auto addressInputType = InsightProjectSettings::addressRangeInputTypesByName.valueAt(
|
const auto addressInputType = InsightProjectSettings::addressTypesByName.valueAt(
|
||||||
regionObj.find("addressInputType")->toString()
|
regionObj.find("addressInputType")->toString()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -277,7 +283,7 @@ namespace Bloom
|
|||||||
|
|
||||||
region.createdDate.setSecsSinceEpoch(regionObj.find("createdTimestamp")->toInteger());
|
region.createdDate.setSecsSinceEpoch(regionObj.find("createdTimestamp")->toInteger());
|
||||||
|
|
||||||
const auto addressInputType = InsightProjectSettings::addressRangeInputTypesByName.valueAt(
|
const auto addressInputType = InsightProjectSettings::addressTypesByName.valueAt(
|
||||||
regionObj.find("addressInputType")->toString()
|
regionObj.find("addressInputType")->toString()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -334,6 +340,10 @@ namespace Bloom
|
|||||||
QJsonObject InsightProjectSettings::memoryInspectionPaneSettingsToJson(
|
QJsonObject InsightProjectSettings::memoryInspectionPaneSettingsToJson(
|
||||||
const Widgets::TargetMemoryInspectionPaneSettings& inspectionPaneSettings
|
const Widgets::TargetMemoryInspectionPaneSettings& inspectionPaneSettings
|
||||||
) const {
|
) const {
|
||||||
|
const auto& regionDataTypesByName = InsightProjectSettings::regionDataTypesByName;
|
||||||
|
const auto& regionEndiannessByName = InsightProjectSettings::regionEndiannessByName;
|
||||||
|
const auto& addressTypesByName = InsightProjectSettings::addressTypesByName;
|
||||||
|
|
||||||
auto settingsObj = QJsonObject({
|
auto settingsObj = QJsonObject({
|
||||||
{"refreshOnTargetStop", inspectionPaneSettings.refreshOnTargetStop},
|
{"refreshOnTargetStop", inspectionPaneSettings.refreshOnTargetStop},
|
||||||
{"refreshOnActivation", inspectionPaneSettings.refreshOnActivation},
|
{"refreshOnActivation", inspectionPaneSettings.refreshOnActivation},
|
||||||
@@ -346,17 +356,14 @@ namespace Bloom
|
|||||||
{"highlightHoveredRowAndCol", hexViewerSettings.highlightHoveredRowAndCol},
|
{"highlightHoveredRowAndCol", hexViewerSettings.highlightHoveredRowAndCol},
|
||||||
{"displayAsciiValues", hexViewerSettings.displayAsciiValues},
|
{"displayAsciiValues", hexViewerSettings.displayAsciiValues},
|
||||||
{"displayAnnotations", hexViewerSettings.displayAnnotations},
|
{"displayAnnotations", hexViewerSettings.displayAnnotations},
|
||||||
|
{"addressLabelType", addressTypesByName.valueAt(hexViewerSettings.addressLabelType).value()},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const auto& regionDataTypesByName = InsightProjectSettings::regionDataTypesByName;
|
|
||||||
const auto& regionEndiannessByName = InsightProjectSettings::regionEndiannessByName;
|
|
||||||
const auto& addressRangeInputTypesByName = InsightProjectSettings::addressRangeInputTypesByName;
|
|
||||||
|
|
||||||
auto focusedRegions = QJsonArray();
|
auto focusedRegions = QJsonArray();
|
||||||
for (const auto& focusedRegion : inspectionPaneSettings.focusedMemoryRegions) {
|
for (const auto& focusedRegion : inspectionPaneSettings.focusedMemoryRegions) {
|
||||||
if (!regionDataTypesByName.contains(focusedRegion.dataType)
|
if (!regionDataTypesByName.contains(focusedRegion.dataType)
|
||||||
|| !regionEndiannessByName.contains(focusedRegion.endianness)
|
|| !regionEndiannessByName.contains(focusedRegion.endianness)
|
||||||
|| !addressRangeInputTypesByName.contains(focusedRegion.addressRangeInputType)
|
|| !addressTypesByName.contains(focusedRegion.addressRangeInputType)
|
||||||
) {
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -370,7 +377,7 @@ namespace Bloom
|
|||||||
{"name", focusedRegion.name},
|
{"name", focusedRegion.name},
|
||||||
{"addressRange", addressRangeObj},
|
{"addressRange", addressRangeObj},
|
||||||
{"createdTimestamp", focusedRegion.createdDate.toSecsSinceEpoch()},
|
{"createdTimestamp", focusedRegion.createdDate.toSecsSinceEpoch()},
|
||||||
{"addressInputType", addressRangeInputTypesByName.at(focusedRegion.addressRangeInputType)},
|
{"addressInputType", addressTypesByName.at(focusedRegion.addressRangeInputType)},
|
||||||
{"dataType", regionDataTypesByName.at(focusedRegion.dataType)},
|
{"dataType", regionDataTypesByName.at(focusedRegion.dataType)},
|
||||||
{"endianness", regionEndiannessByName.at(focusedRegion.endianness)},
|
{"endianness", regionEndiannessByName.at(focusedRegion.endianness)},
|
||||||
});
|
});
|
||||||
@@ -380,7 +387,7 @@ namespace Bloom
|
|||||||
|
|
||||||
auto excludedRegions = QJsonArray();
|
auto excludedRegions = QJsonArray();
|
||||||
for (const auto& excludedRegion : inspectionPaneSettings.excludedMemoryRegions) {
|
for (const auto& excludedRegion : inspectionPaneSettings.excludedMemoryRegions) {
|
||||||
if (!addressRangeInputTypesByName.contains(excludedRegion.addressRangeInputType)) {
|
if (!addressTypesByName.contains(excludedRegion.addressRangeInputType)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,7 +400,7 @@ namespace Bloom
|
|||||||
{"name", excludedRegion.name},
|
{"name", excludedRegion.name},
|
||||||
{"addressRange", addressRangeObj},
|
{"addressRange", addressRangeObj},
|
||||||
{"createdTimestamp", excludedRegion.createdDate.toSecsSinceEpoch()},
|
{"createdTimestamp", excludedRegion.createdDate.toSecsSinceEpoch()},
|
||||||
{"addressInputType", addressRangeInputTypesByName.at(excludedRegion.addressRangeInputType)},
|
{"addressInputType", addressTypesByName.at(excludedRegion.addressRangeInputType)},
|
||||||
});
|
});
|
||||||
|
|
||||||
excludedRegions.push_back(regionObj);
|
excludedRegions.push_back(regionObj);
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ namespace Bloom
|
|||||||
{Targets::TargetMemoryEndianness::BIG, "big"},
|
{Targets::TargetMemoryEndianness::BIG, "big"},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const inline BiMap<AddressType, QString> addressRangeInputTypesByName = {
|
static const inline BiMap<AddressType, QString> addressTypesByName = {
|
||||||
{AddressType::ABSOLUTE, "absolute"},
|
{AddressType::ABSOLUTE, "absolute"},
|
||||||
{AddressType::RELATIVE, "relative"},
|
{AddressType::RELATIVE, "relative"},
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user