backupwidget.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. /*
  2. *openPilotLog - A FOSS Pilot Logbook Application
  3. *Copyright (C) 2020-2022 Felix Turowsky
  4. *
  5. *This program is free software: you can redistribute it and/or modify
  6. *it under the terms of the GNU General Public License as published by
  7. *the Free Software Foundation, either version 3 of the License, or
  8. *(at your option) any later version.
  9. *
  10. *This program is distributed in the hope that it will be useful,
  11. *but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. *GNU General Public License for more details.
  14. *
  15. *You should have received a copy of the GNU General Public License
  16. *along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. #include "backupwidget.h"
  19. #include "ui_backupwidget.h"
  20. #include "src/opl.h"
  21. #include "src/database/database.h"
  22. #include "src/functions/datetime.h"
  23. #include "src/database/dbsummary.h"
  24. #include "src/gui/dialogues/firstrundialog.h"
  25. #include <QListView>
  26. #include <QStandardItemModel>
  27. #include <QFileIconProvider>
  28. #include <QMessageBox>
  29. #include <QFileDialog>
  30. BackupWidget::BackupWidget(QWidget *parent) :
  31. QWidget(parent),
  32. ui(new Ui::BackupWidget)
  33. {
  34. ui->setupUi(this);
  35. model = new QStandardItemModel(this);
  36. model->setHorizontalHeaderLabels(QStringList{tr("Total Time"),tr("Flights"), tr("Aircraft"),
  37. tr("Pilots"), tr("Last Flight"), tr("Backup File")});
  38. view = ui->tableView;
  39. refresh();
  40. }
  41. BackupWidget::~BackupWidget()
  42. {
  43. delete ui;
  44. }
  45. void BackupWidget::changeEvent(QEvent *event)
  46. {
  47. if (event != nullptr)
  48. if(event->type() == QEvent::LanguageChange)
  49. ui->retranslateUi(this);
  50. }
  51. void BackupWidget::refresh()
  52. {
  53. // First column in table, would be created by listing the files in backupdir
  54. QDir backup_dir = OPL::Paths::directory(OPL::Paths::Backup);
  55. const QStringList entries = backup_dir.entryList(QStringList{"*.db"}, QDir::Files, QDir::Time);
  56. QFileIconProvider provider;
  57. // Get summary of each db file and populate lists (columns) of data
  58. for (const auto &entry : entries) {
  59. QMap<OPL::DbSummaryKey, QString> summary = OPL::DbSummary::databaseSummary(backup_dir.absoluteFilePath(entry));
  60. model->appendRow({new QStandardItem(summary[OPL::DbSummaryKey::total_time]),
  61. new QStandardItem(summary[OPL::DbSummaryKey::total_flights]),
  62. new QStandardItem(summary[OPL::DbSummaryKey::total_tails]),
  63. new QStandardItem(summary[OPL::DbSummaryKey::total_pilots]),
  64. new QStandardItem(summary[OPL::DbSummaryKey::last_flight]),
  65. new QStandardItem(provider.icon(QFileIconProvider::File), entry),
  66. });
  67. }
  68. view->setModel(model);
  69. view->resizeColumnsToContents();
  70. }
  71. const QString BackupWidget::absoluteBackupPath()
  72. {
  73. const QString backup_name = backupName();
  74. return OPL::Paths::filePath(OPL::Paths::Backup, backup_name);
  75. }
  76. const QString BackupWidget::backupName()
  77. {
  78. auto owner = DB->getPilotEntry(1);
  79. return QString("logbook_backup_%1_%2.db").arg(
  80. OPL::DateTime::dateTimeToString(QDateTime::currentDateTime(), OPL::DateTimeFormat::Backup),
  81. owner.lastName()
  82. );
  83. }
  84. void BackupWidget::on_tableView_clicked(const QModelIndex &index)
  85. {
  86. selectedRows.clear();
  87. selectedRows.append(index.row());
  88. }
  89. void BackupWidget::on_createLocalPushButton_clicked()
  90. {
  91. QString filename = absoluteBackupPath();
  92. DEB << filename;
  93. if(!DB->createBackup(QDir::toNativeSeparators(filename))) {
  94. WARN(tr("Could not create local file: %1").arg(filename));
  95. return;
  96. } else {
  97. INFO(tr("Backup successfully created."));
  98. }
  99. QFileInfo file_info(filename);
  100. QFileIconProvider provider;
  101. QMap<OPL::DbSummaryKey, QString> summary = OPL::DbSummary::databaseSummary(filename);
  102. model->insertRow(0, {new QStandardItem(summary[OPL::DbSummaryKey::total_time]),
  103. new QStandardItem(summary[OPL::DbSummaryKey::total_flights]),
  104. new QStandardItem(summary[OPL::DbSummaryKey::total_tails]),
  105. new QStandardItem(summary[OPL::DbSummaryKey::total_pilots]),
  106. new QStandardItem(summary[OPL::DbSummaryKey::last_flight]),
  107. new QStandardItem(provider.icon(QFileIconProvider::File), file_info.fileName()),
  108. });
  109. }
  110. void BackupWidget::on_restoreLocalPushButton_clicked()
  111. {
  112. if(selectedRows.isEmpty()) {
  113. INFO(tr("No backup selected"));
  114. return;
  115. }
  116. const QString file_name = model->item(selectedRows.first(), 5)->data(Qt::DisplayRole).toString();
  117. const QString backup_name = OPL::Paths::filePath(OPL::Paths::Backup, file_name);
  118. QMessageBox confirm(this);
  119. confirm.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
  120. confirm.setDefaultButton(QMessageBox::No);
  121. confirm.setIcon(QMessageBox::Warning);
  122. confirm.setWindowTitle(tr("Restoring Backup"));
  123. confirm.setText(tr("The following backup will be restored:<br><br><b><tt>"
  124. "%1</b></tt><br><br>"
  125. "This will replace your currently active database with the backup.<br>This action is irreversible.<br><br>Are you sure?"
  126. ).arg(OPL::DbSummary::summaryString(backup_name)));
  127. if (confirm.exec() == QMessageBox::No)
  128. return;
  129. if(!DB->restoreBackup(QDir::toNativeSeparators(backup_name))) {
  130. WARN(tr("Unable to restore Backup file: %1").arg(backup_name));
  131. } else {
  132. INFO(tr("Backup successfully restored."));
  133. }
  134. view->clearSelection();
  135. selectedRows.clear();
  136. }
  137. void BackupWidget::on_deleteSelectedPushButton_clicked()
  138. {
  139. if(selectedRows.isEmpty()) {
  140. INFO(tr("No backup was selected"));
  141. return;
  142. }
  143. const QString file_name = model->item(selectedRows.first(), 5)->data(Qt::DisplayRole).toString();
  144. const QString backup_name = OPL::Paths::filePath(OPL::Paths::Backup, file_name);
  145. QFile file(OPL::Paths::filePath(OPL::Paths::Backup, file_name));
  146. if(!file.exists()) {
  147. WARN(tr("Selected backup file (<tt>%1</tt>) does not exist.").arg(file_name));
  148. return;
  149. }
  150. QMessageBox confirm(this);
  151. confirm.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
  152. confirm.setDefaultButton(QMessageBox::No);
  153. confirm.setIcon(QMessageBox::Question);
  154. confirm.setWindowTitle(tr("Delete Backup"));
  155. confirm.setText(tr("The following backup will be deleted:<br><br><i>%1</i><br><br><b><tt>"
  156. "%2</b></tt><br><br>"
  157. "<b>This action is irreversible.</b><br><br>Continue?"
  158. ).arg(file_name, OPL::DbSummary::summaryString(backup_name)));
  159. if (confirm.exec() == QMessageBox::No)
  160. return;
  161. LOG << "Deleting backup:" << file_name;
  162. if(!file.remove()) {
  163. WARN(tr("Unable to remove file %1<br>Error: %2").arg(file_name,file.errorString()));
  164. return;
  165. } else {
  166. INFO(tr("Backup successfully deleted."));
  167. }
  168. model->removeRow(selectedRows.first());
  169. view->clearSelection();
  170. selectedRows.clear();
  171. }
  172. void BackupWidget::on_createExternalPushButton_clicked()
  173. {
  174. QString filename = QFileDialog::getSaveFileName(
  175. this,
  176. tr("Choose destination file"),
  177. QDir::homePath() + QDir::separator() + backupName(),
  178. "*.db"
  179. );
  180. if(filename.isEmpty()) { // QFileDialog has been cancelled
  181. return;
  182. }
  183. if(!filename.endsWith(".db")) {
  184. filename.append(".db");
  185. }
  186. if(!DB->createBackup(QDir::toNativeSeparators(filename))) {
  187. WARN(tr("Unable to backup file:").arg(filename));
  188. return;
  189. } else {
  190. INFO(tr("Backup successfully created."));
  191. }
  192. }
  193. void BackupWidget::on_restoreExternalPushButton_clicked()
  194. {
  195. QString filename = QFileDialog::getOpenFileName(
  196. this,
  197. tr("Choose backup file"),
  198. QDir::homePath(),
  199. "*.db"
  200. );
  201. if(filename.isEmpty()) { // QFileDialog has been cancelled
  202. return;
  203. }
  204. // Maybe create a Message Box asking for confirmation here and displaying the summary of backup and active DB
  205. QMessageBox confirm(this);
  206. confirm.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
  207. confirm.setDefaultButton(QMessageBox::No);
  208. confirm.setIcon(QMessageBox::Question);
  209. confirm.setWindowTitle(tr("Import Database"));
  210. confirm.setText(tr("The following database will be imported:<br><br><b><tt>"
  211. "%1<br></b></tt>"
  212. "<br>Continue?"
  213. ).arg(OPL::DbSummary::summaryString(filename)));
  214. if (confirm.exec() == QMessageBox::Yes) {
  215. if(!DB->restoreBackup(QDir::toNativeSeparators(filename))) {
  216. WARN(tr("Unable to import database file:").arg(filename));
  217. return;
  218. }
  219. INFO(tr("Database successfully imported."));
  220. }
  221. }
  222. /*!
  223. * \brief BackupWidget::on_createNewLogbookPushButton_clicked Enables the user to reset the database
  224. */
  225. void BackupWidget::on_createNewLogbookPushButton_clicked()
  226. {
  227. QMessageBox confirm(this);
  228. confirm.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
  229. confirm.setDefaultButton(QMessageBox::No);
  230. confirm.setIcon(QMessageBox::Warning);
  231. confirm.setWindowTitle(tr("Start new Logbook"));
  232. confirm.setText(tr("By starting a new logbook, you reset and empty the database currently in use.<br><br>"
  233. "You will be asked if you want to keep a backup of your current database, but it is highly "
  234. "recommended to create an external backup before starting a new logbook.<br><br>"
  235. "Do you want to continue?"
  236. ));
  237. if (confirm.exec() == QMessageBox::Yes) {
  238. auto frd = new FirstRunDialog(this);
  239. if(!frd->exec()) {
  240. WARN(tr("Creating New Logbook has been unsuccessful or aborted."));
  241. }
  242. }
  243. }