diff --git a/check/check.cpp b/check/check.cpp index a4c41a0..72fcf2b 100644 --- a/check/check.cpp +++ b/check/check.cpp @@ -1,14 +1,19 @@ #include "check.h" #include "../goods/goods.h" +#include Check::Check() {} -void Check::add_goods(Goods goods) { this->goods.push_back(goods); } +void Check::add_goods(Goods goods) { + this->goods.push_back(goods); + this->total = this->calculae_total_price(); +} void Check::add_goods(std::vector &goods) { - for (auto g : goods) { + for (auto &g : goods) { this->goods.push_back(g); } + this->total = this->calculae_total_price(); } double Check::calculae_total_price() { @@ -17,7 +22,6 @@ double Check::calculae_total_price() { for (Goods &g : goods) { total += g.calculate_total_price(); } - return total; } @@ -25,6 +29,64 @@ std::vector& Check::get_goods() { return goods; } +void Check::set_fn(std::string fn) { + this->fn = fn; +} + +void Check::set_fd(std::string fd) { + this->fd = fd; +} + +void Check::set_fi(std::string fi) { + this->fi = fi; +} + std::string Check::get_date() { return date; } + +void Check::set_date(std::string date) { + this->date = date; +} + +void Check::set_operation_type(OperationType t) { + this->operation_type = t; +} + +double Check::get_total() { + return total; +} + +bool Check::operator==(Check &c) { + // std::cout << "Comparing" << std::endl; + // std::cout << this->date << " <>" << c.date << std::endl; + // std::cout << this->fd << " <>" << c.fd << std::endl; + // std::cout << this->fi<< " <>" << c.fi << std::endl; + // std::cout << this->fn<< " <>" << c.fn << std::endl; + // std::cout << this->operation_type << " <>" << c.operation_type << std::endl; + // std::cout << this->total<< " <>" << c.total<< std::endl; + return + this->date == c.date && + this->fd == c.fd && + this->fi == c.fi && + this->fn == c.fn && + this->operation_type == c.operation_type && + this->total == c.total; +} + +bool Check::operator==(const Check &c) { + // std::cout << "Comparing" << std::endl; + // std::cout << this->date << " <>" << c.date << std::endl; + // std::cout << this->fd << " <>" << c.fd << std::endl; + // std::cout << this->fi<< " <>" << c.fi << std::endl; + // std::cout << this->fn<< " <>" << c.fn << std::endl; + // std::cout << this->operation_type << " <>" << c.operation_type << std::endl; + // std::cout << this->total<< " <>" << c.total<< std::endl; + return + this->date == c.date && + this->fd == c.fd && + this->fi == c.fi && + this->fn == c.fn && + this->operation_type == c.operation_type && + this->total == c.total; +} diff --git a/check/check.h b/check/check.h index 1fc64d8..1d97a04 100644 --- a/check/check.h +++ b/check/check.h @@ -43,6 +43,9 @@ public: std::string get_date(); OperationType get_operationType(); double get_total(); + + bool operator==(Check &); + bool operator==(const Check &); }; #endif // CHECK_H diff --git a/deploy/base-docker/ubuntu/Dockerfile b/deploy/base-docker/ubuntu/Dockerfile index 3235e01..56e00c9 100644 --- a/deploy/base-docker/ubuntu/Dockerfile +++ b/deploy/base-docker/ubuntu/Dockerfile @@ -1,9 +1,9 @@ -FROM ubuntu:18.04 +FROM ubuntu:24.04 # Installing dependencies RUN apt update -RUN DEBIAN_FRONTEND=noninteractive apt install -y qtbase5-dev openssl libmbedtls-dev libopencv-dev libzbar-dev qttools5-dev nlohmann-json-dev libcurl4-openssl-dev libqrencode-dev +RUN DEBIAN_FRONTEND=noninteractive apt install -y qt6-base-dev qt6-tools-dev openssl libmbedtls-dev libopencv-dev libzbar-dev nlohmann-json3-dev libcurl4-openssl-dev libqrencode-dev RUN DEBIAN_FRONTEND=noninteractive apt install -y wget git cmake make gcc g++ fuse libboost-regex-dev WORKDIR /app @@ -21,6 +21,8 @@ COPY net ./net COPY translations ./translations COPY http_server ./http_server COPY utils ./utils +COPY widgets ./widgets +COPY email_parser ./email_parser COPY ./*.h ./*cpp ./*.ui ./*.qrc CMakeLists.txt . diff --git a/mainwindow.cpp b/mainwindow.cpp index 9395261..6704aa3 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -33,11 +33,13 @@ MainWindow::MainWindow(QWidget *parent) ui->stop_server_button->hide(); QVBoxLayout *layout = new QVBoxLayout; + + ui->checks_scroll_area->setLayout(layout); ui->scrollAreaWidgetContents->setLayout(layout); - QLabel a = QLabel("123"); - layout->addWidget(&a); - // ui->checks_to_parse_label->hide(); - // ui->checks_scroll_area->hide(); + ui->checks_to_parse_label->hide(); + ui->checks_scroll_area->hide(); + + connect(this, &MainWindow::deleteCheckFromList, this, &MainWindow::deleteCheckFromListHandler); #ifdef BUILD_OFD_BINARYEYE_SCAN QObject::connect(this, &MainWindow::httpErrorOccured, this, &MainWindow::notifyHttpServerFailure); @@ -97,7 +99,7 @@ void MainWindow::on_binary_eye_button_clicked() { infoDialog.setText(QString::fromStdString(connectionString)); infoDialog.setIconPixmap(QPixmap(QString::fromStdString(get_path_relative_to_home(".local/share/checks_parser/binaryeye_connection.png"))).scaled(400, 400, Qt::KeepAspectRatio)); infoDialog.setWindowTitle(tr("QR code for binaryeye to connect")); - infoDialog.setButtonText(1, tr("I've scanned")); + infoDialog.addButton(tr("I've scanned"), QMessageBox::ButtonRole::AcceptRole); infoDialog.exec(); } @@ -206,6 +208,30 @@ void MainWindow::on_parse_button_clicked() { d.exec(); } +void MainWindow::deleteCheckFromListHandler(Check &check) { + for (unsigned int i = 0; i < ui->scrollAreaWidgetContents->layout()->count(); i ++) { + QLayoutItem *item = ui->scrollAreaWidgetContents->layout()->itemAt(i); + QObject *child = item->widget(); + CheckListViewWidget *c = (CheckListViewWidget *)child; + if (c->get_check() == check) { + ui->scrollAreaWidgetContents->layout()->removeItem(item); + delete item; + delete child; + ui->scrollAreaWidgetContents->layout()->update(); + ui->scrollAreaWidgetContents->update(); + + } + } + + int position = std::find(checks.begin(), checks.end(), check) - checks.begin() - 1; + checks.erase(checks.begin() + position); + + if (ui->scrollAreaWidgetContents->layout()->count() == 0) { + ui->checks_to_parse_label->hide(); + ui->checks_scroll_area->hide(); + } +} + void MainWindow::on_add_new_check_button_clicked() { Check *new_check = parse_new_check(); if (new_check == nullptr) { @@ -214,10 +240,9 @@ void MainWindow::on_add_new_check_button_clicked() { checks.push_back(*new_check); - CheckListViewWidget check_list_widget(this, *new_check); + CheckListViewWidget *check_list_widget = new CheckListViewWidget(this, *new_check); - auto a = QLabel("123"); - ui->scrollAreaWidgetContents->layout()->addWidget(&a); + ui->scrollAreaWidgetContents->layout()->addWidget(check_list_widget); delete new_check; @@ -250,6 +275,11 @@ Check *MainWindow::parse_new_check() { solved_captcha); (*check) = parseOfdRuAnswer(check_content); + check->set_date(ui->purchase_datetime_edit->dateTime().toString(Qt::ISODate).toStdString()); + check->set_fn(ui->fn_line_edit->text().toStdString()); + check->set_fd(ui->fd_line_edit->text().toStdString()); + check->set_fi(ui->fi_line_edit->text().toStdString()); + check->set_operation_type(OperationType(ui->operation_type_combo_box->currentIndex() + 1)); return check; } catch(OfdRequestException e) { if (!strcmp(e.what(), "Incorrect captcha")) { diff --git a/mainwindow.h b/mainwindow.h index 055f1d4..2e66a0c 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -22,6 +22,7 @@ public: ~MainWindow(); Check *parse_new_check(); + #ifdef BUILD_OFD_BINARYEYE_SCAN void startHttpServer(); #endif @@ -29,6 +30,7 @@ public: signals: void httpNewMessage(QString message); void httpErrorOccured(); + void deleteCheckFromList(Check&); private slots: #ifdef BUILD_OFD_LOCAL_QR_SCAN @@ -45,12 +47,12 @@ private slots: void on_stop_server_button_clicked(); void httpNewMessageHandler(QString message); + void deleteCheckFromListHandler(Check&); #endif #ifdef BUILD_EMAIL_MODE void on_parse_email_button_clicked(); #endif void on_add_new_check_button_clicked(); - private: Ui::MainWindow *ui; std::vector checks; diff --git a/outputdialog.cpp b/outputdialog.cpp index b32d9c7..b78c1f6 100644 --- a/outputdialog.cpp +++ b/outputdialog.cpp @@ -15,6 +15,12 @@ OutputDialog::OutputDialog(QWidget *parent, std::vector *checks) ui->setupUi(this); + ui->tableWidget->resizeColumnsToContents(); + ui->tableWidget->verticalHeader()->setSectionsMovable(true); + ui->tableWidget->verticalHeader()->setDragDropOverwriteMode(false); + ui->tableWidget->verticalHeader()->setDragEnabled(true); + ui->tableWidget->verticalHeader()->setDragDropMode(QAbstractItemView::InternalMove); + ui->tableWidget->item(0, 1)->setText(QString::fromStdString(settings.get_all_settings()["output_order"]["date"]["name"])); ui->tableWidget->item(0, 0)->setText(QString::number((int)settings.get_all_settings()["output_order"]["date"]["position"])); @@ -79,7 +85,7 @@ void OutputDialog::on_buttonBox_accepted() { for (auto &column : this->options.get_columns()) { switch (column.type) { case ColumnType::date: - if (i == 0) output_file << "date goes here"; + if (i == 0) output_file << check.get_date(); break; case ColumnType::goods_name: output_file << it->get_name(); diff --git a/scenes/mainwindow.ui b/scenes/mainwindow.ui index abb62c7..92e155e 100644 --- a/scenes/mainwindow.ui +++ b/scenes/mainwindow.ui @@ -26,10 +26,10 @@ Form - - + + - + 0 0 @@ -39,23 +39,10 @@ - - + + - Add new check - - - - - - - - 0 - 0 - - - - FN (Fiscal Number) + Date and time of purchase @@ -72,118 +59,6 @@ - - - - - - - - 0 - 0 - - - - Choose image on your PC - - - - - - - - 0 - 0 - - - - Stop server - - - - - - - FI (Fiscal Identifier) - - - - - - - - 0 - 0 - - - - Settings - - - - - - - Total - - - - - - - - 0 - 0 - - - - - - - - - - - - 0 - 0 - - - - Clear - - - - - - - Date and time of purchase - - - - - - - - 0 - 0 - - - - or - - - - - - - Operation type - - - - - - @@ -191,16 +66,20 @@ - - - - - 0 - 0 - - + + - Use your phone as a QR code scanner + Checks to parse + + + Qt::AlignmentFlag::AlignCenter + + + + + + + FI (Fiscal Identifier) @@ -217,8 +96,41 @@ - - + + + + + 0 + 0 + + + + Settings + + + + + + + + 0 + 0 + + + + FN (Fiscal Number) + + + + + + + Total + + + + + 0 @@ -226,10 +138,49 @@ - Parse an E-Mail + Use your phone as a QR code scanner + + + + + 0 + 0 + + + + or + + + + + + + + 0 + 0 + + + + Choose image on your PC + + + + + + + + 0 + 0 + + + + + + + @@ -243,6 +194,19 @@ + + + + + 0 + 0 + + + + Stop server + + + @@ -267,14 +231,54 @@ - - + + + + Operation type + + + + + - + 0 0 + + Parse an E-Mail + + + + + + + + 0 + 0 + + + + Clear + + + + + + + + + + Add new check + + + + + + + + true @@ -290,16 +294,6 @@ - - - - Checks to parse - - - Qt::AlignmentFlag::AlignCenter - - - diff --git a/scenes/outputdialog.ui b/scenes/outputdialog.ui index 277e601..dc83715 100644 --- a/scenes/outputdialog.ui +++ b/scenes/outputdialog.ui @@ -14,13 +14,10 @@ Dialog - - - - Qt::Orientation::Horizontal - - - QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok + + + + Path to export: @@ -45,15 +42,18 @@ - - - - Path to export: + + + + Qt::Orientation::Horizontal + + + QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok - + 0 @@ -200,6 +200,13 @@ + + + TableWidgetMovable + QTableWidget +
widgets/tablewidgetmovable.hpp
+
+
diff --git a/translations/en_US.ts b/translations/en_US.ts index c2c5e77..c4af473 100644 --- a/translations/en_US.ts +++ b/translations/en_US.ts @@ -70,7 +70,7 @@ Store type - + Parse Parse @@ -113,13 +113,13 @@ 0000000000000000 - + FN (Fiscal Number) FN = Фискальный Номер FN (Fiscal Number) - + FD (Fiscal Document) FD = Фискальный Документ FD (Fiscal Document) @@ -133,93 +133,93 @@ Back - + Stop server Stop server - + Choose image on your PC Choose image on your PC - + or or - + Use your phone as a QR code scanner Use your phone as a QR code scanner - + FI (Fiscal Identifier) FI = Фискальный Признак FI (Fiscal Identifier) - + Add new check Add new check - + Clear Clear - + Date and time of purchase Date and time of purchase - + Operation type Operation type - + Parse an E-Mail Parse an E-Mail - + Funds income Приход средств Funds income - + Funds return Возврат средств Funds return - + Funds spend Расход средств Funds spend - + Spends return Возврат расхода Spends return - + Checks to parse Checks to parse - + Settings Settings - + Total Total @@ -228,37 +228,37 @@ checks parser - + QR code for binaryeye to connect QR code for binaryeye to connect - + I've scanned I've scanned - + Could not start http server. 10 times in a row random port was occupied. Either you should run for a lottery ticket, or the problem is in the program. If the lottery ticket wasn't lucky, please, contact the developer. Could not start http server. 10 times in a row random port was occupied. Either you should run for a lottery ticket, or the problem is in the program. If the lottery ticket wasn't lucky, please, contact the developer. - + Could not start http server. Could not start http server. - + Selected image: Selected image: - + This feature is under development. Wait it to appear in next updates. This feature is under development. Wait for it to appear in next updates. - + Under development Under development @@ -271,32 +271,32 @@ No checks to parse - + Captcha was not solved correctly! Captcha was not solved correctly! - + Captcha is incorrect Captcha is incorrect - + Internal server error. Please, try again later. Internal server error. Please, try again later. - + Internal server error Internal server error - + Check not found. Please, ensure correctness of entered data. Check not found. Please, ensure correctness of entered data. - + Check was not found Check was not found @@ -309,12 +309,12 @@ Error in parsing - + Please, select a picture where QR code that contains info about check is present Please, select a picture where QR code that contains info about check is present - + Picture was not selected Picture was not selected @@ -522,17 +522,17 @@ Dialog - + Path to export: Path to export: - + Choose Choose - + Print header Print header @@ -633,7 +633,7 @@ Total price - + Print total Print total diff --git a/translations/ru_RU.ts b/translations/ru_RU.ts index 738f8df..46fc56b 100644 --- a/translations/ru_RU.ts +++ b/translations/ru_RU.ts @@ -70,7 +70,7 @@ Магазин - + Parse Парсить @@ -113,13 +113,13 @@ 0000000000000000 - + FN (Fiscal Number) Фискальный Норма ФН - + FD (Fiscal Document) Фискальный Документ ФД @@ -133,89 +133,89 @@ Назад - + Stop server Остановить сервер - + Choose image on your PC Выбрать изображение на компьютере - + or или - + Use your phone as a QR code scanner Использовать телефон как сканнер QR - + FI (Fiscal Identifier) Фискальный Признак ФП - + Add new check - + Clear - + Date and time of purchase Дата и время покупки - + Operation type Тип операции - + Parse an E-Mail Парсить E-Mail - + Funds income Приход средств - + Funds return Возврат средств - + Funds spend Расход средств - + Spends return Возврат расхода - + Checks to parse - + Settings Настройки - + Total Итого @@ -224,67 +224,67 @@ Парсер чеков - + QR code for binaryeye to connect QR код для подключения BinaryEye - + I've scanned Просканировал - + Could not start http server. 10 times in a row random port was occupied. Either you should run for a lottery ticket, or the problem is in the program. If the lottery ticket wasn't lucky, please, contact the developer. Не смог поднять HTTP сервер. 10 раз подряд случайно выбранный порт был занят. Либо Вам следует бежать за лоттерейным билетом, или в программе баг. Если лотерейный билет не был выигрышным, пожалуйста, сообщите разработчику. - + Could not start http server. Не получилось запустить HTTP сервер. - + Selected image: Выбранное изображение: - + This feature is under development. Wait it to appear in next updates. - + Under development - + Captcha was not solved correctly! Капча была решена неверно! - + Captcha is incorrect Капча введена неверно - + Internal server error. Please, try again later. Внутренняя ошибка сервера. Пожалуйста, попробуйте снова позже. - + Internal server error Внутренняя ошибка сервера - + Check not found. Please, ensure correctness of entered data. Чек не найден. Пожалуйста, убедитесь в правильности введённых данных. - + Check was not found Чек не найден @@ -297,12 +297,12 @@ Ошибка в парсинге - + Please, select a picture where QR code that contains info about check is present Пожалуйста, выберете изображение, содержащее QR код с информацией о чеке - + Picture was not selected Изображение не было выбрано @@ -510,17 +510,17 @@ Диалог - + Path to export: Путь для экспорта: - + Choose Выбрать - + Print header Печатать заголовок @@ -621,7 +621,7 @@ Всего - + Print total Печатать Итого diff --git a/widgets/checklistviewwidget.cpp b/widgets/checklistviewwidget.cpp index ce28851..0ca4de6 100644 --- a/widgets/checklistviewwidget.cpp +++ b/widgets/checklistviewwidget.cpp @@ -7,23 +7,30 @@ #include CheckListViewWidget::CheckListViewWidget(QWidget *parent, Check check) : QWidget(parent), check(check) { + mw = (MainWindow*) parent; std::cout << "I was created with check with date " << check.get_date() << std::endl; QHBoxLayout *layout = new QHBoxLayout; - QLabel *label1 = new QLabel(QString::fromStdString(check.get_date())); - QLabel *label2 = new QLabel("Text 2"); - QLabel *label3 = new QLabel("Text 3"); + QLabel *date_label = new QLabel(QString::fromStdString(check.get_date())); + QLabel *summ_label = new QLabel(QString::number(check.get_total())); QPushButton *deleteButton = new QPushButton(tr("Delete")); - deleteButton->connect(deleteButton, &QPushButton::clicked, this, &CheckListViewWidget::deleteButtonPressed); + deleteButton->connect(deleteButton, &QPushButton::clicked, this, &CheckListViewWidget::delete_button_pressed); - layout->addWidget(label1); - layout->addWidget(label2); - layout->addWidget(label3); + layout->addWidget(date_label); + layout->addWidget(summ_label); layout->addSpacing(10); layout->addWidget(deleteButton); setLayout(layout); } + +Check &CheckListViewWidget::get_check(){ + return check; +} + +void CheckListViewWidget::delete_button_pressed() { + emit mw->deleteCheckFromList(this->check); +} diff --git a/widgets/checklistviewwidget.h b/widgets/checklistviewwidget.h index 05609d5..e079425 100644 --- a/widgets/checklistviewwidget.h +++ b/widgets/checklistviewwidget.h @@ -3,6 +3,7 @@ #include #include +#include #include @@ -10,9 +11,12 @@ class CheckListViewWidget : public QWidget { Q_OBJECT Check check; + MainWindow* mw; public: explicit CheckListViewWidget(QWidget *parent = nullptr, Check check = Check()); + Check &get_check(); + void delete_button_pressed(); signals: Check deleteButtonPressed(); }; diff --git a/widgets/tablewidgetmovable.cpp b/widgets/tablewidgetmovable.cpp index df3a15d..ba6defa 100644 --- a/widgets/tablewidgetmovable.cpp +++ b/widgets/tablewidgetmovable.cpp @@ -7,6 +7,56 @@ TableWidgetMovable::TableWidgetMovable(QWidget *parent) : QTableWidget(parent) { } +// void TableWidgetMovable::dropEvent(QDropEvent *event) { +// if (event->source() == this) { +// // Get the index of the row being dragged +// QModelIndex sourceIndex = currentIndex(); +// if (!sourceIndex.isValid()) { +// return; +// } + +// // Get the index of the target row +// QModelIndex targetIndex = indexAt(event->pos()); +// if (!targetIndex.isValid()) { +// return; +// } + +// int sourceRow = sourceIndex.row(); +// int targetRow = targetIndex.row(); + +// // Swap rows +// if (sourceRow != targetRow) { +// // Store the data of the source row +// QList itemsSource; +// for (int col = 0; col < columnCount(); ++col) { +// itemsSource.append(takeItem(sourceRow, col)); +// } + +// QList itemsTarget; +// for (int col = 0; col < columnCount(); ++col) { +// itemsTarget.append(takeItem(targetRow, col)); +// } + +// // Insert the items into the target row +// for (int col = 0; col < columnCount(); ++col) { +// setItem(targetRow, col, itemsSource[col]); +// setItem(sourceRow, col, itemsTarget[col]); +// } + +// // for (int col = 0; col < columnCount(); ++col) { + +// // } + +// // Remove the original row +// // removeRow(sourceRow < targetRow ? sourceRow : sourceRow + 1); +// } + +// event->acceptProposedAction(); +// } else { +// QTableWidget::dropEvent(event); +// } +// } + // TOOD: fix None of these works. WIP // void TableWidgetMovable::dropEvent(QDropEvent *event) {