Russian Qt Forum

Qt => Кладовая готовых решений => Тема начата: nata267 от Июнь 18, 2012, 15:22



Название: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: nata267 от Июнь 18, 2012, 15:22
Взято из QtDesigner. Реализация Undo/Redo действий пользователя в случае mdi интерфейса, используя QUndoStack, QUndoGroup, QUndoCommand. В качестве первого аргумента конструкторов классов QFormWindowManager, QFormWindow указатель на медиатор. Про который написано в этой теме http://www.prog.org.ru/topic_22148_0.html.


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: alexis031182 от Июнь 18, 2012, 16:14
Мне кажется интересней было бы, если бы это было Ваше собственное решение. Оно тогда к каким-нибудь завлекательно-увлекательным темам повело бы. А так похоже, что Вы справочник по внутренностям Qt взялись делать. Впрочем, может это и интересно, если оно так. Могу даже название предложить: "Кухня Qt. Вкуснее, чем у бабушки" :)


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: nata267 от Июнь 18, 2012, 20:15
Мне кажется интересней было бы, если бы это было Ваше собственное решение. Оно тогда к каким-нибудь завлекательно-увлекательным темам повело бы. А так похоже, что Вы справочник по внутренностям Qt взялись делать. Впрочем, может это и интересно, если оно так. Могу даже название предложить: "Кухня Qt. Вкуснее, чем у бабушки" :)

Действительно, интереснее было бы. Но к сожалению, тролли опередили меня. Вот эти вот их классы QUndoCommand, QUndoStack... в голову не приходит как решить задачу с помощью этих классов как то по другому чем у них. Кстати я не присваиваю себе их решение. Просто это единственное которое нашла на сегодняшний день. Предложите лучше)))  Вообще я предпочитаю пользоваться хорошим опытом других, если сама не могу придумать лучше. И вообще зачем  тогда qt? Пишите свои решения на чистом с++. Qt и всякие там решения нужны чтобы облегчить нам жизнь. Это тоже уже люди придумали и этим можно пользоваться. Я просто хотела пообсуждать эти решения. Потому что эти темы на этом форуме не обсуждаются вообще. Но видимо людям не очень это интересно. Ок.


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: alexis031182 от Июнь 18, 2012, 20:31
Действительно, интереснее было бы. Но к сожалению, тролли опередили меня.
Да, не раз замечал за ними этот грешок ;D

Вот эти вот их классы QUndoCommand, QUndoStack... в голову не приходит как решить задачу с помощью этих классов как то по другому чем у них.
Да не обязательно лучше. С другой стороны, если с заделом на будущее использование, то как раз обязательно :)

Кстати я не присваиваю себе их решение.
Я этого не говорил и не подразумевал. Тут я чист :)

Просто это единственное которое нашла на сегодняшний день. Предложите лучше)))
Пока не могу (если вообще смогу :) ), занят разработкой пула объектов. Тоже паттерн + фабрика.

Вообще я предпочитаю пользоваться хорошим опытом других, если сама не могу придумать лучше.
Оно наверное и правильно, сам также бывает поступаю. Впрочем, часто мне свой велосипед, пусть и о пяти колёсах, написать интереснее :)


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: nata267 от Июнь 18, 2012, 20:36

Просто это единственное которое нашла на сегодняшний день. Предложите лучше)))
Пока не могу (если вообще смогу :) ), занят разработкой пула объектов. Тоже паттерн + фабрика.


Вот то-то же...

Вообще я предпочитаю пользоваться хорошим опытом других, если сама не могу придумать лучше.
Оно наверное и правильно, сам также бывает поступаю. Впрочем, часто мне свой велосипед, пусть и о пяти колёсах, написать интереснее :)

А мне интереснее копаться в чужих решениях)) Особенно после того как свое вышло о пяти колесах...

