forked from qt-creator/qt-creator
QmlJsEditor: Further aspectify settings gui
Change-Id: Ia14289a414e23c6e830d88bbfe0a69577c0f2a31 Reviewed-by: Sami Shalayel <sami.shalayel@qt.io> Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -202,24 +202,66 @@ QmlJsEditingSettings::QmlJsEditingSettings()
|
|||||||
|
|
||||||
useQmlls.setSettingsKey(group, USE_QMLLS);
|
useQmlls.setSettingsKey(group, USE_QMLLS);
|
||||||
useQmlls.setDefaultValue(true);
|
useQmlls.setDefaultValue(true);
|
||||||
|
useQmlls.setLabelText(Tr::tr("Turn on"));
|
||||||
|
|
||||||
enableContextPane.setSettingsKey(group, QML_CONTEXTPANE_KEY);
|
enableContextPane.setSettingsKey(group, QML_CONTEXTPANE_KEY);
|
||||||
|
enableContextPane.setLabelText(Tr::tr("Always show Qt Quick Toolbar"));
|
||||||
|
|
||||||
pinContextPane.setSettingsKey(group, QML_CONTEXTPANEPIN_KEY);
|
pinContextPane.setSettingsKey(group, QML_CONTEXTPANEPIN_KEY);
|
||||||
|
pinContextPane.setLabelText(Tr::tr("Pin Qt Quick Toolbar"));
|
||||||
|
|
||||||
autoFormatOnSave.setSettingsKey(group, AUTO_FORMAT_ON_SAVE);
|
autoFormatOnSave.setSettingsKey(group, AUTO_FORMAT_ON_SAVE);
|
||||||
|
autoFormatOnSave.setLabelText(Tr::tr("Enable auto format on file save"));
|
||||||
|
|
||||||
autoFormatOnlyCurrentProject.setSettingsKey(group, AUTO_FORMAT_ONLY_CURRENT_PROJECT);
|
autoFormatOnlyCurrentProject.setSettingsKey(group, AUTO_FORMAT_ONLY_CURRENT_PROJECT);
|
||||||
|
autoFormatOnlyCurrentProject.setEnabler(&autoFormatOnSave);
|
||||||
|
autoFormatOnlyCurrentProject.setLabelText(
|
||||||
|
Tr::tr("Restrict to files contained in the current project"));
|
||||||
|
|
||||||
foldAuxData.setSettingsKey(group, FOLD_AUX_DATA);
|
foldAuxData.setSettingsKey(group, FOLD_AUX_DATA);
|
||||||
foldAuxData.setDefaultValue(true);
|
foldAuxData.setDefaultValue(true);
|
||||||
|
foldAuxData.setLabelText(Tr::tr("Auto-fold auxiliary data"));
|
||||||
|
|
||||||
uiQmlOpenMode.setSettingsKey(group, UIQML_OPEN_MODE);
|
uiQmlOpenMode.setSettingsKey(group, UIQML_OPEN_MODE);
|
||||||
|
|
||||||
useLatestQmlls.setSettingsKey(group, USE_LATEST_QMLLS);
|
useLatestQmlls.setSettingsKey(group, USE_LATEST_QMLLS);
|
||||||
|
useLatestQmlls.setEnabler(&useQmlls);
|
||||||
|
useLatestQmlls.setLabelText(Tr::tr("Use from latest Qt version"));
|
||||||
|
|
||||||
disableBuiltinCodemodel.setSettingsKey(group, DISABLE_BUILTIN_CODEMODEL);
|
disableBuiltinCodemodel.setSettingsKey(group, DISABLE_BUILTIN_CODEMODEL);
|
||||||
|
disableBuiltinCodemodel.setEnabler(&useQmlls);
|
||||||
|
disableBuiltinCodemodel.setLabelText(
|
||||||
|
Tr::tr("Use advanced features (renaming, find usages, and so on) "
|
||||||
|
"(experimental)"));
|
||||||
|
|
||||||
generateQmllsIniFiles.setSettingsKey(group, GENERATE_QMLLS_INI_FILES);
|
generateQmllsIniFiles.setSettingsKey(group, GENERATE_QMLLS_INI_FILES);
|
||||||
|
generateQmllsIniFiles.setEnabler(&useQmlls);
|
||||||
|
generateQmllsIniFiles.setLabelText(
|
||||||
|
Tr::tr("Create .qmlls.ini files for new projects"));
|
||||||
|
|
||||||
ignoreMinimumQmllsVersion.setSettingsKey(group, IGNORE_MINIMUM_QMLLS_VERSION);
|
ignoreMinimumQmllsVersion.setSettingsKey(group, IGNORE_MINIMUM_QMLLS_VERSION);
|
||||||
formatCommand.setSettingsKey(group, FORMAT_COMMAND);
|
ignoreMinimumQmllsVersion.setEnabler(&useQmlls);
|
||||||
formatCommandOptions.setSettingsKey(group, FORMAT_COMMAND_OPTIONS);
|
ignoreMinimumQmllsVersion.setLabelText(
|
||||||
|
Tr::tr("Allow versions below Qt %1")
|
||||||
|
.arg(QmlJsEditingSettings::mininumQmllsVersion.toString()));
|
||||||
|
|
||||||
useCustomFormatCommand.setSettingsKey(group, CUSTOM_COMMAND);
|
useCustomFormatCommand.setSettingsKey(group, CUSTOM_COMMAND);
|
||||||
|
useCustomFormatCommand.setLabelText(
|
||||||
|
Tr::tr("Use custom command instead of built-in formatter"));
|
||||||
|
|
||||||
|
formatCommand.setSettingsKey(group, FORMAT_COMMAND);
|
||||||
|
formatCommand.setEnabler(&useCustomFormatCommand);
|
||||||
|
formatCommand.setDisplayStyle(StringAspect::LineEditDisplay);
|
||||||
|
formatCommand.setPlaceHolderText(defaultFormatCommand());
|
||||||
|
formatCommand.setLabelText(Tr::tr("Command:"));
|
||||||
|
|
||||||
|
formatCommandOptions.setSettingsKey(group, FORMAT_COMMAND_OPTIONS);
|
||||||
|
formatCommandOptions.setEnabler(&useCustomFormatCommand);
|
||||||
|
formatCommandOptions.setDisplayStyle(StringAspect::LineEditDisplay);
|
||||||
|
formatCommandOptions.setLabelText(Tr::tr("Arguments:"));
|
||||||
|
|
||||||
useCustomAnalyzer.setSettingsKey(group, CUSTOM_ANALYZER);
|
useCustomAnalyzer.setSettingsKey(group, CUSTOM_ANALYZER);
|
||||||
|
useCustomAnalyzer.setLabelText(Tr::tr("Use customized static analyzer"));
|
||||||
|
|
||||||
disabledMessages.setSettingsKey(group, DISABLED_MESSAGES);
|
disabledMessages.setSettingsKey(group, DISABLED_MESSAGES);
|
||||||
disabledMessages.setDefaultValue(defaultDisabledMessages());
|
disabledMessages.setDefaultValue(defaultDisabledMessages());
|
||||||
@@ -300,29 +342,8 @@ class QmlJsEditingSettingsPageWidget final : public Core::IOptionsPageWidget
|
|||||||
public:
|
public:
|
||||||
QmlJsEditingSettingsPageWidget()
|
QmlJsEditingSettingsPageWidget()
|
||||||
{
|
{
|
||||||
const QmlJsEditingSettings &s = settings();
|
QmlJsEditingSettings &s = settings();
|
||||||
autoFormatOnSave = new QCheckBox(Tr::tr("Enable auto format on file save"));
|
|
||||||
autoFormatOnSave->setChecked(s.autoFormatOnSave());
|
|
||||||
autoFormatOnlyCurrentProject =
|
|
||||||
new QCheckBox(Tr::tr("Restrict to files contained in the current project"));
|
|
||||||
autoFormatOnlyCurrentProject->setChecked(s.autoFormatOnlyCurrentProject());
|
|
||||||
autoFormatOnlyCurrentProject->setEnabled(autoFormatOnSave->isChecked());
|
|
||||||
useCustomFormatCommand = new QCheckBox(
|
|
||||||
Tr::tr("Use custom command instead of built-in formatter"));
|
|
||||||
useCustomFormatCommand->setChecked(s.useCustomFormatCommand());
|
|
||||||
auto formatCommandLabel = new QLabel(Tr::tr("Command:"));
|
|
||||||
formatCommand = new QLineEdit();
|
|
||||||
formatCommand->setText(s.formatCommand());
|
|
||||||
formatCommand->setPlaceholderText(s.defaultFormatCommand());
|
|
||||||
auto formatCommandOptionsLabel = new QLabel(Tr::tr("Arguments:"));
|
|
||||||
formatCommandOptions = new QLineEdit();
|
|
||||||
formatCommandOptions->setText(s.formatCommandOptions());
|
|
||||||
pinContextPane = new QCheckBox(Tr::tr("Pin Qt Quick Toolbar"));
|
|
||||||
pinContextPane->setChecked(s.pinContextPane());
|
|
||||||
enableContextPane = new QCheckBox(Tr::tr("Always show Qt Quick Toolbar"));
|
|
||||||
enableContextPane->setChecked(s.enableContextPane());
|
|
||||||
foldAuxData = new QCheckBox(Tr::tr("Auto-fold auxiliary data"));
|
|
||||||
foldAuxData->setChecked(s.foldAuxData());
|
|
||||||
uiQmlOpenComboBox = new QComboBox;
|
uiQmlOpenComboBox = new QComboBox;
|
||||||
uiQmlOpenComboBox->addItem(Tr::tr("Always Ask"), "");
|
uiQmlOpenComboBox->addItem(Tr::tr("Always Ask"), "");
|
||||||
uiQmlOpenComboBox->addItem(Tr::tr("Qt Design Studio"), Core::Constants::MODE_DESIGN);
|
uiQmlOpenComboBox->addItem(Tr::tr("Qt Design Studio"), Core::Constants::MODE_DESIGN);
|
||||||
@@ -332,45 +353,14 @@ public:
|
|||||||
uiQmlOpenComboBox->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
|
uiQmlOpenComboBox->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
|
||||||
uiQmlOpenComboBox->setSizeAdjustPolicy(QComboBox::QComboBox::AdjustToContents);
|
uiQmlOpenComboBox->setSizeAdjustPolicy(QComboBox::QComboBox::AdjustToContents);
|
||||||
|
|
||||||
useQmlls = new QCheckBox(Tr::tr("Turn on"));
|
analyzerMessageModel.setHeader({Tr::tr("Enabled"),
|
||||||
useQmlls->setChecked(s.useQmlls());
|
Tr::tr("Disabled for non Qt Quick UI"),
|
||||||
|
Tr::tr("Message")});
|
||||||
ignoreMinimumQmllsVersion = new QCheckBox(
|
|
||||||
Tr::tr("Allow versions below Qt %1")
|
|
||||||
.arg(QmlJsEditingSettings::mininumQmllsVersion.toString()));
|
|
||||||
ignoreMinimumQmllsVersion->setChecked(s.ignoreMinimumQmllsVersion());
|
|
||||||
ignoreMinimumQmllsVersion->setEnabled(s.useQmlls());
|
|
||||||
|
|
||||||
disableBuiltInCodemodel = new QCheckBox(
|
|
||||||
Tr::tr("Use advanced features (renaming, find usages, and so on) "
|
|
||||||
"(experimental)"));
|
|
||||||
disableBuiltInCodemodel->setChecked(s.disableBuiltinCodemodel());
|
|
||||||
disableBuiltInCodemodel->setEnabled(s.useQmlls());
|
|
||||||
useLatestQmlls = new QCheckBox(Tr::tr("Use from latest Qt version"));
|
|
||||||
useLatestQmlls->setChecked(s.useLatestQmlls());
|
|
||||||
useLatestQmlls->setEnabled(s.useQmlls());
|
|
||||||
|
|
||||||
generateQmllsIniFiles = new QCheckBox(Tr::tr("Create .qmlls.ini files for new projects"));
|
|
||||||
generateQmllsIniFiles->setChecked(s.generateQmllsIniFiles());
|
|
||||||
generateQmllsIniFiles->setEnabled(s.useQmlls());
|
|
||||||
QObject::connect(useQmlls, &QCheckBox::stateChanged, this, [this](int checked) {
|
|
||||||
useLatestQmlls->setEnabled(checked != Qt::Unchecked);
|
|
||||||
disableBuiltInCodemodel->setEnabled(checked != Qt::Unchecked);
|
|
||||||
generateQmllsIniFiles->setEnabled(checked != Qt::Unchecked);
|
|
||||||
ignoreMinimumQmllsVersion->setEnabled(checked != Qt::Unchecked);
|
|
||||||
});
|
|
||||||
|
|
||||||
useCustomAnalyzer = new QCheckBox(Tr::tr("Use customized static analyzer"));
|
|
||||||
useCustomAnalyzer->setChecked(s.useCustomAnalyzer());
|
|
||||||
analyzerMessageModel = new Utils::TreeModel<AnalyzerMessageItem>(this);
|
|
||||||
analyzerMessageModel->setHeader({Tr::tr("Enabled"),
|
|
||||||
Tr::tr("Disabled for non Qt Quick UI"),
|
|
||||||
Tr::tr("Message")});
|
|
||||||
analyzerMessagesView = new QTreeView;
|
analyzerMessagesView = new QTreeView;
|
||||||
analyzerMessagesView->setModel(analyzerMessageModel);
|
analyzerMessagesView->setModel(&analyzerMessageModel);
|
||||||
analyzerMessagesView->setEnabled(s.useCustomAnalyzer());
|
analyzerMessagesView->setEnabled(s.useCustomAnalyzer());
|
||||||
QObject::connect(useCustomAnalyzer, &QCheckBox::stateChanged, this, [this](int checked){
|
QObject::connect(&s.useCustomAnalyzer, &BoolAspect::volatileValueChanged, this, [this, &s] {
|
||||||
analyzerMessagesView->setEnabled(checked != Qt::Unchecked);
|
analyzerMessagesView->setEnabled(s.useCustomAnalyzer.volatileValue());
|
||||||
});
|
});
|
||||||
analyzerMessagesView->setToolTip(
|
analyzerMessagesView->setToolTip(
|
||||||
"<html>"
|
"<html>"
|
||||||
@@ -388,33 +378,45 @@ public:
|
|||||||
bindTo(&formattingGroup),
|
bindTo(&formattingGroup),
|
||||||
title(Tr::tr("Automatic Formatting on File Save")),
|
title(Tr::tr("Automatic Formatting on File Save")),
|
||||||
Column {
|
Column {
|
||||||
autoFormatOnSave,
|
s.autoFormatOnSave,
|
||||||
autoFormatOnlyCurrentProject,
|
s.autoFormatOnlyCurrentProject,
|
||||||
useCustomFormatCommand,
|
s.useCustomFormatCommand,
|
||||||
Form {
|
Form {
|
||||||
formatCommandLabel, formatCommand, br,
|
s.formatCommand, br,
|
||||||
formatCommandOptionsLabel, formatCommandOptions
|
s.formatCommandOptions
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Group {
|
Group {
|
||||||
title(Tr::tr("Qt Quick Toolbars")),
|
title(Tr::tr("Qt Quick Toolbars")),
|
||||||
Column { pinContextPane, enableContextPane },
|
Column {
|
||||||
|
s.pinContextPane,
|
||||||
|
s.enableContextPane
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Group {
|
Group {
|
||||||
title(Tr::tr("Features")),
|
title(Tr::tr("Features")),
|
||||||
Column {
|
Column {
|
||||||
foldAuxData,
|
s.foldAuxData,
|
||||||
Form { Tr::tr("Open .ui.qml files with:"), uiQmlOpenComboBox },
|
Form { Tr::tr("Open .ui.qml files with:"), uiQmlOpenComboBox },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Group{
|
Group{
|
||||||
title(Tr::tr("QML Language Server")),
|
title(Tr::tr("QML Language Server")),
|
||||||
Column{useQmlls, ignoreMinimumQmllsVersion, disableBuiltInCodemodel, useLatestQmlls, generateQmllsIniFiles},
|
Column {
|
||||||
|
s.useQmlls,
|
||||||
|
s.ignoreMinimumQmllsVersion,
|
||||||
|
s.disableBuiltinCodemodel,
|
||||||
|
s.useLatestQmlls,
|
||||||
|
s.generateQmllsIniFiles
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Group {
|
Group {
|
||||||
title(Tr::tr("Static Analyzer")),
|
title(Tr::tr("Static Analyzer")),
|
||||||
Column{ useCustomAnalyzer, analyzerMessagesView },
|
Column {
|
||||||
|
s.useCustomAnalyzer,
|
||||||
|
analyzerMessagesView
|
||||||
|
},
|
||||||
},
|
},
|
||||||
st,
|
st,
|
||||||
}.attachTo(this);
|
}.attachTo(this);
|
||||||
@@ -423,46 +425,18 @@ public:
|
|||||||
Utils::VariableChooser::addSupportForChildWidgets(formattingGroup,
|
Utils::VariableChooser::addSupportForChildWidgets(formattingGroup,
|
||||||
Utils::globalMacroExpander());
|
Utils::globalMacroExpander());
|
||||||
|
|
||||||
const auto updateFormatCommandState = [&, formatCommandLabel, formatCommandOptionsLabel] {
|
|
||||||
const bool enabled = useCustomFormatCommand->isChecked();
|
|
||||||
formatCommandLabel->setEnabled(enabled);
|
|
||||||
formatCommand->setEnabled(enabled);
|
|
||||||
formatCommandOptionsLabel->setEnabled(enabled);
|
|
||||||
formatCommandOptions->setEnabled(enabled);
|
|
||||||
};
|
|
||||||
updateFormatCommandState();
|
|
||||||
|
|
||||||
connect(autoFormatOnSave, &QCheckBox::toggled, this, [&, updateFormatCommandState]() {
|
|
||||||
autoFormatOnlyCurrentProject->setEnabled(autoFormatOnSave->isChecked());
|
|
||||||
updateFormatCommandState();
|
|
||||||
});
|
|
||||||
connect(useCustomFormatCommand, &QCheckBox::toggled, this, updateFormatCommandState);
|
|
||||||
|
|
||||||
populateAnalyzerMessages(s.disabledMessages(), s.disabledMessagesForNonQuickUi());
|
populateAnalyzerMessages(s.disabledMessages(), s.disabledMessagesForNonQuickUi());
|
||||||
}
|
}
|
||||||
|
|
||||||
void apply() final
|
void apply() final
|
||||||
{
|
{
|
||||||
QmlJsEditingSettings &s = settings();
|
QmlJsEditingSettings &s = settings();
|
||||||
s.enableContextPane.setValue(enableContextPane->isChecked());
|
s.apply();
|
||||||
s.pinContextPane.setValue(pinContextPane->isChecked());
|
|
||||||
s.autoFormatOnSave.setValue(autoFormatOnSave->isChecked());
|
|
||||||
s.autoFormatOnlyCurrentProject.setValue(autoFormatOnlyCurrentProject->isChecked());
|
|
||||||
s.useCustomFormatCommand.setValue(useCustomFormatCommand->isChecked());
|
|
||||||
s.formatCommand.setValue(formatCommand->text());
|
|
||||||
s.formatCommandOptions.setValue(formatCommandOptions->text());
|
|
||||||
s.foldAuxData.setValue(foldAuxData->isChecked());
|
|
||||||
s.uiQmlOpenMode.setValue(uiQmlOpenComboBox->currentData().toString());
|
s.uiQmlOpenMode.setValue(uiQmlOpenComboBox->currentData().toString());
|
||||||
s.useQmlls.setValue(useQmlls->isChecked());
|
|
||||||
s.disableBuiltinCodemodel.setValue(disableBuiltInCodemodel->isChecked());
|
|
||||||
s.ignoreMinimumQmllsVersion.setValue(ignoreMinimumQmllsVersion->isChecked());
|
|
||||||
s.useLatestQmlls.setValue(useLatestQmlls->isChecked());
|
|
||||||
s.generateQmllsIniFiles.setValue(generateQmllsIniFiles->isChecked());
|
|
||||||
s.useCustomAnalyzer.setValue(useCustomAnalyzer->isChecked());
|
|
||||||
QList<int> disabled;
|
QList<int> disabled;
|
||||||
QList<int> disabledForNonQuickUi;
|
QList<int> disabledForNonQuickUi;
|
||||||
|
|
||||||
analyzerMessageModel->forAllItems(
|
analyzerMessageModel.forAllItems(
|
||||||
[&disabled, &disabledForNonQuickUi](AnalyzerMessageItem *item){
|
[&disabled, &disabledForNonQuickUi](AnalyzerMessageItem *item){
|
||||||
if (item->data(0, Qt::CheckStateRole) == Qt::Unchecked)
|
if (item->data(0, Qt::CheckStateRole) == Qt::Unchecked)
|
||||||
disabled.append(item->messageNumber());
|
disabled.append(item->messageNumber());
|
||||||
@@ -480,7 +454,7 @@ private:
|
|||||||
{
|
{
|
||||||
using namespace QmlJS::StaticAnalysis;
|
using namespace QmlJS::StaticAnalysis;
|
||||||
auto knownMessages = Utils::sorted(Message::allMessageTypes());
|
auto knownMessages = Utils::sorted(Message::allMessageTypes());
|
||||||
auto root = analyzerMessageModel->rootItem();
|
auto root = analyzerMessageModel.rootItem();
|
||||||
for (auto msgType : knownMessages) {
|
for (auto msgType : knownMessages) {
|
||||||
const QString msg = Message::prototypeForMessageType(msgType).message;
|
const QString msg = Message::prototypeForMessageType(msgType).message;
|
||||||
auto item = new AnalyzerMessageItem(msgType, msg);
|
auto item = new AnalyzerMessageItem(msgType, msg);
|
||||||
@@ -499,7 +473,7 @@ private:
|
|||||||
QAction *reset = new QAction(Tr::tr("Reset to Default"), &menu);
|
QAction *reset = new QAction(Tr::tr("Reset to Default"), &menu);
|
||||||
menu.addAction(reset);
|
menu.addAction(reset);
|
||||||
connect(reset, &QAction::triggered, this, [this](){
|
connect(reset, &QAction::triggered, this, [this](){
|
||||||
analyzerMessageModel->clear();
|
analyzerMessageModel.clear();
|
||||||
populateAnalyzerMessages(defaultDisabledMessages(),
|
populateAnalyzerMessages(defaultDisabledMessages(),
|
||||||
defaultDisabledMessagesNonQuickUi());
|
defaultDisabledMessagesNonQuickUi());
|
||||||
|
|
||||||
@@ -507,23 +481,9 @@ private:
|
|||||||
menu.exec(analyzerMessagesView->mapToGlobal(position));
|
menu.exec(analyzerMessagesView->mapToGlobal(position));
|
||||||
}
|
}
|
||||||
|
|
||||||
QCheckBox *autoFormatOnSave;
|
|
||||||
QCheckBox *autoFormatOnlyCurrentProject;
|
|
||||||
QCheckBox *useCustomFormatCommand;
|
|
||||||
QLineEdit *formatCommand;
|
|
||||||
QLineEdit *formatCommandOptions;
|
|
||||||
QCheckBox *pinContextPane;
|
|
||||||
QCheckBox *enableContextPane;
|
|
||||||
QCheckBox *foldAuxData;
|
|
||||||
QCheckBox *useQmlls;
|
|
||||||
QCheckBox *useLatestQmlls;
|
|
||||||
QCheckBox *ignoreMinimumQmllsVersion;
|
|
||||||
QCheckBox *disableBuiltInCodemodel;
|
|
||||||
QCheckBox *generateQmllsIniFiles;
|
|
||||||
QComboBox *uiQmlOpenComboBox;
|
QComboBox *uiQmlOpenComboBox;
|
||||||
QCheckBox *useCustomAnalyzer;
|
|
||||||
QTreeView *analyzerMessagesView;
|
QTreeView *analyzerMessagesView;
|
||||||
Utils::TreeModel<AnalyzerMessageItem> *analyzerMessageModel;
|
Utils::TreeModel<AnalyzerMessageItem> analyzerMessageModel;
|
||||||
};
|
};
|
||||||
|
|
||||||
QmlJsEditingSettingsPage::QmlJsEditingSettingsPage()
|
QmlJsEditingSettingsPage::QmlJsEditingSettingsPage()
|
||||||
|
Reference in New Issue
Block a user