Add fully-functional administration panel for administrators and dispatchers

This commit is contained in:
E. Kozlovskaya 2021-01-05 16:01:34 +07:00
parent bf599549ea
commit ff6901e3a9
22 changed files with 1257 additions and 42 deletions

View file

@ -0,0 +1,250 @@
#include "administrationpanel.h"
#include "ui_administrationpanel.h"
AdministrationPanel::AdministrationPanel(QWidget *parent) :
QMainWindow(parent), ui(new Ui::AdministrationPanel) {
ui->setupUi(this);
connect(this, &AdministrationPanel::invalidateTables,
this, &AdministrationPanel::onTablesInvalidation);
avm = new AdministrationViewModel(this);
ui->administrationView->setModel(avm);
wvm = new WorkersViewModel(this);
ui->workersView->setModel(wvm);
pvm = new ProfessionsViewModel(this);
ui->professionsView->setModel(pvm);
emit invalidateTables();
}
AdministrationPanel::~AdministrationPanel() {
delete ui;
delete avm;
delete wvm;
delete pvm;
}
void AdministrationPanel::setUser(User *user) {
mUser = user;
ui->user->setText(user->getFullNameShortForm());
ui->administrationGroup->setVisible(user->getUserType() == UserType::ADMINISTRATOR);
}
void AdministrationPanel::resizeEvent(QResizeEvent *event) {
int cellWidth = 60;
ui->administrationView->setColumnWidth(0, cellWidth*4);
ui->administrationView->setColumnWidth(1, cellWidth*1);
ui->administrationView->setColumnWidth(2, cellWidth*4);
ui->administrationView->setColumnWidth(3, cellWidth*2);
ui->workersView->setColumnWidth(0, cellWidth*4);
ui->workersView->setColumnWidth(1, cellWidth*1);
ui->workersView->setColumnWidth(2, cellWidth*4);
ui->workersView->setColumnWidth(3, cellWidth*4);
ui->workersView->setColumnWidth(4, cellWidth*4);
ui->workersView->setColumnWidth(5, cellWidth*4);
ui->workersView->setColumnWidth(6, cellWidth*4);
QMainWindow::resizeEvent(event);
}
void AdministrationPanel::doLogout() {
close();
}
void AdministrationPanel::addAdministration() {
QStringList items = {
"Administrator",
"Dispatcher"
};
bool ok;
QString sel = QInputDialog::getItem(this, "Administration type", "", items, 0, false, &ok);
if (ok) {
UserType t = sel == "Administrator"? UserType::ADMINISTRATOR : UserType::DISPATCHER;
User *user = new User();
RegistrationDialog rd(this);
rd.setEditMode(false);
rd.setUser(user);
rd.lockUserType(t);
rd.setWindowTitle("New administration");
if (rd.exec() == RegistrationDialog::Accepted) {
Database::instance()->addUser(*user);
emit invalidateTables();
return;
}
}
QMessageBox::critical(this, "Error", "Aborted by user");
}
void AdministrationPanel::addWorker() {
User *user = new User();
RegistrationDialog rd(this);
rd.setEditMode(false);
rd.setUser(user);
rd.lockUserType(UserType::WORKER);
rd.setWindowTitle("New worker");
if (rd.exec() == RegistrationDialog::Accepted) {
Database::instance()->addUser(*user);
emit invalidateTables();
return;
}
}
void AdministrationPanel::addProfession() {
QString title = QInputDialog::getText(this, "Input", "Profession title").trimmed();
if (!title.isEmpty()) {
Profession p = Profession::createProfession(title);
bool ok = Database::instance()->addProfession(p);
if (ok) {
emit invalidateTables();
}
else {
QMessageBox::critical(this, "Error", "You are trying to add the same job twice");
}
return;
}
QMessageBox::critical(this, "Error", "Aborted by user");
}
void AdministrationPanel::editAdministration() {
auto rows = ui->administrationView->selectionModel()->selectedRows();
if (rows.isEmpty() || rows.size() > 1) {
return;
}
UID aUID = avm->index(rows[0].row(), 0).data().toString();
if (aUID == mUser->uID()) {
QMessageBox::critical(this, "Error", "You cannot edit yourself.");
return;
}
editUser(aUID);
}
void AdministrationPanel::editWorker() {
auto rows = ui->workersView->selectionModel()->selectedRows();
if (rows.isEmpty() || rows.size() > 1) {
return;
}
UID wUID = wvm->index(rows[0].row(), 0).data().toString();
editUser(wUID);
}
void AdministrationPanel::editUser(UID uid) {
User *user = Database::instance()->getUser(uid);
if (user == nullptr) {
QMessageBox::critical(this, "Error", "USer not found");
return;
}
RegistrationDialog rd(this);
rd.setEditMode(true);
rd.setUser(user);
rd.lockUserType(user->getUserType());
rd.setWindowTitle("Edit user");
if (rd.exec() == RegistrationDialog::Accepted) {
Database::instance()->addUser(*user);
emit invalidateTables();
}
}
void AdministrationPanel::editProfession() {
QStringList professions;
foreach (auto prof, Database::instance()->professions()) {
professions << prof.title() + "|" + prof.pID().toString();
}
if (professions.isEmpty()) {
QMessageBox::critical(this, "Error", "No professions found");
return;
}
bool ok;
QString p = QInputDialog::getItem(this, "Choose profession", "Profession title",
professions, 0, false, &ok);
if (ok) {
PID pid = p.split("|").last();
QString title = QInputDialog::getText(this, "Input", "New title").trimmed();
if (!title.isEmpty()) {
Database::instance()->getProfession(pid)->setTitle(title);
emit invalidateTables();
return;
}
}
QMessageBox::critical(this, "Error", "Aborted by user");
}
void AdministrationPanel::removeAdministration() {
auto rows = ui->administrationView->selectionModel()->selectedRows();
if (rows.isEmpty()) {
return;
}
QMessageBox remconf(this);
remconf.setIcon(QMessageBox::Question);
remconf.setWindowTitle("Remove confirmation");
remconf.setText("Are you sure you want to remove this worker?");
remconf.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
remconf.setDefaultButton(QMessageBox::No);
if (remconf.exec() == QMessageBox::No) {
return;
}
for (int i = rows.size() - 1; i >= 0; i--) {
UID aUID = avm->index(rows[i].row(), 0).data().toString();
if (aUID == mUser->uID()) {
QMessageBox::critical(this, "Error", "You cannot remove yourself.");
}
else {
Database::instance()->removeUser(aUID);
}
}
emit invalidateTables();
}
void AdministrationPanel::removeWorker() {
auto rows = ui->workersView->selectionModel()->selectedRows();
if (rows.isEmpty()) {
return;
}
QMessageBox remconf(this);
remconf.setIcon(QMessageBox::Question);
remconf.setWindowTitle("Remove confirmation");
remconf.setText("Are you sure you want to remove this worker?");
remconf.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
remconf.setDefaultButton(QMessageBox::No);
if (remconf.exec() == QMessageBox::No) {
return;
}
for (int i = rows.size() - 1; i >= 0; i--) {
UID wUID = wvm->index(rows[i].row(), 0).data().toString();
Database::instance()->removeUser(wUID);
}
emit invalidateTables();
}
void AdministrationPanel::removeProfession() {
QStringList professions;
foreach (auto prof, Database::instance()->professions()) {
professions << prof.title() + "|" + prof.pID().toString();
}
if (professions.isEmpty()) {
QMessageBox::critical(this, "Error", "No professions found");
return;
}
bool ok;
QString p = QInputDialog::getItem(this, "Choose profession", "Profession title",
professions, 0, false, &ok);
if (ok) {
PID pid = p.split("|").last();
ok = Database::instance()->removeProfession(pid);
if (ok) {
emit invalidateTables();
return;
}
}
QMessageBox::critical(this, "Error", "Aborted by user or "
"workers depend on selected profession");
}
void AdministrationPanel::onTablesInvalidation() {
avm->invalidateData();
wvm->invalidateData();
pvm->invalidateData();
}