В данном примере простор для творчества открывается в реализации комманд. Их там не мало.


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: alexis031182 от Июнь 18, 2012, 20:42
Вот то-то же...
Да, не повезло :( а то бы я сразу эх, ух, ох ;D

А мне интереснее копаться в чужих решениях)) Особенно после того как свое вышло о пяти колесах...
Вот очень ценное качество, любимое всеми без исключения работодателями программеров - умение разбираться в чужом коде. Или всё же умение работать в команде выше ценится? Я так до сих пор и не определил :)


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: alexis031182 от Июнь 18, 2012, 20:44
В данном примере простор для творчества открывается в реализации комманд. Их там не мало.
Попробуйте предложить вариант для творчества. Это будет интересно


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: nata267 от Июнь 18, 2012, 21:00
В данном примере простор для творчества открывается в реализации комманд. Их там не мало.
Попробуйте предложить вариант для творчества. Это будет интересно

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


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: alexis031182 от Июнь 18, 2012, 21:28
Надоело оправдываться(
Эм :o

Никто не сказал - спасибо, крутое решение.
Добре, спасибо, крутое решение :)

Все молчат и не хотят ни в чем разбираться или что-то понимать.
Тёмные люди, дикие нравы

Блин, куда я со своей женской логикой...
Наталья, если позволите, ну с чего Вы взяли, что Ваш труд не интересен и никому не будет нужен. Ну вот сей же час, может быть и нет, но спустя время обязательно оценят. Тут много тёмных людей, я среди них первый, так что Вы не расстраивайтесь ни в коем случае. Мы догоним, каждый в своё время и на своей волне. Миру мир, аминь :)


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: Akon от Июнь 18, 2012, 23:44
2nata267:
Вам действительно можно дополнять каталоги паттернов ссылками на современное применение - будет полезная информация.

