-
Notifications
You must be signed in to change notification settings - Fork 8
Копирование и вставка элементов на диаграммах
Копирование и вставка основаны на использовании QClipboard в качестве буфера, содержащего необходимые свойства копируемых элементов.
- Глубокое копирование: вместе с каждым элементом копируются и все его потомки
- При копировании сохраняются свойства объекта
- Сохраняются точки излома связей
- Возможно копирование между диаграммами
- Возможно создание только графических копий без копирования логических элементов
- Горячие клавиши: * Копирование: Ctrl+C * Вставка полной копии элемента: Ctrl+V * Вставка только графической копии: Ctrl+Shift+V
- Копирование и вставка посредством контекстного меню
- Выделенная связь копируется только в том случае, если оба элемента, которые она соединяет, тоже выделены
- Положение нового элемента на сцене определяется в зависимости от типа вставки и от местонахождения его в контейнере:
- Элементы вне контейнеров всегда копируются в позицию мыши
- Элементы, копируемые вместе с содержащими их контейнерами, сохраняют своё положение внутри них
- При полном копировании элемент, содержащийся в контейнере, но копируемый без него, вставляется в позицию курсора
- При вставке только графических копий в этом случае поведение определяется положением курсора:
- Если курсор находится внутри родителя исходного элемента, копия вставляется в позицию курсора в тот же контейнер
- В ином случае - в ту же позицию, где и исходный элемент
- Элемент без контейнера, вставляемый в позицию, где находится контейнер, способный его принять, добавляется в него.
Так, во всяком случае, должно быть =)
-
Не всегда корректно копируются элементы, способные иметь родителя, но не имеющие его. В этом случае при вставке такого элемента в то место, где находится элемент, допустимый для него в качестве контейнера, возможны следующие варианты поведения:
- "ребёнок" добавляется в контейнер, при этом если продолжать вставку, все его последующие копии тоже будут добавляться в этот контейнер, независимо от позиции курсора на сцене;
- "ребёнок" не добавляется в контейнер, вместо этого он вставляется на сцену, причём его позиция в таком случае непредсказуема;
- вставка корректна, то есть элемент вставляется в нужное место и при этом не добавляется ни в какие контейнеры.
Причины и условия воспроизведения того или иного сценария на данный момент не выяснены.
-
При вставке графической копии вставленная связь не прикрепляется к портам, оставаясь красной.
-
Контейнеры, содержащие какие-то элементы, при вставке имеют непредсказуемые размеры.
-
Вставка графической копии внутрь контейнера не всегда корректна (неправильная позиция вставленной копии + изменение размеров контейнера).
При копировании нужные узлы и связи сериализуются и записываются в QClipboard. Сериализация элементов осуществляется с помощью POD-классов EdgeData и NodeData, поля которых содержат нужную для копирования информацию о связи или узле. Для каждого элемента создаётся такая структура и пишется в QByteArray, который и является содержимым буфера обмена. (Чтобы это было возможным, для структуры и для всех типов полей должны быть реализованы operator<< и operator>>, а так же типы полей (qReal::Id) должны быть зарегистрированы с помощью qRegisterMetaType() и qRegisterMetaTypeStreamOperators()).
Список копируемых узлов формируется так, чтобы каждый элемент в этом списке предшествовал всем своим потомкам. Это значительно упрощает вставку.
- Общие поля: id и pos - id и позиция исходного элемента; logicalId - логический id, необходимый для вставки графических копий
- EdgeData: srcId и dstId - id элементов, являющихся началом и концом связи, соответственно; portFrom и portTo - конкретные порты, к которым присоединена связь; configuration - точки излома связи
- NodeData: parentId - id родителя копируемого узла; contents - используется для восстановления геометрии вставленного элемента и установки правильного его положения на сцене; properties - свойства узла.
При вставке из буфера вытаскиваются (посредством QByteArray, так же, как производилось и копирование) все сохранённые в нём структуры и на основе данных, содержащихся в них, создаются новые элементы. При этом:
- Смещение объектов определяется относительно первого в списке узла (если список пуст, то вставлять нечего, ибо связей тогда тоже нет)
- Благодаря тому, что узлы при копировании записывались в буфер в "правильном" порядке, нам не нужно каждый раз искать по всему списку элемент, который можно вставить (с отсутствующим или уже вставленным родителем), а можно брать их последовательно, начиная с начала, потому что если у текущего элемента был родитель, то он уже вставлен
- Используется табличка, сопоставляющая id-шники исходного элемента и копии: при вставке узла она нужна, чтобы установить правильного родителя, а при вставке связи - её начало и конец.