editor.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
3 Copyright (C) 2004 Alexander Dymo <cloudtemple@mskat.net>
4 Copyright (C) 2004-2006 Jaroslaw Staniek <js@iidea.pl>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20*/
21
22#include "editor.h"
23#include "editoritem.h"
24#include "set.h"
25#include "factory.h"
26#include "property.h"
27#include "widget.h"
28
29#include <tqpushbutton.h>
30#include <tqlayout.h>
31#include <tqmap.h>
32#include <tqguardedptr.h>
33#include <tqheader.h>
34#include <tqasciidict.h>
35#include <tqtooltip.h>
36#include <tqapplication.h>
37#include <tqeventloop.h>
38#include <tqtimer.h>
39#include <tqlabel.h>
40
41#include <kdebug.h>
42#include <kiconloader.h>
43#include <tdelocale.h>
44#include <tdeversion.h>
45#include <tdeapplication.h>
46
47namespace KoProperty {
48
50static bool kofficeAppDirAdded = false;
51
54inline bool hasParent(TQObject* par, TQObject* o)
55{
56 if (!o || !par)
57 return false;
58 while (o && o != par)
59 o = o->parent();
60 return o == par;
61}
62
63class EditorPrivate
64{
65 public:
66 EditorPrivate(Editor *editor)
67 : itemDict(101, false), justClickedItem(false)
68 {
69 currentItem = 0;
70 undoButton = 0;
71 topItem = 0;
72 itemToSelectLater = 0;
73 if (!kofficeAppDirAdded) {
74 kofficeAppDirAdded = true;
75 TDEGlobal::iconLoader()->addAppDir("koffice");
76 }
77 previouslyCollapsedGroupItem = 0;
78 childFormPreviouslyCollapsedGroupItem = 0;
79 slotPropertyChanged_enabled = true;
80 TQObject::connect(&changeSetLaterTimer, TQ_SIGNAL(timeout()),
81 editor, TQ_SLOT(changeSetLater()));
82 }
83 ~EditorPrivate()
84 {
85 }
86
87 TQGuardedPtr<Set> set;
89 TQMap<Property*, Widget* > widgetCache;
90 TQGuardedPtr<Widget> currentWidget;
91 EditorItem *currentItem;
92 EditorItem *topItem;
93 TQPushButton *undoButton;
94 EditorItem::Dict itemDict;
95
96 int baseRowHeight;
97 bool sync : 1;
98 bool insideSlotValueChanged : 1;
99
101 TQTimer changeSetLaterTimer;
102 bool setListLater_set : 1;
103 bool preservePrevSelection_preservePrevSelection : 1;
104 TQCString preservePrevSelection_propertyToSelect;
105 //bool doNotSetFocusOnSelection : 1;
107 bool justClickedItem : 1;
109 bool slotPropertyChanged_enabled : 1;
111 Set* setListLater_list;
113 EditorItem *itemToSelectLater;
114
115 TQListViewItem *previouslyCollapsedGroupItem;
116 TQListViewItem *childFormPreviouslyCollapsedGroupItem;
117};
118}
119
120using namespace KoProperty;
121
122Editor::Editor(TQWidget *parent, bool autoSync, const char *name)
123 : TDEListView(parent, name)
124{
125 d = new EditorPrivate(this);
126 d->itemDict.setAutoDelete(false);
127
128 d->set = 0;
129 d->topItem = 0;
130 d->currentItem = 0;
131 d->sync = autoSync;
132 d->insideSlotValueChanged = false;
133 d->setListLater_set = false;
134 d->preservePrevSelection_preservePrevSelection = false;
135 d->setListLater_list = 0;
136
137 d->undoButton = new TQPushButton(viewport());
138 d->undoButton->setFocusPolicy(TQWidget::NoFocus);
139 setFocusPolicy(TQWidget::ClickFocus);
140 d->undoButton->setMinimumSize(TQSize(5,5)); // allow to resize undoButton even below pixmap size
141 d->undoButton->setPixmap(SmallIcon("edit-undo"));
142 TQToolTip::add(d->undoButton, i18n("Undo changes"));
143 d->undoButton->hide();
144 connect(d->undoButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(undo()));
145
146 installEventFilter(this);
147 viewport()->installEventFilter(this);
148
149 addColumn(i18n("Name"));
150 addColumn(i18n("Value"));
151 setAllColumnsShowFocus(true);
152 setColumnWidthMode(0, TQListView::Maximum);
153 setFullWidth(true);
154 setShowSortIndicator(false);
155#if KDE_IS_VERSION(3,3,9)
156 setShadeSortColumn(false);
157#endif
159 setSorting(0);
160 setItemMargin(KPROPEDITOR_ITEM_MARGIN);
161 header()->setMovingEnabled( false );
162 setTreeStepSize(16 + 2/*left*/ + 1/*right*/);
163
164 updateFont();
165// d->baseRowHeight = TQFontMetrics(font()).height() + itemMargin()*2;
166
167 connect(this, TQ_SIGNAL(selectionChanged(TQListViewItem *)), this, TQ_SLOT(slotClicked(TQListViewItem *)));
168 connect(this, TQ_SIGNAL(currentChanged(TQListViewItem *)), this, TQ_SLOT(slotCurrentChanged(TQListViewItem *)));
169 connect(this, TQ_SIGNAL(expanded(TQListViewItem *)), this, TQ_SLOT(slotExpanded(TQListViewItem *)));
170 connect(this, TQ_SIGNAL(collapsed(TQListViewItem *)), this, TQ_SLOT(slotCollapsed(TQListViewItem *)));
171 connect(header(), TQ_SIGNAL(sizeChange(int, int, int)), this, TQ_SLOT(slotColumnSizeChanged(int, int, int)));
172// connect(header(), TQ_SIGNAL(clicked(int)), this, TQ_SLOT(updateEditorGeometry()));
173// connect(header(), TQ_SIGNAL(clicked(int)), this, TQ_SLOT(updateEditorGeometryAndGroupLabels()));
174 connect(header(), TQ_SIGNAL(sectionHandleDoubleClicked (int)), this, TQ_SLOT(slotColumnSizeChanged(int)));
175 updateGroupLabelsPosition();
176}
177
178Editor::~Editor()
179{
181 delete d;
182 d = 0;
183}
184
185void
186Editor::fill()
187{
188 setUpdatesEnabled(false);
189 d->itemToSelectLater = 0;
190 tqApp->eventLoop()->processEvents(TQEventLoop::AllEvents);
191 hideEditor();
192 TDEListView::clear();
193 d->itemDict.clear();
195 if(!d->set) {
196 d->topItem = 0;
197 setUpdatesEnabled(true);
198 triggerUpdate();
199 return;
200 }
201
202 d->topItem = new EditorDummyItem(this);
203
204 const TQValueList<TQCString> groupNames = d->set->groupNames();
205// kopropertydbg << "Editor::fill(): group names = " << groupNames.count() << endl;
206 if(groupNames.count() == 1) { // one group (default one), so don't show groups
207 //add flat set of properties
208 const TQValueList<TQCString>& propertyNames = d->set->propertyNamesForGroup( groupNames.first() );
209 TQValueListConstIterator<TQCString> it = propertyNames.constBegin();
210 for( ; it != propertyNames.constEnd(); ++it)
211 addItem(*it, d->topItem);
212 }
213 else { // create a groupItem for each group
214 EditorGroupItem *prevGroupItem = 0;
215 int sortOrder = 0;
216 for (TQValueListConstIterator<TQCString> it = groupNames.constBegin(); it!=groupNames.constEnd();
217 ++it, sortOrder++)
218 {
219 const TQValueList<TQCString>& propertyNames = d->set->propertyNamesForGroup(*it);
220 EditorGroupItem *groupItem;
221 if (prevGroupItem)
222 groupItem = new EditorGroupItem(d->topItem, prevGroupItem,
223 d->set->groupDescription(*it), d->set->groupIcon(*it), sortOrder );
224 else
225 groupItem = new EditorGroupItem(d->topItem,
226 d->set->groupDescription(*it), d->set->groupIcon(*it), sortOrder );
227
228 TQValueList<TQCString>::ConstIterator it2 = propertyNames.constBegin();
229 for( ; it2 != propertyNames.constEnd(); ++it2)
230 addItem(*it2, groupItem);
231
232 prevGroupItem = groupItem;
233 }
234 }
235
236// repaint();
237
238 if (firstChild())
239 {
240 setCurrentItem(firstChild());
241 setSelected(firstChild(), true);
242 slotClicked(firstChild());
243 updateGroupLabelsPosition();
244 }
245 setUpdatesEnabled(true);
246 // aaah, call this instead of update()
247 triggerUpdate();
248}
249
250void
251Editor::addItem(const TQCString &name, EditorItem *parent)
252{
253 if(!d->set || !d->set->contains(name))
254 return;
255
256 Property *property = &(d->set->property(name));
257 if(!property || !property->isVisible()) {
258// kopropertydbg << "Property is not visible: " << name << endl;
259 return;
260 }
261 TQListViewItem *last = parent ? parent->firstChild() : d->topItem->firstChild();
262 while(last && last->nextSibling())
263 last = last->nextSibling();
264
265 EditorItem *item=0;
266 if(parent)
267 item = new EditorItem(this, parent, property, last);
268 else
269 item = new EditorItem(this, d->topItem, property, last);
270 d->itemDict.insert(name, item);
271
272 // Create child items
273 item->setOpen(true);
274 if(!property->children())
275 return;
276
277 last = 0;
278 TQValueList<Property*>::ConstIterator endIt = property->children()->constEnd();
279 for(TQValueList<Property*>::ConstIterator it = property->children()->constBegin(); it != endIt; ++it) {
281 if( *it && (*it)->isVisible() )
282 last = new EditorItem(this, item, *it, last);
283 }
284}
285
286void
287Editor::changeSet(Set *set, bool preservePrevSelection)
288{
289 changeSetInternal(set, preservePrevSelection, "");
290}
291
292void
293Editor::changeSet(Set *set, const TQCString& propertyToSelect)
294{
295 changeSetInternal(set, !propertyToSelect.isEmpty(), propertyToSelect);
296}
297
298void
299Editor::changeSetInternal(Set *set, bool preservePrevSelection, const TQCString& propertyToSelect)
300{
301 if (d->insideSlotValueChanged) {
302 //changeSet() called from inside of slotValueChanged()
303 //this is dangerous, because there can be pending events,
304 //especially for the GUI stuff, so let's do delayed work
305 d->setListLater_list = set;
306 d->preservePrevSelection_preservePrevSelection = preservePrevSelection;
307 d->preservePrevSelection_propertyToSelect = propertyToSelect;
308 tqApp->eventLoop()->processEvents(TQEventLoop::AllEvents);
309 if (d->set) {
310 //store prev. selection for this prop set
311 if (d->currentItem)
312 d->set->setPrevSelection( d->currentItem->property()->name() );
313 kdDebug() << d->set->prevSelection() << endl;
314 }
315 if (!d->setListLater_set) {
316 d->setListLater_set = true;
317 d->changeSetLaterTimer.start(10, true);
318 }
319 return;
320 }
321
322 if (d->set) {
323 slotWidgetAcceptInput(d->currentWidget);
324 //store prev. selection for this prop set
325 if (d->currentItem)
326 d->set->setPrevSelection( d->currentItem->property()->name() );
327 else
328 d->set->setPrevSelection( "" );
329 d->set->disconnect(this);
330 }
331
332 TQCString selectedPropertyName1 = propertyToSelect, selectedPropertyName2 = propertyToSelect;
333 if (preservePrevSelection) {
334 //try to find prev. selection:
335 //1. in new list's prev. selection
336 if(set)
337 selectedPropertyName1 = set->prevSelection();
338 //2. in prev. list's current selection
339 if(d->set)
340 selectedPropertyName2 = d->set->prevSelection();
341 }
342
343 d->set = set;
344 if (d->set) {
345 //receive property changes
346 connect(d->set, TQ_SIGNAL(propertyChangedInternal(KoProperty::Set&, KoProperty::Property&)),
348 connect(d->set, TQ_SIGNAL(propertyReset(KoProperty::Set&, KoProperty::Property&)),
349 this, TQ_SLOT(slotPropertyReset(KoProperty::Set&, KoProperty::Property&)));
350 connect(d->set,TQ_SIGNAL(aboutToBeCleared()), this, TQ_SLOT(slotSetWillBeCleared()));
351 connect(d->set,TQ_SIGNAL(aboutToBeDeleted()), this, TQ_SLOT(slotSetWillBeDeleted()));
352 }
353
354 fill();
355
356 emit propertySetChanged(d->set);
357
358 if (d->set) {
359 //select prev. selected item
360 EditorItem * item = 0;
361 if (!selectedPropertyName2.isEmpty()) //try other one for old prop set
362 item = d->itemDict[selectedPropertyName2];
363 if (!item && !selectedPropertyName1.isEmpty()) //try old one for current prop set
364 item = d->itemDict[selectedPropertyName1];
365
366 if (item) {
367 d->itemToSelectLater = item;
368 TQTimer::singleShot(10, this, TQ_SLOT(selectItemLater()));
369 //d->doNotSetFocusOnSelection = !hasParent(this, focusWidget());
370 //setSelected(item, true);
371 //d->doNotSetFocusOnSelection = false;
372// ensureItemVisible(item);
373 }
374 }
375}
376
378void Editor::selectItemLater()
379{
380 if (!d->itemToSelectLater)
381 return;
382 EditorItem *item = d->itemToSelectLater;
383 d->itemToSelectLater = 0;
384 setSelected(item, true);
385 ensureItemVisible(item);
386}
387
389void
390Editor::changeSetLater()
391{
392 tqApp->eventLoop()->processEvents(TQEventLoop::AllEvents);
393 if (kapp->hasPendingEvents()) {
394 d->changeSetLaterTimer.start(10, true); //try again...
395 return;
396 }
397 d->setListLater_set = false;
398 if (!d->setListLater_list)
399 return;
400
401 bool b = d->insideSlotValueChanged;
402 d->insideSlotValueChanged = false;
403 changeSetInternal(d->setListLater_list, d->preservePrevSelection_preservePrevSelection,
404 d->preservePrevSelection_propertyToSelect);
405 d->insideSlotValueChanged = b;
406}
407
408void
409Editor::clear(bool editorOnly)
410{
411 d->itemToSelectLater = 0;
412 hideEditor();
413
414 if(!editorOnly) {
415 tqApp->eventLoop()->processEvents(TQEventLoop::AllEvents);
416 if(d->set)
417 d->set->disconnect(this);
419 TDEListView::clear();
420 d->itemDict.clear();
421 d->topItem = 0;
422 }
423}
424
425void
427{
428 if(!d->currentWidget || !d->currentItem || (d->set && d->set->isReadOnly()) || (d->currentWidget && d->currentWidget->isReadOnly()))
429 return;
430
431 int propertySync = d->currentWidget->property()->autoSync();
432 bool sync = (propertySync != 0 && propertySync != 1) ?
433 d->sync : (propertySync!=0);
434
435 if(sync)
436 d->currentItem->property()->resetValue();
437 if (d->currentWidget && d->currentItem) {//(check because current widget could be removed by resetValue())
438 d->currentWidget->setValue( d->currentItem->property()->value());
439 repaintItem(d->currentItem);
440 }
441}
442
443void
445{
446 if (!d->slotPropertyChanged_enabled)
447 return;
448 if(&set != d->set)
449 return;
450
451 if (d->currentItem && d->currentItem->property() == &property) {
452 d->currentWidget->setValue(property.value(), false);
453 for(TQListViewItem *item = d->currentItem->firstChild(); item; item = item->nextSibling())
454 repaintItem(item);
455 }
456 else {
457 // prop not in the dict, might be a child property:
458 EditorItem *item = d->itemDict[property.name()];
459 if(!item && property.parent())
460 item = d->itemDict[property.parent()->name()];
461 if (item) {
462 repaintItem(item);
463 for(TQListViewItem *it = item->firstChild(); it; it = it->nextSibling())
464 repaintItem(it);
465 }
466 }
467
469#if 0
470 if (property.parent() && property.parent()->type()==Rect) {
471 const int delta = property.value().toInt()-previousValue.toInt();
472 if (property.type()==Rect_X) { //|| property.type()==Rect_Y)
473 property.parent()->child("width")->setValue(delta, false);
474 }
475
476/* if (widget->property() && (TQWidget*)d->currentWidget==widget && d->currentItem->parent()) {
477 EditorItem *parentItem = static_cast<EditorItem*>(d->currentItem->parent());
478 const int thisType = ;
479 && parentItem->property()->type()==Rect) {
480 //changing x or y components of Rect type shouldn't change width or height, respectively
481 if (thisType==Rect_X) {
482 EditorItem *rectWidthItem = static_cast<EditorItem*>(d->currentItem->nextSibling()->nextSibling());
483 if (delta!=0) {
484 rectWidthItem->property()->setValue(rectWidthItem->property()->value().toInt()+delta, false);
485 }
486 }
487 }*/
488 }
489#endif
490 showUndoButton( property.isModified() );
491}
492
493void
494Editor::slotPropertyReset(Set& set, Property& property)
495{
496 if(&set != d->set)
497 return;
498
499 if (d->currentItem && d->currentItem->property() == &property) {
500 d->currentWidget->setValue(property.value(), false);
501 for(TQListViewItem *item = d->currentItem->firstChild(); item; item = item->nextSibling())
502 repaintItem(item);
503 }
504 else {
505 EditorItem *item = d->itemDict[property.name()];
506 // prop not in the dict, might be a child prop.
507 if(!item && property.parent())
508 item = d->itemDict[property.parent()->name()];
509 if (item) {
510 repaintItem(item);
511 for(TQListViewItem *it = item->firstChild(); it; it = it->nextSibling())
512 repaintItem(it);
513 }
514 }
515
516 showUndoButton( false );
517}
518
519void
521{
522 if(!widget || !d->set || (d->set && d->set->isReadOnly()) || (widget && widget->isReadOnly()) || !widget->property())
523 return;
524
525 d->insideSlotValueChanged = true;
526
527 TQVariant value = widget->value();
528 int propertySync = widget->property()->autoSync();
529 bool sync = (propertySync != 0 && propertySync != 1) ?
530 d->sync : (propertySync!=0);
531
532 if(sync) {
533 d->slotPropertyChanged_enabled = false;
534 TQGuardedPtr<Widget> pWidget = widget; //safe, widget can be destroyed in the meantime
535 widget->property()->setValue(value);
536 if (pWidget)
537 showUndoButton( pWidget->property()->isModified() );
538 d->slotPropertyChanged_enabled = true;
539 }
540
541 d->insideSlotValueChanged = false;
542}
543
544void
546{
547 slotWidgetAcceptInput(d->currentWidget);
548}
549
550void
552{
553 if(!widget || !d->set || !widget->property() || (d->set && d->set->isReadOnly()) || (widget && widget->isReadOnly()))
554 return;
555
556 widget->property()->setValue(widget->value());
557}
558
559void
561{
562 if(!widget || !d->set)
563 return;
564
565 undo();
566}
567
568void
569Editor::slotClicked(TQListViewItem *it)
570{
571 d->previouslyCollapsedGroupItem = 0;
572 d->childFormPreviouslyCollapsedGroupItem = 0;
573
574 acceptInput();
575
576 hideEditor();
577 if(!it)
578 return;
579
580 EditorItem *item = static_cast<EditorItem*>(it);
581 Property *p = item ? item->property() : 0;
582 if(!p)
583 return;
584
585 d->currentItem = item;
586 d->currentWidget = createWidgetForProperty(p);
587
588 //moved up updateEditorGeometry();
589 showUndoButton( p->isModified() );
590 if (d->currentWidget) {
591 if (d->currentWidget->visibleFlag()) {
592 d->currentWidget->show();
593 if (hasParent( this, kapp->focusWidget() ))
594 d->currentWidget->setFocus();
595 }
596 }
597
598 d->justClickedItem = true;
599}
600
601void
602Editor::slotCurrentChanged(TQListViewItem *item)
603{
604 if (item == firstChild()) {
605 TQListViewItem *oldItem = item;
606 while (item && (!item->isSelectable() || !item->isVisible()))
607 item = item->itemBelow();
608 if (item && item != oldItem) {
609 setSelected(item,true);
610 return;
611 }
612 }
613}
614
615void
617{
618 d->itemToSelectLater = 0;
619 if (d->currentWidget) {
620 acceptInput();
621 d->currentWidget->setProperty(0);
622 }
623 clear();
624}
625
626void
628{
629 clear();
630 d->set = 0;
631}
632
633Widget*
634Editor::createWidgetForProperty(Property *property, bool changeWidgetProperty)
635{
636// int type = property->type();
637 TQGuardedPtr<Widget> widget = d->widgetCache[property];
638
639 if(!widget) {
640 widget = FactoryManager::self()->createWidgetForProperty(property);
641 if (!widget)
642 return 0;
643 widget->setReadOnly( (d->set && d->set->isReadOnly()) || property->isReadOnly() );
644 d->widgetCache[property] = widget;
645 widget->setProperty(0); // to force reloading property later
646 widget->hide();
647 connect(widget, TQ_SIGNAL(valueChanged(Widget*)),
648 this, TQ_SLOT(slotWidgetValueChanged(Widget*)) );
649 connect(widget, TQ_SIGNAL(acceptInput(Widget*)),
650 this, TQ_SLOT(slotWidgetAcceptInput(Widget*)) );
651 connect(widget, TQ_SIGNAL(rejectInput(Widget*)),
652 this, TQ_SLOT(slotWidgetRejectInput(Widget*)) );
653 }
654
655 //update geometry earlier, because Widget::setValue() can depend on widget's geometry
656 updateEditorGeometry(d->currentItem, widget);
657
658 if(widget && (!widget->property() || changeWidgetProperty))
659 widget->setProperty(property);
660
661// if (!d->doNotSetFocusOnSelection) {
662// widget->setFocus();
663// }
664
665 return widget;
666}
667
668
669void
671{
672 for(TQMap<Property*, Widget*>::iterator it = d->widgetCache.begin(); it != d->widgetCache.end(); ++it)
673 it.data()->deleteLater();
674// delete it.data();
675 d->widgetCache.clear();
676}
677
678void
679Editor::updateEditorGeometry(bool forceUndoButtonSettings, bool undoButtonVisible)
680{
681 updateEditorGeometry(d->currentItem, d->currentWidget,
682 forceUndoButtonSettings, undoButtonVisible);
683}
684
685void
686Editor::updateEditorGeometry(EditorItem *item, Widget* widget,
687 bool forceUndoButtonSettings, bool undoButtonVisible)
688{
689 if(!item || !widget)
690 return;
691
692 int placeForUndoButton;
693 if (forceUndoButtonSettings ? undoButtonVisible : d->undoButton->isVisible())
694 placeForUndoButton = d->undoButton->width();
695 else
696 placeForUndoButton = widget->leavesTheSpaceForRevertButton() ? d->undoButton->width() : 0;
697
698 TQRect r;
699 int y = itemPos(item);
700 r.setX(header()->sectionPos(1)-(widget->hasBorders()?1:0)); //-1, to align to horizontal line
701 r.setY(y-(widget->hasBorders()?1:0));
702 r.setWidth(header()->sectionSize(1)+(widget->hasBorders()?1:0) //+1 because we subtracted 1 from X
703 - placeForUndoButton);
704 r.setHeight(item->height()+(widget->hasBorders()?1:-1));
705
706 // check if the column is fully visible
707 if (visibleWidth() < r.right())
708 r.setRight(visibleWidth());
709
710 moveChild(widget, r.x(), r.y());
711 widget->resize(r.size());
712 tqApp->eventLoop()->processEvents(TQEventLoop::AllEvents);
713}
714
715void
716Editor::updateGroupLabelsPosition()
717{
718 if(!d->topItem || d->itemDict.isEmpty())
719 return;
720
721 EditorGroupItem *group = dynamic_cast<EditorGroupItem*>(d->topItem->firstChild());
722 while(group) {
723 TQRect r = itemRect((TQListViewItem*) group);
724 if(group->label()) {
725 group->label()->setGeometry(r);
726 group->label()->repaint();
727 }
728 group = dynamic_cast<EditorGroupItem*>(group->nextSibling());
729 }
730}
731
732void
733Editor::hideEditor()
734{
735 d->currentItem = 0;
736 TQWidget *cw = d->currentWidget;
737 if(cw) {
738 d->currentWidget = 0;
739 cw->hide();
740 }
741 d->undoButton->hide();
742}
743
744void
745Editor::showUndoButton( bool show )
746{
747 if (!d->currentItem || !d->currentWidget || (d->currentWidget && d->currentWidget->isReadOnly()))
748 return;
749
750 int y = viewportToContents(TQPoint(0, itemRect(d->currentItem).y())).y();
751 TQRect geometry(columnWidth(0), y, columnWidth(1) + 1, d->currentItem->height());
752 d->undoButton->resize(d->baseRowHeight, d->currentItem->height());
753
754 updateEditorGeometry(true, show);
755
756 if (!show) {
757/* if (d->currentWidget) {
758 if (d->currentWidget->leavesTheSpaceForRevertButton()) {
759 geometry.setWidth(geometry.width()-d->undoButton->width());
760 }
761 d->currentWidget->resize(geometry.width(), geometry.height());
762 }*/
763 d->undoButton->hide();
764 return;
765 }
766
767 TQPoint p = contentsToViewport(TQPoint(0, geometry.y()));
768 d->undoButton->move(geometry.x() + geometry.width()
769 -((d->currentWidget && d->currentWidget->hasBorders())?1:0)/*editor is moved by 1 to left*/
770 - d->undoButton->width(), p.y());
771// if (d->currentWidget) {
772// d->currentWidget->move(d->currentWidget->x(), p.y());
773// d->currentWidget->resize(geometry.width()-d->undoButton->width(), geometry.height());
774// }
775 d->undoButton->show();
776}
777
778void
779Editor::slotExpanded(TQListViewItem *item)
780{
781 if (!item)
782 return;
783
784 //select child item again if a group item has been expanded
785 if (!selectedItem() && dynamic_cast<EditorGroupItem*>(item) && d->previouslyCollapsedGroupItem == item
786 && d->childFormPreviouslyCollapsedGroupItem) {
787 setSelected(d->childFormPreviouslyCollapsedGroupItem, true);
788 setCurrentItem(selectedItem());
789 slotClicked(selectedItem());
790 }
791 updateEditorGeometry();
792 updateGroupLabelsPosition();
793 repaintContents();
794 repaint();
795}
796
797void
798Editor::slotCollapsed(TQListViewItem *item)
799{
800 if (!item)
801 return;
802 //unselect child item and hide editor if a group item has been collapsed
803 if (dynamic_cast<EditorGroupItem*>(item)) {
804 for (TQListViewItem *i = selectedItem(); i; i = i->parent()) {
805 if (i->parent()==item) {
806 d->previouslyCollapsedGroupItem = item;
807 d->childFormPreviouslyCollapsedGroupItem = selectedItem();
808 hideEditor();
809 setSelected(selectedItem(), false);
810 setSelected(item->nextSibling(), true);
811 break;
812 }
813 }
814 }
815 updateEditorGeometry();
816 updateGroupLabelsPosition();
817 repaintContents();
818 repaint();
819}
820
821void
822Editor::slotColumnSizeChanged(int section, int oldSize, int newSize)
823{
824 Q_UNUSED(section);
825 Q_UNUSED(oldSize);
826 Q_UNUSED(newSize);
827 /*for (TQListViewItemIterator it(this); it.current(); ++it) {
828 if (section == 0 && dynamic_cast<EditorGroupItem*>(it.current())) {
829 it.current()->repaint();
830 }
831 }*/
832/*
833 if(d->currentWidget) {
834 if(section == 0)
835 d->currentWidget->move(newS, d->currentWidget->y());
836 else {
837 if(d->undoButton->isVisible())
838 d->currentWidget->resize(newS - d->undoButton->width(), d->currentWidget->height());
839 else
840 d->currentWidget->resize(
841 newS-(d->currentWidget->leavesTheSpaceForRevertButton() ? d->undoButton->width() : 0),
842 d->currentWidget->height());
843 }
844 }*/
845// repaintContents();
846// repaint();
847 updateEditorGeometry();
848 update();
849}
850
851void
852Editor::slotColumnSizeChanged(int section)
853{
854 setColumnWidth(1, viewport()->width() - columnWidth(0));
855 slotColumnSizeChanged(section, 0, header()->sectionSize(section));
856
857/* if(d->currentWidget) {
858 if(d->undoButton->isVisible())
859 d->currentWidget->resize(columnWidth(1) - d->undoButton->width(), d->currentWidget->height());
860 else
861 d->currentWidget->resize(
862 columnWidth(1)-(d->currentWidget->leavesTheSpaceForRevertButton() ? d->undoButton->width() : 0),
863 d->currentWidget->height());
864 }*/
865 if(d->undoButton->isVisible())
866 showUndoButton(true);
867 else
868 updateEditorGeometry();
869}
870
871TQSize
872Editor::sizeHint() const
873{
874 return TQSize( TQFontMetrics(font()).width(columnText(0)+columnText(1)+" "),
875 TDEListView::sizeHint().height());
876}
877
878void
879Editor::setFocus()
880{
881 EditorItem *item = static_cast<EditorItem *>(selectedItem());
882 if (item) {
883 if (!d->justClickedItem)
884 ensureItemVisible(item);
885 d->justClickedItem = false;
886 }
887 else {
888 //select an item before focusing
889 item = static_cast<EditorItem *>(itemAt(TQPoint(10,1)));
890 if (item) {
891 ensureItemVisible(item);
892 setSelected(item, true);
893 }
894 }
895 if (d->currentWidget) {
896// kopropertydbg << "d->currentWidget->setFocus()" << endl;
897 d->currentWidget->setFocus();
898 }
899 else {
900// kopropertydbg << "TDEListView::setFocus()" << endl;
901 TDEListView::setFocus();
902 }
903}
904
905void
906Editor::resizeEvent(TQResizeEvent *ev)
907{
908 TDEListView::resizeEvent(ev);
909 if(d->undoButton->isVisible())
910 showUndoButton(true);
911 update();
912 updateGroupLabelsPosition();
913}
914
915bool
916Editor::eventFilter( TQObject * watched, TQEvent * e )
917{
918 if ((watched==this || watched==viewport()) && e->type()==TQEvent::KeyPress) {
919 if (handleKeyPress(static_cast<TQKeyEvent*>(e)))
920 return true;
921 }
922 return TDEListView::eventFilter(watched, e);
923}
924
925bool
926Editor::handleKeyPress(TQKeyEvent* ev)
927{
928 const int k = ev->key();
929 const TQt::ButtonState s = ev->state();
930
931 //selection moving
932 TQListViewItem *item = 0;
933
934 if ( ((s == TQt::NoButton) && (k == Key_Up)) || (k==Key_BackTab) ) {
935 //find prev visible
936 item = selectedItem() ? selectedItem()->itemAbove() : 0;
937 while (item && (!item->isSelectable() || !item->isVisible()))
938 item = item->itemAbove();
939 if (!item)
940 return true;
941 }
942 else if( (s == TQt::NoButton) && ((k == Key_Down) || (k == Key_Tab)) ) {
943 //find next visible
944 item = selectedItem() ? selectedItem()->itemBelow() : 0;
945 while (item && (!item->isSelectable() || !item->isVisible()))
946 item = item->itemBelow();
947 if (!item)
948 return true;
949 }
950 else if( (s==TQt::NoButton) && (k==Key_Home) ) {
951 if (d->currentWidget && d->currentWidget->hasFocus())
952 return false;
953 //find 1st visible
954 item = firstChild();
955 while (item && (!item->isSelectable() || !item->isVisible()))
956 item = item->itemBelow();
957 }
958 else if( (s==TQt::NoButton) && (k==Key_End) ) {
959 if (d->currentWidget && d->currentWidget->hasFocus())
960 return false;
961 //find last visible
962 item = selectedItem();
963 TQListViewItem *lastVisible = item;
964 while (item) { // && (!item->isSelectable() || !item->isVisible()))
965 item = item->itemBelow();
966 if (item && item->isSelectable() && item->isVisible())
967 lastVisible = item;
968 }
969 item = lastVisible;
970 }
971
972 if(item) {
973 ev->accept();
974 ensureItemVisible(item);
975 setSelected(item, true);
976 return true;
977 }
978 return false;
979}
980
981void
982Editor::updateFont()
983{
984 setFont(parentWidget()->font());
985 d->baseRowHeight = TQFontMetrics(parentWidget()->font()).height() + itemMargin() * 2;
986 if (!d->currentItem)
987 d->undoButton->resize(d->baseRowHeight, d->baseRowHeight);
988 else {
989 showUndoButton(d->undoButton->isVisible());
990 updateEditorGeometry();
991 }
992 updateGroupLabelsPosition();
993}
994
995bool
996Editor::event( TQEvent * e )
997{
998 if (e->type()==TQEvent::ParentFontChange) {
999 updateFont();
1000 }
1001 return TDEListView::event(e);
1002}
1003
1004void
1005Editor::contentsMousePressEvent( TQMouseEvent * e )
1006{
1007 TQListViewItem *item = itemAt(e->pos());
1008 if (dynamic_cast<EditorGroupItem*>(item)) {
1009 setOpen( item, !isOpen(item) );
1010 return;
1011 }
1013}
1014
1015void
1016Editor::setSorting( int column, bool ascending )
1017{
1018 if (d->set && d->set->groupNames().count()>1) //do not sort when groups are present (maybe reenable this later?)
1019 return;
1020 TDEListView::setSorting( column, ascending );
1021 updateEditorGeometry();
1022 updateGroupLabelsPosition();
1023 repaintContents();
1024 repaint();
1025}
1026
1027#include "editor.moc"
Item for a single property displayed within Editor object.
Definition editoritem.h:48
A listview to edit properties Editor widgets use property options using Property::option(const char *...
Definition editor.h:64
void slotWidgetValueChanged(Widget *widget)
Definition editor.cpp:520
void slotSetWillBeDeleted()
Definition editor.cpp:627
Editor(TQWidget *parent=0, bool autoSync=true, const char *name=0)
Definition editor.cpp:122
void slotWidgetRejectInput(Widget *widget)
Definition editor.cpp:560
void changeSetInternal(Set *set, bool preservePrevSelection, const TQCString &propertyToSelect)
Definition editor.cpp:299
void clearWidgetCache()
Definition editor.cpp:670
void slotClicked(TQListViewItem *item)
Definition editor.cpp:569
void slotWidgetAcceptInput(Widget *widget)
Definition editor.cpp:551
void slotSetWillBeCleared()
Definition editor.cpp:616
void addItem(const TQCString &name, EditorItem *parent)
Definition editor.cpp:251
void clear(bool editorOnly=false)
Definition editor.cpp:409
void propertySetChanged(KoProperty::Set *set)
Widget * createWidgetForProperty(Property *property, bool changeWidgetProperty=true)
Definition editor.cpp:634
void changeSet(Set *set, bool preservePrevSelection=false)
Definition editor.cpp:287
void slotPropertyChanged(KoProperty::Set &set, KoProperty::Property &property)
Definition editor.cpp:444
Widget * createWidgetForProperty(Property *property)
Definition factory.cpp:128
static FactoryManager * self()
Definition factory.cpp:93
The base class representing a single property.
Definition property.h:177
TQCString name() const
Definition property.cpp:248
bool isReadOnly() const
Definition property.cpp:476
bool isModified() const
Definition property.cpp:464
Property * parent() const
Definition property.cpp:651
TQVariant value() const
Definition property.cpp:314
void setValue(const TQVariant &value, bool rememberOldValue=true, bool useCustomProperty=true)
Definition property.cpp:331
int autoSync() const
Definition property.cpp:500
Lists holding properties in groups.
Definition set.h:41
bool isEmpty() const
Definition set.cpp:338
TQCString prevSelection() const
Definition set.cpp:420
The base class for all item editors used in Editor.
Definition widget.h:37
bool hasBorders() const
Definition widget.cpp:184
virtual Property * property() const
Definition widget.cpp:72
bool isReadOnly() const
Definition widget.cpp:208
void setReadOnly(bool readOnly)
Definition widget.cpp:214
bool leavesTheSpaceForRevertButton() const
Definition widget.cpp:166
virtual TQVariant value() const =0
virtual void setTooltipColumn(int column)
virtual int addColumn(const TQString &label, int width=-1)
virtual bool event(TQEvent *)
void setFullWidth() TDE_DEPRECATED
void setShadeSortColumn(bool shadeSortColumn)
virtual void setSorting(int column, bool ascending=true)
virtual void contentsMousePressEvent(TQMouseEvent *e)
Namespace for a set of classes implementing generic properties framework.
@ Rect
rectangle (x,y, width, height)
Definition property.h:76
bool hasParent(TQObject *par, TQObject *o)
Definition editor.cpp:54