View file

@ -0,0 +1,58 @@
#ifndef ADMINISTRATIONPANEL_H
#define ADMINISTRATIONPANEL_H
#include <QMainWindow>
#include <QMessageBox>
#include <QInputDialog>
#include "objects/user.h"
#include "objects/profession.h"
#include "db/database.h"
#include "registrationdialog.h"
#include "viewmodels/administrationviewmodel.h"
#include "viewmodels/workersviewmodel.h"
#include "viewmodels/professionsviewmodel.h"
namespace Ui { class AdministrationPanel; }
class AdministrationPanel : public QMainWindow {
private:
Q_OBJECT
Ui::AdministrationPanel *ui;
AdministrationViewModel *avm;
WorkersViewModel *wvm;
ProfessionsViewModel *pvm;
User *mUser;
public:
explicit AdministrationPanel(QWidget *parent = nullptr);
~AdministrationPanel();
void setUser(User *user);
signals:
void invalidateTables();
public slots:
void resizeEvent(QResizeEvent *event);
void doLogout();
void addAdministration();
void addWorker();
void addProfession();
void editAdministration();
void editWorker();
void editUser(UID uid);
void editProfession();
void removeAdministration();
void removeWorker();
void removeProfession();
void onTablesInvalidation();
};
#endif // ADMINISTRATIONPANEL_H

