Esempio n. 1
0
QString CopyCommand::saveAsPlainText(const Region &region)
{
    // Only one cell selected? => copy active cell
    if (region.isSingular()) {
        const Cell cell(region.firstSheet(), region.firstRange().topLeft());
        return cell.displayText();
    }

    QString result;
    Region::ConstIterator end(region.constEnd());
    for (Region::ConstIterator it(region.constBegin()); it != end; ++it) {
      if (result.length()) result += QLatin1Char('\n');
      Region::Element *el = *it;
      QRect used = el->sheet()->usedArea (true);
      QRect rect = el->rect().intersected (used);
      for (int row = rect.top(); row <= rect.bottom(); ++row) {
        for (int col = rect.left(); col <= rect.right(); ++col) {
          Cell cell (el->sheet(), col, row);
          result += cellAsText (cell, col != rect.right());
        }
        result += QLatin1Char('\n');
      }
    }
    return result;
}
void ScriptingCellListener::slotChanged(const Region& region)
{
    Region::ConstIterator end(region.constEnd());

    QVariantList ranges;
    for (Region::ConstIterator it = region.constBegin(); it != end; ++it)
        ranges << (*it)->rect();
    emit regionChanged(ranges);

    for (Region::ConstIterator it = region.constBegin(); it != end; ++it) {
        const QRect r((*it)->rect());
        for (int row = r.top(); row <= r.bottom(); ++row)
            for (int col = r.left(); col <= r.right(); ++col)
                emit cellChanged(col, row);
    }
}
Esempio n. 3
0
void RecalcManager::Private::cellsToCalculate(const Region& region, QSet<Cell>& cells) const
{
    Region::ConstIterator end(region.constEnd());
    for (Region::ConstIterator it(region.constBegin()); it != end; ++it) {
        const QRect range = (*it)->rect();
        const Sheet* sheet = (*it)->sheet();
        for (int col = range.left(); col <= range.right(); ++col) {
            for (int row = range.top(); row <= range.bottom(); ++row) {
                Cell cell(sheet, col, row);
                // Even empty cells may act as value
                // providers and need to be processed.

                // check for already processed cells
                if (cells.contains(cell))
                    continue;

                // add it to the list
                if (cell.isFormula())
                    cells.insert(cell);

                // add its consumers to the list
                cellsToCalculate(map->dependencyManager()->consumingRegion(cell), cells);
            }
        }
    }
}
Esempio n. 4
0
void BindingManager::regionChanged(const Region& region)
{
    Sheet* sheet;
    QList< QPair<QRectF, Binding> > bindings;
    Region::ConstIterator end(region.constEnd());
    for (Region::ConstIterator it = region.constBegin(); it != end; ++it) {
        sheet = (*it)->sheet();
        const Region changedRegion((*it)->rect(), sheet);
        bindings = sheet->cellStorage()->bindingStorage()->intersectingPairs(changedRegion);
        for (int j = 0; j < bindings.count(); ++j)
            bindings[j].second.update(changedRegion);
    }
}
Esempio n. 5
0
void Binding::update(const Region& region)
{
    QRect rect;
    Region changedRegion;
    const QPoint offset = d->model->region().firstRange().topLeft();
    const QRect range = d->model->region().firstRange();
    const Sheet* sheet = d->model->region().firstSheet();
    Region::ConstIterator end(region.constEnd());
    for (Region::ConstIterator it = region.constBegin(); it != end; ++it) {
        if (sheet != (*it)->sheet())
            continue;
        rect = range & (*it)->rect();
        rect.translate(-offset.x(), -offset.y());
        if (rect.isValid()) {
            d->model->emitDataChanged(rect);
            changedRegion.add(rect, (*it)->sheet());
        }
    }
    d->model->emitChanged(changedRegion);
}
Esempio n. 6
0
QDomDocument CopyCommand::saveAsHtml(const Region &region)
{
    QDomDocument doc("spreadsheet-html");
    QDomElement html = doc.createElement("html");
    doc.appendChild(html);
    QDomElement body = doc.createElement("body");
    html.appendChild(body);
    QDomElement table = doc.createElement("table");
    body.appendChild(table);

    const Region::ConstIterator end(region.constEnd());
    for (Region::ConstIterator it(region.constBegin()); it != end; ++it) {
        Sheet *const sheet = (*it)->sheet();
        const QRect range = (*it)->rect();

        // TODO
        Q_UNUSED(sheet);
        Q_UNUSED(range);
    }
    return doc;
}
Esempio n. 7
0
void Selection::extend(const Region& region)
{
    if (!region.isValid())
        return;

    uint count = cells().count();
    ConstIterator end(region.constEnd());
    for (ConstIterator it = region.constBegin(); it != end; ++it) {
        Element *element = *it;
        if (!element) continue;
        if (element->type() == Element::Point) {
            Point* point = static_cast<Point*>(element);
            extend(point->pos(), element->sheet());
        } else {
            extend(element->rect(), element->sheet());
        }
    }

    d->activeSubRegionLength += cells().count() - count;

    emitChanged(*this);
}
Esempio n. 8
0
// era: encode references absolutely
QDomDocument CopyCommand::saveAsXml(const Region& region, bool era)
{
    QDomDocument xmlDoc("spreadsheet-snippet");
    xmlDoc.appendChild(xmlDoc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\""));
    QDomElement root = xmlDoc.createElement("spreadsheet-snippet");
    xmlDoc.appendChild(root);

    // find the upper left corner of the selection
    const QRect boundingRect = region.boundingRect();
    int left = boundingRect.left();
    int top = boundingRect.top();

    // for tiling the clipboard content in the selection
    root.setAttribute("rows", QString::number(boundingRect.height()));
    root.setAttribute("columns", QString::number(boundingRect.width()));

    const Region::ConstIterator end(region.constEnd());
    for (Region::ConstIterator it = region.constBegin(); it != end; ++it) {
        Sheet *const sheet = (*it)->sheet();
        const QRect range = (*it)->rect();
        CellStorage *const storage = sheet->cellStorage();

        //
        // Entire rows selected?
        //
        if ((*it)->isRow()) {
            QDomElement rows = xmlDoc.createElement("rows");
            rows.setAttribute("count", QString::number(range.height()));
            rows.setAttribute("row", QString::number(range.top() - top + 1));
            root.appendChild(rows);

            // Save all cells.
            for (int row = range.top(); row <= range.bottom(); ++row) {
                Cell cell = storage->firstInRow(row);
                for (; !cell.isNull(); cell = storage->nextInRow(cell.column(), cell.row())) {
                    if (!cell.isPartOfMerged()) {
                        root.appendChild(cell.save(xmlDoc, 0, top - 1, era));
                    }
                }
            }

            // TODO Stefan: Inefficient, use cluster functionality
            // Save the row formats if there are any
            //const RowFormat* format;
            for (int row = range.top(); row <= range.bottom(); ++row) {
                if (!sheet->rowFormats()->isDefaultRow(row)) {
                    QDomElement e = RowFormat(sheet->rowFormats(), row).save(xmlDoc, top - 1);
                    if (!e.isNull()) {
                        rows.appendChild(e);
                    }
                }
            }
            continue;
        }

        //
        // Entire columns selected?
        //
        if ((*it)->isColumn()) {
            QDomElement columns = xmlDoc.createElement("columns");
            columns.setAttribute("count", QString::number(range.width()));
            columns.setAttribute("column", QString::number(range.left() - left + 1));
            root.appendChild(columns);

            // Save all cells.
            for (int col = range.left(); col <= range.right(); ++col) {
                Cell cell = storage->firstInColumn(col);
                for (; !cell.isNull(); cell = storage->nextInColumn(cell.column(), cell.row())) {
                    if (!cell.isPartOfMerged()) {
                        root.appendChild(cell.save(xmlDoc, left - 1, 0, era));
                    }
                }
            }

            // TODO Stefan: Inefficient, use the cluster functionality
            // Save the column formats if there are any
            const ColumnFormat* format;
            for (int col = range.left(); col <= range.right(); ++col) {
                format = sheet->columnFormat(col);
                if (format && !format->isDefault()) {
                    QDomElement e = format->save(xmlDoc, left - 1);
                    if (!e.isNull()) {
                        columns.appendChild(e);
                    }
                }
            }
            continue;
        }

        // Save all cells.
        Cell cell;
        for (int row = range.top(); row <= range.bottom(); ++row) {
            if (range.left() == 1) {
                cell = storage->firstInRow(row);
            } else {
                cell = storage->nextInRow(range.left() - 1, row);
            }
            while (!cell.isNull() && cell.column() >= range.left() && cell.column() <= range.right()) {
                if (!cell.isPartOfMerged()) {
                    root.appendChild(cell.save(xmlDoc, left - 1, top - 1, era));
                }
                cell = storage->nextInRow(cell.column(), cell.row());
            }
        }
    }
    return xmlDoc;
}
Esempio n. 9
0
void Selection::emitChanged(const Region& region)
{
    Sheet * const sheet = d->activeSheet;
    if(!sheet) // no sheet no update needed
        return;
    Region extendedRegion;
    ConstIterator end(region.constEnd());
    for (ConstIterator it = region.constBegin(); it != end; ++it) {
        Element* element = *it;
        QRect area = element->rect();

        const ColumnFormat *col;
        //look at if column is hiding.
        //if it's hiding refreshing column+1 (or column -1 )
        int left = area.left();
        int right = area.right();
        int top = area.top();
        int bottom = area.bottom();

        // a merged cells is selected
        if (element->type() == Region::Element::Point) {
            Cell cell(sheet, left, top);
            if (cell.doesMergeCells()) {
                // extend to the merged region
                // prevents artefacts of the selection rectangle
                right += cell.mergedXCells();
                bottom += cell.mergedYCells();
            }
        }

        if (right < KS_colMax) {
            do {
                right++;
                col = sheet->columnFormat(right);
            } while (col->isHiddenOrFiltered() && right != KS_colMax);
        }
        if (left > 1) {
            do {
                left--;
                col = sheet->columnFormat(left);
            } while (col->isHiddenOrFiltered() && left != 1);
        }

        if (bottom < KS_rowMax) {
            do {
                bottom++;
                int lastHidden;
                if (sheet->rowFormats()->isHiddenOrFiltered(bottom, &lastHidden)) {
                    bottom = lastHidden;
                } else {
                    break;
                }
            } while (bottom != KS_rowMax);
        }

        if (top > 1) {
            do {
                top--;
                int firstHidden;
                if (sheet->rowFormats()->isHiddenOrFiltered(top, 0, &firstHidden)) {
                    top = firstHidden;
                } else {
                    break;
                }
            } while (top != 1);
        }

        area.setLeft(left);
        area.setRight(right);
        area.setTop(top);
        area.setBottom(bottom);

        extendedRegion.add(area, element->sheet());
    }

    const QList<Cell> masterCells = sheet->cellStorage()->masterCells(extendedRegion);
    for (int i = 0; i < masterCells.count(); ++i)
        extendedRegion.add(masterCells[i].cellPosition(), sheet);

    emit changed(extendedRegion);
}
Esempio n. 10
0
bool Conditions::isTrueFormula(const Cell &cell, const QString &formula, const QString &baseCellAddress) const
{
    Map* const map = cell.sheet()->map();
    ValueCalc *const calc = map->calc();
    Formula f(cell.sheet(), cell);
    f.setExpression('=' + formula);
    Region r(baseCellAddress, map, cell.sheet());
    if (r.isValid() && r.isSingular()) {
        QPoint basePoint = static_cast<Region::Point*>(*r.constBegin())->pos();
        QString newFormula('=');
        const Tokens tokens = f.tokens();
        for (int t = 0; t < tokens.count(); ++t) {
            const Token token = tokens[t];
            if (token.type() == Token::Cell || token.type() == Token::Range) {
                if (map->namedAreaManager()->contains(token.text())) {
                    newFormula.append(token.text());
                    continue;
                }
                const Region region(token.text(), map, cell.sheet());
                if (!region.isValid() || !region.isContiguous()) {
                    newFormula.append(token.text());
                    continue;
                }
                if (region.firstSheet() != r.firstSheet()) {
                    newFormula.append(token.text());
                    continue;
                }
                Region::Element* element = *region.constBegin();
                if (element->type() == Region::Element::Point) {
                    Region::Point* point = static_cast<Region::Point*>(element);
                    QPoint pos = point->pos();
                    if (!point->isRowFixed()) {
                        int delta = pos.y() - basePoint.y();
                        pos.setY(cell.row() + delta);
                    }
                    if (!point->isColumnFixed()) {
                        int delta = pos.x() - basePoint.x();
                        pos.setX(cell.column() + delta);
                    }
                    newFormula.append(Region(pos, cell.sheet()).name());
                } else {
                    Region::Range* range = static_cast<Region::Range*>(element);
                    QRect r = range->rect();
                    if (!range->isTopFixed()) {
                        int delta = r.top() - basePoint.y();
                        r.setTop(cell.row() + delta);
                    }
                    if (!range->isBottomFixed()) {
                        int delta = r.bottom() - basePoint.y();
                        r.setBottom(cell.row() + delta);
                    }
                    if (!range->isLeftFixed()) {
                        int delta = r.left() - basePoint.x();
                        r.setLeft(cell.column() + delta);
                    }
                    if (!range->isRightFixed()) {
                        int delta = r.right() - basePoint.x();
                        r.setRight(cell.column() + delta);
                    }
                    newFormula.append(Region(r, cell.sheet()).name());
                }
            } else {
                newFormula.append(token.text());
            }
        }
        f.setExpression(newFormula);
    }
    Value val = f.eval();
    return calc->conv()->asBoolean(val).asBoolean();
}
Esempio n. 11
0
void CellEditor::permuteFixation()
{
    // Nothing to do, if not in reference selection mode.
    if (!d->selection->referenceSelection()) {
        return;
    }

    // Search for the last range before or the range at the cursor.
    int index = -1;
    const int cursorPosition = textCursor().position() - 1; // - '='
    const Tokens tokens = d->highlighter->formulaTokens();
    for (int i = 0; i < tokens.count(); ++i) {
        const Token token = tokens[i];
        if (token.pos() > cursorPosition) {
            break; // for loop
        }
        if (token.type() == Token::Cell || token.type() == Token::Range) {
            index = i;
        }
    }
    // Quit, if no range was found.
    if (index == -1) {
        return;
    }

    const Token token = tokens[index];
    Map *const map = d->selection->activeSheet()->map();
    QString regionName = token.text();
    // Filter sheet; truncates regionName; range without sheet name resides.
    Sheet *const sheet = Region(QString(), map).filterSheetName(regionName);
    const Region region(regionName, map, 0);
    // TODO Stefan: Skip named areas.
    if (!region.isValid()) {
        return;
    }
    // FIXME Stefan: need access to fixation, thus to Region::Range; must use iterator
    Region::Element *range = (*region.constBegin());
    QString result(sheet ? (sheet->sheetName() + '!') : QString());
    // Permute fixation.
    if (region.isSingular()) {
        char fixation = 0x00;
        if (range->isRowFixed()) {
            fixation += 0x01;
        }
        if (range->isColumnFixed()) {
            fixation += 0x02;
        }
        fixation += 0x01;

        int i = 0;
        result += permuteLocationFixation(regionName, i, fixation & 0x02, fixation & 0x01);
    } else {
        char fixation = 0x00;
        if (range->isBottomFixed()) {
            fixation += 0x01;
        }
        if (range->isRightFixed()) {
            fixation += 0x02;
        }
        if (range->isTopFixed()) {
            fixation += 0x04;
        }
        if (range->isLeftFixed()) {
            fixation += 0x08;
        }
        fixation += 0x01;

        int i = 0;
        result += permuteLocationFixation(regionName, i, fixation & 0x08, fixation & 0x04);
        Q_ASSERT(regionName[i] == ':');
        ++i;
        result += ':';
        result += permuteLocationFixation(regionName, i, fixation & 0x02, fixation & 0x01);
    }
    // Replace the range in the formula's expression.
    QString text = toPlainText();
    const int start = token.pos() + 1; // + '='
    const int length = token.text().length();
    setPlainText(text.replace(start, length, result));
    // Set the cursor to the end of the range.
    QTextCursor textCursor = this->textCursor();
    textCursor.setPosition(start + result.length());
    setTextCursor(textCursor);
}