#include #include #include #include #if QT_VERSION < 0x050000 # include #else # include #endif #include "qad_locations.h" #include "qad_types.h" #include "session_manager.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::addEntry(const QString & name, QMainWindow * e) { mwindows.push_back(QPair(name, e)); mw_splitters[e] = e->findChildren(); } 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 spl = mw_splitters[mwindows[i].second]; foreach(QSplitter * s, spl) 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 all_list; foreach(QObject * c, tsc) { all_list |= QList2QSet(c->findChildren()); all_list |= c; } QMap 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) { QTimer::singleShot(0, w, [w, wstate]() { 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 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 spl = mw_splitters[mw]; foreach(QSplitter * s, spl) { 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(sr.getValue(stacks[i].first, stacks[i].second->currentIndex()).toInt(), 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 all_list; foreach(QObject * c, tsc) { all_list |= QList2QSet(c->findChildren()); all_list |= c; } QMap 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(); mw_splitters.clear(); if (with_filename) setFile(""); } QMap SessionManager::metaFunctions(const QSet & objects, QByteArray fname) { QMap 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; }