lib

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