Russian Qt Forum

Qt => Общие вопросы => Тема начата: serg_hd от Апрель 01, 2010, 22:09



Название: Qt и флаги
Отправлено: serg_hd от Апрель 01, 2010, 22:09
Каким образом в Qt реализованы флаги (напр. Qt::QueuedConnection) и доступ к ним? Накидал:
Код
enum enType
{
flag1,
flag2
};
 
namespace Qt
{
enType str; //тут неправильно
}
 
Флаги это, по-идее, элементы enum. Но как к ним добраться через оператор разрешения ("::")?


Название: Re: Qt и флаги
Отправлено: BRE от Апрель 01, 2010, 22:15
Код
namespace Qt
{
enum enType
{
flag1,
flag2
};
 
}
 
int val = Qt::flag1;
 


Название: Re: Qt и флаги
Отправлено: SABROG от Апрель 01, 2010, 22:22
Вообще сама область видимости Qt очень интересно сделана. С точки зрения экспорта из библиотек Qt это класс, а с точки зрения подключения в качестве хедера это обычный namespace. Вот бы найти QMetaObject класса Qt, тогда я бы мог для большинства флагов получать текстовые названия энумов для вывода отладки. Только где ж взять указатель на экземпляр класса Qt, если такой существует...

QMetaObject точно существует для Qt: moc_qnamespace.cpp


Название: Re: Qt и флаги
Отправлено: serg_hd от Апрель 01, 2010, 22:33
Да, меня подобная тематика тоже изначально заинтересовала. Спасиб за ответ.


Название: Re: Qt и флаги
Отправлено: niXman от Апрель 01, 2010, 22:55
так же, перечисления могут быть анонимными:
Код
C++ (Qt)
namespace qt {
   enum {
       one,
       two
   };
};
...
int v = qt::one;
 
в с++, по умолчанию, перечисления являются целыми(int)
но если перечисление, декларировано как в примере выше, то мы не сможем его использовать как тип:

Код
C++ (Qt)
void func(qt v) { // так нельзя. потому что qt, не является типом. это нэймспейс.
}
 

и по поводу нэймспейсов: они могут быть анонимные. для чего? - для того чтоб ограничить область видимости одним файлом. иногда просто необходимо. можно конечно придумать уникальное имя для этого нэймспейса, которое небудет перекрываться ни с одним другим. но, нужно обладать не шуточной фантазией, чтоб придумать 100 уникальных имен ;)
пример file1.h :
Код
C++ (Qt)
namespace {
  const std::string str = "blablabla";
};
 
// in the body of any function
std::string str1 = "oops..." + str;
 
но если file1.h подключить в file2.h, то переменной str, в нем существовать не будет.


Название: Re: Qt и флаги
Отправлено: serg_hd от Апрель 01, 2010, 22:58
полезно!


Название: Re: Qt и флаги
Отправлено: SABROG от Апрель 01, 2010, 23:57
Да, меня подобная тематика тоже изначально заинтересовала. Спасиб за ответ.

Готово. Удалось (http://vingrad.ru/blogs/sabrog/2010/04/01/qt-462-perevod-znacheniya-perechisleniya-v-stroku-enum-to-string) таки сделать то, что было в голове около года.


Название: Re: Qt и флаги
Отправлено: niXman от Апрель 02, 2010, 00:06
супер!
только сегодня об это думал)


Название: Re: Qt и флаги
Отправлено: kuzulis от Апрель 02, 2010, 07:17
А я думал, что всё гораздо проще и уже собирался делать так как в QIODevice сделано, т.е. писать что-то вроде:
Код:
...
    enum OpenModeFlag {
        NotOpen = 0x0000,
        ReadOnly = 0x0001,
        WriteOnly = 0x0002,
        ReadWrite = ReadOnly | WriteOnly,
        Append = 0x0004,
        Truncate = 0x0008,
        Text = 0x0010,
        Unbuffered = 0x0020
    };
    Q_DECLARE_FLAGS(OpenMode, OpenModeFlag)
...

Думал - что это и есть решение проблемы! А оказывается  - всё не так?