имхо, но в "кладовой готовых решений" должны приводиться готовые решения, а не паттерны, например, "Частный случай механизма сигнал-слот", "Виджет просмотра PDF-файлов" и т.п. Вот если бы вы сделали, например, в достаточной степени абстрактную реализацию какого-нибудь паттерна (например,  "Частный случай механизма сигнал-слот" покрывает фундаментальный паттерн "наблюдатель"), то это бы было очень интересно.
 


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: Igors от Июнь 19, 2012, 09:07
Надоело оправдываться( Никто не сказал - спасибо, крутое решение. Все молчат и не хотят ни в чем разбираться или что-то понимать. Блин, куда я со своей женской логикой...
Очень даже "туда", повторюсь, тема паттернов интересная и нужная. Да, разбираться не хотят, понимать тоже. Потому что нужно менять форму/стиль обсуждения.

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

Однако если внимательнее посмотреть на тот же пример "undo", или начать интенсивно пользовать этот метод - возникают серьезные проблемы. Есть желание - обсудим. А нет, "мы и так все знаем" - ну и не надо, нет проблем.


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: alexis031182 от Июнь 19, 2012, 10:33
Вроде кучу паттернов уже перебрали, а не можем даже разобраться в том, а что же нам интересно обсуждать, с чем интересно разобраться. Вот лично мне больше про фабрику тема понравилась, но и то только потому, что урвал на свою сторону значительный кусок "одеяла", оставив ТС, по большому счёту, без оного :) Поэтому сейчас, сожалея о ранее содеянном, спрошу Вас, Igors, об означенных Вами проблемах с "undo".


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: nata267 от Июнь 19, 2012, 11:23
Надоело оправдываться( Никто не сказал - спасибо, крутое решение. Все молчат и не хотят ни в чем разбираться или что-то понимать. Блин, куда я со своей женской логикой...
Очень даже "туда", повторюсь, тема паттернов интересная и нужная. Да, разбираться не хотят, понимать тоже. Потому что нужно менять форму/стиль обсуждения.

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

Однако если внимательнее посмотреть на тот же пример "undo", или начать интенсивно пользовать этот метод - возникают серьезные проблемы. Есть желание - обсудим. А нет, "мы и так все знаем" - ну и не надо, нет проблем.


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


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: Igors от Июнь 19, 2012, 11:34
Уже интереснее... Что за метод "undo" ?? Очень было бы интересно в нем разобраться. А кстати чем плох метод который я привела (не считая того, что он написан не мной)??
Не метод, а пример "undo" в Qt Examples. Он использует ту же технику что Вы привели. Вот на нем предлагаю обсудить проблемы архитектуры - если Вы не против


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: nata267 от Июнь 19, 2012, 11:55
В данном примере опять используется медиатор из предыдущей темы. Для связи окон с менеджером окон. Вот этот код идет в конструкторе окон:

Код:
 if (FormWindowManager *manager = qobject_cast<FormWindowManager*> (core()->formWindowManager())) {
        m_commandHistory = new QUndoStack(this);
        manager->undoGroup()->addStack(m_commandHistory);
    }

В этом месте стек истории действий данного окна помещается в QUndoGroup менеджера окон. core() - медиатор, который хранит указатель на менеджера и предоставляет окну доступ к нему. Когда окно становится активным, делаем стек этого окна активным. Этот код идет в слоте менеджера, который делает окно активным:

Код:
 m_activeFormWindow->commandHistory()->setActive();

Таким образом действия Undo/Redo главного окна будут относится к активному дочернему окну.


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: Igors от Июнь 19, 2012, 14:46
спрошу Вас, Igors, об означенных Вами проблемах с "undo".
Однако же Наташа не сказала ни "да" ни "нет". Хмм.. ну ладно, попробуем

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

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

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

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

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


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: alexis031182 от Июнь 19, 2012, 15:05
Однако же Наташа не сказала ни "да" ни "нет". Хмм.. ну ладно, попробуем
Уверен, она за, да и многие тоже.

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

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

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

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


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: nata267 от Июнь 19, 2012, 15:28
Уже интереснее... Что за метод "undo" ?? Очень было бы интересно в нем разобраться. А кстати чем плох метод который я привела (не считая того, что он написан не мной)??
Не метод, а пример "undo" в Qt Examples. Он использует ту же технику что Вы привели. Вот на нем предлагаю обсудить проблемы архитектуры - если Вы не против

я видела этот пример, по моему с одним окном, а в моем примере mdi


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: nata267 от Июнь 19, 2012, 15:33
спрошу Вас, Igors, об означенных Вами проблемах с "undo".
Однако же Наташа не сказала ни "да" ни "нет". Хмм.. ну ладно, попробуем

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

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

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

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

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

это уже вопрос реализации команд, в этом то и сложность


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: alexis031182 от Июнь 19, 2012, 15:42
Я вот подумал, а что если применить построение классов, которое используется при расшаривании данных. Это к вопросу об остающихся активными сигналах при помещении объекта в "корзину". Другими словами, я предлагаю разделить данные и методы объекта в два разных класса. Таким образом, можно смело выполнять delete для помещаемого в "корзину" объекта. Точнее сказать для той части, которая содержит только методы. А данные объекта (второй класс) помещаем в "корзину". Тогда получится, что при удалении виджета все конекты сигналов будут разорваны. А при создании - восстановлены в конструкторе объекта класса методов. А данные просто по указателям туда-сюда могут шнырять. Даже копирования как такового не потребуется.


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: nata267 от Июнь 19, 2012, 15:53
А как у них эта проблема решается с сигналами и событиями у отправленных в "корзину" объектов? Или никак?

если написать упрощенно то в методе undo комманды DeleteWidgetCommand присутствует m_widget->show();, а в методе redo
-  m_widget->hide(); соответсвенно, следовательно виджет просто скрывается на форме. m_widget - это указатель на удаляемый виджет, который сохраняется в команде


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: alexis031182 от Июнь 19, 2012, 15:57
если написать упрощенно то в методе undo комманды DeleteWidgetCommand присутствует m_widget->show();, а в методе redo
-  m_widget->hide(); соответсвенно, следовательно виджет просто скрывается на форме
Другими словами - никак. Виджет не должен реагировать на сигналы вообще, если он "удалён".


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: Igors от Июнь 19, 2012, 16:22
А может быть всё-таки в некоторых ситуациях имеет смысл удалить сам объект, но при этом запомнить его состояние?
"в некоторых ситуациях" считаю неуместным. Вопрос принципиальный - "удаляем" или "прячем"?  Мое мнение что принципиально правильно удалять с помощью delete, предварительно сериализовав в файл. Иначе придется бесконечно латать дыры.

Тогда получится, что при удалении виджета все конекты сигналов будут разорваны. А при создании - восстановлены в конструкторе объекта класса методов. А данные просто по указателям туда-сюда могут шнырять. Даже копирования как такового не потребуется.
Небольшая трудность в том что указатель меняется после его удаления и затем опять создания  :)


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: alexis031182 от Июнь 19, 2012, 16:32
"в некоторых ситуациях" считаю неуместным. Вопрос принципиальный - "удаляем" или "прячем"?  Мое мнение что принципиально правильно удалять с помощью delete, предварительно сериализовав в файл. Иначе придется бесконечно латать дыры.
Здесь я имел в виду отталкиваться не от того как фишка ляжет, а исходя из особенностей виджетов. Впрочем, мне самому этот вариант тоже не нравится.

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


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: Igors от Июнь 19, 2012, 16:41
Указатель на данные останется тот же. На методы конечно будет другой. Но разве все ссылающиеся на "уничтожаемый" объект объекты не должны обнулить свои указатели?
Вы коннектитесь к "сигнальной" части, которая и будет удалена. Сохранить указатели можете, но они уже ничему не соответствуют на момент undo.

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


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: alexis031182 от Июнь 19, 2012, 16:55
Вы коннектитесь к "сигнальной" части, которая и будет удалена. Сохранить указатели можете, но они уже ничему не соответствуют на момент undo.
Вот и хорошо. Нет коннектов - нет сигналов. Событий, кстати, тоже не будет. А когда сработает redo, то запускаем конструктор методного объекта и он уже все сигналы переподключит таким образом, как это нужно виджету.

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


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: Igors от Июнь 19, 2012, 17:16
Вот и хорошо. Нет коннектов - нет сигналов. Событий, кстати, тоже не будет. А когда сработает redo, то запускаем конструктор методного объекта и он уже все сигналы переподключит таким образом, как это нужно виджету.
Был объект связанный сигналами. Мы его удалили и возвращаем - так что undo. Только вот довольно редко все коннекты назначаются в конструкторе - обычно связующим выступает 3-я сторона (напр родитель).

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


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: alexis031182 от Июнь 19, 2012, 17:25
Был объект связанный сигналами. Мы его удалили и возвращаем - так что undo.
А ну да, точно.

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

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


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: Igors от Июнь 19, 2012, 17:49
Но конечно это уже огород получится.
Еще какой, ведь обобщить здесь не удается

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

