/* Diese Datei ist Teil von pmv-client * * 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 . * * SPDX-License-Identifier: GPL-3.0-only */ #include #include #include #include #include #include #include #include #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 "amtadressdialog.h" #include "configdialog.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); QMap 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!"); } db = QSqlDatabase::addDatabase("QMYSQL"); if (!db.isValid()) { QMessageBox msg; msg.critical(this, "Mitgliederverwaltung", "Datenbanktreiber für MariaDB fehlt!"); exit(1); } #ifdef _WIN32 QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8")); #endif } 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 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 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(); db.setHostName(host); db.setPort(port); db.setDatabaseName(dbname); db.setUserName(user); db.setPassword(pass); if (db.open()) { // Der Sessionkey wird benötigt um über diesem mit dem PMV-Server // über XMLRPC zu kommunizieren init_sessionkey(); // Globale Landesverbandsdaten aus Datenbank 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; QString msgstr = "

Piraten Mitglieder Verwaltung.
Schneller Hack um Ausfall des Bundessystems zu kompensieren.

"; if (db.isValid() && db.isOpen()) { msgstr += QString("

Datenbankversion %1\n

").arg(lv.getVersion()); // TODO Versionsdatum einbauen. Funktionsweise von .arg() mit mehreren Variablen? } else { msgstr += "Datenbank nicht geöffnet."; } msg.about(this, "Über PMV", msgstr); } 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_actionAmtadressen_triggered() { AmtAdressDialog dlg(this); dlg.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"); } }