Название: Re: Qt и флаги
Отправлено: SimpleSunny от Апрель 02, 2010, 08:07
OFFTOPIC
Блин, и не знал про SecretsOfQtFull.pdf, может кто-нить выложит? Так как весь http://labs.trolltech.com/page/Projects/DevDays/DevDays2007 недоступен почему-то, а интересно что там внутри :)


Название: Re: Qt и флаги
Отправлено: SABROG от Апрель 02, 2010, 08:24
OFFTOPIC
Блин, и не знал про SecretsOfQtFull.pdf, может кто-нить выложит? Так как весь http://labs.trolltech.com/page/Projects/DevDays/DevDays2007 недоступен почему-то, а интересно что там внутри :)

Выложил (http://www.sendspace.com/file/sd0fmv) все архивы, давно как-то скачивал.

Цитировать
Думал - что это и есть решение проблемы! А оказывается  - всё не так?
Дублировать перечисления Qt в то время как они статические, а значит общие для всех классов QObject'a? Вариант конечно, но скорее для безвыходной ситуации, если тролли что-то поменяют и метод перестанет работать.


Название: Re: Qt и флаги
Отправлено: kuzulis от Апрель 02, 2010, 09:43
Цитировать
Дублировать перечисления Qt в то время как они статические, а значит общие для всех классов QObject'a? Вариант конечно, но скорее для безвыходной ситуации, если тролли что-то поменяют и метод перестанет работать.

Ненене.. Я другое имел ввиду.

К примеру создаю свой класс и в нём объявляю енумы:

MyClass.h
Код:
...
    enum MyModeFlag {
        MyFlag1,
        MyFlag2,
        ....
        MyFlagN
    };
...

а потом сделать:
Код:
...
    Q_DECLARE_FLAGS(MyMode, MyModeFlag)
...

т.е. я думал, что этот "волшебный" макрос Q_DECLARE_FLAGS - сам всё там делает, т.е. при компиляции , moc или нечто иное, парсит MyClass.h ищет задекларированные флаги этим макросом и присваивает им "текстовые" имена.. т.е парсит слова MyFlag1, MyFlag2 и т.п. и внутрях у себя уже создает нужные привязки.. или как то так :)


Название: Re: Qt и флаги
Отправлено: SABROG от Апрель 02, 2010, 13:18
т.е. я думал, что этот "волшебный" макрос Q_DECLARE_FLAGS - сам всё там делает, т.е. при компиляции ,

Правильно думал, только флаги и перечисления немного разные вещи. Например для обычных перечислений нужно использовать макрос Q_ENUMS(), для флагов на основе перечислений Q_DECLARE_FLAGS. Но это всё решения, которые предназначены для пользовательских типов. Я сейчас говорю о готовых перечислениях внутри Qt.


Название: Re: Qt и флаги
Отправлено: kuzulis от Апрель 02, 2010, 13:33
Цитировать
Правильно думал, только флаги и перечисления немного разные вещи. Например для обычных перечислений нужно использовать макрос Q_ENUMS(), для флагов на основе перечислений Q_DECLARE_FLAGS. Но это всё решения, которые предназначены для пользовательских типов. Я сейчас говорю о готовых перечислениях внутри Qt.

хм.. что-то не выходит...

вот коды:
MyClass.h
Код:

#include <QObject>

class MyClass : public QObject
{
    Q_OBJECT
public:
    MyClass(QObject *parent = 0);

        enum MyModeFlag {
        Mode1 = 0,
        Mode2 = 1,
        Mode3 = 2
    };
    Q_DECLARE_FLAGS(MyMode, MyModeFlag)

    void setMode(MyClass::MyMode m);
    MyClass::MyMode getMode() const;

private:
    MyClass::MyMode m_mode;
};

MyClass.cpp
Код:
MyClass::MyClass(QObject *parent)
        : QObject(parent), m_mode(MyClass::Mode1)
{
}

void MyClass::setMode(MyClass::MyMode m)
{
    m_mode = m;
}

MyClass::MyMode MyClass::getMode() const
{
    return m_mode;
}


main.cpp
Код:
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    MyClass mc;

    qDebug() << "Default mode: " << mc.getMode();

    mc.setMode(MyClass::Mode3);

    qDebug() << "New mode: " << mc.getMode();

    return a.exec();
}

при запуске выводит:
Цитировать
...
Default mode:  0
New mode:  2
...

