From 92f25e11e1d2e078f1928b29b7c1158f315c369c Mon Sep 17 00:00:00 2001 From: Yannik Schmidt Date: Fri, 7 Aug 2020 21:47:48 +0200 Subject: [PATCH] Implement basic functionality --- mainwindow.cpp | 296 ++++++++++++++++++++++++++++++++++++++--- mainwindow.h | 15 ++- mainwindow.ui | 29 ++-- notificationwidget.cpp | 97 ++++++++++++++ notificationwidget.h | 38 ++++++ untitled.pro | 6 +- 6 files changed, 449 insertions(+), 32 deletions(-) create mode 100644 notificationwidget.cpp create mode 100644 notificationwidget.h diff --git a/mainwindow.cpp b/mainwindow.cpp index 1ad7ac0..1a3298b 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -1,72 +1,330 @@ -#include "mainwindow.h" +#include "mainwindow.h" +#include "notificationwidget.h" #include "ui_mainwindow.h" #include #include #include #include #include +#include #include +#include +#include +#include +#include +#include #include -MainWindow::MainWindow(QWidget *parent) : - QMainWindow(parent), - ui(new Ui::MainWindow) -{ +#define FILENAME_COL 0 +#define TRACKING_ID_COL 1 +#define PG_BAR_COL 2 +#define OPEN_DIR_COL 3 +#define TRANSCRIPT_STATUS_COL 4 + +#define STATUS_REQUEST_URL "http://localhost:5000/dumpstate" +#define SUBMIT_URL "http://localhost:5000/submit-async" +#define REQUEST_TRANSCRIPT_URL "http://localhost:5000/transcript" +#define TRANSCRIPT_TARGET_DIR "." + +MainWindow::MainWindow(QWidget *parent):QMainWindow(parent), ui(new Ui::MainWindow){ + + /* setup ui */ ui->setupUi(this); + + + setAuthHeader("user", "pass"); + networkManager = new QNetworkAccessManager(this); + + /* setup buttons */ button = ui->centralWidget->findChild("pushButton"); connect(button, SIGNAL (released()), this, SLOT (importFile())); + + /* table ui */ + tw = ui->centralWidget->findChild("tableWidget"); + //QProgressBar *pgbar = new QProgressBar(); + + tw->verticalHeader()->setVisible(false); + tw->horizontalHeader()->setVisible(false); + tw->setRowCount(0); + /* FILE | trackingId | STATUS | open dir | download completed? true/false | */ + tw->setColumnCount(5); + tw->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); + tw->setColumnHidden(TRANSCRIPT_STATUS_COL, true); + + /* table header */ + tw->insertRow(0); + tw->setItem(0, FILENAME_COL, new QTableWidgetItem("Dateiname")); + tw->setItem(0, TRACKING_ID_COL, new QTableWidgetItem("Tracking-Id")); + tw->setItem(0, PG_BAR_COL, new QTableWidgetItem("Status")); + tw->setItem(0, OPEN_DIR_COL, new QTableWidgetItem("Ordner Öffnen")); + tw->setItem(0, OPEN_DIR_COL, new QTableWidgetItem("Ordner Öffnen")); + + /* create status update timer */ + QTimer *timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), this, SLOT(queryStatusAll())); + timer->start(1000); } - -void MainWindow::importFile() -{ +void MainWindow::importFile(){ QString filename = QFileDialog::getOpenFileName( this, "Open Document", QDir::currentPath(), "All files (*.*) ;; Document files (*.doc *.rtf);; PNG files (*.png)"); - if( !filename.isNull() ){ + + if(filename.isNull()){ return; + }else{ + submitFile(filename); } } -void MainWindow::submitFile(QString filename) -{ +void MainWindow::showNotification(QString str){ + #ifdef Q_OS_LINUX + return; + #endif + auto popUp = new NotificationWidget(this); + popUp->setPopupText(str); + popUp->setGeometry(0, 0, popUp->width(), popUp->height()); + popUp->show(); + auto *timer = new QTimer(); + connect(timer, SIGNAL(timeout()), popUp, SLOT(fadeOut())); + timer->start(5000); +} + +void MainWindow::setAuthHeader(const QString username, const QString password){ + /* prepare auth */ - QString username = "lol"; - QString password = "lol"; QString concatenated = username + ":" + password; QByteArray data = concatenated.toLocal8Bit().toBase64(); - QString authHeaderData = "Basic " + data; + QString authHeaderStr = "Basic " + data; + authHeaderData = authHeaderStr.toLocal8Bit(); + +} + +void MainWindow::submitFile(QString filename){ /* prepare request */ - QUrl serviceUrl = QUrl("http://localhost:5000"); + QUrl serviceUrl = QUrl(SUBMIT_URL); QNetworkRequest request(serviceUrl); - request.setRawHeader("Authorization", authHeaderData.toLocal8Bit()); + request.setRawHeader("Authorization", authHeaderData); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); /* read audio as base64 */ QFile sourceFile(filename); + sourceFile.open(QIODevice::ReadOnly | QIODevice::Text); QByteArray base64Encoded = sourceFile.readAll().toBase64(); QString dataString = QString::fromUtf8(base64Encoded); + sourceFile.close(); /* prepare json */ QJsonObject json = QJsonObject(); QJsonValue dataFieldContent = QJsonValue(dataString); - QFileInfo info(filename); QString basename(info.fileName()); json["filename"] = filename; json["data"] = dataFieldContent; /* make request */ - QNetworkAccessManager *networkManager = new QNetworkAccessManager(this); connect(networkManager, SIGNAL(finished(QNetworkReply*)), this, - SLOT(fileSubmissionFinished(QNetworkReply*))); + SLOT(requestFinished(QNetworkReply*)), Qt::UniqueConnection); networkManager->post(request, QJsonDocument(json).toJson()); + + qDebug("Request submitted"); } +void MainWindow::queryTransscript(QString trackingId){ + QString url = QString("%1?id=%2").arg(REQUEST_TRANSCRIPT_URL, trackingId); + QUrl transcriptUrl = QUrl(url); + QNetworkRequest request(transcriptUrl); + request.setRawHeader("Authorization", authHeaderData); + networkManager->get(request); +} +void MainWindow::openContainingDir(){ + qDebug("Called"); + auto filePath = TRANSCRIPT_TARGET_DIR; + QStringList args; + #ifdef Q_OS_LINUX + args << QDir::toNativeSeparators(filePath); + QProcess::startDetached("/usr/bin/thunar", args); + #endif + #ifdef Q_OS_WIN + QStringList args; + args << "/select," << QDir::toNativeSeparators(filePath); + QProcess::startDetached("explorer", args); + #endif +} + +void MainWindow::updateList(QNetworkReply* reply){ + if(reply->error() != QNetworkReply::NoError){ + showNotification("HTTP Error on status Request"); + return; + } + + /* get filename and tracking id from replay */ + QJsonObject json = QJsonDocument::fromJson(reply->readAll()).object(); + for(int i = 0; irowCount(); i++){ + auto trackingId = tw->model()->data(tw->model()->index(i, TRACKING_ID_COL)).toString(); + + if(json.contains(trackingId)){ + QJsonArray statusArray = json.value(trackingId).toArray(); + if(statusArray.size() == 0){ + qDebug("Status array empty wtf?"); + } + + auto currentStatus = statusArray[statusArray.size()-1].toObject(); + auto status = currentStatus["status"].toString(); + auto percentage = currentStatus["percent"].toInt(); + auto statusMsg = currentStatus["message"].toString(); + + auto pg = tw->cellWidget(i, PG_BAR_COL)->findChild(); + pg->setFormat(statusMsg); + pg->setValue(100); + + if(percentage == -1){ + pg->setValue(100); + pg->setStyleSheet("QProgressBar::chunk { background-color: red; }"); + }else if(percentage == 100){ + pg->setValue(percentage); + pg->setStyleSheet("QProgressBar::chunk { background-color: green; }"); + auto status = tw->model()->data(tw->model()->index(i, TRANSCRIPT_STATUS_COL)); + auto tStatus = status.toString().toInt(); + if(tStatus == 0){ + queryTransscript(trackingId); + } + }else{ + pg->setValue(percentage); + } + } + } +} + +void MainWindow::saveTranscript(QNetworkReply* reply){ + + /* get return data */ + QJsonDocument json = QJsonDocument::fromJson(reply->readAll()); + auto transcript = json["transcript"].toString(); + auto trackingId = json["id"].toString(); + auto targetName = json["true-name"].toString(); + if(QString::compare(trackingId, "") == 0){ + qFatal("Empty TrackingId, file might have been request by it's name."); + } + + /* get filename for id */ + QString filename; + int rowId = -1; + for(int i = 0; irowCount(); i++){ + auto curId = tw->model()->data(tw->model()->index(i, TRACKING_ID_COL)).toString(); + auto curName = tw->model()->data(tw->model()->index(i, FILENAME_COL)).toString(); + if(QString::compare(trackingId, curId) == 0){ + filename = curName; + rowId = i; + break; + } + } + + /* save return data */ + QString fullpath = QDir(TRANSCRIPT_TARGET_DIR).filePath(targetName); + qDebug(qPrintable(fullpath)); + QFile file(fullpath); + if (!file.open(QIODevice::WriteOnly)) { + QMessageBox::information(this, tr("Unable to open file"), file.errorString()); + qWarning("Error opening File"); + } + QDataStream out(&file); + out.setVersion(QDataStream::Qt_4_5); + out << transcript; + file.close(); + + /* mark as downloaded */ + auto ts = new QTableWidgetItem(); + ts->setData(Qt::DisplayRole, 1); + tw->setItem(rowId, TRANSCRIPT_STATUS_COL, ts); +} + +void MainWindow::addTrackingToList(QNetworkReply* reply){ + if(reply->error() != QNetworkReply::NoError){ + showNotification("Fehler bei Dateiübertragung, keine Tracking-ID zugewiesen!"); + return; + } + + /* add new row */ + tw->insertRow(tw->rowCount()); + auto row = tw->rowCount() - 1; + + /* get filename and tracking id from replay */ + QJsonDocument json = QJsonDocument::fromJson(reply->readAll()); + auto filename = json["filename"].toString(); + auto trackingId = json["trackingId"].toString(); + + /* create cusomt widget for pg bar */ + auto *pgBarLayout = new QGridLayout(); + auto *pg = new QProgressBar(); + auto *pgBarCellContent = new QWidget(); + pg->setRange(0,100); + pg->setValue(0); + pg->setTextVisible(true); + pg->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + const QFont *font = new QFont("Times", 12, QFont::Weight::Bold, false); + pg->setFont(*font); + pg->setAlignment(Qt::AlignCenter); + + pgBarLayout->addWidget(pg); + pgBarLayout->setContentsMargins(0,0,0,0); + pgBarCellContent->setLayout(pgBarLayout); + + /* create cusomt widget for open-dir button */ + auto *openDirLayout = new QGridLayout(); + auto dirButton = new QPushButton("Ordner"); + connect(dirButton, SIGNAL (released()), this, SLOT (openContainingDir())); + + auto *openDirCellContent = new QWidget(); + openDirLayout->addWidget(dirButton); + dirButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + openDirLayout->setContentsMargins(0,0,0,0); + openDirCellContent->setLayout(openDirLayout); + + /* set values */ + tw->setItem(row, FILENAME_COL, new QTableWidgetItem(filename)); + tw->setItem(row, TRACKING_ID_COL, new QTableWidgetItem(trackingId)); + tw->setCellWidget(row, PG_BAR_COL, pgBarCellContent); + tw->setCellWidget(row, OPEN_DIR_COL, openDirCellContent); + + + /* set transcript status */ + auto ts = new QTableWidgetItem(); + ts->setData(Qt::DisplayRole, 0); + tw->setItem(row, TRANSCRIPT_STATUS_COL, ts); + tw->setColumnHidden(TRACKING_ID_COL, true); + + qDebug("Reply added to be tracked by list"); +} + +void MainWindow::requestFinished(QNetworkReply *reply){ + qDebug(qPrintable(reply->url().toString())); + if(QString::compare(reply->url().toString(), SUBMIT_URL) == 0){ + addTrackingToList(reply); + }else if (QString::compare(reply->url().toString(), STATUS_REQUEST_URL) == 0) { + updateList(reply); + }else if (reply->url().toString().startsWith(REQUEST_TRANSCRIPT_URL)) { + qDebug("Saving transcript"); + saveTranscript(reply); + }else{ + qDebug("URL-Response: %s", qUtf8Printable(reply->url().toString())); + qFatal("Unexpected responding URL"); + } + //qDebug("Reply handling finished"); +} + +void MainWindow::queryStatusAll(){ + QUrl trackingUrl = QUrl(STATUS_REQUEST_URL); + QNetworkRequest request(trackingUrl); + request.setRawHeader("Authorization", authHeaderData); + networkManager->get(request); + //qDebug("Status query sent"); +} MainWindow::~MainWindow() { diff --git a/mainwindow.h b/mainwindow.h index a474b4b..2820f97 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace Ui { class MainWindow; @@ -19,12 +20,22 @@ public: private slots: void importFile(); - void fileSubmissionFinished(QNetworkReply*); - + void requestFinished(QNetworkReply*); + void queryStatusAll(); + void openContainingDir(); private: Ui::MainWindow *ui; + QTableWidget *tw; QPushButton *button; + QByteArray authHeaderData; + QNetworkAccessManager *networkManager; void submitFile(QString filename); + void setAuthHeader(const QString username, const QString password); + void updateList(QNetworkReply *reply); + void addTrackingToList(QNetworkReply *reply); + void showNotification(QString str); + void queryTransscript(QString trackingId); + void saveTranscript(QNetworkReply *reply); }; #endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui index cf58991..cc90630 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -22,15 +22,8 @@ - - - - 24 - - - - + @@ -43,15 +36,33 @@ 20 + + + &Konfiguration + + + + + TopToolBarArea - true + false + + + Server + + + + + Standards + + diff --git a/notificationwidget.cpp b/notificationwidget.cpp new file mode 100644 index 0000000..446bb97 --- /dev/null +++ b/notificationwidget.cpp @@ -0,0 +1,97 @@ +#include +#include +#include + +#include "notificationwidget.h" + +#include + +NotificationWidget::NotificationWidget(QWidget *parent) : + QWidget(parent) +{ + resize(200, 50); + + setWindowFlags(Qt::FramelessWindowHint | Qt::Tool); + setAttribute(Qt::WA_TranslucentBackground); + setAttribute(Qt::WA_ShowWithoutActivating); + + animation.setTargetObject(this); + animation.setPropertyName("popupOpacity"); + animation.setDuration(150); + + label.setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + + layout.addWidget(&label, 0, 0); + setLayout(&layout); + setAttribute(Qt::WA_X11NetWmWindowTypeSplash); +} + +void NotificationWidget::paintEvent(QPaintEvent *e) +{ + Q_UNUSED(e) + + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + + // Prepare the popup dimensions + QRect roundedRectDimensions; + roundedRectDimensions.setX(rect().x() + 5); + roundedRectDimensions.setY(rect().y() + 5); + roundedRectDimensions.setWidth(rect().width() - 10); + roundedRectDimensions.setHeight(rect().height() - 10); + + painter.setBrush(QBrush(Qt::lightGray)); + + QPen pen; + pen.setColor(Qt::gray); + pen.setWidth(3); + painter.setPen(pen); + + // Draw the popup body + painter.drawRoundedRect(roundedRectDimensions, 15, 15); +} + +void NotificationWidget::setPopupText(const QString &text) +{ + label.setText(text); +} + +void NotificationWidget::show() +{ + setWindowOpacity(0.0); + + animation.setStartValue(0.0); + animation.setEndValue(1.0); + + QWidget::show(); + + animation.start(); +} + +void NotificationWidget::setPopupOpacity(float opacity) +{ + popupOpacity = opacity; + setWindowOpacity(static_cast(opacity)); +} + +float NotificationWidget::getPopupOpacity() const +{ + return popupOpacity; +} + +void NotificationWidget::fadeOut(){ + QGraphicsOpacityEffect *effect = new QGraphicsOpacityEffect(); + setGraphicsEffect(effect); + QPropertyAnimation *a = new QPropertyAnimation(effect,"opacity"); + a->setDuration(1000); // it will took 1000ms to face out + a->setStartValue(1); + a->setEndValue(0); + a->setEasingCurve(QEasingCurve::OutBack); + a->start(QPropertyAnimation::DeleteWhenStopped); + connect(a, SIGNAL(finished()), this, SLOT(hideAndDestroy())); +} + +void NotificationWidget::hideAndDestroy(){ + this->hide(); + delete this; +} diff --git a/notificationwidget.h b/notificationwidget.h new file mode 100644 index 0000000..1a2b632 --- /dev/null +++ b/notificationwidget.h @@ -0,0 +1,38 @@ +#ifndef NOTIFICATIONWIDGET_H +#define NOTIFICATIONWIDGET_H + +#include +#include +#include +#include + +class NotificationWidget : public QWidget +{ + Q_OBJECT + + Q_PROPERTY(float popupOpacity READ getPopupOpacity WRITE setPopupOpacity) + + void setPopupOpacity(float opacity); + float getPopupOpacity() const; + +public: + explicit NotificationWidget(QWidget *parent = nullptr); +protected: + void paintEvent(QPaintEvent *e); + +public slots: + void setPopupText(const QString& text); + void show(); + void fadeOut(); + +private slots: + void hideAndDestroy(); + +private: + QLabel label; + QGridLayout layout; + QPropertyAnimation animation; + float popupOpacity; +}; + +#endif // NOTIFICATIONWIDGET_H diff --git a/untitled.pro b/untitled.pro index bd9e486..9e65277 100644 --- a/untitled.pro +++ b/untitled.pro @@ -26,10 +26,12 @@ CONFIG += c++11 SOURCES += \ main.cpp \ - mainwindow.cpp + mainwindow.cpp \ + notificationwidget.cpp HEADERS += \ - mainwindow.h + mainwindow.h \ + notificationwidget.h FORMS += \ mainwindow.ui