Однако.. где же архитекторы? (ну или хотя бы "я знаю"). Как я и предполагал, диалог между Вами и мной. Предлагаю сделать паузу, а то мы тарахтим и не даем людям сказать (им наверное есть что..). Примолкаю


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: alexis031182 от Июнь 19, 2012, 18:09
Ну виноват, и что? :) Никто не предусмотрит всего на старте, тем более undo, которое кажется... ну так.. мелкой технической подробностью, решается с помощью паттерна "команда"  :)
Тут получаются сигналы камнем преткновения. К этому будут защитники Команды апеллировать.

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


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: nata267 от Июнь 20, 2012, 08:45
Вот нашла интересный момент. Вот метод, который удаляет выбранные на форме виджеты:

Код:
void FormWindowBase::deleteWidgetList(const QWidgetList &widget_list)
{
    // We need a macro here even for single widgets because the some components (for example,
    // the signal slot editor are connected to widgetRemoved() and add their
    // own commands (for example, to delete w's connections)
    const QString description = widget_list.size() == 1 ?
        tr("Delete '%1'").arg(widget_list.front()->objectName()) : tr("Delete");

    commandHistory()->beginMacro(description);
    foreach (QWidget *w, widget_list) {
        emit widgetRemoved(w);
        DeleteWidgetCommand *cmd = new DeleteWidgetCommand(this);
        cmd->init(w);
        commandHistory()->push(cmd);
    }
    commandHistory()->endMacro();
}

