Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: aliks-os от Июль 06, 2011, 11:58



Название: Динамическая загрузка формы, путь движения развития
Отправлено: aliks-os от Июль 06, 2011, 11:58
В проекте, есть динамическая загрузка формы.
Форма может быть как для чтения так и для редактирования.
В режиме редактирования, виджеты расположенные на форме можно перемещать по форме, изменять их размеры, добавлять новые. Вся эта функциональность уже реализована.
Настал этап когда необходимо сохранить изменения на форме обратно в UI файл.
Пытался сделать через FormBuilder, но у Qt оказался баг. Этот вопрос мною уже обсуждался здесь http://www.prog.org.ru/topic_18724_0.html. Так что это направление оказалось провальным.

Соответственно возникают вопросы, в каком направлении двигаться, чтобы иметь возможность чтения/записи формы.
Сразу возникает мысль вручную парсить каждый виджет расположенный на форме и вручную составлять XML и записывать его в UI файл. Однако, как мне кажется, уйдет немало времени на написание такого парсера.

Может, кто нибудь поделиться своими мыслями по данной проблеме.


Название: Re: Динамическая загрузка формы, путь движения развития
Отправлено: Пантер от Июль 06, 2011, 12:01
ИМХО, только самому наследоваться от QFormBuilder и переписать функционал. Или же делать пост-обработку, удаляя косяки.


Название: Re: Динамическая загрузка формы, путь движения развития
Отправлено: aliks-os от Июль 06, 2011, 12:09
ИМХО, только самому наследоваться от QFormBuilder и переписать функционал. Или же делать пост-обработку, удаляя косяки.

Пост-обработку думаю лучше не делать, кажется проще для нервов переписать функционал.
Ну это в принципе тоже самое что я имел ввиду "написать свой парсер". Соответственно возникают вопросы. Почему QFormBuilder пишет ui файлы по одному принципу, а дизайнер по другому. Значить использованы разные механизмы записи. Где можно взять шаблон xml для каждого виджета? или исследовать все это вручную?


Название: Re: Динамическая загрузка формы, путь движен&
Отправлено: iks от Июль 07, 2011, 08:05
И так и сяк пробовал, но все больше схожусь к мысли обработки XML и вставки новых данных, а прямое сохранение дает кривой файл .ui который роняет приложение потом.
Или как решение плюнуть на сохранение самого .ui а данные заносить в struct и сохранять их в xml файл, хотя сама реализация нормальной обработки, а точнее перезаписи .ui где-то зарыта и не так глубоко.


Название: Re: Динамическая загрузка формы, путь движения развития
Отправлено: aliks-os от Июль 07, 2011, 08:35
Вот и я пришел к выводу что надо напрямую обрабатывать xml и сохранять его


Название: Re: Динамическая загрузка формы, путь движения развития
Отправлено: Пантер от Июль 07, 2011, 09:18
aliks-os, можешь методом Великого Ученого Тыка найти виджеты, которые неверно сохраняются и только для них переписать сохраняловку.


Название: Re: Динамическая загрузка формы, путь движен&
Отправлено: iks от Июль 07, 2011, 11:32
ПРи сохранении идут строки
Цитировать
Designer: Flags property are not supported yet.
То есть что флаги собственности еще не поддерживаются, и сохраненый xml имеет первую ошибку
Цитировать
Возникла ошибка при чтении файла UI в строке 662 позиции 38: Объявление XML находится не в начале документа.
при открытии его в дизайнере, и при загрузке в приложение
Цитировать
Designer: An error has occurred while reading the UI file at line 662, column 38: XML declaration not at start of document.
такая же ошибка.
Попробовал сохранится с очисткой старого хлама
Код
C++ (Qt)
file->resize(0);
builder->save(file, formWidget);
Цитировать
Designer: An error has occurred while reading the UI file at line 7676, column 4: Premature end of document.
и xml пишется не законченым, нет закрытия тегов таких как </ui> дальше не смотрел, но проблема кроется похоже тут.


