You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
371 lines
12 KiB
371 lines
12 KiB
/* Diese Datei ist Teil von pmv-client <https://git.piratenpartei-sh.de>
|
|
*
|
|
* pmv-client ist Freie Software: Sie können es unter den Bedingungen
|
|
* der GNU General Public License, wie von der Free Software Foundation,
|
|
* Version 3 der Lizenz weiter verteilen und/oder modifizieren.
|
|
*
|
|
* Dieses Programm wird in der Hoffnung bereitgestellt, dass es nützlich sein
|
|
* wird, jedoch OHNE JEDE GEWÄHR,; sogar ohne die implizite Gewähr der
|
|
* MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK.
|
|
* Siehe die GNU General Public License für weitere Einzelheiten.
|
|
*
|
|
* Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
|
|
* Programm erhalten haben. Wenn nicht, siehe <https://www.gnu.org/licenses/>.
|
|
*
|
|
* SPDX-License-Identifier: GPL-3.0-only
|
|
*/
|
|
|
|
#include <QMessageBox>
|
|
#include <QSettings>
|
|
#include <QSqlDatabase>
|
|
#include <QSqlQuery>
|
|
#include <QSqlQueryModel>
|
|
#include <QSqlRecord>
|
|
#include <QDebug>
|
|
#include <QNetworkInterface>
|
|
|
|
#include "mainwindow.h"
|
|
#include "ui_mainwindow.h"
|
|
#include "conndialog.h"
|
|
#include "passdialog.h"
|
|
#include "editdialog.h"
|
|
#include "helpdialog.h"
|
|
#include "importdialog.h"
|
|
#include "wahldialog.h"
|
|
#include "wahlkreisdialog.h"
|
|
#include "configdialog.h"
|
|
|
|
MainWindow::MainWindow(QWidget *parent)
|
|
: QMainWindow(parent)
|
|
, ui(new Ui::MainWindow)
|
|
{
|
|
ui->setupUi(this);
|
|
|
|
QMap<int, QString> fieldmap;
|
|
fieldmap.insert(1, "Nachname");
|
|
fieldmap.insert(2, "Vorname");
|
|
|
|
QStringList filterfeld = {"Nachname", "Vorname", "Vor- oder Nachname"};
|
|
ui->comboBox_filter->insertItems(0, filterfeld);
|
|
//ui->comboBox_filter-> ->insertItems(0, fieldmap);
|
|
|
|
statusLabel = new QLabel(this);
|
|
statusLabel->setText("Nicht verbunden");
|
|
ui->statusbar->addPermanentWidget(statusLabel);
|
|
|
|
QSettings settings;
|
|
development = settings.value("develop").toBool();
|
|
restoreGeometry(settings.value("geometry").toByteArray());
|
|
restoreState(settings.value("windowState").toByteArray());
|
|
|
|
if (!development && !check_wireguard()) {
|
|
ui->actionVerbindung->setDisabled(true);
|
|
ui->statusbar->showMessage("Wireguard-Interface 'wg0' nicht gefunden.Tunnel aktiv?");
|
|
QMessageBox msg;
|
|
msg.warning(this, "Mitgliederverwaltung", "Keine Wireguard-Verbindung 'wg0' gefunden!");
|
|
}
|
|
|
|
}
|
|
|
|
MainWindow::~MainWindow()
|
|
{
|
|
delete ui;
|
|
|
|
QSettings settings;
|
|
settings.setValue("geometry", saveGeometry());
|
|
settings.setValue("windowState", saveState());
|
|
|
|
if (db.isOpen()) {
|
|
QSqlQuery qry;
|
|
qry.prepare("DELETE FROM session WHERE sessionkey=:sessionkey");
|
|
qry.bindValue(":sessionkey", sessionkey);
|
|
if (qry.exec()) {
|
|
qDebug() << "Sessionkey aus Datenbank entfernt";
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
bool MainWindow::check_wireguard()
|
|
{
|
|
// Prüfe ob ein aktives Wireguard-Interface vorhanden ist
|
|
// Die lokale Wireguard-Konfiguration ist für einen normalen Benutzer
|
|
// nicht im Zugriff, Konfigurationsdatei kann also nicht ausgewertet
|
|
// werden.
|
|
// siehe auch: /sys/devices/virtual/net/wg0/uevent
|
|
|
|
// Für Windows
|
|
// - isP2P anscheinend nicht gesetzt
|
|
// - Interfacename muß im Wireguard-Konfigurationsdialog auf "wg0"
|
|
// gesetzt werden
|
|
|
|
QList<QNetworkInterface> ifaces = QNetworkInterface::allInterfaces();
|
|
if (!ifaces.isEmpty()) {
|
|
for (int i=0; i < ifaces.size(); i++) {
|
|
#ifdef _WIN32
|
|
if (ifaces[i].type() == QNetworkInterface::Unknown) {
|
|
#else
|
|
if (ifaces[i].type() == QNetworkInterface::Virtual) {
|
|
#endif
|
|
unsigned int flags = ifaces[i].flags();
|
|
bool isUp = bool(flags & QNetworkInterface::IsUp);
|
|
bool isRunning = bool(flags & QNetworkInterface::IsRunning);
|
|
#ifdef _WIN32
|
|
// kein P2P für Windows?
|
|
if (QString::compare(ifaces[i].name(), "wg0") == 0 && isUp && isRunning) {
|
|
#else
|
|
bool isP2P = bool(flags & QNetworkInterface::IsPointToPoint);
|
|
if (QString::compare(ifaces[i].name(), "wg0") == 0 && isUp && isRunning && isP2P) {
|
|
#endif
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool MainWindow::check_interface(QString ifname)
|
|
{
|
|
// Prüfe ob eine bestimmte IP-Adresse existiert.
|
|
// Diese sollte die lokale Adresse des Wireguard-Interfaces sein.
|
|
QNetworkInterface iface = QNetworkInterface::interfaceFromName(ifname);
|
|
QList<QHostAddress> addresses = iface.allAddresses();
|
|
for (int a=0; a < addresses.size(); a++) {
|
|
if (addresses[a] == QHostAddress::LocalHost ) continue;
|
|
if (!addresses[a].toIPv4Address()) continue;
|
|
QString ip = addresses[a].toString();
|
|
if (QString::compare(ip, "192.168.23.102", Qt::CaseInsensitive) == 0) {
|
|
qDebug() << "IP gefunden";
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
QString random_string(std::size_t length)
|
|
{
|
|
const QString CHARACTERS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
QString tempstring;
|
|
|
|
std::random_device random_device;
|
|
std::mt19937 generator(random_device());
|
|
std::uniform_int_distribution<> distribution(0, CHARACTERS.size() - 1);
|
|
for (std::size_t i = 0; i < length; ++i) {
|
|
tempstring += CHARACTERS[distribution(generator)];
|
|
}
|
|
return tempstring;
|
|
}
|
|
|
|
void MainWindow::init_sessionkey()
|
|
{
|
|
sessionkey = random_string(32);
|
|
qDebug() << "Sessionkey=" << sessionkey;
|
|
QSqlQuery qry;
|
|
qry.prepare("INSERT INTO session (sessionkey) VALUES (:sessionkey)");
|
|
qry.bindValue(":sessionkey", sessionkey);
|
|
qry.exec();
|
|
}
|
|
|
|
|
|
void MainWindow::on_actionVerbindung_triggered()
|
|
{
|
|
// Anzeige des Datenbankverbindungseditors
|
|
// Modaler Dialog mit Rückgabewert
|
|
|
|
ConnDialog d(this);
|
|
model = new QSqlQueryModel;
|
|
QSortFilterProxyModel *proxymodel = new QSortFilterProxyModel;
|
|
|
|
int result = d.exec();
|
|
//QString s;
|
|
if (result == QDialog::Accepted) {
|
|
|
|
// Werte aus dem Dialog auslesen
|
|
qDebug() << "Verbindung aufbauen ..";
|
|
|
|
QString host = d.getHost();
|
|
qint16 port = d.getPort();
|
|
QString dbname = d.getDatabaseName();
|
|
QString user = d.getUserName();
|
|
QString pass = d.getPassword();
|
|
|
|
//QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
|
|
db = QSqlDatabase::addDatabase("QMYSQL");
|
|
db.setHostName(host);
|
|
db.setPort(port);
|
|
db.setDatabaseName(dbname);
|
|
db.setUserName(user);
|
|
db.setPassword(pass);
|
|
if (db.open()) {
|
|
init_sessionkey();
|
|
|
|
// Globale LV_Daten aus DB vorladen
|
|
lv.loadFromDatabase();
|
|
qDebug() << "Version" << lv.getVersion();
|
|
qDebug() << "Releasedate" << lv.getReleaseDate();
|
|
|
|
statusLabel->setText(QString("Datenbank '%1' verbunden als '%2'").arg(dbname, user));
|
|
ui->actionVerbindung->setDisabled(true);
|
|
ui->actionKennwort->setDisabled(false);
|
|
ui->pushButton_add->setEnabled(true);
|
|
ui->pushButton_edit->setEnabled(true);
|
|
|
|
// Erfolgreiche Verbindung, speichern der Dialogeinstellung für nächste Verwendung
|
|
QSettings s;
|
|
s.setValue("host", host);
|
|
s.setValue("port", port);
|
|
s.setValue("db", dbname);
|
|
s.setValue("user", user);
|
|
|
|
model->setQuery("SELECT nr, vorname, nachname, status FROM mitglied WHERE status<>'ausgetreten' ORDER BY nr");
|
|
model->setHeaderData(0, Qt::Horizontal, "Nummer");
|
|
model->setHeaderData(1, Qt::Horizontal, "Vorname");
|
|
model->setHeaderData(2, Qt::Horizontal, "Nachname");
|
|
model->setHeaderData(3, Qt::Horizontal, "Status");
|
|
|
|
proxymodel->setSourceModel(model);
|
|
proxymodel->setFilterKeyColumn(2); // Nachname
|
|
proxymodel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
|
|
|
ui->tableView->setModel(proxymodel);
|
|
ui->tableView->show();
|
|
|
|
} else {
|
|
statusLabel->setText("Nicht verbunden");
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void MainWindow::on_actionUeber_triggered()
|
|
{
|
|
QMessageBox msg;
|
|
msg.about(this, "Über PMV", "Piraten Mitglieder Verwaltung.<br>"
|
|
"Schneller Hack um Ausfall des Bundessystems zu kompensieren.");
|
|
}
|
|
|
|
void MainWindow::on_pushButton_edit_clicked()
|
|
{
|
|
QItemSelectionModel *selectionModel = ui->tableView->selectionModel();
|
|
const QModelIndexList indexes = selectionModel->selectedRows();
|
|
const QModelIndex row = indexes.at(0);
|
|
EditDialog ed(this, ui->tableView->model()->data(row).toInt());
|
|
int result = ed.exec();
|
|
if (result == QDialog::Accepted) {
|
|
// Geänderte Daten nachladen bzw. im Model aktualisieren?
|
|
model->query().exec();
|
|
// Beispiel für Zugriff auf die zweite Spalte der selektierten Modellzeile
|
|
// qDebug() << "row" << row.siblingAtColumn(1).data();
|
|
|
|
}
|
|
}
|
|
|
|
void MainWindow::on_actionBeenden_triggered()
|
|
{
|
|
qDebug() << "Programm über Menü normal beenden.";
|
|
}
|
|
|
|
void MainWindow::on_actionKennwort_triggered()
|
|
{
|
|
// Kennwortänderung auf Datenbankebene
|
|
PassDialog pd(this);
|
|
int result = pd.exec();
|
|
if (result == QDialog::Accepted) {
|
|
ui->statusbar->showMessage("Kennwort wurde geändert");
|
|
}
|
|
}
|
|
|
|
void MainWindow::on_actionAnleitung_triggered()
|
|
{
|
|
// Anleitung zur Mitgliederverwaltung
|
|
HelpDialog hd(this);
|
|
hd.exec();
|
|
}
|
|
|
|
void MainWindow::on_actionImport_triggered()
|
|
{
|
|
// Daten importieren
|
|
ImportDialog id(this);
|
|
id.exec();
|
|
}
|
|
|
|
void MainWindow::on_actionWahlen_triggered()
|
|
{
|
|
WahlDialog wd(this);
|
|
wd.exec();
|
|
}
|
|
|
|
void MainWindow::on_actionWahlkreise_triggered()
|
|
{
|
|
WahlkreisDialog wkd(this);
|
|
wkd.exec();
|
|
}
|
|
|
|
void MainWindow::on_actionEinstellungen_triggered()
|
|
{
|
|
ConfigDialog dialog(this, &lv);
|
|
dialog.exec();
|
|
}
|
|
|
|
void MainWindow::on_lineEdit_filter_textChanged(const QString &arg1)
|
|
{
|
|
// Filter bei jedem Tastendruck aktualisieren
|
|
QSortFilterProxyModel *model = (QSortFilterProxyModel *)ui->tableView->model();
|
|
model->setFilterFixedString(arg1);
|
|
}
|
|
|
|
void MainWindow::on_comboBox_filter_currentIndexChanged(int index)
|
|
{
|
|
// Feldauswahl für den Filter
|
|
QSortFilterProxyModel *model = (QSortFilterProxyModel *)ui->tableView->model();
|
|
if (!model) {
|
|
return;
|
|
}
|
|
if (index == 0) {
|
|
// Nachname
|
|
model->setFilterKeyColumn(2);
|
|
} else if (index == 1) {
|
|
// Vorname
|
|
model->setFilterKeyColumn(1);
|
|
} else {
|
|
model->setFilterKeyColumn(-1);
|
|
}
|
|
}
|
|
|
|
void MainWindow::on_pushButton_clear_clicked()
|
|
{
|
|
ui->lineEdit_filter->setText("");
|
|
}
|
|
|
|
void MainWindow::on_pushButton_add_clicked()
|
|
{
|
|
// Neues Mitglied anlegen, direkt mit genau einem SQL-Statement in der Datenbank,
|
|
// damit es nicht zu Kollisionen bei gleichzeitigem Arbeiten mit mehreren Benutzern
|
|
// kommt. Temporäre Nummer verwenden, dabei immer die Basisnummer beachten!
|
|
|
|
QSqlQuery qry;
|
|
QString sql;
|
|
sql = QString("INSERT INTO mitglied"
|
|
" (nr, vorname, nachname, geburtsdatum, staatsang, eintrittsdatum) "
|
|
"SELECT"
|
|
" (SELECT IFNULL(MAX(nr)+1,%1) FROM mitglied WHERE nr>=%1),"
|
|
" 'Neu' , 'Mitglied', '1900-01-01', 'DE', NOW()").arg(lv.getOffsetNrNeu());
|
|
qDebug() << sql;
|
|
if (!qry.exec(sql)) {
|
|
qDebug() << "Fehler beim Erzeugen eines neuen Mitgliederdatensatzes";
|
|
}
|
|
}
|
|
|
|
void MainWindow::on_checkBox_stateChanged(int arg1)
|
|
{
|
|
if (!model) {
|
|
return;
|
|
}
|
|
if (arg1 == 2) {
|
|
model->setQuery("SELECT nr, vorname, nachname, status FROM mitglied ORDER BY nr");
|
|
} else {
|
|
model->setQuery("SELECT nr, vorname, nachname, status FROM mitglied WHERE status<>'ausgetreten' ORDER BY nr");
|
|
}
|
|
}
|
|
|