В комментарии у них написано, что они используют макро, т.е. объединение комманд, потому что некоторые компоненты (например, редактор сигналов-слотов) соединены с сигналом widgetRemoved(w) и добавляют свои комманды (например, удаление connections виджетов).

Но это те коннекты, который создает пользователь(. Они на форме не работают, а пишутся в ui файл.


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: alexis031182 от Июнь 20, 2012, 09:03
Это понятно, как раз проблемы в дисконекте виджетов/объектов нет. Проблема в восстановлении конектов по активации undo. Если получение объектов, которые подключены к сигналам "удаляемого" объекта, ещё наверное возможно, то вот получение объектов, подключенных к его слотам - нет. Точнее сказать, что эта информация находится в приватной части QObject и просто так доступа к ней не получить. Это либо править исходники Qt, либо писать враппер для connect(). Оба способа естественно левые.


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: nata267 от Июнь 20, 2012, 10:09
А о каких именно коннектах вы говорите? Приведите пример?


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: alexis031182 от Июнь 20, 2012, 10:15
А о каких именно коннектах вы говорите? Приведите пример?
QObject::connect(), который может быть вызван родителем "удаляемого" объекта или вообще в альтернативной реальности :) Как тогда узнать, к кому своими слотами подключен объект/виджет? Просто так - никак. А значит о восстановлении копии состояния объекта/виджета после фактического delete не может быть и речи.


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: Igors от Июнь 20, 2012, 12:08
А не допускаете ли Вы (ну или мы) ошибок в проектировании? Почему уткнулись носом в одну-единственную проблему (как восстановить сигналы)? Это может съесть все время и силы. Может есть смысл посмотреть - а какие еще проблемы?

Ну напр один объект содержит указатель(и) на  другой (наверное это Алексей называет "перекрестные ссылки"). Тут возможны варианты - напр при удалении держащего тот всегда удаляет и указатель. Или не удаляет никогда. Или когда счетчик ссылок на указатель станет = 0. Как это все выглядит с точки зрения undo?


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: nata267 от Июнь 20, 2012, 12:28
А о каких именно коннектах вы говорите? Приведите пример?
QObject::connect(), который может быть вызван родителем "удаляемого" объекта или вообще в альтернативной реальности :) Как тогда узнать, к кому своими слотами подключен объект/виджет? Просто так - никак. А значит о восстановлении копии состояния объекта/виджета после фактического delete не может быть и речи.

вообще-то я и так понимаю о чем речь, я имею в виду вы можете привести конкретный пример.
вот к примеру. у меня я на форме разместила текстовое поле по двойному нажатию на которое у меня выскакивает редактор текста этого окна. если я вместо удаления спрячу это текстовое поле, то соответственно пользователь уже не сможет на него нажать и сгенерировать это событие или сигнал. в данном случае этот коннект никому не мешает. вот я и спрашиваю конкретный пример коннекта, который может повлечь ошибки, рассматриваz вариант с hide()

может быть в слотах проверять состояние объекта, и в зависимости от этого выполнять или не выполнять действия?? но опять же я рассматриваю вариант с hide()


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: nata267 от Июнь 20, 2012, 12:35
А не допускаете ли Вы (ну или мы) ошибок в проектировании? Почему уткнулись носом в одну-единственную проблему (как восстановить сигналы)? Это может съесть все время и силы. Может есть смысл посмотреть - а какие еще проблемы?

Ну напр один объект содержит указатель(и) на  другой (наверное это Алексей называет "перекрестные ссылки"). Тут возможны варианты - напр при удалении держащего тот всегда удаляет и указатель. Или не удаляет никогда. Или когда счетчик ссылок на указатель станет = 0. Как это все выглядит с точки зрения undo?

