XDataField_TextMulti(XData::Field f, QGridLayout *grid, int row, QWidget *parent)
        : XDataField(f)
    {
        QLabel *label = new QLabel(labelText(), parent);
        grid->addWidget(label, row, 0);

        edit = new QTextEdit(parent);
        grid->addWidget(edit, row, 1);

        QString text;
        QStringList val = f.value();
        QStringList::Iterator it = val.begin();
        for ( ; it != val.end(); ++it) {
            if ( !text.isEmpty() )
                text += "\n";
            text += *it;
        }
        edit->setText(text);

        QLabel *req = new QLabel(reqText(), parent);
        grid->addWidget(req, row, 2);

        if ( !f.desc().isEmpty() ) {
            label->setToolTip(f.desc());
            edit->setToolTip(f.desc());
            req->setToolTip(f.desc());
        }
    }
    XDataField_ListMulti(XData::Field f, QGridLayout *grid, int row, QWidget *parent)
        : XDataField(f)
    {
        QLabel *label = new QLabel(labelText(), parent);
        grid->addWidget(label, row, 0);

        list = new QListWidget(parent);
        grid->addWidget(list, row, 1);
        list->setSelectionMode(QAbstractItemView::MultiSelection);

        XData::Field::OptionList opts = f.options();
        XData::Field::OptionList::Iterator it = opts.begin();
        for ( ; it != opts.end(); ++it) {
            QString lbl = (*it).label;
            if ( lbl.isEmpty() )
                lbl = (*it).value;

            QListWidgetItem* item = new QListWidgetItem(lbl,list);

            QStringList val = f.value();
            QStringList::Iterator sit = val.begin();
            for ( ; sit != val.end(); ++sit)
                if ( (*it).label == *sit || (*it).value == *sit )
                    list->setItemSelected(item, true);
        }

        QLabel *req = new QLabel(reqText(), parent);
        grid->addWidget(req, row, 2);

        if ( !f.desc().isEmpty() ) {
            label->setToolTip(f.desc());
            list->setToolTip(f.desc());
            req->setToolTip(f.desc());
        }
    }
    XDataField_ListSingle(XData::Field f, QGridLayout *grid, int row, QWidget *parent)
        : XDataField(f)
    {
        QLabel *label = new QLabel(labelText(), parent);
        grid->addWidget(label, row, 0);

        combo = new QComboBox(parent);
        grid->addWidget(combo, row, 1);
        combo->setInsertionPolicy(QComboBox::NoInsertion);

        QString sel;
        if ( !f.value().isEmpty() )
            sel = f.value().first();

        XData::Field::OptionList opts = f.options();
        XData::Field::OptionList::Iterator it = opts.begin();
        for ( ; it != opts.end(); ++it) {
            QString lbl = (*it).label;
            if ( lbl.isEmpty() )
                lbl = (*it).value;

            combo->insertItem(lbl);
            if ( (*it).value == sel )
                combo->setCurrentText( lbl );
        }

        QLabel *req = new QLabel(reqText(), parent);
        grid->addWidget(req, row, 2);

        if ( !f.desc().isEmpty() ) {
            label->setToolTip(f.desc());
            combo->setToolTip(f.desc());
            req->setToolTip(f.desc());
        }
    }
    XDataField_Boolean(XData::Field f, QGridLayout *grid, int row, QWidget *parent)
        : XDataField(f)
    {
        bool checked = false;
        if ( f.value().count() ) {
            QString s = f.value().first();
            if ( s == "1" || s == "true" || s == "yes" )
                checked = true;
        }

        QLabel *label = new QLabel(labelText(), parent);
        grid->addWidget(label, row, 0);

        check = new QCheckBox(parent);
        check->setChecked(checked);
        grid->addWidget(check, row, 1);

        QLabel *req = new QLabel(reqText(), parent);
        grid->addWidget(req, row, 2);

        if ( !f.desc().isEmpty() ) {
            label->setToolTip(f.desc());
            check->setToolTip(f.desc());
            req->setToolTip(f.desc());
        }
    }
    XDataField_Fixed(XData::Field f, QGridLayout *grid, int row, QWidget *parent)
        : XDataField(f)
    {
        QString text;
        QStringList val = f.value();
        QStringList::Iterator it = val.begin();
        for ( ; it != val.end(); ++it) {
            if ( !text.isEmpty() )
                text += "<br>";
            text += *it;
        }

        QLabel *fixed = new QLabel("<qt>" + text + "</qt>", parent);
        grid->addMultiCellWidget(fixed, row, row, 0, 2);

        if ( !f.desc().isEmpty() ) {
            fixed->setToolTip(f.desc());
        }
    }
    XDataField_TextSingle(XData::Field f, QGridLayout *grid, int row, QWidget *parent)
        : XDataField(f)
    {
        QString text;
        if ( f.value().count() )
            text = f.value().first();

        QLabel *label = new QLabel(labelText(), parent);
        grid->addWidget(label, row, 0);

        edit = new QLineEdit(parent);
        edit->setText(text);
        grid->addWidget(edit, row, 1);

        QLabel *req = new QLabel(reqText(), parent);
        grid->addWidget(req, row, 2);

        if ( !f.desc().isEmpty() ) {
            label->setToolTip(f.desc());
            edit->setToolTip(f.desc());
            req->setToolTip(f.desc());
        }
    }