Browse Source

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

qt: delayed save in background. should be better ui experience
pull/1499/head
orignal 5 years ago committed by GitHub
parent
commit
82bdcfbbcb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      .gitignore
  2. 2
      daemon/HTTPServer.h
  3. 3
      qt/i2pd_qt/DelayedSaveManager.cpp
  4. 24
      qt/i2pd_qt/DelayedSaveManager.h
  5. 140
      qt/i2pd_qt/DelayedSaveManagerImpl.cpp
  6. 82
      qt/i2pd_qt/DelayedSaveManagerImpl.h
  7. 6
      qt/i2pd_qt/Saver.cpp
  8. 22
      qt/i2pd_qt/Saver.h
  9. 79
      qt/i2pd_qt/SaverImpl.cpp
  10. 33
      qt/i2pd_qt/SaverImpl.h
  11. 7
      qt/i2pd_qt/TunnelConfig.h
  12. 7
      qt/i2pd_qt/TunnelPane.cpp
  13. 2
      qt/i2pd_qt/TunnelPane.h
  14. 12
      qt/i2pd_qt/i2pd_qt.pro
  15. 137
      qt/i2pd_qt/mainwindow.cpp
  16. 32
      qt/i2pd_qt/mainwindow.h

8
.gitignore vendored

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

2
daemon/HTTPServer.h

@ -89,7 +89,7 @@ namespace http
void ShowTransports (std::stringstream& s); void ShowTransports (std::stringstream& s);
void ShowSAMSessions (std::stringstream& s); void ShowSAMSessions (std::stringstream& s);
void ShowI2PTunnels (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 } // http
} // i2p } // i2p

3
qt/i2pd_qt/DelayedSaveManager.cpp

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

24
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

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

82
qt/i2pd_qt/DelayedSaveManagerImpl.h

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

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

22
qt/i2pd_qt/Saver.h

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

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

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

7
qt/i2pd_qt/TunnelConfig.h

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

7
qt/i2pd_qt/TunnelPane.cpp

