Implement basic functionality

This commit is contained in:
Yannik Schmidt
2020-08-07 21:47:48 +02:00
parent 91988b0bed
commit 92f25e11e1
6 changed files with 449 additions and 32 deletions

View File

@@ -1,72 +1,330 @@
#include "mainwindow.h" #include "mainwindow.h"
#include "notificationwidget.h"
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
#include <QCoreApplication> #include <QCoreApplication>
#include <QFileDialog> #include <QFileDialog>
#include <QMainWindow> #include <QMainWindow>
#include <QDebug> #include <QDebug>
#include <QJsonObject> #include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument> #include <QJsonDocument>
#include <QTimer>
#include <QMessageBox>
#include <QPushButton>
#include <QProgressBar>
#include <QProcess>
#include <QtNetwork/QNetworkAccessManager> #include <QtNetwork/QNetworkAccessManager>
MainWindow::MainWindow(QWidget *parent) : #define FILENAME_COL 0
QMainWindow(parent), #define TRACKING_ID_COL 1
ui(new Ui::MainWindow) #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); ui->setupUi(this);
setAuthHeader("user", "pass");
networkManager = new QNetworkAccessManager(this);
/* setup buttons */
button = ui->centralWidget->findChild<QPushButton*>("pushButton"); button = ui->centralWidget->findChild<QPushButton*>("pushButton");
connect(button, SIGNAL (released()), this, SLOT (importFile())); connect(button, SIGNAL (released()), this, SLOT (importFile()));
/* table ui */
tw = ui->centralWidget->findChild<QTableWidget*>("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( QString filename = QFileDialog::getOpenFileName(
this, this,
"Open Document", "Open Document",
QDir::currentPath(), QDir::currentPath(),
"All files (*.*) ;; Document files (*.doc *.rtf);; PNG files (*.png)"); "All files (*.*) ;; Document files (*.doc *.rtf);; PNG files (*.png)");
if( !filename.isNull() ){
if(filename.isNull()){
return; 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 */ /* prepare auth */
QString username = "lol";
QString password = "lol";
QString concatenated = username + ":" + password; QString concatenated = username + ":" + password;
QByteArray data = concatenated.toLocal8Bit().toBase64(); QByteArray data = concatenated.toLocal8Bit().toBase64();
QString authHeaderData = "Basic " + data; QString authHeaderStr = "Basic " + data;
authHeaderData = authHeaderStr.toLocal8Bit();
}
void MainWindow::submitFile(QString filename){
/* prepare request */ /* prepare request */
QUrl serviceUrl = QUrl("http://localhost:5000"); QUrl serviceUrl = QUrl(SUBMIT_URL);
QNetworkRequest request(serviceUrl); QNetworkRequest request(serviceUrl);
request.setRawHeader("Authorization", authHeaderData.toLocal8Bit()); request.setRawHeader("Authorization", authHeaderData);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
/* read audio as base64 */ /* read audio as base64 */
QFile sourceFile(filename); QFile sourceFile(filename);
sourceFile.open(QIODevice::ReadOnly | QIODevice::Text);
QByteArray base64Encoded = sourceFile.readAll().toBase64(); QByteArray base64Encoded = sourceFile.readAll().toBase64();
QString dataString = QString::fromUtf8(base64Encoded); QString dataString = QString::fromUtf8(base64Encoded);
sourceFile.close();
/* prepare json */ /* prepare json */
QJsonObject json = QJsonObject(); QJsonObject json = QJsonObject();
QJsonValue dataFieldContent = QJsonValue(dataString); QJsonValue dataFieldContent = QJsonValue(dataString);
QFileInfo info(filename); QFileInfo info(filename);
QString basename(info.fileName()); QString basename(info.fileName());
json["filename"] = filename; json["filename"] = filename;
json["data"] = dataFieldContent; json["data"] = dataFieldContent;
/* make request */ /* make request */
QNetworkAccessManager *networkManager = new QNetworkAccessManager(this);
connect(networkManager, SIGNAL(finished(QNetworkReply*)), this, connect(networkManager, SIGNAL(finished(QNetworkReply*)), this,
SLOT(fileSubmissionFinished(QNetworkReply*))); SLOT(requestFinished(QNetworkReply*)), Qt::UniqueConnection);
networkManager->post(request, QJsonDocument(json).toJson()); 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; i<tw->rowCount(); 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<QProgressBar*>();
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; i<tw->rowCount(); 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() MainWindow::~MainWindow()
{ {

View File

@@ -4,6 +4,7 @@
#include <QMainWindow> #include <QMainWindow>
#include <QNetworkReply> #include <QNetworkReply>
#include <QPushButton> #include <QPushButton>
#include <QTableWidget>
namespace Ui { namespace Ui {
class MainWindow; class MainWindow;
@@ -19,12 +20,22 @@ public:
private slots: private slots:
void importFile(); void importFile();
void fileSubmissionFinished(QNetworkReply*); void requestFinished(QNetworkReply*);
void queryStatusAll();
void openContainingDir();
private: private:
Ui::MainWindow *ui; Ui::MainWindow *ui;
QTableWidget *tw;
QPushButton *button; QPushButton *button;
QByteArray authHeaderData;
QNetworkAccessManager *networkManager;
void submitFile(QString filename); 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 #endif // MAINWINDOW_H

View File

@@ -22,15 +22,8 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0">
<widget class="QProgressBar" name="progressBar">
<property name="value">
<number>24</number>
</property>
</widget>
</item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QTableView" name="tableView"/> <widget class="QTableWidget" name="tableWidget"/>
</item> </item>
</layout> </layout>
</widget> </widget>
@@ -43,15 +36,33 @@
<height>20</height> <height>20</height>
</rect> </rect>
</property> </property>
<widget class="QMenu" name="menuKonfiguration">
<property name="title">
<string>&amp;Konfiguration</string>
</property>
<addaction name="actionServer"/>
<addaction name="actionStandards"/>
</widget>
<addaction name="menuKonfiguration"/>
</widget> </widget>
<widget class="QToolBar" name="mainToolBar"> <widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea"> <attribute name="toolBarArea">
<enum>TopToolBarArea</enum> <enum>TopToolBarArea</enum>
</attribute> </attribute>
<attribute name="toolBarBreak"> <attribute name="toolBarBreak">
<bool>true</bool> <bool>false</bool>
</attribute> </attribute>
</widget> </widget>
<action name="actionServer">
<property name="text">
<string>Server</string>
</property>
</action>
<action name="actionStandards">
<property name="text">
<string>Standards</string>
</property>
</action>
</widget> </widget>
<layoutdefault spacing="6" margin="11"/> <layoutdefault spacing="6" margin="11"/>
<resources/> <resources/>

97
notificationwidget.cpp Normal file
View File

@@ -0,0 +1,97 @@
#include <QGraphicsOpacityEffect>
#include <QPropertyAnimation>
#include <QString>
#include "notificationwidget.h"
#include <QPainter>
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<double>(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;
}

38
notificationwidget.h Normal file
View File

@@ -0,0 +1,38 @@
#ifndef NOTIFICATIONWIDGET_H
#define NOTIFICATIONWIDGET_H
#include <QWidget>
#include <QLabel>
#include <QGridLayout>
#include <QPropertyAnimation>
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

View File

@@ -26,10 +26,12 @@ CONFIG += c++11
SOURCES += \ SOURCES += \
main.cpp \ main.cpp \
mainwindow.cpp mainwindow.cpp \
notificationwidget.cpp
HEADERS += \ HEADERS += \
mainwindow.h mainwindow.h \
notificationwidget.h
FORMS += \ FORMS += \
mainwindow.ui mainwindow.ui