From ee73ee365f5d02a4fc29832745f70a381b085aa1 Mon Sep 17 00:00:00 2001 From: user Date: Tue, 10 Mar 2020 21:49:04 +0800 Subject: [PATCH] some work on qt --- .gitignore | 4 + qt/i2pd_qt/DelayedSaveManager.cpp | 3 + qt/i2pd_qt/DelayedSaveManager.h | 24 +++++ qt/i2pd_qt/DelayedSaveManagerImpl.cpp | 140 ++++++++++++++++++++++++++ qt/i2pd_qt/DelayedSaveManagerImpl.h | 82 +++++++++++++++ qt/i2pd_qt/Saver.cpp | 6 ++ qt/i2pd_qt/Saver.h | 22 ++++ qt/i2pd_qt/SaverImpl.cpp | 79 +++++++++++++++ qt/i2pd_qt/SaverImpl.h | 33 ++++++ qt/i2pd_qt/TunnelPane.cpp | 2 +- qt/i2pd_qt/i2pd_qt.pro | 14 ++- qt/i2pd_qt/mainwindow.cpp | 103 ++++++++----------- qt/i2pd_qt/mainwindow.h | 29 ++++-- 13 files changed, 466 insertions(+), 75 deletions(-) create mode 100644 qt/i2pd_qt/DelayedSaveManager.cpp create mode 100644 qt/i2pd_qt/DelayedSaveManager.h create mode 100644 qt/i2pd_qt/DelayedSaveManagerImpl.cpp create mode 100644 qt/i2pd_qt/DelayedSaveManagerImpl.h create mode 100644 qt/i2pd_qt/Saver.cpp create mode 100644 qt/i2pd_qt/Saver.h create mode 100644 qt/i2pd_qt/SaverImpl.cpp create mode 100644 qt/i2pd_qt/SaverImpl.h diff --git a/.gitignore b/.gitignore index c2db70e0..68aea504 100644 --- a/.gitignore +++ b/.gitignore @@ -264,3 +264,7 @@ qt/i2pd_qt/*.ui_* #unknown android stuff android/libs/ + +#various logs +*LOGS/ + diff --git a/qt/i2pd_qt/DelayedSaveManager.cpp b/qt/i2pd_qt/DelayedSaveManager.cpp new file mode 100644 index 00000000..8e17d111 --- /dev/null +++ b/qt/i2pd_qt/DelayedSaveManager.cpp @@ -0,0 +1,3 @@ +#include "DelayedSaveManager.h" + +DelayedSaveManager::DelayedSaveManager(){} diff --git a/qt/i2pd_qt/DelayedSaveManager.h b/qt/i2pd_qt/DelayedSaveManager.h new file mode 100644 index 00000000..9a9a997b --- /dev/null +++ b/qt/i2pd_qt/DelayedSaveManager.h @@ -0,0 +1,24 @@ +#ifndef DELAYEDSAVEMANAGER_H +#define DELAYEDSAVEMANAGER_H + +#include "Saver.h" + +class DelayedSaveManager +{ +public: + DelayedSaveManager(); + + virtual void setSaver(Saver* saver)=0; + + typedef unsigned int DATA_SERIAL_TYPE; + + virtual void delayedSave(DATA_SERIAL_TYPE dataSerial, bool needsTunnelFocus, std::string tunnelNameToFocus)=0; + + //returns false iff save failed + virtual bool appExiting()=0; + + virtual bool needsFocusOnTunnel()=0; + virtual std::string getTunnelNameToFocus()=0; +}; + +#endif // DELAYEDSAVEMANAGER_H diff --git a/qt/i2pd_qt/DelayedSaveManagerImpl.cpp b/qt/i2pd_qt/DelayedSaveManagerImpl.cpp new file mode 100644 index 00000000..5588d7e9 --- /dev/null +++ b/qt/i2pd_qt/DelayedSaveManagerImpl.cpp @@ -0,0 +1,140 @@ +#include "DelayedSaveManagerImpl.h" + +DelayedSaveManagerImpl::DelayedSaveManagerImpl() : + saver(nullptr), + lastDataSerialSeen(DelayedSaveManagerImpl::INITIAL_DATA_SERIAL), + lastSaveStartedTimestamp(A_VERY_OBSOLETE_TIMESTAMP), + exiting(false), + thread(new DelayedSaveThread(this)) +{ +} + +void DelayedSaveManagerImpl::setSaver(Saver* saver) { + this->saver = saver; +} + +void DelayedSaveManagerImpl::start() { + thread->start(); +} + +bool DelayedSaveManagerImpl::isSaverValid() { + return saver != nullptr; +} + +void DelayedSaveManagerImpl::delayedSave(DATA_SERIAL_TYPE dataSerial, bool focusOnTunnel, std::string tunnelNameToFocus) { + if(lastDataSerialSeen==dataSerial)return; + this->focusOnTunnel = focusOnTunnel; + this->tunnelNameToFocus = tunnelNameToFocus; + lastDataSerialSeen=dataSerial; + assert(isSaverValid()); + TIMESTAMP_TYPE now = getTime(); + TIMESTAMP_TYPE wakeTime = lastSaveStartedTimestamp + DelayedSaveThread::WAIT_TIME_MILLIS; + if(now < wakeTime) { + //defer save until lastSaveStartedTimestamp + DelayedSaveThread::WAIT_TIME_MILLIS + thread->deferSaveUntil(wakeTime); + return; + } + lastSaveStartedTimestamp = now; + thread->startSavingNow(); +} + +bool DelayedSaveManagerImpl::appExiting() { + exiting=true; + thread->wakeThreadAndJoinThread(); + assert(isSaverValid()); + saver->save(false, ""); + return true; +} + +DelayedSaveThread::DelayedSaveThread(DelayedSaveManagerImpl* delayedSaveManagerImpl_): + delayedSaveManagerImpl(delayedSaveManagerImpl_), + mutex(new QMutex()), + waitCondition(new QWaitCondition()), + saveNow(false), + defer(false) +{ + mutex->lock(); +} + +DelayedSaveThread::~DelayedSaveThread(){ + mutex->unlock(); + delete mutex; + delete waitCondition; +} + +void DelayedSaveThread::run() { + forever { + if(delayedSaveManagerImpl->isExiting())return; + waitCondition->wait(mutex, WAIT_TIME_MILLIS); + if(delayedSaveManagerImpl->isExiting())return; + Saver* saver = delayedSaveManagerImpl->getSaver(); + assert(saver!=nullptr); + if(saveNow) { + saveNow = false; + const bool focusOnTunnel = delayedSaveManagerImpl->needsFocusOnTunnel(); + const std::string tunnelNameToFocus = delayedSaveManagerImpl->getTunnelNameToFocus(); + saver->save(focusOnTunnel, tunnelNameToFocus); + continue; + } + if(defer) { + defer=false; +#define max(a,b) (((a)>(b))?(a):(b)) + forever { + TIMESTAMP_TYPE now = DelayedSaveManagerImpl::getTime(); + TIMESTAMP_TYPE millisToWait = max(wakeTime-now, 0); + if(millisToWait>0) { + waitCondition->wait(mutex, millisToWait); + if(delayedSaveManagerImpl->isExiting())return; + continue; + } + const bool focusOnTunnel = delayedSaveManagerImpl->needsFocusOnTunnel(); + const std::string tunnelNameToFocus = delayedSaveManagerImpl->getTunnelNameToFocus(); + saver->save(focusOnTunnel, tunnelNameToFocus); + break; //break inner loop + } + } + } +} + +void DelayedSaveThread::wakeThreadAndJoinThread() { + waitCondition->wakeAll(); + quit(); + wait();//join //"similar to the POSIX pthread_join()" +} + +DelayedSaveManagerImpl::TIMESTAMP_TYPE DelayedSaveManagerImpl::getTime() { + return QDateTime::currentMSecsSinceEpoch(); +} + +void DelayedSaveThread::deferSaveUntil(TIMESTAMP_TYPE wakeTime_) { + wakeTime = wakeTime_; + defer = true; + waitCondition->wakeAll(); +} + +void DelayedSaveThread::startSavingNow() { + //mutex->lock(); + saveNow=true; + waitCondition->wakeAll(); + //mutex->unlock(); +} + +DelayedSaveManagerImpl::~DelayedSaveManagerImpl() { + thread->wakeThreadAndJoinThread(); + delete thread; +} + +bool DelayedSaveManagerImpl::isExiting() { + return exiting; +} +Saver* DelayedSaveManagerImpl::getSaver() { + return saver; +} + +bool DelayedSaveManagerImpl::needsFocusOnTunnel() { + return focusOnTunnel; +} + +std::string DelayedSaveManagerImpl::getTunnelNameToFocus() { + return tunnelNameToFocus; +} diff --git a/qt/i2pd_qt/DelayedSaveManagerImpl.h b/qt/i2pd_qt/DelayedSaveManagerImpl.h new file mode 100644 index 00000000..0d8c7592 --- /dev/null +++ b/qt/i2pd_qt/DelayedSaveManagerImpl.h @@ -0,0 +1,82 @@ +#ifndef DELAYEDSAVEMANAGERIMPL_H +#define DELAYEDSAVEMANAGERIMPL_H + +#include +#include +#include +#include +#include + +#include "mainwindow.h" +#include "DelayedSaveManager.h" +#include "Saver.h" + +class DelayedSaveManagerImpl; + +class DelayedSaveThread : public QThread +{ + Q_OBJECT + +public: + static constexpr unsigned long WAIT_TIME_MILLIS = 1000L; + + typedef qint64 TIMESTAMP_TYPE; + static constexpr TIMESTAMP_TYPE A_VERY_OBSOLETE_TIMESTAMP=0; + + DelayedSaveThread(DelayedSaveManagerImpl* delayedSaveManagerImpl); + virtual ~DelayedSaveThread(); + + void run() override; + + void deferSaveUntil(TIMESTAMP_TYPE wakeTime); + void startSavingNow(); + + void wakeThreadAndJoinThread(); + +private: + DelayedSaveManagerImpl* delayedSaveManagerImpl; + QMutex* mutex; + QWaitCondition* waitCondition; + volatile bool saveNow; + volatile bool defer; + volatile TIMESTAMP_TYPE wakeTime; +}; + +class DelayedSaveManagerImpl : public DelayedSaveManager +{ +public: + DelayedSaveManagerImpl(); + virtual ~DelayedSaveManagerImpl(); + virtual void setSaver(Saver* saver); + virtual void start(); + virtual void delayedSave(DATA_SERIAL_TYPE dataSerial, bool focusOnTunnel, std::string tunnelNameToFocus); + virtual bool appExiting(); + + typedef DelayedSaveThread::TIMESTAMP_TYPE TIMESTAMP_TYPE; + + static constexpr DATA_SERIAL_TYPE INITIAL_DATA_SERIAL=0; + bool isExiting(); + Saver* getSaver(); + static TIMESTAMP_TYPE getTime(); + + bool needsFocusOnTunnel(); + std::string getTunnelNameToFocus(); + +private: + Saver* saver; + bool isSaverValid(); + + volatile DATA_SERIAL_TYPE lastDataSerialSeen; + + static constexpr TIMESTAMP_TYPE A_VERY_OBSOLETE_TIMESTAMP=DelayedSaveThread::A_VERY_OBSOLETE_TIMESTAMP; + TIMESTAMP_TYPE lastSaveStartedTimestamp; + + volatile bool exiting; + DelayedSaveThread* thread; + void wakeThreadAndJoinThread(); + + volatile bool focusOnTunnel; + std::string tunnelNameToFocus; +}; + +#endif // DELAYEDSAVEMANAGERIMPL_H diff --git a/qt/i2pd_qt/Saver.cpp b/qt/i2pd_qt/Saver.cpp new file mode 100644 index 00000000..4841acb0 --- /dev/null +++ b/qt/i2pd_qt/Saver.cpp @@ -0,0 +1,6 @@ +#include "Saver.h" + +Saver::Saver() +{ + +} diff --git a/qt/i2pd_qt/Saver.h b/qt/i2pd_qt/Saver.h new file mode 100644 index 00000000..cefe0220 --- /dev/null +++ b/qt/i2pd_qt/Saver.h @@ -0,0 +1,22 @@ +#ifndef SAVER_H +#define SAVER_H + +#include +#include +#include + +class Saver : public QObject +{ + Q_OBJECT + +public: + Saver(); + //false iff failures + virtual bool save(const bool focusOnTunnel, const std::string& tunnelNameToFocus)=0; + +signals: + void reloadTunnelsConfigAndUISignal(const QString); + +}; + +#endif // SAVER_H diff --git a/qt/i2pd_qt/SaverImpl.cpp b/qt/i2pd_qt/SaverImpl.cpp new file mode 100644 index 00000000..f35ef5b7 --- /dev/null +++ b/qt/i2pd_qt/SaverImpl.cpp @@ -0,0 +1,79 @@ +#include "SaverImpl.h" + +#include +#include +#include + +#include "QList" +#include "QString" + +#include "mainwindow.h" + +SaverImpl::SaverImpl(MainWindow *mainWindowPtr_, QList * configItems_, std::map* tunnelConfigs_) : + configItems(configItems_), tunnelConfigs(tunnelConfigs_), confpath(), tunconfpath(), mainWindowPtr(mainWindowPtr_) +{} + +SaverImpl::~SaverImpl() {} + +bool SaverImpl::save(const bool focusOnTunnel, const std::string& tunnelNameToFocus) { + //save main config + { + std::stringstream out; + for(QList::iterator it = configItems->begin(); it!= configItems->end(); ++it) { + MainWindowItem* item = *it; + item->saveToStringStream(out); + } + + using namespace std; + + + QString backup=confpath+"~"; + if(QFile::exists(backup)) QFile::remove(backup);//TODO handle errors + if(QFile::exists(confpath)) QFile::rename(confpath, backup);//TODO handle errors + ofstream outfile; + outfile.open(confpath.toStdString());//TODO handle errors + outfile << out.str().c_str(); + outfile.close(); + } + + //save tunnels config + { + std::stringstream out; + + for (std::map::iterator it=tunnelConfigs->begin(); it!=tunnelConfigs->end(); ++it) { + //const std::string& name = it->first; + TunnelConfig* tunconf = it->second; + tunconf->saveHeaderToStringStream(out); + tunconf->saveToStringStream(out); + tunconf->saveI2CPParametersToStringStream(out); + } + + using namespace std; + + QString backup=tunconfpath+"~"; + if(QFile::exists(backup)) QFile::remove(backup);//TODO handle errors + if(QFile::exists(tunconfpath)) QFile::rename(tunconfpath, backup);//TODO handle errors + ofstream outfile; + outfile.open(tunconfpath.toStdString());//TODO handle errors + outfile << out.str().c_str(); + outfile.close(); + } + + //reload saved configs +#if 0 + i2p::client::context.ReloadConfig(); +#endif + + if(focusOnTunnel) emit reloadTunnelsConfigAndUISignal(QString::fromStdString(tunnelNameToFocus)); + + return true; +} + +void SaverImpl::setConfPath(QString& confpath_) { confpath = confpath_; } + +void SaverImpl::setTunnelsConfPath(QString& tunconfpath_) { tunconfpath = tunconfpath_; } + +/*void SaverImpl::setTunnelFocus(bool focusOnTunnel, std::string tunnelNameToFocus) { + this->focusOnTunnel=focusOnTunnel; + this->tunnelNameToFocus=tunnelNameToFocus; +}*/ diff --git a/qt/i2pd_qt/SaverImpl.h b/qt/i2pd_qt/SaverImpl.h new file mode 100644 index 00000000..c44877a2 --- /dev/null +++ b/qt/i2pd_qt/SaverImpl.h @@ -0,0 +1,33 @@ +#ifndef SAVERIMPL_H +#define SAVERIMPL_H + +#include +#include + +#include +#include "QList" + +#include "mainwindow.h" +#include "TunnelConfig.h" +#include "Saver.h" + +class MainWindowItem; +class TunnelConfig; + +class SaverImpl : public Saver +{ +public: + SaverImpl(MainWindow *mainWindowPtr_, QList * configItems_, std::map* tunnelConfigs_); + virtual ~SaverImpl(); + virtual bool save(const bool focusOnTunnel, const std::string& tunnelNameToFocus); + void setConfPath(QString& confpath_); + void setTunnelsConfPath(QString& tunconfpath_); +private: + QList * configItems; + std::map* tunnelConfigs; + QString confpath; + QString tunconfpath; + MainWindow* mainWindowPtr; +}; + +#endif // SAVERIMPL_H diff --git a/qt/i2pd_qt/TunnelPane.cpp b/qt/i2pd_qt/TunnelPane.cpp index fb840276..3813eafc 100644 --- a/qt/i2pd_qt/TunnelPane.cpp +++ b/qt/i2pd_qt/TunnelPane.cpp @@ -64,7 +64,7 @@ void TunnelPane::setupTunnelPane( //type { - const QString& type = tunnelConfig->getType(); + //const QString& type = tunnelConfig->getType(); QHBoxLayout * horizontalLayout_ = new QHBoxLayout(); horizontalLayout_->setObjectName(QStringLiteral("horizontalLayout_")); typeLabel = new QLabel(gridLayoutWidget_2); diff --git a/qt/i2pd_qt/i2pd_qt.pro b/qt/i2pd_qt/i2pd_qt.pro index 15565c5c..0cb73a2f 100644 --- a/qt/i2pd_qt/i2pd_qt.pro +++ b/qt/i2pd_qt/i2pd_qt.pro @@ -62,6 +62,7 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \ ../../libi2pd/TunnelGateway.cpp \ ../../libi2pd/TunnelPool.cpp \ ../../libi2pd/util.cpp \ + ../../libi2pd/Elligator.cpp \ ../../libi2pd_client/AddressBook.cpp \ ../../libi2pd_client/BOB.cpp \ ../../libi2pd_client/ClientContext.cpp \ @@ -89,7 +90,11 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \ pagewithbackbutton.cpp \ widgetlock.cpp \ widgetlockregistry.cpp \ - logviewermanager.cpp + logviewermanager.cpp \ + DelayedSaveManager.cpp \ + Saver.cpp \ + DelayedSaveManagerImpl.cpp \ + SaverImpl.cpp HEADERS += DaemonQT.h mainwindow.h \ ../../libi2pd/api.h \ @@ -147,6 +152,7 @@ HEADERS += DaemonQT.h mainwindow.h \ ../../libi2pd/TunnelPool.h \ ../../libi2pd/util.h \ ../../libi2pd/version.h \ + ../../libi2pd/Elligator.h \ ../../libi2pd_client/AddressBook.h \ ../../libi2pd_client/BOB.h \ ../../libi2pd_client/ClientContext.h \ @@ -175,7 +181,11 @@ HEADERS += DaemonQT.h mainwindow.h \ widgetlock.h \ widgetlockregistry.h \ i2pd.rc \ - logviewermanager.h + logviewermanager.h \ + DelayedSaveManager.h \ + Saver.h \ + DelayedSaveManagerImpl.h \ + SaverImpl.h INCLUDEPATH += ../../libi2pd INCLUDEPATH += ../../libi2pd_client diff --git a/qt/i2pd_qt/mainwindow.cpp b/qt/i2pd_qt/mainwindow.cpp index e4c9f2a7..3b1890c4 100644 --- a/qt/i2pd_qt/mainwindow.cpp +++ b/qt/i2pd_qt/mainwindow.cpp @@ -1,11 +1,8 @@ -#include -#include #include "mainwindow.h" #include "ui_mainwindow.h" #include "ui_statusbuttons.h" #include "ui_routercommandswidget.h" #include "ui_generalsettingswidget.h" -#include #include #include #include @@ -29,17 +26,22 @@ #include "logviewermanager.h" +#include "DelayedSaveManagerImpl.h" +#include "SaverImpl.h" + std::string programOptionsWriterCurrentSection; MainWindow::MainWindow(std::shared_ptr logStream_, QWidget *parent) : QMainWindow(parent) ,logStream(logStream_) -#ifndef ANDROID - ,quitting(false) -#endif + ,delayedSaveManagerPtr(new DelayedSaveManagerImpl()) + ,dataSerial(DelayedSaveManagerImpl::INITIAL_DATA_SERIAL) ,wasSelectingAtStatusMainPage(false) ,showHiddenInfoStatusMainPage(false) ,logViewerManagerPtr(nullptr) +#ifndef ANDROID + ,quitting(false) +#endif ,ui(new Ui::MainWindow) ,statusButtonsUI(new Ui::StatusButtonsForm) ,routerCommandsUI(new Ui::routerCommandsWidget) @@ -51,9 +53,14 @@ MainWindow::MainWindow(std::shared_ptr logStream_, QWidget *paren ,datadir() ,confpath() ,tunconfpath() + ,tunnelConfigs() ,tunnelsPageUpdateListener(this) + ,saverPtr(new SaverImpl(this, &configItems, &tunnelConfigs)) { + assert(delayedSaveManagerPtr!=nullptr); + assert(saverPtr!=nullptr); + ui->setupUi(this); statusButtonsUI->setupUi(ui->statusButtonsPane); routerCommandsUI->setupUi(routerCommandsParent); @@ -75,7 +82,7 @@ MainWindow::MainWindow(std::shared_ptr logStream_, QWidget *paren ui->stackedWidget->setCurrentIndex(0); ui->settingsScrollArea->resize(uiSettings->settingsContentsGridLayout->sizeHint().width()+10,380); - QScrollBar* const barSett = ui->settingsScrollArea->verticalScrollBar(); + //QScrollBar* const barSett = ui->settingsScrollArea->verticalScrollBar(); int w = 683; int h = 3060; ui->settingsContents->setFixedSize(w, h); @@ -270,7 +277,13 @@ MainWindow::MainWindow(std::shared_ptr logStream_, QWidget *paren widgetlocks.add(new widgetlock(uiSettings->comboBox_httpPorxySignatureType,uiSettings->httpProxySignTypeComboEditPushButton)); widgetlocks.add(new widgetlock(uiSettings->comboBox_socksProxySignatureType,uiSettings->socksProxySignTypeComboEditPushButton)); - loadAllConfigs(); + loadAllConfigs(saverPtr); + + QObject::connect(saverPtr, SIGNAL(reloadTunnelsConfigAndUISignal(const QString)), + this, SLOT(reloadTunnelsConfigAndUI_QString(const QString))); + + delayedSaveManagerPtr->setSaver(saverPtr); + delayedSaveManagerPtr->start(); QObject::connect(uiSettings->logDestinationComboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(logDestinationComboBoxValueChanged(const QString &))); @@ -292,7 +305,6 @@ MainWindow::MainWindow(std::shared_ptr logStream_, QWidget *paren QObject::connect(uiSettings->tunnelsConfigFileLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(reloadTunnelsConfigAndUI())); - QObject::connect(ui->addServerTunnelPushButton, SIGNAL(released()), this, SLOT(addServerTunnelPushButtonReleased())); QObject::connect(ui->addClientTunnelPushButton, SIGNAL(released()), this, SLOT(addClientTunnelPushButtonReleased())); @@ -307,7 +319,7 @@ MainWindow::MainWindow(std::shared_ptr logStream_, QWidget *paren logViewerManagerPtr=new LogViewerManager(logStream_,ui->logViewerTextEdit,this); assert(logViewerManagerPtr!=nullptr); - onLoggingOptionsChange(); + //onLoggingOptionsChange(); //QMetaObject::connectSlotsByName(this); } @@ -500,6 +512,8 @@ void MainWindow::handleQuitButton() { quitting=true; #endif close(); + delayedSaveManagerPtr->appExiting(); + qDebug("Performing quit"); QApplication::instance()->quit(); } @@ -526,6 +540,7 @@ void MainWindow::handleGracefulQuitTimerEvent() { quitting=true; #endif close(); + delayedSaveManagerPtr->appExiting(); qDebug("Performing quit"); QApplication::instance()->quit(); } @@ -534,6 +549,8 @@ MainWindow::~MainWindow() { qDebug("Destroying main window"); delete statusPageUpdateTimer; + delete delayedSaveManagerPtr; + delete saverPtr; for(QList::iterator it = configItems.begin(); it!= configItems.end(); ++it) { MainWindowItem* item = *it; item->deleteLater(); @@ -594,7 +611,7 @@ NonGUIOptionItem* MainWindow::initNonGUIOption(ConfigOption option) { return retValue; } -void MainWindow::loadAllConfigs(){ +void MainWindow::loadAllConfigs(SaverImpl* saverPtr){ //BORROWED FROM ??? //TODO move this code into single location std::string config; i2p::config::GetOption("conf", config); @@ -635,6 +652,9 @@ void MainWindow::loadAllConfigs(){ this->datadir = datadir.c_str(); this->tunconfpath = tunConf.c_str(); + saverPtr->setConfPath(this->confpath); + saverPtr->setTunnelsConfPath(this->tunconfpath); + for(QList::iterator it = configItems.begin(); it!= configItems.end(); ++it) { MainWindowItem* item = *it; item->loadFromConfigOption(); @@ -642,10 +662,10 @@ void MainWindow::loadAllConfigs(){ ReadTunnelsConfig(); - onLoggingOptionsChange(); + //onLoggingOptionsChange(); } /** returns false iff not valid items present and save was aborted */ -bool MainWindow::saveAllConfigs(){ +bool MainWindow::saveAllConfigs(bool focusOnTunnel, std::string tunnelNameToFocus){ QString cannotSaveSettings = QApplication::tr("Cannot save settings."); programOptionsWriterCurrentSection=""; /*if(!logFileNameOption->lineEdit->text().trimmed().isEmpty())logOption->optionValue=boost::any(std::string("file")); @@ -653,7 +673,6 @@ bool MainWindow::saveAllConfigs(){ daemonOption->optionValue=boost::any(false); serviceOption->optionValue=boost::any(false); - std::stringstream out; for(QList::iterator it = configItems.begin(); it!= configItems.end(); ++it) { MainWindowItem* item = *it; if(!item->isValid()){ @@ -661,27 +680,8 @@ bool MainWindow::saveAllConfigs(){ return false; } } - - for(QList::iterator it = configItems.begin(); it!= configItems.end(); ++it) { - MainWindowItem* item = *it; - item->saveToStringStream(out); - } - - using namespace std; - - - QString backup=confpath+"~"; - if(QFile::exists(backup)) QFile::remove(backup);//TODO handle errors - if(QFile::exists(confpath)) QFile::rename(confpath, backup);//TODO handle errors - ofstream outfile; - outfile.open(confpath.toStdString());//TODO handle errors - outfile << out.str().c_str(); - outfile.close(); - - SaveTunnelsConfig(); - - onLoggingOptionsChange(); - + delayedSaveManagerPtr->delayedSave(++dataSerial, focusOnTunnel, tunnelNameToFocus); + //onLoggingOptionsChange(); return true; } @@ -711,7 +711,7 @@ void MainWindow::updated() { adjustSizesAccordingToWrongLabel(); applyTunnelsUiToConfigs(); - saveAllConfigs(); + saveAllConfigs(false); } void MainWindowItem::installListeners(MainWindow *mainWindow) {} @@ -784,6 +784,10 @@ bool MainWindow::applyTunnelsUiToConfigs() { return true; } +void MainWindow::reloadTunnelsConfigAndUI_QString(const QString tunnelNameToFocus) { + reloadTunnelsConfigAndUI(tunnelNameToFocus.toStdString()); +} + void MainWindow::reloadTunnelsConfigAndUI(std::string tunnelNameToFocus) { deleteTunnelForms(); for (std::map::iterator it=tunnelConfigs.begin(); it!=tunnelConfigs.end(); ++it) { @@ -795,31 +799,6 @@ void MainWindow::reloadTunnelsConfigAndUI(std::string tunnelNameToFocus) { appendTunnelForms(tunnelNameToFocus); } -void MainWindow::SaveTunnelsConfig() { - std::stringstream out; - - for (std::map::iterator it=tunnelConfigs.begin(); it!=tunnelConfigs.end(); ++it) { - const std::string& name = it->first; - TunnelConfig* tunconf = it->second; - tunconf->saveHeaderToStringStream(out); - tunconf->saveToStringStream(out); - tunconf->saveI2CPParametersToStringStream(out); - } - - using namespace std; - - QString backup=tunconfpath+"~"; - if(QFile::exists(backup)) QFile::remove(backup);//TODO handle errors - if(QFile::exists(tunconfpath)) QFile::rename(tunconfpath, backup);//TODO handle errors - ofstream outfile; - outfile.open(tunconfpath.toStdString());//TODO handle errors - outfile << out.str().c_str(); - outfile.close(); - - i2p::client::context.ReloadConfig(); - -} - void MainWindow::TunnelsPageUpdateListenerMainWindowImpl::updated(std::string oldName, TunnelConfig* tunConf) { if(oldName!=tunConf->getName()) { //name has changed @@ -827,7 +806,7 @@ void MainWindow::TunnelsPageUpdateListenerMainWindowImpl::updated(std::string ol if(it!=mainWindow->tunnelConfigs.end())mainWindow->tunnelConfigs.erase(it); mainWindow->tunnelConfigs[tunConf->getName()]=tunConf; } - mainWindow->saveAllConfigs(); + mainWindow->saveAllConfigs(true, tunConf->getName()); } void MainWindow::TunnelsPageUpdateListenerMainWindowImpl::needsDeleting(std::string oldName){ diff --git a/qt/i2pd_qt/mainwindow.h b/qt/i2pd_qt/mainwindow.h index 048f44af..bfbc527f 100644 --- a/qt/i2pd_qt/mainwindow.h +++ b/qt/i2pd_qt/mainwindow.h @@ -62,6 +62,12 @@ #include "widgetlockregistry.h" #include "widgetlock.h" +#include "DelayedSaveManager.h" +#include "DelayedSaveManagerImpl.h" +#include "SaverImpl.h" + +class SaverImpl; + class LogViewerManager; template @@ -373,10 +379,14 @@ using namespace i2p::qt; class Controller; +class DelayedSaveManagerImpl; + class MainWindow : public QMainWindow { Q_OBJECT private: std::shared_ptr logStream; + DelayedSaveManagerImpl* delayedSaveManagerPtr; + DelayedSaveManager::DATA_SERIAL_TYPE dataSerial; public: explicit MainWindow(std::shared_ptr logStream_, QWidget *parent=nullptr); ~MainWindow(); @@ -502,16 +512,16 @@ protected: void initStringBox(ConfigOption option, QLineEdit* lineEdit); NonGUIOptionItem* initNonGUIOption(ConfigOption option); - void loadAllConfigs(); + void loadAllConfigs(SaverImpl* saverPtr); public slots: /** returns false iff not valid items present and save was aborted */ - bool saveAllConfigs(); - void SaveTunnelsConfig(); + bool saveAllConfigs(bool focusOnTunnel, std::string tunnelNameToFocus=""); void reloadTunnelsConfigAndUI(std::string tunnelNameToFocus); //focus none void reloadTunnelsConfigAndUI() { reloadTunnelsConfigAndUI(""); } + void reloadTunnelsConfigAndUI_QString(const QString tunnelNameToFocus); void addServerTunnelPushButtonReleased(); void addClientTunnelPushButtonReleased(); @@ -578,8 +588,7 @@ private: tunnelConfigs.erase(it); delete tc; } - saveAllConfigs(); - reloadTunnelsConfigAndUI(""); + saveAllConfigs(false); } std::string GenerateNewTunnelName() { @@ -614,8 +623,7 @@ private: destinationPort, sigType); - saveAllConfigs(); - reloadTunnelsConfigAndUI(name); + saveAllConfigs(true, name); } void CreateDefaultServerTunnel() {//TODO dedup default values with ReadTunnelsConfig() and with ClientContext.cpp::ReadTunnels () @@ -651,8 +659,7 @@ private: isUniqueLocal); - saveAllConfigs(); - reloadTunnelsConfigAndUI(name); + saveAllConfigs(true, name); } void ReadTunnelsConfig() //TODO deduplicate the code with ClientContext.cpp::ReadTunnels () @@ -793,7 +800,9 @@ private: TunnelsPageUpdateListenerMainWindowImpl tunnelsPageUpdateListener; - void onLoggingOptionsChange() {} + //void onLoggingOptionsChange() {} + + SaverImpl* saverPtr; }; #endif // MAINWINDOW_H