Название: Re: Динамическая загрузка формы, путь движения развития
Отправлено: aliks-os от Июль 07, 2011, 13:05
aliks-os, можешь методом Великого Ученого Тыка найти виджеты, которые неверно сохраняются и только для них переписать сохраняловку.

В принципе я уже практически написал написал поиск необходимого в xml и сохранение в файл. Так что практически осталось немного довести до ума. Две вот такие функции осуществляют нужные свойств, пока протестил только на x,y,width,heigth

Код:
bool DocForm::setXMLProperty(QString widgetName, QString propertyName, QString value) {
    QDomNodeList nodelist = xmlDoc->elementsByTagName("widget");
    QDomElement elem; // здесь будет сохранен нужный нам узел
    for (int i =0; i != nodelist.count(); i++) {
        elem = nodelist.item(i).toElement();
        if (elem.attribute("name") == widgetName) {
            QDomNode node = getNode(nodelist.item(i), propertyName);
            qDebug() << node.nodeName();
            if (!node.isNull()) {
                node.firstChild().setNodeValue(value);
                return true;
            } else return false;
        }
    }
}

QDomNode DocForm::getNode(QDomNode node, QString nodeName) {
    if (node.nodeName() == nodeName)
        return node;
    QDomNode tmp;
    tmp.clear();
    if (node.hasChildNodes()) {
        for(QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
            if (n.isText()) continue;
            if (n.nodeName() == nodeName) {
                return n;
            }

            if (n.hasChildNodes()) {
                tmp = getNode(n,nodeName);
                if (!tmp.isNull()) break;
            }
        }
    }
    return tmp;
}

//вот так их использую
    setXMLProperty("tableWidget","x","100");
    setXMLProperty("tableWidget","y","600");

//вот так произвожу сохранение
    QFile file("c:\outfile.ui");
    file.open(QIODevice::WriteOnly);
    QTextStream stream(&file1);
    xmlDoc->save(stream, 5, QDomNode::EncodingFromTextStream);
    file.close();


В принципе осталось мне только сделать изменения стилей. Ну и привязать все это к событиям


Название: Re: Динамическая загрузка формы, путь движен&
Отправлено: iks от Июль 07, 2011, 13:54
Ну похоже оптимальный вариант, обработки xml, но перед перезаписью всеж почистите файл для гарантии file.resize(0) чтоб не дописывать в конец новую инфу
Я сейчас пробовал через QAbstractFormBuilder, та-же ерунда, только вид сзади получилась при сохранении.
--------------------------------------
Кстати по поводу isNull(), рекомендуется использовать isEmpty()
Цитировать
Все функции, за исключением isNull(), обращаются с нулевой строкой точно также, как с пустой. Например, toAscii().constData() возвращаят указатель на символ '\0' для нулевой строки (а не нулевой указатель), а QString() считается равным QString(""). Мы рекомендуем всегда пользоваться isEmpty() и избегать isNull().
Код:
QString().isNull();             // возвращает true
QString().isEmpty();            // возвращает true

QString("").isNull();           // возвращает false
QString("").isEmpty();          // возвращает true

QString("abc").isNull();        // возвращает false
QString("abc").isEmpty();       // возвращает false
Хотя не совсем в тему я написал про QString, а вы используете isNull() к QDomNode, но пусть висит, может кому и пригодится


Название: Re: Динамическая загрузка формы, путь движения развития
Отправлено: aliks-os от Июль 08, 2011, 08:29
В данном случае также проверяется наличие необходимого узла

bool QDomNode::isNull () const
Returns true if this node is null (i.e. if it has no type or contents); otherwise returns false

Так что это оправдано


Название: Re: Динамическая загрузка формы, путь движен&
Отправлено: iks от Июль 08, 2011, 08:38
В данном случае также проверяется наличие необходимого узла
Так что это оправдано
Ну я сразу поправился, =)
Хотя не совсем в тему я написал про QString, а вы используете isNull() к QDomNode, но пусть висит, может кому и пригодится


Название: Re: Динамическая загрузка формы, путь движения развития
Отправлено: aliks-os от Июль 08, 2011, 08:49
До конца не дочитал :)