www.pudn.com > qtbook-examples.zip > spreadsheet.cpp
#include#include #include #include #include #include #include #include #include #include using namespace std; #include "cell.h" #include "spreadsheet.h" Spreadsheet::Spreadsheet(QWidget *parent, const char *name) : QTable(parent, name) { autoRecalc = true; setSelectionMode(Single); clear(); } void Spreadsheet::clear() { setNumRows(0); setNumCols(0); setNumRows(NumRows); setNumCols(NumCols); for (int i = 0; i < NumCols; i++) horizontalHeader()->setLabel(i, QChar('A' + i)); setCurrentCell(0, 0); } Cell *Spreadsheet::cell(int row, int col) const { return (Cell *)item(row, col); } QString Spreadsheet::formula(int row, int col) const { Cell *c = cell(row, col); if (c) return c->formula(); else return ""; } void Spreadsheet::setFormula(int row, int col, const QString &formula) { Cell *c = cell(row, col); if (c) { c->setFormula(formula); updateCell(row, col); } else { setItem(row, col, new Cell(this, formula)); } } QString Spreadsheet::currentLocation() const { return QChar('A' + currentColumn()) + QString::number(currentRow() + 1); } QString Spreadsheet::currentFormula() const { return formula(currentRow(), currentColumn()); } QWidget *Spreadsheet::createEditor(int row, int col, bool initFromCell) const { QLineEdit *lineEdit = new QLineEdit(viewport()); lineEdit->setFrame(false); if (initFromCell) lineEdit->setText(formula(row, col)); return lineEdit; } void Spreadsheet::endEdit(int row, int col, bool accepted, bool wasReplacing) { QLineEdit *lineEdit = (QLineEdit *)cellWidget(row, col); if (!lineEdit) return; QString oldFormula = formula(row, col); QString newFormula = lineEdit->text(); QTable::endEdit(row, col, false, wasReplacing); if (accepted && newFormula != oldFormula) { setFormula(row, col, newFormula); somethingChanged(); } } void Spreadsheet::somethingChanged() { if (autoRecalc) recalculate(); emit modified(); } bool Spreadsheet::writeFile(const QString &fileName) { QFile file(fileName); if (!file.open(IO_WriteOnly)) { QMessageBox::warning(this, tr("Spreadsheet"), tr("Cannot write file %1:\n%2.") .arg(file.name()) .arg(file.errorString())); return false; } QDataStream out(&file); out.setVersion(5); out << (Q_UINT32)MagicNumber; QApplication::setOverrideCursor(waitCursor); for (int row = 0; row < NumRows; ++row) { for (int col = 0; col < NumCols; ++col) { QString str = formula(row, col); if (!str.isEmpty()) out << (Q_UINT16)row << (Q_UINT16)col << str; } } QApplication::restoreOverrideCursor(); return true; } bool Spreadsheet::readFile(const QString &fileName) { QFile file(fileName); if (!file.open(IO_ReadOnly)) { QMessageBox::warning(this, tr("Spreadsheet"), tr("Cannot read file %1:\n%2.") .arg(file.name()) .arg(file.errorString())); return false; } QDataStream in(&file); in.setVersion(5); Q_UINT32 magic; in >> magic; if (magic != MagicNumber) { QMessageBox::warning(this, tr("Spreadsheet"), tr("The file is not a " "Spreadsheet file.")); return false; } clear(); Q_UINT16 row; Q_UINT16 col; QString str; QApplication::setOverrideCursor(waitCursor); while (!in.atEnd()) { in >> row >> col >> str; setFormula(row, col, str); } QApplication::restoreOverrideCursor(); return true; } void Spreadsheet::cut() { copy(); del(); } void Spreadsheet::copy() { QTableSelection sel = selection(); QString str; for (int i = 0; i < sel.numRows(); ++i) { if (i > 0) str += "\n"; for (int j = 0; j < sel.numCols(); ++j) { if (j > 0) str += "\t"; str += formula(sel.topRow() + i, sel.leftCol() + j); } } QApplication::clipboard()->setText(str); } QTableSelection Spreadsheet::selection() { if (QTable::selection(0).isEmpty()) return QTableSelection(currentRow(), currentColumn(), currentRow(), currentColumn()); return QTable::selection(0); } void Spreadsheet::paste() { QTableSelection sel = selection(); QString str = QApplication::clipboard()->text(); QStringList rows = QStringList::split("\n", str, true); int numRows = rows.size(); int numCols = rows.first().contains("\t") + 1; if (sel.numRows() * sel.numCols() != 1 && (sel.numRows() != numRows || sel.numCols() != numCols)) { QMessageBox::information(this, tr("Spreadsheet"), tr("The information cannot be pasted because the " "copy and paste areas aren't the same size.")); return; } for (int i = 0; i < numRows; ++i) { QStringList cols = QStringList::split("\t", rows[i], true); for (int j = 0; j < numCols; ++j) { int row = sel.topRow() + i; int col = sel.leftCol() + j; if (row < NumRows && col < NumCols) setFormula(row, col, cols[j]); } } somethingChanged(); } void Spreadsheet::del() { QTableSelection sel = selection(); for (int i = 0; i < sel.numRows(); ++i) { for (int j = 0; j < sel.numCols(); ++j) delete cell(sel.topRow() + i, sel.leftCol() + j); } clearSelection(); } void Spreadsheet::selectRow() { clearSelection(); QTable::selectRow(currentRow()); } void Spreadsheet::selectColumn() { clearSelection(); QTable::selectColumn(currentColumn()); } void Spreadsheet::selectAll() { clearSelection(); selectCells(0, 0, NumRows - 1, NumCols - 1); } void Spreadsheet::findNext(const QString &str, bool caseSensitive) { int row = currentRow(); int col = currentColumn() + 1; while (row < NumRows) { while (col < NumCols) { if (text(row, col).contains(str, caseSensitive)) { clearSelection(); setCurrentCell(row, col); setActiveWindow(); return; } ++col; } col = 0; ++row; } qApp->beep(); } void Spreadsheet::findPrev(const QString &str, bool caseSensitive) { int row = currentRow(); int col = currentColumn() - 1; while (row >= 0) { while (col >= 0) { if (text(row, col).contains(str, caseSensitive)) { clearSelection(); setCurrentCell(row, col); setActiveWindow(); return; } --col; } col = NumCols - 1; --row; } qApp->beep(); } void Spreadsheet::recalculate() { int row; for (row = 0; row < NumRows; ++row) { for (int col = 0; col < NumCols; ++col) { if (cell(row, col)) cell(row, col)->setDirty(); } } for (row = 0; row < NumRows; ++row) { for (int col = 0; col < NumCols; ++col) { if (cell(row, col)) updateCell(row, col); } } } void Spreadsheet::sort(const SpreadsheetCompare &compare) { vector rows; QTableSelection sel = selection(); int i; for (i = 0; i < sel.numRows(); ++i) { QStringList row; for (int j = 0; j < sel.numCols(); ++j) row.push_back(formula(sel.topRow() + i, sel.leftCol() + j)); rows.push_back(row); } stable_sort(rows.begin(), rows.end(), compare); for (i = 0; i < sel.numRows(); ++i) { for (int j = 0; j < sel.numCols(); ++j) setFormula(sel.topRow() + i, sel.leftCol() + j, rows[i][j]); } clearSelection(); somethingChanged(); } void Spreadsheet::setAutoRecalculate(bool on) { autoRecalc = on; if (autoRecalc) recalculate(); } bool SpreadsheetCompare::operator()(const QStringList &row1, const QStringList &row2) const { for (int i = 0; i < NumKeys; ++i) { int column = keys[i]; if (column != -1) { if (row1[column] != row2[column]) { if (ascending[i]) return row1[column] < row2[column]; else return row1[column] > row2[column]; } } } return false; }