예제 #1
0
bool GemTestCommand::execute(Gem* self, Gem* test)
{
    bool result = false;

    switch (_id)
    {
    case HasFlag:
        return (test->style() & _arg) != 0;

    case GemType:
        return test->gemType() == _arg;

    case GemFlushMode:
        return (test->gemClass().flushMode() & _arg) != 0;

    case Text:
        return (_text == test->text());

    case TextBegins:
        return test->text().startsWith(_text);

    case NthChild:
    {
        result = false;
        Gem* origin = test->parentGem();
        if (!origin) break;
        int target = qAbs(_arg);
        int i = 1; // Counts the order.
        Gem* it;
        for (it = _arg > 0? origin->firstGem()
            : origin->lastGem(); it && it != test;
            it = _arg > 0? it->nextGem() : it->prevGem(), i++)
        {
            if (i == target)
            {
                // Didn't match it == test...
                return false;
            }
        }
        if (!it) break;
        result = i == target;
        break;
    }

    case NthOrder:
    {
        result = false;
        Gem* origin = test->parentGem();
        if (!origin) break;
        int target = qAbs(_arg);
        int i = 0; // Counts the order.
        for (Gem* it = _arg > 0? origin->firstGem() : origin->finalGem();
            it && it != origin->nextGem() && it != origin;
            it = _arg > 0? it->followingGem() : it->precedingGem())
        {
            if (!it->isControl()) i++;
            if (it == test)
            {
                result = true;
                break;
            }
            if (i >= target) return false;
        }
        if (!result) break; // Not even found...
        result = i == target;
        break;
    }

    case IsTop:
        return test->parent() == NULL;

    case IsMe:
        return test == self;

    case IsMyParent:
        return test == self->parentGem();

    case IsMyAncestor:
        result = false;
        for (Gem* it = self->parentGem(); it; it = it->parentGem())
            if (it == test)
            {
                result = true;
                break;
            }
        break;

    case IsBreak:
        return test->isBreak();

    case IsLineBreak:
        return test->isLineBreak();

    case IsControl:
        return test->isControl();

    case ExclusiveFlag:
        return (test->style() & ~_arg) == 0;

    case ChildCount:
        return test->count() == _arg;

    case CellWidth:
        return test->width() == _arg;

    default:
        qFatal("GemTestCommand: Invalid test command.");
        break;
    }

    return result;
}
예제 #2
0
bool GemTest::test(Gem *gem)
{
    Gem *test = gem;       // The test pointer.
    Gem *tryStart;
    bool result, trying = false, passed;
    int i;
    
    for(GemTestCommand *cmd = _commands.next(); !cmd->isRoot(); cmd = cmd->next())
    {
        // We can skip commands if trying is passed.
        if(trying && ((passed && cmd->id() != CheckIfPassed) ||
                      (!test && cmd->id() != CheckIfPassed && cmd->id() != GoSelf)))
            continue;

        result = true;
        switch(cmd->id())
        {
        case GoSelf:
            test = gem;
            break;

        case GoParent:
            for(i = 0; test && i < cmd->intArg(); i++) test = test->parentGem();
            break;

        case GoNext:
            for(i = 0; test && i < cmd->intArg(); i++) test = test->nextGem();
            break;

        case GoPrev:
            for(i = 0; test && i < cmd->intArg(); i++) test = test->prevGem();
            break;

        case GoFirst:
            for(i = 0; test && i < cmd->intArg(); i++) test = test->firstGem();
            break;

        case GoLast:
            for(i = 0; test && i < cmd->intArg(); i++) test = test->lastGem();
            break;

        case GoFollowing:
            for(i = 0; test && i < cmd->intArg(); i++) test = test->followingGem();
            break;
            
        case GoPreceding:
            for(i = 0; test && i < cmd->intArg(); i++) test = test->precedingGem();
            break;

        case GoFinal:
            test = gem->finalGem();
            break;

        case BeginTry:
            trying = true;
            passed = false;
            tryStart = test;
            break;

        case CheckIfPassed:
            trying = false;
            result = passed;
            test = tryStart; // Return to where the test began.
            break;

        default:
            // Are we escalating this check?
            if(cmd->escalating())
            {
                result = false;
                for(Gem* it = test->parentGem(); it; it = it->parentGem())
                {
                    if(cmd->execute(gem, it))
                    {
                        result = true;
                        break;
                    }
                }
            }
            else
            {
                result = cmd->execute(gem, test);
            }
            break;
        }

        // You can't fail the BeginTry command.
        if(cmd->id() == BeginTry) continue;

        // A null test pointer is an automatic failure.
        if(!test)
        {
            if(!trying) return false;
            result = false;
        }

        // Did it fail?
        if(trying)
        {
            if(result != cmd->negated()) passed = true; // Passed!
        }
        else
        {
            if(result == cmd->negated()) return false; // Failed!
        }
    }

    if(trying)
    {
        qCritical("A 'try..pass' is missing 'pass'.");
        exit(1);
    }

    // All commands were successful.
    return true;
}