mirror of
https://github.com/DreamSourceLab/DSView.git
synced 2025-02-02 13:52:55 +08:00
Perfect solution to window recovery issues
This commit is contained in:
parent
288a459c93
commit
decde39462
@ -199,8 +199,10 @@ static void _loadFrame(FrameOptions &o, QSettings &st)
|
|||||||
getFiled("top", st, o.top, 0);
|
getFiled("top", st, o.top, 0);
|
||||||
getFiled("right", st, o.right, 0);
|
getFiled("right", st, o.right, 0);
|
||||||
getFiled("bottom", st, o.bottom, 0);
|
getFiled("bottom", st, o.bottom, 0);
|
||||||
getFiled("x", st, o.x, -10000);
|
getFiled("x", st, o.x, NO_POINT_VALUE);
|
||||||
getFiled("y", st, o.y, -10000);
|
getFiled("y", st, o.y, NO_POINT_VALUE);
|
||||||
|
getFiled("ox", st, o.ox, NO_POINT_VALUE);
|
||||||
|
getFiled("oy", st, o.oy, NO_POINT_VALUE);
|
||||||
|
|
||||||
_loadDockOptions(o._logicDock, st, "LOGIC_DOCK");
|
_loadDockOptions(o._logicDock, st, "LOGIC_DOCK");
|
||||||
_loadDockOptions(o._analogDock, st, "ANALOG_DOCK");
|
_loadDockOptions(o._analogDock, st, "ANALOG_DOCK");
|
||||||
@ -232,6 +234,8 @@ static void _saveFrame(FrameOptions &o, QSettings &st)
|
|||||||
setFiled("bottom", st, o.bottom);
|
setFiled("bottom", st, o.bottom);
|
||||||
setFiled("x", st, o.x);
|
setFiled("x", st, o.x);
|
||||||
setFiled("y", st, o.y);
|
setFiled("y", st, o.y);
|
||||||
|
setFiled("ox", st, o.ox);
|
||||||
|
setFiled("oy", st, o.oy);
|
||||||
|
|
||||||
st.setValue("windowState", o.windowState);
|
st.setValue("windowState", o.windowState);
|
||||||
|
|
||||||
|
@ -54,6 +54,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
#define APP_CONFIG_VERSION 3
|
#define APP_CONFIG_VERSION 3
|
||||||
|
#define NO_POINT_VALUE -10000
|
||||||
|
|
||||||
struct AppOptions
|
struct AppOptions
|
||||||
{
|
{
|
||||||
@ -93,6 +94,8 @@ struct FrameOptions
|
|||||||
int bottom;
|
int bottom;
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
|
int ox;
|
||||||
|
int oy;
|
||||||
bool isMax;
|
bool isMax;
|
||||||
QByteArray windowState;
|
QByteArray windowState;
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
#include <QFont>
|
#include <QFont>
|
||||||
|
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
#endif
|
#endif
|
||||||
@ -69,6 +70,10 @@ MainFrame::MainFrame()
|
|||||||
_titleBar = NULL;
|
_titleBar = NULL;
|
||||||
_mainWindow = NULL;
|
_mainWindow = NULL;
|
||||||
_is_native_title = false;
|
_is_native_title = false;
|
||||||
|
_is_resize_ready = false;
|
||||||
|
_move_event_count = false;
|
||||||
|
_is_resize_reset_timer = false;
|
||||||
|
_resize_event_count = 0;
|
||||||
|
|
||||||
AppControl::Instance()->SetTopWindow(this);
|
AppControl::Instance()->SetTopWindow(this);
|
||||||
|
|
||||||
@ -81,7 +86,7 @@ MainFrame::MainFrame()
|
|||||||
_is_native_title = false;
|
_is_native_title = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_is_native_title = true;
|
//_is_native_title = true;
|
||||||
|
|
||||||
setMinimumWidth(MainWindow::Min_Width);
|
setMinimumWidth(MainWindow::Min_Width);
|
||||||
setMinimumHeight(MainWindow::Min_Height);
|
setMinimumHeight(MainWindow::Min_Height);
|
||||||
@ -173,6 +178,12 @@ MainFrame::MainFrame()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(unfreezing()));
|
connect(&_timer, SIGNAL(timeout()), this, SLOT(unfreezing()));
|
||||||
|
|
||||||
|
QTimer::singleShot(500, this, [this](){
|
||||||
|
_is_resize_ready = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
installEventFilter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainFrame::resizeEvent(QResizeEvent *event)
|
void MainFrame::resizeEvent(QResizeEvent *event)
|
||||||
@ -185,9 +196,25 @@ void MainFrame::resizeEvent(QResizeEvent *event)
|
|||||||
|
|
||||||
if (isMaximized()) {
|
if (isMaximized()) {
|
||||||
hide_border();
|
hide_border();
|
||||||
} else {
|
|
||||||
show_border();
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
show_border();
|
||||||
|
|
||||||
|
_resize_event_count++;
|
||||||
|
|
||||||
|
if (_resize_event_count >= 2){
|
||||||
|
saveNormalRegion();
|
||||||
|
}
|
||||||
|
else if (!_is_resize_reset_timer){
|
||||||
|
_is_resize_reset_timer = true;
|
||||||
|
|
||||||
|
QTimer::singleShot(500, this, [this](){
|
||||||
|
_is_resize_reset_timer = false;
|
||||||
|
_resize_event_count = 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_titleBar->setRestoreButton(isMaximized());
|
_titleBar->setRestoreButton(isMaximized());
|
||||||
_layout->update();
|
_layout->update();
|
||||||
}
|
}
|
||||||
@ -197,10 +224,10 @@ void MainFrame::closeEvent(QCloseEvent *event)
|
|||||||
writeSettings();
|
writeSettings();
|
||||||
|
|
||||||
if (_mainWindow->able_to_close()){
|
if (_mainWindow->able_to_close()){
|
||||||
event->accept();
|
event->accept();
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
event->ignore();
|
event->ignore();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,28 +277,61 @@ void MainFrame::showNormal()
|
|||||||
void MainFrame::showMaximized()
|
void MainFrame::showMaximized()
|
||||||
{
|
{
|
||||||
hide_border();
|
hide_border();
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
float sk = QGuiApplication::primaryScreen()->logicalDotsPerInch() / 96;
|
|
||||||
if (sk >= 1.5)
|
|
||||||
{
|
|
||||||
auto rect = QGuiApplication::primaryScreen()->availableGeometry();
|
|
||||||
// this->move(rect.left(), rect.top());
|
|
||||||
//this->resize(rect.width(), rect.height());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QFrame::showMaximized();
|
QFrame::showMaximized();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainFrame::showMinimized()
|
void MainFrame::showMinimized()
|
||||||
{
|
{
|
||||||
writeSettings();
|
|
||||||
QFrame::showMinimized();
|
QFrame::showMinimized();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainFrame::changeEvent(QEvent *event)
|
||||||
|
{
|
||||||
|
if (event->type() == QEvent::WindowStateChange && _is_resize_ready) {
|
||||||
|
QWindowStateChangeEvent *stateChangeEvent = static_cast<QWindowStateChangeEvent*>(event);
|
||||||
|
if (stateChangeEvent->oldState() & Qt::WindowMaximized
|
||||||
|
&& !(windowState() & Qt::WindowMaximized)) {
|
||||||
|
moveToNormal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QFrame::changeEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainFrame::moveToNormal()
|
||||||
|
{
|
||||||
|
AppConfig &app = AppConfig::Instance();
|
||||||
|
int left = app.frameOptions.left;
|
||||||
|
int top = app.frameOptions.top;
|
||||||
|
int right = app.frameOptions.right;
|
||||||
|
int bottom = app.frameOptions.bottom;
|
||||||
|
int x = app.frameOptions.x;
|
||||||
|
int y = app.frameOptions.y;
|
||||||
|
|
||||||
|
if (_is_native_title && y != NO_POINT_VALUE){
|
||||||
|
move(x, y);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
move(left, top);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (right - left > 0){
|
||||||
|
resize(right - left, bottom - top);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool MainFrame::eventFilter(QObject *object, QEvent *event)
|
bool MainFrame::eventFilter(QObject *object, QEvent *event)
|
||||||
{
|
{
|
||||||
|
if (event->type() == QEvent::Move && _is_resize_ready){
|
||||||
|
if (isMaximized() == false){
|
||||||
|
_move_event_count++;
|
||||||
|
if (_move_event_count >= 2){
|
||||||
|
saveNormalRegion();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QFrame::eventFilter(object, event);
|
||||||
|
}
|
||||||
|
_move_event_count = 0;
|
||||||
|
|
||||||
if (_is_native_title){
|
if (_is_native_title){
|
||||||
return QFrame::eventFilter(object, event);
|
return QFrame::eventFilter(object, event);
|
||||||
}
|
}
|
||||||
@ -351,7 +411,6 @@ bool MainFrame::eventFilter(QObject *object, QEvent *event)
|
|||||||
if (newHeight > minimumHeight())
|
if (newHeight > minimumHeight())
|
||||||
newTop = y0;
|
newTop = y0;
|
||||||
setGeometry(newLeft, newTop, newWidth, newHeight);
|
setGeometry(newLeft, newTop, newWidth, newHeight);
|
||||||
saveWindowRegion();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BottomLeft:
|
case BottomLeft:
|
||||||
@ -361,7 +420,6 @@ bool MainFrame::eventFilter(QObject *object, QEvent *event)
|
|||||||
if (newWidth > minimumWidth())
|
if (newWidth > minimumWidth())
|
||||||
newLeft = x0;
|
newLeft = x0;
|
||||||
setGeometry(newLeft, _dragStartGeometry.top(), newWidth, newHeight);
|
setGeometry(newLeft, _dragStartGeometry.top(), newWidth, newHeight);
|
||||||
saveWindowRegion();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TopRight:
|
case TopRight:
|
||||||
@ -371,21 +429,18 @@ bool MainFrame::eventFilter(QObject *object, QEvent *event)
|
|||||||
if (newHeight > minimumHeight())
|
if (newHeight > minimumHeight())
|
||||||
newTop = y0;
|
newTop = y0;
|
||||||
setGeometry(_dragStartGeometry.left(), newTop, newWidth, newHeight);
|
setGeometry(_dragStartGeometry.left(), newTop, newWidth, newHeight);
|
||||||
saveWindowRegion();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BottomRight:
|
case BottomRight:
|
||||||
newWidth = std::max(x0 - _dragStartGeometry.left(), minimumWidth());
|
newWidth = std::max(x0 - _dragStartGeometry.left(), minimumWidth());
|
||||||
newHeight = std::max(y0 - _dragStartGeometry.top(), minimumHeight());
|
newHeight = std::max(y0 - _dragStartGeometry.top(), minimumHeight());
|
||||||
setGeometry(_dragStartGeometry.left(), _dragStartGeometry.top(), newWidth, newHeight);
|
setGeometry(_dragStartGeometry.left(), _dragStartGeometry.top(), newWidth, newHeight);
|
||||||
saveWindowRegion();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Left:
|
case Left:
|
||||||
newWidth = _dragStartGeometry.right() - x0;
|
newWidth = _dragStartGeometry.right() - x0;
|
||||||
if (newWidth > minimumWidth()){
|
if (newWidth > minimumWidth()){
|
||||||
setGeometry(x0, _dragStartGeometry.top(), newWidth, height());
|
setGeometry(x0, _dragStartGeometry.top(), newWidth, height());
|
||||||
saveWindowRegion();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -393,7 +448,6 @@ bool MainFrame::eventFilter(QObject *object, QEvent *event)
|
|||||||
newWidth = x0 - _dragStartGeometry.left();
|
newWidth = x0 - _dragStartGeometry.left();
|
||||||
if (newWidth > minimumWidth()){
|
if (newWidth > minimumWidth()){
|
||||||
setGeometry(_dragStartGeometry.left(), _dragStartGeometry.top(), newWidth, height());
|
setGeometry(_dragStartGeometry.left(), _dragStartGeometry.top(), newWidth, height());
|
||||||
saveWindowRegion();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -401,7 +455,6 @@ bool MainFrame::eventFilter(QObject *object, QEvent *event)
|
|||||||
newHeight = _dragStartGeometry.bottom() - y0;
|
newHeight = _dragStartGeometry.bottom() - y0;
|
||||||
if (newHeight > minimumHeight()){
|
if (newHeight > minimumHeight()){
|
||||||
setGeometry(_dragStartGeometry.left(), y0,width(), newHeight);
|
setGeometry(_dragStartGeometry.left(), y0,width(), newHeight);
|
||||||
saveWindowRegion();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -409,7 +462,6 @@ bool MainFrame::eventFilter(QObject *object, QEvent *event)
|
|||||||
newHeight = y0 - _dragStartGeometry.top();
|
newHeight = y0 - _dragStartGeometry.top();
|
||||||
if (newHeight > minimumHeight()){
|
if (newHeight > minimumHeight()){
|
||||||
setGeometry(_dragStartGeometry.left(), _dragStartGeometry.top(), width(), newHeight);
|
setGeometry(_dragStartGeometry.left(), _dragStartGeometry.top(), width(), newHeight);
|
||||||
saveWindowRegion();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -442,8 +494,15 @@ bool MainFrame::eventFilter(QObject *object, QEvent *event)
|
|||||||
return QFrame::eventFilter(object, event);
|
return QFrame::eventFilter(object, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainFrame::saveWindowRegion()
|
void MainFrame::saveNormalRegion()
|
||||||
{
|
{
|
||||||
|
if (!_is_resize_ready){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isMaximized()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
AppConfig &app = AppConfig::Instance();
|
AppConfig &app = AppConfig::Instance();
|
||||||
QRect rc = geometry();
|
QRect rc = geometry();
|
||||||
app.frameOptions.left = rc.left();
|
app.frameOptions.left = rc.left();
|
||||||
@ -454,13 +513,16 @@ bool MainFrame::eventFilter(QObject *object, QEvent *event)
|
|||||||
QRect frc = frameGeometry();
|
QRect frc = frameGeometry();
|
||||||
app.frameOptions.x = frc.x();
|
app.frameOptions.x = frc.x();
|
||||||
app.frameOptions.y = frc.y();
|
app.frameOptions.y = frc.y();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainFrame::writeSettings()
|
void MainFrame::writeSettings()
|
||||||
{
|
{
|
||||||
AppConfig &app = AppConfig::Instance();
|
AppConfig &app = AppConfig::Instance();
|
||||||
app.frameOptions.isMax = isMaximized();
|
app.frameOptions.isMax = isMaximized();
|
||||||
saveWindowRegion();
|
|
||||||
|
if (isMaximized() == false && isVisible()){
|
||||||
|
saveNormalRegion();
|
||||||
|
}
|
||||||
app.SaveFrame();
|
app.SaveFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -481,21 +543,21 @@ void MainFrame::readSettings()
|
|||||||
int bottom = app.frameOptions.bottom;
|
int bottom = app.frameOptions.bottom;
|
||||||
int x = app.frameOptions.x;
|
int x = app.frameOptions.x;
|
||||||
int y = app.frameOptions.y;
|
int y = app.frameOptions.y;
|
||||||
|
int ox = app.frameOptions.ox;
|
||||||
|
int oy = app.frameOptions.oy;
|
||||||
|
|
||||||
bool bReset = false;
|
bool bReset = false;
|
||||||
int scrIndex = -1;
|
int scrIndex = -1;
|
||||||
QRect lstInrc = {0,0,0,0};
|
|
||||||
QRect winRc = {left, top, right, bottom};
|
QRect winRc = {left, top, right-left, bottom-top};
|
||||||
|
|
||||||
for (int i=0; i<QGuiApplication::screens().size(); i++){
|
for (int i=0; i<QGuiApplication::screens().size(); i++){
|
||||||
QRect rc = QGuiApplication::screens().at(i)->availableGeometry();
|
QRect rc = QGuiApplication::screens().at(i)->availableGeometry();
|
||||||
QRect inrc = winRc.intersected(rc);
|
QRect inrc = rc.intersected(winRc);
|
||||||
if (inrc.width() > 0){
|
|
||||||
if (inrc.width() > lstInrc.width()
|
if (inrc.width() > 10 || inrc.height() > 10){
|
||||||
|| inrc.height() > lstInrc.height()){
|
scrIndex = i;
|
||||||
lstInrc = inrc;
|
break;
|
||||||
scrIndex = i;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,8 +565,8 @@ void MainFrame::readSettings()
|
|||||||
bReset = true;
|
bReset = true;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
QRect trc = QGuiApplication::screens().at(scrIndex)->availableGeometry();
|
QRect rc = QGuiApplication::screens().at(scrIndex)->availableGeometry();
|
||||||
QRect inrc = trc.intersected(winRc);
|
QRect inrc = rc.intersected(winRc);
|
||||||
if (inrc.width() < 70 || inrc.height() < 70){
|
if (inrc.width() < 70 || inrc.height() < 70){
|
||||||
bReset = true;
|
bReset = true;
|
||||||
}
|
}
|
||||||
@ -512,26 +574,21 @@ void MainFrame::readSettings()
|
|||||||
|
|
||||||
if (app.frameOptions.isMax)
|
if (app.frameOptions.isMax)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
QRect rc;
|
||||||
if (y != -10000){
|
|
||||||
move(x, y);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
move(left, top);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
move(left, top);
|
|
||||||
#endif
|
|
||||||
showMaximized(); // show max by system api
|
|
||||||
|
|
||||||
QString scrName;
|
QString scrName;
|
||||||
|
|
||||||
if (scrIndex == -1){
|
if (scrIndex == -1){
|
||||||
|
rc = QGuiApplication::primaryScreen()->availableGeometry();
|
||||||
scrName = QGuiApplication::primaryScreen()->name();
|
scrName = QGuiApplication::primaryScreen()->name();
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
rc = QGuiApplication::screens().at(scrIndex)->availableGeometry();
|
||||||
scrName = QGuiApplication::screens().at(scrIndex)->name();
|
scrName = QGuiApplication::screens().at(scrIndex)->name();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
move(rc.left(), rc.top());
|
||||||
|
|
||||||
|
showMaximized(); // show max by system api
|
||||||
dsv_info("show as max, screen:%s", scrName.toStdString().c_str());
|
dsv_info("show as max, screen:%s", scrName.toStdString().c_str());
|
||||||
}
|
}
|
||||||
else if (bReset)
|
else if (bReset)
|
||||||
@ -561,7 +618,7 @@ void MainFrame::readSettings()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (y != -10000){
|
if (y != NO_POINT_VALUE){
|
||||||
move(x, y);
|
move(x, y);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@ -571,7 +628,9 @@ void MainFrame::readSettings()
|
|||||||
move(left, top);
|
move(left, top);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
resize(right - left, bottom - top);
|
if (right - left > 0){
|
||||||
|
resize(right - left, bottom - top);
|
||||||
|
}
|
||||||
|
|
||||||
dsv_info("restore, screen:%s", QGuiApplication::screens().at(scrIndex)->name().toStdString().c_str());
|
dsv_info("restore, screen:%s", QGuiApplication::screens().at(scrIndex)->name().toStdString().c_str());
|
||||||
}
|
}
|
||||||
|
@ -78,19 +78,23 @@ protected:
|
|||||||
void showEvent(QShowEvent *event);
|
void showEvent(QShowEvent *event);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void changeEvent(QEvent *event) override;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void unfreezing();
|
void unfreezing();
|
||||||
|
void show_doc();
|
||||||
|
void setTaskbarProgress(int progress);
|
||||||
|
|
||||||
void showNormal();
|
void showNormal();
|
||||||
void showMaximized();
|
void showMaximized();
|
||||||
void showMinimized();
|
void showMinimized();
|
||||||
void show_doc();
|
void moveToNormal();
|
||||||
void setTaskbarProgress(int progress);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void hide_border();
|
void hide_border();
|
||||||
void show_border();
|
void show_border();
|
||||||
void writeSettings();
|
void writeSettings();
|
||||||
void saveWindowRegion();
|
void saveNormalRegion();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
toolbars::TitleBar *_titleBar;
|
toolbars::TitleBar *_titleBar;
|
||||||
@ -117,7 +121,11 @@ private:
|
|||||||
QWinTaskbarProgress *_taskPrg;
|
QWinTaskbarProgress *_taskPrg;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool _is_native_title;
|
bool _is_native_title;
|
||||||
|
bool _is_resize_ready;
|
||||||
|
int _move_event_count;
|
||||||
|
int _resize_event_count;
|
||||||
|
bool _is_resize_reset_timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace pv
|
} // namespace pv
|
||||||
|
Loading…
x
Reference in New Issue
Block a user