Жасмин Бланшет - QT 4: программирование GUI на С++ стр 28.

Шрифт
Фон

Слот findNext() в цикле просматривает ячейки, начиная с ячейки, расположенной правее курсора, и двигается вправо до достижения последнего столбца; затем процесс идет с первого столбца строки, расположенной ниже, и так продолжается, пока не будет найден требуемый текст или пока не будет достигнута самая последняя ячейка. Например, если текущей является ячейка C24, поиск будет продолжаться по ячейкам D24, E24, … Z24, затем no A25, B25, C25, … Z25 и так далее, пока не будет достигнута ячейка Z999. Если соответствующее значение найдено, мы сбрасываем текущее выделение и перемещаем курсор на ячейку, в которой оно находится, и делаем активным окно, содержащее эту электронную таблицу Spreadsheet. При неудачном завершении поиска мы заставляем приложение выдать соответствующий звуковой сигнал.

01 void Spreadsheet::findPrevious(const QString &str, Qt::CaseSensitivity cs)

02 {

03 int row = currentRow();

04 int column = currentColumn() - 1;

05 while (row>= 0) {

06 while (column >= 0) {

07 if (text(row, column).contains(str, cs)) {

08 clearSelection();

09 setCurrentCell(row, column);

10 activateWindow();

11 return;

12 }

13 --column;

14 }

15 column = ColumnCount - 1;

16 --row;

17 }

18 QApplication::beep();

19 }

Слот findPrevious() похож на findNext(), но здесь цикл выполняется в обратном направлении и заканчивается в ячейке A1.

Реализация других меню

Теперь мы реализуем слоты для пунктов меню Tools и Options.

QT 4: программирование GUI на С++

Рис. 4.7. Меню Tools и Options приложения Электронная таблица.

01 void Spreadsheet::recalculate()

02 {

03 for (int row = 0; row < RowCount; ++row) {

04 for (int column = 0; column < ColumnCount; ++column) {

05 if (cell(row, column))

06 cell(row, column)->setDirty();

07 }

08 }

09 viewport()->update();

10 }

Слот recalculate() соответствует пункту меню Tools | Recalculate (Инструменты | Пересчитать). Он также вызывается в Spreadsheet автоматически по мере необходимости.

Мы выполняем цикл по всем ячейкам и вызываем функцию setDirty(), которая помечает каждую из них для перерасчета значения. В следующий раз, когда QTableWidget для получения отображаемого в электронной таблице значения вызовет text() для некоторой ячейки Cell, значение этой ячейки будет пересчитано.

Затем мы вызываем для области отображения функцию update() для перерисовки всей электронной таблицы. При этом используемый в QTableWidget программный код по перерисовке вызывает функцию text() для каждой видимой ячейки для получения отображаемого значения. Поскольку функция setDirty() вызывалась нами для каждой ячейки, в вызовах text() будет использовано новое рассчитанное значение. В этом случае может потребоваться расчет невидимых ячеек, который будет проводиться до тех пор, пока не будут рассчитаны все ячейки, влияющие на правильное отображение текста в перерассчитанной области отображения. Этот расчет выполняется в классе Cell.

01 void Spreadsheet::setAutoRecalculate(bool recalc)

02 {

03 autoRecalc = recalc;

04 if (autoRecalc)

05 recalculate();

06 }

Слот setAutoRecalculate() соответствует пункту меню Options | Auto-Recalculate. Если эта опция включена, мы сразу же пересчитаем всю электронную таблицу и будем уверены, что она показывает обновленные значения; впоследствии функция recalculate() будет автоматически вызываться из somethingChanged().

Нам не нужно реализовывать специальную функцию для пункта меню Options | Show Grid, поскольку в QTableWidget уже содержится слот setShowGrid(), который наследуется от базового класса QTableView. Остается только реализовать функцию Spreadsheet::sort(), которая вызывается из MainWindow::sort():

01 void Spreadsheet::sort(const SpreadsheetCompare &compare)

02 {

03 QList<QStringList> rows;

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 ("Классы-контейнеры").

QT 4: программирование GUI на С++

Рис. 4.8. Хранение выделенной области в виде списка строк.

В качестве аргументов функции qStableSort() используются итератор начала, итератор конца и функция сравнения. Функция сравнения имеет два аргумента (оба имеют тип QStringLists), и она возвращает true, когда первый аргумент "больше, чем" второй аргумент, и false в противном случае. Передаваемый как функция сравнения объект compare фактически не является функцией, но он может использоваться и в таком качестве, в чем мы вскоре сможем убедиться.

Ваша оценка очень важна

0
Шрифт
Фон

Помогите Вашим друзьям узнать о библиотеке