void PageItem_Table::mergeCells(int row, int column, int numRows, int numCols) { ASSERT_VALID(); if (!validCell(row, column) || !validCell(row + numRows - 1, column + numCols - 1)) return; CellArea newArea(row, column, numCols, numRows); // Unite intersecting areas. QMutableListIterator<CellArea> areaIt(m_cellAreas); while (areaIt.hasNext()) { CellArea oldArea = areaIt.next(); if (newArea.intersects(oldArea)) { // The two areas intersect, so unite them. newArea = newArea.united(oldArea); // Reset row/column span of old spanning cell, then remove old area. TableCell oldSpanningCell = cellAt(oldArea.row(), oldArea.column()); oldSpanningCell.setRowSpan(1); oldSpanningCell.setColumnSpan(1); areaIt.remove(); } } // Set row/column span of new spanning cell, and add new area. TableCell newSpanningCell = cellAt(newArea.row(), newArea.column()); newSpanningCell.setRowSpan(newArea.height()); newSpanningCell.setColumnSpan(newArea.width()); m_cellAreas.append(newArea); // Update cells. TODO: Not for entire table. updateCells(); // If merged area covers active position, move to the spanning cell. if (newArea.contains(m_activeRow, m_activeColumn)) moveTo(newSpanningCell); // Remove all cells covered by the merged area from the selection. QMutableSetIterator<TableCell> cellIt(m_selection); while (cellIt.hasNext()) { TableCell cell = cellIt.next(); if (newArea.contains(cell.row(), cell.column()) && !(cell.row() == newArea.row() && cell.column() == newArea.column())) cellIt.remove(); } emit changed(); ASSERT_VALID(); }
void PageItem_Table::updateCells(int startRow, int startColumn, int endRow, int endColumn) { if (startRow > endRow || startColumn > endColumn) return; // Invalid area. if (!validCell(startRow, startColumn) || !validCell(endRow, endColumn)) return; // Invalid area. foreach (const QList<TableCell>& cellRow, m_cellRows) foreach (TableCell cell, cellRow) cell.updateContent(); }
void PageItem_Table::selectCell(int row, int column) { if (!validCell(row, column)) return; m_selection.insert(cellAt(row, column)); emit selectionChanged(); }
void PageItem_Table::assertValid() const { // Check list sizes. Q_ASSERT(rows() == m_rowPositions.size()); Q_ASSERT(rows() == m_rowHeights.size()); Q_ASSERT(columns() == m_columnPositions.size()); Q_ASSERT(columns() == m_columnWidths.size()); Q_ASSERT(rows() == m_cellRows.size()); foreach (QList<TableCell> cellRow, m_cellRows) Q_ASSERT(columns() == cellRow.size()); for (int row = 0; row < rows(); ++row) { for (int col = 0; col < columns(); ++col) { TableCell cell = m_cellRows[row][col]; // Check that the cell reports correct row and column. Q_ASSERT(cell.row() == row); Q_ASSERT(cell.column() == col); // Check that the row and column span is sane. Q_ASSERT(cell.rowSpan() >= 1 && cell.columnSpan() >= 1); if (cell.rowSpan() > 1 || cell.columnSpan() > 1) { // Check that there's exactly one matching cell area. CellArea expectedArea(cell.row(), cell.column(), cell.columnSpan(), cell.rowSpan()); Q_ASSERT(m_cellAreas.count(expectedArea) == 1); } } } // Check that the active position is in this table. Q_ASSERT(validCell(m_activeRow, m_activeColumn)); // Check that the active cell is valid. Q_ASSERT(m_activeCell.isValid()); Q_ASSERT(validCell(m_activeCell.row(), m_activeCell.column())); // Check that selected cells are valid. foreach (const TableCell& cell, m_selection) { Q_ASSERT(cell.isValid()); Q_ASSERT(validCell(cell.row(), cell.column())); }
void PageItem_Table::selectCells(int startRow, int startColumn, int endRow, int endColumn) { if (!validCell(startRow, startColumn) || !validCell(endRow, endColumn)) return; const TableCell startCell = cellAt(startRow, startColumn); const TableCell endCell = cellAt(endRow, endColumn); const int topRow = qMin(startCell.row(), endCell.row()); const int bottomRow = qMax(startCell.row() + startCell.rowSpan() - 1, endCell.row() + endCell.rowSpan() - 1); const int leftCol = qMin(startCell.column(), endCell.column()); const int rightCol = qMax(startCell.column() + startCell.columnSpan() - 1, endCell.column() + endCell.columnSpan() - 1); for (int row = topRow; row <= bottomRow; ++row) for (int col = leftCol; col <= rightCol; ++col) selectCell(row, col); emit selectionChanged(); }
void PageItem_Table::activateCell(const TableCell& cell) { ASSERT_VALID(); TableCell newActiveCell = validCell(cell.row(), cell.column()) ? cell : cellAt(0, 0); // Deselect previous active cell and its text. m_activeCell.textFrame()->setSelected(false); m_activeCell.textFrame()->itemText.deselectAll(); // Set the new active cell and select it. m_activeCell = newActiveCell; m_activeCell.textFrame()->setSelected(true); m_Doc->currentStyle = m_activeCell.textFrame()->currentStyle(); m_activeRow = m_activeCell.row(); m_activeColumn = m_activeCell.column(); emit selectionChanged(); ASSERT_VALID(); }
TableCell PageItem_Table::cellAt(int row, int column) const { if (!validCell(row, column)) return TableCell(); TableCell cell = m_cellRows[row][column]; QList<CellArea>::const_iterator areaIt; for (areaIt = m_cellAreas.begin(); areaIt != m_cellAreas.end(); ++areaIt) { CellArea area = (*areaIt); if (area.contains(row, column)) { // Cell was contained in merged area, so use spanning cell. cell = m_cellRows[area.row()][area.column()]; break; } } return cell; }
/** * Prompts user for input * @param response Pointer to store address user inputted * @param value Pointer to store value user inputted */ bool prompt(char *response, char *value, int socket) { // printf("In %s\n",__func__); SOCKET_WRITE(socket, "Enter row and column you would like to manipulate or enter 'exit' to exit program: ", 0); read(socket, response, IN_BUF_LIMIT); printf("%s\n", response); if (strcmp(response, "exit") == 0) return false; response[0] = toupper(response[0]); while(!validCell(response) || !response) { SOCKET_WRITE(socket, "Invalid cell. Enter cell to edit ('exit' to quit): ", 0); read(socket, response, IN_BUF_LIMIT); if (strcmp(response, "exit") == 0) return false; response[0] = toupper(response[0]); } SOCKET_WRITE(socket, "Enter value: ", 0); read(socket, value, IN_BUF_LIMIT); return true; }