Lock file. Save windows geometry.
--HG-- branch : feature
This commit is contained in:
parent
d9ca57d550
commit
6e6b040b60
|
@ -42,6 +42,8 @@ DialogMDataBase::DialogMDataBase(const QStringList &list, QWidget *parent)
|
||||||
|
|
||||||
connect(ui->treeWidget, &QTreeWidget::itemChanged, this, &DialogMDataBase::UpdateChecks);
|
connect(ui->treeWidget, &QTreeWidget::itemChanged, this, &DialogMDataBase::UpdateChecks);
|
||||||
connect(ui->treeWidget, &QTreeWidget::itemClicked, this, &DialogMDataBase::ShowDescription);
|
connect(ui->treeWidget, &QTreeWidget::itemClicked, this, &DialogMDataBase::ShowDescription);
|
||||||
|
|
||||||
|
ReadSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
@ -56,11 +58,14 @@ DialogMDataBase::DialogMDataBase(QWidget *parent)
|
||||||
InitDataBase();
|
InitDataBase();
|
||||||
|
|
||||||
connect(ui->treeWidget, &QTreeWidget::itemClicked, this, &DialogMDataBase::ShowDescription);
|
connect(ui->treeWidget, &QTreeWidget::itemClicked, this, &DialogMDataBase::ShowDescription);
|
||||||
|
|
||||||
|
ReadSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
DialogMDataBase::~DialogMDataBase()
|
DialogMDataBase::~DialogMDataBase()
|
||||||
{
|
{
|
||||||
|
WriteSettings();
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1510,3 +1515,15 @@ QString DialogMDataBase::MapDiagrams(const QString &number) const
|
||||||
|
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
void DialogMDataBase::ReadSettings()
|
||||||
|
{
|
||||||
|
restoreGeometry(qApp->TapeSettings()->GetDataBaseGeometry());
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
void DialogMDataBase::WriteSettings()
|
||||||
|
{
|
||||||
|
qApp->TapeSettings()->SetDataBaseGeometry(saveGeometry());
|
||||||
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ class DialogMDataBase : public QDialog
|
||||||
public:
|
public:
|
||||||
DialogMDataBase(const QStringList &list, QWidget *parent = 0);
|
DialogMDataBase(const QStringList &list, QWidget *parent = 0);
|
||||||
explicit DialogMDataBase(QWidget *parent = 0);
|
explicit DialogMDataBase(QWidget *parent = 0);
|
||||||
~DialogMDataBase();
|
virtual ~DialogMDataBase() Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
QStringList GetNewNames() const;
|
QStringList GetNewNames() const;
|
||||||
|
|
||||||
|
@ -84,6 +84,9 @@ private:
|
||||||
void AddMeasurement(QTreeWidgetItem *group, const QString &name, const QStringList &list);
|
void AddMeasurement(QTreeWidgetItem *group, const QString &name, const QStringList &list);
|
||||||
|
|
||||||
QString MapDiagrams(const QString &number) const;
|
QString MapDiagrams(const QString &number) const;
|
||||||
|
|
||||||
|
void ReadSettings();
|
||||||
|
void WriteSettings();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DIALOGMDATABASE_H
|
#endif // DIALOGMDATABASE_H
|
||||||
|
|
|
@ -16,7 +16,8 @@ HEADERS += \
|
||||||
$$PWD/mapplication.h \
|
$$PWD/mapplication.h \
|
||||||
$$PWD/dialogs/dialogabouttape.h \
|
$$PWD/dialogs/dialogabouttape.h \
|
||||||
$$PWD/dialogs/dialognewmeasurements.h \
|
$$PWD/dialogs/dialognewmeasurements.h \
|
||||||
$$PWD/dialogs/dialogmdatabase.h
|
$$PWD/dialogs/dialogmdatabase.h \
|
||||||
|
$$PWD/version.h
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
$$PWD/tmainwindow.ui \
|
$$PWD/tmainwindow.ui \
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "../ifc/xml/vvstconverter.h"
|
#include "../ifc/xml/vvstconverter.h"
|
||||||
#include "../qmuparser/qmudef.h"
|
#include "../qmuparser/qmudef.h"
|
||||||
#include "../vtools/dialogs/support/dialogeditwrongformula.h"
|
#include "../vtools/dialogs/support/dialogeditwrongformula.h"
|
||||||
|
#include "version.h"
|
||||||
#include "mapplication.h" // Should be last because of definning qApp
|
#include "mapplication.h" // Should be last because of definning qApp
|
||||||
|
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
|
@ -44,9 +45,14 @@
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
# include <QLockFile>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define DIALOG_MAX_FORMULA_HEIGHT 64
|
#define DIALOG_MAX_FORMULA_HEIGHT 64
|
||||||
|
|
||||||
|
Q_LOGGING_CATEGORY(tMainWindow, "t.mainwindow")
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
TMainWindow::TMainWindow(QWidget *parent)
|
TMainWindow::TMainWindow(QWidget *parent)
|
||||||
:QMainWindow(parent),
|
:QMainWindow(parent),
|
||||||
|
@ -58,7 +64,8 @@ TMainWindow::TMainWindow(QWidget *parent)
|
||||||
curFile(),
|
curFile(),
|
||||||
gradationHeights(nullptr),
|
gradationHeights(nullptr),
|
||||||
gradationSizes(nullptr),
|
gradationSizes(nullptr),
|
||||||
formulaBaseHeight(0)
|
formulaBaseHeight(0),
|
||||||
|
lock(nullptr)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
ui->tabWidget->setVisible(false);
|
ui->tabWidget->setVisible(false);
|
||||||
|
@ -70,6 +77,8 @@ TMainWindow::TMainWindow(QWidget *parent)
|
||||||
SetupMenu();
|
SetupMenu();
|
||||||
|
|
||||||
setWindowTitle(tr("untitled %1").arg(qApp->MainWindows().size()+1));
|
setWindowTitle(tr("untitled %1").arg(qApp->MainWindows().size()+1));
|
||||||
|
|
||||||
|
ReadSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
@ -84,6 +93,11 @@ TMainWindow::~TMainWindow()
|
||||||
{
|
{
|
||||||
delete m;
|
delete m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
delete lock; // Unlock pattern file
|
||||||
|
#endif
|
||||||
|
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,10 +119,24 @@ void TMainWindow::LoadFile(const QString &path)
|
||||||
if (list.at(i)->CurrentFile() == path)
|
if (list.at(i)->CurrentFile() == path)
|
||||||
{
|
{
|
||||||
list.at(i)->activateWindow();
|
list.at(i)->activateWindow();
|
||||||
|
close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
lock = new QLockFile(QFileInfo(path).fileName()+".lock");
|
||||||
|
lock->setStaleLockTime(0);
|
||||||
|
if (not MApplication::TryLock(lock))
|
||||||
|
{
|
||||||
|
if (lock->error() == QLockFile::LockFailedError)
|
||||||
|
{
|
||||||
|
qCCritical(tMainWindow, "%s", tr("This file already opened in another window.").toUtf8().constData());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif //QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
data = new VContainer(qApp->TrVars(), &mUnit);
|
data = new VContainer(qApp->TrVars(), &mUnit);
|
||||||
|
@ -277,6 +305,7 @@ void TMainWindow::closeEvent(QCloseEvent *event)
|
||||||
{
|
{
|
||||||
if (MaybeSave())
|
if (MaybeSave())
|
||||||
{
|
{
|
||||||
|
WriteSettings();
|
||||||
event->accept();
|
event->accept();
|
||||||
deleteLater();
|
deleteLater();
|
||||||
}
|
}
|
||||||
|
@ -1722,6 +1751,25 @@ void TMainWindow::GUIReadOnly(bool ro)
|
||||||
Controls(); // Buttons remove, up, down
|
Controls(); // Buttons remove, up, down
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
void TMainWindow::ReadSettings()
|
||||||
|
{
|
||||||
|
restoreGeometry(qApp->TapeSettings()->GetGeometry());
|
||||||
|
restoreState(qApp->TapeSettings()->GetWindowState());
|
||||||
|
restoreState(qApp->TapeSettings()->GetToolbarsState(), APP_VERSION);
|
||||||
|
|
||||||
|
// Stack limit
|
||||||
|
//qApp->getUndoStack()->setUndoLimit(qApp->TapeSettings()->GetUndoCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
void TMainWindow::WriteSettings()
|
||||||
|
{
|
||||||
|
qApp->TapeSettings()->SetGeometry(saveGeometry());
|
||||||
|
qApp->TapeSettings()->SetWindowState(saveState());
|
||||||
|
qApp->TapeSettings()->SetToolbarsState(saveState(APP_VERSION));
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
void TMainWindow::SetDecimals()
|
void TMainWindow::SetDecimals()
|
||||||
{
|
{
|
||||||
|
|
|
@ -42,6 +42,9 @@ namespace Ui
|
||||||
class QComboBox;
|
class QComboBox;
|
||||||
class QTableWidgetItem;
|
class QTableWidgetItem;
|
||||||
class QLabel;
|
class QLabel;
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
class QLockFile;
|
||||||
|
#endif
|
||||||
|
|
||||||
class TMainWindow : public QMainWindow
|
class TMainWindow : public QMainWindow
|
||||||
{
|
{
|
||||||
|
@ -116,6 +119,10 @@ private:
|
||||||
QComboBox *gradationSizes;
|
QComboBox *gradationSizes;
|
||||||
int formulaBaseHeight;
|
int formulaBaseHeight;
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
QLockFile *lock;
|
||||||
|
#endif
|
||||||
|
|
||||||
void SetupMenu();
|
void SetupMenu();
|
||||||
void InitWindow();
|
void InitWindow();
|
||||||
void InitTable();
|
void InitTable();
|
||||||
|
@ -148,6 +155,9 @@ private:
|
||||||
|
|
||||||
void Open(const QString &pathTo, const QString &filter);
|
void Open(const QString &pathTo, const QString &filter);
|
||||||
void GUIReadOnly(bool ro);
|
void GUIReadOnly(bool ro);
|
||||||
|
|
||||||
|
void ReadSettings();
|
||||||
|
void WriteSettings();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TMAINWINDOW_H
|
#endif // TMAINWINDOW_H
|
||||||
|
|
|
@ -48,9 +48,6 @@
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
|
|
||||||
# include <QLockFile>
|
|
||||||
#endif
|
|
||||||
#include <QtXmlPatterns>
|
#include <QtXmlPatterns>
|
||||||
|
|
||||||
Q_LOGGING_CATEGORY(vApp, "v.application")
|
Q_LOGGING_CATEGORY(vApp, "v.application")
|
||||||
|
@ -274,46 +271,6 @@ bool VApplication::notify(QObject *receiver, QEvent *event)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
|
||||||
bool VApplication::TryLock(QLockFile *lock)
|
|
||||||
{
|
|
||||||
if (lock == nullptr)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lock->tryLock())
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (lock->error() == QLockFile::LockFailedError)
|
|
||||||
{
|
|
||||||
// This happens if a stale lock file exists and another process uses that PID.
|
|
||||||
// Try removing the stale file, which will fail if a real process is holding a
|
|
||||||
// file-level lock. A false error is more problematic than not locking properly
|
|
||||||
// on corner-case systems.
|
|
||||||
if (lock->removeStaleLockFile() == false || lock->tryLock() == false)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
QString VApplication::translationsPath() const
|
QString VApplication::translationsPath() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,9 +39,6 @@ class VApplication;// use in define
|
||||||
class VMainGraphicsView;
|
class VMainGraphicsView;
|
||||||
class VPattern;
|
class VPattern;
|
||||||
class QFile;
|
class QFile;
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
|
|
||||||
class QLockFile;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(qApp)
|
#if defined(qApp)
|
||||||
#undef qApp
|
#undef qApp
|
||||||
|
@ -62,10 +59,6 @@ public:
|
||||||
|
|
||||||
void InitOptions();
|
void InitOptions();
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
|
|
||||||
static bool TryLock(QLockFile *lock);
|
|
||||||
#endif //QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
|
|
||||||
|
|
||||||
QString translationsPath() const;
|
QString translationsPath() const;
|
||||||
|
|
||||||
QTimer *getAutoSaveTimer() const;
|
QTimer *getAutoSaveTimer() const;
|
||||||
|
|
|
@ -43,6 +43,9 @@ namespace Ui
|
||||||
}
|
}
|
||||||
|
|
||||||
class VToolOptionsPropertyBrowser;
|
class VToolOptionsPropertyBrowser;
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
class QLockFile;
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The MainWindow class main windows.
|
* @brief The MainWindow class main windows.
|
||||||
|
|
|
@ -29,6 +29,10 @@
|
||||||
#include "vabstractapplication.h"
|
#include "vabstractapplication.h"
|
||||||
#include "../vmisc/def.h"
|
#include "../vmisc/def.h"
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
# include <QLockFile>
|
||||||
|
#endif
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
VAbstractApplication::VAbstractApplication(int &argc, char **argv)
|
VAbstractApplication::VAbstractApplication(int &argc, char **argv)
|
||||||
:QApplication(argc, argv),
|
:QApplication(argc, argv),
|
||||||
|
@ -112,3 +116,43 @@ double VAbstractApplication::fromPixel(double pix) const
|
||||||
{
|
{
|
||||||
return FromPixel(pix, _patternUnit);
|
return FromPixel(pix, _patternUnit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
bool VAbstractApplication::TryLock(QLockFile *lock)
|
||||||
|
{
|
||||||
|
if (lock == nullptr)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lock->tryLock())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (lock->error() == QLockFile::LockFailedError)
|
||||||
|
{
|
||||||
|
// This happens if a stale lock file exists and another process uses that PID.
|
||||||
|
// Try removing the stale file, which will fail if a real process is holding a
|
||||||
|
// file-level lock. A false error is more problematic than not locking properly
|
||||||
|
// on corner-case systems.
|
||||||
|
if (lock->removeStaleLockFile() == false || lock->tryLock() == false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
|
@ -39,6 +39,9 @@ class VTranslateVars;
|
||||||
class VAbstractPattern;
|
class VAbstractPattern;
|
||||||
class VMainGraphicsView;
|
class VMainGraphicsView;
|
||||||
class QUndoStack;
|
class QUndoStack;
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
class QLockFile;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(qApp)
|
#if defined(qApp)
|
||||||
#undef qApp
|
#undef qApp
|
||||||
|
@ -86,6 +89,10 @@ public:
|
||||||
|
|
||||||
QUndoStack *getUndoStack() const;
|
QUndoStack *getUndoStack() const;
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
static bool TryLock(QLockFile *lock);
|
||||||
|
#endif //QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QUndoStack *undoStack;
|
QUndoStack *undoStack;
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,8 @@
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
|
||||||
const QString VTapeSettings::SettingPathsTemplates = QStringLiteral("paths/templates");
|
const QString VTapeSettings::SettingPathsTemplates = QStringLiteral("paths/templates");
|
||||||
|
const QString VTapeSettings::SettingDataBaseGeometry = QStringLiteral("database/geometry");
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
VTapeSettings::VTapeSettings(Format format, Scope scope, const QString &organization, const QString &application,
|
VTapeSettings::VTapeSettings(Format format, Scope scope, const QString &organization, const QString &application,
|
||||||
|
@ -161,3 +162,15 @@ void VTapeSettings::SetPathTemplate(const QString &value)
|
||||||
{
|
{
|
||||||
setValue(SettingPathsTemplates, value);
|
setValue(SettingPathsTemplates, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
QByteArray VTapeSettings::GetDataBaseGeometry() const
|
||||||
|
{
|
||||||
|
return value(SettingDataBaseGeometry).toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
void VTapeSettings::SetDataBaseGeometry(const QByteArray &value)
|
||||||
|
{
|
||||||
|
setValue(SettingDataBaseGeometry, value);
|
||||||
|
}
|
||||||
|
|
|
@ -44,10 +44,14 @@ public:
|
||||||
QString GetPathTemplate() const;
|
QString GetPathTemplate() const;
|
||||||
void SetPathTemplate(const QString &value);
|
void SetPathTemplate(const QString &value);
|
||||||
|
|
||||||
|
QByteArray GetDataBaseGeometry() const;
|
||||||
|
void SetDataBaseGeometry(const QByteArray &value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(VTapeSettings)
|
Q_DISABLE_COPY(VTapeSettings)
|
||||||
|
|
||||||
static const QString SettingPathsTemplates;
|
static const QString SettingPathsTemplates;
|
||||||
|
static const QString SettingDataBaseGeometry;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VTAPESETTINGS_H
|
#endif // VTAPESETTINGS_H
|
||||||
|
|
Loading…
Reference in New Issue
Block a user