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

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

Страниц: 1 [2] 3 4   Вниз
  Печать  
Автор Тема: Реализация Undo/Redo действий пользователя в случае mdi интерфейса  (Прочитано 24934 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #15 : Июнь 19, 2012, 14:46 »

спрошу Вас, Igors, об означенных Вами проблемах с "undo".
Однако же Наташа не сказала ни "да" ни "нет". Хмм.. ну ладно, попробуем

Рассматривая пример undo мы видим - удаляемые объекты не удаляются с помощью delete, а указатели на них переносятся в данные стека undo. Понятно что простота и ясность - большие достоинства такого решения. Однако, на мой взгляд, далеко не всегда такая техника может устроить.

1)  Объем данных непрерывно растет. Пользователь загрузил напр большую модель данных, поредактировал а удалил. Потом спохватился - "верните взад!". Вполне вероятно после серии таких манипуляций память будет исчерпана или, хуже того, пойдет по свапам с жуткими тормозами. Не бужу утверждать что таких случаев большинство, но они никак не "редкое исключение" от которого можно отмахнуться.

2) Перенос объекта в стек и обратно нуждается в активации/деактивации, и это требует много кода. Это в примерчике фигуры не зависят друг от друга, а в реальной задаче все обвязано сигналами. Объект перенесенный в undo будет продолжать их принимать. Или объект генерит события по таймеру и.т.п.

3) Отсутствие реального delete искажает логику языка. Выглядит как продолжение 2, но разница принципиальная. Не говоря уже о том что невдобняк страшный, получить за напр deleteLater очень легко - трудно будет разгрести.

Ну и теперь стандартный вопрос "а как же правильно?". Архитекторы приглашаются. Посмотрим сколько их и каких если не прятаться за решения "троллей"  Улыбающийся
Записан
alexis031182
Гость
« Ответ #16 : Июнь 19, 2012, 15:05 »

Однако же Наташа не сказала ни "да" ни "нет". Хмм.. ну ладно, попробуем
Уверен, она за, да и многие тоже.

...
1)  Объем данных непрерывно растет. Пользователь загрузил напр большую модель данных, поредактировал а удалил. Потом спохватился - "верните взад!". Вполне вероятно после серии таких манипуляций память будет исчерпана или, хуже того, пойдет по свапам с жуткими тормозами. Не бужу утверждать что таких случаев большинство, но они никак не "редкое исключение" от которого можно отмахнуться.
Какое-то ограничение на количество должно быть, конечно. Тут наверное зависит от веса самих объектов. Можно же заранее предположить, что вполне достаточным будет для таких-то виджетов вести историю в столько-то записей, а для таких - столько. По идее должно разруливаться.

2) Перенос объекта в стек и обратно нуждается в активации/деактивации, и это требует много кода. Это в примерчике фигуры не зависят друг от друга, а в реальной задаче все обвязано сигналами. Объект перенесенный в undo будет продолжать их принимать. Или объект генерит события по таймеру и.т.п.
Да, тут конечно проблема. Конечно всякий виджет можно отключить от всех сигналов одной строкой. Но это надо учитывать. Да и восстановление приёма сигналов будет сложным. А если ещё и события используются?..

3) Отсутствие реального delete искажает логику языка. Выглядит как продолжение 2, но разница принципиальная. Не говоря уже о том что невдобняк страшный, получить за напр deleteLater очень легко - трудно будет разгрести.
А может быть всё-таки в некоторых ситуациях имеет смысл удалить сам объект, но при этом запомнить его состояние?

Ну и теперь стандартный вопрос "а как же правильно?". Архитекторы приглашаются. Посмотрим сколько их и каких если не прятаться за решения "троллей"  Улыбающийся
А как у них эта проблема решается с сигналами и событиями у отправленных в "корзину" объектов? Или никак?
Записан
nata267
Гость
« Ответ #17 : Июнь 19, 2012, 15:28 »

Уже интереснее... Что за метод "undo" ?? Очень было бы интересно в нем разобраться. А кстати чем плох метод который я привела (не считая того, что он написан не мной)??
Не метод, а пример "undo" в Qt Examples. Он использует ту же технику что Вы привели. Вот на нем предлагаю обсудить проблемы архитектуры - если Вы не против

я видела этот пример, по моему с одним окном, а в моем примере mdi
Записан
nata267
Гость
« Ответ #18 : Июнь 19, 2012, 15:33 »

спрошу Вас, Igors, об означенных Вами проблемах с "undo".
Однако же Наташа не сказала ни "да" ни "нет". Хмм.. ну ладно, попробуем

