New viewer Open logic(only the first time)
This commit is contained in:
@@ -37,7 +37,7 @@ public:
|
|||||||
* @param dir
|
* @param dir
|
||||||
* @param openMode
|
* @param openMode
|
||||||
*/
|
*/
|
||||||
void preRead(const std::string &dir, SeriesOpenMode openMode);
|
void preReadNewFile(const std::string &dir, SeriesOpenMode openMode);
|
||||||
UniqueIDInfo_t* createUniqueID(const std::string &dicomName, SeriesOpenMode openMode);
|
UniqueIDInfo_t* createUniqueID(const std::string &dicomName, SeriesOpenMode openMode);
|
||||||
bool IsDuplicate(UniqueIDInfo_t* unique);
|
bool IsDuplicate(UniqueIDInfo_t* unique);
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ class vtkRenderWindow;
|
|||||||
class vtkRenderer;
|
class vtkRenderer;
|
||||||
class vtkRenderWindowInteractor;
|
class vtkRenderWindowInteractor;
|
||||||
|
|
||||||
|
class ExtendMedicalImageProperties;
|
||||||
class MeasureStore;
|
class MeasureStore;
|
||||||
|
|
||||||
#define IN_TEST_MODE
|
#define IN_TEST_MODE
|
||||||
@@ -56,7 +57,7 @@ public:
|
|||||||
}
|
}
|
||||||
void updateCornerInfo(int index);
|
void updateCornerInfo(int index);
|
||||||
void updateCornerInfoAll();
|
void updateCornerInfoAll();
|
||||||
void initCornerInfo(DicomTagInfo_t *pSeriesTags);
|
void initCornerInfo(ExtendMedicalImageProperties *pSeriesTags);
|
||||||
void updateOrienInfo(TransFormType type);
|
void updateOrienInfo(TransFormType type);
|
||||||
void setUpImageViewer();
|
void setUpImageViewer();
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <QFrame>
|
#include <QFrame>
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
#include "global/QGlobals.h"
|
#include "global/QGlobals.h"
|
||||||
@@ -28,8 +28,8 @@ public:
|
|||||||
void setCurrentView(DicomImageView *view);
|
void setCurrentView(DicomImageView *view);
|
||||||
void emptyCurrentView();
|
void emptyCurrentView();
|
||||||
|
|
||||||
void replaceViewWithSerie(UniqueIDInfo_t* unique_info, DicomTagInfo_t* tag_info,
|
void replaceViewWithSerie(UniqueIDInfo_t* unique_info,
|
||||||
DicomImageView* curV, SeriesInstance* old = nullptr, bool copy = false);
|
DicomImageView* curV = nullptr);
|
||||||
|
|
||||||
//fusion
|
//fusion
|
||||||
void toggleViewWithFusion();
|
void toggleViewWithFusion();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "QDicomViewer.h"
|
#include "QDicomViewer.h"
|
||||||
#include "global/include_all.h"
|
#include "global/include_all.h"
|
||||||
#include "base/SeriesImageSet.h"
|
#include "base/SeriesImageSet.h"
|
||||||
#include "view/subview/gridpopwidget.h"
|
#include "view/subview/gridpopwidget.h"
|
||||||
@@ -1001,8 +1001,7 @@ void QDicomViewer::openDICOMFromPACS(int err, std::string dirName)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QDicomViewer::openAndDrawDICOM(const std::string& dicomName, SeriesOpenMode openMode)
|
void QDicomViewer::openAndDrawDICOM(const std::string& dicomName, SeriesOpenMode openMode) {
|
||||||
{
|
|
||||||
|
|
||||||
displayThumbnailBar(true);
|
displayThumbnailBar(true);
|
||||||
|
|
||||||
@@ -1010,7 +1009,7 @@ void QDicomViewer::openAndDrawDICOM(const std::string& dicomName, SeriesOpenMode
|
|||||||
DicomLoader *helper = DicomLoader::GetInstance();
|
DicomLoader *helper = DicomLoader::GetInstance();
|
||||||
|
|
||||||
//load image and tag
|
//load image and tag
|
||||||
helper->preRead(dicomName, openMode);
|
helper->preReadNewFile(dicomName, openMode);
|
||||||
|
|
||||||
|
|
||||||
UniqueIDInfo_t *unique = helper->createUniqueID(dicomName, openMode);
|
UniqueIDInfo_t *unique = helper->createUniqueID(dicomName, openMode);
|
||||||
@@ -1019,8 +1018,7 @@ void QDicomViewer::openAndDrawDICOM(const std::string& dicomName, SeriesOpenMode
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//判断是否重复,并设置AddDicomType
|
//判断是否重复,并设置AddDicomType
|
||||||
if (helper->IsDuplicate(unique))
|
if (helper->IsDuplicate(unique)) {
|
||||||
{
|
|
||||||
this->statusBar()->showMessage(tr("Already Exists!"));
|
this->statusBar()->showMessage(tr("Already Exists!"));
|
||||||
|
|
||||||
//need to delete UniqueID first
|
//need to delete UniqueID first
|
||||||
@@ -1034,64 +1032,11 @@ void QDicomViewer::openAndDrawDICOM(const std::string& dicomName, SeriesOpenMode
|
|||||||
//You have to judge AddDicomType first!
|
//You have to judge AddDicomType first!
|
||||||
AddDicomType type = helper->getAddDicomType();
|
AddDicomType type = helper->getAddDicomType();
|
||||||
|
|
||||||
DicomImageView* curV = nullptr;
|
|
||||||
//
|
|
||||||
// if (type == AddDicomType::OVERRIDE_LEVEL)
|
|
||||||
// disable override first
|
|
||||||
if (false)
|
|
||||||
{
|
|
||||||
/************************************************************************/
|
|
||||||
/* 1.Get multiple relevant windows
|
|
||||||
* 2.createSeries and addSeries one by one
|
|
||||||
* 3.Get the return replaced instance,delete it!
|
|
||||||
/************************************************************************/
|
|
||||||
QList<DicomImageView*> view_list;
|
|
||||||
ui->viewContainer->getRelevantViewList(*unique, view_list);
|
|
||||||
|
|
||||||
//only the first conducts raw mode
|
ui->viewContainer->replaceViewWithSerie(unique);
|
||||||
//the following conducts copy mode
|
|
||||||
bool copy = false;
|
|
||||||
|
|
||||||
for (DicomImageView* v : view_list)
|
|
||||||
{
|
|
||||||
//copy mode
|
|
||||||
SeriesInstance* series = helper->createSeries(unique, tag_info, v->getRenWin(), copy);
|
|
||||||
//after series is properly set, call addSeriesInstance
|
|
||||||
SeriesInstance* to_del = helper->addSeriesInstance(series);
|
|
||||||
if (false == copy)
|
|
||||||
{
|
|
||||||
ui->thumbnailBar->updateThumbnailBar();
|
|
||||||
//d_unique = to_del->getUniqueID();
|
|
||||||
//d_tag_info = to_del->getDicomTagInfo();
|
|
||||||
copy = true;
|
|
||||||
}
|
|
||||||
v->setDicomImageView(series);
|
|
||||||
v->Render();
|
|
||||||
// not use deleteSeries here
|
|
||||||
delete to_del;
|
|
||||||
//curV = v;
|
|
||||||
}
|
|
||||||
//it is time to release memory of series
|
|
||||||
//delete d_unique;
|
|
||||||
//delete d_tag_info;
|
|
||||||
curV = view_list.at(view_list.size() - 1);
|
|
||||||
ui->viewContainer->setCurrentView(curV);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//only add new data
|
|
||||||
curV = ui->viewContainer->getCurrentView();
|
|
||||||
|
|
||||||
SeriesInstance* old = nullptr;
|
|
||||||
if (curV->HasSeries())
|
|
||||||
{
|
|
||||||
old = curV->getSeriesInstance();
|
|
||||||
}
|
|
||||||
ui->viewContainer->replaceViewWithSerie(unique, tag_info, curV, old);
|
|
||||||
//view clicked will notify thumbnailbar update
|
//view clicked will notify thumbnailbar update
|
||||||
ui->thumbnailBar->updateThumbnailBar();
|
ui->thumbnailBar->updateThumbnailBar();
|
||||||
ui->viewContainer->setCurrentView(curV);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -306,10 +306,7 @@ SeriesInfo_t* DicomLoader::getSerieInfo(const UniqueIDInfo &uniqueID)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return nullptr;
|
void DicomLoader::preReadNewFile(const std::string &dir, SeriesOpenMode openMode)
|
||||||
}
|
|
||||||
|
|
||||||
void DicomLoader::preRead(const std::string &dir, SeriesOpenMode openMode)
|
|
||||||
{
|
{
|
||||||
DICOMDirectoryHelper DICOMHelper;
|
DICOMDirectoryHelper DICOMHelper;
|
||||||
if (openMode == FILE_OPEN_MODE)
|
if (openMode == FILE_OPEN_MODE)
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
#include "MeasureStore.h"
|
#include "MeasureStore.h"
|
||||||
#include "vtkTextActor.h"
|
#include "vtkTextActor.h"
|
||||||
#include "vtkTextProperty.h"
|
#include "vtkTextProperty.h"
|
||||||
#include "vtkLookupTable.h"
|
#include "ExtendMedicalImageProperties.h"
|
||||||
#include "RulerLegendActor.h"
|
#include "RulerLegendActor.h"
|
||||||
#include "ColorMapReader.h"
|
#include "ColorMapReader.h"
|
||||||
|
|
||||||
@@ -1199,44 +1199,41 @@ void infinitiViewer::initTopLeftCornerInfo(const std::string& lbl_ser_num, const
|
|||||||
m_cornerInfo.ConstAnno[TOP_LEFT].append(ser_num);
|
m_cornerInfo.ConstAnno[TOP_LEFT].append(ser_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
void infinitiViewer::initCornerInfo(DicomTagInfo_t* pSeriesTags)
|
void infinitiViewer::initCornerInfo(ExtendMedicalImageProperties* pSeries)
|
||||||
{
|
{
|
||||||
|
if(pSeries->GetNumberOfWindowLevelPresets()>0)
|
||||||
|
{
|
||||||
|
double * wwwl = pSeries->GetNthWindowLevelPreset(0);
|
||||||
|
m_cornerInfo.win_level = (int)wwwl[1];
|
||||||
|
m_cornerInfo.win_width = (int)wwwl[0];
|
||||||
|
}
|
||||||
|
|
||||||
m_cornerInfo.win_level = pSeriesTags->WL;
|
char buffer [sizeof(long)*8+1];
|
||||||
//m_cornerInfo.ConstAnno[BOTTOM_RIGHT].append("WL ");
|
const char* s = ltoa(pSeries->GetFileNames()->size(), buffer, 10);
|
||||||
//m_cornerInfo.ConstAnno[BOTTOM_RIGHT].append(std::to_string(pSeriesTags->WL));
|
m_cornerInfo.ConstAnno[TOP_LEFT].append(buffer);
|
||||||
//m_cornerInfo.ConstAnno[BOTTOM_RIGHT].append("\n");
|
|
||||||
|
|
||||||
|
|
||||||
m_cornerInfo.win_width = pSeriesTags->WW;
|
|
||||||
//m_cornerInfo.ConstAnno[BOTTOM_RIGHT].append("WW ");
|
|
||||||
//m_cornerInfo.ConstAnno[BOTTOM_RIGHT].append(std::to_string(pSeriesTags->WW));
|
|
||||||
|
|
||||||
|
|
||||||
m_cornerInfo.ConstAnno[TOP_LEFT].append(pSeriesTags->lbl_ser_num);
|
|
||||||
m_cornerInfo.ConstAnno[TOP_LEFT].append(" ");
|
m_cornerInfo.ConstAnno[TOP_LEFT].append(" ");
|
||||||
m_cornerInfo.ConstAnno[TOP_LEFT].append(pSeriesTags->m_SeriesNumber);
|
m_cornerInfo.ConstAnno[TOP_LEFT].append(pSeries->GetSeriesNumber());
|
||||||
|
|
||||||
m_cornerInfo.ConstAnno[TOP_RIGHT].append(pSeriesTags->m_PatientName);
|
m_cornerInfo.ConstAnno[TOP_RIGHT].append(pSeries->GetPatientName());
|
||||||
m_cornerInfo.ConstAnno[TOP_RIGHT].append("\n");
|
m_cornerInfo.ConstAnno[TOP_RIGHT].append("\n");
|
||||||
m_cornerInfo.ConstAnno[TOP_RIGHT].append(pSeriesTags->m_StudyDescription);
|
m_cornerInfo.ConstAnno[TOP_RIGHT].append(pSeries->GetStudyDescription());
|
||||||
m_cornerInfo.ConstAnno[TOP_RIGHT].append("\n");
|
m_cornerInfo.ConstAnno[TOP_RIGHT].append("\n");
|
||||||
m_cornerInfo.ConstAnno[TOP_RIGHT].append(pSeriesTags->m_SeriesDescription);
|
m_cornerInfo.ConstAnno[TOP_RIGHT].append(pSeries->GetSeriesDescription());
|
||||||
m_cornerInfo.ConstAnno[TOP_RIGHT].append("\n");
|
m_cornerInfo.ConstAnno[TOP_RIGHT].append("\n");
|
||||||
m_cornerInfo.ConstAnno[TOP_RIGHT].append(pSeriesTags->m_Institution);
|
m_cornerInfo.ConstAnno[TOP_RIGHT].append(pSeries->GetInstitutionName());
|
||||||
m_cornerInfo.ConstAnno[TOP_RIGHT].append("\n");
|
m_cornerInfo.ConstAnno[TOP_RIGHT].append("\n");
|
||||||
|
|
||||||
|
|
||||||
m_cornerInfo.ConstAnno[TOP_RIGHT_PRIVACY].append("****");
|
m_cornerInfo.ConstAnno[TOP_RIGHT_PRIVACY].append("****");
|
||||||
m_cornerInfo.ConstAnno[TOP_RIGHT_PRIVACY].append("\n");
|
m_cornerInfo.ConstAnno[TOP_RIGHT_PRIVACY].append("\n");
|
||||||
m_cornerInfo.ConstAnno[TOP_RIGHT_PRIVACY].append(pSeriesTags->m_StudyDescription);
|
m_cornerInfo.ConstAnno[TOP_RIGHT_PRIVACY].append(pSeries->GetStudyDescription());
|
||||||
m_cornerInfo.ConstAnno[TOP_RIGHT_PRIVACY].append("\n");
|
m_cornerInfo.ConstAnno[TOP_RIGHT_PRIVACY].append("\n");
|
||||||
m_cornerInfo.ConstAnno[TOP_RIGHT_PRIVACY].append(pSeriesTags->m_SeriesDescription);
|
m_cornerInfo.ConstAnno[TOP_RIGHT_PRIVACY].append(pSeries->GetSeriesDescription());
|
||||||
m_cornerInfo.ConstAnno[TOP_RIGHT_PRIVACY].append("\n");
|
m_cornerInfo.ConstAnno[TOP_RIGHT_PRIVACY].append("\n");
|
||||||
m_cornerInfo.ConstAnno[TOP_RIGHT_PRIVACY].append("****");
|
m_cornerInfo.ConstAnno[TOP_RIGHT_PRIVACY].append("****");
|
||||||
m_cornerInfo.ConstAnno[TOP_RIGHT_PRIVACY].append("\n");
|
m_cornerInfo.ConstAnno[TOP_RIGHT_PRIVACY].append("\n");
|
||||||
|
|
||||||
std::vector<std::string>* orien_list = orientationHelper::getOrientationStrList(pSeriesTags->m_orientation);
|
std::vector<std::string>* orien_list = orientationHelper::getOrientationStrList("");
|
||||||
//currently only adapt to USCT Format
|
//currently only adapt to USCT Format
|
||||||
if (orien_list)
|
if (orien_list)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -39,10 +39,7 @@ DicomImageView::DicomImageView(QWidget* parent)
|
|||||||
_glWidt = new QVTKOpenGLNativeWidget(wrapper);
|
_glWidt = new QVTKOpenGLNativeWidget(wrapper);
|
||||||
|
|
||||||
m_glrenWin = vtkSmartPointer <vtkGenericOpenGLRenderWindow>::New();
|
m_glrenWin = vtkSmartPointer <vtkGenericOpenGLRenderWindow>::New();
|
||||||
//m_glrenWin->SetOffScreenRendering(1); //for offscreen rendering
|
|
||||||
_glWidt->SetRenderWindow(m_glrenWin);//set up interacte
|
_glWidt->SetRenderWindow(m_glrenWin);//set up interacte
|
||||||
//in order to visit in both way!
|
|
||||||
// _glWidt->SetImageView(this);
|
|
||||||
|
|
||||||
controlLayout->addWidget(_glWidt, 0, 0);
|
controlLayout->addWidget(_glWidt, 0, 0);
|
||||||
|
|
||||||
@@ -650,8 +647,14 @@ void DicomImageView::removeViewWithMeasure()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void DicomImageView::setDicomImageView(SeriesInstance *series)
|
void DicomImageView::setDicomImageView(SeriesImageSet *series)
|
||||||
{
|
{
|
||||||
|
if (!_ImageViewer){
|
||||||
|
|
||||||
|
_ImageViewer = infinitiViewer::New();
|
||||||
|
_ImageViewer->SetRenderWindow(m_glrenWin);
|
||||||
|
_ImageViewer->SetupInteractor(m_glrenWin->GetInteractor());
|
||||||
|
}
|
||||||
//series->setVTKOpenGLNativeWidget(this->_glView);
|
//series->setVTKOpenGLNativeWidget(this->_glView);
|
||||||
CopyFromSeries(series);
|
CopyFromSeries(series);
|
||||||
//whenver change instance,set scroll value to zero
|
//whenver change instance,set scroll value to zero
|
||||||
@@ -663,11 +666,7 @@ void DicomImageView::setDicomImageView(SeriesInstance *series)
|
|||||||
|
|
||||||
bool DicomImageView::HasSeries()
|
bool DicomImageView::HasSeries()
|
||||||
{
|
{
|
||||||
if (nullptr == _Series)
|
return _Series ;
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
void DicomImageView::Render()
|
void DicomImageView::Render()
|
||||||
{
|
{
|
||||||
@@ -683,12 +682,19 @@ void DicomImageView::Render()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DicomImageView::CopyFromSeries(SeriesInstance *series)
|
void DicomImageView::CopyFromSeries(SeriesImageSet *series)
|
||||||
{
|
{
|
||||||
_Series = series;
|
_Series = series;
|
||||||
_ImageViewer = series->getImageViewer2();
|
|
||||||
//_CornerAnno = _ImageViewer->GetvtkCornerAnnotation();
|
|
||||||
|
|
||||||
|
_ImageViewer->SetInputData(_Series->GetData());
|
||||||
|
//_CornerAnno = _ImageViewer->GetvtkCornerAnnotation();
|
||||||
|
_ImageViewer->initCornerInfo(series->GetProperty());
|
||||||
|
_ImageViewer->setUpImageViewer();
|
||||||
|
|
||||||
|
|
||||||
|
// vtkCamera* cam = _ImageViewer->GetRenderer()->GetActiveCamera();
|
||||||
|
// m_extent = m_image->GetDimensions()[0] * m_pSeriesTags->spacing[0] * 0.5;
|
||||||
|
// cam->SetParallelScale(m_extent);
|
||||||
|
|
||||||
//create some callbacks
|
//create some callbacks
|
||||||
//m_syncEventCallback = vtkCallbackCommand::New();
|
//m_syncEventCallback = vtkCallbackCommand::New();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "viewcontainerwidget.h"
|
#include "viewcontainerwidget.h"
|
||||||
#include "thumbnailImage.h"
|
#include "thumbnailImage.h"
|
||||||
#include "DicomLoader.h"
|
#include "DicomLoader.h"
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
@@ -207,11 +207,9 @@ void ViewContainerWidget::Slot_SyncEvent(DicomImageView *view, int interactionMo
|
|||||||
void ViewContainerWidget::SetInteractionMode(int InteractionMode)
|
void ViewContainerWidget::SetInteractionMode(int InteractionMode)
|
||||||
{
|
{
|
||||||
for (auto *v : view_list_) {
|
for (auto *v : view_list_) {
|
||||||
QVTKOpenGLNativeWidget*gl_w = v->getGLWidget();
|
if (v->getImageViewer())
|
||||||
if (gl_w->GetRenderWindow() && gl_w->GetRenderWindow()->GetInteractor() && v->HasSeries())
|
|
||||||
{
|
{
|
||||||
infinitiViewer* viewer = v->getSeriesInstance()->getImageViewer2();
|
v->getImageViewer()->GetInteractorStyle()->SetInteractionModeFromEnum(InteractionMode);
|
||||||
viewer->GetInteractorStyle()->SetInteractionModeFromEnum(InteractionMode);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -397,7 +395,7 @@ void ViewContainerWidget::Slot_DragDropEvent(DicomImageView *view, thumbnailImag
|
|||||||
{
|
{
|
||||||
old = view->getSeriesInstance();
|
old = view->getSeriesInstance();
|
||||||
}
|
}
|
||||||
replaceViewWithSerie(serie_info->unique_info, serie_info->tag_info, view, old, copy);
|
replaceViewWithSerie(serie_info->unique_info, view);
|
||||||
setCurrentView(view);
|
setCurrentView(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -416,22 +414,20 @@ void ViewContainerWidget::Slot_ThumbnailClickEvent(thumbnailImage* tb)
|
|||||||
{
|
{
|
||||||
old = view->getSeriesInstance();
|
old = view->getSeriesInstance();
|
||||||
}
|
}
|
||||||
replaceViewWithSerie(serie_info->unique_info, serie_info->tag_info, view, old, copy);
|
replaceViewWithSerie(serie_info->unique_info, view);
|
||||||
setCurrentView(view);
|
setCurrentView(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewContainerWidget::replaceViewWithSerie(UniqueIDInfo_t* unique_info, DicomTagInfo_t* tag_info, DicomImageView* curV, SeriesInstance* old, bool copy)
|
void ViewContainerWidget::replaceViewWithSerie(UniqueIDInfo_t* unique_info, DicomImageView* curV)
|
||||||
{
|
{
|
||||||
|
if (!curV)
|
||||||
|
{
|
||||||
|
curV= getCurrentView();
|
||||||
|
}
|
||||||
curV->removeViewWithFusion();
|
curV->removeViewWithFusion();
|
||||||
|
|
||||||
DicomLoader *helper = DicomLoader::GetInstance();
|
DicomLoader *helper = DicomLoader::GetInstance();
|
||||||
curV->setDicomImageView(helper->createSeries(unique_info));
|
curV->setDicomImageView(helper->createSeries(unique_info));
|
||||||
curV->Render();
|
curV->Render();
|
||||||
//delete old after new instance render
|
|
||||||
if (old)
|
|
||||||
{
|
|
||||||
helper->deleteSeriesInstance(old);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewContainerWidget::toggleViewWithFusion()
|
void ViewContainerWidget::toggleViewWithFusion()
|
||||||
|
|||||||
Reference in New Issue
Block a user