а нужно что бы было типа:
Цитировать
...
Default mode:  MyMode( "MyFlag1" )
New mode:  MyMode( "MyFlag3" )
...

что нужно подправить? :)

Прикрепляю проект


Название: Re: Qt и флаги
Отправлено: SABROG от Апрель 02, 2010, 14:08
Цитировать
что нужно подправить?

Много чего. Вот пример:

Код
C++ (Qt)
#include <QtCore/QtGlobal>
#include <QtCore/QtDebug>
#include <QtCore/QMetaObject>
#include <QtCore/QMetaEnum>
 
class Programmer : public QObject
{
   Q_OBJECT
public:
   enum Language {ASM, C, CPP, PASCAL, FORTRAN, BASIC, JAVA};
   Q_ENUMS(Language)
};
 
int main(int argc, char *argv[])
{
   const QMetaObject &mo = Programmer::staticMetaObject;
   int index = mo.indexOfEnumerator("Language");
   QMetaEnum me = mo.enumerator(index);
 
   Programmer::Language p = Programmer::CPP;
   Programmer::Language l= static_cast<Programmer::Language>(me.keyToValue("CPP"));
 
   qDebug() << me.valueToKey(p) << ":" << l;
   return 0;
}
 
#include "main.moc"
 
 


Название: Re: Qt и флаги
Отправлено: kuzulis от Апрель 02, 2010, 14:20
Цитировать
Много чего. Вот пример:
Не, это нечто не то...  (ИМХО) Я проверил вывод.

--

Нужно чтобы при qDebug() в консоль выдавалось "текстовое" представление флага/перечисления, но реально значение этого флага/перечисления было бы целым! т.е. как по аналогии с QAbstractSocket, QFile  и т.п.

-----

УРА! Понял как это делается, вот прикрепляю проект.


Название: Re: Qt и флаги
Отправлено: SABROG от Апрель 02, 2010, 15:35
Ааа, ты про реализацию оператора << для QDebug в своем классе...

Кстати гораздо удобней будет все-таки реализовывать вывод текстового названия через QMetaEnum, несмотря на то, что тролли захардкодили строки в исходнике ручками. Самому же потом легче будет переименовывать или добавлять новые перечисления не меняя строки в "QDebug operator<<".


Название: Re: Qt и флаги
Отправлено: kuzulis от Апрель 02, 2010, 17:26
Цитировать
Кстати гораздо удобней будет все-таки реализовывать вывод текстового названия через QMetaEnum, несмотря на то, что тролли захардкодили строки в исходнике ручками. Самому же потом легче будет переименовывать или добавлять новые перечисления не меняя строки в "QDebug operator<<".
Если не трудно, то приведи,пжлста, конкретный пример кода (проект) в котором бы это было реализовано..  Применительно к тому проекту что я прикрепил.. А то что-то я не въеду.


Название: Re: Qt и флаги
Отправлено: SABROG от Апрель 02, 2010, 23:02
Если не трудно, то приведи,пжлста, конкретный пример кода (проект) в котором бы это было реализовано..  Применительно к тому проекту что я прикрепил.. А то что-то я не въеду.

Вот.

Код
C++ (Qt)
int main(int argc, char* argv[])
{
   MyClass mc;
 
   qDebug() << "Default mode: " << mc.mode();
 
   mc.setMode(MyClass::Option4);
 
   qDebug() << "New mode: " << mc.mode();
 
   mc.setMode(MyClass::Option1 | MyClass::Option3 | MyClass::Option5);
   qDebug() << "Combined flags: " << mc.mode();
 
   return 0;
}
 
 

Код:
Default mode:  "NoOptions" 0
New mode:  "Option4" 8
Combined flags:  "Option1|Option3|Option5" 21


Название: Re: Qt и флаги
Отправлено: SASA от Апрель 03, 2010, 13:52
Вот бы найти QMetaObject класса Qt

staticQtMetaObject

Был найден в каких-то релизация проперти браузера.


Название: Re: Qt и флаги
Отправлено: SABROG от Апрель 03, 2010, 15:32
Вот бы найти QMetaObject класса Qt

staticQtMetaObject

Был найден в каких-то релизация проперти браузера.


Судя по всему Вы тему не полностью читали, я уже все нашел и выложил пример.