Слот findNext в цикле просматривает ячейки, начиная с ячейки, расположенной правее курсора, и двигается вправо до достижения последнего столбца; затем процесс идет с первого столбца строки, расположенной ниже, и так продолжается, пока не будет найден требуемый текст или пока не будет достигнута самая последняя
ячейка. Например, если текущей является ячейка C24, поиск будет продолжаться по ячейкам D24, E24, … Z24, затем no A25, B25, C25, … Z25 и так далее, пока не будет достигнута ячейка Z999. Если соответствующее значение найдено, мы сбрасываем текущее выделение и перемещаем курсор на ячейку, в которой оно находится, и делаем активным окно, содержащее эту электронную таблицу Spreadsheet. При неудачном завершении поиска мы заставляем приложение выдать соответствующий звуковой сигнал.
Слот recalculate соответствует пункту меню Tools | Recalculate (Инструменты | Пересчитать). Он также вызывается в Spreadsheet автоматически по мере необходимости.
Мы выполняем цикл по всем ячейкам и вызываем функцию setDirty, которая помечает каждую из них для перерасчета значения. В следующий раз, когда QTableWidget для получения отображаемого в электронной таблице значения вызовет text для некоторой ячейки Cell, значение этой ячейки будет пересчитано.
Затем мы вызываем для области отображения функцию update для перерисовки
всей электронной таблицы. При этом используемый в QTableWidget программный код по перерисовке вызывает функцию text для каждой видимой ячейки для получения отображаемого значения. Поскольку функция setDirty вызывалась нами для каждой ячейки, в вызовах text будет использовано новое рассчитанное значение. В этом случае может потребоваться расчет невидимых ячеек, который будет проводиться до тех пор, пока не будут рассчитаны все ячейки, влияющие на правильное отображение текста в перерассчитанной области отображения. Этот расчет выполняется в классе Cell.
Слот setAutoRecalculate соответствует пункту меню Options | Auto—Recalculate. Если эта опция включена, мы сразу же пересчитаем всю электронную таблицу и будем уверены, что она показывает обновленные значения; впоследствии функция recalculate будет автоматически вызываться из somethingChanged.
Нам не нужно реализовывать специальную функцию для пункта меню Options | Show Grid, поскольку в QTableWidget уже содержится слот setShowGrid, который наследуется от базового класса QTableView. Остается только реализовать функцию Spreadsheet::sort, которая вызывается из MainWindow::sort:
04 QTableWidgetSelectionRange range = selectedRange;
05 int i;
06 for (i = 0; i < range.rowCount; ++i) {
07 QStringList row;
08 for (int j = 0; j < range.columnCount; ++j)
09 row.append(formula(range.topRow + i,
10 range.leftColumn + j));
11 rows.append(row);
12 }
13 qStableSort(rows.begin, rows.end, compare);
14 for (i = 0; i < range.rowCount; ++i) {
15 for (int j = 0; j < range.columnCount; ++j)
16 setFormula(range.topRow + i, range.leftColumn + j, rows[i][j]);
17 }
18 clearSelection;
19 somethingChanged;
20 }
Сортировка работает на текущей выделенной области и переупорядочивает строки в соответствии со значениями ключей порядка сортировки, хранящимися в объекте compare. Мы представляем каждую строку данных в QStringList, а выделенную область храним в виде списка строк. Мы используем алгоритм Qt qStableSort и для простоты сортируем по выражениям формул, а не по их значениям. Стандартные алгоритмы и структуры данных Qt рассматривается в главе 11 («Классы—контейнеры»).