diff --git a/oscar/Resources.qrc b/oscar/Resources.qrc
index 95050bd4..816db239 100644
--- a/oscar/Resources.qrc
+++ b/oscar/Resources.qrc
@@ -58,5 +58,12 @@
icons/fp_icon.png
icons/up-down.png
icons/warning.png
+ icons/exit.png
+ icons/brick-wall.png
+ icons/plus.png
+ icons/rename.png
+ icons/restore.png
+ icons/trash_can.png
+ icons/update.png
diff --git a/oscar/backupFiles.cpp b/oscar/backupFiles.cpp
new file mode 100644
index 00000000..7d708c3f
--- /dev/null
+++ b/oscar/backupFiles.cpp
@@ -0,0 +1,612 @@
+/* backup graph settiongs Implementation
+ *
+ * Copyright (c) 2019-2022 The OSCAR Team
+ * 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 BACKUPMENUHEADER_OFF
+#define MESSAGEBOXHEADER_OFF
+
+#define TEST_MACROS_ENABLED_OFF
+#include
+
+#include
+#include
+#include
+#include
+#include "SleepLib/profiles.h"
+#include "backupFiles.h"
+
+
+BackupFiles::BackupFiles(QString title,QWidget* parent) : parent(parent),title(title)
+{
+ // Initialize directory accesses to profile files.
+ QString dirname = p_profile->Get("{DataFolder}/");
+ dir = new QDir(dirname);
+ if (!dir->exists()) {
+ //qWarning (QString("Cannot find the directory %1").arg(dirname));
+ return ;
+ }
+ dir->setFilter(QDir::Files | QDir::Readable | QDir::Writable | QDir::NoSymLinks);
+
+ createMenu() ;
+ QString descFileName = QString("%1.%2").arg(title).arg("descriptions.txt");
+ backupDescriptions = new BackupDescriptions (dir,descFileName);
+
+ backupDialog->connect(backupaddFullBtn, SIGNAL(clicked()), this, SLOT (addFull_feature() ));
+ backupDialog->connect(backupAddBtn, SIGNAL(clicked()), this, SLOT (add_feature() ));
+ backupDialog->connect(backupRestoreBtn, SIGNAL(clicked()), this, SLOT (restore_feature() ));
+ backupDialog->connect(backupUpdateBtn, SIGNAL(clicked()), this, SLOT (update_feature() ));
+ backupDialog->connect(backupRenameBtn, SIGNAL(clicked()), this, SLOT (rename_feature() ));
+ backupDialog->connect(backupDeleteBtn, SIGNAL(clicked()), this, SLOT (delete_feature() ));
+#ifndef BACKUPMENUHEADER
+ backupDialog->connect(backupExitBtn, SIGNAL(clicked()), this, SLOT (exit() ));
+#endif
+
+ backupDialog->connect(backuplist, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(itemChanged(QListWidgetItem*) ));
+ backupDialog->connect(backuplist, SIGNAL(itemSelectionChanged()), this, SLOT(itemSelectionChanged() ));
+
+ singleLineRe = new QRegularExpression( QString("^\\s*([^\\r\\n]{0,%1})").arg(1+maxDescriptionLen) );
+ backupFileNumRe = new QRegularExpression( QString("backup(\\d+)(.shg)?$") );
+ parseFilenameRe = new QRegularExpression(QString("^(%1[.](backup(\\d*)))[.]shg$").arg(title));
+}
+
+BackupFiles::~BackupFiles()
+{
+ backupDialog->disconnect(backupaddFullBtn, SIGNAL(clicked()), this, SLOT (addFull_feature() ));
+ backupDialog->disconnect(backupAddBtn, SIGNAL(clicked()), this, SLOT (add_feature() ));
+ backupDialog->disconnect(backupRestoreBtn, SIGNAL(clicked()), this, SLOT (restore_feature() ));
+ backupDialog->disconnect(backupUpdateBtn, SIGNAL(clicked()), this, SLOT (update_feature() ));
+ backupDialog->disconnect(backupDeleteBtn, SIGNAL(clicked()), this, SLOT (delete_feature() ));
+ backupDialog->disconnect(backupRenameBtn, SIGNAL(clicked()), this, SLOT (rename_feature() ));
+#ifndef BACKUPMENUHEADER
+ backupDialog->disconnect(backupExitBtn, SIGNAL(clicked()), this, SLOT (exit() ));
+#endif
+
+ backupDialog->disconnect(backuplist, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(itemChanged(QListWidgetItem*) ));
+ backupDialog->disconnect(backuplist, SIGNAL(itemSelectionChanged()), this, SLOT(itemSelectionChanged() ));
+
+ delete backupDescriptions;
+
+ delete singleLineRe;
+ delete backupFileNumRe;
+ delete parseFilenameRe;
+}
+
+void BackupFiles::createMenu() {
+ styleOn= calculateStyle(true,false);
+ styleOff= calculateStyle(false,false);
+ styleExitBtn=calculateStyle(true,true);
+ //"background:transparent;"
+ //"background-color:yellow;"
+ styleMessageBox=
+ "QMessageBox { "
+ "background-color:yellow;"
+ "color:black;"
+ //"font: 24px ;"
+ //"padding: 4px;"
+ "border: 2px solid black;"
+ "text-align: center;"
+ "}"
+ "QPushButton { "
+ //"font: 24px ;"
+ "color:black;"
+ "}"
+ ;
+ styleDialog=
+ "QDialog { "
+ "border: 3px solid black;"
+ "min-width:30em;" // make large fonts in message box
+ "}";
+
+
+ backupDialog= new QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint|Qt::WindowSystemMenuHint);
+#ifndef BACKUPMENUHEADER
+ backupDialog->setWindowFlag(Qt::FramelessWindowHint);
+#else
+ backupDialog->setWindowTitle(tr("Backup Files Management"));
+#endif
+
+ backupaddFullBtn =new QPushButton("Add", parent);
+ backupAddBtn =new QPushButton(tr("Add"), parent);
+ backupRestoreBtn = new QPushButton(tr("Restore"), parent);
+ backupUpdateBtn = new QPushButton(tr("Update"), parent);
+ backupRenameBtn = new QPushButton(tr("Rename"), parent);
+ backupDeleteBtn = new QPushButton(tr("Delete"), parent);
+#ifndef BACKUPMENUHEADER
+ backupExitBtn = new QPushButton(*m_icon_exit,tr(""),parent);
+#endif
+
+ backuplist=new QListWidget();
+ backuplist->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+
+ backupLayout = new QVBoxLayout(backupDialog);
+ layout1 = new QHBoxLayout();
+ layout2 = new QVBoxLayout();
+ layout2->setMargin(6);
+ backupLayout->addLayout(layout1);
+ backupLayout->addLayout(layout2);
+
+ layout1->addWidget(backupaddFullBtn);
+ layout1->addWidget(backupAddBtn);
+ layout1->addWidget(backupRestoreBtn);
+ layout1->addWidget(backupRenameBtn);
+ layout1->addWidget(backupUpdateBtn);
+ layout1->addWidget(backupDeleteBtn);
+#ifndef BACKUPMENUHEADER
+ layout1->addWidget(backupExitBtn);
+#endif
+ layout2->addWidget(backuplist, 1);
+/*TRANSLATION*/
+ backupaddFullBtn-> setToolTip(tr("Add has been inhibited. The maximum number of backups have been exceeded. "));
+ backupAddBtn-> setToolTip(tr("Adds new Backup with current settings."));
+ backupRestoreBtn-> setToolTip(tr("Restores settings from the selected Backup."));
+ backupRenameBtn-> setToolTip(tr("Rename the selected Backup. Must edit existing name then press enter."));
+ backupUpdateBtn-> setToolTip(tr("Update the selected Backup with current settings."));
+ backupDeleteBtn-> setToolTip(tr("Delete the selected Backup."));
+#ifndef BACKUPMENUHEADER
+ backupExitBtn-> setToolTip(tr("Closes the dialog menu. Returns to previous menu."));
+#endif
+
+ backupDialog->setStyleSheet(styleDialog);
+ backupaddFullBtn->setStyleSheet(styleOff);
+ backupAddBtn->setStyleSheet(styleOn);
+ backupRestoreBtn->setStyleSheet(styleOn);
+ backupUpdateBtn->setStyleSheet(styleOn);
+ backupRenameBtn->setStyleSheet(styleOn);
+ backupDeleteBtn->setStyleSheet(styleOn);
+#ifndef BACKUPMENUHEADER
+ backupExitBtn->setStyleSheet( styleExitBtn );
+#endif
+
+
+ backupaddFullBtn->setIcon(*m_icon_add );
+ backupAddBtn->setIcon(*m_icon_add );
+ backupRestoreBtn->setIcon(*m_icon_restore );
+ backupRenameBtn->setIcon(*m_icon_rename );
+ backupUpdateBtn->setIcon(*m_icon_update );
+ backupDeleteBtn->setIcon(*m_icon_delete );
+ backupDeleteBtn->setIcon(*m_icon_delete );
+
+
+ int timeout = AppSetting->tooltipTimeout();
+ backupaddFullBtn->setToolTipDuration(timeout);
+ backupAddBtn->setToolTipDuration(timeout);
+ backupRestoreBtn->setToolTipDuration(timeout);
+ backupUpdateBtn->setToolTipDuration(timeout);
+ backupRenameBtn->setToolTipDuration(timeout);
+ backupDeleteBtn->setToolTipDuration(timeout);
+#ifndef BACKUPMENUHEADER
+ backupExitBtn->setToolTipDuration(timeout);
+#endif
+
+};
+
+bool BackupFiles::confirmAction(QString name,QString question,QIcon* icon) {
+ QMessageBox msgBox;
+ msgBox.setText(question);
+ if (icon!=nullptr) {
+ msgBox.setIconPixmap(icon->pixmap(QSize(50,50)));
+ }
+
+ msgBox.setStandardButtons(QMessageBox::Cancel | QMessageBox::Yes );
+ msgBox.setDefaultButton(QMessageBox::Cancel);
+ msgBox.setStyleSheet(styleMessageBox);
+
+ #ifdef MESSAGEBOXHEADER
+ msgBox.setWindowTitle(name);
+ #else
+ Q_UNUSED(name);
+ msgBox.setWindowFlag(Qt::FramelessWindowHint,true);
+ #endif
+
+ return (msgBox.exec()==QMessageBox::Yes);
+
+}
+
+QString BackupFiles::calculateStyle(bool on,bool exitBtn){
+ QString btnStyle=QString("QPushButton{%1%2}").arg(on
+ ?"color: black;background-color:white;"
+ :"color: darkgray;background-color:#e8e8e8 ;"
+ ).arg(!exitBtn ?
+ ""
+ :
+ "background: transparent;"
+ "border-radius: 8px;"
+ "border: 2px solid transparent;"
+ "max-width:1em;"
+ "border:none;"
+ );
+
+ QString toolTipStyle=" QToolTip { "
+ "border: 1px solid black;"
+ "border-width: 1px;"
+ "padding: 4px;"
+ "font: 14px ; color:black; background-color:yellow;"
+ "}";
+ btnStyle.append(toolTipStyle);
+ return btnStyle;
+}
+
+void BackupFiles::looksOn(QPushButton* button,bool on){
+ button->setEnabled(on);
+ button->setStyleSheet(on?styleOn:styleOff);
+}
+
+void BackupFiles::enableButtons(bool enable) {
+ looksOn(backupUpdateBtn,enable);
+ looksOn(backupRestoreBtn,enable);
+ looksOn(backupDeleteBtn,enable);
+ looksOn(backupRenameBtn,enable);
+ if (unusedBackupNum<0) { // check if at Maximum limit
+ backupAddBtn->hide();
+ backupaddFullBtn->show();
+ } else {
+ backupaddFullBtn->hide();
+ backupAddBtn->show();
+ }
+}
+
+void BackupFiles::update_feature() {
+ if(!graphView) return;
+ QListWidgetItem * item=backuplist->currentItem();
+ if (!item) return;
+ if(!confirmAction( item->text(), tr("Ok to Update?") , m_icon_update) ) return;
+ QString backupName = item->data(backupFileName).toString();
+ QString name = QString("%1.%2").arg(title).arg(backupName);
+ graphView->SaveSettings(name);
+};
+
+void BackupFiles::restore_feature() {
+ if(!graphView) return;
+ QListWidgetItem * item=backuplist->currentItem();
+ if (!item) return;
+ QString backupName = item->data(backupFileName).toString();
+ QString name = QString("%1.%2").arg(title).arg(backupName);
+ graphView->LoadSettings(name);
+ exit();
+};
+
+void BackupFiles::rename_feature() {
+ if(!graphView) return;
+ QListWidgetItem * item=backuplist->currentItem();
+ if (!item) return;
+ backuplist->editItem(item);
+ // BackupFiles::itemChanged(QListWidgetItem *item) is called when edit changes the entry.
+ // itemChanged will update the description map
+}
+
+void BackupFiles::delete_feature() {
+ if(!graphView) return;
+ QListWidgetItem * item=backuplist->currentItem();
+ if (!item) return;
+
+ if(!confirmAction(item->text(), tr("Ok To Delete?") ,m_icon_delete) ) return;
+
+ QString backupName = item->data(backupFileName).toString();
+ backupDescriptions->remove(backupName);
+ backupDescriptions->save();
+ QString relFileName=QString("%1.%2.shg").arg(title).arg(backupName);
+ dir->remove(relFileName);
+ delete item;
+ unusedBackupNum=backupNum(backupName);
+ enableButtons(true);
+}
+
+void BackupFiles::addFull_feature() {
+ QMessageBox msgBox;
+ msgBox.setText(tr("Maximum number of Backups exceeded."));
+ msgBox.setStandardButtons(QMessageBox::Cancel);
+ msgBox.setDefaultButton(QMessageBox::Cancel);
+#ifdef MESSAGEBOXHEADER
+ msgBox.setWindowTitle(tr("Maximum Files Exceeded"));
+#else
+ msgBox.setWindowFlag(Qt::FramelessWindowHint,true);
+#endif
+ msgBox.setStyleSheet(styleMessageBox);
+ msgBox.setIconPixmap(m_icon_addFull->pixmap(QSize(50,50)));
+ msgBox.exec();
+}
+
+void BackupFiles::add_feature() {
+ if(!graphView) return;
+
+ QString backupName = QString("%2%3").arg("backup").arg(unusedBackupNum,backupNumMaxLength,10,QLatin1Char('0'));
+ QString name = QString("%1.%2").arg(title).arg(backupName);
+ graphView->SaveSettings(name);
+ // create a default description - use formatted datetime.
+ QString desc=QDateTime::currentDateTime().toString();
+ backupDescriptions->add(backupName,desc);
+ backupDescriptions->save();
+ QListWidgetItem* item = updateFileList( backupName);
+ if (item!=nullptr) {
+ backuplist->setCurrentItem(item,QItemSelectionModel::ClearAndSelect);
+ backuplist->editItem(item);
+ }
+}
+
+void BackupFiles::itemChanged(QListWidgetItem *item)
+{
+ QString backupName=item->data(backupFileName).toString();
+ QString desc= item->text();
+
+ // use only the first line in a multiline string. Can be set using cut and paste
+ QRegularExpressionMatch match = singleLineRe->match(desc);
+ if (match.hasMatch()) {
+ // captured match is the first line and has been truncated
+ desc=match.captured(1).trimmed(); // reoves spaces at end.
+ } else {
+ // no match.
+ // an invalid name was entered. too much white space or empty
+ desc="";
+ }
+ if (desc.length()>maxDescriptionLen) {
+ desc.append("...");
+ }
+ if (desc.length() <=0) {
+ // returns name back to previous saved name
+ desc=backupDescriptions->get(backupName);
+ } else {
+ backupDescriptions->add(backupName,desc);
+ backupDescriptions->save();
+ }
+ item->setText(desc);
+}
+
+void BackupFiles::itemSelectionChanged()
+{
+ enableButtons(true);
+}
+
+int BackupFiles::backupNum(QString backupName) {
+ QRegularExpressionMatch match = backupFileNumRe->match(backupName);
+ int value=-1;
+ if (match.hasMatch()) {
+ value=match.captured(1).toInt();
+ }
+ return value;
+}
+
+QListWidgetItem* BackupFiles::updateFileList(QString find) {
+ Q_UNUSED(find);
+ QListWidgetItem* ret=nullptr;
+ enableButtons(false);
+ dir->refresh();
+ QFileInfoList filelist = dir->entryInfoList( QDir::Files | QDir::Readable | QDir::Writable | QDir::NoSymLinks,QDir::Name);
+
+ // Restrict number of files. easy to find availble unused entry for add function.
+
+ int row=0;
+ int count=0;
+ backuplist->clear();
+ unusedBackupNum=-1;
+ backupDescriptions->load();
+ for (int i = 0; i < filelist.size(); ++i) {
+ QFileInfo fileInfo = filelist.at(i);
+ QString fileName = fileInfo.fileName();
+ QRegularExpressionMatch match = parseFilenameRe->match(fileName);
+ if (match.hasMatch()) {
+ if (match.lastCapturedIndex()==3) {
+ QString backupName=match.captured(2);
+ int backupNum=match.captured(3).toInt();
+ // find an available backup name(number);
+ if (backupNum!=count) {
+ if (unusedBackupNum<0) unusedBackupNum=count;
+ }
+ count++;
+
+ QListWidgetItem *item = new QListWidgetItem(backupDescriptions->get(backupName));
+ item->setData(backupFileName,backupName);
+ item->setFlags(item->flags() | Qt::ItemIsEditable);
+ backuplist->insertItem(row,item);
+ //DEBUGF Q(count) Q(backupName) Q(item->text());
+ row++;
+ if (find!=nullptr && backupName==find) {
+ ret=item;
+ }
+ }
+ }
+ }
+ if (unusedBackupNum<0) { // check if there is an existing empty slot
+ // if not then the next available slot is at the end. CHeck if at max files.
+ if (countsortItems();
+ return ret;
+}
+
+
+void BackupFiles::exit() {
+ backupDialog->close();
+}
+
+void BackupFiles::backupMenu(gGraphView* graphView) {
+ this->graphView=graphView;
+ updateFileList();
+ backupDialog->raise();
+ backupDialog->exec();
+ exit();
+}
+
+//====================================================================================================
+//====================================================================================================
+// Backup Descriptions map class with file backup
+
+BackupDescriptions::BackupDescriptions(QDir* dir, QString _filename)
+{
+ filename = dir->absoluteFilePath(_filename);
+ parseDescriptionsRe = new QRegularExpression("^\\s*(\\w+):(.*)$");
+};
+
+BackupDescriptions::~BackupDescriptions() {
+ delete parseDescriptionsRe;
+};
+
+void BackupDescriptions::add(QString key,QString desc) {
+ descriptions.insert(key,desc);
+};
+
+void BackupDescriptions::remove(QString key) {
+ descriptions.remove(key);
+}
+QString BackupDescriptions::get(QString key) {
+ QString ret =descriptions.value(key,key);
+ return ret;
+}
+
+void BackupDescriptions::save() {
+ QFile file(filename);
+ file.open(QFile::WriteOnly);
+ QTextStream out(&file);
+
+ QMapIteratorit(descriptions);
+ while (it.hasNext()) {
+ it.next();
+ QString line=QString("%1:%2\n").arg(it.key()).arg(it.value());
+ out <match(line);
+ if (match.hasMatch()) {
+ QString backupName = match.captured(1);
+ QString desc = match.captured(2);
+ add(backupName,desc);
+ } else {
+ DEBUGF QQ("MATCH ERROR",line);
+ }
+ }
+}
+
+
+//====================================================================================================
+//====================================================================================================
+
+
+#if 0
+Are you <b>absolutely sure</b> you want to proceed?
+
+QMessageBox msgBox; msgBox.setText(tr("Confirm?"));
+QAbstractButton* pButtonYes = msgBox.addButton(tr("Yeah!"), QMessageBox::YesRole);
+pButtonNo=msgBox.addButton(tr("Nope"), QMessageBox::NoRole);
+btn.setIcon(const QIcon &icon);
+
+msgBox.exec();
+
+if (msgBox.clickedButton()==pButtonYes) {
+
+
+QIcon groupIcon( style()->standardIcon( QStyle::SP_DirClosedIcon ) )
+https://www.pythonguis.com/faq/built-in-qicons-pyqt/
+
+QMessageBox msgBox;
+msgBox.setText("The document has been modified.");
+msgBox.setInformativeText("Do you want to save your changes?");
+msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
+msgBox.setDefaultButton(QMessageBox::Save);
+int ret = msgBox.exec();
+switch (ret) {
+ case QMessageBox::Save:
+ // Save was clicked
+ break;
+ case QMessageBox::Discard:
+ // Don't Save was clicked
+ break;
+ case QMessageBox::Cancel:
+ // Cancel was clicked
+ break;
+ default:
+ // should never be reached
+ break;
+}
+
+
+
+// Reminders For testing
+
+ Different languages unicodes to test. optained from translation files
+
+ 도움주신분들
+ 已成功删除
+ 删除
+ הצג את מחיצת הנתונים
+
+ הצג את מחיצת הנתונים 已成功删除 عذرا ، لا يمكن تحديد موقع ملف.
+ 已成功删除 عذرا ، لا يمكن تحديد موقع ملف. 删除
+ Toon gegevensmap
+ عذرا ، لا يمكن تحديد موقع ملف.
+
+
+ backupDialog->connect(backuplist, SIGNAL(itemActivated(QListWidgetItem*)), this, SLOT(itemActivated(QListWidgetItem*) ));
+ backupDialog->connect(backuplist, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(itemDoubleClicked(QListWidgetItem*) ));
+ backupDialog->connect(backuplist, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(itemClicked(QListWidgetItem*) ));
+ backupDialog->connect(backuplist, SIGNAL(itemEntered(QListWidgetItem*)), this, SLOT(itemEntered(QListWidgetItem*) ));
+ backupDialog->connect(backuplist, SIGNAL(itemPressed(QListWidgetItem*)), this, SLOT(itemEntered(QListWidgetItem*) ));
+
+
+
+ backupDialog->disconnect(backuplist, SIGNAL(itemActivated(QListWidgetItem*)), this, SLOT(itemActivated(QListWidgetItem*) ));
+ backupDialog->disconnect(backuplist, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(itemDoubleClicked(QListWidgetItem*) ));
+ backupDialog->disconnect(backuplist, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(itemClicked(QListWidgetItem*) ));
+ backupDialog->disconnect(backuplist, SIGNAL(itemEntered(QListWidgetItem*)), this, SLOT(itemEntered(QListWidgetItem*) ));
+ backupDialog->disconnect(backuplist, SIGNAL(itemPressed(QListWidgetItem*)), this, SLOT(itemEntered(QListWidgetItem*) ));
+
+
+void BackupFiles::itemActivated(QListWidgetItem *item)
+{
+ Q_UNUSED( item );
+ DEBUGF Q( item->text() );
+}
+
+void BackupFiles::itemDoubleClicked(QListWidgetItem *item)
+{
+ Q_UNUSED( item );
+ DEBUGF Q( item->text() );
+}
+
+void BackupFiles::itemClicked(QListWidgetItem *item)
+{
+ Q_UNUSED( item );
+ DEBUGF Q( item->text() );
+}
+
+void BackupFiles::itemEntered(QListWidgetItem *item)
+{
+ Q_UNUSED( item );
+ DEBUGF Q( item->text() );
+}
+
+void BackupFiles::itemPressed(QListWidgetItem *item)
+{
+ Q_UNUSED( item );
+ DEBUGF Q( item->text() );
+}
+
+//private_slots:
+ void itemActivated(QListWidgetItem *item);
+ void itemDoubleClicked(QListWidgetItem *item);
+ void itemClicked(QListWidgetItem *item);
+ void itemEntered(QListWidgetItem *item);
+ void itemPressed(QListWidgetItem *item);
+
+
+
+
+
+#endif
+
diff --git a/oscar/backupFiles.h b/oscar/backupFiles.h
new file mode 100644
index 00000000..31f4bd11
--- /dev/null
+++ b/oscar/backupFiles.h
@@ -0,0 +1,121 @@
+/* Overview GUI Headers
+ *
+ * Copyright (c) 2019-2022 The OSCAR Team
+ * 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. */
+
+#ifndef BACKUPFILES_H
+#define BACKUPFILES_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include "Graphs/gGraphView.h"
+
+class BackupDescriptions
+{
+public:
+ BackupDescriptions(QDir* dir, QString filename) ;
+ virtual ~BackupDescriptions();
+ void add(QString key,QString desc);
+ void remove(QString key);
+ QString get(QString key);
+ void load();
+ void save();
+private:
+ QString filename;
+ QMap descriptions;
+ const QRegularExpression* parseDescriptionsRe;
+};
+
+class BackupFiles : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit BackupFiles(QString title , QWidget* parent) ;
+ ~BackupFiles();
+ void backupMenu(gGraphView* graphView);
+protected:
+ QIcon* m_icon_exit = new QIcon(":/icons/exit.png");
+ QIcon* m_icon_delete = new QIcon(":/icons/trash_can.png");
+ QIcon* m_icon_update = new QIcon(":/icons/update.png");
+ QIcon* m_icon_restore = new QIcon(":/icons/restore.png");
+ QIcon* m_icon_rename = new QIcon(":/icons/rename.png");
+ QIcon* m_icon_add = new QIcon(":/icons/plus.png");
+ QIcon* m_icon_addFull = new QIcon(":/icons/brick-wall.png");
+
+private:
+ const static int backupNumMaxLength=3;
+ const static int maxFiles=10; // Max supported design limited is 1000 - based on backupName has has 3 numeric digits backupNumMaxLength=3.
+ const static int maxDescriptionLen=60;
+
+ const QRegularExpression* singleLineRe;
+ const QRegularExpression* backupFileNumRe;
+ const QRegularExpression* parseFilenameRe;
+
+
+ QWidget* parent;
+ const QString title;
+ gGraphView* graphView=nullptr;
+
+ // backup widget
+ QDialog* backupDialog;
+ QListWidget* backuplist;
+
+ QPushButton* backupaddFullBtn; // Must be first item for workaround.
+ QPushButton* backupAddBtn;
+ QPushButton* backupDeleteBtn;
+ QPushButton* backupRestoreBtn;
+ QPushButton* backupUpdateBtn;
+ QPushButton* backupRenameBtn;
+ QPushButton* backupExitBtn;
+
+ QVBoxLayout* backupLayout;
+ QHBoxLayout* layout1;
+ QVBoxLayout* layout2;
+
+ QDir* dir;
+ int unusedBackupNum;
+ QListWidgetItem* updateFileList(QString findi=QString());
+ QString styleOn;
+ QString styleOff;
+ QString styleExitBtn;
+ QString styleMessageBox;
+ QString styleDialog;
+ QString calculateStyle(bool on,bool border);
+ void looksOn(QPushButton* button,bool on);
+ BackupDescriptions* backupDescriptions;
+ bool confirmAction(QString name,QString question,QIcon* icon);
+
+ void createMenu();
+ void enableButtons(bool enable);
+ void add_featurertn();
+
+ const int backupFileName = Qt::UserRole;
+ int backupNum(QString backupName);
+
+public slots:
+private slots:
+ void add_feature();
+ void addFull_feature();
+ void update_feature();
+ void restore_feature();
+ void delete_feature();
+ void rename_feature();
+ void exit();
+
+ void itemChanged(QListWidgetItem *item);
+ void itemSelectionChanged();
+};
+
+
+#endif // BACKUPFILES_H
diff --git a/oscar/daily.cpp b/oscar/daily.cpp
index 488727fe..4909c7eb 100644
--- a/oscar/daily.cpp
+++ b/oscar/daily.cpp
@@ -541,6 +541,7 @@ Daily::Daily(QWidget *parent,gGraphView * shared)
ui->JournalNotes->installEventFilter(this);
// qDebug() << "Finished making new Daily object";
// sleep(3);
+ backupFiles=nullptr;
}
Daily::~Daily()
@@ -563,6 +564,7 @@ Daily::~Daily()
delete ui;
delete icon_on;
delete icon_off;
+ if (backupFiles!=nullptr) delete backupFiles;
}
void Daily::showEvent(QShowEvent *)
@@ -2849,3 +2851,13 @@ void Daily::on_splitter_2_splitterMoved(int, int)
// qDebug() << "Left Panel width set to " << size;
AppSetting->setDailyPanelWidth(size);
}
+
+void Daily::on_backup_clicked() {
+ if (!backupFiles) {
+ backupFiles= new BackupFiles("daily",this);
+ }
+ if (backupFiles) {
+ backupFiles->backupMenu(GraphView);
+ }
+}
+
diff --git a/oscar/daily.h b/oscar/daily.h
index 71198971..9d8edaf6 100644
--- a/oscar/daily.h
+++ b/oscar/daily.h
@@ -28,6 +28,7 @@
#include "Graphs/gLineChart.h"
#include "sessionbar.h"
#include "mytextbrowser.h"
+#include "backupFiles.h"
namespace Ui {
@@ -272,6 +273,8 @@ private slots:
void on_splitter_2_splitterMoved(int pos, int index);
+ void on_backup_clicked();
+
protected:
virtual void showEvent(QShowEvent *);
@@ -360,6 +363,7 @@ private:
#endif
bool BookmarksChanged;
+ BackupFiles* backupFiles=nullptr;
};
#endif // DAILY_H
diff --git a/oscar/daily.ui b/oscar/daily.ui
index 6199b948..294abed7 100644
--- a/oscar/daily.ui
+++ b/oscar/daily.ui
@@ -1557,6 +1557,13 @@ QToolButton:pressed {
+ -
+
+
+ Backup
+
+
+
-
diff --git a/oscar/icons/brick-wall.png b/oscar/icons/brick-wall.png
new file mode 100644
index 00000000..9d2c3536
Binary files /dev/null and b/oscar/icons/brick-wall.png differ
diff --git a/oscar/icons/exit.png b/oscar/icons/exit.png
new file mode 100644
index 00000000..47491db7
Binary files /dev/null and b/oscar/icons/exit.png differ
diff --git a/oscar/icons/plus.png b/oscar/icons/plus.png
new file mode 100644
index 00000000..ab8e6287
Binary files /dev/null and b/oscar/icons/plus.png differ
diff --git a/oscar/icons/rename.png b/oscar/icons/rename.png
new file mode 100644
index 00000000..9acf567f
Binary files /dev/null and b/oscar/icons/rename.png differ
diff --git a/oscar/icons/restore.png b/oscar/icons/restore.png
new file mode 100644
index 00000000..65f2e76c
Binary files /dev/null and b/oscar/icons/restore.png differ
diff --git a/oscar/icons/trash_can.png b/oscar/icons/trash_can.png
new file mode 100644
index 00000000..d0c180e3
Binary files /dev/null and b/oscar/icons/trash_can.png differ
diff --git a/oscar/icons/update.png b/oscar/icons/update.png
new file mode 100644
index 00000000..b16a4aa7
Binary files /dev/null and b/oscar/icons/update.png differ
diff --git a/oscar/oscar.pro b/oscar/oscar.pro
index 2f908712..aef6e320 100644
--- a/oscar/oscar.pro
+++ b/oscar/oscar.pro
@@ -255,6 +255,8 @@ lessThan(QT_MAJOR_VERSION,5)|lessThan(QT_MINOR_VERSION,12) {
SOURCES += \
checkupdates.cpp \
+ overview.cpp \
+ backupFiles.cpp \
common_gui.cpp \
cprogressbar.cpp \
daily.cpp \
@@ -262,7 +264,6 @@ SOURCES += \
main.cpp \
mainwindow.cpp \
newprofile.cpp \
- overview.cpp \
preferencesdialog.cpp \
# psettings.cpp \
reports.cpp \
@@ -361,13 +362,14 @@ QMAKE_EXTRA_COMPILERS += optimize
HEADERS += \
checkupdates.h \
+ overview.h \
+ backupFiles.h \
common_gui.h \
cprogressbar.h \
daily.h \
exportcsv.h \
mainwindow.h \
newprofile.h \
- overview.h \
preferencesdialog.h \
# psettings.h \
reports.h \
diff --git a/oscar/overview.cpp b/oscar/overview.cpp
index a2e6907a..5edc37c8 100644
--- a/oscar/overview.cpp
+++ b/oscar/overview.cpp
@@ -171,6 +171,7 @@ Overview::Overview(QWidget *parent, gGraphView *shared) :
connect(GraphView, SIGNAL(updateRange(double,double)), this, SLOT(on_RangeUpdate(double,double)));
connect(GraphView, SIGNAL(GraphsChanged()), this, SLOT(updateGraphCombo()));
connect(GraphView, SIGNAL(XBoundsChanged(qint64 ,qint64)), this, SLOT(on_XBoundsChanged(qint64 ,qint64)));
+ backupFiles=nullptr;
}
Overview::~Overview()
@@ -192,6 +193,7 @@ Overview::~Overview()
delete icon_off ;
delete icon_up_down ;
delete icon_warning ;
+ if (backupFiles!=nullptr) delete backupFiles;
}
void Overview::ResetFont()
@@ -933,3 +935,12 @@ void Overview::on_toggleVisibility_clicked(bool checked)
GraphView->redraw();
}
+void Overview::on_backup_clicked() {
+ if (!backupFiles) {
+ backupFiles= new BackupFiles("overview",this);
+ }
+ if (backupFiles) {
+ backupFiles->backupMenu(GraphView);
+ }
+}
+
diff --git a/oscar/overview.h b/oscar/overview.h
index a5497b4a..2260b41a 100644
--- a/oscar/overview.h
+++ b/oscar/overview.h
@@ -23,6 +23,11 @@
#include "Graphs/gOverviewGraph.h"
#endif
#include "Graphs/gSummaryChart.h"
+#include "backupFiles.h"
+
+#include
+#include
+#include
namespace Ui {
class Overview;
@@ -140,6 +145,8 @@ class Overview : public QWidget
void on_RangeUpdate(double minx, double maxx);
void setGraphText ();
+ void on_backup_clicked();
+
private:
void CreateAllGraphs();
void timedUpdateOverview(int ms=0);
@@ -193,6 +200,7 @@ class Overview : public QWidget
// Are start and end widgets displaying the same month.
bool samePage;
+ BackupFiles* backupFiles=nullptr;
};
diff --git a/oscar/overview.ui b/oscar/overview.ui
index 267cd9b8..90ab0d87 100644
--- a/oscar/overview.ui
+++ b/oscar/overview.ui
@@ -259,6 +259,13 @@ QToolButton:pressed {
+ -
+
+
+ Backup
+
+
+
-