fix: finalize non sql logic
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QTabWidget>
|
#include <QTabWidget>
|
||||||
|
#include <QTextEdit>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
// Self
|
// Self
|
||||||
@@ -90,7 +91,12 @@ EditClientDialog::EditClientDialog(LicenseModel* model, QWidget *parent)
|
|||||||
m_hardwareHashLineEdit = new QLineEdit(m_manualWidget);
|
m_hardwareHashLineEdit = new QLineEdit(m_manualWidget);
|
||||||
gridLayout->addWidget(m_hardwareHashLineEdit, 9, 1);
|
gridLayout->addWidget(m_hardwareHashLineEdit, 9, 1);
|
||||||
|
|
||||||
gridLayout->addItem(new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding), 10, 0, 1, 2);
|
gridLayout->addWidget(makeLabel(tr("Comment")), 10, 0);
|
||||||
|
m_commentTextEdit = new QTextEdit(m_manualWidget);
|
||||||
|
gridLayout->addWidget(m_commentTextEdit, 11, 0, 1, 2);
|
||||||
|
m_commentTextEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||||
|
gridLayout->setRowStretch(11, 1);
|
||||||
|
|
||||||
m_tabWidget->addTab(m_manualWidget, tr("Manual"));
|
m_tabWidget->addTab(m_manualWidget, tr("Manual"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,6 +160,8 @@ void EditClientDialog::onFilesChanged(const QStringList &paths)
|
|||||||
m_cityLineEdit->setText(configBody.value("city").toString());
|
m_cityLineEdit->setText(configBody.value("city").toString());
|
||||||
if (configBody.contains("yourCompany"))
|
if (configBody.contains("yourCompany"))
|
||||||
m_yourCompanyNameTextEdit->setText(configBody.value("yourCompany").toString());
|
m_yourCompanyNameTextEdit->setText(configBody.value("yourCompany").toString());
|
||||||
|
if (configBody.contains("createdAtUtc"))
|
||||||
|
m_createdAtUtc = configBody.value("createdAtUtc").toString();
|
||||||
if (configBody.contains("hardwareHash"))
|
if (configBody.contains("hardwareHash"))
|
||||||
m_hardwareHashLineEdit->setText(configBody.value("hardwareHash").toString());
|
m_hardwareHashLineEdit->setText(configBody.value("hardwareHash").toString());
|
||||||
|
|
||||||
@@ -188,5 +196,37 @@ LicenseModel::LicenseItem EditClientDialog::getLicenseItem() const
|
|||||||
item.city = m_cityLineEdit->text().trimmed();
|
item.city = m_cityLineEdit->text().trimmed();
|
||||||
item.yourCompany = m_yourCompanyNameTextEdit->text().trimmed();
|
item.yourCompany = m_yourCompanyNameTextEdit->text().trimmed();
|
||||||
item.hardwareHash = m_hardwareHashLineEdit->text().trimmed();
|
item.hardwareHash = m_hardwareHashLineEdit->text().trimmed();
|
||||||
|
item.createdAtUtc = m_createdAtUtc;
|
||||||
|
item.comment = m_commentTextEdit->toPlainText().trimmed();
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditClientDialog::clear()
|
||||||
|
{
|
||||||
|
m_firstNameLineEdit->clear();
|
||||||
|
m_lastNameLineEdit->clear();
|
||||||
|
m_patronymicLineEdit->clear();
|
||||||
|
m_emailLineEdit->clear();
|
||||||
|
m_phoneLineEdit->clear();
|
||||||
|
m_cityLineEdit->clear();
|
||||||
|
m_yourCompanyNameTextEdit->clear();
|
||||||
|
m_hardwareHashLineEdit->clear();
|
||||||
|
m_commentTextEdit->clear();
|
||||||
|
m_configPathLabel->setText(tr("Drop file here"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditClientDialog::setClientInfo(int index)
|
||||||
|
{
|
||||||
|
if (index < 0 || index >= m_model->rowCount())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto item = m_model->getItem(index);
|
||||||
|
m_lastNameLineEdit->setText(item.lastName);
|
||||||
|
m_firstNameLineEdit->setText(item.firstName);
|
||||||
|
m_patronymicLineEdit->setText(item.patronymic);
|
||||||
|
m_emailLineEdit->setText(item.email);
|
||||||
|
m_phoneLineEdit->setText(item.phone);
|
||||||
|
m_cityLineEdit->setText(item.city);
|
||||||
|
m_yourCompanyNameTextEdit->setText(item.yourCompany);
|
||||||
|
m_hardwareHashLineEdit->setText(item.hardwareHash);
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "LicenseModel/LicenseModel.h"
|
#include "LicenseModel/LicenseModel.h"
|
||||||
class QLineEdit;
|
class QLineEdit;
|
||||||
class QTabWidget;
|
class QTabWidget;
|
||||||
|
class QTextEdit;
|
||||||
|
|
||||||
// Self
|
// Self
|
||||||
class LicenseModel;
|
class LicenseModel;
|
||||||
@@ -32,6 +33,8 @@ public:
|
|||||||
void setType(Type type);
|
void setType(Type type);
|
||||||
Type getType() const;
|
Type getType() const;
|
||||||
LicenseModel::LicenseItem getLicenseItem() const;
|
LicenseModel::LicenseItem getLicenseItem() const;
|
||||||
|
void clear();
|
||||||
|
void setClientInfo(int index);
|
||||||
private slots:
|
private slots:
|
||||||
void onFilesChanged(const QStringList &paths);
|
void onFilesChanged(const QStringList &paths);
|
||||||
private:
|
private:
|
||||||
@@ -52,7 +55,9 @@ private:
|
|||||||
QLineEdit* m_sellerNameTextEdit{nullptr}; //!< Поле ввода названия продавца (если используется).
|
QLineEdit* m_sellerNameTextEdit{nullptr}; //!< Поле ввода названия продавца (если используется).
|
||||||
QLineEdit* m_cityLineEdit{nullptr}; //!< Поле ввода города.
|
QLineEdit* m_cityLineEdit{nullptr}; //!< Поле ввода города.
|
||||||
QLineEdit* m_hardwareHashLineEdit{nullptr}; //!< Поле для отображения хеша оборудования.
|
QLineEdit* m_hardwareHashLineEdit{nullptr}; //!< Поле для отображения хеша оборудования.
|
||||||
QPushButton* m_saveButton{nullptr};
|
QTextEdit* m_commentTextEdit{nullptr}; //!<
|
||||||
|
QPushButton* m_saveButton{nullptr}; //!<
|
||||||
|
QString m_createdAtUtc;
|
||||||
QString m_filesPath;
|
QString m_filesPath;
|
||||||
Type m_type = Type::None;
|
Type m_type = Type::None;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,8 +13,15 @@
|
|||||||
|
|
||||||
const static int COLUMN_COUNT = 9;
|
const static int COLUMN_COUNT = 9;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
quintptr licenseItemToInternalId(const LicenseModel::LicenseItem &item)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<quintptr>(&item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LicenseModel::LicenseModel(QObject* parent)
|
LicenseModel::LicenseModel(QObject* parent)
|
||||||
: QAbstractTableModel(parent)
|
: QAbstractItemModel(parent)
|
||||||
{
|
{
|
||||||
m_db = QSqlDatabase::addDatabase("QSQLITE");
|
m_db = QSqlDatabase::addDatabase("QSQLITE");
|
||||||
m_db.setDatabaseName(DB_PATH);
|
m_db.setDatabaseName(DB_PATH);
|
||||||
@@ -55,17 +62,38 @@ int LicenseModel::columnCount(const QModelIndex &parent) const
|
|||||||
|
|
||||||
QVariant LicenseModel::data(const QModelIndex &index, int role) const
|
QVariant LicenseModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
switch (role)
|
if (!index.isValid() || index.row() < 0 || index.row() >= m_data.size())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
if (role == Qt::ToolTipRole && index.column() == 0)
|
||||||
|
return m_data[index.row()].id;
|
||||||
|
|
||||||
|
if (role != Qt::DisplayRole)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
switch (index.column())
|
||||||
{
|
{
|
||||||
case Qt::DisplayRole:
|
case 0:
|
||||||
break;
|
return m_data[index.row()].lastName ;
|
||||||
case Qt::ToolTipRole:
|
case 1:
|
||||||
return {}; // TODO: return client id
|
return m_data[index.row()].firstName ;
|
||||||
|
case 2:
|
||||||
|
return m_data[index.row()].patronymic ;
|
||||||
|
case 3:
|
||||||
|
return m_data[index.row()].email ;
|
||||||
|
case 4:
|
||||||
|
return m_data[index.row()].phone ;
|
||||||
|
case 5:
|
||||||
|
return m_data[index.row()].yourCompany ;
|
||||||
|
case 6:
|
||||||
|
return m_data[index.row()].city ;
|
||||||
|
case 7:
|
||||||
|
return m_data[index.row()].createdAtUtc ;
|
||||||
|
case 8:
|
||||||
|
return m_data[index.row()].comment ;
|
||||||
default:
|
default:
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant LicenseModel::headerData(int section, Qt::Orientation orientation, int role) const
|
QVariant LicenseModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||||
@@ -101,6 +129,23 @@ QVariant LicenseModel::headerData(int section, Qt::Orientation orientation, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QModelIndex LicenseModel::parent(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(index)
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex LicenseModel::index(int row, int column, const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
if (row < 0 || row >= m_data.size() || column < 0 || column >= COLUMN_COUNT)
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
if (parent.isValid())
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
return createIndex(row, column, reinterpret_cast<quintptr>(&(m_data[row])));
|
||||||
|
}
|
||||||
|
|
||||||
LicenseModel::Status LicenseModel::getStatus()
|
LicenseModel::Status LicenseModel::getStatus()
|
||||||
{
|
{
|
||||||
return m_status;
|
return m_status;
|
||||||
@@ -113,13 +158,13 @@ QString LicenseModel::getStatusText()
|
|||||||
|
|
||||||
bool LicenseModel::checkTables()
|
bool LicenseModel::checkTables()
|
||||||
{
|
{
|
||||||
bool clienttableExist = false;
|
bool clientTableExist = false;
|
||||||
for (const auto &table : m_db.tables())
|
for (const auto &table : m_db.tables())
|
||||||
{
|
{
|
||||||
if (table == "clients")
|
if (table == "clients")
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!clienttableExist)
|
if (!clientTableExist)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,15 +196,33 @@ bool LicenseModel::prepareDatabase()
|
|||||||
|
|
||||||
void LicenseModel::addClient(const LicenseItem &item)
|
void LicenseModel::addClient(const LicenseItem &item)
|
||||||
{
|
{
|
||||||
|
beginInsertRows({}, m_data.size() - 1, m_data.size() - 1);
|
||||||
m_data.append(item);
|
m_data.append(item);
|
||||||
|
endInsertRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LicenseModel::deleteClient(int index)
|
void LicenseModel::deleteClient(int index)
|
||||||
{
|
{
|
||||||
|
beginRemoveRows({}, index, index);
|
||||||
m_data.removeAt(index);
|
m_data.removeAt(index);
|
||||||
|
endRemoveRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LicenseModel::editClient(const LicenseItem &item, int index)
|
void LicenseModel::editClient(const LicenseItem &item, int index)
|
||||||
{
|
{
|
||||||
m_data[index] = item;
|
m_data[index] = item;
|
||||||
|
dataChanged(this->index(index, 0), this->index(index, COLUMN_COUNT));
|
||||||
|
}
|
||||||
|
|
||||||
|
void LicenseModel::updateModel()
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
LicenseModel::LicenseItem LicenseModel::getItem(int index) const
|
||||||
|
{
|
||||||
|
if (index < 0 || index >= m_data.count())
|
||||||
|
return LicenseItem();
|
||||||
|
return m_data[index];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
#define LICENSEMANAGER_LICENSEMODEL_H
|
#define LICENSEMANAGER_LICENSEMODEL_H
|
||||||
|
|
||||||
// Qt
|
// Qt
|
||||||
#include <QAbstractTableModel>
|
#include <QAbstractItemModel>
|
||||||
#include <QtSql/QSqlDatabase>
|
#include <QtSql/QSqlDatabase>
|
||||||
|
|
||||||
class LicenseModel : public QAbstractTableModel
|
class LicenseModel : public QAbstractItemModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@@ -29,6 +29,7 @@ public:
|
|||||||
QString patronymic;
|
QString patronymic;
|
||||||
QString phone;
|
QString phone;
|
||||||
QString yourCompany;
|
QString yourCompany;
|
||||||
|
QString createdAtUtc;
|
||||||
QString comment;
|
QString comment;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -38,13 +39,17 @@ public:
|
|||||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||||
|
QModelIndex parent(const QModelIndex &index) const override;
|
||||||
|
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
|
||||||
Status getStatus();
|
Status getStatus();
|
||||||
QString getStatusText();
|
QString getStatusText();
|
||||||
bool prepareDatabase();
|
bool prepareDatabase();
|
||||||
void addClient(const LicenseItem &item);
|
void addClient(const LicenseItem &item);
|
||||||
void deleteClient(int index);
|
void deleteClient(int index);
|
||||||
void editClient(const LicenseItem &item, int index);
|
void editClient(const LicenseItem &item, int index);
|
||||||
|
void updateModel();
|
||||||
|
LicenseItem getItem(int index) const;
|
||||||
private:
|
private:
|
||||||
bool checkTables();
|
bool checkTables();
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ MainWidget::MainWidget(QWidget *parent)
|
|||||||
m_editClientsMenuAction = m_menu->addAction(QIcon(QStringLiteral(":/deps/edit.png")), tr("Edit client"));
|
m_editClientsMenuAction = m_menu->addAction(QIcon(QStringLiteral(":/deps/edit.png")), tr("Edit client"));
|
||||||
m_deleteClientsMenuAction = m_menu->addAction(QIcon(QStringLiteral(":/deps/delete.png")), tr("Delete client"));
|
m_deleteClientsMenuAction = m_menu->addAction(QIcon(QStringLiteral(":/deps/delete.png")), tr("Delete client"));
|
||||||
|
|
||||||
connect(m_reloadTableMenuAction, &QAction::triggered, this, &MainWidget::onAddClientTriggered);
|
connect(m_reloadTableMenuAction, &QAction::triggered, this, &MainWidget::onReloadTableTriggered);
|
||||||
connect(m_addClientsMenuAction, &QAction::triggered, this, &MainWidget::onAddClientTriggered);
|
connect(m_addClientsMenuAction, &QAction::triggered, this, &MainWidget::onAddClientTriggered);
|
||||||
connect(m_editClientsMenuAction, &QAction::triggered, this, &MainWidget::onEditClientTriggered);
|
connect(m_editClientsMenuAction, &QAction::triggered, this, &MainWidget::onEditClientTriggered);
|
||||||
connect(m_deleteClientsMenuAction, &QAction::triggered, this, &MainWidget::onDeleteClientTriggered);
|
connect(m_deleteClientsMenuAction, &QAction::triggered, this, &MainWidget::onDeleteClientTriggered);
|
||||||
@@ -92,6 +92,12 @@ MainWidget::MainWidget(QWidget *parent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Edit client dialog
|
||||||
|
{
|
||||||
|
m_editClientDialog = new EditClientDialog(m_licenseModel, this);
|
||||||
|
connect(m_editClientDialog, &QDialog::finished, this, &MainWidget::onEditClientDialogClosed);
|
||||||
|
}
|
||||||
|
|
||||||
m_tableView->resizeColumnsToContents();
|
m_tableView->resizeColumnsToContents();
|
||||||
selectionChanged({}, {});
|
selectionChanged({}, {});
|
||||||
loadSettings();
|
loadSettings();
|
||||||
@@ -139,21 +145,23 @@ void MainWidget::onGetInfoTriggered()
|
|||||||
|
|
||||||
void MainWidget::onReloadTableTriggered()
|
void MainWidget::onReloadTableTriggered()
|
||||||
{
|
{
|
||||||
|
m_licenseModel->updateModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::onAddClientTriggered()
|
void MainWidget::onAddClientTriggered()
|
||||||
{
|
{
|
||||||
EditClientDialog dialog(m_licenseModel, this);
|
m_editClientDialog->setType(EditClientDialog::Type::Add);
|
||||||
dialog.setType(EditClientDialog::Type::Add);
|
m_editClientDialog->clear();
|
||||||
dialog.exec();
|
m_editClientDialog->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::onEditClientTriggered()
|
void MainWidget::onEditClientTriggered()
|
||||||
{
|
{
|
||||||
EditClientDialog dialog(m_licenseModel, this);
|
m_editClientDialog->setType(EditClientDialog::Type::Edit);
|
||||||
dialog.setType(EditClientDialog::Type::Edit);
|
if (m_tableView->selectionModel()->selectedRows().size() != 1)
|
||||||
dialog.exec();
|
return;
|
||||||
|
m_editClientDialog->setClientInfo(m_tableView->selectionModel()->selectedRows().first().row());
|
||||||
|
m_editClientDialog->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::onDeleteClientTriggered()
|
void MainWidget::onDeleteClientTriggered()
|
||||||
@@ -203,3 +211,23 @@ void MainWidget::saveSettings()
|
|||||||
QSettings settings(ORGANIZATION_NAME, metaObject()->className());
|
QSettings settings(ORGANIZATION_NAME, metaObject()->className());
|
||||||
settings.setValue(WINDOW_SIZE, size());
|
settings.setValue(WINDOW_SIZE, size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWidget::onEditClientDialogClosed(int result)
|
||||||
|
{
|
||||||
|
if (result == QDialog::Rejected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (m_editClientDialog->getType())
|
||||||
|
{
|
||||||
|
case EditClientDialog::Type::Edit:
|
||||||
|
if (m_tableView->selectionModel()->selectedRows().size() != 1)
|
||||||
|
return;
|
||||||
|
m_licenseModel->editClient(m_editClientDialog->getLicenseItem(), m_tableView->selectionModel()->selectedRows().at(0).row());
|
||||||
|
break;
|
||||||
|
case EditClientDialog::Type::Add:
|
||||||
|
m_licenseModel->addClient(m_editClientDialog->getLicenseItem());
|
||||||
|
break;
|
||||||
|
case EditClientDialog::Type::None:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ class QMenu;
|
|||||||
class QAction;
|
class QAction;
|
||||||
|
|
||||||
// Self
|
// Self
|
||||||
|
class EditClientDialog;
|
||||||
class LicenseModel;
|
class LicenseModel;
|
||||||
|
|
||||||
class MainWidget : public QMainWindow
|
class MainWidget : public QMainWindow
|
||||||
@@ -16,7 +17,7 @@ class MainWidget : public QMainWindow
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit MainWidget(QWidget *parent = nullptr);
|
explicit MainWidget(QWidget *parent = nullptr);
|
||||||
~MainWidget();
|
~MainWidget() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void closeEvent(QCloseEvent *event) override;
|
void closeEvent(QCloseEvent *event) override;
|
||||||
@@ -28,6 +29,7 @@ private slots:
|
|||||||
void onAddClientTriggered();
|
void onAddClientTriggered();
|
||||||
void onEditClientTriggered();
|
void onEditClientTriggered();
|
||||||
void onDeleteClientTriggered();
|
void onDeleteClientTriggered();
|
||||||
|
void onEditClientDialogClosed(int result);
|
||||||
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
|
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -45,7 +47,7 @@ private:
|
|||||||
QAction* m_addClientsMenuAction{nullptr};
|
QAction* m_addClientsMenuAction{nullptr};
|
||||||
QAction* m_deleteClientsMenuAction{nullptr};
|
QAction* m_deleteClientsMenuAction{nullptr};
|
||||||
QAction* m_editClientsMenuAction{nullptr};
|
QAction* m_editClientsMenuAction{nullptr};
|
||||||
|
EditClientDialog* m_editClientDialog{nullptr};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // LICENSEMANAGER_MAINWIDGET_H
|
#endif // LICENSEMANAGER_MAINWIDGET_H
|
||||||
|
|||||||
Reference in New Issue
Block a user