/*
*openPilotLog - A FOSS Pilot Logbook Application
*Copyright (C) 2020-2023 Felix Turowsky
*
*This program is free software: you can redistribute it and/or modify
*it under the terms of the GNU General Public License as published by
*the Free Software Foundation, either version 3 of the License, or
*(at your option) any later version.
*
*This program is distributed in the hope that it will be useful,
*but WITHOUT ANY WARRANTY; without even the implied warranty of
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*GNU General Public License for more details.
*
*You should have received a copy of the GNU General Public License
*along with this program. If not, see .
*/
#include "backupwidget.h"
#include "ui_backupwidget.h"
#include "src/opl.h"
#include "src/database/database.h"
#include "src/functions/datetime.h"
#include "src/database/dbsummary.h"
#include "src/gui/dialogues/firstrundialog.h"
#include "src/classes/settings.h"
#include "src/classes/styleddatedelegate.h"
#include
#include
#include
#include
#include
BackupWidget::BackupWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::BackupWidget)
{
ui->setupUi(this);
model = new QStandardItemModel(this);
model->setHorizontalHeaderLabels(QStringList{tr("Total Time"),tr("Flights"), tr("Aircraft"),
tr("Pilots"), tr("Last Flight"), tr("Backup File")});
view = ui->tableView;
// julian day to Date Format
const auto dateDelegate = new StyledDateDelegate(Settings::getDisplayFormat(), model);
view->setItemDelegateForColumn(DATE_COLUMN, dateDelegate);
refresh();
}
BackupWidget::~BackupWidget()
{
delete ui;
}
void BackupWidget::changeEvent(QEvent *event)
{
if (event != nullptr)
if(event->type() == QEvent::LanguageChange)
ui->retranslateUi(this);
}
void BackupWidget::refresh()
{
// First column in table, would be created by listing the files in backupdir
QDir backup_dir = OPL::Paths::directory(OPL::Paths::Backup);
const QStringList entries = backup_dir.entryList(QStringList{"*.db"}, QDir::Files, QDir::Time);
QFileIconProvider provider;
// Get summary of each db file and populate lists (columns) of data
for (const auto &entry : entries) {
QMap summary = OPL::DbSummary::databaseSummary(backup_dir.absoluteFilePath(entry));
model->appendRow({new QStandardItem(summary[OPL::DbSummaryKey::total_time]),
new QStandardItem(summary[OPL::DbSummaryKey::total_flights]),
new QStandardItem(summary[OPL::DbSummaryKey::total_tails]),
new QStandardItem(summary[OPL::DbSummaryKey::total_pilots]),
new QStandardItem(summary[OPL::DbSummaryKey::last_flight]),
new QStandardItem(provider.icon(QFileIconProvider::File), entry),
});
}
view->setModel(model);
view->resizeColumnsToContents();
}
const QString BackupWidget::absoluteBackupPath()
{
const QString backup_name = backupName();
return OPL::Paths::filePath(OPL::Paths::Backup, backup_name);
}
const QString BackupWidget::backupName()
{
auto owner = DB->getPilotEntry(1);
return QStringLiteral("logbook_backup_%1_%2.db").arg(
OPL::DateTime::dateTimeToString(QDateTime::currentDateTime(), OPL::DateTimeFormat_deprecated::Backup),
owner.getLastName()
);
}
void BackupWidget::on_tableView_clicked(const QModelIndex &index)
{
selectedRows.clear();
selectedRows.append(index.row());
}
void BackupWidget::on_createLocalPushButton_clicked()
{
QString filename = absoluteBackupPath();
DEB << filename;
if(!DB->createBackup(QDir::toNativeSeparators(filename))) {
WARN(tr("Could not create local file: %1").arg(filename));
return;
} else {
INFO(tr("Backup successfully created."));
}
QFileInfo file_info(filename);
QFileIconProvider provider;
QMap summary = OPL::DbSummary::databaseSummary(filename);
model->insertRow(0, {new QStandardItem(summary[OPL::DbSummaryKey::total_time]),
new QStandardItem(summary[OPL::DbSummaryKey::total_flights]),
new QStandardItem(summary[OPL::DbSummaryKey::total_tails]),
new QStandardItem(summary[OPL::DbSummaryKey::total_pilots]),
new QStandardItem(summary[OPL::DbSummaryKey::last_flight]),
new QStandardItem(provider.icon(QFileIconProvider::File), file_info.fileName()),
});
}
void BackupWidget::on_restoreLocalPushButton_clicked()
{
if(selectedRows.isEmpty()) {
INFO(tr("No backup selected"));
return;
}
const QString file_name = model->item(selectedRows.first(), 5)->data(Qt::DisplayRole).toString();
const QString backup_name = OPL::Paths::filePath(OPL::Paths::Backup, file_name);
QMessageBox confirm(this);
confirm.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
confirm.setDefaultButton(QMessageBox::No);
confirm.setIcon(QMessageBox::Warning);
confirm.setWindowTitle(tr("Restoring Backup"));
confirm.setText(tr("The following backup will be restored:
"
"%1
"
"This will replace your currently active database with the backup.
This action is irreversible.
Are you sure?"
).arg(OPL::DbSummary::summaryString(backup_name)));
if (confirm.exec() == QMessageBox::No)
return;
if(!DB->restoreBackup(QDir::toNativeSeparators(backup_name))) {
WARN(tr("Unable to restore Backup file: %1").arg(backup_name));
} else {
INFO(tr("Backup successfully restored."));
}
view->clearSelection();
selectedRows.clear();
}
void BackupWidget::on_deleteSelectedPushButton_clicked()
{
if(selectedRows.isEmpty()) {
INFO(tr("No backup was selected"));
return;
}
const QString file_name = model->item(selectedRows.first(), 5)->data(Qt::DisplayRole).toString();
const QString backup_name = OPL::Paths::filePath(OPL::Paths::Backup, file_name);
QFile file(OPL::Paths::filePath(OPL::Paths::Backup, file_name));
if(!file.exists()) {
WARN(tr("Selected backup file (%1) does not exist.").arg(file_name));
return;
}
QMessageBox confirm(this);
confirm.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
confirm.setDefaultButton(QMessageBox::No);
confirm.setIcon(QMessageBox::Question);
confirm.setWindowTitle(tr("Delete Backup"));
confirm.setText(tr("The following backup will be deleted:
%1
"
"%2
"
"This action is irreversible.
Continue?"
).arg(file_name, OPL::DbSummary::summaryString(backup_name)));
if (confirm.exec() == QMessageBox::No)
return;
LOG << "Deleting backup:" << file_name;
if(!file.remove()) {
WARN(tr("Unable to remove file %1
Error: %2").arg(file_name,file.errorString()));
return;
} else {
INFO(tr("Backup successfully deleted."));
}
model->removeRow(selectedRows.first());
view->clearSelection();
selectedRows.clear();
}
void BackupWidget::on_createExternalPushButton_clicked()
{
QString filename = QFileDialog::getSaveFileName(
this,
tr("Choose destination file"),
QDir::homePath() + QDir::separator() + backupName(),
"*.db"
);
if(filename.isEmpty()) { // QFileDialog has been cancelled
return;
}
if(!filename.endsWith(".db")) {
filename.append(".db");
}
if(!DB->createBackup(QDir::toNativeSeparators(filename))) {
WARN(tr("Unable to backup file:").arg(filename));
return;
} else {
INFO(tr("Backup successfully created."));
}
}
void BackupWidget::on_restoreExternalPushButton_clicked()
{
QString filename = QFileDialog::getOpenFileName(
this,
tr("Choose backup file"),
QDir::homePath(),
"*.db"
);
if(filename.isEmpty()) { // QFileDialog has been cancelled
return;
}
// Maybe create a Message Box asking for confirmation here and displaying the summary of backup and active DB
QMessageBox confirm(this);
confirm.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
confirm.setDefaultButton(QMessageBox::No);
confirm.setIcon(QMessageBox::Question);
confirm.setWindowTitle(tr("Import Database"));
confirm.setText(tr("The following database will be imported:
"
"%1
"
"
Continue?"
).arg(OPL::DbSummary::summaryString(filename)));
if (confirm.exec() == QMessageBox::Yes) {
if(!DB->restoreBackup(QDir::toNativeSeparators(filename))) {
WARN(tr("Unable to import database file:").arg(filename));
return;
}
INFO(tr("Database successfully imported."));
}
}
/*!
* \brief BackupWidget::on_createNewLogbookPushButton_clicked Enables the user to reset the database
*/
void BackupWidget::on_createNewLogbookPushButton_clicked()
{
QMessageBox confirm(this);
confirm.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
confirm.setDefaultButton(QMessageBox::No);
confirm.setIcon(QMessageBox::Warning);
confirm.setWindowTitle(tr("Start new Logbook"));
confirm.setText(tr("By starting a new logbook, you reset and empty the database currently in use.
"
"You will be asked if you want to keep a backup of your current database, but it is highly "
"recommended to create an external backup before starting a new logbook.
"
"Do you want to continue?"
));
if (confirm.exec() == QMessageBox::Yes) {
auto frd = new FirstRunDialog(this);
if(!frd->exec()) {
WARN(tr("Creating New Logbook has been unsuccessful or aborted."));
}
}
}