Russian Qt Forum
Ноябрь 24, 2024, 11:55 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Откат-накат по модели "хранение изменений" до сих пор никак не поддерживается?  (Прочитано 7817 раз)
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« : Март 31, 2015, 19:54 »

Поддержка отката-наката в Qt ориентирована только на модель "функции прямого действия и функции обратного действия". У меня так не получается, поскольку действие пользователя может вызывать непредсказуемые изменения, которые одним определенным "обратным действием" откатить не получится. Например, если пользователь кидает айтем на графсцену, то это может вызывать перетрассировку нескольких соединителей, а может не вызывать, смотря куда айтем упадет. И если вызовет, то какие соединители перетрассируются и как они пройдут, неизвестно. То есть, невозможно написать обратное действие "убрать айтем", которое будет однозначно восстанавливать соединители во всех случаях.

То есть, откат-накат реализуем только по модели сохранения промежуточных состояний, но поддержки этой модели в Qt нет, как минимум в 4.7. То есть, всё надо делать самому руками - формировать обезличенные массивы измененных данных, класть в файл отката, доставать оттуда и т.д.? Или может такая библиотека уже есть опенсорсная для Qt? Несколько лет назад искал - не было. Может сейчас появилась, кто знает?
Записан

2^7-1 == 127, задумайтесь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #1 : Март 31, 2015, 20:09 »

Говорите прямо: undo, serialize, а не изобретайте "откат-накат", "обезличенные массивы" и.т.п  Улыбающийся 
Undo - задача фундаментальная, поэтому шансы найти какую-то реализацию на стороне = нулю. Если б было то раструбили бы так что все услышат - оно того заслуживает. 
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #2 : Март 31, 2015, 20:25 »

Я и говорю прямо, только русскими терминами, которые использовал еще лет 25 назад, еще до новомодных undo, serialize и т.д.

Ну нет, значит нет, опять придётся с нуля всё это делать, только теперь для Qt...  В замешательстве
Записан

2^7-1 == 127, задумайтесь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Апрель 01, 2015, 08:31 »

Имею (обязан) поддерживать undo. Принципы те же что в undo Qt, но объекты должны удаляться и запись должна быть в файл. Ну что, геморрой конечно капитальный. Написать "обратное действие" всегда возможно, просто часто это тонна работы. Обычно записывается серия действий а 1 блоке. Многие проблемы связаны с "исчезновением указателей" - их-то в файл не записать. Если у Вас пока ничего нет, то может пока ограничиться упрощенным решением: запись/восстановление всей сцены
Записан
Fregloin
Супер
******
Offline Offline

Сообщений: 1025


Просмотр профиля
« Ответ #4 : Апрель 01, 2015, 09:41 »

Хехе, сталкивался с подобной проблемой. У самого графическая сцена (даже несколько), на которой много различных элементов и связей между ними и логикой.
Удаление указателей решилось просто: в команду QUndoCommand я передаю не указатель на элемент, а его id. Когда нужно в команде что то делать, я ищу элемент по его ид и работаю с ним. Если ид по каким то причинам не найден (хотя такого быть не должно) вывожу отладочное сообщение и разбираюсь что да как. Раньше как раз вылетала прога часто после удаления/вставки элементов.
Как только перешёл на хранение ид, все заработало без ошибок. Соответсвтенно и в файл тоже самое можно писать. Для каждой команды задать методы сериализации, и при добавлении в стек команд писать их параллельно в файл. Т.е. нужно по максимуму отказаться от прямой передачи и хранения указателей на объекты в этих командах (если объекты могут удаляться произвольно или юзером). Проще передать некую ссылку или ид на него. По необходимости получать указатель через ид.
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #5 : Апрель 01, 2015, 14:16 »

С указателями у меня нет проблем - всё, что есть на сцене, имеет имена, и все объекты, которые редактируются во внутреннем представлении, тоже имеют имена. Сохранять имена и координаты нет проблем.

