В функции QTableWidget::setCurrentCell() задаются два аргумента: индекс строки и индекс столбца. В приложении Электронная таблица обозначение A1 относится к ячейке (0, 0), а обозначение B27 относится к ячейке (26, 1). Для получения индекса строки из возвращаемого функцией QLineEdit::text() значения типа QString мы выделяем номер строки с помощью функции QString::mid() (которая возвращает подстроку с первой позиции до конца этой строки), преобразуем ее в целое число типа int при помощи функции QString::toInt() и вычитаем единицу. Для получения номера столбца мы вычитаем числовой код буквы «А» из числового кода первой буквы строки, преобразованной в прописную. Мы знаем, что строка будет иметь правильный формат, потому что осуществляемый нами контроль диалога с помощью QRegExpValidator делает кнопку OK активной только в том случае, если за буквой располагается не более трех цифр.
Функция goToCell() отличается от приводимого до сих пор программного кода тем, что она создает виджет (GoToCellDialog) в виде переменной стека. Мы столь же легко могли бы воспользоваться операторами new и delete, что увеличило бы программный код только на одну строку:
01 void MainWindow::goToCell()
02 {
03 GoToCellDialog *dialog = new GoToCellDialog(this);
04 if (dialog->exec()) {
05 QString str = dialog->lineEdit->text().toUpper();
06 spreadsheet->setCurrentCell(str.mid(1).toInt() - 1,
07 str[0].unicode() - 'A');
08 }
09 delete dialog;
10 }
Создание модальных диалоговых окон (и контекстных меню при переопределении QWidget::contextMenuEvent()) является обычной практикой программирования, поскольку такое окно (или меню) будет не нужно после его использования, и оно будет автоматически уничтожено при выходе из области видимости.
Теперь мы перейдем к созданию диалогового окна Sort. Это диалоговое окно является модальным и позволяет пользователю упорядочить текущую выбранную область, задавая в качестве ключей сортировки определенные столбцы. На рис. 3.14 показан пример сортировки, когда в качестве главного ключа сортировки используется столбец В, а в качестве вторичного ключа сортировки используется столбец А (в обоих случаях сортировка выполняется по возрастанию значений).
Рис. 3.14. Сортировка выделенной области электронной таблицы.
01 void MainWindow::sort()
02 {
03 SortDialog dialog(this);
04 QTableWidgetSelectionRange range = spreadsheet->selectedRange();
05 dialog.setColumnRange('A' + range.leftColumn(),
06 'А' + range.rightColumn());
07 if (dialog.exec()) {
08 SpreadsheetCompare compare;
09 compare.keys[0] =
10 dialog.primaryColumnCombo->currentIndex();
11 compare.keys[1] =
12 dialog.secondaryColumnCombo->currentIndex() - 1;
13 compare.keys[2] =
14 dialog.tertiaryColumnCombo->currentIndex() - 1;
15 compare.ascending[0] =
16 (dialog.primaryOrderCombo->currentIndex() == 0);
17 compare.ascending[1] =
18 (dialog.secondaryOrderCombo->currentIndex() == 0);
19 compare.ascending[2] =
20 (dialog.tertiaryOrderCombo->currentIndex() == 0);
21 spreadsheet->sort(compaге);
22 }
23 }
Порядок действий при программировании функции sort() аналогичен порядку действий, применяемому при программировании функции goToCell();
• мы создаем диалоговое окно в стеке и инициализируем его;
• мы вызываем диалоговое окно при помощи функции exec();
• если пользователь нажимает кнопку OK, мы используем введенные пользователем в диалоговом окне значения соответствующим образом.
Вызов setColumnRange() задает столбцы, выбранные для сортировки. Например, при выделении области, показанной на рис. 3.14, функция range.leftColumn() возвратит 0, давая в результате 'A' + 0 = 'A', a range.rightColumn() возвратит 2, давая в результате 'A' + 2 = 'C'.
В объекте compare хранятся первичный, вторичный и третичный ключи, а также порядок сортировки по ним. (Определение класса SpreadsheetCompare мы рассмотрим в следующей главе.) Этот объект используется функцией Spreadsheet::sort() для сортировки строк. В массиве keys содержатся номера столбцов ключей. Например, если выбрана область с C2 по E5, то столбец С будет иметь индекс 0. В массиве ascending в переменных типа bool хранятся значения направления сортировки для каждого ключа. Функция QComboBox::currentIndex() возвращает индекс текущего элемента (начиная с 0). Для вторичного и третичного ключей мы вычитаем единицу из текущего элемента, чтобы учесть значения «None» (отсутствует).