Example #1
0
bool FixtureGroup::assignFixture(quint32 id, const QLCPoint& pt)
{
    Fixture* fxi = doc()->fixture(id);
    Q_ASSERT(fxi != NULL);
    QLCPoint tmp = pt;
    int headAddedcount = 0;

    for (int i = 0; i < fxi->heads(); i++)
    {
        if (pt.isNull())
        {
            if (assignHead(pt, GroupHead(fxi->id(), i)) == true)
                headAddedcount++;
        }
        else
        {
            if (assignHead(tmp, GroupHead(fxi->id(), i)) == true)
                headAddedcount++;

            tmp.setX(tmp.x() + 1);
            if (tmp.x() >= size().width())
            {
                tmp.setX(0);
                tmp.setY(tmp.y() + 1);
            }
        }
    }

    return headAddedcount ? true : false;
}
void FixtureGroup_Test::resignFixture()
{
    FixtureGroup grp(m_doc);
    grp.setSize(QSize(4, 4));
    for (quint32 id = 0; id < 16; id++)
    {
        Fixture* fxi = new Fixture(m_doc);
        fxi->setChannels(1);
        m_doc->addFixture(fxi);
        grp.assignFixture(fxi->id());
    }
    QCOMPARE(grp.headList().size(), 16);

    // Remove a fixture
    grp.resignFixture(13);
    QCOMPARE(grp.headList().size(), 15);
    QVERIFY(grp.headList().contains(13) == false);
    QVERIFY(grp.headHash().contains(QLCPoint(1, 3)) == false);

    // Remove a nonexistent fixture
    grp.resignFixture(42);
    QCOMPARE(grp.headList().size(), 15);
    QVERIFY(grp.headList().contains(42) == false);
    QVERIFY(grp.headHash().contains(QLCPoint(1, 3)) == false);

    // Test that the gap is again filled
    Fixture* fxi = new Fixture(m_doc);
    fxi->setChannels(1);
    m_doc->addFixture(fxi, 42);
    grp.assignFixture(42);
    QCOMPARE(grp.headList().size(), 16);
    QVERIFY(grp.headList().contains(GroupHead(42, 0)) == true);
    QVERIFY(grp.headHash().contains(QLCPoint(1, 3)) == true);
    QCOMPARE(grp.headHash()[QLCPoint(1, 3)], GroupHead(42, 0));
}
Example #3
0
void EFXFixture_Test::save()
{
    EFX e(m_doc);
    EFXFixture ef(&e);
    ef.setHead(GroupHead(56, 7));
    ef.setDirection(EFX::Backward);

    QDomDocument doc;
    QDomElement root = doc.createElement("EFX");

    QVERIFY(ef.saveXML(&doc, &root) == true);

    QDomElement tag = root.firstChild().toElement();
    QVERIFY(tag.tagName() == "Fixture");

    tag = tag.firstChild().toElement();
    QVERIFY(tag.tagName() == "ID");
    QVERIFY(tag.text() == "56");

    tag = tag.nextSibling().toElement();
    QVERIFY(tag.tagName() == "Head");
    QVERIFY(tag.text() == "7");

    tag = tag.nextSibling().toElement();
    QVERIFY(tag.tagName() == "Direction");
    QVERIFY(tag.text() == "Backward");
}
Example #4
0
void FixtureGroup::assignFixture(quint32 id, const QLCPoint& pt)
{
    Fixture* fxi = doc()->fixture(id);
    Q_ASSERT(fxi != NULL);
    for (int i = 0; i < fxi->heads(); i++)
        assignHead(pt, GroupHead(fxi->id(), i));
}
void FixtureGroup_Test::save()
{
    FixtureGroup grp(m_doc);
    grp.setSize(QSize(4, 5));
    grp.setName("Pertti Pasanen");
    grp.setId(99);
    for (quint32 id = 0; id < 32; id++)
    {
        Fixture* fxi = new Fixture(m_doc);
        fxi->setChannels(1);
        m_doc->addFixture(fxi);
        grp.assignFixture(fxi->id());
    }

    QDomDocument doc;
    QDomElement root = doc.createElement("Foo");

    QVERIFY(grp.saveXML(&doc, &root) == true);
    QDomElement tag = root.firstChild().toElement();
    QCOMPARE(tag.tagName(), QString("FixtureGroup"));
    QCOMPARE(tag.attribute("ID"), QString("99"));

    int size = 0, name = 0, fixture = 0;

    QDomNode node = tag.firstChild();
    while (node.isNull() == false)
    {
        QDomElement tag = node.toElement();
        if (tag.tagName() == "Size")
        {
            QCOMPARE(tag.attribute("X").toInt(), 4);
            QCOMPARE(tag.attribute("Y").toInt(), 5);
            size++;
        }
        else if (tag.tagName() == "Name")
        {
            QCOMPARE(tag.text(), QString("Pertti Pasanen"));
            name++;
        }
        else if (tag.tagName() == "Head")
        {
            quint32 id = tag.attribute("Fixture").toUInt();
            int head = tag.text().toInt();
            QLCPoint pt(tag.attribute("X").toInt(), tag.attribute("Y").toInt());
            QCOMPARE(grp.head(pt), GroupHead(id, head));
            fixture++;
        }
        else
        {
            QFAIL(QString("Unexpected tag in FixtureGroup: %1").arg(tag.tagName()).toUtf8().constData());
        }

        node = node.nextSibling();
    }

    QCOMPARE(size, 1);
    QCOMPARE(name, 1);
    QCOMPARE(fixture, 32);
}
Example #6
0
void EFXFixture_Test::isValid()
{
    EFX e(m_doc);
    EFXFixture ef(&e);

    QVERIFY(ef.isValid() == false);

    ef.setHead(GroupHead(0,0));
    QVERIFY(ef.isValid() == true);
}
Example #7
0
void VCXYPad_Test::fixtures()
{
    QWidget w;

    VCXYPad pad(&w, m_doc);

    VCXYPadFixture xyf1(m_doc);
    xyf1.setHead(GroupHead(1,0));

    pad.appendFixture(xyf1);
    QCOMPARE(pad.m_fixtures.size(), 1);
    pad.appendFixture(xyf1);
    QCOMPARE(pad.m_fixtures.size(), 1);

    VCXYPadFixture xyf2(m_doc);
    xyf2.setHead(GroupHead(2,5));

    pad.appendFixture(xyf2);
    QCOMPARE(pad.m_fixtures.size(), 2);
    pad.appendFixture(xyf2);
    QCOMPARE(pad.m_fixtures.size(), 2);
    pad.appendFixture(xyf1);
    QCOMPARE(pad.m_fixtures.size(), 2);

    pad.removeFixture(GroupHead(3,0));
    QCOMPARE(pad.m_fixtures.size(), 2);

    pad.removeFixture(GroupHead(1,0));
    QCOMPARE(pad.m_fixtures.size(), 1);
    QCOMPARE(pad.m_fixtures[0].head().fxi, quint32(2));
    QCOMPARE(pad.m_fixtures[0].head().head, 5);

    pad.appendFixture(xyf1);
    QCOMPARE(pad.m_fixtures.size(), 2);

    pad.clearFixtures();
    QCOMPARE(pad.m_fixtures.size(), 0);

    // Invalid fixture
    VCXYPadFixture xyf3(m_doc);
    pad.appendFixture(xyf3);
    QCOMPARE(pad.m_fixtures.size(), 0);
}
void VCXYPadFixtureEditor_Test::accept()
{
    QList <VCXYPadFixture> list;

    VCXYPadFixture fxi(m_doc);
    fxi.setDisplayMode(VCXYPadFixture::Percentage);

    fxi.setHead(GroupHead(0, 0));
    fxi.setX(0, 1, false);
    fxi.setY(0, 1, false);
    list << fxi;

    fxi.setHead(GroupHead(1, 0));
    fxi.setX(0.5, 0.6, true);
    fxi.setY(0.5, 0.6, true);
    list << fxi;

    VCXYPadFixtureEditor fe(NULL, list);
    fe.m_xMin->setValue(10);
    fe.m_xMax->setValue(20);
    fe.m_yMin->setValue(30);
    fe.m_yMax->setValue(40);
    fe.accept();
    QCOMPARE(fe.m_xMin->value(), 10);
    QCOMPARE(fe.m_xMax->value(), 20);
    QCOMPARE(fe.m_yMin->value(), 30);
    QCOMPARE(fe.m_yMax->value(), 40);

    list = fe.fixtures();
    QCOMPARE(list[0].head().fxi, quint32(0));
    QCOMPARE(list[0].head().head, 0);
    QCOMPARE(list[0].xMin(), qreal(0.1));
    QCOMPARE(list[0].xMax(), qreal(0.2));
    QCOMPARE(list[0].yMin(), qreal(0.3));
    QCOMPARE(list[0].yMax(), qreal(0.4));
    QCOMPARE(list[1].head().fxi, quint32(1));
    QCOMPARE(list[1].head().head, 0);
    QCOMPARE(list[1].xMin(), qreal(0.1));
    QCOMPARE(list[1].xMax(), qreal(0.2));
    QCOMPARE(list[1].yMin(), qreal(0.3));
    QCOMPARE(list[1].yMax(), qreal(0.4));
}
Example #9
0
void EFXFixture_Test::startOffset()
{
    EFX e(m_doc);
    EFXFixture ef(&e);
    ef.setHead(GroupHead(0,0));

    QCOMPARE(0, ef.startOffset());
    for(int i = 0; i < 360; i += 90)
    {
        ef.setStartOffset(i);
        QCOMPARE(i, ef.startOffset());
    }
}
Example #10
0
void VCXYPad_Test::copy()
{
    QWidget w;

    VCFrame parent(&w, m_doc);
    VCXYPad pad(&parent, m_doc);
    pad.setCaption("Dingdong");
    QSize size(80, 80);
    QPointF pt(50, 30);
    pad.m_area->setPosition(pt);

    VCXYPadFixture xyf1(m_doc);
    xyf1.setHead(GroupHead(1,5));
    pad.appendFixture(xyf1);

    VCXYPadFixture xyf2(m_doc);
    xyf2.setHead(GroupHead(2,7));
    pad.appendFixture(xyf2);

    VCXYPadFixture xyf3(m_doc);
    xyf3.setHead(GroupHead(3,9));
    pad.appendFixture(xyf3);

    VCXYPad* copy = qobject_cast<VCXYPad*> (pad.createCopy(&parent));
    QVERIFY(copy != NULL);
    QCOMPARE(copy->m_fixtures.size(), 3);
    QVERIFY(copy->m_fixtures[0] == xyf1);
    QVERIFY(copy->m_fixtures[1] == xyf2);
    QVERIFY(copy->m_fixtures[2] == xyf3);

    QVERIFY(&copy->m_fixtures[0] != &xyf1);
    QVERIFY(&copy->m_fixtures[1] != &xyf2);
    QVERIFY(&copy->m_fixtures[2] != &xyf3);

    QCOMPARE(copy->m_area->position(), pt);
    QCOMPARE(copy->size(), pad.size());
    QCOMPARE(copy->caption(), QString("Dingdong"));
}
Example #11
0
void EFXFixture_Test::setPointLedBar()
{
    EFX e(m_doc);
    EFXFixture ef(&e);
    ef.setHead(GroupHead(m_fixtureLedBar, 0));

    QList<Universe*> ua;
    ua.append(new Universe(0, new GrandMaster()));
    ef.setPoint(ua, 5.4, 1.5); // PMSB: 5, PLSB: 0.4, TMSB: 1 (102), TLSB: 0.5(127)
    QCOMPARE((int)ua[0]->preGMValues()[0], 1); /* Tilt */
    QCOMPARE((int)ua[0]->preGMValues()[1], 0);
    QCOMPARE((int)ua[0]->preGMValues()[2], 0);
    QCOMPARE((int)ua[0]->preGMValues()[3], 0);
}
Example #12
0
void EFXFixture_Test::publicProperties()
{
    EFX e(m_doc);
    EFXFixture ef(&e);

    ef.setHead(GroupHead(19, 5));
    QVERIFY(ef.head().fxi == 19);
    QVERIFY(ef.head().head == 5);

    ef.setHead(GroupHead());
    QVERIFY(ef.head().fxi == Fixture::invalidId());

    ef.setDirection(EFX::Backward);
    QVERIFY(ef.direction() == EFX::Backward);
    QVERIFY(ef.m_runTimeDirection == EFX::Backward);

    ef.setDirection(EFX::Forward);
    QVERIFY(ef.direction() == EFX::Forward);
    QVERIFY(ef.m_runTimeDirection == EFX::Forward);

    ef.setFadeIntensity(69);
    QVERIFY(ef.fadeIntensity() == 69);
}
void VCXYPadFixtureEditor_Test::initial()
{
    QList <VCXYPadFixture> list;

    VCXYPadFixture fxi(m_doc);
    fxi.setDisplayMode(VCXYPadFixture::Percentage);

    fxi.setHead(GroupHead(0, 0));
    fxi.setX(0.1, 0.2, false);
    fxi.setY(0.3, 0.4, true);
    list << fxi;

    fxi.setHead(GroupHead(1, 0));
    fxi.setX(0, 1, true);
    fxi.setY(0, 1, false);
    list << fxi;

    VCXYPadFixtureEditor fe(NULL, list);
    QCOMPARE(fe.fixtures(), list);
    QCOMPARE(fe.m_xMin->value(), 10);
    QCOMPARE(fe.m_xMax->value(), 20);
    QCOMPARE(fe.m_xReverse->isChecked(), false);
    QCOMPARE(fe.m_yMin->value(), 30);
    QCOMPARE(fe.m_yMax->value(), 40);
    QCOMPARE(fe.m_yReverse->isChecked(), true);

    list.clear();

    VCXYPadFixtureEditor fe2(NULL, list);
    QCOMPARE(fe2.fixtures().isEmpty(), true);
    QCOMPARE(fe2.m_xMin->value(), 0);
    QCOMPARE(fe2.m_xMax->value(), 100);
    QCOMPARE(fe2.m_xReverse->isChecked(), false);
    QCOMPARE(fe2.m_yMin->value(), 0);
    QCOMPARE(fe2.m_yMax->value(), 100);
    QCOMPARE(fe2.m_yReverse->isChecked(), false);
}
Example #14
0
void FixtureGroup_Test::resignHead()
{
    FixtureGroup grp(m_doc);
    grp.setSize(QSize(4, 4));
    Fixture* fxi = new Fixture(m_doc);
    fxi->setChannels(16);
    m_doc->addFixture(fxi);

    for (quint32 id = 0; id < 16; id++)
        grp.assignFixture(fxi->id());
    QCOMPARE(grp.headList().size(), 16);

    QSignalSpy spy(&grp, SIGNAL(changed(quint32)));
    QCOMPARE(grp.resignHead(QLCPoint(0, 0)), true);
    QCOMPARE(grp.headList().size(), 15);
    QCOMPARE(grp.headHash().contains(QLCPoint(0, 0)), false);
    QCOMPARE(spy.size(), 1);

    QCOMPARE(grp.resignHead(QLCPoint(0, 0)), false);
    QCOMPARE(grp.headList().size(), 15);
    QCOMPARE(grp.headHash().contains(QLCPoint(0, 0)), false);
    QCOMPARE(spy.size(), 1);

    QCOMPARE(grp.resignHead(QLCPoint(15, 0)), false);
    QCOMPARE(grp.headList().size(), 15);
    QCOMPARE(grp.headHash().contains(QLCPoint(15, 0)), false);
    QCOMPARE(grp.headHash().contains(QLCPoint(0, 0)), false);
    QCOMPARE(spy.size(), 1);

    // Assign the head back to 0, 0
    grp.assignHead(QLCPoint(0, 0), GroupHead(fxi->id(), 0));
    QCOMPARE(spy.size(), 2);

    // Verify that head & fixtures work properly
    for (int x = 0; x < 4; x++)
    {
        for (int y = 0; y < 4; y++)
        {
            QLCPoint pt(x, y);
            QCOMPARE(grp.resignHead(pt), true);
            if (x == 3 && y == 3)
                QCOMPARE(grp.fixtureList().size(), 0);
            else
                QCOMPARE(grp.fixtureList().size(), 1);
        }
    }

    QCOMPARE(spy.size(), 18);
}
Example #15
0
void FixtureGroup::assignFixture(quint32 id, const QLCPoint& pt)
{
    Fixture* fxi = doc()->fixture(id);
    Q_ASSERT(fxi != NULL);
    QLCPoint tmp = pt;

    for (int i = 0; i < fxi->heads(); i++)
    {
        if (pt.isNull())
        {
            assignHead(pt, GroupHead(fxi->id(), i));
        }
        else
        {
            assignHead(tmp, GroupHead(fxi->id(), i));
            tmp.setX(tmp.x() + 1);
            if (tmp.x() >= size().width())
            {
                tmp.setX(0);
                tmp.setY(tmp.y() + 1);
            }
        }
    }
}
Example #16
0
void VCXYPad_Test::modeChange()
{
    //UniverseArray ua(512);
    QWidget w;

    Fixture* fxi = new Fixture(m_doc);
    QLCFixtureDef* def = m_doc->fixtureDefCache()->fixtureDef("Futurelight", "DJScan250");
    QVERIFY(def != NULL);
    QLCFixtureMode* mode = def->modes().first();
    QVERIFY(mode != NULL);
    fxi->setFixtureDefinition(def, mode);
    m_doc->addFixture(fxi);

    VCXYPad pad(&w, m_doc);
    pad.show();
    w.show();
    pad.resize(QSize(200, 200));

    VCXYPadFixture xy(m_doc);
    xy.setHead(GroupHead(fxi->id(), 0));
    pad.appendFixture(xy);
    QCOMPARE(pad.fixtures().size(), 1);
    QCOMPARE(pad.fixtures()[0].m_xMSB, QLCChannel::invalid());
    QCOMPARE(pad.fixtures()[0].m_xLSB, QLCChannel::invalid());

    m_doc->setMode(Doc::Operate);
    QVERIFY(pad.fixtures()[0].m_xMSB != QLCChannel::invalid());
    QVERIFY(pad.fixtures()[0].m_yMSB != QLCChannel::invalid());
    QCOMPARE(m_doc->masterTimer()->m_dmxSourceList.size(), 1);
    QCOMPARE(m_doc->masterTimer()->m_dmxSourceList[0], &pad);
/*
    // FIXME !!
    pad.m_area->setPosition(QPoint(pad.m_area->width(), pad.m_area->height()));
    pad.writeDMX(m_doc->masterTimer(), &ua);
    QCOMPARE(ua.preGMValues()[0], char(255));
    QCOMPARE(ua.preGMValues()[1], char(255));

    pad.m_area->setPosition(QPoint(pad.m_area->width() / 2, pad.m_area->height() / 4));
    pad.writeDMX(m_doc->masterTimer(), &ua);
    QCOMPARE(ua.preGMValues()[0], char(128));
    QCOMPARE(ua.preGMValues()[1], char(64));
*/
    m_doc->setMode(Doc::Design);
    QCOMPARE(pad.fixtures()[0].m_xMSB, QLCChannel::invalid());
    QCOMPARE(pad.fixtures()[0].m_yMSB, QLCChannel::invalid());
    QCOMPARE(m_doc->masterTimer()->m_dmxSourceList.size(), 0);
}
Example #17
0
void EFXFixture_Test::stop()
{
    QList<Universe*> ua;
    ua.append(new Universe(0, new GrandMaster()));
    MasterTimerStub mts(m_doc, ua);

    EFX e(m_doc);
    e.setFadeInSpeed(1000);
    e.setFadeOutSpeed(2000);
    EFXFixture* ef = new EFXFixture(&e);
    ef->setHead(GroupHead(0,0));
    e.addFixture(ef);

    Fixture* fxi = m_doc->fixture(0);
    QVERIFY(fxi != NULL);

    e.preRun(&mts);

    // Not started yet
    ef->stop(&mts, ua);
    QCOMPARE(e.m_fader->m_channels.size(), 0);
    QCOMPARE(mts.fader()->m_channels.size(), 0);

    // Start
    ef->start(&mts, ua);
    QCOMPARE(e.m_fader->m_channels.size(), 1);
    FadeChannel fc;
    fc.setFixture(m_doc, fxi->id());
    fc.setChannel(fxi->masterIntensityChannel());
    QVERIFY(e.m_fader->m_channels.contains(fc) == true);

    // Then stop
    ef->stop(&mts, ua);
    QCOMPARE(e.m_fader->m_channels.size(), 0);

    // FadeChannels are handed over to MasterTimer's GenericFader
    QCOMPARE(mts.fader()->m_channels.size(), 1);
    QVERIFY(e.m_fader->m_channels.contains(fc) == false);
    QVERIFY(mts.m_fader->m_channels.contains(fc) == true);
    QCOMPARE(mts.m_fader->m_channels[fc].fadeTime(), uint(2000));

    e.postRun(&mts, ua);
}
Example #18
0
void EFXFixture_Test::nextStepSingleShot()
{
    QList<Universe*> ua;
    ua.append(new Universe(0, new GrandMaster()));
    MasterTimerStub mts(m_doc, ua);

    EFX e(m_doc);
    e.setDuration(1000); // 1s
    e.setRunOrder(EFX::SingleShot);

    EFXFixture* ef = new EFXFixture(&e);
    ef->setHead(GroupHead(0,0));
    e.addFixture(ef);

    /* Initialize the EFXFixture so that it can do math */
    ef->setSerialNumber(0);
    QVERIFY(ef->isValid() == true);
    QVERIFY(ef->isReady() == false);
    QVERIFY(ef->m_elapsed == 0);

    e.preRun(&mts);

    ef->reset();

    /* Run one cycle (50 steps) */
    uint max = MasterTimer::tick() * MasterTimer::frequency();
    for (uint i = MasterTimer::tick(); i < max; i += MasterTimer::tick())
    {
        ef->nextStep(&mts, ua);
        QVERIFY(ef->isReady() == false);
        QCOMPARE(ef->m_elapsed, i);
    }

    ef->nextStep(&mts, ua);

    /* Single-shot EFX should now be ready */
    QVERIFY(ef->isReady() == true);

    e.postRun(&mts, ua);
}
Example #19
0
void EFXFixture_Test::nextStepLoopZeroDuration()
{
    QList<Universe*> ua;
    ua.append(new Universe(0, new GrandMaster()));
    MasterTimerStub mts(m_doc, ua);

    EFX e(m_doc);
    e.setDuration(0); // 0s

    EFXFixture* ef = new EFXFixture(&e);
    ef->setHead(GroupHead(0,0));
    e.addFixture(ef);

    /* Initialize the EFXFixture so that it can do math */
    ef->setSerialNumber(0);
    QVERIFY(ef->isValid() == true);
    QVERIFY(ef->isReady() == false);
    QVERIFY(ef->m_elapsed == 0);

    e.preRun(&mts);

    /* Run two cycles (2 * tickms * freq) to see that Loop never quits */
    uint max = MasterTimer::tick() * MasterTimer::frequency();
    uint i = MasterTimer::tick();
    for (uint times = 0; times < 2; times++)
    {
        for (; i < max; i += MasterTimer::tick())
        {
            ef->nextStep(&mts, ua);
            QVERIFY(ef->isReady() == false); // Loop is never ready
            QCOMPARE(ef->m_elapsed, i);
        }

        // m_elapsed is NOT zeroed since there are no "rounds" when duration == 0
    }

    e.postRun(&mts, ua);
}
Example #20
0
void EFXFixture_Test::start()
{
    QList<Universe*> ua;
    ua.append(new Universe(0, new GrandMaster()));
    MasterTimerStub mts(m_doc, ua);

    EFX e(m_doc);
    e.setFadeInSpeed(1000);
    e.setFadeOutSpeed(2000);
    EFXFixture* ef = new EFXFixture(&e);
    ef->setHead(GroupHead(0,0));
    e.addFixture(ef);

    Fixture* fxi = m_doc->fixture(0);
    QVERIFY(fxi != NULL);

    e.preRun(&mts);

    // Fade intensity == 0, no need to do fade-in
    ef->setFadeIntensity(0);
    ef->start(&mts, ua);
    QCOMPARE(e.m_fader->m_channels.size(), 0);
    ef->m_started = false;

    // Fade intensity > 0, need to do fade-in
    ef->setFadeIntensity(1);
    ef->start(&mts, ua);
    QCOMPARE(e.m_fader->m_channels.size(), 1);

    FadeChannel fc;
    fc.setFixture(m_doc, fxi->id());
    fc.setChannel(fxi->masterIntensityChannel());
    QVERIFY(e.m_fader->m_channels.contains(fc) == true);
    QCOMPARE(e.m_fader->m_channels[fc].fadeTime(), uint(1000));

    e.postRun(&mts, ua);
}
Example #21
0
void FixtureGroup_Test::swap()
{
    FixtureGroup grp(m_doc);
    grp.setSize(QSize(4, 4));
    for (quint32 id = 0; id < 16; id++)
    {
        Fixture* fxi = new Fixture(m_doc);
        fxi->setChannels(1);
        m_doc->addFixture(fxi);
        grp.assignFixture(fxi->id());
    }
    QCOMPARE(grp.headList().size(), 16);

    QLCPoint pt1(0, 0);
    QLCPoint pt2(2, 1);
    QVERIFY(grp.headHash().contains(pt1) == true);
    QVERIFY(grp.headHash().contains(pt2) == true);
    QCOMPARE(grp.headHash()[pt1], GroupHead(0, 0));
    QCOMPARE(grp.headHash()[pt2], GroupHead(6, 0));

    // Switch places with two fixtures
    grp.swap(pt1, pt2);
    QVERIFY(grp.headHash().contains(pt1) == true);
    QVERIFY(grp.headHash().contains(pt2) == true);
    QCOMPARE(grp.headHash()[pt1], GroupHead(6, 0));
    QCOMPARE(grp.headHash()[pt2], GroupHead(0, 0));

    // Switch places with a fixture and an empty point
    pt2 = QLCPoint(500, 500);
    grp.swap(pt1, pt2);
    QVERIFY(grp.headHash().contains(pt1) == false);
    QVERIFY(grp.headHash().contains(pt2) == true);
    QCOMPARE(grp.headHash()[pt2], GroupHead(6, 0));

    // ...and back again
    grp.swap(pt1, pt2);
    QVERIFY(grp.headHash().contains(pt1) == true);
    QVERIFY(grp.headHash().contains(pt2) == false);
    QCOMPARE(grp.headHash()[pt1], GroupHead(6, 0));
}
Example #22
0
void VCXYPad_Test::saveXML()
{
    QWidget w;

    VCXYPad pad(&w, m_doc);
    pad.show();
    w.show();
    pad.setCaption("MyPad");
    pad.resize(QSize(150, 200));
    pad.move(QPoint(10, 20));
    pad.m_area->setPosition(QPointF(23, 45));
    pad.setInputSource(new QLCInputSource(0, 1), VCXYPad::panInputSourceId);
    pad.setInputSource(new QLCInputSource(2, 3), VCXYPad::tiltInputSourceId);
    QCOMPARE(pad.m_area->position(), QPointF(23, 45));
    QCOMPARE(pad.m_area->position(), QPointF(23, 45));

    VCXYPadFixture fixture1(m_doc);
    fixture1.setHead(GroupHead(11, 0));
    pad.appendFixture(fixture1);

    VCXYPadFixture fixture2(m_doc);
    fixture2.setHead(GroupHead(22, 0));
    pad.appendFixture(fixture2);

    QDomDocument xmldoc;
    QDomElement root = xmldoc.createElement("Root");
    xmldoc.appendChild(root);

    int fixture = 0, position = 0, wstate = 0, appearance = 0, pan = 0, tilt = 0;

    QVERIFY(pad.saveXML(&xmldoc, &root) == true);
    QDomNode node = root.firstChild();
    QCOMPARE(node.toElement().tagName(), QString("XYPad"));
    QCOMPARE(node.toElement().attribute("Caption"), QString("MyPad"));
    node = node.firstChild();
    while (node.isNull() == false)
    {
        QDomElement tag = node.toElement();
        if (tag.tagName() == "Fixture")
        {
            fixture++;
            QVERIFY(tag.attribute("ID") == QString("11") ||
                    tag.attribute("ID") == QString("22"));
            QVERIFY(tag.attribute("Head") == QString("0"));
            QCOMPARE(tag.childNodes().count(), 2);
        }
        else if (tag.tagName() == "Position")
        {
            position++;
            QFAIL("Legacy tag found in saved XML!");
        }
        else if (tag.tagName() == "Pan")
        {
            pan++;
            QCOMPARE(tag.attribute("Position"), QString("23"));
            QCOMPARE(tag.firstChild().toElement().attribute("Universe"), QString("0"));
            QCOMPARE(tag.firstChild().toElement().attribute("Channel"), QString("1"));
        }
        else if (tag.tagName() == "Tilt")
        {
            tilt++;
            QCOMPARE(tag.attribute("Position"), QString("45"));
            QCOMPARE(tag.firstChild().toElement().attribute("Universe"), QString("2"));
            QCOMPARE(tag.firstChild().toElement().attribute("Channel"), QString("3"));
        }
        else if (tag.tagName() == "WindowState")
        {
            wstate++;
        }
        else if (tag.tagName() == "Appearance")
        {
            appearance++;
        }
        else
        {
            QFAIL(QString("Unexpected tag: %1").arg(tag.tagName()).toUtf8().constData());
        }

        node = node.nextSibling();
    }

    QCOMPARE(fixture, 2);
    QCOMPARE(position, 0);
    QCOMPARE(pan, 1);
    QCOMPARE(tilt, 1);
    QCOMPARE(wstate, 1);
    QCOMPARE(appearance, 1);
}
Example #23
0
void VCXYPad_Test::loadXML()
{
    QWidget w;

    QDomDocument xmldoc;
    QDomElement root = xmldoc.createElement("XYPad");
    xmldoc.appendChild(root);

    QDomElement pos = xmldoc.createElement("Position");
    pos.setAttribute("X", "10");
    pos.setAttribute("Y", "20");
    root.appendChild(pos);

    QDomElement fxi = xmldoc.createElement("Fixture");
    fxi.setAttribute("ID", "69");
    fxi.setAttribute("Head", "96");
    root.appendChild(fxi);

    QDomElement x = xmldoc.createElement("Axis");
    x.setAttribute("ID", "X");
    x.setAttribute("LowLimit", "0.1");
    x.setAttribute("HighLimit", "0.5");
    x.setAttribute("Reverse", "True");
    fxi.appendChild(x);

    QDomElement y = xmldoc.createElement("Axis");
    y.setAttribute("ID", "Y");
    y.setAttribute("LowLimit", "0.2");
    y.setAttribute("HighLimit", "0.6");
    y.setAttribute("Reverse", "True");
    fxi.appendChild(y);

    QDomElement fxi2 = xmldoc.createElement("Fixture");
    fxi2.setAttribute("ID", "50");
    fxi2.setAttribute("Head", "55");
    root.appendChild(fxi2);

    QDomElement x2 = xmldoc.createElement("Axis");
    x2.setAttribute("ID", "X");
    x2.setAttribute("LowLimit", "0.0");
    x2.setAttribute("HighLimit", "1.0");
    x2.setAttribute("Reverse", "False");
    fxi2.appendChild(x2);

    QDomElement y2 = xmldoc.createElement("Axis");
    y2.setAttribute("ID", "Y");
    y2.setAttribute("LowLimit", "0.0");
    y2.setAttribute("HighLimit", "1.0");
    y2.setAttribute("Reverse", "False");
    fxi2.appendChild(y2);

    QDomElement wstate = xmldoc.createElement("WindowState");
    wstate.setAttribute("Width", "42");
    wstate.setAttribute("Height", "69");
    wstate.setAttribute("X", "3");
    wstate.setAttribute("Y", "4");
    wstate.setAttribute("Visible", "True");
    root.appendChild(wstate);

    QDomElement appearance = xmldoc.createElement("Appearance");
    QFont f(w.font());
    f.setPointSize(f.pointSize() + 3);
    QDomElement font = xmldoc.createElement("Font");
    QDomText fontText = xmldoc.createTextNode(f.toString());
    font.appendChild(fontText);
    appearance.appendChild(font);
    root.appendChild(appearance);

    QDomElement foobar = xmldoc.createElement("Foobar");
    root.appendChild(foobar);

    VCXYPad pad(&w, m_doc);
    QVERIFY(pad.loadXML(&root) == true);
    QCOMPARE(pad.m_fixtures.size(), 2);
    QCOMPARE(pad.pos(), QPoint(3, 4));
    QCOMPARE(pad.size(), QSize(42, 69));
    QCOMPARE(pad.m_area->position(), QPointF(10, 20));

    VCXYPadFixture fixture(m_doc);
    fixture.setHead(GroupHead(69, 96));
    QVERIFY(pad.m_fixtures.contains(fixture) == true);
    fixture.setHead(GroupHead(50, 55));
    QVERIFY(pad.m_fixtures.contains(fixture) == true);

    root.setTagName("YXPad");
    QVERIFY(pad.loadXML(&root) == false);
}
Example #24
0
void EFXFixture_Test::reset()
{
    EFX e(m_doc);

    EFXFixture* ef1 = new EFXFixture(&e);
    ef1->setHead(GroupHead(1,0));
    ef1->setSerialNumber(0);
    ef1->m_runTimeDirection = EFX::Forward;
    ef1->m_ready = true;
    ef1->m_elapsed = 1337;
    e.addFixture(ef1);

    EFXFixture* ef2 = new EFXFixture(&e);
    ef2->setHead(GroupHead(2,0));
    ef2->setSerialNumber(1);
    ef2->m_runTimeDirection = EFX::Forward;
    ef2->m_ready = true;
    ef2->m_elapsed = 13;
    e.addFixture(ef2);

    EFXFixture* ef3 = new EFXFixture(&e);
    ef3->setHead(GroupHead(3,0));
    ef3->setSerialNumber(2);
    ef3->setDirection(EFX::Forward);
    ef3->m_runTimeDirection = EFX::Backward;
    ef3->m_ready = true;
    ef3->m_elapsed = 69;
    e.addFixture(ef3);

    EFXFixture* ef4 = new EFXFixture(&e);
    ef4->setHead(GroupHead(4,0));
    ef4->setSerialNumber(3);
    ef4->setDirection(EFX::Forward);
    ef4->m_runTimeDirection = EFX::Backward;
    ef4->m_ready = true;
    ef4->m_elapsed = 42;
    e.addFixture(ef4);

    ef1->reset();
    QVERIFY(ef1->m_head.fxi == 1);
    QVERIFY(ef1->m_direction == EFX::Forward);
    QVERIFY(ef1->m_serialNumber == 0);
    QVERIFY(ef1->m_runTimeDirection == EFX::Forward);
    QVERIFY(ef1->m_ready == false);
    QVERIFY(ef1->m_elapsed == 0);

    ef2->reset();
    QVERIFY(ef2->m_head.fxi == 2);
    QVERIFY(ef2->m_direction == EFX::Forward);
    QVERIFY(ef2->m_serialNumber == 1);
    QVERIFY(ef2->m_runTimeDirection == EFX::Forward);
    QVERIFY(ef2->m_ready == false);
    QVERIFY(ef2->m_elapsed == 0);

    ef3->reset();
    QVERIFY(ef3->m_head.fxi == 3);
    QVERIFY(ef3->m_direction == EFX::Forward);
    QVERIFY(ef3->m_serialNumber == 2);
    QVERIFY(ef3->m_runTimeDirection == EFX::Forward);
    QVERIFY(ef3->m_ready == false);
    QVERIFY(ef3->m_elapsed == 0);

    ef4->reset();
    QVERIFY(ef4->m_head.fxi == 4);
    QVERIFY(ef4->m_direction == EFX::Forward);
    QVERIFY(ef4->m_serialNumber == 3);
    QVERIFY(ef4->m_runTimeDirection == EFX::Forward);
    QVERIFY(ef4->m_ready == false);
    QVERIFY(ef4->m_elapsed == 0);
}
Example #25
0
void VCXYPadProperties::slotAddClicked()
{
    /* Put all fixtures already present into a list of fixtures that
       will be disabled in the fixture selection dialog */
    QList <GroupHead> disabled;
    QTreeWidgetItemIterator twit(m_tree);
    while (*twit != NULL)
    {
        QVariant var((*twit)->data(KColumnFixture, Qt::UserRole));
        VCXYPadFixture fxi(m_doc, var);
        disabled << fxi.head();
        ++twit;
    }

    /* Disable all fixtures that don't have pan OR tilt channels */
    QListIterator <Fixture*> fxit(m_doc->fixtures());
    while (fxit.hasNext() == true)
    {
        Fixture* fixture(fxit.next());
        Q_ASSERT(fixture != NULL);

        // If a channel with pan or tilt group exists, don't disable this fixture
        if (fixture->channel(QLCChannel::Pan) == QLCChannel::invalid() &&
            fixture->channel(QLCChannel::Tilt) == QLCChannel::invalid())
        {
            // Disable all fixtures without pan or tilt channels
            disabled << fixture->id();
        }
        else
        {
            QVector <QLCFixtureHead> const& heads = fixture->fixtureMode()->heads();
            for (int i = 0; i < heads.size(); ++i)
            {
                if (heads[i].panMsbChannel() == QLCChannel::invalid() &&
                    heads[i].tiltMsbChannel() == QLCChannel::invalid() &&
                    heads[i].panLsbChannel() == QLCChannel::invalid() &&
                    heads[i].tiltLsbChannel() == QLCChannel::invalid())
                {
                    // Disable heads without pan or tilt channels
                    disabled << GroupHead(fixture->id(), i);
                }
            }
        }
    }

    /* Get a list of new fixtures to add to the pad */
    QTreeWidgetItem* item = NULL;
    FixtureSelection fs(this, m_doc);
    fs.setMultiSelection(true);
    fs.setSelectionMode(FixtureSelection::Heads);
    fs.setDisabledHeads(disabled);
    if (fs.exec() == QDialog::Accepted)
    {
        QListIterator <GroupHead> it(fs.selectedHeads());
        while (it.hasNext() == true)
        {
            VCXYPadFixture fxi(m_doc);
            fxi.setHead(it.next());
            item = new QTreeWidgetItem(m_tree);
            updateFixtureItem(item, fxi);
        }
    }

    if (item != NULL)
        m_tree->setCurrentItem(item);

    m_tree->resizeColumnToContents(KColumnFixture);
    m_tree->resizeColumnToContents(KColumnXAxis);
    m_tree->resizeColumnToContents(KColumnYAxis);
}
Example #26
0
void FixtureGroup_Test::assignFixture4x2()
{
    QLCPoint pt;
    FixtureGroup grp(m_doc);
    grp.setSize(QSize(4, 2));
    QCOMPARE(grp.headList().size(), 0);

    for (int i = 0; i < 11; i++)
    {
        QLCFixtureDef* def = m_doc->fixtureDefCache()->fixtureDef("Futurelight", "DJScan250");
        QVERIFY(def != NULL);
        QLCFixtureMode* mode = def->modes().first();
        QVERIFY(mode != NULL);

        Fixture* fxi = new Fixture(m_doc);
        fxi->setFixtureDefinition(def, mode);
        m_doc->addFixture(fxi);
    }

    grp.assignFixture(0);
    QCOMPARE(grp.headList().size(), 1);
    QCOMPARE(grp.size(), QSize(4, 2));
    pt = QLCPoint(0, 0);
    QVERIFY(grp.head(pt) == GroupHead(0, 0));

    grp.assignFixture(1);
    QCOMPARE(grp.headList().size(), 2);
    QCOMPARE(grp.size(), QSize(4, 2));
    pt = QLCPoint(0, 0);
    QVERIFY(grp.head(pt) == GroupHead(0, 0));
    pt = QLCPoint(1, 0);
    QVERIFY(grp.head(pt) == GroupHead(1, 0));

    grp.assignFixture(2);
    QCOMPARE(grp.headList().size(), 3);
    QCOMPARE(grp.size(), QSize(4, 2));
    pt = QLCPoint(0, 0);
    QVERIFY(grp.head(pt) == GroupHead(0, 0));
    pt = QLCPoint(1, 0);
    QVERIFY(grp.head(pt) == GroupHead(1, 0));
    pt = QLCPoint(2, 0);
    QVERIFY(grp.head(pt) == GroupHead(2, 0));

    grp.assignFixture(3);
    QCOMPARE(grp.headList().size(), 4);
    QCOMPARE(grp.size(), QSize(4, 2));
    pt = QLCPoint(0, 0);
    QVERIFY(grp.head(pt) == GroupHead(0, 0));
    pt = QLCPoint(1, 0);
    QVERIFY(grp.head(pt) == GroupHead(1, 0));
    pt = QLCPoint(2, 0);
    QVERIFY(grp.head(pt) == GroupHead(2, 0));
    pt = QLCPoint(3, 0);
    QVERIFY(grp.head(pt) == GroupHead(3, 0));

    grp.assignFixture(4);
    QCOMPARE(grp.headList().size(), 5);
    QCOMPARE(grp.size(), QSize(4, 2));
    pt = QLCPoint(0, 0);
    QVERIFY(grp.head(pt) == GroupHead(0, 0));
    pt = QLCPoint(1, 0);
    QVERIFY(grp.head(pt) == GroupHead(1, 0));
    pt = QLCPoint(2, 0);
    QVERIFY(grp.head(pt) == GroupHead(2, 0));
    pt = QLCPoint(3, 0);
    QVERIFY(grp.head(pt) == GroupHead(3, 0));
    pt = QLCPoint(0, 1);
    QVERIFY(grp.head(pt) == GroupHead(4, 0));

    grp.assignFixture(5);
    QCOMPARE(grp.headList().size(), 6);
    QCOMPARE(grp.size(), QSize(4, 2));
    pt = QLCPoint(0, 0);
    QVERIFY(grp.head(pt) == GroupHead(0, 0));
    pt = QLCPoint(1, 0);
    QVERIFY(grp.head(pt) == GroupHead(1, 0));
    pt = QLCPoint(2, 0);
    QVERIFY(grp.head(pt) == GroupHead(2, 0));
    pt = QLCPoint(3, 0);
    QVERIFY(grp.head(pt) == GroupHead(3, 0));
    pt = QLCPoint(0, 1);
    QVERIFY(grp.head(pt) == GroupHead(4, 0));
    pt = QLCPoint(1, 1);
    QVERIFY(grp.head(pt) == GroupHead(5, 0));

    grp.assignFixture(6);
    QCOMPARE(grp.headList().size(), 7);
    QCOMPARE(grp.size(), QSize(4, 2));
    pt = QLCPoint(0, 0);
    QVERIFY(grp.head(pt) == GroupHead(0, 0));
    pt = QLCPoint(1, 0);
    QVERIFY(grp.head(pt) == GroupHead(1, 0));
    pt = QLCPoint(2, 0);
    QVERIFY(grp.head(pt) == GroupHead(2, 0));
    pt = QLCPoint(3, 0);
    QVERIFY(grp.head(pt) == GroupHead(3, 0));
    pt = QLCPoint(0, 1);
    QVERIFY(grp.head(pt) == GroupHead(4, 0));
    pt = QLCPoint(1, 1);
    QVERIFY(grp.head(pt) == GroupHead(5, 0));
    pt = QLCPoint(2, 1);
    QVERIFY(grp.head(pt) == GroupHead(6, 0));

    grp.assignFixture(7);
    QCOMPARE(grp.headList().size(), 8);
    QCOMPARE(grp.size(), QSize(4, 2));
    pt = QLCPoint(0, 0);
    QVERIFY(grp.head(pt) == GroupHead(0, 0));
    pt = QLCPoint(1, 0);
    QVERIFY(grp.head(pt) == GroupHead(1, 0));
    pt = QLCPoint(2, 0);
    QVERIFY(grp.head(pt) == GroupHead(2, 0));
    pt = QLCPoint(3, 0);
    QVERIFY(grp.head(pt) == GroupHead(3, 0));
    pt = QLCPoint(0, 1);
    QVERIFY(grp.head(pt) == GroupHead(4, 0));
    pt = QLCPoint(1, 1);
    QVERIFY(grp.head(pt) == GroupHead(5, 0));
    pt = QLCPoint(2, 1);
    QVERIFY(grp.head(pt) == GroupHead(6, 0));
    pt = QLCPoint(3, 1);
    QVERIFY(grp.head(pt) == GroupHead(7, 0));

    // Now beyond size(); should continue to make a third row of 4 columns
    grp.assignFixture(8);
    QCOMPARE(grp.headList().size(), 9);
    QCOMPARE(grp.size(), QSize(4, 2));
    pt = QLCPoint(0, 0);
    QVERIFY(grp.head(pt) == GroupHead(0, 0));
    pt = QLCPoint(1, 0);
    QVERIFY(grp.head(pt) == GroupHead(1, 0));
    pt = QLCPoint(2, 0);
    QVERIFY(grp.head(pt) == GroupHead(2, 0));
    pt = QLCPoint(3, 0);
    QVERIFY(grp.head(pt) == GroupHead(3, 0));
    pt = QLCPoint(0, 1);
    QVERIFY(grp.head(pt) == GroupHead(4, 0));
    pt = QLCPoint(1, 1);
    QVERIFY(grp.head(pt) == GroupHead(5, 0));
    pt = QLCPoint(2, 1);
    QVERIFY(grp.head(pt) == GroupHead(6, 0));
    pt = QLCPoint(3, 1);
    QVERIFY(grp.head(pt) == GroupHead(7, 0));
    pt = QLCPoint(0, 2);
    QVERIFY(grp.head(pt) == GroupHead(8, 0));

    grp.assignFixture(9);
    QCOMPARE(grp.headList().size(), 10);
    QCOMPARE(grp.size(), QSize(4, 2));
    pt = QLCPoint(0, 0);
    QVERIFY(grp.head(pt) == GroupHead(0, 0));
    pt = QLCPoint(1, 0);
    QVERIFY(grp.head(pt) == GroupHead(1, 0));
    pt = QLCPoint(2, 0);
    QVERIFY(grp.head(pt) == GroupHead(2, 0));
    pt = QLCPoint(3, 0);
    QVERIFY(grp.head(pt) == GroupHead(3, 0));
    pt = QLCPoint(0, 1);
    QVERIFY(grp.head(pt) == GroupHead(4, 0));
    pt = QLCPoint(1, 1);
    QVERIFY(grp.head(pt) == GroupHead(5, 0));
    pt = QLCPoint(2, 1);
    QVERIFY(grp.head(pt) == GroupHead(6, 0));
    pt = QLCPoint(3, 1);
    QVERIFY(grp.head(pt) == GroupHead(7, 0));
    pt = QLCPoint(0, 2);
    QVERIFY(grp.head(pt) == GroupHead(8, 0));
    pt = QLCPoint(1, 2);
    QVERIFY(grp.head(pt) == GroupHead(9, 0));

    // Going waaay beyond size should be possible
    pt = QLCPoint(1024, 2048);
    grp.assignFixture(10, pt);
    QVERIFY(grp.headHash().contains(pt) == true);
    QCOMPARE(grp.head(pt), GroupHead(10, 0));
    QCOMPARE(grp.size(), QSize(4, 2));
}
Example #27
0
void FixtureGroup_Test::assignFixtureNoSize()
{
    QLCPoint pt;
    FixtureGroup grp(m_doc);
    QCOMPARE(grp.headList().size(), 0);

    Fixture* fxi = new Fixture(m_doc);
    fxi->setChannels(2);
    m_doc->addFixture(fxi);

    grp.assignFixture(fxi->id());
    QCOMPARE(grp.headList().size(), 2);
    QCOMPARE(grp.size(), QSize(1, 1));
    QVERIFY(grp.headHash()[QLCPoint(0, 0)] == GroupHead(0, 0));
    QVERIFY(grp.headHash()[QLCPoint(0, 1)] == GroupHead(0, 1));

    // Same fixture can't be at two places
    grp.assignFixture(0, QLCPoint(100, 100));
    QCOMPARE(grp.headList().size(), 2);
    QCOMPARE(grp.size(), QSize(1, 1));
    QVERIFY(grp.headHash()[QLCPoint(0, 0)] == GroupHead(0, 0));
    QVERIFY(grp.headHash()[QLCPoint(0, 1)] == GroupHead(0, 1));

    fxi = new Fixture(m_doc);
    fxi->setChannels(1);
    m_doc->addFixture(fxi);

    grp.assignFixture(fxi->id());
    QCOMPARE(grp.headList().size(), 3);
    QCOMPARE(grp.size(), QSize(1, 1));
    QVERIFY(grp.headHash()[QLCPoint(0, 0)] == GroupHead(0, 0));
    QVERIFY(grp.headHash()[QLCPoint(0, 1)] == GroupHead(0, 1));
    QVERIFY(grp.headHash()[QLCPoint(0, 2)] == GroupHead(1, 0));

    QLCFixtureDef* def = m_doc->fixtureDefCache()->fixtureDef("Futurelight", "DJScan250");
    QVERIFY(def != NULL);
    QLCFixtureMode* mode = def->modes().first();
    QVERIFY(mode != NULL);

    fxi = new Fixture(m_doc);
    fxi->setFixtureDefinition(def, mode);
    m_doc->addFixture(fxi);

    grp.assignFixture(fxi->id());
    QCOMPARE(grp.headList().size(), 4);
    QCOMPARE(grp.size(), QSize(1, 1));
    QVERIFY(grp.headHash()[QLCPoint(0, 0)] == GroupHead(0, 0));
    QVERIFY(grp.headHash()[QLCPoint(0, 1)] == GroupHead(0, 1));
    QVERIFY(grp.headHash()[QLCPoint(0, 2)] == GroupHead(1, 0));
    QVERIFY(grp.headHash()[QLCPoint(0, 3)] == GroupHead(2, 0));

    def = m_doc->fixtureDefCache()->fixtureDef("i-Pix", "BB4");
    QVERIFY(def != NULL);
    mode = def->modes().last();
    QVERIFY(mode != NULL);
    QCOMPARE(mode->heads().size(), 4);

    fxi = new Fixture(m_doc);
    fxi->setFixtureDefinition(def, mode);
    m_doc->addFixture(fxi);

    grp.assignFixture(fxi->id());
    QCOMPARE(grp.headList().size(), 8);
    QCOMPARE(grp.size(), QSize(1, 1));
    QVERIFY(grp.headHash()[QLCPoint(0, 0)] == GroupHead(0, 0));
    QVERIFY(grp.headHash()[QLCPoint(0, 1)] == GroupHead(0, 1));
    QVERIFY(grp.headHash()[QLCPoint(0, 2)] == GroupHead(1, 0));
    QVERIFY(grp.headHash()[QLCPoint(0, 3)] == GroupHead(2, 0));
    // BB4 heads
    QVERIFY(grp.headHash()[QLCPoint(0, 4)] == GroupHead(3, 0));
    QVERIFY(grp.headHash()[QLCPoint(0, 5)] == GroupHead(3, 1));
    QVERIFY(grp.headHash()[QLCPoint(0, 6)] == GroupHead(3, 2));
    QVERIFY(grp.headHash()[QLCPoint(0, 7)] == GroupHead(3, 3));
}