Проблема в другом. Сцена у меня - это визуальное представление внутренних связей между объектами. При этом одна и та же внутренняя связь на сцене может быть нарисована по-разному, в зависимости, как получилось у трейсера провести автоматически соединения. Во внутреннем представлении это сигнал-слот соединение между двумя QObject, а на сцене это последовательность отрезков между двумя айтемами типа "разъем", котрые являются дочерними для айтемов "объект". Видимая последовательность отрезков может изменяться при неизменном соединении сигнал-слот - пользовтель может отредактировать автоматически проведенную линию, если она ему не нравится, но при этом соединение сигнал-слот не изменяется. Или просто если объект перенесли в другое место схемы, то автомат проложит другое визуальное соединение, а внутреннее останется таким же. Но визуальное может изменяться синхронно с внутренним - при создании и удалении соединения, исчезает или появляется также и последовательность отрезков. То есть, у меня 2 представления - внутренне и визуальное, которые связаны друг с другом, но не однозначно. То есть, даже просто сохранять для отката всю сцену - недостаточно. Получается, что надо сохранять И редактирующие действия для внутреннего представления, И данные для отображаемой сцены. То есть, обе модели придётся использовать - и функциональную для внутреннего представления, и модель данных для сцены. Причем, да, в реализации выглядит проще сохранять всю сцену при её изменениях. Хотя это и громоздко, и избыточно.

Как жаль, что для QGraphicsScene у Qt нет универсального отката-наката...  Грустный Для текстового редактора есть же искаропки.
Записан

2^7-1 == 127, задумайтесь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Апрель 01, 2015, 15:00 »

С указателями у меня нет проблем - всё, что есть на сцене, имеет имена, и все объекты, которые редактируются во внутреннем представлении, тоже имеют имена. Сохранять имена и координаты нет проблем.
ID должно быть уникальным и неуклонно расти при создании объектов. Использовать с той же целью имя возможно, но менее удобно.
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #7 : Апрель 01, 2015, 15:32 »

Это уже несущественные мелочи.
Записан

2^7-1 == 127, задумайтесь...
Fregloin
Супер
******
Offline Offline

Сообщений: 1025


Просмотр профиля
« Ответ #8 : Апрель 02, 2015, 13:48 »

ну так что мешает любое изменение пользователем пихать в команду? Последовательное пихаиние в undo стек команд даст вам результрующую картинку. Т.е. если юзер подвинул линию, то нужно это тоже сделать через QUndoCommand. Я добился этого посредством того, что все операции с элементами делал через QUndoCommand. Раньше делал напрямую, соотвественного никакого отката не было вообще. К сожалению еще есть некоторые функции в программе, которые косвенно затрагивают сцену и они немогут быть undo по причине больших объемов операций и данных. Тогда я вывожу об этом предупреждение, что данную команду нельзя отменить. Если же у вас не получается сохранить всю последовательность, то тут я не помощник.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #9 : Апрель 02, 2015, 14:39 »

ну так что мешает любое изменение пользователем пихать в команду?
Вот как просто...  А можно на примере? (маааленький такой  Улыбающийся)
Код
C++ (Qt)
struct SomeUser {
QList <Data *> mData;
};
 
Какая-то Data была удалена. Ну надо вычеркнуть указатель на нее из mData (что уже не мед). Но как обеспечить "откат-накат" Непонимающий  Что же куда пихать?

И еще момент. Техника undo в Qt предполагает что объект не будет реально удален, а сохранен в данных undo. Тогда неясно что с его сигналами/слотами. Ведь если "якобы удаленный" объект будет их испускать/получать - тогда "ой". Когда-то смотрел примерчик, ну там совсем тупенькая структурка для undo. А как в реале ?

Спасибо
« Последнее редактирование: Апрель 02, 2015, 14:41 от Igors » Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #10 : Апрель 02, 2015, 21:51 »

если юзер подвинул линию, то нужно это тоже сделать через QUndoCommand

Просто так не получается. Перемещение линии на сцене - это мелочи. Но когда пользователь переместил айтем на сцене, автомат перетрассирует все подключенные к этому айтему соединения. А потом делает их двухэтапную оптимизацию - удаляет лишние ступеньки, и замещает однонаправленные последовательные отрезки одним отрезком. И это только у тех соединений, которые пользователь не редактировал до этого вручную. Но и то не у всех - если айтем упал на отредактированное соединение, то автомат и его перетрассирует и оптимизирует. То есть, потребуется, кроме действий пользователя, в стеке команд сохранять отменяющие команды для всех действий автомата. А там с ума можно будет сойти...

