Skip to content
Snippets Groups Projects
Select Git revision
  • 12353822b0d9c6e1e8b75e65be383b4a7883d9da
  • master default protected
  • release/202005
  • release/202001
  • release/201912
  • release/201911
  • release/201910
  • release/201908
  • release/201906
  • release/201905
  • release/201904
  • release/201903
  • release/201902
  • release/201901
  • release/201812
  • release/201811
  • release/201808
  • releases/beta1
  • packaging
  • native
  • release-0.2.x
  • 1.0.0
  • 0.2.0
  • 0.1.1
  • 0.1.0
25 results

navwidget.cpp

Blame
  • 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()
    {
    
    }