View file

@ -0,0 +1,444 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AdministrationPanel</class>
<widget class="QMainWindow" name="AdministrationPanel">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>808</width>
<height>679</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>808</width>
<height>503</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>808</width>
<height>679</height>
</size>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="user">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Hello,**%user%**</string>
</property>
<property name="textFormat">
<enum>Qt::MarkdownText</enum>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="btnLogout">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Logout</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="administrationGroup">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Aministration</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="1">
<widget class="QPushButton" name="btnRemoveAdministration">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="3">
<widget class="QTableView" name="administrationView">
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<attribute name="horizontalHeaderCascadingSectionResizes">
<bool>true</bool>
</attribute>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="btnAddAdministration">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="btnEditAdministration">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Edit</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QGroupBox" name="workersGroup">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Workers</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0" rowspan="3">
<widget class="QTableView" name="workersView">
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<attribute name="horizontalHeaderCascadingSectionResizes">
<bool>true</bool>
</attribute>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="btnRemoveWorker">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="btnAddWorker">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="btnEditWorker">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Edit</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QGroupBox" name="professionsGroup">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Professions</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="2" column="1">
<widget class="QPushButton" name="btnRemoveProfession">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="btnAddProfession">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="btnEditProfession">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Edit</string>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="3">
<widget class="QTreeView" name="professionsView">
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="headerHidden">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>btnLogout</sender>
<signal>clicked()</signal>
<receiver>AdministrationPanel</receiver>
<slot>doLogout()</slot>
<hints>
<hint type="sourcelabel">
<x>137</x>
<y>20</y>
</hint>
<hint type="destinationlabel">
<x>188</x>
<y>20</y>
</hint>
</hints>
</connection>
<connection>
<sender>btnAddAdministration</sender>
<signal>clicked()</signal>
<receiver>AdministrationPanel</receiver>
<slot>addAdministration()</slot>
<hints>
<hint type="sourcelabel">
<x>747</x>
<y>85</y>
</hint>
<hint type="destinationlabel">
<x>799</x>
<y>31</y>
</hint>
</hints>
</connection>
<connection>
<sender>btnEditAdministration</sender>
<signal>clicked()</signal>
<receiver>AdministrationPanel</receiver>
<slot>editAdministration()</slot>
<hints>
<hint type="sourcelabel">
<x>733</x>
<y>156</y>
</hint>
<hint type="destinationlabel">
<x>774</x>
<y>14</y>
</hint>
</hints>
</connection>
<connection>
<sender>btnRemoveAdministration</sender>
<signal>clicked()</signal>
<receiver>AdministrationPanel</receiver>
<slot>removeAdministration()</slot>
<hints>
<hint type="sourcelabel">
<x>740</x>
<y>198</y>
</hint>
<hint type="destinationlabel">
<x>762</x>
<y>7</y>
</hint>
</hints>
</connection>
<connection>
<sender>btnAddWorker</sender>
<signal>clicked()</signal>
<receiver>AdministrationPanel</receiver>
<slot>addWorker()</slot>
<hints>
<hint type="sourcelabel">
<x>751</x>
<y>305</y>
</hint>
<hint type="destinationlabel">
<x>698</x>
<y>28</y>
</hint>
</hints>
</connection>
<connection>
<sender>btnEditWorker</sender>
<signal>clicked()</signal>
<receiver>AdministrationPanel</receiver>
<slot>editWorker()</slot>
<hints>
<hint type="sourcelabel">
<x>743</x>
<y>352</y>
</hint>
<hint type="destinationlabel">
<x>652</x>
<y>13</y>
</hint>
</hints>
</connection>
<connection>
<sender>btnRemoveWorker</sender>
<signal>clicked()</signal>
<receiver>AdministrationPanel</receiver>
<slot>removeWorker()</slot>
<hints>
<hint type="sourcelabel">
<x>742</x>
<y>423</y>
</hint>
<hint type="destinationlabel">
<x>609</x>
<y>29</y>
</hint>
</hints>
</connection>
<connection>
<sender>btnAddProfession</sender>
<signal>clicked()</signal>
<receiver>AdministrationPanel</receiver>
<slot>addProfession()</slot>
<hints>
<hint type="sourcelabel">
<x>756</x>
<y>525</y>
</hint>
<hint type="destinationlabel">
<x>355</x>
<y>6</y>
</hint>
</hints>
</connection>
<connection>
<sender>btnEditProfession</sender>
<signal>clicked()</signal>
<receiver>AdministrationPanel</receiver>
<slot>editProfession()</slot>
<hints>
<hint type="sourcelabel">
<x>751</x>
<y>578</y>
</hint>
<hint type="destinationlabel">
<x>374</x>
<y>18</y>
</hint>
</hints>
</connection>
<connection>
<sender>btnRemoveProfession</sender>
<signal>clicked()</signal>
<receiver>AdministrationPanel</receiver>
<slot>removeProfession()</slot>
<hints>
<hint type="sourcelabel">
<x>762</x>
<y>625</y>
</hint>
<hint type="destinationlabel">
<x>446</x>
<y>11</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>doLogout()</slot>
<slot>addAdministration()</slot>
<slot>addWorker()</slot>
<slot>addProfession()</slot>
<slot>removeAdministration()</slot>
<slot>removeWorker()</slot>
<slot>removeProfession()</slot>
<slot>editAdministration()</slot>
<slot>editWorker()</slot>
<slot>editProfession()</slot>
</slots>
</ui>

