LINUX.ORG.RU

Qt, клонирование QObject


0

2

Добрый день. Вопрос к специалистам Qt. Делаю своеобразный редактор. Создаю иерархию классов. Базовый класс в ней (назовем RBase) наследуется от QWidget. Хочу, чтоб любой визуальный объект в редакторе можно было скопировать (выделили объект - копировать). Для этого в RBase добавил

virtual RBase *clone() const = 0;
чтобы в конкретных классах ее переопределять. каждый новосозданный объект создает некоторые соединения сигнал-слот.

Вопрос. как правильно скопировать QWidget, если конструктор копирования у него закрыт? открывать не предлагать. В итоге нужно создать идентичный объект (с такими же QWidget свойствами, такими же соединениями сигнал-слот).

Сейчас свойства копирую через мета информацию объекта (property(), setProperty()). Как скопировать инфу о соединениях не знаю. Заново вызывать для нового объекта connect не хотелось бы. Все коннекшены создаются в MainWindow, и лезть туда не хочется. Хочется извлечь эту инфу из копируемого объекта.

Заранее спасибо.

★★★★★

Виджеты не предназначены для клонирования.

Возможно, создание прототипов на каждый виджет будет более уместным.

schizoid ★★★
()

Как скопировать инфу о соединениях не знаю.

man QMetaObject man QMetaMethod man QObject::metaObject

RTFS SIGNAL, SLOT

Begemoth ★★★★★
()

А напиши, пожалуйста, для чего нужно клонировать виджеты, да еще и с соединениями сигнал-слот. Эти соединения у тебя предполагается динамически менять через гуй? Ты не редактор интерфейса пишешь часом?

thesis ★★★★★
()
Ответ на: комментарий от thesis

я же написал, в каком контексте это хочу использовать. кинул ты на форму таблицу. создались соединения (focusSet -> setWidgetModelToTableView к примеру). выделил эту таблицу (получил указатель на RBase), жму кнопку копировать (вызываю base->clone()). на форме 2 одинаковых таблицы. нет, не редактор интерфейса. соединения динамически менять не предполагается. Статически задать имена сигналам слотам не предлагать

vvviperrr ★★★★★
() автор топика
Ответ на: комментарий от Begemoth

ну поконкретнее можно? я же сказал, что свойства скопировал через metaObject->property(). как скопировать инфу о соединениях не нашел

vvviperrr ★★★★★
() автор топика
Ответ на: комментарий от schizoid

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

vvviperrr ★★★★★
() автор топика
Ответ на: комментарий от anonymous

я описал задачу. описал требуемое поведение. подскажи, как сделать «так».

vvviperrr ★★★★★
() автор топика
Ответ на: комментарий от vvviperrr

Просто я всерьез не понимаю, зачем клонировать элемент гуя целиком, если можно скопировать все его мало-мальски важные атрибуты и задать соединения сигнал-слот для копии там же, где это сделано для исходного элемента. Это уж не говоря о моём непонимании, для чего на форме две идентичных таблицы вообще, но это фиг с ним.

thesis ★★★★★
()
Ответ на: комментарий от nanoolinux

а у тебя ошибка в слове «неправильная». что конкретно неверно? есть tableView, есть виджет с моделью. создаем виджет - создаем соединение сигнал/слот. сигнал - виджет получил фокус. основное окно получает этот сигнал

tableView->setModel(focusWidget->model());

выделили виджет - нажали кнопку «Копировать», скопировали виджет (создали новый с таким же родителем с такими же пропертями). Как скопировать соннекшены не знаю. Заново вызывать все connect(..) вручную?

что неправильного в этой архитектуре?

vvviperrr ★★★★★
() автор топика
Ответ на: комментарий от thesis

да, я скопировал мало-мальски вижные атрибуты. да, я могу при клонировании вызвать какой нить метод initWidget(RBase *base), который заново установит все коннекшены, но мне это не нравится. вдруг в будущем захочу на разные виджеты вешать разные соединения.

Это уж не говоря о моём непонимании, для чего на форме две идентичных таблицы вообще, но это фиг с ним.

чтобы копию можно было опять редактировать. для упрощения жизни пользователям

vvviperrr ★★★★★
() автор топика
Ответ на: комментарий от vvviperrr

А как в общем случае скопировать маппинг сигнала? Вот, например, конструктор объекта класса А примапил сигнал объекта класса Б к своему приватному слоту. А тут к объекту класса Б лезет другой объект того же класса и говорит «хочу тебя клонировать». Вот так прямо брать и лепить еще один сигнал в приватный слот ничего не подозревающего объекта А?

вдруг в будущем захочу на разные виджеты вешать разные соединения.

А как здесь поможет клонирование?

thesis ★★★★★
()
Ответ на: комментарий от vvviperrr

Сделай данные implicitly shared. А в каждом виджете слот set_data(). Нажали кнопку копировать - создаёться ещё один виджет и подсовываеться ему существующие данные посредсвом вызова set_data() (или прямо в контструктор в качестве параметра).

nanoolinux ★★★★
()
Ответ на: комментарий от thesis

А как здесь поможет клонирование?

RTable table1;
table1.connect(...);
table1.connect(...);
table1.connect(...);

RTable table2;
table2.connect(...);

void copy(RBase *obj)
{
    RBase *newObj = obj->clone();
    newObj->show();
    // some other stuff with newObj
}

что неясного то, не пойму. при клонировании ХОЧУ получить АБСОЛЮТНО АНАЛОГИЧНЫЙ ОБЪЕКТ (свойства и коннекшены).

vvviperrr ★★★★★
() автор топика
Ответ на: комментарий от vvviperrr

Все неясное написано в первом вопросе.
Впрочем, на второй ты тоже не ответил.

thesis ★★★★★
()

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

trex6 ★★★★★
()
Ответ на: комментарий от vvviperrr

В документации есть раздел, в котором одробно написано, почему нельзя копировать QObject.

anonymous
()
Ответ на: комментарий от trex6

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

tableView->setModel(activeObject->model());
в QTableView отобразились свойства выделенного элемента. Их можно редактировать, они сохраняются в текущей модели. Кликнули на другой элемент - установили в таблицу новую модель.

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

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

vvviperrr ★★★★★
() автор топика
Ответ на: комментарий от anonymous

в доке описано, почему copy ctor закрыт, и это правильно. использовать идиому виртуального конструктора никто не запрещает.

анонимусы вообще тред читают перед постингом?

vvviperrr ★★★★★
() автор топика
Ответ на: комментарий от vvviperrr

Я правильно понял: при клике по элементу срабатывает сигнал в объекте.
Этот сигнал подключен к слоту какого-то main-объекта и уже в этом слоте вызывается tableView->setModel(...

Но ведь речь шла о том, что у тебя много соединений надо скопировать. Или я что-то не так понял?

trex6 ★★★★★
()
Ответ на: комментарий от trex6

Этот сигнал подключен к слоту какого-то main-объекта и уже в этом слоте вызывается tableView->setModel(...

именно так.

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

RTable table1;
table1.connect(...);
table1.connect(...);
table1.connect(...);

RTable table2;
table2.connect(...);

void copy(RBase *obj)
{
    RBase *newObj = obj->clone();
    newObj->show();
    // ??? какие соединения установить для newObj ???
}

vvviperrr ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.