@ -64,7 +64,7 @@ void TunnelPane::setupTunnelPane(
//type //type
{ {
const QString& type = tunnelConfig->getType(); //const QString& type = tunnelConfig->getType();
QHBoxLayout * horizontalLayout_ = new QHBoxLayout(); QHBoxLayout * horizontalLayout_ = new QHBoxLayout();
horizontalLayout_->setObjectName(QStringLiteral("horizontalLayout_")); horizontalLayout_->setObjectName(QStringLiteral("horizontalLayout_"));
typeLabel = new QLabel(gridLayoutWidget_2); typeLabel = new QLabel(gridLayoutWidget_2);
@ -83,6 +83,11 @@ void TunnelPane::setupTunnelPane(
retranslateTunnelForm(*this); retranslateTunnelForm(*this);
} }
void TunnelPane::deleteWidget() {
//gridLayoutWidget_2->deleteLater();
tunnelGroupBox->deleteLater();
}
void TunnelPane::appendControlsForI2CPParameters(I2CPParameters& i2cpParameters, int& gridIndex) { void TunnelPane::appendControlsForI2CPParameters(I2CPParameters& i2cpParameters, int& gridIndex) {
{ {
//number of hops of an inbound tunnel //number of hops of an inbound tunnel

2
qt/i2pd_qt/TunnelPane.h

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

12
qt/i2pd_qt/i2pd_qt.pro

@ -91,7 +91,11 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \
pagewithbackbutton.cpp \ pagewithbackbutton.cpp \
widgetlock.cpp \ widgetlock.cpp \
widgetlockregistry.cpp \ widgetlockregistry.cpp \
logviewermanager.cpp logviewermanager.cpp \
DelayedSaveManager.cpp \
Saver.cpp \
DelayedSaveManagerImpl.cpp \
SaverImpl.cpp
HEADERS += DaemonQT.h mainwindow.h \ HEADERS += DaemonQT.h mainwindow.h \
../../libi2pd/api.h \ ../../libi2pd/api.h \
@ -179,7 +183,11 @@ HEADERS += DaemonQT.h mainwindow.h \
widgetlock.h \ widgetlock.h \
widgetlockregistry.h \ widgetlockregistry.h \
i2pd.rc \ i2pd.rc \
logviewermanager.h logviewermanager.h \
DelayedSaveManager.h \
Saver.h \
DelayedSaveManagerImpl.h \
SaverImpl.h
INCLUDEPATH += ../../libi2pd INCLUDEPATH += ../../libi2pd
INCLUDEPATH += ../../libi2pd_client INCLUDEPATH += ../../libi2pd_client

137
qt/i2pd_qt/mainwindow.cpp

@ -1,11 +1,8 @@
#include <fstream>
#include <assert.h>
#include "mainwindow.h" #include "mainwindow.h"
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
#include "ui_statusbuttons.h" #include "ui_statusbuttons.h"
#include "ui_routercommandswidget.h" #include "ui_routercommandswidget.h"
#include "ui_generalsettingswidget.h" #include "ui_generalsettingswidget.h"
#include <sstream>
#include <QScrollBar> #include <QScrollBar>
#include <QMessageBox> #include <QMessageBox>
#include <QTimer> #include <QTimer>
@ -29,17 +26,22 @@
#include "logviewermanager.h" #include "logviewermanager.h"
#include "DelayedSaveManagerImpl.h"
#include "SaverImpl.h"
std::string programOptionsWriterCurrentSection; std::string programOptionsWriterCurrentSection;
MainWindow::MainWindow(std::shared_ptr<std::iostream> logStream_, QWidget *parent) : MainWindow::MainWindow(std::shared_ptr<std::iostream> logStream_, QWidget *parent) :
QMainWindow(parent) QMainWindow(parent)
,logStream(logStream_) ,logStream(logStream_)
#ifndef ANDROID ,delayedSaveManagerPtr(new DelayedSaveManagerImpl())
,quitting(false) ,dataSerial(DelayedSaveManagerImpl::INITIAL_DATA_SERIAL)
#endif
,wasSelectingAtStatusMainPage(false) ,wasSelectingAtStatusMainPage(false)
,showHiddenInfoStatusMainPage(false) ,showHiddenInfoStatusMainPage(false)
,logViewerManagerPtr(nullptr) ,logViewerManagerPtr(nullptr)
#ifndef ANDROID
,quitting(false)
#endif
,ui(new Ui::MainWindow) ,ui(new Ui::MainWindow)
,statusButtonsUI(new Ui::StatusButtonsForm) ,statusButtonsUI(new Ui::StatusButtonsForm)
,routerCommandsUI(new Ui::routerCommandsWidget) ,routerCommandsUI(new Ui::routerCommandsWidget)
@ -51,9 +53,14 @@ MainWindow::MainWindow(std::shared_ptr<std::iostream> logStream_, QWidget *paren
,datadir() ,datadir()
,confpath() ,confpath()
,tunconfpath() ,tunconfpath()
,tunnelConfigs()
,tunnelsPageUpdateListener(this) ,tunnelsPageUpdateListener(this)
,saverPtr(new SaverImpl(this, &configItems, &tunnelConfigs))
{ {
assert(delayedSaveManagerPtr!=nullptr);
assert(saverPtr!=nullptr);
ui->setupUi(this); ui->setupUi(this);
statusButtonsUI->setupUi(ui->statusButtonsPane); statusButtonsUI->setupUi(ui->statusButtonsPane);
routerCommandsUI->setupUi(routerCommandsParent); routerCommandsUI->setupUi(routerCommandsParent);
@ -75,7 +82,7 @@ MainWindow::MainWindow(std::shared_ptr<std::iostream> logStream_, QWidget *paren
ui->stackedWidget->setCurrentIndex(0); ui->stackedWidget->setCurrentIndex(0);
ui->settingsScrollArea->resize(uiSettings->settingsContentsGridLayout->sizeHint().width()+10,380); 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 w = 683;
int h = 3060; int h = 3060;
ui->settingsContents->setFixedSize(w, h); 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_httpPorxySignatureType,uiSettings->httpProxySignTypeComboEditPushButton));
widgetlocks.add(new widgetlock(uiSettings->comboBox_socksProxySignatureType,uiSettings->socksProxySignTypeComboEditPushButton)); 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 &)), QObject::connect(uiSettings->logDestinationComboBox, SIGNAL(currentIndexChanged(const QString &)),
this, SLOT(logDestinationComboBoxValueChanged(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 &)), QObject::connect(uiSettings->tunnelsConfigFileLineEdit, SIGNAL(textChanged(const QString &)),
this, SLOT(reloadTunnelsConfigAndUI())); this, SLOT(reloadTunnelsConfigAndUI()));
QObject::connect(ui->addServerTunnelPushButton, SIGNAL(released()), this, SLOT(addServerTunnelPushButtonReleased())); QObject::connect(ui->addServerTunnelPushButton, SIGNAL(released()), this, SLOT(addServerTunnelPushButtonReleased()));
QObject::connect(ui->addClientTunnelPushButton, SIGNAL(released()), this, SLOT(addClientTunnelPushButtonReleased())); 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); logViewerManagerPtr=new LogViewerManager(logStream_,ui->logViewerTextEdit,this);
assert(logViewerManagerPtr!=nullptr); assert(logViewerManagerPtr!=nullptr);
onLoggingOptionsChange(); //onLoggingOptionsChange();
//QMetaObject::connectSlotsByName(this); //QMetaObject::connectSlotsByName(this);
} }
@ -500,6 +512,8 @@ void MainWindow::handleQuitButton() {
quitting=true; quitting=true;
#endif #endif
close(); close();
delayedSaveManagerPtr->appExiting();
qDebug("Performing quit");
QApplication::instance()->quit(); QApplication::instance()->quit();
} }
@ -526,6 +540,7 @@ void MainWindow::handleGracefulQuitTimerEvent() {
quitting=true; quitting=true;
#endif #endif
close(); close();
delayedSaveManagerPtr->appExiting();
qDebug("Performing quit"); qDebug("Performing quit");
QApplication::instance()->quit(); QApplication::instance()->quit();
} }
@ -534,6 +549,8 @@ MainWindow::~MainWindow()
{ {
qDebug("Destroying main window"); qDebug("Destroying main window");
delete statusPageUpdateTimer; delete statusPageUpdateTimer;
delete delayedSaveManagerPtr;
delete saverPtr;
for(QList<MainWindowItem*>::iterator it = configItems.begin(); it!= configItems.end(); ++it) { for(QList<MainWindowItem*>::iterator it = configItems.begin(); it!= configItems.end(); ++it) {
MainWindowItem* item = *it; MainWindowItem* item = *it;
item->deleteLater(); item->deleteLater();
@ -594,7 +611,7 @@ NonGUIOptionItem* MainWindow::initNonGUIOption(ConfigOption option) {
return retValue; return retValue;
} }
void MainWindow::loadAllConfigs(){ void MainWindow::loadAllConfigs(SaverImpl* saverPtr){
//BORROWED FROM ??? //TODO move this code into single location //BORROWED FROM ??? //TODO move this code into single location
std::string config; i2p::config::GetOption("conf", config); std::string config; i2p::config::GetOption("conf", config);
@ -635,6 +652,9 @@ void MainWindow::loadAllConfigs(){
this->datadir = datadir.c_str(); this->datadir = datadir.c_str();
this->tunconfpath = tunConf.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) { for(QList<MainWindowItem*>::iterator it = configItems.begin(); it!= configItems.end(); ++it) {
MainWindowItem* item = *it; MainWindowItem* item = *it;
item->loadFromConfigOption(); item->loadFromConfigOption();
@ -642,10 +662,40 @@ void MainWindow::loadAllConfigs(){
ReadTunnelsConfig(); 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 */ /** 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."); QString cannotSaveSettings = QApplication::tr("Cannot save settings.");
programOptionsWriterCurrentSection=""; programOptionsWriterCurrentSection="";
/*if(!logFileNameOption->lineEdit->text().trimmed().isEmpty())logOption->optionValue=boost::any(std::string("file")); /*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); daemonOption->optionValue=boost::any(false);
serviceOption->optionValue=boost::any(false); serviceOption->optionValue=boost::any(false);
std::stringstream out;
for(QList<MainWindowItem*>::iterator it = configItems.begin(); it!= configItems.end(); ++it) { for(QList<MainWindowItem*>::iterator it = configItems.begin(); it!= configItems.end(); ++it) {
MainWindowItem* item = *it; MainWindowItem* item = *it;
if(!item->isValid()){ if(!item->isValid()){
@ -661,27 +710,9 @@ bool MainWindow::saveAllConfigs(){
return false; return false;
} }
} }
delayedSaveManagerPtr->delayedSave(++dataSerial, focusOnTunnel, tunnelNameToFocus);
for(QList<MainWindowItem*>::iterator it = configItems.begin(); it!= configItems.end(); ++it) { //onLoggingOptionsChange();
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();
return true; return true;
} }
@ -711,7 +742,7 @@ void MainWindow::updated() {
adjustSizesAccordingToWrongLabel(); adjustSizesAccordingToWrongLabel();
applyTunnelsUiToConfigs(); applyTunnelsUiToConfigs();
saveAllConfigs(); saveAllConfigs(false);
} }
void MainWindowItem::installListeners(MainWindow *mainWindow) {} void MainWindowItem::installListeners(MainWindow *mainWindow) {}
@ -725,6 +756,7 @@ void MainWindow::appendTunnelForms(std::string tunnelNameToFocus) {
ServerTunnelConfig* stc = tunconf->asServerTunnelConfig(); ServerTunnelConfig* stc = tunconf->asServerTunnelConfig();
if(stc){ if(stc){
ServerTunnelPane * tunnelPane=new ServerTunnelPane(&tunnelsPageUpdateListener, stc, ui->wrongInputLabel, ui->wrongInputLabel, this); ServerTunnelPane * tunnelPane=new ServerTunnelPane(&tunnelsPageUpdateListener, stc, ui->wrongInputLabel, ui->wrongInputLabel, this);
tunconf->setTunnelPane(tunnelPane);
int h=tunnelPane->appendServerTunnelForm(stc, ui->tunnelsScrollAreaWidgetContents, tunnelPanes.size(), height); int h=tunnelPane->appendServerTunnelForm(stc, ui->tunnelsScrollAreaWidgetContents, tunnelPanes.size(), height);
height+=h; height+=h;
//qDebug() << "tun.height:" << height << "sz:" << tunnelPanes.size(); //qDebug() << "tun.height:" << height << "sz:" << tunnelPanes.size();
@ -738,6 +770,7 @@ void MainWindow::appendTunnelForms(std::string tunnelNameToFocus) {
ClientTunnelConfig* ctc = tunconf->asClientTunnelConfig(); ClientTunnelConfig* ctc = tunconf->asClientTunnelConfig();
if(ctc){ if(ctc){
ClientTunnelPane * tunnelPane=new ClientTunnelPane(&tunnelsPageUpdateListener, ctc, ui->wrongInputLabel, ui->wrongInputLabel, this); ClientTunnelPane * tunnelPane=new ClientTunnelPane(&tunnelsPageUpdateListener, ctc, ui->wrongInputLabel, ui->wrongInputLabel, this);
tunconf->setTunnelPane(tunnelPane);
int h=tunnelPane->appendClientTunnelForm(ctc, ui->tunnelsScrollAreaWidgetContents, tunnelPanes.size(), height); int h=tunnelPane->appendClientTunnelForm(ctc, ui->tunnelsScrollAreaWidgetContents, tunnelPanes.size(), height);
height+=h; height+=h;
//qDebug() << "tun.height:" << height << "sz:" << tunnelPanes.size(); //qDebug() << "tun.height:" << height << "sz:" << tunnelPanes.size();
@ -784,6 +817,10 @@ bool MainWindow::applyTunnelsUiToConfigs() {
return true; return true;
} }
void MainWindow::reloadTunnelsConfigAndUI_QString(const QString tunnelNameToFocus) {
reloadTunnelsConfigAndUI(tunnelNameToFocus.toStdString());
}
void MainWindow::reloadTunnelsConfigAndUI(std::string tunnelNameToFocus) { void MainWindow::reloadTunnelsConfigAndUI(std::string tunnelNameToFocus) {
deleteTunnelForms(); deleteTunnelForms();
for (std::map<std::string,TunnelConfig*>::iterator it=tunnelConfigs.begin(); it!=tunnelConfigs.end(); ++it) { 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); 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) { void MainWindow::TunnelsPageUpdateListenerMainWindowImpl::updated(std::string oldName, TunnelConfig* tunConf) {
if(oldName!=tunConf->getName()) { if(oldName!=tunConf->getName()) {
//name has changed //name has changed
@ -827,7 +839,7 @@ void MainWindow::TunnelsPageUpdateListenerMainWindowImpl::updated(std::string ol
if(it!=mainWindow->tunnelConfigs.end())mainWindow->tunnelConfigs.erase(it); if(it!=mainWindow->tunnelConfigs.end())mainWindow->tunnelConfigs.erase(it);
mainWindow->tunnelConfigs[tunConf->getName()]=tunConf; mainWindow->tunnelConfigs[tunConf->getName()]=tunConf;
} }
mainWindow->saveAllConfigs(); mainWindow->saveAllConfigs(true, tunConf->getName());
} }
void MainWindow::TunnelsPageUpdateListenerMainWindowImpl::needsDeleting(std::string oldName){ void MainWindow::TunnelsPageUpdateListenerMainWindowImpl::needsDeleting(std::string oldName){
@ -875,7 +887,8 @@ void MainWindow::anchorClickedHandler(const QUrl & link) {
pageWithBackButton->show(); pageWithBackButton->show();
textBrowser->hide(); textBrowser->hide();
std::stringstream s; 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())); childTextBrowser->setHtml(QString::fromStdString(s.str()));
} }
} }

32
qt/i2pd_qt/mainwindow.h

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

Loading…
Cancel
Save