Files
qad/libs/widgets/session_manager.cpp
2020-08-25 22:24:02 +03:00

298 lines
10 KiB
C++

#include <QApplication>
#include <QFileInfo>
#include <QMetaMethod>
#if QT_VERSION < 0x050000
# include <QDesktopWidget>
#else
# include <QScreen>
#endif
#include "session_manager.h"
#include "qad_locations.h"
SessionManager::SessionManager(QString file) {
if (file.isEmpty() && !QCoreApplication::applicationName().isEmpty()) {
file = QAD::userPath(QAD::ltConfig, "session");
}
setFile(file);
}
void SessionManager::setFile(const QString & file) {
if (file.isEmpty()) {
file_.clear();
return;
}
QFileInfo fi(file);
if (fi.isAbsolute()) {
file_ = file;
return;
}
file_ = QApplication::applicationDirPath() + "/" + file;
}
void SessionManager::removeMainWidget(QWidget * e) {
for (int i = 0; i < widgets.size(); ++i) {
if (widgets[i].first == e->objectName()) {
widgets.remove(i);
--i;
}
}
}
void SessionManager::save() {
if (file_.isEmpty()) {
qDebug() << "[SessionManager] filename is empty";
return;
}
QPIConfig sr(file_);
QObjectList tsc;
for (int i = 0; i < mwindows.size(); ++i) {
tsc << mwindows[i].second;
sr.setValue(mwindows[i].first + " state", mwindows[i].second->saveState(), false);
sr.setValue(mwindows[i].first + " window state", (int)mwindows[i].second->windowState(), false);
sr.setValue(mwindows[i].first + " geometry " + QString::number((int)mwindows[i].second->windowState()), mwindows[i].second->saveGeometry(), false);
QList<QSplitter * > sp = mwindows[i].second->findChildren<QSplitter * >();
foreach (QSplitter * s, sp)
sr.setValue(mwindows[i].first + " splitter " + s->objectName(), s->saveState(), false);
}
for (int i = 0; i < widgets.size(); ++i) {
tsc << widgets[i].second;
sr.setValue(widgets[i].first + " geometry " + QString::number((int)widgets[i].second->windowState()), widgets[i].second->saveGeometry(), false);
sr.setValue(widgets[i].first + " window state", (int)widgets[i].second->windowState(), false);
}
for (int i = 0; i < checks.size(); ++i)
sr.setValue(checks[i].first, checks[i].second->isChecked(), false);
for (int i = 0; i < lines.size(); ++i)
sr.setValue(lines[i].first, lines[i].second->text(), "s", false);
for (int i = 0; i < combos.size(); ++i)
sr.setValue(combos[i].first, combos[i].second->currentIndex(), false);
for (int i = 0; i < dspins.size(); ++i)
sr.setValue(dspins[i].first, dspins[i].second->value(), false);
for (int i = 0; i < spins.size(); ++i)
sr.setValue(spins[i].first, spins[i].second->value(), false);
for (int i = 0; i < spinsliders.size(); ++i)
sr.setValue(spinsliders[i].first, spinsliders[i].second->value(), false);
for (int i = 0; i < evals.size(); ++i)
sr.setValue(evals[i].first, evals[i].second->expression(), "s", false);
for (int i = 0; i < tabs.size(); ++i)
sr.setValue(tabs[i].first, tabs[i].second->currentIndex(), false);
for (int i = 0; i < groups.size(); ++i)
sr.setValue(groups[i].first, groups[i].second->isChecked(), false);
for (int i = 0; i < buttons.size(); ++i)
sr.setValue(buttons[i].first, buttons[i].second->isChecked(), false);
for (int i = 0; i < stacks.size(); ++i)
sr.setValue(stacks[i].first, stacks[i].second->currentIndex(), false);
for (int i = 0; i < actions.size(); ++i)
sr.setValue(actions[i].first, actions[i].second->isChecked(), false);
for (int i = 0; i < stringlists.size(); ++i)
sr.setValue(stringlists[i].first, *stringlists[i].second, false);
for (int i = 0; i < strings.size(); ++i)
sr.setValue(strings[i].first, *strings[i].second, "s", false);
for (int i = 0; i < colors.size(); ++i)
sr.setValue(colors[i].first, *colors[i].second, false);
for (int i = 0; i < bools.size(); ++i)
sr.setValue(bools[i].first, *bools[i].second, false);
for (int i = 0; i < ints.size(); ++i)
sr.setValue(ints[i].first, *ints[i].second, false);
for (int i = 0; i < floats.size(); ++i)
sr.setValue(floats[i].first, *floats[i].second, false);
QSet<QObject*> all_list;
foreach (QObject * c, tsc) {
all_list |= QSet<QObject*>::fromList(c->findChildren<QObject*>());
}
QMap<const QMetaObject*, QByteArray> funcs = metaFunctions(all_list, "sessionSave");
//qDebug() << "check for save" << all_list.size();
foreach (QObject * o, all_list) {
const QMetaObject * mo = o->metaObject();
QByteArray fn = funcs.value(mo);
if (!mo || fn.isEmpty()) continue;
QByteArray value;
//qDebug() << "save" << o->objectName();
mo->invokeMethod(o, fn.constData(), Q_ARG(QByteArray*, &value));
sr.setValue(o->objectName(), value, false);
}
//qDebug() << mcl.size();
emit saving(sr);
sr.writeAll();
}
void restoreWindowState(QWidget * w, QPIConfig & sr, QString name) {
int wstate = sr.getValue(name + " window state").toInt();
w->setWindowState(Qt::WindowNoState);
w->restoreGeometry(sr.getValue(name + " geometry 0").toByteArray());
if (wstate == Qt::WindowMaximized)
w->setWindowState((Qt::WindowState)wstate);
bool wnd_ok = false;
QRect srect;
#if QT_VERSION < 0x050000
wnd_ok = (QApplication::desktop()->screenNumber(w) >= 0);
if (!wnd_ok) {
srect = QApplication::desktop()->geometry();
}
#else
QList<QScreen*> sl = QApplication::screens();
foreach (QScreen * s, sl) {
if (s->geometry().contains(w->geometry())) {
wnd_ok = true;
break;
}
}
srect = QApplication::primaryScreen()->geometry();
#endif
if (!wnd_ok) {
w->setWindowState(Qt::WindowNoState);
w->setGeometry(srect.x() + (srect.width () - w->width ()) / 2,
srect.y() + (srect.height() - w->height()) / 2,
w->width(), w->height());
}
}
void SessionManager::load(bool onlyMainwindow) {
if (file_.isEmpty()) {
qDebug() << "[SessionManager] filename is empty";
return;
}
QPIConfig sr(file_);
QObjectList tsc;
for (int i = 0; i < mwindows.size(); ++i) {
QMainWindow * mw = mwindows[i].second;
tsc << mw;
QByteArray ba = sr.getValue(mwindows[i].first + " state").toByteArray();
if (!ba.isEmpty())
mw->restoreState(ba);
QList<QSplitter * > sp = mw->findChildren<QSplitter * >();
foreach (QSplitter * s, sp) {
ba = sr.getValue(mwindows[i].first + " splitter " + s->objectName()).toByteArray();
if (!ba.isEmpty())
s->restoreState(ba);
}
restoreWindowState(mw, sr, mwindows[i].first);
}
for (int i = 0; i < widgets.size(); ++i) {
QWidget * mw = widgets[i].second;
tsc << mw;
restoreWindowState(mw, sr, widgets[i].first);
}
if (onlyMainwindow) return;
for (int i = 0; i < checks.size(); ++i)
checks[i].second->setChecked(sr.getValue(checks[i].first, checks[i].second->isChecked()).toBool());
for (int i = 0; i < lines.size(); ++i)
lines[i].second->setText(sr.getValue(lines[i].first, lines[i].second->text()).toString());
for (int i = 0; i < combos.size(); ++i) {
QComboBox * c = combos[i].second;
int v = sr.getValue(combos[i].first, c->currentIndex()).toInt();
if (v >= 0 && v < c->count())
c->setCurrentIndex(v);
}
for (int i = 0; i < dspins.size(); ++i)
dspins[i].second->setValue(sr.getValue(dspins[i].first, dspins[i].second->value()).toDouble());
for (int i = 0; i < spins.size(); ++i)
spins[i].second->setValue(sr.getValue(spins[i].first, spins[i].second->value()).toInt());
for (int i = 0; i < spinsliders.size(); ++i)
spinsliders[i].second->setValue(sr.getValue(spinsliders[i].first, spinsliders[i].second->value()).toDouble());
for (int i = 0; i < evals.size(); ++i)
evals[i].second->setExpression(sr.getValue(evals[i].first, evals[i].second->expression()).toString());
for (int i = 0; i < tabs.size(); ++i) {
QTabWidget * t = tabs[i].second;
int v = sr.getValue(tabs[i].first, t->currentIndex()).toDouble();
if (v >= 0 && v < t->count())
t->setCurrentIndex(v);
}
for (int i = 0; i < groups.size(); ++i)
groups[i].second->setChecked(sr.getValue(groups[i].first, groups[i].second->isChecked()).toBool());
for (int i = 0; i < buttons.size(); ++i)
buttons[i].second->setChecked(sr.getValue(buttons[i].first, buttons[i].second->isChecked()).toBool());
for (int i = 0; i < stacks.size(); ++i)
stacks[i].second->setCurrentIndex(qMin<int>(sr.getValue(stacks[i].first, stacks[i].second->currentIndex()).toBool(), stacks[i].second->count()));
for (int i = 0; i < actions.size(); ++i)
actions[i].second->setChecked(sr.getValue(actions[i].first, actions[i].second->isChecked()).toBool());
for (int i = 0; i < stringlists.size(); ++i)
*stringlists[i].second = sr.getValue(stringlists[i].first, *stringlists[i].second).toStringList();
for (int i = 0; i < strings.size(); ++i)
*strings[i].second = sr.getValue(strings[i].first, *strings[i].second).toString();
for (int i = 0; i < colors.size(); ++i)
*colors[i].second = sr.getValue(colors[i].first, *colors[i].second).toColor();
for (int i = 0; i < bools.size(); ++i)
*bools[i].second = sr.getValue(bools[i].first, *bools[i].second).toBool();
for (int i = 0; i < ints.size(); ++i)
*ints[i].second = sr.getValue(ints[i].first, *ints[i].second).toInt();
for (int i = 0; i < floats.size(); ++i)
*floats[i].second = sr.getValue(floats[i].first, *floats[i].second).toFloat();
QSet<QObject*> all_list;
foreach (QObject * c, tsc) {
all_list |= QSet<QObject*>::fromList(c->findChildren<QObject*>());
}
QMap<const QMetaObject*, QByteArray> funcs = metaFunctions(all_list, "sessionLoad");
//qDebug() << "check for load" << all_list.size();
foreach (QObject * o, all_list) {
const QMetaObject * mo = o->metaObject();
QByteArray fn = funcs.value(mo);
if (!mo || fn.isEmpty()) continue;
QByteArray value = sr.getValue(o->objectName()).toByteArray();
//qDebug() << "load" << o->objectName();
mo->invokeMethod(o, fn.constData(), Q_ARG(QByteArray*, &value));
}
emit loading(sr);
}
void SessionManager::clear(bool with_filename) {
mwindows.clear();
widgets.clear();
checks.clear();
lines.clear();
combos.clear();
dspins.clear();
spins.clear();
spinsliders.clear();
evals.clear();
tabs.clear();
buttons.clear();
stacks.clear();
actions.clear();
stringlists.clear();
strings.clear();
colors.clear();
bools.clear();
ints.clear();
floats.clear();
if (with_filename) setFile("");
}
QMap<const QMetaObject *, QByteArray> SessionManager::metaFunctions(const QSet<QObject *> & objects, QByteArray fname) {
QMap<const QMetaObject*, QByteArray> funcs;
foreach (QObject * o, objects) {
const QMetaObject * mo = o->metaObject();
if (!mo) continue;
QByteArray fn;
if (!funcs.contains(mo)) {
for (int i = 0; i < mo->methodCount(); ++i) {
QMetaMethod mm = mo->method(i);
QByteArray mmn =
#if QT_VERSION >= 0x050000
mm.name();
#else
mm.signature();
mmn = mmn.left(mmn.indexOf('('));
#endif
if (mmn == fname) {
if (mm.parameterTypes().size() > 0) {
if (mm.parameterTypes()[0] == "QByteArray*") {
fn = mmn;
}
}
}
}
funcs[mo] = fn;
} else fn = funcs[mo];
}
return funcs;
}