как мы можем удалить указатель, а если этот объект должен существовать независимо от удаляемого??


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: Igors от Июнь 20, 2012, 12:44
вообще-то я и так понимаю о чем речь, я имею в виду вы можете привести конкретный пример.
Усложним немного учебный пример undo. Допустим если мы тащим Rectangle - мы хотим чтобы остальные фигуры двигались тоже. Ну вот мы и получили тот самый случай.

Обратите внимание что alexis031182 не тратит время на изучение типа "а какие частные случаи возможны", а подходит к деактивации принципиально - никаких сигналов не должно быть получено вообще. Однако мне кажется этого недостаточно. "Хороший индеец - мертвый индеец". Мочить надо, а не цацкаться перенося туда-сюда


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: alexis031182 от Июнь 20, 2012, 12:46
А не допускаете ли Вы (ну или мы) ошибок в проектировании? Почему уткнулись носом в одну-единственную проблему (как восстановить сигналы)? Это может съесть все время и силы. Может есть смысл посмотреть - а какие еще проблемы?
А я обычно так всегда утыкаюсь и бъюсь до потери пульса, пока не решу или буду вынужден отступить ;D

Ну напр один объект содержит указатель(и) на  другой (наверное это Алексей называет "перекрестные ссылки").
Александр :) Перекрёстные - да, когда друг на друга.

Тут возможны варианты - напр при удалении держащего тот всегда удаляет и указатель. Или не удаляет никогда. Или когда счетчик ссылок на указатель станет = 0. Как это все выглядит с точки зрения undo?
По идее, проблема с восстановлением сигналов возникла из-за того, что пока не придумали (я во всяком случае), каким образом можно получить информацию о конектах объекта (т.е. без какого-либо изврата). Если такие данные будут доступны, то восстановление работы через сигналы не видится сложным. Наверное аналогично и с перекрёстными указателями. Надо сохранять всю информацию об объекте, в т.ч. и всяческие указатели.

Но как всегда проблема только кажется легко решаемой. Когда объект помещается в корзину (удаляется через delete, но информация о нём где-нибудь сохранена) его родитель будет автоматом проинформирован об этом, и тот в свою очередь уже сам обнулит указатель. Но хуже обстоит ситуация со сторонними объектами, которые могут "глядеть в сторону" рассматриваемого нами подопытного. Конечно их всех можно "посадить" на сигнал QObject::destroyed(QObject *obj = 0), но это опять будет решение, притянутое за уши. В общем проблема, которая говорит, что между объектами должно быть как можно меньше ссылок друг на друга. Не то что даже перекрёстных, а просто, когда один на другого ссылается. Всё должно идти через посредника, который был бы озадачен разруливанием вот таких вот связей.


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: alexis031182 от Июнь 20, 2012, 12:56
вообще-то я и так понимаю о чем речь, я имею в виду вы можете привести конкретный пример. вот к примеру. у меня я на форме разместила текстовое поле по двойному нажатию на которое у меня выскакивает редактор текста этого окна. если я вместо удаления спрячу это текстовое поле, то соответственно пользователь уже не сможет на него нажать и сгенерировать это событие или сигнал. в данном случае этот коннект никому не мешает. вот я и спрашиваю конкретный пример коннекта, который может повлечь ошибки, рассматриваz вариант с hide()
Если Ваше текстовое поле будет подключено к ещё каким-либо сигналам, то в скрытом состоянии оно продолжит их принимать и обрабатывать. Таким образом, нажав как-нибудь на undo, пользователь увидит совсем не то текстовое поле, что ранее было скрыто.

может быть в слотах проверять состояние объекта, и в зависимости от этого выполнять или не выполнять действия?? но опять же я рассматриваю вариант с hide()
Вы везде стремитесь к концептуальным решениям, отличающимся гибкостью и изрядной долей изящества, но вставка if-проверки в слоты во всех мыслимых виджетах таковым решением не является.


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: alexis031182 от Июнь 20, 2012, 12:57
как мы можем удалить указатель, а если этот объект должен существовать независимо от удаляемого??
Имелось ввиду обнуление указателя.


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: alexis031182 от Июнь 20, 2012, 13:06
Усложним немного учебный пример undo. Допустим если мы тащим Rectangle - мы хотим чтобы остальные фигуры двигались тоже. Ну вот мы и получили тот самый случай.
Как и написал выше, нужен посредник. Если объекты будут ссылаться напрямую, то не получится восстановить (да и даже сохранить) ссылочную целостность при undo объекта.

