KOffice – TDE office suite
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1602 line
45KB

  1. /* This file is part of the KDE project
  2. Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
  3. Copyright (C) 2005 Jaroslaw Staniek <js@iidea.pl>
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public
  6. License as published by the Free Software Foundation; either
  7. version 2 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public License
  13. along with this library; see the file COPYING.LIB. If not, write to
  14. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  15. * Boston, MA 02110-1301, USA.
  16. */
  17. #include <tqdom.h>
  18. #include <tqwidget.h>
  19. #include <tqlayout.h>
  20. #include <tqlabel.h>
  21. #include <tqsplitter.h>
  22. #include <tqmetaobject.h>
  23. #include <kdebug.h>
  24. #include <tdelocale.h>
  25. #include <tdepopupmenu.h>
  26. #include <tdemessagebox.h>
  27. #include <tdeaccelmanager.h>
  28. #include "formIO.h"
  29. #include "container.h"
  30. #include "objecttree.h"
  31. #include "formmanager.h"
  32. #include "form.h"
  33. #include "widgetlibrary.h"
  34. #include "events.h"
  35. #include "utils.h"
  36. #include "widgetpropertyset.h"
  37. #include "widgetwithsubpropertiesinterface.h"
  38. #include <koproperty/property.h>
  39. #include "commands.h"
  40. using namespace KFormDesigner;
  41. // Command
  42. Command::Command()
  43. : KCommand()
  44. {
  45. }
  46. Command::~Command()
  47. {
  48. }
  49. // PropertyCommand
  50. PropertyCommand::PropertyCommand(WidgetPropertySet *set, const TQCString &wname,
  51. const TQVariant &oldValue, const TQVariant &value, const TQCString &property)
  52. : Command(), m_propSet(set), m_value(value), m_property(property)
  53. {
  54. m_oldvalues.insert(wname, oldValue);
  55. }
  56. PropertyCommand::PropertyCommand(WidgetPropertySet *set, const TQMap<TQCString, TQVariant> &oldvalues,
  57. const TQVariant &value, const TQCString &property)
  58. : Command(), m_propSet(set), m_value(value), m_oldvalues(oldvalues), m_property(property)
  59. {
  60. }
  61. /*
  62. MultiCommand::MultiCommand()
  63. {
  64. }
  65. MultiCommandGroup::addSubCommand(PropertyCommand* subCommand)
  66. : Command(), m_propSet(set), m_value(value), m_oldvalues(oldvalues), m_property(property)
  67. {
  68. }
  69. */
  70. void
  71. PropertyCommand::setValue(const TQVariant &value)
  72. {
  73. m_value = value;
  74. emit FormManager::self()->dirty(FormManager::self()->activeForm());
  75. }
  76. void
  77. PropertyCommand::execute()
  78. {
  79. FormManager::self()->activeForm()->selectFormWidget();
  80. m_propSet->setUndoing(true);
  81. TQMap<TQCString, TQVariant>::ConstIterator endIt = m_oldvalues.constEnd();
  82. for(TQMap<TQCString, TQVariant>::ConstIterator it = m_oldvalues.constBegin(); it != endIt; ++it)
  83. {
  84. ObjectTreeItem* item = FormManager::self()->activeForm()->objectTree()->lookup(it.key());
  85. if (item) {//we're checking for item!=0 because the name could be of a form widget
  86. FormManager::self()->activeForm()->setSelectedWidget(item->widget(), true);
  87. }
  88. }
  89. (*m_propSet)[m_property] = m_value;
  90. m_propSet->setUndoing(false);
  91. }
  92. void
  93. PropertyCommand::unexecute()
  94. {
  95. FormManager::self()->activeForm()->selectFormWidget();
  96. m_propSet->setUndoing(true);
  97. TQMap<TQCString, TQVariant>::ConstIterator endIt = m_oldvalues.constEnd();
  98. for(TQMap<TQCString, TQVariant>::ConstIterator it = m_oldvalues.constBegin(); it != endIt; ++it)
  99. {
  100. ObjectTreeItem* item = FormManager::self()->activeForm()->objectTree()->lookup(it.key());
  101. if (!item)
  102. continue; //better this than a crash
  103. TQWidget *widg = item->widget();
  104. FormManager::self()->activeForm()->setSelectedWidget(widg, true);
  105. //m_propSet->setSelectedWidget(widg, true);
  106. WidgetWithSubpropertiesInterface* subpropIface = dynamic_cast<WidgetWithSubpropertiesInterface*>(widg);
  107. TQWidget *subWidget = (subpropIface && subpropIface->subwidget()) ? subpropIface->subwidget() : widg;
  108. if (-1!=subWidget->metaObject()->findProperty( m_property, true ))
  109. subWidget->setProperty(m_property, it.data());
  110. }
  111. (*m_propSet)[m_property] = m_oldvalues.begin().data();
  112. m_propSet->setUndoing(false);
  113. }
  114. TQString
  115. PropertyCommand::name() const
  116. {
  117. if(m_oldvalues.count() >= 2)
  118. return i18n("Change \"%1\" property for multiple widgets" ).arg(TQString(m_property));
  119. else
  120. return i18n("Change \"%1\" property for widget \"%2\"" ).arg(TQString(m_property)).arg(TQString(m_oldvalues.begin().key()));
  121. }
  122. void
  123. PropertyCommand::debug()
  124. {
  125. kdDebug() << "PropertyCommand: name=\"" << name() << "\" widgets=" << m_oldvalues.keys()
  126. << " value=" << m_value << " oldValues=" << m_oldvalues.values() << endl;
  127. }
  128. // GeometryPropertyCommand (for multiples widgets)
  129. GeometryPropertyCommand::GeometryPropertyCommand(WidgetPropertySet *set,
  130. const TQStringList &names, const TQPoint& oldPos)
  131. : Command(), m_propSet(set), m_names(names), m_oldPos(oldPos)
  132. {
  133. }
  134. void
  135. GeometryPropertyCommand::execute()
  136. {
  137. m_propSet->setUndoing(true);
  138. int dx = m_pos.x() - m_oldPos.x();
  139. int dy = m_pos.y() - m_oldPos.y();
  140. TQStringList::ConstIterator endIt = m_names.constEnd();
  141. // We move every widget in our list by (dx, dy)
  142. for(TQStringList::ConstIterator it = m_names.constBegin(); it != endIt; ++it)
  143. {
  144. ObjectTreeItem* item = FormManager::self()->activeForm()->objectTree()->lookup(*it);
  145. if (!item)
  146. continue; //better this than a crash
  147. TQWidget *w = item->widget();
  148. w->move(w->x() + dx, w->y() + dy);
  149. }
  150. m_propSet->setUndoing(false);
  151. }
  152. void
  153. GeometryPropertyCommand::unexecute()
  154. {
  155. m_propSet->setUndoing(true);
  156. int dx = m_pos.x() - m_oldPos.x();
  157. int dy = m_pos.y() - m_oldPos.y();
  158. TQStringList::ConstIterator endIt = m_names.constEnd();
  159. // We move every widget in our list by (-dx, -dy) to undo the move
  160. for(TQStringList::ConstIterator it = m_names.constBegin(); it != endIt; ++it)
  161. {
  162. ObjectTreeItem* item = FormManager::self()->activeForm()->objectTree()->lookup(*it);
  163. if (!item)
  164. continue; //better this than a crash
  165. TQWidget *w = item->widget();
  166. w->move(w->x() - dx, w->y() - dy);
  167. }
  168. m_propSet->setUndoing(false);
  169. }
  170. void
  171. GeometryPropertyCommand::setPos(const TQPoint& pos)
  172. {
  173. m_pos = pos;
  174. emit FormManager::self()->dirty(FormManager::self()->activeForm());
  175. }
  176. TQString
  177. GeometryPropertyCommand::name() const
  178. {
  179. return i18n("Move multiple widgets");
  180. }
  181. void
  182. GeometryPropertyCommand::debug()
  183. {
  184. kdDebug() << "GeometryPropertyCommand: pos=" << m_pos << " oldPos=" << m_oldPos
  185. << " widgets=" << m_names << endl;
  186. }
  187. ///////////////// AlignWidgetsCommand ////////
  188. AlignWidgetsCommand::AlignWidgetsCommand(int type, WidgetList &list, Form *form)
  189. : Command(), m_form(form), m_type(type)
  190. {
  191. for(TQWidget *w = list.first(); w; w = list.next())
  192. m_pos.insert(w->name(), w->pos());
  193. }
  194. void
  195. AlignWidgetsCommand::execute()
  196. {
  197. // To avoid creation of GeometryPropertyCommand
  198. m_form->selectFormWidget();
  199. int gridX = m_form->gridSize();
  200. int gridY = m_form->gridSize();
  201. TQWidget *parentWidget = m_form->selectedWidgets()->first()->parentWidget();
  202. int tmpx, tmpy;
  203. WidgetList list;
  204. TQMap<TQCString, TQPoint>::ConstIterator endIt = m_pos.constEnd();
  205. for(TQMap<TQCString, TQPoint>::ConstIterator it = m_pos.constBegin(); it != endIt; ++it)
  206. {
  207. ObjectTreeItem *item = m_form->objectTree()->lookup(it.key());
  208. if(item && item->widget())
  209. list.append(item->widget());
  210. }
  211. switch(m_type)
  212. {
  213. case AlignToGrid:
  214. {
  215. for(TQWidget *w = list.first(); w; w = list.next())
  216. {
  217. tmpx = int( (float)w->x() / ((float)gridX) + 0.5 ) * gridX;
  218. tmpy = int( (float)w->y() / ((float)gridY) + 0.5 ) * gridY;
  219. if((tmpx != w->x()) || (tmpy != w->y()))
  220. w->move(tmpx, tmpy);
  221. }
  222. break;
  223. }
  224. case AlignToLeft:
  225. {
  226. tmpx = parentWidget->width();
  227. for(TQWidget *w = list.first(); w; w = list.next())
  228. {
  229. if(w->x() < tmpx)
  230. tmpx = w->x();
  231. }
  232. for(TQWidget *w = list.first(); w; w = list.next())
  233. w->move(tmpx, w->y());
  234. break;
  235. }
  236. case AlignToRight:
  237. {
  238. tmpx = 0;
  239. for(TQWidget *w = list.first(); w; w = list.next())
  240. {
  241. if(w->x() + w->width() > tmpx)
  242. tmpx = w->x() + w->width();
  243. }
  244. for(TQWidget *w = list.first(); w; w = list.next())
  245. w->move(tmpx - w->width(), w->y());
  246. break;
  247. }
  248. case AlignToTop:
  249. {
  250. tmpy = parentWidget->height();
  251. for(TQWidget *w = list.first(); w; w = list.next())
  252. {
  253. if(w->y() < tmpy)
  254. tmpy = w->y();
  255. }
  256. for(TQWidget *w = list.first(); w; w = list.next())
  257. w->move(w->x(), tmpy);
  258. break;
  259. }
  260. case AlignToBottom:
  261. {
  262. tmpy = 0;
  263. for(TQWidget *w = list.first(); w; w = list.next())
  264. {
  265. if(w->y() + w->height() > tmpy)
  266. tmpy = w->y() + w->height();
  267. }
  268. for(TQWidget *w = list.first(); w; w = list.next())
  269. w->move(w->x(), tmpy - w->height());
  270. break;
  271. }
  272. default:
  273. return;
  274. }
  275. // We restore selection
  276. for(TQWidget *w = list.first(); w; w = list.next())
  277. m_form->setSelectedWidget(w, true);
  278. }
  279. void
  280. AlignWidgetsCommand::unexecute()
  281. {
  282. // To avoid creation of GeometryPropertyCommand
  283. m_form->selectFormWidget();
  284. // We move widgets to their original pos
  285. TQMap<TQCString, TQPoint>::ConstIterator endIt = m_pos.constEnd();
  286. for(TQMap<TQCString, TQPoint>::ConstIterator it = m_pos.constBegin(); it != endIt; ++it)
  287. {
  288. ObjectTreeItem *item = m_form->objectTree()->lookup(it.key());
  289. if(item && item->widget())
  290. item->widget()->move( m_pos[item->widget()->name()] );
  291. m_form->setSelectedWidget(item->widget(), true); // We restore selection
  292. }
  293. }
  294. TQString
  295. AlignWidgetsCommand::name() const
  296. {
  297. switch(m_type)
  298. {
  299. case AlignToGrid:
  300. return i18n("Align Widgets to Grid");
  301. case AlignToLeft:
  302. return i18n("Align Widgets to Left");
  303. case AlignToRight:
  304. return i18n("Align Widgets to Right");
  305. case AlignToTop:
  306. return i18n("Align Widgets to Top");
  307. case AlignToBottom:
  308. return i18n("Align Widgets to Bottom");
  309. default:
  310. return TQString();
  311. }
  312. }
  313. void
  314. AlignWidgetsCommand::debug()
  315. {
  316. kdDebug() << "AlignWidgetsCommand: name=\"" << name() << "\" form=" << m_form->widget()->name()
  317. << " widgets=" << m_pos.keys() << endl;
  318. }
  319. ///// AdjustSizeCommand ///////////
  320. AdjustSizeCommand::AdjustSizeCommand(int type, WidgetList &list, Form *form)
  321. : Command(), m_form(form), m_type(type)
  322. {
  323. for(TQWidget *w = list.first(); w; w = list.next())
  324. {
  325. if(w->parentWidget() && w->parentWidget()->isA(TQWIDGETSTACK_OBJECT_NAME_STRING))
  326. {
  327. w = w->parentWidget(); // widget is WidgetStack page
  328. if(w->parentWidget() && w->parentWidget()->inherits(TQTABWIDGET_OBJECT_NAME_STRING)) // widget is tabwidget page
  329. w = w->parentWidget();
  330. }
  331. m_sizes.insert(w->name(), w->size());
  332. if(m_type == SizeToGrid) // SizeToGrid also move widgets
  333. m_pos.insert(w->name(), w->pos());
  334. }
  335. }
  336. void
  337. AdjustSizeCommand::execute()
  338. {
  339. // To avoid creation of GeometryPropertyCommand
  340. m_form->selectFormWidget();
  341. int gridX = m_form->gridSize();
  342. int gridY = m_form->gridSize();
  343. int tmpw=0, tmph=0;
  344. WidgetList list;
  345. TQMap<TQCString, TQSize>::ConstIterator endIt = m_sizes.constEnd();
  346. for(TQMap<TQCString, TQSize>::ConstIterator it = m_sizes.constBegin(); it != endIt; ++it)
  347. {
  348. ObjectTreeItem *item = m_form->objectTree()->lookup(it.key());
  349. if(item && item->widget())
  350. list.append(item->widget());
  351. }
  352. switch(m_type)
  353. {
  354. case SizeToGrid:
  355. {
  356. int tmpx=0, tmpy=0;
  357. // same as in 'Align to Grid' + for the size
  358. for(TQWidget *w = list.first(); w; w = list.next())
  359. {
  360. tmpx = int( (float)w->x() / ((float)gridX) + 0.5 ) * gridX;
  361. tmpy = int( (float)w->y() / ((float)gridY) + 0.5 ) * gridY;
  362. tmpw = int( (float)w->width() / ((float)gridX) + 0.5 ) * gridX;
  363. tmph = int( (float)w->height() / ((float)gridY) + 0.5 ) * gridY;
  364. if((tmpx != w->x()) || (tmpy != w->y()))
  365. w->move(tmpx, tmpy);
  366. if((tmpw != w->width()) || (tmph != w->height()))
  367. w->resize(tmpw, tmph);
  368. }
  369. break;
  370. }
  371. case SizeToFit:
  372. {
  373. for(TQWidget *w = list.first(); w; w = list.next()) {
  374. ObjectTreeItem *item = m_form->objectTree()->lookup(w->name());
  375. if(item && !item->children()->isEmpty()) { // container
  376. TQSize s;
  377. if(item->container() && item->container()->layout())
  378. s = w->sizeHint();
  379. else
  380. s = getSizeFromChildren(item);
  381. // minimum size for containers
  382. if(s.width() < 30)
  383. s.setWidth(30);
  384. if(s.height() < 30)
  385. s.setHeight(30);
  386. // small hack for flow layouts
  387. int type = item->container() ? item->container()->layoutType() : Container::NoLayout;
  388. if(type == Container::HFlow)
  389. s.setWidth(s.width() + 5);
  390. else if(type == Container::VFlow)
  391. s.setHeight(s.height() + 5);
  392. w->resize(s);
  393. }
  394. else if(item && item->container()) // empty container
  395. w->resize(item->container()->form()->gridSize() * 5, item->container()->form()->gridSize() * 5); // basic size
  396. else {
  397. TQSize sizeHint(w->sizeHint());
  398. if (sizeHint.isValid())
  399. w->resize(sizeHint);
  400. }
  401. }
  402. break;
  403. }
  404. case SizeToSmallWidth:
  405. {
  406. for(TQWidget *w = list.first(); w; w = list.next())
  407. {
  408. if((tmpw == 0) || (w->width() < tmpw))
  409. tmpw = w->width();
  410. }
  411. for(TQWidget *w = list.first(); w; w = list.next())
  412. {
  413. if(tmpw != w->width())
  414. w->resize(tmpw, w->height());
  415. }
  416. break;
  417. }
  418. case SizeToBigWidth:
  419. {
  420. for(TQWidget *w = list.first(); w; w = list.next())
  421. {
  422. if(w->width() > tmpw)
  423. tmpw = w->width();
  424. }
  425. for(TQWidget *w = list.first(); w; w = list.next())
  426. {
  427. if(tmpw != w->width())
  428. w->resize(tmpw, w->height());
  429. }
  430. break;
  431. }
  432. case SizeToSmallHeight:
  433. {
  434. for(TQWidget *w = list.first(); w; w = list.next())
  435. {
  436. if((tmph == 0) || (w->height() < tmph))
  437. tmph = w->height();
  438. }
  439. for(TQWidget *w = list.first(); w; w = list.next())
  440. {
  441. if(tmph != w->height())
  442. w->resize(w->width(), tmph);
  443. }
  444. break;
  445. }
  446. case SizeToBigHeight:
  447. {
  448. for(TQWidget *w = list.first(); w; w = list.next())
  449. {
  450. if(w->height() > tmph)
  451. tmph = w->height();
  452. }
  453. for(TQWidget *w = list.first(); w; w = list.next())
  454. {
  455. if(tmph != w->height())
  456. w->resize(w->width(), tmph);
  457. }
  458. break;
  459. }
  460. default:
  461. break;
  462. }
  463. // We restore selection
  464. for(TQWidget *w = list.first(); w; w = list.next())
  465. m_form->setSelectedWidget(w, true);
  466. }
  467. TQSize
  468. AdjustSizeCommand::getSizeFromChildren(ObjectTreeItem *item)
  469. {
  470. if(!item->container()) // multi pages containers (eg tabwidget)
  471. {
  472. TQSize s;
  473. // get size for each container, and keep the biggest one
  474. for(ObjectTreeItem *tree = item->children()->first(); tree; tree = item->children()->next())
  475. s = s.expandedTo(getSizeFromChildren(tree));
  476. return s;
  477. }
  478. int tmpw = 0, tmph = 0;
  479. for(ObjectTreeItem *tree = item->children()->first(); tree; tree = item->children()->next()) {
  480. if(!tree->widget())
  481. continue;
  482. tmpw = TQMAX(tmpw, tree->widget()->geometry().right());
  483. tmph = TQMAX(tmph, tree->widget()->geometry().bottom());
  484. }
  485. return TQSize(tmpw, tmph) + TQSize(10, 10);
  486. }
  487. void
  488. AdjustSizeCommand::unexecute()
  489. {
  490. // To avoid creation of GeometryPropertyCommand
  491. m_form->selectFormWidget();
  492. // We resize widgets to their original size
  493. TQMap<TQCString, TQSize>::ConstIterator endIt = m_sizes.constEnd();
  494. for(TQMap<TQCString, TQSize>::ConstIterator it = m_sizes.constBegin(); it != endIt; ++it)
  495. {
  496. ObjectTreeItem *item = m_form->objectTree()->lookup(it.key());
  497. if(item && item->widget())
  498. {
  499. item->widget()->resize( m_sizes[item->widget()->name()] );
  500. if(m_type == SizeToGrid)
  501. item->widget()->move( m_pos[item->widget()->name()] );
  502. m_form->setSelectedWidget(item->widget(), true); // We restore selection
  503. }
  504. }
  505. }
  506. TQString
  507. AdjustSizeCommand::name() const
  508. {
  509. switch(m_type)
  510. {
  511. case SizeToGrid:
  512. return i18n("Resize Widgets to Grid");
  513. case SizeToFit:
  514. return i18n("Resize Widgets to Fit Contents");
  515. case SizeToSmallWidth:
  516. return i18n("Resize Widgets to Narrowest");
  517. case SizeToBigWidth:
  518. return i18n("Resize Widgets to Widest");
  519. case SizeToSmallHeight:
  520. return i18n("Resize Widgets to Shortest");
  521. case SizeToBigHeight:
  522. return i18n("Resize Widgets to Tallest");
  523. default:
  524. return TQString();
  525. }
  526. }
  527. void
  528. AdjustSizeCommand::debug()
  529. {
  530. kdDebug() << "AdjustSizeCommand: name=\"" << name() << "\" form=" << m_form->widget()->name()
  531. << " widgets=" << m_sizes.keys() << endl;
  532. }
  533. // LayoutPropertyCommand
  534. LayoutPropertyCommand::LayoutPropertyCommand(WidgetPropertySet *buf, const TQCString &wname,
  535. const TQVariant &oldValue, const TQVariant &value)
  536. : PropertyCommand(buf, wname, oldValue, value, "layout")
  537. {
  538. m_form = FormManager::self()->activeForm();
  539. ObjectTreeItem* titem = m_form->objectTree()->lookup(wname);
  540. if (!titem)
  541. return; //better this than a crash
  542. Container *m_container = titem->container();
  543. // We save the geometry of each wigdet
  544. for(ObjectTreeItem *it = m_container->objectTree()->children()->first(); it; it = m_container->objectTree()->children()->next())
  545. m_geometries.insert(it->name().latin1(), it->widget()->geometry());
  546. }
  547. void
  548. LayoutPropertyCommand::execute()
  549. {
  550. PropertyCommand::execute();
  551. }
  552. void
  553. LayoutPropertyCommand::unexecute()
  554. {
  555. ObjectTreeItem* titem = m_form->objectTree()->lookup(m_oldvalues.begin().key());
  556. if (!titem)
  557. return; //better this than a crash
  558. Container *m_container = titem->container();
  559. m_container->setLayout(Container::NoLayout);
  560. // We put every widget back in its old location
  561. TQMap<TQCString,TQRect>::ConstIterator endIt = m_geometries.constEnd();
  562. for(TQMap<TQCString,TQRect>::ConstIterator it = m_geometries.constBegin(); it != endIt; ++it)
  563. {
  564. ObjectTreeItem *tree = m_container->form()->objectTree()->lookup(it.key());
  565. if(tree)
  566. tree->widget()->setGeometry(it.data());
  567. }
  568. PropertyCommand::unexecute();
  569. }
  570. TQString
  571. LayoutPropertyCommand::name() const
  572. {
  573. return i18n("Change layout of widget \"%1\"").arg(TQString(m_oldvalues.begin().key()));
  574. }
  575. void
  576. LayoutPropertyCommand::debug()
  577. {
  578. kdDebug() << "LayoutPropertyCommand: name=\"" << name() << "\" oldValue=" << m_oldvalues.keys()
  579. << " value=" << m_value << endl;
  580. }
  581. // InsertWidgetCommand
  582. InsertWidgetCommand::InsertWidgetCommand(Container *container)
  583. : Command()
  584. {
  585. m_containername = container->widget()->name();
  586. m_form = container->form();
  587. m_class = FormManager::self()->selectedClass();
  588. m_insertRect = container->m_insertRect;
  589. m_point = container->m_insertBegin;
  590. m_name = container->form()->objectTree()->generateUniqueName(
  591. container->form()->library()->namePrefix(m_class).latin1(),
  592. /*!numberSuffixRequired*/false);
  593. }
  594. InsertWidgetCommand::InsertWidgetCommand(Container *container,
  595. const TQCString& className, const TQPoint& pos, const TQCString& namePrefix)
  596. : Command()
  597. {
  598. m_containername = container->widget()->name();
  599. m_form = container->form();
  600. m_class = className;
  601. //m_insertRect is null (default)
  602. m_point = pos;
  603. if (namePrefix.isEmpty()) {
  604. m_name = container->form()->objectTree()->generateUniqueName(
  605. container->form()->library()->namePrefix(m_class).latin1() );
  606. }
  607. else {
  608. m_name = container->form()->objectTree()->generateUniqueName(
  609. namePrefix, false /*!numberSuffixRequired*/ );
  610. }
  611. }
  612. void
  613. InsertWidgetCommand::execute()
  614. {
  615. if (!m_form->objectTree())
  616. return;
  617. ObjectTreeItem* titem = m_form->objectTree()->lookup(m_containername);
  618. if (!titem)
  619. return; //better this than a crash
  620. Container *m_container = titem->container();
  621. int options = WidgetFactory::DesignViewMode | WidgetFactory::AnyOrientation;
  622. if (m_container->form()->library()->internalProperty(m_class, "orientationSelectionPopup")=="1") {
  623. if(m_insertRect.isValid()) {
  624. if (m_insertRect.width() < m_insertRect.height()) {
  625. options |= WidgetFactory::VerticalOrientation;
  626. options ^= WidgetFactory::AnyOrientation;
  627. }
  628. else if (m_insertRect.width() > m_insertRect.height()) {
  629. options |= WidgetFactory::HorizontalOrientation;
  630. options ^= WidgetFactory::AnyOrientation;
  631. }
  632. }
  633. if (options & WidgetFactory::AnyOrientation) {
  634. options ^= WidgetFactory::AnyOrientation;
  635. options |= m_container->form()->library()->showOrientationSelectionPopup(
  636. m_class, m_container->m_container,
  637. m_container->form()->widget()->mapToGlobal(m_point));
  638. if (options & WidgetFactory::AnyOrientation)
  639. return; //cancelled
  640. }
  641. }
  642. else
  643. options |= WidgetFactory::AnyOrientation;
  644. TQWidget *w = m_container->form()->library()->createWidget(m_class, m_container->m_container, m_name,
  645. m_container, options);
  646. if(!w) {
  647. FormManager::self()->stopInsert();
  648. WidgetInfo *winfo = m_container->form()->library()->widgetInfoForClassName(m_class);
  649. KMessageBox::sorry(FormManager::self()->activeForm() ? FormManager::self()->activeForm()->widget() : 0,
  650. i18n("Could not insert widget of type \"%1\". A problem with widget's creation encountered.")
  651. .arg(winfo ? winfo->name() : TQString()));
  652. kdWarning() << "InsertWidgetCommand::execute() ERROR: widget creation failed" << endl;
  653. return;
  654. }
  655. #if TDE_VERSION >= TDE_MAKE_VERSION(3,4,0)
  656. //! @todo allow setting this for data view mode as well
  657. if (m_form->designMode()) {
  658. //don't generate accelerators for widgets in design mode
  659. TDEAcceleratorManager::setNoAccel(w);
  660. }
  661. #endif
  662. // if the insertRect is invalid (ie only one point), we use widget' size hint
  663. if(( (m_insertRect.width() < 21) && (m_insertRect.height() < 21)))
  664. {
  665. TQSize s = w->sizeHint();
  666. if(s.isEmpty())
  667. s = TQSize(20, 20); // Minimum size to avoid creating a (0,0) widget
  668. int x, y;
  669. if(m_insertRect.isValid())
  670. {
  671. x = m_insertRect.x();
  672. y = m_insertRect.y();
  673. }
  674. else
  675. {
  676. x = m_point.x();
  677. y = m_point.y();
  678. }
  679. m_insertRect = TQRect(x, y, s.width() + 16/* add some space so more text can be entered*/,
  680. s.height());
  681. }
  682. w->move(m_insertRect.x(), m_insertRect.y());
  683. w->resize(m_insertRect.width()-1, m_insertRect.height()-1); // -1 is not to hide dots
  684. w->setStyle(&(m_container->widget()->style()));
  685. w->setBackgroundOrigin(TQWidget::ParentOrigin);
  686. w->show();
  687. FormManager::self()->stopInsert();
  688. // ObjectTreeItem object already exists for widgets which corresponds to a Container
  689. // it's already created in Container's constructor
  690. ObjectTreeItem *item = m_container->form()->objectTree()->lookup(m_name);
  691. if (!item) { //not yet created...
  692. m_container->form()->objectTree()->addItem(m_container->m_tree,
  693. item = new ObjectTreeItem(m_container->form()->library()->displayName(m_class), m_name, w, m_container)
  694. );
  695. }
  696. //assign item for its widget if it supports DesignTimeDynamicChildWidgetHandler interface
  697. //(e.g. KexiDBAutoField)
  698. if (m_form->designMode() && dynamic_cast<DesignTimeDynamicChildWidgetHandler*>(w)) {
  699. dynamic_cast<DesignTimeDynamicChildWidgetHandler*>(w)->assignItem(item);
  700. }
  701. // We add the autoSaveProperties in the modifProp list of the ObjectTreeItem, so that they are saved later
  702. TQValueList<TQCString> list(m_container->form()->library()->autoSaveProperties(w->className()));
  703. TQValueList<TQCString>::ConstIterator endIt = list.constEnd();
  704. for(TQValueList<TQCString>::ConstIterator it = list.constBegin(); it != endIt; ++it)
  705. item->addModifiedProperty(*it, w->property(*it));
  706. m_container->reloadLayout(); // reload the layout to take the new wigdet into account
  707. m_container->setSelectedWidget(w, false);
  708. if (m_container->form()->library()->internalProperty(w->className(),
  709. "dontStartEditingOnInserting").isEmpty())
  710. {
  711. m_container->form()->library()->startEditing(
  712. w->className(), w, item->container() ? item->container() : m_container); // we edit the widget on creation
  713. }
  714. //! @todo update widget's width for entered text's metrics
  715. kdDebug() << "Container::eventFilter(): widget added " << this << endl;
  716. }
  717. void
  718. InsertWidgetCommand::unexecute()
  719. {
  720. ObjectTreeItem* titem = m_form->objectTree()->lookup(m_name);
  721. if (!titem)
  722. return; //better this than a crash
  723. TQWidget *m_widget = titem->widget();
  724. Container *m_container = m_form->objectTree()->lookup(m_containername)->container();
  725. m_container->deleteWidget(m_widget);
  726. }
  727. TQString
  728. InsertWidgetCommand::name() const
  729. {
  730. if(!m_name.isEmpty())
  731. return i18n("Insert widget \"%1\"").arg(TQString(m_name));
  732. else
  733. return i18n("Insert widget");
  734. }
  735. void
  736. InsertWidgetCommand::debug()
  737. {
  738. kdDebug() << "InsertWidgetCommand: name=\"" << name() << "\" generatedName=" << m_name
  739. << " container=" << m_containername
  740. << " form=" << m_form->widget()->name() << " class=" << m_class
  741. << " rect=" << m_insertRect << " pos=" << m_point << endl;
  742. }
  743. /// CreateLayoutCommand ///////////////
  744. CreateLayoutCommand::CreateLayoutCommand(int layoutType, WidgetList &list, Form *form)
  745. : m_form(form), m_type(layoutType)
  746. {
  747. WidgetList *m_list=0;
  748. switch(layoutType)
  749. {
  750. case Container::HBox:
  751. case Container::Grid:
  752. case Container::HSplitter:
  753. case Container::HFlow:
  754. m_list = new HorWidgetList(form->toplevelContainer()->widget()); break;
  755. case Container::VBox:
  756. case Container::VSplitter:
  757. case Container::VFlow:
  758. m_list = new VerWidgetList(form->toplevelContainer()->widget()); break;
  759. }
  760. for(TQWidget *w = list.first(); w; w = list.next())
  761. m_list->append(w);
  762. m_list->sort(); // we sort them now, before creating the layout
  763. for(TQWidget *w = m_list->first(); w; w = m_list->next())
  764. m_pos.insert(w->name(), w->geometry());
  765. ObjectTreeItem *item = form->objectTree()->lookup(m_list->first()->name());
  766. if(item && item->parent()->container())
  767. m_containername = item->parent()->name();
  768. delete m_list;
  769. }
  770. void
  771. CreateLayoutCommand::execute()
  772. {
  773. WidgetLibrary *lib = m_form->library();
  774. if(!lib)
  775. return;
  776. ObjectTreeItem* titem = m_form->objectTree()->lookup(m_containername);
  777. Container *container = titem ? titem->container() : 0;
  778. if(!container)
  779. container = m_form->toplevelContainer(); // use toplevelContainer by default
  780. TQCString classname;
  781. switch(m_type) {
  782. case Container::HSplitter: case Container::VSplitter:
  783. classname = TQSPLITTER_OBJECT_NAME_STRING; break;
  784. default:
  785. classname = Container::layoutTypeToString(m_type).latin1();
  786. }
  787. if(m_name.isEmpty())// the name must be generated only once
  788. m_name = m_form->objectTree()->generateUniqueName(classname);
  789. TQWidget *w = lib->createWidget(classname, container->widget(), m_name.latin1(), container);
  790. #if TDE_VERSION >= TDE_MAKE_VERSION(3,4,0)
  791. //! @todo allow setting this for data view mode as well
  792. if (w) {
  793. if (m_form->designMode()) {
  794. //don't generate accelerators for widgets in design mode
  795. TDEAcceleratorManager::setNoAccel(w);
  796. }
  797. }
  798. #endif
  799. ObjectTreeItem *tree = w ? m_form->objectTree()->lookup(w->name()) : 0;
  800. if(!tree)
  801. return;
  802. container->setSelectedWidget(0, false);
  803. w->move(m_pos.begin().data().topLeft()); // we move the layout at the position of the topleft widget
  804. // sizeHint of these widgets depends on geometry, so give them appropriate geometry
  805. if(m_type == Container::HFlow)
  806. w->resize( TQSize(700, 20) );
  807. else if(m_type == Container::VFlow)
  808. w->resize( TQSize(20, 700));
  809. w->show();
  810. // We reparent every widget to the Layout and insert them into it
  811. TQMap<TQCString,TQRect>::ConstIterator endIt = m_pos.constEnd();
  812. for(TQMap<TQCString,TQRect>::ConstIterator it = m_pos.constBegin(); it != endIt; ++it)
  813. {
  814. ObjectTreeItem *item = m_form->objectTree()->lookup(it.key());
  815. if(item && item->widget())
  816. {
  817. item->widget()->reparent(w, item->widget()->pos(), true);
  818. item->eventEater()->setContainer(tree->container());
  819. m_form->objectTree()->reparent(item->name(), m_name);
  820. }
  821. }
  822. if(m_type == Container::HSplitter)
  823. ((TQSplitter*)w)->setOrientation(Qt::Horizontal);
  824. else if(m_type == Container::VSplitter)
  825. ((TQSplitter*)w)->setOrientation(Qt::Vertical);
  826. else if(tree->container()) {
  827. tree->container()->setLayout((Container::LayoutType)m_type);
  828. w->resize(tree->container()->layout()->sizeHint()); // the layout doesn't have its own size
  829. }
  830. container->setSelectedWidget(w, false);
  831. FormManager::self()->windowChanged(m_form->widget()); // to reload the ObjectTreeView
  832. }
  833. void
  834. CreateLayoutCommand::unexecute()
  835. {
  836. ObjectTreeItem *parent = m_form->objectTree()->lookup(m_containername);
  837. if(!parent)
  838. parent = m_form->objectTree();
  839. // We reparent every widget to the Container and take them out of the layout
  840. TQMap<TQCString,TQRect>::ConstIterator endIt = m_pos.constEnd();
  841. for(TQMap<TQCString,TQRect>::ConstIterator it = m_pos.constBegin(); it != endIt; ++it)
  842. {
  843. ObjectTreeItem *item = m_form->objectTree()->lookup(it.key());
  844. if(item && item->widget())
  845. {
  846. item->widget()->reparent(parent->widget(), TQPoint(0,0), true);
  847. item->eventEater()->setContainer(parent->container());
  848. if(m_pos[it.key()].isValid())
  849. item->widget()->setGeometry(m_pos[it.key()]);
  850. m_form->objectTree()->reparent(item->name(), m_containername);
  851. }
  852. }
  853. if(!parent->container())
  854. return;
  855. ObjectTreeItem* titem = m_form->objectTree()->lookup(m_name);
  856. if (!titem)
  857. return; //better this than a crash
  858. TQWidget *w = titem->widget();
  859. parent->container()->deleteWidget(w); // delete the layout widget
  860. FormManager::self()->windowChanged(m_form->widget()); // to reload ObjectTreeView
  861. }
  862. TQString
  863. CreateLayoutCommand::name() const
  864. {
  865. switch(m_type)
  866. {
  867. case Container::HBox:
  868. return i18n("Group Widgets Horizontally");
  869. case Container::VBox:
  870. return i18n("Group Widgets Vertically");
  871. case Container::Grid:
  872. return i18n("Group Widgets in a Grid");
  873. case Container::HSplitter:
  874. return i18n("Group Widgets Horizontally in a Splitter");
  875. case Container::VSplitter:
  876. return i18n("Group Widgets Vertically in a Splitter");
  877. case Container::HFlow:
  878. return i18n("Group Widgets By Rows");
  879. case Container::VFlow:
  880. return i18n("Group Widgets Vertically By Columns");
  881. default:
  882. return i18n("Group widgets");
  883. }
  884. }
  885. void
  886. CreateLayoutCommand::debug()
  887. {
  888. kdDebug() << "CreateLayoutCommand: name=\"" << name() << "\" generatedName=" << m_name
  889. << " widgets=" << m_pos.keys() << " container=" << m_containername
  890. << " form=" << m_form->widget()->name() << endl;
  891. }
  892. /// BreakLayoutCommand ///////////////
  893. BreakLayoutCommand::BreakLayoutCommand(Container *container)
  894. : CreateLayoutCommand()
  895. {
  896. m_containername = container->toplevel()->widget()->name();
  897. m_name = container->widget()->name();
  898. m_form = container->form();
  899. m_type = container->layoutType();
  900. for(ObjectTreeItem *tree = container->objectTree()->children()->first(); tree; tree = container->objectTree()->children()->next())
  901. {
  902. TQRect r(container->widget()->mapTo(container->widget()->parentWidget(), tree->widget()->pos()), tree->widget()->size());
  903. m_pos.insert(tree->widget()->name(), r);
  904. }
  905. }
  906. void
  907. BreakLayoutCommand::execute()
  908. {
  909. CreateLayoutCommand::unexecute();
  910. }
  911. void
  912. BreakLayoutCommand::unexecute()
  913. {
  914. CreateLayoutCommand::execute();
  915. }
  916. TQString
  917. BreakLayoutCommand::name() const
  918. {
  919. return i18n("Break Layout: \"%1\"").arg(m_name);
  920. }
  921. void
  922. BreakLayoutCommand::debug()
  923. {
  924. kdDebug() << "BreakLayoutCommand: name=\"" << name()
  925. << " widgets=" << m_pos.keys() << " container=" << m_containername
  926. << " form=" << m_form->widget()->name() << endl;
  927. }
  928. // PasteWidgetCommand
  929. PasteWidgetCommand::PasteWidgetCommand(TQDomDocument &domDoc, Container *container, const TQPoint& p)
  930. : m_point(p)
  931. {
  932. m_data = domDoc.toCString();
  933. m_containername = container->widget()->name();
  934. m_form = container->form();
  935. if(domDoc.namedItem("UI").firstChild().nextSibling().toElement().tagName() != "widget")
  936. return;
  937. TQRect boundingRect;
  938. for(TQDomNode n = domDoc.namedItem("UI").firstChild(); !n.isNull(); n = n.nextSibling()) // more than one widget
  939. {
  940. if(n.toElement().tagName() != "widget")
  941. continue;
  942. TQDomElement el = n.toElement();
  943. TQDomElement rect;
  944. for(TQDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling())
  945. {
  946. if((n.toElement().tagName() == "property") && (n.toElement().attribute("name") == "geometry"))
  947. rect = n.firstChild().toElement();
  948. }
  949. TQDomElement x = rect.namedItem("x").toElement();
  950. TQDomElement y = rect.namedItem("y").toElement();
  951. TQDomElement wi = rect.namedItem("width").toElement();
  952. TQDomElement h = rect.namedItem("height").toElement();
  953. int rx = x.text().toInt();
  954. int ry = y.text().toInt();
  955. int rw = wi.text().toInt();
  956. int rh = h.text().toInt();
  957. TQRect r(rx, ry, rw, rh);
  958. boundingRect = boundingRect.unite(r);
  959. }
  960. m_point = m_point - boundingRect.topLeft();
  961. }
  962. void
  963. PasteWidgetCommand::execute()
  964. {
  965. ObjectTreeItem* titem = m_form->objectTree()->lookup(m_containername);
  966. if (!titem)
  967. return; //better this than a crash
  968. Container *container = titem->container();
  969. TQString errMsg;
  970. int errLine;
  971. int errCol;
  972. TQDomDocument domDoc("UI");
  973. bool parsed = domDoc.setContent(m_data, false, &errMsg, &errLine, &errCol);
  974. if(!parsed)
  975. {
  976. kdDebug() << "WidgetWatcher::load(): " << errMsg << endl;
  977. kdDebug() << "WidgetWatcher::load(): line: " << errLine << " col: " << errCol << endl;
  978. return;
  979. }
  980. //FormIO::setCurrentForm(m_container->form());
  981. kdDebug() << domDoc.toString() << endl;
  982. if(!domDoc.namedItem("UI").hasChildNodes()) // nothing in the doc
  983. return;
  984. if(domDoc.namedItem("UI").firstChild().nextSibling().toElement().tagName() != "widget") // only one widget, so we can paste it at cursor pos
  985. {
  986. TQDomElement el = domDoc.namedItem("UI").firstChild().toElement();
  987. fixNames(el);
  988. if(m_point.isNull())
  989. fixPos(el, container);
  990. else
  991. changePos(el, m_point);
  992. m_form->setInteractiveMode(false);
  993. FormIO::loadWidget(container, el);
  994. m_form->setInteractiveMode(true);
  995. }
  996. else for(TQDomNode n = domDoc.namedItem("UI").firstChild(); !n.isNull(); n = n.nextSibling()) // more than one widget
  997. {
  998. if(n.toElement().tagName() != "widget")
  999. continue;
  1000. TQDomElement el = n.toElement();
  1001. fixNames(el);
  1002. if(!m_point.isNull())
  1003. moveWidgetBy(el, container, m_point);
  1004. else {
  1005. fixPos(el, container);
  1006. kdDebug() << "jdkjfldfksmfkdfjmqdsklfjdkkfmsqfksdfsm" << endl;
  1007. }
  1008. m_form->setInteractiveMode(false);
  1009. FormIO::loadWidget(container, el);
  1010. m_form->setInteractiveMode(true);
  1011. }
  1012. //FormIO::setCurrentForm(0);
  1013. m_names.clear();
  1014. // We store the names of all the created widgets, to delete them later
  1015. for(TQDomNode n = domDoc.namedItem("UI").firstChild(); !n.isNull(); n = n.nextSibling())
  1016. {
  1017. if(n.toElement().tagName() != "widget")
  1018. continue;
  1019. for(TQDomNode m = n.firstChild(); !m.isNull(); n = m.nextSibling())
  1020. {
  1021. if((m.toElement().tagName() == "property") && (m.toElement().attribute("name") == "name"))
  1022. {
  1023. m_names.append(m.toElement().text());
  1024. break;
  1025. }
  1026. }
  1027. }
  1028. container->form()->selectFormWidget();
  1029. TQStringList::ConstIterator endIt = m_names.constEnd();
  1030. for(TQStringList::ConstIterator it = m_names.constBegin(); it != endIt; ++it) // We select all the pasted widgets
  1031. {
  1032. ObjectTreeItem *item = m_form->objectTree()->lookup(*it);
  1033. if(item)
  1034. container->setSelectedWidget(item->widget(), true);
  1035. }
  1036. }
  1037. void
  1038. PasteWidgetCommand::unexecute()
  1039. {
  1040. ObjectTreeItem* titem = m_form->objectTree()->lookup(m_containername);
  1041. if (!titem)
  1042. return; //better this than a crash
  1043. Container *container = titem->container();
  1044. // We just delete all the widgets we have created
  1045. TQStringList::ConstIterator endIt = m_names.constEnd();
  1046. for(TQStringList::ConstIterator it = m_names.constBegin(); it != endIt; ++it)
  1047. {
  1048. ObjectTreeItem* titem = container->form()->objectTree()->lookup(*it);
  1049. if (!titem)
  1050. continue; //better this than a crash
  1051. TQWidget *w = titem->widget();
  1052. container->deleteWidget(w);
  1053. }
  1054. }
  1055. TQString
  1056. PasteWidgetCommand::name() const
  1057. {
  1058. return i18n("Paste");
  1059. }
  1060. void
  1061. //TQDomElement
  1062. PasteWidgetCommand::changePos(TQDomElement &el, const TQPoint &newpos)
  1063. {
  1064. //TQDomElement el = widg.cloneNode(true).toElement();
  1065. TQDomElement rect;
  1066. // Find the widget geometry if there is one
  1067. for(TQDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling())
  1068. {
  1069. if((n.toElement().tagName() == "property") && (n.toElement().attribute("name") == "geometry"))
  1070. rect = n.firstChild().toElement();
  1071. }
  1072. TQDomElement x = rect.namedItem("x").toElement();
  1073. x.removeChild(x.firstChild());
  1074. TQDomText valueX = el.ownerDocument().createTextNode(TQString::number(newpos.x()));
  1075. x.appendChild(valueX);
  1076. TQDomElement y = rect.namedItem("y").toElement();
  1077. y.removeChild(y.firstChild());
  1078. TQDomText valueY = el.ownerDocument().createTextNode(TQString::number(newpos.y()));
  1079. y.appendChild(valueY);
  1080. //return el;
  1081. }
  1082. void
  1083. PasteWidgetCommand::fixPos(TQDomElement &el, Container *container)
  1084. {
  1085. /* TQDomElement rect;
  1086. for(TQDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling())
  1087. {
  1088. if((n.toElement().tagName() == "property") && (n.toElement().attribute("name") == "geometry"))
  1089. rect = n.firstChild().toElement();
  1090. }
  1091. TQDomElement x = rect.namedItem("x").toElement();
  1092. TQDomElement y = rect.namedItem("y").toElement();
  1093. TQDomElement wi = rect.namedItem("width").toElement();
  1094. TQDomElement h = rect.namedItem("height").toElement();
  1095. int rx = x.text().toInt();
  1096. int ry = y.text().toInt();
  1097. int rw = wi.text().toInt();
  1098. int rh = h.text().toInt();
  1099. TQRect r(rx, ry, rw, rh);
  1100. TQWidget *w = m_form->widget()->childAt(r.x() + 6, r.y() + 6, false);
  1101. if(!w)
  1102. return;
  1103. while((w->geometry() == r) && (w != 0))// there is already a widget there, with the same size
  1104. {
  1105. w = m_form->widget()->childAt(w->x() + 16, w->y() + 16, false);
  1106. r.moveBy(10,10);
  1107. }
  1108. // the pasted wigdet should stay inside container's boundaries
  1109. if(r.x() < 0)
  1110. r.moveLeft(0);
  1111. else if(r.right() > container->widget()->width())
  1112. r.moveLeft(container->widget()->width() - r.width());
  1113. if(r.y() < 0)
  1114. r.moveTop(0);
  1115. else if(r.bottom() > container->widget()->height())
  1116. r.moveTop(container->widget()->height() - r.height());
  1117. if(r != TQRect(rx, ry, rw, rh))
  1118. //return el;
  1119. //else
  1120. changePos(el, TQPoint(r.x(), r.y()));
  1121. */
  1122. moveWidgetBy(el, container, TQPoint(0, 0));
  1123. }
  1124. void
  1125. PasteWidgetCommand::moveWidgetBy(TQDomElement &el, Container *container, const TQPoint &p)
  1126. {
  1127. TQDomElement rect;
  1128. for(TQDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling())
  1129. {
  1130. if((n.toElement().tagName() == "property") && (n.toElement().attribute("name") == "geometry"))
  1131. rect = n.firstChild().toElement();
  1132. }
  1133. TQDomElement x = rect.namedItem("x").toElement();
  1134. TQDomElement y = rect.namedItem("y").toElement();
  1135. TQDomElement wi = rect.namedItem("width").toElement();
  1136. TQDomElement h = rect.namedItem("height").toElement();
  1137. int rx = x.text().toInt();
  1138. int ry = y.text().toInt();
  1139. int rw = wi.text().toInt();
  1140. int rh = h.text().toInt();
  1141. TQRect r(rx + p.x(), ry + p.y(), rw, rh);
  1142. kdDebug() << "Moving widget by " << p << " from " << rx << " " << ry << " to " << r.topLeft() << endl;
  1143. TQWidget *w = m_form->widget()->childAt(r.x() + 6, r.y() + 6, false);
  1144. while(w && (w->geometry() == r))// there is already a widget there, with the same size
  1145. {
  1146. w = m_form->widget()->childAt(w->x() + 16, w->y() + 16, false);
  1147. r.moveBy(10,10);
  1148. }
  1149. // the pasted wigdet should stay inside container's boundaries
  1150. if(r.x() < 0)
  1151. r.moveLeft(0);
  1152. else if(r.right() > container->widget()->width())
  1153. r.moveLeft(container->widget()->width() - r.width());
  1154. if(r.y() < 0)
  1155. r.moveTop(0);
  1156. else if(r.bottom() > container->widget()->height())
  1157. r.moveTop(container->widget()->height() - r.height());
  1158. if(r != TQRect(rx, ry, rw, rh))
  1159. //return el;
  1160. //else
  1161. changePos(el, TQPoint(r.x(), r.y()));
  1162. }
  1163. void
  1164. PasteWidgetCommand::fixNames(TQDomElement &el)
  1165. {
  1166. TQString wname;
  1167. for(TQDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling())
  1168. {
  1169. if((n.toElement().tagName() == "property") && (n.toElement().attribute("name") == "name"))
  1170. {
  1171. wname = n.toElement().text();
  1172. while(m_form->objectTree()->lookup(wname)) // name already exists
  1173. {
  1174. bool ok;
  1175. int num = wname.right(1).toInt(&ok, 10);
  1176. if(ok)
  1177. wname = wname.left(wname.length()-1) + TQString::number(num+1);
  1178. else
  1179. wname += "2";
  1180. }
  1181. if(wname != n.toElement().text()) // we change the name, so we recreate the element
  1182. {
  1183. n.removeChild(n.firstChild());
  1184. TQDomElement type = el.ownerDocument().createElement("string");
  1185. TQDomText valueE = el.ownerDocument().createTextNode(wname);
  1186. type.appendChild(valueE);
  1187. n.toElement().appendChild(type);
  1188. }
  1189. }
  1190. if(n.toElement().tagName() == "widget") // fix child widgets names
  1191. {
  1192. TQDomElement child = n.toElement();
  1193. fixNames(child);
  1194. }
  1195. }
  1196. }
  1197. void
  1198. PasteWidgetCommand::debug()
  1199. {
  1200. kdDebug() << "PasteWidgetCommand: pos=" << m_point
  1201. << " widgets=" << m_names << " container=" << m_containername
  1202. << " form=" << m_form->widget()->name()
  1203. << " data=\"" << m_data.left(80) << "...\"" << endl;
  1204. }
  1205. // DeleteWidgetCommand
  1206. DeleteWidgetCommand::DeleteWidgetCommand(WidgetList &list, Form *form)
  1207. : Command(), m_form(form)
  1208. {
  1209. m_domDoc = TQDomDocument("UI");
  1210. m_domDoc.appendChild(m_domDoc.createElement("UI"));
  1211. TQDomElement parent = m_domDoc.namedItem("UI").toElement();
  1212. //for(TQWidget *w = list.first(); w; w = list.next())
  1213. /*for(WidgetListIterator it(list); it.current() != 0; ++it)
  1214. {
  1215. TQWidget *w = it.current();
  1216. // Don't delete tabwidget or widgetstack pages
  1217. if(w->parentWidget()->inherits(TQWIDGETSTACK_OBJECT_NAME_STRING))
  1218. {
  1219. list.remove(w);
  1220. continue;
  1221. }
  1222. }*/
  1223. removeChildrenFromList(list);
  1224. for(WidgetListIterator it(list); it.current() != 0; ++it)
  1225. {
  1226. ObjectTreeItem *item = m_form->objectTree()->lookup(it.current()->name());
  1227. if (!item)
  1228. return;
  1229. // We need to store both parentContainer and parentWidget as they may be different (eg for TabWidget page)
  1230. m_containers.insert(item->name().latin1(), m_form->parentContainer(item->widget())->widget()->name());
  1231. m_parents.insert(item->name().latin1(), item->parent()->name().latin1());
  1232. FormIO::saveWidget(item, parent, m_domDoc);
  1233. form->connectionBuffer()->saveAllConnectionsForWidget(item->widget()->name(), m_domDoc);
  1234. }
  1235. FormIO::cleanClipboard(parent);
  1236. }
  1237. void
  1238. DeleteWidgetCommand::execute()
  1239. {
  1240. Container *containerToSelect = 0;
  1241. TQMap<TQCString,TQCString>::ConstIterator endIt = m_containers.constEnd();
  1242. for(TQMap<TQCString,TQCString>::ConstIterator it = m_containers.constBegin(); it != endIt; ++it)
  1243. {
  1244. ObjectTreeItem *item = m_form->objectTree()->lookup(it.key());
  1245. if (!item || !item->widget())
  1246. continue;
  1247. Container *cont = m_form->parentContainer(item->widget());
  1248. if (!containerToSelect)
  1249. containerToSelect = cont;
  1250. cont->deleteWidget(item->widget());
  1251. }
  1252. //now we've nothing selecte: select parent container
  1253. if (containerToSelect)
  1254. m_form->setSelectedWidget( containerToSelect->widget() );
  1255. }
  1256. void
  1257. DeleteWidgetCommand::unexecute()
  1258. {
  1259. TQCString wname;
  1260. m_form->setInteractiveMode(false);
  1261. for(TQDomNode n = m_domDoc.namedItem("UI").firstChild(); !n.isNull(); n = n.nextSibling())
  1262. {
  1263. if(n.toElement().tagName() == "connections") // restore the widget connections
  1264. m_form->connectionBuffer()->load(n);
  1265. if(n.toElement().tagName() != "widget")
  1266. continue;
  1267. // We need first to know the name of the widget
  1268. for(TQDomNode m = n.firstChild(); !m.isNull(); n = m.nextSibling())
  1269. {
  1270. if((m.toElement().tagName() == "property") && (m.toElement().attribute("name") == "name"))
  1271. {
  1272. wname = m.toElement().text().latin1();
  1273. break;
  1274. }
  1275. }
  1276. ObjectTreeItem* titem = m_form->objectTree()->lookup(m_containers[wname]);
  1277. if (!titem)
  1278. return; //better this than a crash
  1279. Container *cont = titem->container();
  1280. ObjectTreeItem *parent = m_form->objectTree()->lookup(m_parents[wname]);
  1281. TQDomElement widg = n.toElement();
  1282. if(parent)
  1283. FormIO::loadWidget(cont, widg, parent->widget());
  1284. else
  1285. FormIO::loadWidget(cont, widg);
  1286. }
  1287. m_form->setInteractiveMode(true);
  1288. }
  1289. TQString
  1290. DeleteWidgetCommand::name() const
  1291. {
  1292. return i18n("Delete widget");
  1293. }
  1294. void
  1295. DeleteWidgetCommand::debug()
  1296. {
  1297. kdDebug() << "DeleteWidgetCommand: containers=" << m_containers.keys()
  1298. << " parents=" << m_parents.keys() << " form=" << m_form->widget()->name() << endl;
  1299. }
  1300. // CutWidgetCommand
  1301. CutWidgetCommand::CutWidgetCommand(WidgetList &list, Form *form)
  1302. : DeleteWidgetCommand(list, form)
  1303. {}
  1304. void
  1305. CutWidgetCommand::execute()
  1306. {
  1307. DeleteWidgetCommand::execute();
  1308. m_data = FormManager::self()->m_domDoc.toCString();
  1309. FormManager::self()->m_domDoc.setContent(m_domDoc.toCString());
  1310. }
  1311. void
  1312. CutWidgetCommand::unexecute()
  1313. {
  1314. DeleteWidgetCommand::unexecute();
  1315. FormManager::self()->m_domDoc.setContent(m_data);
  1316. }
  1317. TQString
  1318. CutWidgetCommand::name() const
  1319. {
  1320. return i18n("Cut");
  1321. }
  1322. void
  1323. CutWidgetCommand::debug()
  1324. {
  1325. kdDebug() << "CutWidgetCommand: containers=" << m_containers.keys()
  1326. << " parents=" << m_parents.keys() << " form=" << m_form->widget()->name()
  1327. << " data=\"" << m_data.left(80) << "...\"" << endl;
  1328. }
  1329. // CommandGroup
  1330. namespace KFormDesigner {
  1331. class CommandGroup::SubCommands : public KMacroCommand
  1332. {
  1333. public:
  1334. SubCommands( const TQString & name )
  1335. : KMacroCommand(name)
  1336. {
  1337. }
  1338. const TQPtrList<KCommand>& commands() const { return m_commands; }
  1339. };
  1340. }
  1341. CommandGroup::CommandGroup( const TQString & name, WidgetPropertySet *propSet )
  1342. : Command()
  1343. , m_subCommands(new SubCommands(name))
  1344. , m_propSet(propSet)
  1345. {
  1346. }
  1347. CommandGroup::~CommandGroup()
  1348. {
  1349. delete m_subCommands;
  1350. }
  1351. const TQPtrList<KCommand>& CommandGroup::commands() const
  1352. {
  1353. return m_subCommands->commands();
  1354. }
  1355. void CommandGroup::addCommand(KCommand *command, bool allowExecute)
  1356. {
  1357. if (!command)
  1358. return;
  1359. m_subCommands->addCommand(command);
  1360. if (!allowExecute)
  1361. m_commandsShouldntBeExecuted.insert(command, (char*)1);
  1362. }
  1363. void CommandGroup::execute()
  1364. {
  1365. FormManager::self()->blockPropertyEditorUpdating(this);
  1366. for (TQPtrListIterator<KCommand> it(m_subCommands->commands()); it.current(); ++it) {
  1367. if (!m_commandsShouldntBeExecuted[it.current()])
  1368. it.current()->execute();
  1369. }
  1370. FormManager::self()->unblockPropertyEditorUpdating(this, m_propSet);
  1371. }
  1372. void CommandGroup::unexecute()
  1373. {
  1374. FormManager::self()->blockPropertyEditorUpdating(this);
  1375. m_subCommands->unexecute();
  1376. FormManager::self()->unblockPropertyEditorUpdating(this, m_propSet);
  1377. }
  1378. TQString CommandGroup::name() const
  1379. {
  1380. return m_subCommands->name();
  1381. }
  1382. void CommandGroup::resetAllowExecuteFlags()
  1383. {
  1384. m_commandsShouldntBeExecuted.clear();
  1385. }
  1386. void
  1387. CommandGroup::debug()
  1388. {
  1389. kdDebug() << "*CommandGroup: name=\"" << name() << "\" #=" << m_subCommands->commands().count() << endl;
  1390. uint i = 1;
  1391. for (TQPtrListIterator<KCommand> it(m_subCommands->commands()); it.current(); ++it, i++) {
  1392. kdDebug() << "#" << i << ":"
  1393. << (m_commandsShouldntBeExecuted[it.current()] ? "!" : "") << "allowExecute:" << endl;
  1394. if (dynamic_cast<Command*>(it.current()))
  1395. dynamic_cast<Command*>(it.current())->debug();
  1396. else if (dynamic_cast<CommandGroup*>(it.current()))
  1397. dynamic_cast<CommandGroup*>(it.current())->debug();
  1398. else
  1399. kdDebug() << "(other KCommand)" << endl;
  1400. }
  1401. kdDebug() << "End of CommandGroup" << endl;
  1402. }