[Предыдущая: Структура документа форматированного текста] [Содержание] [Следующая: Общие задачи редактирования форматированного текста]
Интерфейс QTextCursor
Интерфейс QTextCursor позволяет редактировать документы и их структуру таким способом, который должен быть знаком большинству пользователей текстовых редакторов и программ для редактирования документов. Документы форматированного текста могут иметь несколько курсоров, связанных с ними и каждый из них содержит информацию о своей позиции в документе и любое выделение, которое он может содержать. Основанная на курсоре парадигма делает обычные операции, такие как вырезание и вставка текста, простыми для реализации программно и также позволяют выполнять в документе более сложные операции редактирования.
Эта глава описывает большинства из общих операций редактирования которые вам потребуется выполнять используя курсор, от основных вставки текста и элементов документа до более сложных манипуляций со структурами документа.
Редактирование, основанное на курсоре
На простейшем уровне текстовые документы сделаны из строк символов, помеченных каким-либо образом для представления структуры блоков текста внутри документа. QTextCursor предоставляет основанный на курсоре интерфейс, который позволяет манипулировать содержимым QTextDocument на уровне символов. Так как элементы (блоки, фреймы, таблицы и так далее) также кодируются в потоку символов, структура документа может быть изменена курсором.
Курсор отслеживает свое положение внутри родительского документа и может сообщать информацию об окружающей структуре, такой как обрамляющий текстовый блок, фрейм, таблица или список. Форматы обрамляющих структур могут быть также непосредственно получены через курсор.
Использование курсора
Основное использование курсора это вставка или модифицирование текста внутри блока. Мы можем использовать курсор текстового редактора что бы сделать это:
QTextEdit *editor = new QTextEdit();
QTextCursor cursor(editor->textCursor());
Или же мы можем получить курсор прямо из документа:
QTextDocument *document = new QTextDocument(editor);
QTextCursor cursor(document);
Курсор установлен в начале документа, так что мы можем писать в первый (пустой) блок в документе.
Группирование операций курсора
Серия операций редактирования может быть упакованы вместе, так что они могут быть повторены или отменены вместе в одно действие. Это достигается использованием функций beginEditBlock() и endEditBlock() следующим способом, как в следующем примере где мы выделяем слово которое содержит курсор:
cursor.beginEditBlock();
cursor.movePosition(QTextCursor::StartOfWord);
cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
cursor.endEditBlock();
Если операции редактирования не группируются, документ автоматически записывает индивидуальные записи так что они могут быть отменены позже. Группирование операций в большие пакеты может сделать редактирование более эффективным как для пользователя, так и для приложения, но надо позаботиться не группировать слишком много операций вместе так как пользователь может пожелать более скрупулёзный контроль над процессом отмены.
Множественные курсоры
Множественные курсоры могут быть использованы для одновременного редактирования одного документа, хотя только один будет виден пользователю в виджете QTextEdit. QTextDocument обеспечивает что каждый курсор пишет текст корректно и не мешает любому другому.
Вставка элементов документа
QTextCursor предоставляет несколько функций которые могут быть использованы для изменения структуры документа форматированного текста. В основном эти функции позволяют создавать элементы документа с важной информацией о форматировании и они могут быть вставлены в документ в позиции курсора.
Первая группа функций вставляет элементы уровня блока и обновляет позицию курсора, но они не возвращают элемент, который был вставлен:
- insertBlock() вставляет новый текстовый блок (параграф) в документ в позицию курсора и перемещает курсор на начало нового блока.
- insertFragment() вставляет существующий фрагмент текста в документ в позицию курсора.
- insertImage() вставляет изображение в документ в позицию курсора.
- insertText() вставляет текст в документ в позицию курсора.
Вы можете исследовать содержимое элемента который был вставлен через интерфейс курсора.
Вторая группа функций вставляет элементы которые предоставляют структуру документа и возвращают структуру которая была вставлена:
- insertFrame() вставляет фрейм в документ после текущего блока курсора и перемещает курсор на начало пустого блока нового фрейма.
- insertList() вставляет список в документ в позицию курсора и перемещает курсор на начало первого элемента в списке.
- insertTable() вставляет таблицу в документ после текущего блока курсора и перемещает курсор на начало блока, следующего за таблицей.
Эти элементы или содержат или группируют вместе элементы в документе.
Текст и текстовые фрагменты
Текст может быть вставлен в текущий блок и текущем формате символов или в собственном формате который указывается вместе с текстом:
cursor.insertText(tr("Character formats"),
headingFormat);
cursor.insertBlock();
cursor.insertText(tr("Text can be displayed in a variety of "
"different character formats. "), plainFormat);
cursor.insertText(tr("We can emphasize text by "));
cursor.insertText(tr("making it italic"), emphasisFormat);
После того как формат символов используется вместе с курсором он становится форматом по умолчанию для любого текста вставленного с этим курсором до тех пор пока не будет указан другой формат символов.
Если курсор используется для вставки текста без указывания формата символов, то текст будет дан в формате символов, используемом в этой позиции в документе.
Блоки
Текстовые блоки вставляются в документ с функцией insertBlock().
QTextBlockFormat backgroundFormat = blockFormat;
backgroundFormat.setBackground(QColor("lightGray"));
cursor.setBlockFormat(backgroundFormat);
Курсор устанавливается на начало нового блока.
Фреймы
Фреймы вставляются в документ с использованием курсора и они будут размещены внутри текущего фрейма курсора после текущего блока. Следующий код показывает как фрейм может быть вставлен между двумя текстовыми блоками в корневом фрейме документа. Мы начинаем поиск текущего фрейма курсора:
QTextFrame *mainFrame = cursor.currentFrame();
cursor.insertText(...);
Мы вставляем некоторый текст в этот фрейм, затем мы устанавливаем формат фрейма для дочернего фрейма:
QTextFrameFormat frameFormat;
frameFormat.setMargin(32);
frameFormat.setPadding(8);
frameFormat.setBorder(4);
Формат фрейма задаст фрейму дополнительный отступ на 32 пиксела, внутреннее наполнение на 8 пикселов и границу шириной 4 пиксела. Смотрите документацию по QTextFrameFormat для получения дополнительной информации о форматах фреймов.
Фрейм вставляется в документ после предшествующего текста:
cursor.insertFrame(frameFormat);
cursor.insertText(...);
Мы добавляем некоторый текст в документ сразу после вставки фрейма. Так как текстовый курсор устанавливается внутри фрейма когда он вставляется в документ, этот текст также будет вставлен внутри фрейма.
Наконец, мы устанавливаем курсор снаружи фрейма беря последную доступную позицию курсора внутри фрейма которую мы записали ранее:
cursor = mainFrame->lastCursorPosition();
cursor.insertText(...);
Текст который мы добавили последним вставляется после дочернего фрейма в документе. Так как каждый фрейм заполняется текстовыми блоками, то это обеспечивает что дополнительные элементы всегда могут быть вставлены с помощью курсора.
Таблицы
Таблицы вставляются в документ с использованием курсора и они будут размещены внутри текущего фрейма курсора после текущего блока.
QTextCursor cursor(editor->textCursor());
QTextTable *table = cursor.insertTable(rows, columns, tableFormat);
Таблицы могут быть созданы с указанным форматом который определяет все свойства таблицы, такие как её выравнивание, цвет фона и используемый интервал между ячейками. Он также может определить ограничения каждому столбца позволяя каждому из них иметь фиксированную величину или изменять размеры с соответствии с доступным пространством.
QTextTableFormat tableFormat;
tableFormat.setBackground(QColor("#e0e0e0"));
QVector<QTextLength> constraints;
constraints << QTextLength(QTextLength::PercentageLength, 16);
constraints << QTextLength(QTextLength::PercentageLength, 28);
constraints << QTextLength(QTextLength::PercentageLength, 28);
constraints << QTextLength(QTextLength::PercentageLength, 28);
tableFormat.setColumnWidthConstraints(constraints);
QTextTable *table = cursor.insertTable(rows, columns, tableFormat);
Каждый из столбцов в таблице созданной выше возьмет определенный процент от доступной ширины. Заметьте, что формат таблицы необязателен; если вы вставите таблицу без формата то некоторые разумные значения по умолчанию будут использованы для параметров таблицы.
Так как ячейки могут содержать другие элементы документа они также могут быть отформатированы и стилизированы при необходимости.
Текст может быть добавлен в таблицу перемещением по каждой ячейке и вставкой текста.
cell = table->cellAt(0, 0);
cellCursor = cell.firstCursorPosition();
cellCursor.insertText(tr("Week"), charFormat);
Мы можем создать простую временную диаграмму следующим подходом:
for (column = 1; column < columns; ++column) {
cell = table->cellAt(0, column);
cellCursor = cell.firstCursorPosition();
cellCursor.insertText(tr("Team %1").arg(column), charFormat);
}
for (row = 1; row < rows; ++row) {
cell = table->cellAt(row, 0);
cellCursor = cell.firstCursorPosition();
cellCursor.insertText(tr("%1").arg(row), charFormat);
for (column = 1; column < columns; ++column) {
if ((row-1) % 3 == column-1) {
cell = table->cellAt(row, column);
QTextCursor cellCursor = cell.firstCursorPosition();
cellCursor.insertText(tr("On duty"), charFormat);
}
}
}
Списки
Списки блоков элементов могут быть автоматически созданы и вставлены в документ в текущую позицию курсора. Каждый список который создан таким способом требует что бы был указан формат списка:
QTextListFormat listFormat;
if (list) {
listFormat = list->format();
listFormat.setIndent(listFormat.indent() + 1);
}
listFormat.setStyle(QTextListFormat::ListDisc);
cursor.insertList(listFormat);
Код выше сначала проверяет не стоит ли курсор внутри существующего списка или если да, то дает формату нового списка удобный уровень отступа. Это позволяет вложенным спискам создаваться с увеличенным уровнем отступа. Более изощренная реализация будет также использовать различные типы символов для точек на каждом уровне листа.
Изображения
Встроенные изображения добавляются в документ через курсор в обычном порядке. В отличае большинства других элементов все свойства изображения указываются форматом изображения. Это значит что объект QTextImageFormat должен быть создан прежде чем изображение может быть вставлено:
QTextImageFormat imageFormat;
imageFormat.setName(":/images/advert.png");
cursor.insertImage(imageFormat);
Имя изображения ссылается на запись в файле ресурсов приложения. Метод используемый для наследования этого имени описан в Системе ресурсов Qt.
[Предыдущая: Структура документа форматированного текста] [Содержание] [Следующая: Общие задачи редактирования форматированного текста]
|