From e273303dcdb0a088c48c3f72a2723dd67124f1ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soutad=C3=A9?= Date: Tue, 20 Mar 2012 20:57:45 +0100 Subject: [PATCH] Add Snapshot feature Add ChangeDatabase() method Add GetDatabaseHome() and GetDatabaseFile() --- ChangeLog | 3 +- src/controller/KissCount.cpp | 5 + src/controller/KissCount.hpp | 2 + src/model/Database.cpp | 41 ++++++-- src/model/Database.hpp | 6 ++ src/model/DatabaseUpdate.cpp | 2 + src/view/AccountPanel.cpp | 11 ++ src/view/AccountPanel.hpp | 1 + src/view/SnapshotsDialog.cpp | 191 +++++++++++++++++++++++++++++++++++ src/view/SnapshotsDialog.hpp | 49 +++++++++ 10 files changed, 303 insertions(+), 8 deletions(-) create mode 100644 src/view/SnapshotsDialog.cpp create mode 100644 src/view/SnapshotsDialog.hpp diff --git a/ChangeLog b/ChangeLog index 0143293..0582227 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,10 +1,11 @@ -v0.3 (27/02/2012) +v0.3 (20/03/2012) ** User ** New interface in Qt Use BDD file from .local/share/kisscount Use libkchart for graphics New account attribute : hidden Description is now auto-completed + Snapshot feature ** Dev ** Version 3 of database (account hidden item added) diff --git a/src/controller/KissCount.cpp b/src/controller/KissCount.cpp index d4c55cd..ff94bb0 100644 --- a/src/controller/KissCount.cpp +++ b/src/controller/KissCount.cpp @@ -644,3 +644,8 @@ std::vector* KissCount::GetExportEngines() return _exportEngines; } + +bool KissCount::ChangeDatabase(QString filename) +{ + return _db->ChangeDatabase(filename); +} diff --git a/src/controller/KissCount.hpp b/src/controller/KissCount.hpp index 567b2b8..2678e05 100644 --- a/src/controller/KissCount.hpp +++ b/src/controller/KissCount.hpp @@ -137,6 +137,8 @@ public: void GetHistory(int month, int year, QStringList& list); + bool ChangeDatabase(QString filename); + private: wxUI* _wxUI; Database* _db; diff --git a/src/model/Database.cpp b/src/model/Database.cpp index 72b5070..86199d5 100644 --- a/src/model/Database.cpp +++ b/src/model/Database.cpp @@ -22,7 +22,6 @@ #include #include -#include #include #include #include @@ -44,7 +43,7 @@ Database::Database(const char* filename, KissCount* kiss) : _kiss(kiss) { std::ifstream bdd_file; - QString sPath = QDir::home().path() + BDD_PATH + BDD_FILE; + QString sPath = GetDatabaseHome() + GetDatabaseFile(); _db = QSqlDatabase::addDatabase("QSQLITE"); @@ -54,7 +53,7 @@ Database::Database(const char* filename, KissCount* kiss) : _kiss(kiss) if (!bdd_file.good()) { - QMessageBox::critical(0, _("Error"), _("Unable to open Database")); + QMessageBox::critical(0, _("Error"), _("Unable to open database")); throw std::string("Unable to open ") + filename; } @@ -62,7 +61,7 @@ Database::Database(const char* filename, KissCount* kiss) : _kiss(kiss) if (!_db.open()) { - QMessageBox::critical(0, _("Error"), _("Unable to open Database")); + QMessageBox::critical(0, _("Error"), _("Unable to open database")); throw std::string("Unable to open ") + filename; } } @@ -81,7 +80,7 @@ Database::Database(const char* filename, KissCount* kiss) : _kiss(kiss) if (!_db.open()) { - QMessageBox::critical(0, _("Error"), _("Unable to open Database")); + QMessageBox::critical(0, _("Error"), _("Unable to open database")); throw std::string("Unable to open ") + sPath.toStdString(); } } @@ -95,8 +94,8 @@ Database::Database(const char* filename, KissCount* kiss) : _kiss(kiss) void Database::CreateDatabase() { QFile init_script(INIT_SCRIPT); - QString sPath = QDir::home().path() + BDD_FILE; - QDir dirname( QDir::home().path() + BDD_PATH); + QString sPath = GetDatabaseHome() + GetDatabaseFile(); + QDir dirname( GetDatabaseHome()); QFile file(sPath); QString message = _("No database found, would you like to create a new one ?\n\n"); message += _("!! Warning !! If there was a bug, the old database will be suppressed !"); @@ -1748,3 +1747,31 @@ void Database::GetHistory(int month, int year, QStringList& list) } } +bool Database::ChangeDatabase(QString filename) +{ + QString oldFilename = _db.databaseName(); + + _db.close(); + + _db.setDatabaseName(filename); + + if (!_db.open()) + { + QMessageBox::critical(0, _("Error"), _("Unable to open database")); + _db.setDatabaseName(oldFilename); + _db.open(); + return false; + } + + try { + CheckDatabaseVersion(); + } + catch(...) + { + _db.setDatabaseName(oldFilename); + _db.open(); + return false; + } + + return true; +} diff --git a/src/model/Database.hpp b/src/model/Database.hpp index d17673e..3ce8bc8 100644 --- a/src/model/Database.hpp +++ b/src/model/Database.hpp @@ -24,6 +24,7 @@ #include #include +#include #include #include "model.hpp" @@ -91,6 +92,9 @@ public: Database(const char* filename, KissCount* kiss); + static QString GetDatabaseHome() { return QDir::home().path() + BDD_PATH; } + static QString GetDatabaseFile() { return QString(BDD_FILE); } + std::list GetUsers(); bool IsValidUser(const QString& user, const QString& password); @@ -154,6 +158,8 @@ public: void GetHistory(int month, int year, QStringList& list); + bool ChangeDatabase(QString filename); + /* Database Update */ void CheckDatabaseVersion(); diff --git a/src/model/DatabaseUpdate.cpp b/src/model/DatabaseUpdate.cpp index b631db3..195feb5 100644 --- a/src/model/DatabaseUpdate.cpp +++ b/src/model/DatabaseUpdate.cpp @@ -159,6 +159,8 @@ void Database::CheckDatabaseVersion() _db.rollback(); + QMessageBox::critical(0, _("Error"), _("Unable to upgrade Database")); + throw e; } diff --git a/src/view/AccountPanel.cpp b/src/view/AccountPanel.cpp index 6350782..c169098 100644 --- a/src/view/AccountPanel.cpp +++ b/src/view/AccountPanel.cpp @@ -26,6 +26,7 @@ #include "AccountPanel.hpp" #include "grid/FloatDelegate.hpp" #include "GenerateDialog.hpp" +#include "SnapshotsDialog.hpp" enum {ACCOUNT_NUMBER, ACCOUNT_NAME, ACCOUNT_INIT, ACCOUNT_CUR, ACCOUNT_FINAL, NUMBER_COLS_ACCOUNTS}; enum {CUR_CREDIT, CUR_DEBIT, TOTAL_CREDIT, TOTAL_DEBIT, BALANCE, STATS_ROW, CATS_STATS, NON_FIX}; @@ -167,10 +168,12 @@ AccountPanel::AccountPanel(KissCount* kiss, wxUI *parent) : KissPanel(kiss, pare QPushButton* buttonGroup = new QPushButton(_("Group")); QPushButton* buttonUnGroup = new QPushButton(_("UnGroup")); QPushButton* buttonUpdateNextMonths = new QPushButton(_("Update next months")); + QPushButton* buttonSnapshots = new QPushButton(_("Snapshots")); connect(buttonGroup, SIGNAL(clicked()), this, SLOT(OnGroup())); connect(buttonUnGroup, SIGNAL(clicked()), this, SLOT(OnUnGroup())); connect(buttonUpdateNextMonths, SIGNAL(clicked()), this, SLOT(OnUpdateNextMonths())); + connect(buttonSnapshots, SIGNAL(clicked()), this, SLOT(OnSnapshots())); vbox3->addWidget(_tree); vbox3->addWidget(buttonUpdateNextMonths); @@ -178,6 +181,8 @@ AccountPanel::AccountPanel(KissCount* kiss, wxUI *parent) : KissPanel(kiss, pare vbox3->addWidget(buttonGroup); vbox3->addWidget(buttonUnGroup); vbox3->addStretch(1); + vbox3->addWidget(buttonSnapshots); + vbox3->addStretch(1); vbox3->addWidget(groupBox); hbox->addLayout(vbox3); @@ -1202,3 +1207,9 @@ end: delete[] deltas; delete[] cur_amounts; } + +void AccountPanel::OnSnapshots() +{ + SnapshotsDialog u(_kiss, _wxUI); + u.exec(); +} diff --git a/src/view/AccountPanel.hpp b/src/view/AccountPanel.hpp index 84412aa..e3ca6f6 100644 --- a/src/view/AccountPanel.hpp +++ b/src/view/AccountPanel.hpp @@ -67,6 +67,7 @@ private slots: void OnGroup(); void OnUnGroup(); void OnUpdateNextMonths(); + void OnSnapshots(); private: QTreeWidget *_tree; diff --git a/src/view/SnapshotsDialog.cpp b/src/view/SnapshotsDialog.cpp new file mode 100644 index 0000000..788ebf1 --- /dev/null +++ b/src/view/SnapshotsDialog.cpp @@ -0,0 +1,191 @@ +/* + Copyright 2010-2012 Grégory Soutadé + + This file is part of KissCount. + + KissCount 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. + + KissCount 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 KissCount. If not, see . +*/ + +#include "SnapshotsDialog.hpp" +#include +#include + +#include + +SnapshotsDialog::SnapshotsDialog(KissCount* kiss, wxUI *parent) : QDialog(0, Qt::Dialog), _kiss(kiss), _wxUI(parent) +{ + QVBoxLayout *vbox = new QVBoxLayout; + QHBoxLayout *hbox = new QHBoxLayout; + QVBoxLayout *vbox2 = new QVBoxLayout; + + setWindowTitle(_("Snapshots")); + setModal(true); + + setLayout(vbox); + + _snapshots = new QListWidget(this); + + hbox->addWidget(_snapshots); + + QPushButton* buttonCreate = new QPushButton(_("Create snapshot")); + QPushButton* buttonDelete = new QPushButton(_("Delete snapshot")); + QPushButton* buttonBackTo = new QPushButton(_("Back to this snapshot")); + + connect(buttonCreate, SIGNAL(clicked()), this, SLOT(OnCreate())); + connect(buttonDelete, SIGNAL(clicked()), this, SLOT(OnDelete())); + connect(buttonBackTo, SIGNAL(clicked()), this, SLOT(OnBackTo())); + + vbox2->addWidget(buttonCreate); + vbox2->addWidget(buttonDelete); + vbox2->addWidget(buttonBackTo); + + hbox->addLayout(vbox2); + + QPushButton* ok = new QPushButton(_("OK")); + + connect(ok, SIGNAL(clicked()), this, SLOT(OnOK())); + + vbox->addLayout(hbox); + vbox->addWidget(ok); + + LoadFiles(); +} + +void SnapshotsDialog::LoadFiles() +{ + QDir dir(Database::GetDatabaseHome()); + QStringList res; + QStringList::const_iterator it; + + res << Database::GetDatabaseFile() + ".bak.????.??.??*"; + dir.setNameFilters(res); + dir.setFilter(QDir::Files); + dir.setSorting(QDir::Name); + + res.clear(); + res = dir.entryList(); + + _snapshots->clear(); + + for(it=res.begin(); it!=res.end(); it++) + { + QString item = it->right(it->size()-Database::GetDatabaseFile().size()-5); + new QListWidgetItem(item, _snapshots); + } +} + +void SnapshotsDialog::OnCreate() +{ + QDir dir(Database::GetDatabaseHome()); + QString bak, bak2, v ; + QDate curDate = QDate::currentDate(); + int i; + + bak = Database::GetDatabaseFile() + ".bak."; + bak += v.sprintf("%d.%02d.%02d", curDate.year(), curDate.month(), curDate.day()); + + if (dir.exists(bak)) + { + bak2 = bak; + for(i=2; dir.exists(bak2); i++) + { + bak2 = bak + "_" + QString::number(i); + } + bak = bak2; + } + + QFile file(Database::GetDatabaseHome() + Database::GetDatabaseFile()); + + if (file.copy(Database::GetDatabaseHome() + bak)) + { + new QListWidgetItem(bak.right(bak.size()-Database::GetDatabaseFile().size()-5), _snapshots); + QMessageBox::information(0, "KissCount", bak + _(" successfully created")); + } + else + { + QMessageBox::critical(0, _("Error"), _("Unable to create ") + Database::GetDatabaseHome() + bak); + } +} + +void SnapshotsDialog::OnDelete() +{ + QString filename ; + QListWidgetItem * item = _snapshots->currentItem(); + + if (!item) return; + + filename = Database::GetDatabaseFile() + ".bak." + item->text(); + QFile file(Database::GetDatabaseHome() + filename); + + if (!file.exists()) + { + QMessageBox::critical(0, _("Error"), filename + _(" does not exist")); + return; + } + + if (QMessageBox::question(0, "KissCount", _("Are you sure want to delete ") + filename + " ?", QMessageBox::Yes|QMessageBox::No) == QMessageBox::No) + return; + + if (!file.remove()) + { + QMessageBox::critical(0, _("Error"), _("Unable to remove ") + filename); + return; + } + + QMessageBox::information(0, "KissCount", filename + _(" successfully removed")); + delete _snapshots->takeItem(_snapshots->currentRow()); +} + +void SnapshotsDialog::OnBackTo() +{ + QString filename, defaultFilename ; + QListWidgetItem * item = _snapshots->currentItem(); + QString user; + + if (!item) return; + + filename = Database::GetDatabaseFile() + ".bak." + item->text(); + defaultFilename = Database::GetDatabaseFile(); + QFile file(Database::GetDatabaseHome() + filename); + QFile defaultFile(Database::GetDatabaseHome() + defaultFilename); + + if (!file.exists()) + { + QMessageBox::critical(0, _("Error"), filename + _(" does not exist")); + return; + } + + if (QMessageBox::question(0, "KissCount", _("Are you sure want to come back to ") + filename + " ?", QMessageBox::Yes|QMessageBox::No) == QMessageBox::No) + return; + + if (!defaultFile.remove()) + { + QMessageBox::critical(0, _("Error"), _("Unable to remove ") + defaultFilename); + return; + } + + if (file.copy(Database::GetDatabaseHome() + defaultFilename)) + + user = _kiss->GetUser()->_name; + + _kiss->ChangeDatabase(Database::GetDatabaseHome() + defaultFilename); + _kiss->LoadUser(user); + + QMessageBox::information(0, "KissCount", _("Welcome back to ") + filename); +} + +void SnapshotsDialog::OnOK() +{ + close(); +} diff --git a/src/view/SnapshotsDialog.hpp b/src/view/SnapshotsDialog.hpp new file mode 100644 index 0000000..1a5a860 --- /dev/null +++ b/src/view/SnapshotsDialog.hpp @@ -0,0 +1,49 @@ +/* + Copyright 2010-2012 Grégory Soutadé + + This file is part of KissCount. + + KissCount 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. + + KissCount 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 KissCount. If not, see . +*/ + +#ifndef SNAPSHOTSDIALOG_H +#define SNAPSHOTSDIALOG_H + +#include +#include + +#include "wxUI.hpp" + +class SnapshotsDialog : public QDialog +{ + Q_OBJECT; + +public: + SnapshotsDialog(KissCount* kiss, wxUI *parent); + +private slots: + void OnOK(); + void OnCreate(); + void OnDelete(); + void OnBackTo(); + +private: + KissCount* _kiss; + wxUI* _wxUI; + QListWidget* _snapshots; + // QLineEdit* _oldSnapshots, *_newSnapshots, *_confirmSnapshots; + + void LoadFiles(); +}; +#endif