И на самом деле, кроме действий пользователя, сцена в будущем еще может изменяться и другими программными действиями, по внешним воздействиям. Разрабатывать каждый раз для каждого такого действия адекватное откатывающее - проще застрелиться. Но если использовать модель отката состояний, то без разницы кто сцену изменяет - пользователь или автомат.

Кстати, то ли в документации на Qt,  то ли где-то еще читал, что для отката изменений на сцене надо применяеть модель отката состояний, а не действий. Так и получается, в общем-то. Увы, создатели Qt для поддержки этой модели НИЧЕГО не дали.
Записан

2^7-1 == 127, задумайтесь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #11 : Апрель 03, 2015, 09:44 »

- если айтем упал на отредактированное соединение, то автомат и его перетрассирует и оптимизирует. То есть, потребуется, кроме действий пользователя, в стеке команд сохранять отменяющие команды для всех действий автомата. А там с ума можно будет сойти...
Да, тяжело, но не так уж страшно. Выделяем базовые команды undo, напр

- сохранить трассу которая будет удалена
- сохранить трассу которая вновь проложена

Т.е. выход/результат автомата, а не каждое его действие

Увы, создатели Qt для поддержки этой модели НИЧЕГО не дали.
Ну а почему кто-то должен вам/нам что-то "давать"? Что это за мужик если ему нужна "мамина сися" (в виде готовых классов)  Улыбающийся
Записан
Fregloin
Супер
******
Offline Offline

Сообщений: 1025


Просмотр профиля
« Ответ #12 : Апрель 03, 2015, 09:56 »

Я конечно не совсем понимаю вашу задачу. Я писал для своей - программа может быть в режиме редактирования и в режиме исполнения. В режиме исполнения у меня undo не используется.
В редакторе да. Опять таки - хранение объектов в undo плохой подход, как минимум потому что действительно объект может быть удален извне. Можно конечно хранить QPointer<T> например, но я предпочел работать через id. По поводу ваших так сказать трассировок линий - может есть смысл их делать не каждый раз в режиме редактирования. Т.е. рисовать как бы червновой вариант во время перетаскивания. А потом сделать отдельной командой - трассировка линий на основе текущих координат элементов. Или в каждую команду пихать: указатель на сцену (минимум), указатель на трассировщик, и собственно элемент с которым производятся манипуляции. Или можно не указатели зранить, а передавать некие сообщения при undo/redo а их уже будут ловить нужные адресаты. Взять к примеру Visio. Там ведь тоже есть сложные линии и все такое, но откат там работает безупречно.
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #13 : Апрель 03, 2015, 14:26 »

По поводу ваших так сказать трассировок линий - может есть смысл их делать не каждый раз в режиме редактирования. .... Там ведь тоже есть сложные линии и все такое, но откат там работает безупречно.

Нет, не имеет, я убрал под многоточие всё, что не имеет логического смысла. У Visio очевидно нет внутреннего представления объектов и связей, есть только то, что видно. И для отката хранятся только промежуточные состояния объектов, лежащих на графической сцене (если там есть такое понятие, как графическая сцена). У меня далеко не аналог Visio.
« Последнее редактирование: Апрель 03, 2015, 14:36 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #14 : Апрель 03, 2015, 14:35 »

Увы, создатели Qt для поддержки этой модели НИЧЕГО не дали.
Ну а почему кто-то должен вам/нам что-то "давать"? Что это за мужик если ему нужна "мамина сися" (в виде готовых классов)  Улыбающийся

Ну здрасьте приехали... "А почему мы кому-то что-то должны?" - это как раз философия создателей Microsoft Foundation Classes - наихудшего фреймворка для Windows за всю историю. Слава Богу, у авторов Qt философия прямо противоположная.  Крутой

На самом деле, QGraphicsScene - это низкоуровневый графический редактор. То есть, он умеет делать разное с объектами на сцене, и он вполне может делать обратные действия. То есть, по-хорошему - откат-накат графической сцены может быть реализован под крышкой QGraphicsScene. Это колоссально облегчило бы жизнь разработчикам софта на Qt, и сделало бы этот фреймворк еще более популярным. У QTextEdit и QPlainTextEdit есть же откат-накат - и никто от этого не умер, ровно наоборот, все живы и счастливы.
« Последнее редактирование: Апрель 03, 2015, 14:37 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.075 секунд. Запросов: 23.