Рассматривая пример undo мы видим - удаляемые объекты не удаляются с помощью delete, а указатели на них переносятся в данные стека undo. Понятно что простота и ясность - большие достоинства такого решения. Однако, на мой взгляд, далеко не всегда такая техника может устроить.

1)  Объем данных непрерывно растет. Пользователь загрузил напр большую модель данных, поредактировал а удалил. Потом спохватился - "верните взад!". Вполне вероятно после серии таких манипуляций память будет исчерпана или, хуже того, пойдет по свапам с жуткими тормозами. Не бужу утверждать что таких случаев большинство, но они никак не "редкое исключение" от которого можно отмахнуться.

2) Перенос объекта в стек и обратно нуждается в активации/деактивации, и это требует много кода. Это в примерчике фигуры не зависят друг от друга, а в реальной задаче все обвязано сигналами. Объект перенесенный в undo будет продолжать их принимать. Или объект генерит события по таймеру и.т.п.

3) Отсутствие реального delete искажает логику языка. Выглядит как продолжение 2, но разница принципиальная. Не говоря уже о том что невдобняк страшный, получить за напр deleteLater очень легко - трудно будет разгрести.

Ну и теперь стандартный вопрос "а как же правильно?". Архитекторы приглашаются. Посмотрим сколько их и каких если не прятаться за решения "троллей"  Улыбающийся

это уже вопрос реализации команд, в этом то и сложность
Записан
alexis031182
Гость
« Ответ #19 : Июнь 19, 2012, 15:42 »

Я вот подумал, а что если применить построение классов, которое используется при расшаривании данных. Это к вопросу об остающихся активными сигналах при помещении объекта в "корзину". Другими словами, я предлагаю разделить данные и методы объекта в два разных класса. Таким образом, можно смело выполнять delete для помещаемого в "корзину" объекта. Точнее сказать для той части, которая содержит только методы. А данные объекта (второй класс) помещаем в "корзину". Тогда получится, что при удалении виджета все конекты сигналов будут разорваны. А при создании - восстановлены в конструкторе объекта класса методов. А данные просто по указателям туда-сюда могут шнырять. Даже копирования как такового не потребуется.
Записан
nata267
Гость
« Ответ #20 : Июнь 19, 2012, 15:53 »

А как у них эта проблема решается с сигналами и событиями у отправленных в "корзину" объектов? Или никак?

если написать упрощенно то в методе undo комманды DeleteWidgetCommand присутствует m_widget->show();, а в методе redo
-  m_widget->hide(); соответсвенно, следовательно виджет просто скрывается на форме. m_widget - это указатель на удаляемый виджет, который сохраняется в команде
« Последнее редактирование: Июнь 19, 2012, 15:57 от nata267 » Записан
alexis031182
Гость
« Ответ #21 : Июнь 19, 2012, 15:57 »

если написать упрощенно то в методе undo комманды DeleteWidgetCommand присутствует m_widget->show();, а в методе redo
-  m_widget->hide(); соответсвенно, следовательно виджет просто скрывается на форме
Другими словами - никак. Виджет не должен реагировать на сигналы вообще, если он "удалён".
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #22 : Июнь 19, 2012, 16:22 »

А может быть всё-таки в некоторых ситуациях имеет смысл удалить сам объект, но при этом запомнить его состояние?
"в некоторых ситуациях" считаю неуместным. Вопрос принципиальный - "удаляем" или "прячем"?  Мое мнение что принципиально правильно удалять с помощью delete, предварительно сериализовав в файл. Иначе придется бесконечно латать дыры.

Тогда получится, что при удалении виджета все конекты сигналов будут разорваны. А при создании - восстановлены в конструкторе объекта класса методов. А данные просто по указателям туда-сюда могут шнырять. Даже копирования как такового не потребуется.
Небольшая трудность в том что указатель меняется после его удаления и затем опять создания  Улыбающийся
Записан
alexis031182
Гость
« Ответ #23 : Июнь 19, 2012, 16:32 »

"в некоторых ситуациях" считаю неуместным. Вопрос принципиальный - "удаляем" или "прячем"?  Мое мнение что принципиально правильно удалять с помощью delete, предварительно сериализовав в файл. Иначе придется бесконечно латать дыры.
Здесь я имел в виду отталкиваться не от того как фишка ляжет, а исходя из особенностей виджетов. Впрочем, мне самому этот вариант тоже не нравится.

Небольшая трудность в том что указатель меняется после его удаления и затем опять создания  Улыбающийся
Указатель на данные останется тот же. На методы конечно будет другой. Но разве все ссылающиеся на "уничтожаемый" объект объекты не должны обнулить свои указатели?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #24 : Июнь 19, 2012, 16:41 »

