Merge pull request #1491 from nonlinear-chaos-order-etc-etal/openssl

qt: delayed save in background. should be better ui experience
This commit is contained in:
orignal 2020-03-10 11:39:07 -04:00 committed by GitHub
commit 82bdcfbbcb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 518 additions and 78 deletions

8
.gitignore vendored
View File

@ -258,9 +258,15 @@ build/Makefile
# qt
qt/i2pd_qt/*.ui.autosave
qt/i2pd_qt/*.autosave
qt/i2pd_qt/*.ui.bk*
qt/i2pd_qt/*.ui_*
#unknown android stuff
android/libs/
#various logs
*LOGS/
qt/build-*.sh*

View File

@ -89,7 +89,7 @@ namespace http
void ShowTransports (std::stringstream& s);
void ShowSAMSessions (std::stringstream& s);
void ShowI2PTunnels (std::stringstream& s);
void ShowLocalDestination (std::stringstream& s, const std::string& b32);
void ShowLocalDestination (std::stringstream& s, const std::string& b32, uint32_t token);
} // http
} // i2p

View File

@ -0,0 +1,3 @@
#include "DelayedSaveManager.h"
DelayedSaveManager::DelayedSaveManager(){}

View File

@ -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

View File

@ -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;
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;
}

View File

@ -0,0 +1,82 @@
#ifndef DELAYEDSAVEMANAGERIMPL_H
#define DELAYEDSAVEMANAGERIMPL_H
#include <QObject>
#include <QThread>
#include <QWaitCondition>
#include <QMutex>
#include <QDateTime>
#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();
DATA_SERIAL_TYPE lastDataSerialSeen;
static constexpr TIMESTAMP_TYPE A_VERY_OBSOLETE_TIMESTAMP=DelayedSaveThread::A_VERY_OBSOLETE_TIMESTAMP;
TIMESTAMP_TYPE lastSaveStartedTimestamp;
bool exiting;
DelayedSaveThread* thread;
void wakeThreadAndJoinThread();
bool focusOnTunnel;
std::string tunnelNameToFocus;
};
#endif // DELAYEDSAVEMANAGERIMPL_H

6
qt/i2pd_qt/Saver.cpp Normal file
View File

@ -0,0 +1,6 @@
#include "Saver.h"
Saver::Saver()
{
}

22
qt/i2pd_qt/Saver.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef SAVER_H
#define SAVER_H
#include <string>
#include <QObject>
#include <QString>
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

79
qt/i2pd_qt/SaverImpl.cpp Normal file
View File

@ -0,0 +1,79 @@
#include "SaverImpl.h"
#include <fstream>
#include <assert.h>
#include <sstream>
#include "QList"
#include "QString"
#include "mainwindow.h"
SaverImpl::SaverImpl(MainWindow *mainWindowPtr_, QList<MainWindowItem*> * configItems_, std::map<std::string,TunnelConfig*>* 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<MainWindowItem*>::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<std::string,TunnelConfig*>::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;
}*/

33
qt/i2pd_qt/SaverImpl.h Normal file
View File

@ -0,0 +1,33 @@
#ifndef SAVERIMPL_H
#define SAVERIMPL_H
#include <map>
#include <string>
#include <QObject>
#include "QList"
#include "mainwindow.h"
#include "TunnelConfig.h"
#include "Saver.h"
class MainWindowItem;
class TunnelConfig;
class SaverImpl : public Saver
{
public:
SaverImpl(MainWindow *mainWindowPtr_, QList<MainWindowItem*> * configItems_, std::map<std::string,TunnelConfig*>* tunnelConfigs_);
virtual ~SaverImpl();
virtual bool save(const bool focusOnTunnel, const std::string& tunnelNameToFocus);
void setConfPath(QString& confpath_);
void setTunnelsConfPath(QString& tunconfpath_);
private:
QList<MainWindowItem*> * configItems;
std::map<std::string,TunnelConfig*>* tunnelConfigs;
QString confpath;
QString tunconfpath;
MainWindow* mainWindowPtr;
};
#endif // SAVERIMPL_H

View File

@ -40,6 +40,9 @@ public:
class ClientTunnelConfig;
class ServerTunnelConfig;
class TunnelPane;
class TunnelConfig {
/*
const char I2P_TUNNELS_SECTION_TYPE_CLIENT[] = "client";
@ -54,6 +57,7 @@ class TunnelConfig {
*/
QString type;
std::string name;
TunnelPane* tunnelPane;
public:
TunnelConfig(std::string name_, QString& type_, I2CPParameters& i2cpParameters_):
type(type_), name(name_), i2cpParameters(i2cpParameters_) {}
@ -68,7 +72,8 @@ public:
virtual void saveToStringStream(std::stringstream& out)=0;
virtual ClientTunnelConfig* asClientTunnelConfig()=0;
virtual ServerTunnelConfig* asServerTunnelConfig()=0;
void setTunnelPane(TunnelPane* tp){this->tunnelPane = tp;}
TunnelPane* getTunnelPane() {return tunnelPane;}
private:
I2CPParameters i2cpParameters;
};

