Esempio n. 1
0
// get the value as integer
qint64 KCValue::asInteger() const
{
    qint64 result = 0;
    if (type() == Integer)
        result = d->i;
    else if (type() == Float)
        result = static_cast<qint64>(floor(numToDouble(d->f)));
    else if (type() == Complex)
        result = static_cast<qint64>(floor(numToDouble(d->pc->real())));
    return result;
}
Esempio n. 2
0
QTextStream& operator<<(QTextStream& ts, KCValue value)
{
    ts << value.type();
    switch (value.type()) {
    case KCValue::Empty:   break;

    case KCValue::Boolean:
        ts << ": ";
        if (value.asBoolean()) ts << "TRUE";
        else ts << "FALSE"; break;

    case KCValue::Integer:
        ts << ": " << value.asInteger(); break;

    case KCValue::Float:
        ts << ": " << (double) numToDouble(value.asFloat()); break;

    case KCValue::Complex: {
        const complex<KCNumber> complex(value.asComplex());
        ts << ": " << (double) numToDouble(complex.real());
        if (complex.imag() >= 0.0)
            ts << '+';
        ts << (double) numToDouble(complex.imag()) << 'i';
        break;
    }

    case KCValue::String:
        ts << ": " << value.asString(); break;

    case KCValue::Array: {
        ts << ": {" << value.asString();
        const int cols = value.columns();
        const int rows = value.rows();
        for (int row = 0; row < rows; ++row) {
            for (int col = 0; col < cols; ++col) {
                ts << value.element(col, row);
                if (col < cols - 1)
                    ts << ';';
            }
            if (row < rows - 1)
                ts << '|';
        }
        ts << '}';
        break;
    }

    case KCValue::Error:
        ts << '(' << value.errorMessage() << ')'; break;

    default: break;
    }
    return ts;
}
Esempio n. 3
0
void TestValue::testAssignment()
{
    Value* v1;
    Value* v2;

    // value assignment
    v1 = new Value(14.3l);
    v2 = new Value(true);
    *v2 = *v1;
    QCOMPARE(v1->type(), Value::Float);
    QCOMPARE(v2->type(), Value::Float);
    QCOMPARE(numToDouble(v1->asFloat()), 14.3l);
    QCOMPARE(numToDouble(v2->asFloat()), 14.3l);
    delete v1;
    delete v2;

    // test copying/detaching of string values (QString*)
    v1 = new Value("Hello");
    v2 = new Value(true);
    *v2 = *v1;
    QCOMPARE(v1->type(), Value::String);
    QCOMPARE(v2->type(), Value::String);
    QCOMPARE(v1->asString(), QString("Hello"));
    QCOMPARE(v2->asString(), QString("Hello"));
    *v2 = Value(QString("World"));
    QCOMPARE(v1->asString(), QString("Hello"));
    QCOMPARE(v2->asString(), QString("World"));
    delete v1;
    delete v2;

    // test copying/detaching of arrays (ValueArray*)
    v1 = new Value(Value::Array);
    v1->setElement(0, 0, Value(1));
    v1->setElement(0, 1, Value(2));
    v2 = new Value(true);
    *v2 = *v1;
    QCOMPARE(v1->type(), Value::Array);
    QCOMPARE(v2->type(), Value::Array);
    QCOMPARE(v1->element(0, 0), Value(1));
    QCOMPARE(v1->element(0, 1), Value(2));
    QCOMPARE(v2->element(0, 0), Value(1));
    QCOMPARE(v2->element(0, 1), Value(2));
    v2->setElement(0, 0, Value(3));
    QCOMPARE(v1->element(0, 0), Value(1));
    QCOMPARE(v1->element(0, 1), Value(2));
    QCOMPARE(v2->element(0, 0), Value(3));
    QCOMPARE(v2->element(0, 1), Value(2));
    delete v1;
    delete v2;
}
Esempio n. 4
0
// get the value as QVariant
QVariant KCValue::asVariant() const
{
    QVariant result;

    switch (d->type) {
    case KCValue::Empty:
    default:
        result = 0;
        break;
    case KCValue::Boolean:
        result = d->b;
        break;
    case KCValue::Integer:
        result = d->i;
        break;
    case KCValue::Float:
        result = (double) numToDouble(d->f);
        break;
    case KCValue::Complex:
        // FIXME: add support for complex numbers
        // pc = new complex<KCNumber>( *o.pc );
        break;
    case KCValue::String:
    case KCValue::Error:
        result = *d->ps;
        break;
    case KCValue::Array:
        // FIXME: not supported yet
        //result = ValueArray( d->pa );
        break;
    }

    return result;
}
Esempio n. 5
0
void TestValue::testCopy()
{
    Value* v1;
    Value* v2;

    // copy value
    v1 = new Value();
    *v1 = Value(14.3l);
    v2 = new Value(*v1);
    QCOMPARE(v1->type(), Value::Float);
    QCOMPARE(v2->type(), Value::Float);
    QCOMPARE(numToDouble(v1->asFloat()), 14.3l);
    QCOMPARE(numToDouble(v2->asFloat()), 14.3l);
    delete v1;
    delete v2;
}
Esempio n. 6
0
void TestValue::testFloat()
{
    Value* v1;

    // floating-point value
    v1 = new Value(M_PI);
    QCOMPARE(v1->type(), Value::Float);
    QCOMPARE(numToDouble(v1->asFloat()), (long double) M_PI);
    *v1 = Value(false);   // dummy
    *v1 = Value(14.03l);
    QCOMPARE(v1->type(), Value::Float);
    QCOMPARE(v1->isInteger(), false);
    QCOMPARE(v1->isFloat(), true);
    QCOMPARE(v1->isString(), false);
    QCOMPARE(v1->isNumber(), true);
    QCOMPARE(numToDouble(v1->asFloat()), 14.03l);
    delete v1;
}
Esempio n. 7
0
// get the value as time
QTime KCValue::asTime(const KCCalculationSettings* settings) const
{
    Q_UNUSED(settings);
    QTime dt;

    const int days = asInteger();
    const int msecs = qRound(numToDouble(asFloat() - double(days)) * 86400000.0);      // 24*60*60*1000
    dt = dt.addMSecs(msecs);

    return dt;
}
Esempio n. 8
0
// get the value as date/time
QDateTime KCValue::asDateTime(const KCCalculationSettings* settings) const
{
    QDateTime datetime(settings->referenceDate(), QTime(), Qt::UTC);

    const int days = asInteger();
    const int msecs = qRound((numToDouble(asFloat() - double(days))) * 86400000.0);      // 24*60*60*1000
    datetime = datetime.addDays(days);
    datetime = datetime.addMSecs(msecs);

    return datetime;
}
Esempio n. 9
0
// round to get at most 10-digits number
static Value RoundNumber(const Value& v)
{
  if(v.isNumber())
  {
    double d = numToDouble(v.asFloat());
    if(fabs(d) < DBL_EPSILON)
      d = 0.0;
    return Value( ROUND(d) );
  }
  else
    return v;
}
Esempio n. 10
0
QVariant KCBindingModel::data(const QModelIndex& index, int role) const
{
    if ((m_region.isEmpty()) || (role != Qt::EditRole && role != Qt::DisplayRole))
        return QVariant();
    const QPoint offset = m_region.firstRange().topLeft();
    const KCSheet* sheet = m_region.firstSheet();
    const KCValue value = sheet->cellStorage()->value(offset.x() + index.column(),
                          offset.y() + index.row());
    // KChart::KCValue is either:
    //  - a double (interpreted as a value)
    //  - a QString (interpreted as a label)
    //  - a QDateTime (interpreted as a date/time value)
    //  - Invalid (interpreted as empty)
    QVariant variant;
    switch (value.type()) {
    case KCValue::Float:
    case KCValue::Integer:
        if (value.format() == KCValue::fmt_DateTime ||
                value.format() == KCValue::fmt_Date ||
                value.format() == KCValue::fmt_Time) {
            variant.setValue<QDateTime>(value.asDateTime(sheet->map()->calculationSettings()));
            break;
        }
    case KCValue::Boolean:
    case KCValue::Complex:
    case KCValue::Array:
        variant.setValue<double>(numToDouble(value.asFloat()));
        break;
    case KCValue::String:
    case KCValue::Error:
        variant.setValue<QString>(value.asString());
        break;
    case KCValue::Empty:
    case KCValue::CellRange:
    default:
        break;
    }
    //kDebug() << index.column() <<"," << index.row() <<"," << variant;
    return variant;
}
Esempio n. 11
0
void TestValue::testDate()
{
    Value* v1;

    // check all (valid) dates from 1900 to 2050
    // note: bail on first error immediately
    CalculationSettings calculationSettings;
    QDate refDate(1899, 12, 31);
    v1 = new Value();
    bool date_error = 0;
    for (unsigned y = 1900; !date_error && y < 2050; y++)
        for (unsigned m = 1; !date_error && m <= 12; m++)
            for (unsigned d = 1; !date_error && d <= 31; d++) {
                QDate dv1 = QDate(y, m, d);
                if (!dv1.isValid()) continue;
                long double serialNo = -dv1.daysTo(refDate) + 1.0;
                *v1 = Value(Value(dv1, &calculationSettings));
                QCOMPARE(numToDouble(v1->asFloat()), serialNo);
                date_error = v1->asFloat() != serialNo;
            }
    delete v1;
}
Esempio n. 12
0
uint qHash(const KCValue& value)
{
    switch (value.type()) {
    case KCValue::Empty:
    case KCValue::CellRange:
        return 0;
    case KCValue::Boolean:
        return ::qHash(value.asBoolean());
    case KCValue::Integer:
        return ::qHash(value.asInteger());
    case KCValue::Float:
        return ::qHash((qint64)numToDouble(value.asFloat()));
    case KCValue::Complex:
        return ::qHash((qint64)value.asComplex().real());
    case KCValue::String:
        return ::qHash(value.asString());
    case KCValue::Array:
        return qHash(value.element(0, 0));
    case KCValue::Error:
        return ::qHash(value.errorMessage());
    }
    return 0;
}
Esempio n. 13
0
void ValidityDialog::init()
{
    const KCMap *const map = m_selection->activeSheet()->map();
    const KCCalculationSettings *settings = map->calculationSettings();
    const KLocale* locale = settings->locale();
    KCValidity validity = KCCell(m_selection->activeSheet(), m_selection->marker()).validity();
    if (!validity.isEmpty()) {
        message->setPlainText(validity.message());
        title->setText(validity.title());
        QString tmp;
        switch (validity.restriction()) {
        case KCValidity::None:
            chooseType->setCurrentIndex(0);
            break;
        case KCValidity::KCNumber:
            chooseType->setCurrentIndex(1);
            if (validity.condition() >= 5)
                val_max->setText(tmp.setNum((double)numToDouble(validity.maximumValue().asFloat())));
            val_min->setText(tmp.setNum((double)numToDouble(validity.minimumValue().asFloat())));
            break;
        case KCValidity::Integer:
            chooseType->setCurrentIndex(2);
            if (validity.condition() >= 5)
                val_max->setText(tmp.setNum((double)numToDouble(validity.maximumValue().asFloat())));
            val_min->setText(tmp.setNum((double)numToDouble(validity.minimumValue().asFloat())));
            break;
        case KCValidity::TextLength:
            chooseType->setCurrentIndex(6);
            if (validity.condition() >= 5)
                val_max->setText(tmp.setNum((double)numToDouble(validity.maximumValue().asFloat())));
            val_min->setText(tmp.setNum((double)numToDouble(validity.minimumValue().asFloat())));
            break;
        case KCValidity::Text:
            chooseType->setCurrentIndex(3);
            break;
        case KCValidity::Date:
            chooseType->setCurrentIndex(4);
            val_min->setText(locale->formatDate(validity.minimumValue().asDate(settings), KLocale::ShortDate));
            if (validity.condition() >= 5)
                val_max->setText(locale->formatDate(validity.maximumValue().asDate(settings), KLocale::ShortDate));
            break;
        case KCValidity::Time:
            chooseType->setCurrentIndex(5);
            val_min->setText(locale->formatTime(validity.minimumValue().asTime(settings), true));
            if (validity.condition() >= 5)
                val_max->setText(locale->formatTime(validity.maximumValue().asTime(settings), true));
            break;
        case KCValidity::List: {
            chooseType->setCurrentIndex(7);
            const QStringList lst = validity.validityList();
            QString tmp;
            for (QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it) {
                tmp += (*it) + '\n';
            }
            validityList->setText(tmp);
        }
        break;
        default :
            chooseType->setCurrentIndex(0);
            break;
        }
        chooseAction->setCurrentIndex(chooseAction->findData(QVariant::fromValue(validity.action())));
        choose->setCurrentIndex(choose->findData(QVariant::fromValue(validity.condition())));
        displayMessage->setChecked(validity.displayMessage());
        allowEmptyCell->setChecked(validity.allowEmptyCell());
        titleHelp->setText(validity.titleInfo());
        messageHelp->setPlainText(validity.messageInfo());
        displayHelp->setChecked(validity.displayValidationInformation());
    }
    changeIndexType(chooseType->currentIndex()) ;
    changeIndexCond(choose->currentIndex()) ;
}
Esempio n. 14
0
bool KCValidity::testValidity(const KCCell* cell) const
{
    bool valid = false;
    if (d->restriction != None) {
        //fixme
        if (d->allowEmptyCell && cell->userInput().isEmpty())
            return true;

        if ((cell->value().isNumber() &&
                (d->restriction == KCNumber ||
                 (d->restriction == Integer &&
                  numToDouble(cell->value().asFloat()) == ceil(numToDouble(cell->value().asFloat())))))
            || (d->restriction == Time && cell->isTime())
            || (d->restriction == Date && cell->isDate())) {
            switch (d->cond) {
            case KCConditional::Equal:
                valid = cell->value().equal(d->minValue);
                break;
            case KCConditional::DifferentTo:
                valid = !cell->value().equal(d->minValue);
                break;
            case KCConditional::Superior:
                valid = cell->value().greater(d->minValue);
                break;
            case KCConditional::Inferior:
                valid = cell->value().less(d->minValue);
                break;
            case KCConditional::SuperiorEqual:
                valid = (cell->value().compare(d->minValue)) >= 0;
                break;
            case KCConditional::InferiorEqual:
                valid = (cell->value().compare(d->minValue)) <= 0;
                break;
            case KCConditional::Between:
                valid = (cell->value().compare(d->minValue) >= 0 &&
                         cell->value().compare(d->maxValue) <= 0);
                break;
            case KCConditional::Different:
                valid = (cell->value().compare(d->minValue) < 0 ||
                         cell->value().compare(d->maxValue) > 0);
                break;
            default :
                break;
            }
        } else if (d->restriction == Text) {
            valid = cell->value().isString();
        } else if (d->restriction == List) {
            //test int value
            if (cell->value().isString() && d->listValidity.contains(cell->value().asString()))
                valid = true;
        } else if (d->restriction == TextLength) {
            if (cell->value().isString()) {
                int len = cell->displayText().length();
                const int min = d->minValue.asInteger();
                const int max = d->maxValue.asInteger();
                switch (d->cond) {
                case KCConditional::Equal:
                    if (len == min)
                        valid = true;
                    break;
                case KCConditional::DifferentTo:
                    if (len != min)
                        valid = true;
                    break;
                case KCConditional::Superior:
                    if (len > min)
                        valid = true;
                    break;
                case KCConditional::Inferior:
                    if (len < min)
                        valid = true;
                    break;
                case KCConditional::SuperiorEqual:
                    if (len >= min)
                        valid = true;
                    break;
                case KCConditional::InferiorEqual:
                    if (len <= min)
                        valid = true;
                    break;
                case KCConditional::Between:
                    if (len >= min && len <= max)
                        valid = true;
                    break;
                case KCConditional::Different:
                    if (len < min || len > max)
                        valid = true;
                    break;
                default :
                    break;
                }
            }
        }
    } else {
        valid = true;
    }

    if (!valid) {
        if (d->displayMessage) {
            switch (d->action) {
            case Stop:
                KMessageBox::error((QWidget*)0, d->message, d->title);
                break;
            case Warning:
                if (KMessageBox::warningYesNo((QWidget*)0, d->message, d->title) == KMessageBox::Yes) {
                    valid = true;
                }
                break;
            case Information:
                KMessageBox::information((QWidget*)0, d->message, d->title);
                valid = true;
                break;
            }
        }

        cell->sheet()->showStatusMessage(i18n("Validation for cell %1 failed", cell->fullName()));
    }
    return valid;
}
Esempio n. 15
0
void TestValue::testArray()
{
    Value* v1;
    Value* v2;

    // array
    v1 = new Value(Value::Array);
    QCOMPARE(v1->type(), Value::Array);
    QCOMPARE(v1->columns(), (unsigned)1);
    QCOMPARE(v1->rows(), (unsigned)1);
    delete v1;

    // check empty value in array
    v1 = new Value(Value::Array);
    QCOMPARE(v1->type(), Value::Array);
    v2 = new Value(v1->element(0, 0));
    QCOMPARE(v2->type(), Value::Empty);
    delete v1;

    // fill simple 1x1 array
    v1 = new Value(Value::Array);
    QCOMPARE(v1->type(), Value::Array);
    v2 = new Value(14.3l);
    v1->setElement(0, 0, *v2);
    delete v2;
    v2 = new Value(v1->element(0, 0));
    QCOMPARE(v2->type(), Value::Float);
    QCOMPARE(numToDouble(v2->asFloat()), 14.3l);
    delete v2;
    delete v1;

    // stress test, array of 1000x1000
    v1 = new Value(Value::Array);
    QCOMPARE(v1->type(), Value::Array);
    for (unsigned r = 0; r < 1000; r++)
        for (unsigned c = 0; c < 1000; c++) {
            int index = 1000 * r + c;
            v1->setElement(c, r, Value(index));
        }
    int array_error = 0;
    for (unsigned c = 0; !array_error && c < 1000; c++)
        for (unsigned r = 0; !array_error && r < 1000; r++) {
            int index = 1000 * r + c;
            v2 = new Value(v1->element(c, r));
            if (v2->type() != Value::Integer) array_error++;
            if (v2->asInteger() != index) array_error++;
            delete v2;
        }
    QCOMPARE(array_error, (int)0);
    delete v1;

    // assignment of array value
    v1 = new Value(Value::Array);
    QCOMPARE(v1->type(), Value::Array);
    v1->setElement(1, 1, Value(44.3l));
    v1->setElement(0, 1, Value(34.3l));
    v1->setElement(1, 0, Value(24.3l));
    v1->setElement(0, 0, Value(14.3l));
    v2 = new Value(*v1);   // v2 is now also an array
    delete v1;
    v1 = new Value(v2->element(0, 0));
    QCOMPARE(v1->type(), Value::Float);
    QCOMPARE(numToDouble(v1->asFloat()), 14.3l);
    delete v1;
    delete v2;

    // equality
    v1 = new Value(Value::Array);
    v2 = new Value(Value::Array);
    QCOMPARE(*v1, *v2);
    v1->setElement(0, 0, Value(1));
    v1->setElement(0, 1, Value(2));
    v2->setElement(0, 0, Value(1));
    v2->setElement(0, 1, Value(2));
    QCOMPARE(*v1, *v2);
    delete v1;
    delete v2;
}