Указатель на данные останется тот же. На методы конечно будет другой. Но разве все ссылающиеся на "уничтожаемый" объект объекты не должны обнулить свои указатели?
Вы коннектитесь к "сигнальной" части, которая и будет удалена. Сохранить указатели можете, но они уже ничему не соответствуют на момент undo.

Ну и вообще, лучше исходить из того что какой-то (обычно значительный) код уже написан, и надо сделать undo. В таком (практическом) контексте переделка многих и многих классов (с целью разделения на 2 части) энтузиазма не вызывает. Дешевизна решения уже утеряна
Записан
alexis031182
Гость
« Ответ #25 : Июнь 19, 2012, 16:55 »

Вы коннектитесь к "сигнальной" части, которая и будет удалена. Сохранить указатели можете, но они уже ничему не соответствуют на момент undo.
Вот и хорошо. Нет коннектов - нет сигналов. Событий, кстати, тоже не будет. А когда сработает redo, то запускаем конструктор методного объекта и он уже все сигналы переподключит таким образом, как это нужно виджету.

Ну и вообще, лучше исходить из того что какой-то (обычно значительный) код уже написан, и надо сделать undo. В таком (практическом) контексте переделка многих и многих классов (с целью разделения на 2 части) энтузиазма не вызывает. Дешевизна решения уже утеряна
Нет, ну тут речь идёт об архитектуре, что изначально предполагает с нуля, иначе серьёзная переделка грозит в любом случае.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #26 : Июнь 19, 2012, 17:16 »

Вот и хорошо. Нет коннектов - нет сигналов. Событий, кстати, тоже не будет. А когда сработает redo, то запускаем конструктор методного объекта и он уже все сигналы переподключит таким образом, как это нужно виджету.
Был объект связанный сигналами. Мы его удалили и возвращаем - так что undo. Только вот довольно редко все коннекты назначаются в конструкторе - обычно связующим выступает 3-я сторона (напр родитель).

Нет, ну тут речь идёт об архитектуре, что изначально предполагает с нуля, иначе серьёзная переделка грозит в любом случае.
Никакого нуля она не предполагает. В процессе написания и любого апгрейда проблемы архитектуры столь же часты как и при изначальном планировании
Записан
alexis031182
Гость
« Ответ #27 : Июнь 19, 2012, 17:25 »

Был объект связанный сигналами. Мы его удалили и возвращаем - так что undo.
А ну да, точно.

Только вот довольно редко все коннекты назначаются в конструкторе - обычно связующим выступает 3-я сторона (напр родитель).
Значит дать понять родителю, что неплохо было бы позаботиться о восстановлении сигналов. То есть коннекты в отдельную функцию. Но конечно это уже огород получится. Жаль. Надо подумать тогда, как тут быть.

Никакого нуля она не предполагает. В процессе написания и любого апгрейда проблемы архитектуры столь же часты как и при изначальном планировании
Ну так если изначально спланировал неверно, значит сам и виноват, как говорится Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #28 : Июнь 19, 2012, 17:49 »

Но конечно это уже огород получится.
Еще какой, ведь обобщить здесь не удается

Ну так если изначально спланировал неверно, значит сам и виноват, как говорится Улыбающийся
Ну виноват, и что? Улыбающийся Никто не предусмотрит всего на старте, тем более undo, которое кажется... ну так.. мелкой технической подробностью, решается с помощью паттерна "команда"  Улыбающийся

Однако.. где же архитекторы? (ну или хотя бы "я знаю"). Как я и предполагал, диалог между Вами и мной. Предлагаю сделать паузу, а то мы тарахтим и не даем людям сказать (им наверное есть что..). Примолкаю
Записан
alexis031182
Гость
« Ответ #29 : Июнь 19, 2012, 18:09 »

Ну виноват, и что? Улыбающийся Никто не предусмотрит всего на старте, тем более undo, которое кажется... ну так.. мелкой технической подробностью, решается с помощью паттерна "команда"  Улыбающийся
Тут получаются сигналы камнем преткновения. К этому будут защитники Команды апеллировать.

Однако.. где же архитекторы? (ну или хотя бы "я знаю"). Как я и предполагал, диалог между Вами и мной. Предлагаю сделать паузу, а то мы тарахтим и не даем людям сказать (им наверное есть что..). Примолкаю
У меня подозрение, что Вы знаете как можно решить эту задачу. Но поскольку сам пока не могу предложить решения, устраняющего проблему сигналов, то придётся тоже лечь на дно.
Записан
Страниц: 1 [2] 3 4   Вверх
  Печать  
 
Перейти в:  


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