Обратите внимание что alexis031182 не тратит время на изучение типа "а какие частные случаи возможны", а подходит к деактивации принципиально - никаких сигналов не должно быть получено вообще.
Да, потому что виджет виджету рознь. С парой десятков объектов может и прокатит if, блокирующий сигнал в слотах, но когда-нибудь это дело навернётся точно. Лучшее решение проблемы - это исключить возможность её появления в принципе.

Однако мне кажется этого недостаточно. "Хороший индеец - мертвый индеец". Мочить надо, а не цацкаться перенося туда-сюда
Я тоже именно за удаление. Это решает все проблемы с блокировкой сигналов (и событий тоже) автоматом. Но вот восстановление как произвести... Какую-то глобальную карту надо иметь обо всех конектах.


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: nata267 от Июнь 20, 2012, 13:17
вообще-то я и так понимаю о чем речь, я имею в виду вы можете привести конкретный пример.
Усложним немного учебный пример undo. Допустим если мы тащим Rectangle - мы хотим чтобы остальные фигуры двигались тоже. Ну вот мы и получили тот самый случай.

подождите, но ведь тогда посдеднем в стеке undo будет не удаление, а перетаскивание rectangle и только вернув его обратно, мы можем вернуть обратно объект.


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: alexis031182 от Июнь 20, 2012, 13:19
подождите, но ведь тогда посдеднем в стеке undo будет не удаление, а перетаскивание rectangle и только вернув его обратно, мы можем вернуть обратно объект.
Конечно, но это к частному вопросу о позиционировании. А мы упёрлись в проблему воссоздания объекта.


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: nata267 от Июнь 20, 2012, 13:20
а если нужно другое поведение, если нужно чтобы он в удаленном состоянии передвинулся. допустим у нас есть контейнер, который содержит набор виджетов. один мы удалили, контейнер передвинули в другое место, виджет восстановили. он должен быть в контейнере, а не за его пределами


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: nata267 от Июнь 20, 2012, 13:22
подождите, но ведь тогда посдеднем в стеке undo будет не удаление, а перетаскивание rectangle и только вернув его обратно, мы можем вернуть обратно объект.
Конечно, но это к частному вопросу о позиционировании. А мы упёрлись в проблему воссоздания объекта.

ну а как ещё решить проблему без конкретики? если вы ставите задачу абстрактно, я её могу понимать неправильно, подругому чем вы и мы говорим на разных языках


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: nata267 от Июнь 20, 2012, 13:26
возможно, способ удаления (удалять или прятать) как раз таки и зависит от конокретных случаев. сколько у удаляемых объектов связей и как их восстанавливать. может если связей много и для восстановления потребуется объект по величине такой же как удаляемый, то уместно действительно прятать а не удалять и просто решить проблему связей


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: alexis031182 от Июнь 20, 2012, 13:31
а если нужно другое поведение, если нужно чтобы он в удаленном состоянии передвинулся. допустим у нас есть контейнер, который содержит набор виджетов. один мы удалили, контейнер передвинули в другое место, виджет восстановили. он должен быть в контейнере, а не за его пределами
Операция undo, если глобальна, не даст восстановить объект, пока не отменятся предыдущие в стеке операции (например, смена положения). Если же undo для контейнера, то смена положения контейнера никак не повлияет на восстанавливаемый объект.


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: alexis031182 от Июнь 20, 2012, 13:33
ну а как ещё решить проблему без конкретики? если вы ставите задачу абстрактно, я её могу понимать неправильно, подругому чем вы и мы говорим на разных языках
Вот мы с Вами по ходу дела, по Вашим вопросам и уточняем, отчего могут быть проблемы в той или иной ситуации на практике. Норм :)


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: alexis031182 от Июнь 20, 2012, 13:36
возможно, способ удаления (удалять или прятать) как раз таки и зависит от конокретных случаев. сколько у удаляемых объектов связей и как их восстанавливать. может если связей много и для восстановления потребуется объект по величине такой же как удаляемый, то уместно действительно прятать а не удалять и просто решить проблему связей
Уместным в этой ситуации будет на мой взгляд вообще запретить undo/redo для таких объектов.


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: Igors от Июнь 20, 2012, 13:45
подождите, но ведь тогда посдеднем в стеке undo будет не удаление, а перетаскивание rectangle и только вернув его обратно, мы можем вернуть обратно объект.
Вернуть-то вернем, но его позиция не будет равна на момент "удаления"

