Project 'savoirfairelinux/ring-daemon' was moved to 'savoirfairelinux/jami-daemon'. Please update any links and bookmarks that may still have the old path.
Select Git revision
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
accountserializationadapter.cpp 7.60 KiB
/***************************************************************************
* Copyright (C) 2015-2016 by Savoir-faire Linux *
* Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com>*
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
**************************************************************************/
#include "accountserializationadapter.h"
#include <QtWidgets/QWidget>
#include <QtWidgets/QLayout>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QSpinBox>
#include <QtWidgets/QGroupBox>
#include <QtWidgets/QFormLayout>
#include <QtWidgets/QAbstractButton>
#include <QtWidgets/QLabel>
#include <account.h>
#include <accountmodel.h>
constexpr static const char LRC_CFG[] = "lrcfg_";
constexpr static const int LRC_CFG_LEN = 6 ;
struct ConnHolder {
QMetaObject::Connection c;
~ConnHolder();
};
Q_DECLARE_METATYPE(ConnHolder*);
ConnHolder::~ConnHolder()
{
QObject::disconnect(c);
}
static void avoidDuplicate(QWidget* w)
{
if (qvariant_cast<ConnHolder*>(w->property("lrcfgConn")))
delete qvariant_cast<ConnHolder*>(w->property("lrcfgConn"));
}
/**
* This check for some supported widgets and bind the widgets and property
*/
static void setupWidget(QWidget* w, Account* a, const QHash<QByteArray, int>& roles)
{
if (w->objectName().left(LRC_CFG_LEN) == LRC_CFG) {
const QByteArray prop = w->objectName().mid(LRC_CFG_LEN, 999).toLatin1();
if (roles.contains(prop)) {
const int role = roles[prop];
if (qobject_cast<QLineEdit*>(w)) {
QLineEdit* le = qobject_cast<QLineEdit*>(w);
avoidDuplicate(le);
le->setText(a->roleData(role).toString());
ConnHolder* c = new ConnHolder {
QObject::connect(le, &QLineEdit::textChanged, [a,role](const QString& text) {
if (a->roleData(role) != text)
a->setRoleData(role, text);
})
};
le->setProperty("lrcfgConn",QVariant::fromValue(c));
}
else if (qobject_cast<QSpinBox*>(w)) {
QSpinBox* sb = qobject_cast<QSpinBox*>(w);
avoidDuplicate(sb);
sb->setValue(a->roleData(role).toInt());
ConnHolder* c = new ConnHolder {
QObject::connect(sb, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [a,role](int value) {
if (a->roleData(role).toInt() != value)
a->setRoleData(role, value);
})
};
sb->setProperty("lrcfgConn",QVariant::fromValue(c));
}
else if (qobject_cast<QAbstractButton*>(w)) {
//QCheckBox, QRadioButton, QToolButton, QPushButton
QAbstractButton* b = qobject_cast<QAbstractButton*>(w);
avoidDuplicate(b);
b->setChecked(a->roleData(role).toBool());
ConnHolder* c = new ConnHolder {
QObject::connect(b, &QAbstractButton::toggled,[a,role](bool c) {
if (a->roleData(role).toBool() != c)
a->setRoleData(role, c);
})
};
b->setProperty("lrcfgConn",QVariant::fromValue(c));
}
else if (qobject_cast<QGroupBox*>(w)) {
QGroupBox* b = qobject_cast<QGroupBox*>(w);
avoidDuplicate(b);
b->setChecked(a->roleData(role).toBool());
ConnHolder* c = new ConnHolder {
QObject::connect(b, &QGroupBox::toggled,[a,role](bool c) {
if (a->roleData(role).toBool() != c)
a->setRoleData(role, c);
})
};
b->setProperty("lrcfgConn",QVariant::fromValue(c));
}
else {
qDebug() << "Unsupported widget type" << w;
}
//Check if the field is required for this account type
if (a->roleState((Account::Role)role) == Account::RoleState::UNAVAILABLE) {
w->setProperty("lrcfgVisible", w->isVisible() ? 2 : 1);
w->setVisible(false);
QFormLayout* fm = qobject_cast<QFormLayout*>(w->parentWidget()->layout());
//There is many of corner case here, this only handle the one that's
//created by Qt Designer
if (!fm) {
QLayoutItem* il = w->parentWidget()->layout()->itemAt(0);
if (il && il->layout())
fm = qobject_cast<QFormLayout*>(il->layout());
}
if (fm) {
QWidget* buddy = fm->labelForField(w);
qDebug() << "BUDDY " << buddy;
if (buddy)
buddy->setVisible(false);
}
}
else {
//0 = unset, 1=invisible, 2=visible
const int oldVisibleState = w->property("lrcfgVisible").toInt();
if (oldVisibleState)
w->setVisible(oldVisibleState-1);
}
}
else {
qWarning() << "Unknown config properties" << w->objectName();
}
}
}
static void clearConnections(QWidget* w)
{
if (w->objectName().left(LRC_CFG_LEN) == LRC_CFG) {
avoidDuplicate(w);
}
}
static void drill(QWidget* w, Account* a, const QHash<QByteArray, int>& roles, bool clear = false)
{
for (QObject *object : w->children()) {
if (!object->isWidgetType())
continue;
QWidget* w2 = static_cast<QWidget*>(object);
if (clear)
clearConnections(w2);
else
setupWidget(w2, a, roles);
drill(w2, a, roles);
}
}
static void hideLabel(QWidget* w) {
for (QObject *object : w->children()) {
if (!object->isWidgetType())
continue;
QWidget* w2 = qobject_cast<QWidget*>(object);
if (w2) {
QLabel* l = qobject_cast<QLabel*>(w2);
if (l && l->buddy()) {
l->setVisible(!l->buddy()->isHidden());
}
}
hideLabel(w2);
}
}
AccountSerializationAdapter::AccountSerializationAdapter(Account* a, QWidget* w) : QObject(w)
{
static QHash<QByteArray, int> reverse;
if (reverse.isEmpty()) {
const QHash<int, QByteArray> a = AccountModel::instance().roleNames();
for (QHash<int, QByteArray>::const_iterator i = a.begin(); i != a.end(); ++i) {
reverse[i.value()] = i.key();
}
}
drill(w, a, reverse);
hideLabel(w);
}
AccountSerializationAdapter::~AccountSerializationAdapter()
{
}