View file

@ -9,6 +9,7 @@ CONFIG += c++11
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
administrationpanel.cpp \
main.cpp \
loginwindow.cpp \
objects/profession.cpp \
@ -16,18 +17,26 @@ SOURCES += \
objects/userprofession.cpp \
db/database.cpp \
registrationdialog.cpp \
viewmodels/userprofessionviewmodel.cpp
viewmodels/administrationviewmodel.cpp \
viewmodels/professionsviewmodel.cpp \
viewmodels/userprofessionviewmodel.cpp \
viewmodels/workersviewmodel.cpp
HEADERS += \
administrationpanel.h \
loginwindow.h \
objects/profession.h \
objects/user.h \
objects/userprofession.h \
db/database.h \
registrationdialog.h \
viewmodels/userprofessionviewmodel.h
viewmodels/administrationviewmodel.h \
viewmodels/professionsviewmodel.h \
viewmodels/userprofessionviewmodel.h \
viewmodels/workersviewmodel.h
FORMS += \
administrationpanel.ui \
loginwindow.ui \
registrationdialog.ui

View file

@ -42,8 +42,17 @@ void LoginWindow::doLogin() {
return;
}
QMessageBox::information(this, "Info", "Success");
// TODO: Open valid window
QWidget *w;
if (user->getUserType() == UserType::WORKER) {
QMessageBox::information(this, "Ok", "Ok");
return;
}
else {
w = new AdministrationPanel();
((AdministrationPanel*)w)->setUser(user);
}
w->show();
close();
}
void LoginWindow::validateForm() {

View file

@ -8,6 +8,7 @@
#include "db/database.h"
#include "registrationdialog.h"
#include "administrationpanel.h"
QT_BEGIN_NAMESPACE
namespace Ui { class LoginWindow; }

View file

@ -4,6 +4,10 @@ QString Profession::title() const {
return mTitle;
}
void Profession::setTitle(const QString &newTitle) {
mTitle = newTitle;
}
PID Profession::pID() const {
return mPID;
}

View file

@ -16,6 +16,7 @@ public:
Profession() = default;
QString title() const;
void setTitle(const QString &newTitle);
PID pID() const;
static Profession createProfession(const QString &title);

View file

@ -29,6 +29,14 @@ QString User::patronymic() const {
return mPatronymic;
}
QString User::getFullName() const {
return QString("%1 %2 %3").arg(mSecondName).arg(mFirstName).arg(mPatronymic);
}
QString User::getFullNameShortForm() const {
return QString("%1 %2.%3.").arg(mSecondName).arg(mFirstName[0]).arg(mPatronymic[0]);
}
ProfessionsList User::getProfessions() const {
return mProfessions;
}
@ -69,11 +77,9 @@ bool User::addProfession(PID pid, ProfRank rank) {
if (mProfessions.size() >= 4) {
if (mCurrentProfession == mProfessions[0].getProfession()) {
mProfessions.remove(1);
}
else {
mProfessions.remove(0);
return false;
}
mProfessions.remove(0);
}
UserProfession up(pid, rank);
@ -91,12 +97,14 @@ bool User::setCurrentProfession(PID pid) {
}
void User::removeProfession(PID pid) {
auto pred = [pid](UserProfession p) {
return p.getProfession() == pid;
};
mProfessions.erase(std::remove_if(mProfessions.begin(), mProfessions.end(), pred),
mProfessions.end());
auto pred = [pid](UserProfession p) { return p.getProfession() == pid; };
if (pid == mCurrentProfession) {
mCurrentProfession = 0;
}
mProfessions.erase(
std::remove_if(mProfessions.begin(), mProfessions.end(), pred),
mProfessions.end()
);
}
bool operator==(const User &l, const User &r) {

View file

@ -42,6 +42,8 @@ public:
QString firstName() const;
QString secondName() const;
QString patronymic() const;
QString getFullName() const;
QString getFullNameShortForm() const;
ProfessionsList getProfessions() const;
PID getCurrentProfession() const;

View file

@ -3,6 +3,7 @@
UserProfession::UserProfession(PID pid, ProfRank rank) {
mProfession = pid;
mRank = rank;
mAcquired = QDate::currentDate();
}
PID UserProfession::getProfession() const {

View file

@ -7,6 +7,23 @@ RegistrationDialog::RegistrationDialog(QWidget *parent) :
upvm = new UserProfessionViewModel(this);
ui->userProfessions->setModel(upvm);
connect(ui->userProfessions->selectionModel(),
&QItemSelectionModel::selectionChanged,
this,
[this]() {
auto rows = ui->userProfessions->selectionModel()->selectedRows();
ui->btnSetProfessionCurrent->setEnabled(rows.size() == 1);
ui->btnRemoveProfession->setEnabled(rows.size() >= 1);
}
);
connect(ui->userGroup,
QOverload<int>::of(&QComboBox::currentIndexChanged),
[this](int newIdx) {
ui->professionsGroup->setVisible((UserType)newIdx == UserType::WORKER);
}
);
}
RegistrationDialog::~RegistrationDialog() {
@ -18,10 +35,12 @@ RegistrationDialog::~RegistrationDialog() {
void RegistrationDialog::lockUserType(UserType type) {
ui->userGroup->setCurrentIndex((int)type);
ui->userGroup->setEnabled(false);
ui->professionsGroup->setVisible(type == UserType::WORKER);
}
void RegistrationDialog::setUser(User *usr) {
user = usr;
upvm->setUser(user);
if (mEditMode) {
ui->firstName->setText(user->firstName());
@ -33,7 +52,6 @@ void RegistrationDialog::setUser(User *usr) {
ui->password->setEnabled(usr->getUserType() == UserType::ADMINISTRATOR);
ui->userGroup->setCurrentIndex((int)user->getUserType());
ui->userGroup->setEnabled(false);
upvm->setProfessionsList(user->getProfessions());
}
}
@ -63,6 +81,8 @@ void RegistrationDialog::accept() {
}
else {
auto u = User::createUser(login, pass, type, fname, sname, patr);
u->mProfessions = user->mProfessions;
u->setCurrentProfession(user->getCurrentProfession());
std::swap(*user, *u);
delete u;
}
@ -87,12 +107,39 @@ void RegistrationDialog::addNewProfession() {
int r = QInputDialog::getInt(this, "Profession rank", "", 1, 1, 2e5, 1, &ok);
if (ok) {
user->addProfession(pid, r);
upvm->invalidateData();
return;
}
}
QMessageBox::critical(this, "Error", "Aborted by user or selected non-existant profession");
}
void RegistrationDialog::removeOldProfession() {
void RegistrationDialog::setCurrentProfession() {
auto rows = ui->userProfessions->selectionModel()->selectedRows();
if (rows.isEmpty() || rows.size() > 1) {
return;
}
auto uProf = user->getProfessions()[rows[0].row()];
user->setCurrentProfession(uProf.getProfession());
upvm->invalidateData();
}
void RegistrationDialog::removeOldProfession() {
auto rows = ui->userProfessions->selectionModel()->selectedRows();
if (rows.isEmpty()) {
return;
}
QMessageBox remconf(this);
remconf.setIcon(QMessageBox::Question);
remconf.setWindowTitle("Remove confirmation");
remconf.setText("Are you sure you want to remove this profession?");
remconf.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
remconf.setDefaultButton(QMessageBox::No);
if (remconf.exec() == QMessageBox::No) {
return;
}
for (int i = rows.size() - 1; i >= 0; i--) {
user->removeProfession(user->getProfessions()[rows[i].row()].getProfession());
}
upvm->invalidateData();
}

View file

@ -31,6 +31,7 @@ public slots:
void accept() Q_DECL_OVERRIDE;
void addNewProfession();
void setCurrentProfession();
void removeOldProfession();
};

View file

@ -28,6 +28,12 @@
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Full name</string>
</property>
@ -58,6 +64,12 @@
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Login data</string>
</property>
@ -84,6 +96,12 @@
</item>
<item>
<widget class="QGroupBox" name="groupBox_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>User type</string>
</property>
@ -111,14 +129,11 @@
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<widget class="QGroupBox" name="professionsGroup">
<property name="title">
<string>Professions</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0" rowspan="2">
<widget class="QTableView" name="userProfessions"/>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="btnAddProfession">
<property name="sizePolicy">
@ -132,7 +147,20 @@
</property>
</widget>
</item>
<item row="1" column="1">
<item row="0" column="0" rowspan="3">
<widget class="QTableView" name="userProfessions">
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<attribute name="horizontalHeaderCascadingSectionResizes">
<bool>true</bool>
</attribute>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="btnRemoveProfession">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
@ -145,9 +173,38 @@
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="btnSetProfessionCurrent">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Set current</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="minimumSize">
@ -232,9 +289,26 @@
</hint>
</hints>
</connection>
<connection>
<sender>btnSetProfessionCurrent</sender>
<signal>clicked()</signal>
<receiver>RegistrationDialog</receiver>
<slot>setCurrentProfession()</slot>
<hints>
<hint type="sourcelabel">
<x>591</x>
<y>286</y>
</hint>
<hint type="destinationlabel">
<x>100</x>
<y>183</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>addNewProfession()</slot>
<slot>removeOldProfession()</slot>
<slot>setCurrentProfession()</slot>
</slots>
</ui>

View file

@ -0,0 +1,64 @@
#include "administrationviewmodel.h"
AdministrationViewModel::AdministrationViewModel(QObject *parent) : QAbstractTableModel(parent) {
}
int AdministrationViewModel::rowCount(const QModelIndex &/*parent*/) const {
return mUserData.length();
}
int AdministrationViewModel::columnCount(const QModelIndex &/*parent*/) const {
return 4;
}
QVariant AdministrationViewModel::headerData(int section, Qt::Orientation orientation,
int role) const {
if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
switch (section) {
case 0:
return QString("UID");
case 1:
return QString("Login");
case 2:
return QString("Full name");
case 3:
return QString("Status");
}
}
return QVariant();
}
QVariant AdministrationViewModel::data(const QModelIndex &index, int role) const {
if (role == Qt::DisplayRole) {
auto usr = mUserData[index.row()];
int col = index.column();
switch (col) {
case 0:
return usr.uID();
case 1:
return usr.getLogin();
case 2:
return usr.getFullName();
case 3:
return usr.getUserType() == UserType::ADMINISTRATOR? "Administrator" : "Dispatcher";
}
return "UNKNOWN FIELD";
}
return QVariant();
}
void AdministrationViewModel::invalidateData() {
beginResetModel();
mUserData.clear();
foreach (auto u, Database::instance()->getUsersByType(UserType::ADMINISTRATOR)) {
mUserData += *u;
}
foreach (auto u, Database::instance()->getUsersByType(UserType::DISPATCHER)) {
mUserData += *u;
}
endResetModel();
}

View file

@ -0,0 +1,27 @@
#ifndef ADMINISTRATIONVIEWMODEL_H
#define ADMINISTRATIONVIEWMODEL_H
#include <QAbstractTableModel>
#include <QVector>
#include "../objects/user.h"
#include "../db/database.h"
class AdministrationViewModel : public QAbstractTableModel {
private:
Q_OBJECT
QVector<User> mUserData;
public:
AdministrationViewModel(QObject *parent);
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
void invalidateData();
};
#endif // ADMINISTRATIONVIEWMODEL_H

View file

@ -0,0 +1,46 @@
#include "professionsviewmodel.h"
ProfessionsViewModel::ProfessionsViewModel(QObject *parent) : QStandardItemModel(parent) {
}
void ProfessionsViewModel::invalidateData() {
beginResetModel();
clear();
QStandardItemModel::setHeaderData(0, Qt::Orientation::Horizontal, "Professions");
QStandardItem *rootNode = invisibleRootItem();
foreach (auto prof, Database::instance()->professions()) {
QStandardItem *profNode = new QStandardItem("Profession: " + prof.title());
QStandardItem *profUID = new QStandardItem("PID: " + prof.pID().toString());
QStandardItem *currentWorkers = new QStandardItem("Current workers");
QStandardItem *availableWorkers = new QStandardItem("Available workers");
foreach(auto worker, Database::instance()->getUsersByProfession(prof.pID())) {
QStandardItem *workerNode = new QStandardItem(worker->getFullNameShortForm());
UserProfession up;
foreach (auto uProf, worker->getProfessions()) {
if (uProf.getProfession() == prof.pID()) {
up = uProf;
}
}
QStandardItem *workerRank = new QStandardItem(tr("%1 rank").arg(up.getRank()));
QStandardItem *acqDateNode = new QStandardItem(
up.getAcquiredDate().toString(Qt::DateFormat::SystemLocaleShortDate));
workerNode->appendRow(workerRank);
workerNode->appendRow(acqDateNode);
if (worker->getCurrentProfession() == prof.pID()) {
currentWorkers->appendRow(workerNode);
}
else {
availableWorkers->appendRow(workerNode);
}
}
profNode->appendRow(profUID);
profNode->appendRow(currentWorkers);
profNode->appendRow(availableWorkers);
rootNode->appendRow(profNode);
}
endResetModel();
}

View file

@ -0,0 +1,18 @@
#ifndef PROFESSIONSVIEMODEL_H
#define PROFESSIONSVIEMODEL_H
#include <QStandardItemModel>
#include "../db/database.h"
class ProfessionsViewModel : public QStandardItemModel {
private:
Q_OBJECT
public:
ProfessionsViewModel(QObject *parent);
void invalidateData();
};
#endif // PROFESSIONSVIEMODEL_H

View file

@ -5,7 +5,7 @@ UserProfessionViewModel::UserProfessionViewModel(QObject *parent) : QAbstractTab
}
int UserProfessionViewModel::rowCount(const QModelIndex &/*parent*/) const {
return mProfList.length();
return mUser != nullptr? mUser->getProfessions().length() : 0;
}
int UserProfessionViewModel::columnCount(const QModelIndex &/*parent*/) const {
@ -16,41 +16,53 @@ QVariant UserProfessionViewModel::headerData(int section,
Qt::Orientation orientation, int role) const {
if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
switch (section) {
case 0:
return QString("Profession");
case 1:
return QString("Date of acquirement");
case 2:
return QString("Rank");
case 0:
return QString("Profession");
case 1:
return QString("Date of acquirement");
case 2:
return QString("Rank");
}
}
return QVariant();
}
QVariant UserProfessionViewModel::data(const QModelIndex &index, int role) const {
auto profs = mUser->getProfessions();
auto uProf = profs[index.row()];
if (role == Qt::DisplayRole) {
auto item = mProfList[index.row()];
auto prof = Database::instance()->getProfession(item.getProfession());
auto prof = Database::instance()->getProfession(uProf.getProfession());
int col = index.column();
switch (col) {
case 0:
return prof == nullptr? "ERROR:UNKNOWN" : prof->title();
case 1:
return item.getAcquiredDate();
case 2:
return item.getRank();
case 0:
return prof == nullptr? "#ERROR!" : prof->title();
case 1:
return uProf.getAcquiredDate().toString(Qt::DateFormat::SystemLocaleShortDate);
case 2:
return uProf.getRank();
}
return "UNKNOWN FIELD";
}
else if (role == Qt::FontRole) {
if (uProf.getProfession() == mUser->getCurrentProfession()) {
QFont f;
f.setBold(true);
return f;
}
}
return QVariant();
}
void UserProfessionViewModel::setProfessionsList(const ProfessionsList &profList) {
void UserProfessionViewModel::setUser(User *user) {
mUser = user;
invalidateData();
}
void UserProfessionViewModel::invalidateData() {
beginResetModel();
mProfList.clear();
mProfList += profList;
endResetModel();
}

View file

@ -2,6 +2,7 @@
#define USERPROFESSIONVIEWMODEL_H
#include <QAbstractTableModel>
#include <QFont>
#include "../objects/user.h"
#include "../db/database.h"
@ -10,16 +11,18 @@ class UserProfessionViewModel : public QAbstractTableModel {
private:
Q_OBJECT
ProfessionsList mProfList;
User *mUser = nullptr;
public:
UserProfessionViewModel(QObject *parent);
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
void setProfessionsList(const ProfessionsList &profList);
void setUser(User *user);
void invalidateData();
};
#endif // USERPROFESSIONVIEWMODEL_H

View file

@ -0,0 +1,103 @@
#include "workersviewmodel.h"
WorkersViewModel::WorkersViewModel(QObject *parent) : QAbstractTableModel(parent) {
}
int WorkersViewModel::rowCount(const QModelIndex &/*parent*/) const {
return mUserData.length();
}
int WorkersViewModel::columnCount(const QModelIndex &/*parent*/) const {
return 7;
}
QVariant WorkersViewModel::headerData(int section, Qt::Orientation orientation, int role) const {
if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
switch (section) {
case 0:
return QString("UID");
case 1:
return QString("Login");
case 2:
return QString("Full name");
case 3:
return QString("First profession");
case 4:
return QString("Second profession");
case 5:
return QString("Third profession");
case 6:
return QString("Fourth profession");
}
}
return QVariant();
}
QString WorkersViewModel::getProfessionAt(const User &user, int pIdx) const {
auto profs = user.getProfessions();
QString out = "";
if (profs.size() >= pIdx + 1) {
auto p = Database::instance()->getProfession(profs[pIdx].getProfession());
out = tr("%1 (%2 rank)").arg(p->title()).arg(profs[pIdx].getRank());
}
return out;
}
bool WorkersViewModel::shouldBeBold(const QModelIndex &index) const {
int col = index.column();
if (col < 3) {
return false;
}
auto usr = mUserData[index.row()];
if (!getProfessionAt(usr, col-3).isEmpty()) {
if (usr.getProfessions()[col-3].getProfession() == usr.getCurrentProfession()) {
return true;
}
}
return false;
}
QVariant WorkersViewModel::data(const QModelIndex &index, int role) const {
if (role == Qt::DisplayRole) {
auto usr = mUserData[index.row()];
auto profs = usr.getProfessions();
int col = index.column();
switch (col) {
case 0:
return usr.uID();
case 1:
return usr.getLogin();
case 2:
return usr.getFullName();
case 3:
return getProfessionAt(usr, 0);
case 4:
return getProfessionAt(usr, 1);
case 5:
return getProfessionAt(usr, 2);
case 6:
return getProfessionAt(usr, 3);
}
return "UNKNOWN FIELD";
}
else if (role == Qt::FontRole) {
if (shouldBeBold(index)) {
QFont f;
f.setBold(true);
return f;
}
}
return QVariant();
}
void WorkersViewModel::invalidateData() {
beginResetModel();
mUserData.clear();
foreach (auto u, Database::instance()->getUsersByType(UserType::WORKER)) {
mUserData += *u;
}
endResetModel();
}

View file

@ -0,0 +1,33 @@
#ifndef WORKERSVIEWMODEL_H
#define WORKERSVIEWMODEL_H
#include <QAbstractTableModel>
#include <QPainter>
#include <QStyleOptionViewItem>
#include <QStyledItemDelegate>
#include <QVector>
#include "../objects/user.h"
#include "../db/database.h"
class WorkersViewModel : public QAbstractTableModel {
private:
Q_OBJECT
QVector<User> mUserData;
QString getProfessionAt(const User &user, int pIdx) const;
bool shouldBeBold(const QModelIndex &index) const;
public:
WorkersViewModel(QObject *parent);
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
void invalidateData();
};
#endif // WORKERSVIEWMODEL_H