а если нужно другое поведение, если нужно чтобы он в удаленном состоянии передвинулся. допустим у нас есть контейнер, который содержит набор виджетов. один мы удалили, контейнер передвинули в другое место, виджет восстановили. он должен быть в контейнере, а не за его пределами
Это может иметь смысл, но это уже не undo,

Какую-то глобальную карту надо иметь обо всех конектах.
А как она должна выглядеть? Что должно быть ключом? И не взять ли ширше - обо всех (подлежаших undo) объектах? А не замахнуться ли нам на Вильяма Шекспира - и формализовать весь механизм связей?

Но давайте не частить - слишком бурное обсуждение утомляет :) Пусть мысли созреют, достаточно на сегодня


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: nata267 от Июнь 20, 2012, 13:45
другой пример. если у нас иерархическая структура и мы удаляем узел, как быть с потомками? куда их переносить для восстановления?



Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: nata267 от Июнь 20, 2012, 13:49
подождите, но ведь тогда посдеднем в стеке undo будет не удаление, а перетаскивание rectangle и только вернув его обратно, мы можем вернуть обратно объект.
Вернуть-то вернем, но его позиция не будет равна на момент "удаления"



а позиция должна быть равна на момент удаления, причем позиция должна вернуться не только у него, но и не удаленных тоже, мы же их всех вместе перетаскивали и их перетавкивание относилось к перетаскиванию rectangle если я не ошибаюсь


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: alexis031182 от Июнь 20, 2012, 13:52
Какую-то глобальную карту надо иметь обо всех конектах.
А как она должна выглядеть? Что должно быть ключом? И не взять ли ширше - обо всех (подлежаших undo) объектах? А не замахнуться ли нам на Вильяма Шекспира - и формализовать весь механизм связей?
Я к тому, что эта информация не помешала бы. А уж как и чего - второй вопрос. Точнее первый, всё тот же ;D


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: alexis031182 от Июнь 20, 2012, 13:58
другой пример. если у нас иерархическая структура и мы удаляем узел, как быть с потомками? куда их переносить для восстановления?
Потомков придётся грохать тоже. И восстанавливать при восстановлении родителя. В этой уже ситуации мы как никогда близко находимся к тому, чтобы запрещение undo/redo было вполне себе рациональным решением. Естественно, что решение о подобном должно приниматься в каждом конкретном случае отдельно.


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: nata267 от Июнь 20, 2012, 14:15
другой пример. если у нас иерархическая структура и мы удаляем узел, как быть с потомками? куда их переносить для восстановления?
Потомков придётся грохать тоже. И восстанавливать при восстановлении родителя. В этой уже ситуации мы как никогда близко находимся к тому, чтобы запрещение undo/redo было вполне себе рациональным решением. Естественно, что решение о подобном должно приниматься в каждом конкретном случае отдельно.

а может в этой ситуации прятать?


Название: Re: Реализация Undo/Redo действий пользователя в случае mdi интерфейса
Отправлено: alexis031182 от Июнь 20, 2012, 14:39
а может в этой ситуации прятать?
Нет, ну конечно прятать или нет - решать разработчику. Просто он должен иметь ввиду возможные проблемы, о которых мы говорим.