From d18826266b1b91b34b6879c15da6605d72a52c7b Mon Sep 17 00:00:00 2001 From: LoudSnorer Date: Mon, 25 Mar 2024 15:48:41 -0400 Subject: [PATCH] [New Feature] Add Import(restore) Journal --- oscar/SleepLib/common.h | 1 + oscar/SleepLib/journal.cpp | 574 ++++++++++++++++++++++--------------- oscar/SleepLib/journal.h | 80 +----- oscar/mainwindow.cpp | 46 ++- oscar/mainwindow.h | 4 +- oscar/mainwindow.ui | 6 + 6 files changed, 402 insertions(+), 309 deletions(-) diff --git a/oscar/SleepLib/common.h b/oscar/SleepLib/common.h index cef4071f..ee0d7bc8 100644 --- a/oscar/SleepLib/common.h +++ b/oscar/SleepLib/common.h @@ -158,6 +158,7 @@ const QString STR_GEN_DataFolder = "DataFolder"; const QString STR_PREF_ReimportBackup = "ReimportBackup"; const QString STR_PREF_LastCPAPPath = "LastCPAPPath"; +const QString STR_PREF_LastJournalPath = "LastJouralPath"; const QString STR_PREF_LastOximetryPath = "LastOximetryPath"; const QString STR_MACH_ResMed = "ResMed"; diff --git a/oscar/SleepLib/journal.cpp b/oscar/SleepLib/journal.cpp index 4032c942..477d2192 100644 --- a/oscar/SleepLib/journal.cpp +++ b/oscar/SleepLib/journal.cpp @@ -1,216 +1,36 @@ /* SleepLib Journal Implementation * * Copyright (c) 2019-2024 The OSCAR Team - * Copyright (c) 2011-2018 Mark Watkins + * Copyright (c) 2011-2018 Mark Watkins * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of the source code * for more details. */ -#define TEST_MACROS_ENABLEDoff +#define TEST_MACROS_ENABLED #include -#include "journal.h" -#include "machine_common.h" +#include #include #include #include #include #include #include -#include +#include "journal.h" +#include "daily.h" +#include "SleepLib/common.h" +#include "SleepLib/machine_common.h" +#include "SleepLib/session.h" +#include "SleepLib/profiles.h" +#include "mainwindow.h" -const int journal_data_version = 1; +extern MainWindow * mainwin; +const QString OLD_ZOMBIE = QString("zombie"); +const QString ZOMBIE = QString("Feelings"); +const QString WEIGHT = QString("weight"); -JournalEntry::JournalEntry(QDate date) -{ - Machine * jmach = p_profile->GetMachine(MT_JOURNAL); - if (jmach == nullptr) { // Create Journal Device record if it doesn't already exist - MachineInfo info(MT_JOURNAL,0, "Journal", QObject::tr("Journal Data"), QString(), QString(), QString(), QString("OSCAR"), QDateTime::currentDateTime(), journal_data_version); - - // Using device ID 1 rather than a random number, so in future, if profile.xml gets screwed up they'll get their data back.. - // TODO: Perhaps search for unlinked journal folders here to save some anger and frustration? :P - - MachineID machid = 1; - QString path = p_profile->Get("{" + STR_GEN_DataFolder + "}"); - QDir dir(path); - QStringList filters; - filters << "Journal_*"; - QStringList dirs = dir.entryList(filters,QDir::Dirs); - int journals = dirs.size(); - if (journals > 0) { - QString tmp = dirs[0].section("_", -1); - bool ok; - machid = tmp.toUInt(&ok, 16); - if (!ok) { - QMessageBox::warning(nullptr, STR_MessageBox_Warning, - QObject::tr("OSCAR found an old Journal folder, but it looks like it's been renamed:")+"\n\n"+ - QString("%1").arg(dirs[0])+ - QObject::tr("OSCAR will not touch this folder, and will create a new one instead.")+"\n\n"+ - QObject::tr("Please be careful when playing in OSCAR's profile folders :-P"), QMessageBox::Ok); - - // User renamed the folder.. report this - machid = 1; - } - if (journals > 1) { - QMessageBox::warning(nullptr, STR_MessageBox_Warning, - QObject::tr("For some reason, OSCAR couldn't find a journal object record in your profile, but did find multiple Journal data folders.\n\n")+ - QObject::tr("OSCAR picked only the first one of these, and will use it in future:\n\n")+ - QString("%1").arg(dirs[0])+ - QObject::tr("If your old data is missing, copy the contents of all the other Journal_XXXXXXX folders to this one manually."), QMessageBox::Ok); - // more then one.. report this. - } - } - jmach = p_profile->CreateMachine(info, machid); - } - - m_date = date; - session = nullptr; - day = p_profile->GetDay(date, MT_JOURNAL); - if (day != nullptr) { - session = day->firstSession(MT_JOURNAL); - } else { - // Doesn't exist.. create a new one.. - session = new Session(jmach,0); - qint64 st,et; - QDateTime dt(date,QTime(22,0)); // 10pm localtime - st=qint64(dt.toTime_t())*1000L; - et=st+3600000L; - session->set_first(st); - session->set_last(et); - - // Let it live in memory...but not on disk unless data is changed... - jmach->AddSession(session, true); - - // and where does day get set??? does day actually need to be set?? - day = p_profile->GetDay(date, MT_JOURNAL); - } -} -JournalEntry::~JournalEntry() -{ - if (session && session->IsChanged()) { - Save(); - } -} - - -bool JournalEntry::Save() -{ - if (session && session->IsChanged()) { - qDebug() << "Saving journal session for" << m_date; - - // just need to write bookmarks, the rest are already stored in the session - QVariantList start; - QVariantList end; - QStringList notes; - - int size = bookmarks.size(); - for (int i=0; isettings[Bookmark_Start] = start; - session->settings[Bookmark_End] = end; - session->settings[Bookmark_Notes] = notes; - - session->settings[LastUpdated] = QDateTime::currentDateTime().toTime_t(); - - session->StoreSummary(); - return true; - } - return false; -} - -QString JournalEntry::notes() -{ - QHash::iterator it; - if (session && ((it=session->settings.find(Journal_Notes)) != session->settings.end())) { - return it.value().toString(); - } - return QString(); -} -void JournalEntry::setNotes(QString notes) -{ - if (!session) return; - session->settings[Journal_Notes] = notes; - session->SetChanged(true); -} -EventDataType JournalEntry::weight() -{ - QHash::iterator it; - if (session && ((it = session->settings.find(Journal_Weight)) != session->settings.end())) { - return it.value().toFloat(); - } - return 0; -} -void JournalEntry::setWeight(EventDataType weight) -{ - if (!session) return; - session->settings[Journal_Weight] = weight; - session->SetChanged(true); -} -int JournalEntry::zombie() -{ - QHash::iterator it; - if (session && ((it = session->settings.find(Journal_ZombieMeter)) != session->settings.end())) { - return it.value().toFloat(); - } - return 0; -} -void JournalEntry::setZombie(int zombie) -{ - if (!session) return; - session->settings[Journal_ZombieMeter] = zombie; - session->SetChanged(true); -} - -QList & JournalEntry::getBookmarks() -{ - bookmarks.clear(); - if (!session || !session->settings.contains(Bookmark_Start)) { - return bookmarks; - } - - QVariantList start=session->settings[Bookmark_Start].toList(); - QVariantList end=session->settings[Bookmark_End].toList(); - QStringList notes=session->settings[Bookmark_Notes].toStringList(); - - int size = start.size(); - for (int i=0; i < size; ++i) { - bookmarks.append(Bookmark(start.at(i).toLongLong(), end.at(i).toLongLong(), notes.at(i))); - } - return bookmarks; -} - -void JournalEntry::addBookmark(qint64 start, qint64 end, QString note) -{ - bookmarks.append(Bookmark(start,end,note)); - session->SetChanged(true); -} - -void JournalEntry::delBookmark(qint64 start, qint64 end) -{ - bool removed; - do { - removed = false; - int size = bookmarks.size(); - for (int i=0; iSetChanged(true); // make sure it gets saved later.. - removed=true; - break; - } - } - } while (removed); // clean up any stupid duplicates just in case.. :P - // if I wanted to be nice above, I could add the note string to the search as well.. - // (some users might be suprised to see the lot go with the same start and end index) -} - -void BackupJournal(QString filename) +bool Journal::BackupJournal(QString filename) { QString outBuf; QXmlStreamWriter stream(&outBuf); @@ -220,13 +40,22 @@ void BackupJournal(QString filename) stream.writeStartDocument(); // stream.writeProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\""); stream.writeStartElement("OSCAR"); + stream.writeAttribute("created", QDateTime::currentDateTime().toString(Qt::ISODate)); + stream.writeStartElement("Journal"); stream.writeAttribute("username", p_profile->user->userName()); + stream.writeAttribute("height_cm", QString::number(p_profile->user->height())); + if (p_profile->general->unitSystem()!=US_Undefined) { + stream.writeAttribute("systemUnits", ( p_profile->general->unitSystem()==US_Metric?"Metric":"Englsh") ); + } QDate first = p_profile->FirstDay(MT_JOURNAL); QDate last = p_profile->LastDay(MT_JOURNAL); + DEBUGFC Q(first) Q(last); + QDate date = first.addDays(-1); + int days_saved = 0 ; do { date = date.addDays(1); @@ -243,18 +72,33 @@ void BackupJournal(QString filename) && !journal->settingExists(Bookmark_Start)) { continue; } + QString weight; + QString zombie; + QString notes; + QString lastupdated; + QVariantList start; + int havedata=0; - stream.writeStartElement("day"); - stream.writeAttribute("date", date.toString()); if (journal->settingExists(Journal_Weight)) { - QString weight = sess->settings[Journal_Weight].toString(); - stream.writeAttribute("weight", weight); + weight = sess->settings[Journal_Weight].toString(); + havedata |= JRNL_Weight ; } if (journal->settingExists(Journal_ZombieMeter)) { - QString zombie = sess->settings[Journal_ZombieMeter].toString(); - stream.writeAttribute("zombie", zombie); + zombie = sess->settings[Journal_ZombieMeter].toString(); + havedata |= JRNL_Zombie ; + } + + if (journal->settingExists(Journal_Notes)) { + notes = sess->settings[Journal_Notes].toString(); + //notes = Daily::convertHtmlToPlainText(notes).trimmed(); + havedata |= JRNL_Notes ; + } + + if (journal->settingExists(Bookmark_Start)) { + start=sess->settings[Bookmark_Start].toList(); + if (start.size()>0) havedata |= JRNL_Bookmarks ; } if (journal->settingExists(LastUpdated)) { @@ -264,35 +108,45 @@ void BackupJournal(QString filename) #else qint64 dtx = dt.toSecsSinceEpoch(); #endif - QString dts = QString::number(dtx); - stream.writeAttribute("lastupdated", dts); + lastupdated = QString::number(dtx); } - if (journal->settingExists(Journal_Notes)) { - stream.writeStartElement("note"); - stream.writeTextElement("text", sess->settings[Journal_Notes].toString()); - stream.writeEndElement(); // notes + if (!havedata) { + // No data to archive. + continue ; } + //QString dateStr = ((++count & 1)==0) ? date.toString(/*Qt::ISODate*/) : date.toString(Qt::ISODate) ; + QString dateStr =date.toString(Qt::ISODate) ; + stream.writeStartElement("day"); + stream.writeAttribute("date", dateStr); + if(!weight.isEmpty()) stream.writeAttribute(WEIGHT, weight); + if(!zombie.isEmpty()) stream.writeAttribute(ZOMBIE, zombie); + stream.writeAttribute("lastupdated", lastupdated); - if (journal->settingExists(Bookmark_Start)) { - QVariantList start=sess->settings[Bookmark_Start].toList(); - QVariantList end=sess->settings[Bookmark_End].toList(); - QStringList notes=sess->settings[Bookmark_Notes].toStringList(); - stream.writeStartElement("bookmarks"); - int size = start.size(); - for (int i=0; i< size; i++) { - stream.writeStartElement("bookmark"); - stream.writeAttribute("notes",notes.at(i)); - stream.writeAttribute("start",start.at(i).toString()); - stream.writeAttribute("end",end.at(i).toString()); - stream.writeEndElement(); // bookmark + if (!notes.isEmpty() ) { + stream.writeStartElement("note"); + stream.writeTextElement("text", notes); + stream.writeEndElement(); // notes } - stream.writeEndElement(); // bookmarks - } + if (start.size()>0) { + QVariantList end=sess->settings[Bookmark_End].toList(); + QStringList notes=sess->settings[Bookmark_Notes].toStringList(); + stream.writeStartElement("bookmarks"); + int size = start.size(); + for (int i=0; i< size; i++) { + stream.writeStartElement("bookmark"); + stream.writeAttribute("notes",notes.at(i)); + stream.writeAttribute("start",start.at(i).toString()); + stream.writeAttribute("end",end.at(i).toString()); + stream.writeEndElement(); // bookmark + } + stream.writeEndElement(); // bookmarks + } + days_saved++; stream.writeEndElement(); // day - } while (date <= last); + // //stream.writeAttribute("DaysSaved", QString::number(days_saved)); stream.writeEndElement(); // Journal stream.writeEndElement(); // OSCAR @@ -302,7 +156,7 @@ void BackupJournal(QString filename) if (!file.open(QIODevice::WriteOnly)) { qWarning() << "Couldn't open journal file" << filename << "error code" << file.error() << file.errorString(); - return; + return false; } QTextStream ts(&file); @@ -310,23 +164,269 @@ void BackupJournal(QString filename) ts.setGenerateByteOrderMark(true); ts << outBuf; file.close(); + QMessageBox::information(nullptr, STR_MessageBox_Information, + QString(QObject::tr("%1 days Journal Data was saved in file %2")).arg(days_saved).arg(filename) , + QMessageBox::Ok); + + return true; } -DayController::DayController() -{ - journal = nullptr; - cpap = nullptr; - oximeter = nullptr; -} -DayController::~DayController() -{ - delete journal; +void Journal::getJournal(Daily*& daily,QDate& date,Session* & journal) { + if (journal) return; + journal = daily->GetJournalSession(date,true); + if (journal) return; + journal = daily->CreateJournalSession(date); } -void DayController::setDate(QDate date) -{ - if (journal) { - delete journal; + +bool Journal::RestoreDay (QDomElement& dayElement,QDate& date,QString& filename) { + Daily* daily = mainwin->getDaily(); + if (!daily) return false; + Session* journal = nullptr; + bool changed = false; + + // handle zombie - feelings + bool ok = false; + int zombie = 0; + zombie = (dayElement.attribute(ZOMBIE)).toInt(&ok); + if (!ok) { zombie=0; } + if (zombie == 0 ) { + zombie = (dayElement.attribute(OLD_ZOMBIE)).toInt(&ok); + if (!ok) { zombie=0; } } - journal = new JournalEntry(date); + DEBUGFC O("\n\n") ; + DEBUGFC O(date) O(filename); Q_UNUSED(filename); + if (zombie>0) { + int jvalue = 0 ; + getJournal(daily,date,journal); + if (journal->settings.contains(Journal_ZombieMeter)) { + jvalue = journal->settings[Journal_ZombieMeter].toInt(); + } + if (jvalue == 0) { + DEBUGFC O(date) Q(zombie); + daily->set_JournalZombie(date,zombie); + if (date == daily->getDate()) daily->set_ZombieUI(zombie); + changed = true; + } + } + + // handle Weight + double weight = (dayElement.attribute(WEIGHT)).toDouble(&ok); + if (weight>zeroD) { + getJournal(daily,date,journal); + double jvalue = 0.0 ; + if (journal->settings.contains(Journal_Weight)) { + jvalue = journal->settings[Journal_Weight].toDouble(); + } + if (jvalue < zeroD ) { + DEBUGFC O(date) Q(weight); + daily->set_JournalWeightValue(date,weight); + if (date == daily->getDate()) daily->set_WeightUI(weight); + changed = true; + } + } + + // Handle Notes. + QDomElement noteText = dayElement.elementsByTagName("note").at(0).toElement().elementsByTagName("text").at(0).toElement(); + if (!noteText.text().isEmpty() ) { + getJournal(daily,date,journal); + // there are characters in notes. maybe just spaces. Ignore spaces. + QString plainTextToAdd = Daily::convertHtmlToPlainText(noteText.text()); + + // get existing note if any. + QString currNoteHtml = journal->settings[Journal_Notes].toString(); + QString currNotePlainText = Daily::convertHtmlToPlainText(currNoteHtml); + if (currNotePlainText.contains(plainTextToAdd) ) { + // plainText to add is equal to curr or is it a subset of the current Note + // use the current notes.. ignore text in backup. + } else { + // plainText is not equal to curr nor is it a subset of the current Note + if (plainTextToAdd.contains(currNotePlainText) ) { + //curr note is a subset of the new - so use new. + currNoteHtml = noteText.text(); + } else { + // ToAdd text and Current text are different. + // use previous verson append with current + currNoteHtml.prepend(noteText.text()); + } + daily->set_JournalNotesHtml(date,currNoteHtml); + if (date == daily->getDate()) daily->set_NotesUI(noteText.text()); + DEBUGFC O(date) Q((void*)journal) O( )Daily::convertHtmlToPlainText(currNoteHtml); + changed = true; + } + } + + QDomNodeList bookmarks = dayElement.elementsByTagName("bookmarks").at(0).toElement().elementsByTagName("bookmark"); + if (bookmarks.size()>0) { + DEBUGFC Q(bookmarks.size()); + getJournal(daily,date,journal); + // get list of bookmarks for journal. These will not be removed. + QVariantList start; + QVariantList end; + QStringList notes; + if (journal->settings.contains(Bookmark_Start)) { + //DEBUGFC; + start=journal->settings[Bookmark_Start].toList(); + end=journal->settings[Bookmark_End].toList(); + notes=journal->settings[Bookmark_Notes].toStringList(); + } + // check if arcived bookmark is current list + bool bmChanged = false; + for (int idx=0 ; idx < bookmarks.size() ; idx++) { + // get archived bookmark + //DEBUGFC Q(idx) Q(bookmarks.size()) Q(start.size()) ; + QDomElement bookmark = bookmarks.at(idx).toElement(); + qint64 archiveStart = bookmark.attribute("start").toLongLong(); + qint64 archiveEnd = bookmark.attribute("end").toLongLong(); + QString archiveNote = bookmark.attribute("notes"); + // check if bookmark already exists. + + bool duplicate = false; + bool bNoteChanged = false; + for (int idy=0 ; idy < start.size() ; idy++) { + //DEBUGFC Q(idy); + qint64 bmStart = start.at(idy).toLongLong(); + qint64 bmEnd = end.at(idy).toLongLong(); + if ( (bmStart == archiveStart) && (bmEnd == archiveEnd) ) { + duplicate = true; + //DEBUGFC Q(idx) Q(idy); + // have same bookmark - new check if notes need merging + QString aNote = archiveNote.simplified(); + QString bmNote = notes.at(idy); + QString bNote = bmNote.simplified(); + DEBUGFC Q(aNote) Q(bNote) Q(bNote.contains(aNote)) Q(aNote.contains(bNote)); + if (bNote.contains(aNote) ) { + // no action needed. + //DEBUGFC Q(idx) Q(idy) Q(bNote);; + break; + } else { + // updated existing bookmark label + //DEBUGFC Q(idx) Q(idy); + // if an append is needed. + if (aNote.contains(bNote)) { + // use archived note + //DEBUGFC Q(idx) Q(idy); + } else { + //DEBUGFC Q(idx) Q(idy); + // prepend archive note to bmNote + archiveNote.append(" :: ").append(bmNote); + } + // use archiveNote. + notes[idy]= archiveNote; + bmChanged = true; + bNoteChanged = true; + } + } + } + if (!duplicate) { + DEBUGFC Q(date) Q(idx) Q(archiveNote); + // here if need to add archive bookmark. + // add archive bookmark to currrent list + start.push_back(archiveStart); + end.push_back(archiveEnd); + notes.push_back(archiveNote); + bmChanged = true; + } else if (bNoteChanged) { + DEBUGFC Q(date) Q(idx) Q(archiveNote); + } + } + if (bmChanged) { + //DEBUGFC Q(bmChanged); + getJournal(daily,date,journal); + journal->settings[Bookmark_Start]=start; + journal->settings[Bookmark_End]=end; + journal->settings[Bookmark_Notes]=notes; + if (date == daily->getDate()) daily->set_BookmarksUI(start,end,notes,0); + } else { + DEBUGFC O("bookmark ignored") ; + } + + } + + if (!journal) { + return true; + } + if (!journal->machine()) { + return true; + } + if (changed) { + journal->SetChanged(true); + journal->settings[LastUpdated] = QDateTime::currentDateTime(); + journal->machine()->SaveSummaryCache(); + journal->SetChanged(false); + } + DEBUGFC O(date) O("\n\n"); + return true; } + + +bool Journal::RestoreJournal(QString filename) +{ + QFile file(filename); + if (!file.open(QFile::ReadOnly)) { + qWarning() << "Could not open" << filename.toLocal8Bit().data() << "for reading, error code" << file.error() << file.errorString(); + return false; + } + + QDomDocument doc("machines.xml"); + + if (!doc.setContent(&file)) { + qWarning() << "Invalid XML Content in" << filename.toLocal8Bit().data(); + return false; + } + file.close(); + + QDomElement root = doc.documentElement(); // Get the root element of the document + if (root.isNull()) { + return false; + } + QDomNodeList days = doc.elementsByTagName("day"); + if (days.isEmpty()) { + return false; + } + + QDate first = p_profile->FirstDay(); + QDate last = p_profile->LastDay(); + QDate current = QDate::currentDate(); + int error=0; + int ignored=0; + int used=0; + for (int idx=0 ; idx < days.size() ; idx++) { + QDomElement dayElement = days.at(idx).toElement(); + + QString dateStr = dayElement.attribute("date") ; + QDate date = QDate::fromString(dateStr,Qt::ISODate) ; + if (!date.isValid()) { + QDate newdate = QDate::fromString(dateStr) ; // read original date format + date = newdate; + } + if (!date.isValid()) { + error++ ; + continue; + } + if (date < first) { + ignored++ ; + continue; + } + if (date > last) { + ignored++ ; + continue; + } + if (date > current) { + error++ ; + continue; + } + if ( RestoreDay(dayElement,date,filename) ) { + used++; + } + } + double user_height_cm = p_profile->user->height(); + if (user_height_cm=zeroD) p_profile->user->setHeight(height_cm); + } + return true; +} + diff --git a/oscar/SleepLib/journal.h b/oscar/SleepLib/journal.h index 2464092d..929b1006 100644 --- a/oscar/SleepLib/journal.h +++ b/oscar/SleepLib/journal.h @@ -1,7 +1,7 @@ /* SleepLib Journal Implementation * * Copyright (c) 2019-2024 The OSCAR Team - * Copyright (C) 2011-2018 Mark Watkins + * Copyright (C) 2011-2018 Mark Watkins * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of the source code @@ -11,72 +11,22 @@ #ifndef JOURNAL_H #define JOURNAL_H +class Session; +#include +#include +#include +#include "daily.h" + #include "SleepLib/profiles.h" - -void BackupJournal(QString filename); - -class Bookmark { +class Journal { public: - Bookmark() { - start = end = 0; - } - Bookmark(const Bookmark & copy) { - start = copy.start; - end = copy.end; - notes = copy.notes; - } - Bookmark& operator=(const Bookmark & other) = default; - Bookmark(qint64 start, qint64 end, QString notes): - start(start), end(end), notes(notes) {} - - qint64 start; - qint64 end; - QString notes; -}; - -class JournalEntry -{ -public: - JournalEntry(QDate date); - ~JournalEntry(); - bool Save(); - - QString notes(); - void setNotes(QString notes); - - EventDataType weight(); - void setWeight(EventDataType weight); - int zombie(); - void setZombie(int zombie); - - QList & getBookmarks(); - void addBookmark(qint64 start, qint64 end, QString note); - void delBookmark(qint64 start, qint64 end); - - -protected: - QDate m_date; - QList bookmarks; - Day * day; - Session * session; - bool newsession; -}; - -void BackupJournal(QString filename); - - -class DayController -{ - DayController(); - ~DayController(); - - void setDate(QDate date); - - QDate m_date; - JournalEntry * journal; - Day * cpap; - Day * oximeter; - + enum { JRNL_Zombie = 1 , JRNL_Weight = 2 , JRNL_Notes = 4 , JRNL_Bookmarks = 8 }; + static bool BackupJournal(QString filename); + static bool RestoreJournal(QString filename); +private: + constexpr static double zeroD = 0.0001; + static void getJournal(Daily*& daily,QDate& date,Session* & journal); + static bool RestoreDay (QDomElement& dayElement,QDate& date,QString& filename) ; }; #endif // JOURNAL_H diff --git a/oscar/mainwindow.cpp b/oscar/mainwindow.cpp index 451c3580..66503363 100644 --- a/oscar/mainwindow.cpp +++ b/oscar/mainwindow.cpp @@ -1,7 +1,7 @@ /* OSCAR MainWindow Implementation * * Copyright (c) 2020-2024 The OSCAR Team - * Copyright (c) 2011-2018 Mark Watkins + * Copyright (c) 2011-2018 Mark Watkins * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of the source code @@ -45,6 +45,7 @@ #include "common_gui.h" #include "version.h" #include "SleepLib/appsettings.h" // defines for REMSTAR_M_SUPPORT +#include "SleepLib/journal.h" // Custom loaders that don't autoscan.. @@ -2400,7 +2401,7 @@ void MainWindow::on_statisticsButton_clicked() } } -void MainWindow::init_reportModeUi() +void MainWindow::init_reportModeUi() { QTextCharFormat format = ui->statStartDate->calendarWidget()->weekdayTextFormat(Qt::Saturday); format.setForeground(QBrush(Qt::black, Qt::SolidPattern)); @@ -2609,17 +2610,50 @@ void MainWindow::on_actionShowPersonalData_toggled(bool visible) #include "SleepLib/journal.h" +void MainWindow::on_actionImport_Journal_triggered() +{ + QString folder; + if (p_profile->contains(STR_PREF_LastJournalPath)) { + folder = (*p_profile)[STR_PREF_LastJournalPath].toString(); + } + QFileInfo fi(folder); + if (!fi.isDir() ) { + folder = QStandardPaths::StandardLocation(QStandardPaths::DocumentsLocation); + } + QString filename = QFileDialog::getOpenFileName(this, + tr("Choose where to read journal"), + folder, + tr("XML Files (*.xml)")); + if (Journal::RestoreJournal(filename) ) { + QFileInfo fi(filename); + QDir dir = fi.dir(); + if (dir.exists() ) { + (*p_profile)[STR_PREF_LastJournalPath] = dir.absolutePath(); + } + } +} + void MainWindow::on_actionExport_Journal_triggered() { QString folder; - - folder = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); - + if (p_profile->contains(STR_PREF_LastJournalPath)) { + folder = (*p_profile)[STR_PREF_LastJournalPath].toString(); + } + QFileInfo fi(folder); + if (!fi.isDir() ) { + folder = QStandardPaths::StandardLocation(QStandardPaths::DocumentsLocation); + } folder += QDir::separator() + tr("%1's Journal").arg(p_profile->user->userName()) + ".xml"; QString filename = QFileDialog::getSaveFileName(this, tr("Choose where to save journal"), folder, tr("XML Files (*.xml)")); - BackupJournal(filename); + if (Journal::BackupJournal(filename) ) { + QFileInfo fi(filename); + QDir dir = fi.dir(); + if (dir.exists() ) { + (*p_profile)[STR_PREF_LastJournalPath] = dir.absolutePath(); + } + } } void MainWindow::on_actionShow_Performance_Counters_toggled(bool arg1) diff --git a/oscar/mainwindow.h b/oscar/mainwindow.h index 5d5a96f4..c74f76e5 100644 --- a/oscar/mainwindow.h +++ b/oscar/mainwindow.h @@ -1,7 +1,7 @@ /* OSCAR MainWindow Headers * * Copyright (c) 2019-2024 The OSCAR Team - * Copyright (C) 2011-2018 Mark Watkins + * Copyright (C) 2011-2018 Mark Watkins * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of the source code @@ -345,6 +345,8 @@ class MainWindow : public QMainWindow void on_actionExport_Journal_triggered(); + void on_actionImport_Journal_triggered(); + void on_actionShow_Performance_Counters_toggled(bool arg1); void on_actionExport_CSV_triggered(); diff --git a/oscar/mainwindow.ui b/oscar/mainwindow.ui index 18ac908f..b2e820e3 100644 --- a/oscar/mainwindow.ui +++ b/oscar/mainwindow.ui @@ -2411,6 +2411,7 @@ p, li { white-space: pre-wrap; } + @@ -2824,6 +2825,11 @@ p, li { white-space: pre-wrap; } Backup Journal + + + Import Journal + + true