Russian Qt Forum

Qt => Общие вопросы => Тема начата: iRQSX от Август 07, 2010, 20:08



Название: Привязка скриптов к динамически загруженной форме
Отправлено: iRQSX от Август 07, 2010, 20:08
Есть такая вот задача... Можно конечно загрузить форму непосредственно из скрипра и пручною связать сигналы со слотами, но хотелось бы реализовать это иначе. Итак мысль такая:
1. загружаем форму
2. определяем какие на ней есть виджеты (QObjectList ui = myWidget->children();)
3. определяем какие сигналы есть у каждого виджета
4. связываем ВСЕ эти сигналы с ОДНИМ слотом
5. в слоте вычисляем какой послан сигнал
6. смотрим кто его послал
7. Запускаем соответствующий скрипт.
не могу понять как(да и можно ли вообще) реализовать пункты 3-5?



 


Название: Re: Привязка скриптов к динамически загруженной форме
Отправлено: asvil от Август 07, 2010, 20:37
ВСЕ с ОДНИМ слотом не получиться из-за несовместимости списков агрументов.

3. определяем какие сигналы есть у каждого виджета
4. связываем ВСЕ эти сигналы с ОДНИМ слотом
Код:
QObjectList children = parent.children();
QMetaMethod *metaMethod;
foreach (QObject *child, children) {
  for (int i = child.staticMetaObject.methodOffset(); i < child.staticMetaObject->methodCount(); ++i) {
    metaMethod = child.staticMetaObject.metaObject->method(i);
    if (metaMethod.methodType() == QMetaMethod::Signal) {
      connect(child, QString("%1%2").arg(QSIGNAL_CODE).arg(metaMethod.signature()).toLatin1().data()
              , this, SLOT(YOUR_SLOT));
    }
  }
}
5. в слоте вычисляем какой послан сигнал
Для сигналов с разными наборами параметров, нужно будет делать слоты с такими же наборами. Тем самым примерно знаем какой сигнал пришел.


Название: Re: Привязка скриптов к динамически загруженной форме
Отправлено: iRQSX от Август 07, 2010, 22:31
Начал копать и вот...
Код
C++ (Qt)
foreach (QObject *child, ui) {
       qDebug()<<child->metaObject()->className();
       for (int i= child->metaObject()->methodOffset();i<child->metaObject()->methodCount();i++){
           QMetaMethod metaMethod = child->metaObject()->method(i);
           if (metaMethod.methodType()==QMetaMethod::Signal) {
           c = metaMethod.signature();
           qDebug()<<c;
           }
       }
   }
 
Вывод приложения:
Код:
QFormInternal::TranslationWatcher 
QHBoxLayout
QPushButton
QLabel
linkActivated(QString)
linkHovered(QString)

Заменяем везде metaObject()-> на staticMetaObject. и :
Код:
QObject 
destroyed(QObject*)
destroyed()
QObject
destroyed(QObject*)
destroyed()
QObject
destroyed(QObject*)
destroyed()
QObject
destroyed(QObject*)
destroyed()
Два вопроса : в чем разница metaObject()-> и staticMetaObject.
и где butoon.clicked?
по поводу того  в чем разница metaObject()-> и staticMetaObject.
я так понял при вызове staticMetaObject мы работаем со статическим методом QObject а вот при использовании metaObject как раз обращаемся к данному конкретному экземпляру класса?

Есть такое предположение что в случае кнопки сигнал clicked() не ищется из за того что он реализован в предке Qpushbutton - QAbstractButton...


Название: Re: Привязка скриптов к динамически загруженной форме
Отправлено: iRQSX от Август 07, 2010, 23:58
Цитировать
Есть такое предположение что в случае кнопки сигнал clicked() не ищется из за того что он реализован в предке Qpushbutton - QAbstractButton...
разобрался... Весь цикл for надо выполнять в рекурсии еще и для qmetaobject->superclass что бы вычислить сигналы предков!


