Qt 勉強会 #13 @Tokyo 開催しました

2014年7月19日(土曜日)に Qt 勉強会 #13 @Tokyo株式会社 PTP さんのミーティングルームで開催しました。

簡単な自己紹介

今回は初めて参加された方が4名、大学生さんが1名、高校生が2名という感じでした。

もくもく

自己紹介の後は自由時間ということで、自分のやりたいことを進めながら、誰かが質問したり、なんかの発表があったりという形で進めていきました。

おやつ

QState クラスの API の追加

と提案をしてみたところメンテナの人から「Good idea」と言われたので(なんかやれって言われてる気がして)色々調べてみました。

QFinalState *s2 = new QFinalState();
s1->addTransition(&button, SIGNAL(clicked()), s2);

を以下のようにも記述できるようにするのが目標です。

QFinalState *s2 = new QFinalState();
s1->addTransition(&button, &QPushButton::clicked, s2);

QObject::connect の関数ポインタ版のコードはテンプレートを使った以下のようなものになっています。

template <typename Func1, typename Func2>
static inline QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
                        const typename QtPrivate::FunctionPointer<Func2>::Object *receiver, Func2 slot,
                        Qt::ConnectionType type = Qt::AutoConnection)
{
    typedef QtPrivate::FunctionPointer<Func1> SignalType;
    typedef QtPrivate::FunctionPointer<Func2> SlotType;

    Q_STATIC_ASSERT_X(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value, "No Q_OBJECT in the class with the signal");

    //compilation error if the arguments does not match.
    Q_STATIC_ASSERT_X(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount),
                "The slot requires more arguments than the signal provides.");
    Q_STATIC_ASSERT_X((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
                "Signal and slot arguments are not compatible.");
    Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible<typename SlotType::ReturnType, typename SignalType::ReturnType>::value),
                "Return type of the slot is not compatible with the return type of the signal.");

    const int *types = 0;
    if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)
        types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();

    return connectImpl(sender, reinterpret_cast<void **>(&signal),
                receiver, reinterpret_cast<void **>(&slot),
                new QtPrivate::QSlotObject<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
                        typename SignalType::ReturnType>(slot),
                type, types, &SignalType::Object::staticMetaObject);
}

シグナル/スロットの接続の場合には引数の数や型の静的チェックが行われていますね。

そこから呼ばれる connectImpl はこんな感じです。

QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signal,
                                             const QObject *receiver, void **slot,
                                             QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type,
                                             const int *types, const QMetaObject *senderMetaObject)
{
    if (!signal) {
        qWarning("QObject::connect: invalid null parameter");
        if (slotObj)
            slotObj->destroyIfLastRef();
        return QMetaObject::Connection();
    }
 
    int signal_index = -1;
    void *args[] = { &signal_index, signal };
    for (; senderMetaObject && signal_index < 0; senderMetaObject = senderMetaObject->superClass()) {
        senderMetaObject->static_metacall(QMetaObject::IndexOfMethod, 0, args);
        if (signal_index >= 0 && signal_index < QMetaObjectPrivate::get(senderMetaObject)->signalCount)
            break;
    }
    if (!senderMetaObject) {
        qWarning("QObject::connect: signal not found in %s", sender->metaObject()->className());
        slotObj->destroyIfLastRef();
        return QMetaObject::Connection(0);
    }
    signal_index += QMetaObjectPrivate::signalOffset(senderMetaObject);
    return QObjectPrivate::connectImpl(sender, signal_index, receiver, slot, slotObj, type, types, senderMetaObject);
}

関数ポインタからシグナル QMetaObject の中のシグナルの特定をしているので、同じ事をすると実現できそうです。

勉強会中にたどり着いたのはここまででしたが、暇を見つけて続きもやってみようかな?と思っています。

みんなの疑問/質問に答えよう

「質問あったら気軽に聞いてください」と言っても初心者の方や初めて来た方が自分から質問を切り出すのはなかなか難しいですよね。というわけで、Qt で何かを作っている上で困っていることや気になってることがないかを聞いて回ってみました。2周くらいしたかな?

Qt Quick 関連の質問であれば「本のこの辺見たら書いてあるよ」で済むのですが、C++ の方になると Qt 5 で書かれた参考になるコードがすぐには見つからないので結構めんどくさいですね。Qt 4 時代のコードであればあれこれ出せるものもあるのですが。。。

成果発表

その他、Qt から Twitter に投稿する方法を調べてる人がいたり、Phonon を使ったコードを QtMultimedia に移植していたり、ひたすら Qt Quick 本を写して勉強していたり、全然 Qt に関係ないことをしていたりと、今回もとても有意義な勉強会だったのではないでしょうか?

Togetter のまとめ

おすすめ