[Предыдущая: Модели-посредники] [Содержание] Создание собственных моделей
|
flags() | Используется другими компонентами для получения информации о каждом элементе, предоставляемом моделью. Во многих моделях комбинация флагов будет включать в себя Qt::ItemIsEnabled и Qt::ItemIsSelectable. |
data() | Используется для снабжения представлений и делегатов элементами данных. Как правило, модели нуждаются только в снабжении данными для Qt::DisplayRole и любых специфичных для приложения пользовательских ролей, но будет хорошей практикой предоставить данные для Qt::ToolTipRole, Qt::AccessibleTextRole и Qt::AccessibleDescriptionRole. |
headerData() | Предоставляется представлениям с информацией для показа в их заголовках. Информация извлекается представлениями, которые могут отобразить информацию заголовков. |
rowCount() | Предоставляет количество строк данных, доступных в модели. |
Эти четыре функции должны быть реализованы во всех видах моделей, включая модели списков (подклассы QAbstractListModel) и табличные модели (подклассы QAbstractTableModel).
Кроме того, следующие функции должны быть реализованы в прямых наследниках QAbstractTableModel и QAbstractItemModel:
columnCount() | Предоставляет количество столбцов данных, доступных в модели. Модели списков не предоставляют эту функцию поскольку она уже реализована в QAbstractListModel. |
Редактируемые модели разрешают модифицировать элементы данных, а также могут предоставить функции, разрешающие вставку и удаление строк и столбцов. Чтобы разрешить редактирование, должны быть корректно реализованы следующие функции:
flags() | Должна возвращать комбинацию флагов, соответствующую каждому элементу. В частности, возвращаемое этой функцией значение, в дополнение к используемым в модели только для чтения значениям, должно включать в себя Qt::ItemIsEditable. |
setData() | Используется для модификации элемента данных, связанного с заданным модельным индексом. Чтобы иметь возможность принимать пользовательский ввод, предоставляемый элементами пользовательского интерфейса, эта функция должна обрабатывать данные, связанные с Qt::EditRole. Реализация может также принимать данные, связанные со многими различными видами ролей, задаваемыми Qt::ItemDataRole. После изменения элемента данных модели должны испустить сигнал dataChanged(), чтобы уведомить другие компоненты об изменении. |
setHeaderData() | Используется для модификации информации в горизонтальном и вертикальном заголовке. После изменения элемента данных модели должны испустить сигнал headerDataChanged(), чтобы уведомить другие компоненты об изменении. |
Все типы моделей могут поддерживать вставку и удаление строк. Табличные модели и иерархические модели могут также поддерживать вставку и удаление столбцов. Важно уведомить другие компоненты об изменениях в измерениях модели как до, так и после того как они произойдут. В результате, следующие функции могут быть реализованы для разрешения модели изменять размеры, но реализации должны гарантировать, что вызываются соответствующие функции для уведомления присоединенных представлений и делегатов:
insertRows() | Используется для добавления новых строк и элементов данных во все виды моделей. Реализации должны содержать вызов beginInsertRows() перед вставкой новых строк в любые базовые структуры данных и вызов endInsertRows() незамедлительно после. |
removeRows() | Используется для удаления строк и содержащихся в них элементов данных изо всех видов моделей. Реализации должны содержать вызов beginRemoveRows() перед удалением столбцов из базовых структур данных и вызов endRemoveRows() незамедлительно после. |
insertColumns() | Используется для добавления новых столбцов и элементов данных в табличные и иерархические модели. Реализации должны содержать вызов beginInsertColumns() перед вставкой строк в любые базовые структуры данных и вызов endInsertColumns() незамедлительно после. |
removeColumns() | Используется для удаления столбцов и содержащихся в них элементов данных из табличных и иерархических моделей. Реализации должны содержать вызов beginRemoveColumns() перед удалением столбцов из любых базовых структур данных и вызов endRemoveColumns() незамедлительно после. |
Как правило, эти функции возвращают true если операция была успешной. Однако могут быть случаи, когда операция достигла успеха только частично; например, если строк может быть вставлено меньше указанного количества. В таких случаях модель должна возвращать false, чтобы, обозначив фатальную ошибку, дать возможность каким-нибудь присоединенным компонентам обработать ситуацию.
Сигналы, испускаемые функциями, вызванными в реализациях API изменения размера, дают шанс присоединенным компонентам принять меры до того, как какие-либо данные станут недоступными. Инкапсуляция операций вставки и удаления с начальными и конечными функциями также дает возможность модели корректно управлять постоянными модельными индексами.
Как правило, начальные и конечные функции способны уведомлять другие компоненты об изменениях в базовой структуре модели. Для более сложных изменений в структуре модели, приводящие возможно к преобразованию или сортировке данных, необходимо испустить сигнал layoutChanged(), чтобы заставить все присоединенные представления обновиться.
Ленивое заполнение данных модели эффективно разрешает запросы информации о модели, отложенные до тех пор пока они фактически не понадобятся представлениям.
Некоторые модели нуждаются в получении данных из удаленных источников или должны выполнять ресурсоемкие операции, чтобы получить информацию о способе организации данных. Так как представления обычно требуют так много информации, сколько возможно по порядку для правильного отображения данных модели, для уменьшения излишних откликов (follow-up) на запрашиваемые данные может быть полезным ограничить количество возвращаемой к ним информации.
В иерархических моделях, где нахождение количества дочерних элементов заданного элемента является дорогостоящей операцией, полезно обеспечить, чтобы реализация rowCount() модели вызывалась только когда это необходимо. В таких случаях, функция hasChildren() может быть переопределена для предоставления представлениям экономного способа проверки наличия дочерних элементов и, в случае QTreeView, рисования соответствующего оформления их родительского элемента.
Возвратит ли переопределенная функция hasChildren() true или false, для представлений нет необходимости вызывать rowCount(), чтобы узнать сколько имеется дочерних элементов. Например, QTreeView не нужно знать сколько имеется дочерних элементов, если родительский элемент не развернут для их показа.
Если известно, что многие элементы имеют дочерние элементы, переопределение hasChildren() для безусловного возврата true является иногда полезным методом. Это гарантирует, что каждый элемент может позднее проверить наличие дочерних элементов при выполнении начального заполнения данных модели так быстро, как это возможно. Единственное неудобство - это то, что элементы без дочерних элементов в некоторых представлениях могут отображаться неправильно пока пользователь пытается просмотреть несуществующие дочерние элементы.
Иерархические модели должны предоставить функции, которые могут вызываться представлениями для навигации в древовидных структурах, которые они отображают, и получения модельных индексов элементов.
Так как структура, открытая представлениям, определяется базовой структурой данных, создание собственных модельных индексов для каждого подкласса модели обеспечивается реализацией следующих функций:
index() | Передавая модельный индекс родительского элемента, эта функция разрешает представлениям и делегатам обращаться к дочерним элементам этого элемента. Если не найдено допустимого дочернего элемента - соответствующего указанным строке, столбцу и родительскому модельному индексу, функция должна вернуть QModelIndex(), который является ошибочным модельным индексом. |
parent() | Предоставляет модельный индекс, соответствующий родителю какого-либо дочернего элемента. Если указанный модельный индекс соответствует элементу верхнего уровня модели, или если у элемента в модели нет правильного родителя, функция должна вернуть неправильный модельный индекс, созданный с помощью пустого конструктора QModelIndex(). |
Обе приведенные выше функции используют фабрику функций createIndex() для генерации индексов, используемых другими компонентами. Для моделей является нормой снабжать эту функцию каким-нибудь уникальным идентификатором, чтобы гарантировать что модельный индекс может быть перепривязан к соответствующему элементу позднее.
Классы модель/представление поддерживают операции перетаскивания (drag and drop), предоставляя поведение по умолчанию, что подходит многим приложениям. Тем не менее, возможно также внести изменения в способ кодирования элементов во время операций перетаскивания, копируются ли они по умолчанию или перемещаются, и как они вставляются в существующие модели.
Кроме того, классы вспомогательных представлений реализуют специализированное поведение, что отвечает ожиданиям существующих разработчиков. Раздел Вспомогательные представления предоставит обзор этого поведения.
По умолчанию, встроенные модели и представления используют внутренний MIME-тип (application/x-qabstractitemmodeldatalist) для передачи информации о модельных индексах. Это задает данные для списка элементов, содержащего номера строк и столбцов для каждого элемента и информацию о ролях, поддерживаемых для каждого элемента.
Закодированные с использованием этого MIME-типа данные могут быть получены с помощью вызова QAbstractItemModel::mimeData() с QModelIndexList, содержащим элементы для преобразования в последовательную форму.
При реализации поддержки перетаскивания в пользовательской модели, можно экспортировать элементы данных в специализированных форматах переопределив следующую функцию:
mimeData() | Эта функция может быть переопределена таким образом, чтобы возвращать данные в форматах, отличных от стандартного внутреннего MIME-типа application/x-qabstractitemmodeldatalist. Подклассы могут получить стандартный объект QMimeData из базового класса и добавить в него данные в дополнительных форматах. |
Для многих моделей полезно предоставить содержимое элементов в общем формате, представленном одним из MIME-типов, таких как text/plain или image/png. Обратите внимание на то, что изображения, цвета и документы HTML могут быть легко добавлены в объект QMimeData с помощью функций QMimeData::setImageData(), QMimeData::setColorData() и QMimeData::setHtml().
Когда операция перетаскивания выполняется в представлении, основная модель запрашивается для определения поддерживаемых ею типов операций и MIME-типов, которые она может принимать. Эта информация предоставляется функциями QAbstractItemModel::supportedDropActions() и QAbstractItemModel::mimeTypes(). Модели, которые не переопределяют реализации, предоставляемые QAbstractItemModel, поддерживают для элементов операции копирования и стандартный внутренний MIME-тип.
Когда преобразованный в последовательную форму (serialized) элемент данных отпускается над представлением, данные вставляются в текущую модель, используя ее реализацию QAbstractItemModel::dropMimeData(). Стандартная реализация этой функции никогда не затирает какие-либо данные в модели; вместо этого она попытается вставить элементы данных либо на одном уровне с элементом, либо в качестве дочерних этого элемента.
Чтобы воспользоваться реализацией по умолчанию QAbstractItemModel для встроенного MIME-типа, новые модели должны обеспечить переопределение следующих функций:
insertRows() | Эти функции разрешают модели автоматическую вставку новых данных используя существующую реализацию, предоставляемую QAbstractItemModel::dropMimeData(). |
insertColumns() | |
setData() | Разрешает заполнять элементами новые строки и столбцы. |
setItemData() | Эта функция предоставляет более эффективную поддержку заполнения новых элементов. |
Чтобы принять другие формы данных эти функции должны быть переопределены:
supportedDropActions() | Используется чтобы возвратить сочетание действий отпускания (drop actions), указывающих типы операций перетаскивания, которые принимает модель. |
mimeTypes() | Используется чтобы возвращать список MIME-типов, которые могут быть декодированы и обработаны моделью. Как правило, MIME-типы, которые поддерживаются для ввода в модель, являются теми же, которые после раскодирования данных могут использоваться внешними компонентами. |
dropMimeData() | Выполняет действительное раскодирование данных, переданных операциями перетаскивания, определяет где в модели они были положены и вставляет новые строки и столбцы там, где необходимо. Как реализуется эта функция в подклассах - зависит от требований данных, доступных в каждой модели. |
Если реализация функции dropMimeData() изменяет измерения модели, вставляя или удаляя строки или столбцы, или же если элементы данных модифицировались, осторожность требует убедиться, что все соответствующие сигналы испущены. Полезно просто вызвать другие переопределенные функции в подклассе, такие как setData(), insertRows() и insertColumns(), чтобы убедиться, что модель ведет себя соответственно.
Для того, чтобы убедиться что операции перетаскивания работают правильно, важно переопределить следующие функции, которые удаляют данные из модели:
За дополнительной информацией о перетаскивании с представлениями элементов обратитесь к Использование перетаскивания (Drag and Drop) с представлениями элементов.
Вспомогательные представления (QListWidget, QTableWidget и QTreeWidget) замещают стандартную функциональность перетаскивания чтобы обеспечить меньшую гибкость, но более естественное поведение, подходящее многим приложениям. Например, так как наиболее распространено отпускание данных в ячейки QTableWidget с заменой имеющегося содержимого переданными данными, базовая модель будет устанавливать данные в элементы-приемник охотнее, чем вставлять в модель новые строки и строки. Для получения дополнительной информации о перетаскивании во вспомогательных представлениях смотрите Использование перетаскивания (Drag and Drop) с представлениями элементов.
Функция canFetchMore() проверяет, содержит ли родитель дополнительные доступные данные и соответственно возвращает true или false. Функция fetchMore() извлекает данные, базирующиеся в указанном родителе. Обе этих функции могут комбинироваться, например, в запросе к базе данных содержать инкрементные данные для заполнения QAbstractItemModel. Мы переопределили canFetchMore() чтобы указать, если для извлечения имеется больше данных, и fetchMore() для заполнения модели по требованию.
Другой пример будет динамически заполнять древовидные модели, в нем мы переопределяем fetchMore() когда ветвь дерева в древовидной модели является раскрытой.
Если ваша переопределенная fetchMore() добавляет строки к модели, вам нужно вызывать beginInsertRows() и endInsertRows(). Кроме того, и canFetchMore() и fetchMore() должны быть переопределены поскольку их реализации по умолчанию возвращают false и ничего не делают.
[Предыдущая: Модели-посредники] [Содержание]
Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies) | Торговые марки | Qt 4.5.3 |
Попытка перевода Qt документации. Если есть желание присоединиться, или если есть замечания или пожелания, то заходите на форум: Перевод Qt документации на русский язык... Люди внесшие вклад в перевод: Команда переводчиков |