View File

@ -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);
@ -83,6 +83,11 @@ void TunnelPane::setupTunnelPane(
retranslateTunnelForm(*this);
}
void TunnelPane::deleteWidget() {
//gridLayoutWidget_2->deleteLater();
tunnelGroupBox->deleteLater();
}
void TunnelPane::appendControlsForI2CPParameters(I2CPParameters& i2cpParameters, int& gridIndex) {
{
//number of hops of an inbound tunnel

View File

@ -41,6 +41,8 @@ public:
virtual ServerTunnelPane* asServerTunnelPane()=0;
virtual ClientTunnelPane* asClientTunnelPane()=0;
void deleteWidget();
protected:
MainWindow* mainWindow;
QWidget * wrongInputPane;

View File

@ -91,7 +91,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 \
@ -179,7 +183,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

View File

@ -1,11 +1,8 @@
#include <fstream>
#include <assert.h>
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "ui_statusbuttons.h"
#include "ui_routercommandswidget.h"
#include "ui_generalsettingswidget.h"
#include <sstream>
#include <QScrollBar>
#include <QMessageBox>
#include <QTimer>
@ -29,17 +26,22 @@
#include "logviewermanager.h"
#include "DelayedSaveManagerImpl.h"
#include "SaverImpl.h"
std::string programOptionsWriterCurrentSection;
MainWindow::MainWindow(std::shared_ptr<std::iostream> 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<std::iostream> 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<std::iostream> 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<std::iostream> 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<std::iostream> 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<std::iostream> 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<MainWindowItem*>::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<MainWindowItem*>::iterator it = configItems.begin(); it!= configItems.end(); ++it) {
MainWindowItem* item = *it;
item->loadFromConfigOption();
@ -642,10 +662,40 @@ void MainWindow::loadAllConfigs(){
ReadTunnelsConfig();
onLoggingOptionsChange();
//onLoggingOptionsChange();
}
void MainWindow::layoutTunnels() {
int height=0;
ui->tunnelsScrollAreaWidgetContents->setGeometry(0,0,0,0);
for(std::map<std::string, TunnelConfig*>::iterator it = tunnelConfigs.begin(); it != tunnelConfigs.end(); ++it) {
const std::string& name=it->first;
TunnelConfig* tunconf = it->second;
TunnelPane * tunnelPane=tunconf->getTunnelPane();
if(!tunnelPane)continue;
int h=tunnelPane->height();
height+=h;
//qDebug() << "tun.height:" << height << "sz:" << tunnelPanes.size();
//int h=tunnelPane->appendClientTunnelForm(ctc, ui->tunnelsScrollAreaWidgetContents, tunnelPanes.size(), height);
}
//qDebug() << "tun.setting height:" << height;
ui->tunnelsScrollAreaWidgetContents->setGeometry(QRect(0, 0, 621, height));
/*QList<QWidget*> childWidgets = ui->tunnelsScrollAreaWidgetContents->findChildren<QWidget*>();
foreach(QWidget* widget, childWidgets)
widget->show();*/
}
void MainWindow::deleteTunnelFromUI(std::string tunnelName, TunnelConfig* cnf) {
TunnelPane* tp = cnf->getTunnelPane();
if(!tp)return;
tunnelPanes.remove(tp);
tp->deleteWidget();
layoutTunnels();
}
/** 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 +703,6 @@ bool MainWindow::saveAllConfigs(){
daemonOption->optionValue=boost::any(false);
serviceOption->optionValue=boost::any(false);
std::stringstream out;
for(QList<MainWindowItem*>::iterator it = configItems.begin(); it!= configItems.end(); ++it) {
MainWindowItem* item = *it;
if(!item->isValid()){
@ -661,27 +710,9 @@ bool MainWindow::saveAllConfigs(){
return false;
}
}
delayedSaveManagerPtr->delayedSave(++dataSerial, focusOnTunnel, tunnelNameToFocus);
for(QList<MainWindowItem*>::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();
//onLoggingOptionsChange();
return true;
}
@ -711,7 +742,7 @@ void MainWindow::updated() {
adjustSizesAccordingToWrongLabel();
applyTunnelsUiToConfigs();
saveAllConfigs();
saveAllConfigs(false);
}
void MainWindowItem::installListeners(MainWindow *mainWindow) {}
@ -725,6 +756,7 @@ void MainWindow::appendTunnelForms(std::string tunnelNameToFocus) {
ServerTunnelConfig* stc = tunconf->asServerTunnelConfig();
if(stc){
ServerTunnelPane * tunnelPane=new ServerTunnelPane(&tunnelsPageUpdateListener, stc, ui->wrongInputLabel, ui->wrongInputLabel, this);
tunconf->setTunnelPane(tunnelPane);
int h=tunnelPane->appendServerTunnelForm(stc, ui->tunnelsScrollAreaWidgetContents, tunnelPanes.size(), height);
height+=h;
//qDebug() << "tun.height:" << height << "sz:" << tunnelPanes.size();
@ -738,6 +770,7 @@ void MainWindow::appendTunnelForms(std::string tunnelNameToFocus) {
ClientTunnelConfig* ctc = tunconf->asClientTunnelConfig();
if(ctc){
ClientTunnelPane * tunnelPane=new ClientTunnelPane(&tunnelsPageUpdateListener, ctc, ui->wrongInputLabel, ui->wrongInputLabel, this);
tunconf->setTunnelPane(tunnelPane);
int h=tunnelPane->appendClientTunnelForm(ctc, ui->tunnelsScrollAreaWidgetContents, tunnelPanes.size(), height);
height+=h;
//qDebug() << "tun.height:" << height << "sz:" << tunnelPanes.size();
@ -784,6 +817,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<std::string,TunnelConfig*>::iterator it=tunnelConfigs.begin(); it!=tunnelConfigs.end(); ++it) {
@ -795,31 +832,6 @@ void MainWindow::reloadTunnelsConfigAndUI(std::string tunnelNameToFocus) {
appendTunnelForms(tunnelNameToFocus);
}
void MainWindow::SaveTunnelsConfig() {
std::stringstream out;
for (std::map<std::string,TunnelConfig*>::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 +839,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){
@ -875,7 +887,8 @@ void MainWindow::anchorClickedHandler(const QUrl & link) {
pageWithBackButton->show();
textBrowser->hide();
std::stringstream s;
i2p::http::ShowLocalDestination(s,str.toStdString());
std::string strstd = str.toStdString();
i2p::http::ShowLocalDestination(s,strstd,0);
childTextBrowser->setHtml(QString::fromStdString(s.str()));
}
}

View File

@ -62,6 +62,12 @@
#include "widgetlockregistry.h"
#include "widgetlock.h"
#include "DelayedSaveManager.h"
#include "DelayedSaveManagerImpl.h"
#include "SaverImpl.h"
class SaverImpl;
class LogViewerManager;
template<typename ValueType>
@ -373,10 +379,14 @@ using namespace i2p::qt;
class Controller;
class DelayedSaveManagerImpl;
class MainWindow : public QMainWindow {
Q_OBJECT
private:
std::shared_ptr<std::iostream> logStream;
DelayedSaveManagerImpl* delayedSaveManagerPtr;
DelayedSaveManager::DATA_SERIAL_TYPE dataSerial;
public:
explicit MainWindow(std::shared_ptr<std::iostream> logStream_, QWidget *parent=nullptr);
~MainWindow();
@ -502,16 +512,17 @@ protected:
void initStringBox(ConfigOption option, QLineEdit* lineEdit);
NonGUIOptionItem* initNonGUIOption(ConfigOption option);
void loadAllConfigs();
void loadAllConfigs(SaverImpl* saverPtr);
void layoutTunnels();
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();
@ -530,6 +541,7 @@ private:
void appendTunnelForms(std::string tunnelNameToFocus);
void deleteTunnelForms();
void deleteTunnelFromUI(std::string tunnelName, TunnelConfig* cnf);
template<typename Section, typename Type>
std::string GetI2CPOption (const Section& section, const std::string& name, const Type& value) const
@ -575,11 +587,11 @@ private:
std::map<std::string,TunnelConfig*>::const_iterator it=tunnelConfigs.find(name);
if(it!=tunnelConfigs.end()){
TunnelConfig* tc=it->second;
deleteTunnelFromUI(name, tc);
tunnelConfigs.erase(it);
delete tc;
}
saveAllConfigs();
reloadTunnelsConfigAndUI("");
saveAllConfigs(false);
}
std::string GenerateNewTunnelName() {
@ -614,8 +626,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 +662,7 @@ private:
isUniqueLocal);
saveAllConfigs();
reloadTunnelsConfigAndUI(name);
saveAllConfigs(true, name);
}
void ReadTunnelsConfig() //TODO deduplicate the code with ClientContext.cpp::ReadTunnels ()
@ -793,7 +803,9 @@ private:
TunnelsPageUpdateListenerMainWindowImpl tunnelsPageUpdateListener;
void onLoggingOptionsChange() {}
//void onLoggingOptionsChange() {}
SaverImpl* saverPtr;
};
#endif // MAINWINDOW_H