Russian Qt Forum

Программирование => С/C++ => Тема начата: Nidxogg от Сентябрь 17, 2015, 18:36



Название: Вопрос по реализации
Отправлено: Nidxogg от Сентябрь 17, 2015, 18:36
Добрый день
Интересует совет как реализовать нужное поведение, может какой паттерн или все намного проще.

Суть:
Есть Qtприложение с плагинами.
Главная форма MainWindow + QMdiArea в centralWidget. Приложению известен только интерфейс плагинов.
В плагинах реализуются action-ы со слотами, создается меню, которое добавляется в menubar MainWindow. Собственно, результатом срабатывания action-а является создание окна-наследника QWidget.

И вопрос, как вернуть через указатель на это окно после срабатывания action-а, чтобы добавить его к QMdiArea? :-\


Название: Re: Вопрос по реализации
Отправлено: Racheengel от Сентябрь 18, 2015, 10:47
Сделать факторизацию через плагин, например, с интерфейсом типа

virtual QWidget* createWidget()
{
...
}

и вызывать этот метод при обработке экшина.


Название: Re: Вопрос по реализации
Отправлено: Nidxogg от Сентябрь 18, 2015, 19:16
Сделать факторизацию через плагин, например, с интерфейсом типа
virtual QWidget* createWidget()
{
...
}
и вызывать этот метод при обработке экшина.
То что указатель на виджет возвращается через интерфейс - это понятно
Аналогично я возвращаю указатель на меню после загрузки плагина

Вопрос в том, как сообщить MainWindow, что нужно вызвать этот метод, если обработка экшена находится внутри плагина.

И ещё вопрос, как отследить что окно закрылось и удалить его (не используя Qt::WA_DeleteOnClose). Вести какой-то контейнер указателей созданных окон внутри плагина?


Название: Re: Вопрос по реализации
Отправлено: Racheengel от Сентябрь 21, 2015, 11:58
Ваш плагин при загрузке должен как-то регистрироваться в приложении.
При регистрации сделайте связь экшена в плагине с методом приложения, которое будет вызывать createWidget().
Как вариант, обычным коннектом слотов-сигналов.

По поводу 2 - можно через QWidget::closeEvent, например.


Название: Re: Вопрос по реализации
Отправлено: Nidxogg от Сентябрь 21, 2015, 18:29
Цитировать
Ваш плагин при загрузке должен как-то регистрироваться в приложении.
При регистрации сделайте связь экшена в плагине с методом приложения, которое будет вызывать createWidget().
Как вариант, обычным коннектом слотов-сигналов.
В результате срабатывания каждого экшена создается окно определенного типа (все они наследники одного базового класса)
Я правильно понимаю, что createWidget() будет просто возвращать указатель на уже созданное окно внутри плагина (в результате экшена), а не сообщать плагину что именно надо создать? (Это вообще законно нормально?)


Цитировать
По поводу 2 - можно через QWidget::closeEvent, например.
Имеете ввиду переопределить этот метод в MainWindow?


Название: Re: Вопрос по реализации
Отправлено: Racheengel от Сентябрь 22, 2015, 01:30
Я правильно понимаю, что createWidget() будет просто возвращать указатель на уже созданное окно внутри плагина (в результате экшена), а не сообщать плагину что именно надо создать? (Это вообще законно нормально?)

А какая разница приложению, как именно плагин создает окно? Главное, чтобы тип созданного окна поддерживался приложением, но ведь ваш плагин это и так гарантирует.

Цитировать
По поводу 2 - можно через QWidget::closeEvent, например.
Имеете ввиду переопределить этот метод в MainWindow?
[/quote]

Я так понял, что вам надо, чтобы каждое окно сообщало о своем закрытии? Тогда в окне надо переопределить.


Название: Re: Вопрос по реализации
Отправлено: Nidxogg от Сентябрь 22, 2015, 18:44
Цитировать
Я так понял, что вам надо, чтобы каждое окно сообщало о своем закрытии? Тогда в окне надо переопределить.
Для сообщения я и так переопределил closeEvent (чтобы уведомлять о наличии несохраненных изменений)
Надо именно корректно освободить выделенную память при закрытии. Сейчас использую флаг deleteonclose, просто интересуют ещё варианты.
Я так понимаю в closeevent нельзя написать что-то вроде delete this?

Цитировать
А какая разница приложению, как именно плагин создает окно? Главное, чтобы тип созданного окна поддерживался приложением, но ведь ваш плагин это и так гарантирует.
Просто интересуюсь, может быть есть другие варианты

Получается, что в интерфейсе придется объявить виртуальный сигнал, сообщающий слоту в MainWindow, что необходимо запросить виджет? Или подключить сигналы от экшенов из возвращаемого интерфесом меню к слоту?


Название: Re: Вопрос по реализации
Отправлено: Racheengel от Сентябрь 22, 2015, 19:41
Цитировать
Я так понимаю в closeevent нельзя написать что-то вроде delete this?

Нельзя.

Цитировать
Сейчас использую флаг deleteonclose, просто интересуют ещё варианты.

Да нормальный, вроде, вариант :)

Цитировать
Получается, что в интерфейсе придется объявить виртуальный сигнал, сообщающий слоту в MainWindow, что необходимо запросить виджет? Или подключить сигналы от экшенов из возвращаемого интерфесом меню к слоту?

Ну так а разве экшены меню не плагином создаются?
Они же пусть будут подключены к слоту в плагине, который делает окно.
Или их можно делегировать в MainWindow, если необходимо по задаче.


Название: Re: Вопрос по реализации
Отправлено: Nidxogg от Сентябрь 22, 2015, 20:09
Цитировать
Ну так а разве экшены меню не плагином создаются?
Они же пусть будут подключены к слоту в плагине, который делает окно.
Все уже так.
Извиняюсь, если непонятно формулирую свои вопросы.

Цитировать
Или их можно делегировать в MainWindow, если необходимо по задаче.
Изначальный вопрос, как сообщить MainWindow, что нужно запросить у плагина окно, которое уже было создано внутри плагина.
Сначала были мысли сигнал в интерфейсе, связанный со слотом в MainWindow. Но мне почему-то такой вариант кажется не очень, какое-то "туда-сюда" получается.



Название: Re: Вопрос по реализации
Отправлено: Nidxogg от Сентябрь 23, 2015, 15:10
Сделал простенькое приложение, чтобы было понятно о чем речь
Проблема все та же, получить из плагина указатель на созданное окно

Даже если прикрутить сигнал в интерфейс, все равно надо как-то узнать, из какого именного плагина он испущен


Название: Re: Вопрос по реализации
Отправлено: Racheengel от Сентябрь 23, 2015, 15:38
Тогда можно передать поинтер на MainWindow в функцию Initialize().
После этого плагин будет знать про главное окно и куда вставлять свои окна.


Название: Re: Вопрос по реализации
Отправлено: Nidxogg от Сентябрь 23, 2015, 15:47
Тогда можно передать поинтер на MainWindow в функцию Initialize().
После этого плагин будет знать про главное окно и куда вставлять свои окна.

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