Название: Re: Привязка скриптов к динамически загруженной форме
Отправлено: iRQSX от Август 11, 2010, 20:25
в итоге вот код:
Код
C++ (Qt)
void windowloader::loadUI(QString uifile){
   QUiLoader loader;
   QFile file(uifile);
   file.open(QFile::ReadOnly);
   QWidget *myWidget = loader.load(&file);
   file.close();
   myWidget->show();
   myWidget->children();
   QObjectList ui = myWidget->children();
   foreach (QObject *child, ui) {
#ifdef QT_DEBUG
       qDebug()<<child->metaObject()->className();
#endif
 
       QList<QMetaMethod>* mthl = mapMethods(child->metaObject());
       for (int i=0;i<mthl->count();i++){
#ifdef QT_DEBUG
           qDebug()<<mthl->value(i).signature();
#endif
 
           qDebug()<< this->connect(child, QString("%1%2").arg(QSIGNAL_CODE).arg(mthl->value(i).signature()).toLatin1().data()
                         ,  SLOT(attachslot()));
 
       }
   }
}
 
QList<QMetaMethod>* windowloader::mapMethods(const QMetaObject* mo,  QList<QMetaMethod>* mthl){
   if (mthl==0){
       mthl = new QList<QMetaMethod>();
   }
 
   QRegExp rx("*()");
   rx.setPatternSyntax(QRegExp::Wildcard);
 
   for (int i= mo->methodOffset();i<mo->methodCount();i++){
       QMetaMethod metaMethod = mo->method(i);
       if ((metaMethod.methodType()==QMetaMethod::Signal)
           && rx.exactMatch(metaMethod.signature())) {
           mthl->append(metaMethod);
       }
   }
   if (mo->superClass()){
       mapMethods(mo->superClass(),mthl);
   }
   return mthl;
 
}
 
void windowloader::attachslot(){
 
   qDebug()<<"work";
}
 
}

Connect происходит(возвращает true), но при клике на кнопку не попадает в attachslot()... Что то не так сделал?
Сам спросил - сам отвечаю. Оказалось, что после загрузки формы и привязки сигналов к слоту сам класс удалялся...


Название: Re: Привязка скриптов к динамически загруженной форме
Отправлено: iRQSX от Август 14, 2010, 13:23
И все таки остается еще одна загвоздка... Так все таки можно ли как то узнать какой именно сигнал вызвал слот? обо без этого вся идея пропадает. По параметрам не вариант т.к. таким образом никак не отличить, например к кнопки, pressed() released() clicked() что само собой нехорошо...


Название: Re: Привязка скриптов к динамически загруженной форме
Отправлено: asvil от Август 15, 2010, 00:24
*Удалено*


Название: Re: Привязка скриптов к динамически загруженной форме
Отправлено: iRQSX от Сентябрь 29, 2010, 01:14
В таком случае единственный рациональный вариант реализовывать свой слот для каждого сигнала, по это по моему слишком. Вообще вся заварушка для того что бы сам скрипт был максимально прост для написания, хотелось избежать команд типа connect и т.п.   Посмотрел пример QtScript Calculator и Бланшета, вобщем то в том же калькуляторе все сделано красиво, но в скрипте приходится заводить класс и реализовывать у него слоты, причем в виде
Код
C++ (Qt)
Calculator.prototype.clearAll = function()
вместо привычного
Код
C++ (Qt)
function clearAll ()
Что может быть непонятно для неподготовленного пользователя(а скрипт по хорошему должен смочь написать даже он). Может можно как то еще упростить синтаксис скрипта, а заодно избавиться от connect()?


Название: Re: Привязка скриптов к динамически загруженной форме
Отправлено: Denjs от Сентябрь 29, 2010, 12:53
ВСЕ с ОДНИМ слотом не получиться из-за несовместимости списков агрументов.
Можно подключать сигналы с "более длинной сигнатурой" к слотам с "менее длинной сигнатурой"
 - важно что бы начальные параметры, описанные в сигнатуре слота совпадали.
Если же слот с пустым списком параметров - то к нему можно подключить любой сигнал. вопрос только в том конечно нужны ли вам некоторые сигналы без параметров? кроме того и смешение событий в таком варианте - не самое хорошее что можно придумать.. имхо...

И все таки остается еще одна загвоздка... Так все таки можно ли как то узнать какой именно сигнал вызвал слот? обо без этого вся идея пропадает. По параметрам не вариант т.к. таким образом никак не отличить, например к кнопки, pressed() released() clicked() что само собой нехорошо...
>>Так все таки можно ли как то узнать какой именно сигнал вызвал слот?
Можно. Есть во первых класс QSignalMapper. Используйте его для "переиспускания" сигналов с дополнительной строковой "меткой".
Во вторых, не совсем конечно то что надо, но есть функция QObject* QObject::sender() доступная в слоте, но только если сигнал испущен не через квотед-коннектион.