diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
commit | 8362bf63dea22bbf6736609b0f49c152f975eb63 (patch) | |
tree | 0eea3928e39e50fae91d4e68b21b1e6cbae25604 /lib/koproperty/editor.cpp | |
download | koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip |
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'lib/koproperty/editor.cpp')
-rw-r--r-- | lib/koproperty/editor.cpp | 1027 |
1 files changed, 1027 insertions, 0 deletions
diff --git a/lib/koproperty/editor.cpp b/lib/koproperty/editor.cpp new file mode 100644 index 00000000..3ae52d40 --- /dev/null +++ b/lib/koproperty/editor.cpp @@ -0,0 +1,1027 @@ +/* This file is part of the KDE project + Copyright (C) 2004 Cedric Pasteur <[email protected]> + Copyright (C) 2004 Alexander Dymo <[email protected]> + Copyright (C) 2004-2006 Jaroslaw Staniek <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "editor.h" +#include "editoritem.h" +#include "set.h" +#include "factory.h" +#include "property.h" +#include "widget.h" + +#include <qpushbutton.h> +#include <qlayout.h> +#include <qmap.h> +#include <qguardedptr.h> +#include <qheader.h> +#include <qasciidict.h> +#include <qtooltip.h> +#include <qapplication.h> +#include <qeventloop.h> +#include <qtimer.h> +#include <qlabel.h> + +#include <kdebug.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kdeversion.h> +#include <kapplication.h> + +namespace KoProperty { + +//! @internal +static bool kofficeAppDirAdded = false; + +//! \return true if \a o has parent \a par. +//! @internal +inline bool hasParent(QObject* par, QObject* o) +{ + if (!o || !par) + return false; + while (o && o != par) + o = o->parent(); + return o == par; +} + +class EditorPrivate +{ + public: + EditorPrivate(Editor *editor) + : itemDict(101, false), justClickedItem(false) + { + currentItem = 0; + undoButton = 0; + topItem = 0; + itemToSelectLater = 0; + if (!kofficeAppDirAdded) { + kofficeAppDirAdded = true; + KGlobal::iconLoader()->addAppDir("koffice"); + } + previouslyCollapsedGroupItem = 0; + childFormPreviouslyCollapsedGroupItem = 0; + slotPropertyChanged_enabled = true; + QObject::connect(&changeSetLaterTimer, SIGNAL(timeout()), + editor, SLOT(changeSetLater())); + } + ~EditorPrivate() + { + } + + QGuardedPtr<Set> set; + //! widget cache for property types, widget will be deleted + QMap<Property*, Widget* > widgetCache; + QGuardedPtr<Widget> currentWidget; + EditorItem *currentItem; + EditorItem *topItem; //! The top item is used to control the drawing of every branches. + QPushButton *undoButton; //! "Revert to defaults" button + EditorItem::Dict itemDict; + + int baseRowHeight; + bool sync : 1; + bool insideSlotValueChanged : 1; + + //! Helpers for changeSetLater() + QTimer changeSetLaterTimer; + bool setListLater_set : 1; + bool preservePrevSelection_preservePrevSelection : 1; + QCString preservePrevSelection_propertyToSelect; + //bool doNotSetFocusOnSelection : 1; + //! Used in setFocus() to prevent scrolling to previously selected item on mouse click + bool justClickedItem : 1; + //! Helper for slotWidgetValueChanged() + bool slotPropertyChanged_enabled : 1; + //! Helper for changeSet() + Set* setListLater_list; + //! used by selectItemLater() + EditorItem *itemToSelectLater; + + QListViewItem *previouslyCollapsedGroupItem; + QListViewItem *childFormPreviouslyCollapsedGroupItem; +}; +} + +using namespace KoProperty; + +Editor::Editor(QWidget *parent, bool autoSync, const char *name) + : KListView(parent, name) +{ + d = new EditorPrivate(this); + d->itemDict.setAutoDelete(false); + + d->set = 0; + d->topItem = 0; + d->currentItem = 0; + d->sync = autoSync; + d->insideSlotValueChanged = false; + d->setListLater_set = false; + d->preservePrevSelection_preservePrevSelection = false; + d->setListLater_list = 0; + + d->undoButton = new QPushButton(viewport()); + d->undoButton->setFocusPolicy(QWidget::NoFocus); + setFocusPolicy(QWidget::ClickFocus); + d->undoButton->setMinimumSize(QSize(5,5)); // allow to resize undoButton even below pixmap size + d->undoButton->setPixmap(SmallIcon("undo")); + QToolTip::add(d->undoButton, i18n("Undo changes")); + d->undoButton->hide(); + connect(d->undoButton, SIGNAL(clicked()), this, SLOT(undo())); + + installEventFilter(this); + viewport()->installEventFilter(this); + + addColumn(i18n("Name")); + addColumn(i18n("Value")); + setAllColumnsShowFocus(true); + setColumnWidthMode(0, QListView::Maximum); + setFullWidth(true); + setShowSortIndicator(false); +#if KDE_IS_VERSION(3,3,9) + setShadeSortColumn(false); +#endif + setTooltipColumn(0); + setSorting(0); + setItemMargin(KPROPEDITOR_ITEM_MARGIN); + header()->setMovingEnabled( false ); + setTreeStepSize(16 + 2/*left*/ + 1/*right*/); + + updateFont(); +// d->baseRowHeight = QFontMetrics(font()).height() + itemMargin()*2; + + connect(this, SIGNAL(selectionChanged(QListViewItem *)), this, SLOT(slotClicked(QListViewItem *))); + connect(this, SIGNAL(currentChanged(QListViewItem *)), this, SLOT(slotCurrentChanged(QListViewItem *))); + connect(this, SIGNAL(expanded(QListViewItem *)), this, SLOT(slotExpanded(QListViewItem *))); + connect(this, SIGNAL(collapsed(QListViewItem *)), this, SLOT(slotCollapsed(QListViewItem *))); + connect(header(), SIGNAL(sizeChange(int, int, int)), this, SLOT(slotColumnSizeChanged(int, int, int))); +// connect(header(), SIGNAL(clicked(int)), this, SLOT(updateEditorGeometry())); +// connect(header(), SIGNAL(clicked(int)), this, SLOT(updateEditorGeometryAndGroupLabels())); + connect(header(), SIGNAL(sectionHandleDoubleClicked (int)), this, SLOT(slotColumnSizeChanged(int))); + updateGroupLabelsPosition(); +} + +Editor::~Editor() +{ + clearWidgetCache(); + delete d; + d = 0; +} + +void +Editor::fill() +{ + setUpdatesEnabled(false); + d->itemToSelectLater = 0; + qApp->eventLoop()->processEvents(QEventLoop::AllEvents); + hideEditor(); + KListView::clear(); + d->itemDict.clear(); + clearWidgetCache(); + if(!d->set) { + d->topItem = 0; + setUpdatesEnabled(true); + triggerUpdate(); + return; + } + + d->topItem = new EditorDummyItem(this); + + const QValueList<QCString> groupNames = d->set->groupNames(); +// kopropertydbg << "Editor::fill(): group names = " << groupNames.count() << endl; + if(groupNames.count() == 1) { // one group (default one), so don't show groups + //add flat set of properties + const QValueList<QCString>& propertyNames = d->set->propertyNamesForGroup( groupNames.first() ); + QValueListConstIterator<QCString> it = propertyNames.constBegin(); + for( ; it != propertyNames.constEnd(); ++it) + addItem(*it, d->topItem); + } + else { // create a groupItem for each group + EditorGroupItem *prevGroupItem = 0; + int sortOrder = 0; + for (QValueListConstIterator<QCString> it = groupNames.constBegin(); it!=groupNames.constEnd(); + ++it, sortOrder++) + { + const QValueList<QCString>& propertyNames = d->set->propertyNamesForGroup(*it); + EditorGroupItem *groupItem; + if (prevGroupItem) + groupItem = new EditorGroupItem(d->topItem, prevGroupItem, + d->set->groupDescription(*it), d->set->groupIcon(*it), sortOrder ); + else + groupItem = new EditorGroupItem(d->topItem, + d->set->groupDescription(*it), d->set->groupIcon(*it), sortOrder ); + + QValueList<QCString>::ConstIterator it2 = propertyNames.constBegin(); + for( ; it2 != propertyNames.constEnd(); ++it2) + addItem(*it2, groupItem); + + prevGroupItem = groupItem; + } + } + +// repaint(); + + if (firstChild()) + { + setCurrentItem(firstChild()); + setSelected(firstChild(), true); + slotClicked(firstChild()); + updateGroupLabelsPosition(); + } + setUpdatesEnabled(true); + // aaah, call this instead of update() as explained here http://lists.trolltech.com/qt-interest/2000-06/thread00337-0.html + triggerUpdate(); +} + +void +Editor::addItem(const QCString &name, EditorItem *parent) +{ + if(!d->set || !d->set->contains(name)) + return; + + Property *property = &(d->set->property(name)); + if(!property || !property->isVisible()) { +// kopropertydbg << "Property is not visible: " << name << endl; + return; + } + QListViewItem *last = parent ? parent->firstChild() : d->topItem->firstChild(); + while(last && last->nextSibling()) + last = last->nextSibling(); + + EditorItem *item=0; + if(parent) + item = new EditorItem(this, parent, property, last); + else + item = new EditorItem(this, d->topItem, property, last); + d->itemDict.insert(name, item); + + // Create child items + item->setOpen(true); + if(!property->children()) + return; + + last = 0; + QValueList<Property*>::ConstIterator endIt = property->children()->constEnd(); + for(QValueList<Property*>::ConstIterator it = property->children()->constBegin(); it != endIt; ++it) { + //! \todo allow to have child prop with child items too + if( *it && (*it)->isVisible() ) + last = new EditorItem(this, item, *it, last); + } +} + +void +Editor::changeSet(Set *set, bool preservePrevSelection) +{ + changeSetInternal(set, preservePrevSelection, ""); +} + +void +Editor::changeSet(Set *set, const QCString& propertyToSelect) +{ + changeSetInternal(set, !propertyToSelect.isEmpty(), propertyToSelect); +} + +void +Editor::changeSetInternal(Set *set, bool preservePrevSelection, const QCString& propertyToSelect) +{ + if (d->insideSlotValueChanged) { + //changeSet() called from inside of slotValueChanged() + //this is dangerous, because there can be pending events, + //especially for the GUI stuff, so let's do delayed work + d->setListLater_list = set; + d->preservePrevSelection_preservePrevSelection = preservePrevSelection; + d->preservePrevSelection_propertyToSelect = propertyToSelect; + qApp->eventLoop()->processEvents(QEventLoop::AllEvents); + if (d->set) { + //store prev. selection for this prop set + if (d->currentItem) + d->set->setPrevSelection( d->currentItem->property()->name() ); + kdDebug() << d->set->prevSelection() << endl; + } + if (!d->setListLater_set) { + d->setListLater_set = true; + d->changeSetLaterTimer.start(10, true); + } + return; + } + + if (d->set) { + slotWidgetAcceptInput(d->currentWidget); + //store prev. selection for this prop set + if (d->currentItem) + d->set->setPrevSelection( d->currentItem->property()->name() ); + else + d->set->setPrevSelection( "" ); + d->set->disconnect(this); + } + + QCString selectedPropertyName1 = propertyToSelect, selectedPropertyName2 = propertyToSelect; + if (preservePrevSelection) { + //try to find prev. selection: + //1. in new list's prev. selection + if(set) + selectedPropertyName1 = set->prevSelection(); + //2. in prev. list's current selection + if(d->set) + selectedPropertyName2 = d->set->prevSelection(); + } + + d->set = set; + if (d->set) { + //receive property changes + connect(d->set, SIGNAL(propertyChangedInternal(KoProperty::Set&, KoProperty::Property&)), + this, SLOT(slotPropertyChanged(KoProperty::Set&, KoProperty::Property&))); + connect(d->set, SIGNAL(propertyReset(KoProperty::Set&, KoProperty::Property&)), + this, SLOT(slotPropertyReset(KoProperty::Set&, KoProperty::Property&))); + connect(d->set,SIGNAL(aboutToBeCleared()), this, SLOT(slotSetWillBeCleared())); + connect(d->set,SIGNAL(aboutToBeDeleted()), this, SLOT(slotSetWillBeDeleted())); + } + + fill(); + + emit propertySetChanged(d->set); + + if (d->set) { + //select prev. selected item + EditorItem * item = 0; + if (!selectedPropertyName2.isEmpty()) //try other one for old prop set + item = d->itemDict[selectedPropertyName2]; + if (!item && !selectedPropertyName1.isEmpty()) //try old one for current prop set + item = d->itemDict[selectedPropertyName1]; + + if (item) { + d->itemToSelectLater = item; + QTimer::singleShot(10, this, SLOT(selectItemLater())); + //d->doNotSetFocusOnSelection = !hasParent(this, focusWidget()); + //setSelected(item, true); + //d->doNotSetFocusOnSelection = false; +// ensureItemVisible(item); + } + } +} + +//! @internal +void Editor::selectItemLater() +{ + if (!d->itemToSelectLater) + return; + EditorItem *item = d->itemToSelectLater; + d->itemToSelectLater = 0; + setSelected(item, true); + ensureItemVisible(item); +} + +//! @internal +void +Editor::changeSetLater() +{ + qApp->eventLoop()->processEvents(QEventLoop::AllEvents); + if (kapp->hasPendingEvents()) { + d->changeSetLaterTimer.start(10, true); //try again... + return; + } + d->setListLater_set = false; + if (!d->setListLater_list) + return; + + bool b = d->insideSlotValueChanged; + d->insideSlotValueChanged = false; + changeSetInternal(d->setListLater_list, d->preservePrevSelection_preservePrevSelection, + d->preservePrevSelection_propertyToSelect); + d->insideSlotValueChanged = b; +} + +void +Editor::clear(bool editorOnly) +{ + d->itemToSelectLater = 0; + hideEditor(); + + if(!editorOnly) { + qApp->eventLoop()->processEvents(QEventLoop::AllEvents); + if(d->set) + d->set->disconnect(this); + clearWidgetCache(); + KListView::clear(); + d->itemDict.clear(); + d->topItem = 0; + } +} + +void +Editor::undo() +{ + if(!d->currentWidget || !d->currentItem || (d->set && d->set->isReadOnly()) || (d->currentWidget && d->currentWidget->isReadOnly())) + return; + + int propertySync = d->currentWidget->property()->autoSync(); + bool sync = (propertySync != 0 && propertySync != 1) ? + d->sync : (propertySync!=0); + + if(sync) + d->currentItem->property()->resetValue(); + if (d->currentWidget && d->currentItem) {//(check because current widget could be removed by resetValue()) + d->currentWidget->setValue( d->currentItem->property()->value()); + repaintItem(d->currentItem); + } +} + +void +Editor::slotPropertyChanged(Set& set, Property& property) +{ + if (!d->slotPropertyChanged_enabled) + return; + if(&set != d->set) + return; + + if (d->currentItem && d->currentItem->property() == &property) { + d->currentWidget->setValue(property.value(), false); + for(QListViewItem *item = d->currentItem->firstChild(); item; item = item->nextSibling()) + repaintItem(item); + } + else { + // prop not in the dict, might be a child property: + EditorItem *item = d->itemDict[property.name()]; + if(!item && property.parent()) + item = d->itemDict[property.parent()->name()]; + if (item) { + repaintItem(item); + for(QListViewItem *it = item->firstChild(); it; it = it->nextSibling()) + repaintItem(it); + } + } + +//! @todo should we move this somewhere? +#if 0 + if (property.parent() && property.parent()->type()==Rect) { + const int delta = property.value().toInt()-previousValue.toInt(); + if (property.type()==Rect_X) { //|| property.type()==Rect_Y) + property.parent()->child("width")->setValue(delta, false); + } + +/* if (widget->property() && (QWidget*)d->currentWidget==widget && d->currentItem->parent()) { + EditorItem *parentItem = static_cast<EditorItem*>(d->currentItem->parent()); + const int thisType = ; + && parentItem->property()->type()==Rect) { + //changing x or y components of Rect type shouldn't change width or height, respectively + if (thisType==Rect_X) { + EditorItem *rectWidthItem = static_cast<EditorItem*>(d->currentItem->nextSibling()->nextSibling()); + if (delta!=0) { + rectWidthItem->property()->setValue(rectWidthItem->property()->value().toInt()+delta, false); + } + } + }*/ + } +#endif + showUndoButton( property.isModified() ); +} + +void +Editor::slotPropertyReset(Set& set, Property& property) +{ + if(&set != d->set) + return; + + if (d->currentItem && d->currentItem->property() == &property) { + d->currentWidget->setValue(property.value(), false); + for(QListViewItem *item = d->currentItem->firstChild(); item; item = item->nextSibling()) + repaintItem(item); + } + else { + EditorItem *item = d->itemDict[property.name()]; + // prop not in the dict, might be a child prop. + if(!item && property.parent()) + item = d->itemDict[property.parent()->name()]; + if (item) { + repaintItem(item); + for(QListViewItem *it = item->firstChild(); it; it = it->nextSibling()) + repaintItem(it); + } + } + + showUndoButton( false ); +} + +void +Editor::slotWidgetValueChanged(Widget *widget) +{ + if(!widget || !d->set || (d->set && d->set->isReadOnly()) || (widget && widget->isReadOnly()) || !widget->property()) + return; + + d->insideSlotValueChanged = true; + + QVariant value = widget->value(); + int propertySync = widget->property()->autoSync(); + bool sync = (propertySync != 0 && propertySync != 1) ? + d->sync : (propertySync!=0); + + if(sync) { + d->slotPropertyChanged_enabled = false; + QGuardedPtr<Widget> pWidget = widget; //safe, widget can be destroyed in the meantime + widget->property()->setValue(value); + if (pWidget) + showUndoButton( pWidget->property()->isModified() ); + d->slotPropertyChanged_enabled = true; + } + + d->insideSlotValueChanged = false; +} + +void +Editor::acceptInput() +{ + slotWidgetAcceptInput(d->currentWidget); +} + +void +Editor::slotWidgetAcceptInput(Widget *widget) +{ + if(!widget || !d->set || !widget->property() || (d->set && d->set->isReadOnly()) || (widget && widget->isReadOnly())) + return; + + widget->property()->setValue(widget->value()); +} + +void +Editor::slotWidgetRejectInput(Widget *widget) +{ + if(!widget || !d->set) + return; + + undo(); +} + +void +Editor::slotClicked(QListViewItem *it) +{ + d->previouslyCollapsedGroupItem = 0; + d->childFormPreviouslyCollapsedGroupItem = 0; + + acceptInput(); + + hideEditor(); + if(!it) + return; + + EditorItem *item = static_cast<EditorItem*>(it); + Property *p = item ? item->property() : 0; + if(!p) + return; + + d->currentItem = item; + d->currentWidget = createWidgetForProperty(p); + + //moved up updateEditorGeometry(); + showUndoButton( p->isModified() ); + if (d->currentWidget) { + if (d->currentWidget->visibleFlag()) { + d->currentWidget->show(); + if (hasParent( this, kapp->focusWidget() )) + d->currentWidget->setFocus(); + } + } + + d->justClickedItem = true; +} + +void +Editor::slotCurrentChanged(QListViewItem *item) +{ + if (item == firstChild()) { + QListViewItem *oldItem = item; + while (item && (!item->isSelectable() || !item->isVisible())) + item = item->itemBelow(); + if (item && item != oldItem) { + setSelected(item,true); + return; + } + } +} + +void +Editor::slotSetWillBeCleared() +{ + d->itemToSelectLater = 0; + if (d->currentWidget) { + acceptInput(); + d->currentWidget->setProperty(0); + } + clear(); +} + +void +Editor::slotSetWillBeDeleted() +{ + clear(); + d->set = 0; +} + +Widget* +Editor::createWidgetForProperty(Property *property, bool changeWidgetProperty) +{ +// int type = property->type(); + QGuardedPtr<Widget> widget = d->widgetCache[property]; + + if(!widget) { + widget = FactoryManager::self()->createWidgetForProperty(property); + if (!widget) + return 0; + widget->setReadOnly( (d->set && d->set->isReadOnly()) || property->isReadOnly() ); + d->widgetCache[property] = widget; + widget->setProperty(0); // to force reloading property later + widget->hide(); + connect(widget, SIGNAL(valueChanged(Widget*)), + this, SLOT(slotWidgetValueChanged(Widget*)) ); + connect(widget, SIGNAL(acceptInput(Widget*)), + this, SLOT(slotWidgetAcceptInput(Widget*)) ); + connect(widget, SIGNAL(rejectInput(Widget*)), + this, SLOT(slotWidgetRejectInput(Widget*)) ); + } + + //update geometry earlier, because Widget::setValue() can depend on widget's geometry + updateEditorGeometry(d->currentItem, widget); + + if(widget && (!widget->property() || changeWidgetProperty)) + widget->setProperty(property); + +// if (!d->doNotSetFocusOnSelection) { +// widget->setFocus(); +// } + + return widget; +} + + +void +Editor::clearWidgetCache() +{ + for(QMap<Property*, Widget*>::iterator it = d->widgetCache.begin(); it != d->widgetCache.end(); ++it) + it.data()->deleteLater(); +// delete it.data(); + d->widgetCache.clear(); +} + +void +Editor::updateEditorGeometry(bool forceUndoButtonSettings, bool undoButtonVisible) +{ + updateEditorGeometry(d->currentItem, d->currentWidget, + forceUndoButtonSettings, undoButtonVisible); +} + +void +Editor::updateEditorGeometry(EditorItem *item, Widget* widget, + bool forceUndoButtonSettings, bool undoButtonVisible) +{ + if(!item || !widget) + return; + + int placeForUndoButton; + if (forceUndoButtonSettings ? undoButtonVisible : d->undoButton->isVisible()) + placeForUndoButton = d->undoButton->width(); + else + placeForUndoButton = widget->leavesTheSpaceForRevertButton() ? d->undoButton->width() : 0; + + QRect r; + int y = itemPos(item); + r.setX(header()->sectionPos(1)-(widget->hasBorders()?1:0)); //-1, to align to horizontal line + r.setY(y-(widget->hasBorders()?1:0)); + r.setWidth(header()->sectionSize(1)+(widget->hasBorders()?1:0) //+1 because we subtracted 1 from X + - placeForUndoButton); + r.setHeight(item->height()+(widget->hasBorders()?1:-1)); + + // check if the column is fully visible + if (visibleWidth() < r.right()) + r.setRight(visibleWidth()); + + moveChild(widget, r.x(), r.y()); + widget->resize(r.size()); + qApp->eventLoop()->processEvents(QEventLoop::AllEvents); +} + +void +Editor::updateGroupLabelsPosition() +{ + if(!d->topItem || d->itemDict.isEmpty()) + return; + + EditorGroupItem *group = dynamic_cast<EditorGroupItem*>(d->topItem->firstChild()); + while(group) { + QRect r = itemRect((QListViewItem*) group); + if(group->label()) { + group->label()->setGeometry(r); + group->label()->repaint(); + } + group = dynamic_cast<EditorGroupItem*>(group->nextSibling()); + } +} + +void +Editor::hideEditor() +{ + d->currentItem = 0; + QWidget *cw = d->currentWidget; + if(cw) { + d->currentWidget = 0; + cw->hide(); + } + d->undoButton->hide(); +} + +void +Editor::showUndoButton( bool show ) +{ + if (!d->currentItem || !d->currentWidget || (d->currentWidget && d->currentWidget->isReadOnly())) + return; + + int y = viewportToContents(QPoint(0, itemRect(d->currentItem).y())).y(); + QRect geometry(columnWidth(0), y, columnWidth(1) + 1, d->currentItem->height()); + d->undoButton->resize(d->baseRowHeight, d->currentItem->height()); + + updateEditorGeometry(true, show); + + if (!show) { +/* if (d->currentWidget) { + if (d->currentWidget->leavesTheSpaceForRevertButton()) { + geometry.setWidth(geometry.width()-d->undoButton->width()); + } + d->currentWidget->resize(geometry.width(), geometry.height()); + }*/ + d->undoButton->hide(); + return; + } + + QPoint p = contentsToViewport(QPoint(0, geometry.y())); + d->undoButton->move(geometry.x() + geometry.width() + -((d->currentWidget && d->currentWidget->hasBorders())?1:0)/*editor is moved by 1 to left*/ + - d->undoButton->width(), p.y()); +// if (d->currentWidget) { +// d->currentWidget->move(d->currentWidget->x(), p.y()); +// d->currentWidget->resize(geometry.width()-d->undoButton->width(), geometry.height()); +// } + d->undoButton->show(); +} + +void +Editor::slotExpanded(QListViewItem *item) +{ + if (!item) + return; + + //select child item again if a group item has been expanded + if (!selectedItem() && dynamic_cast<EditorGroupItem*>(item) && d->previouslyCollapsedGroupItem == item + && d->childFormPreviouslyCollapsedGroupItem) { + setSelected(d->childFormPreviouslyCollapsedGroupItem, true); + setCurrentItem(selectedItem()); + slotClicked(selectedItem()); + } + updateEditorGeometry(); + updateGroupLabelsPosition(); + repaintContents(); + repaint(); +} + +void +Editor::slotCollapsed(QListViewItem *item) +{ + if (!item) + return; + //unselect child item and hide editor if a group item has been collapsed + if (dynamic_cast<EditorGroupItem*>(item)) { + for (QListViewItem *i = selectedItem(); i; i = i->parent()) { + if (i->parent()==item) { + d->previouslyCollapsedGroupItem = item; + d->childFormPreviouslyCollapsedGroupItem = selectedItem(); + hideEditor(); + setSelected(selectedItem(), false); + setSelected(item->nextSibling(), true); + break; + } + } + } + updateEditorGeometry(); + updateGroupLabelsPosition(); + repaintContents(); + repaint(); +} + +void +Editor::slotColumnSizeChanged(int section, int oldSize, int newSize) +{ + Q_UNUSED(section); + Q_UNUSED(oldSize); + Q_UNUSED(newSize); + /*for (QListViewItemIterator it(this); it.current(); ++it) { + if (section == 0 && dynamic_cast<EditorGroupItem*>(it.current())) { + it.current()->repaint(); + } + }*/ +/* + if(d->currentWidget) { + if(section == 0) + d->currentWidget->move(newS, d->currentWidget->y()); + else { + if(d->undoButton->isVisible()) + d->currentWidget->resize(newS - d->undoButton->width(), d->currentWidget->height()); + else + d->currentWidget->resize( + newS-(d->currentWidget->leavesTheSpaceForRevertButton() ? d->undoButton->width() : 0), + d->currentWidget->height()); + } + }*/ +// repaintContents(); +// repaint(); + updateEditorGeometry(); + update(); +} + +void +Editor::slotColumnSizeChanged(int section) +{ + setColumnWidth(1, viewport()->width() - columnWidth(0)); + slotColumnSizeChanged(section, 0, header()->sectionSize(section)); + +/* if(d->currentWidget) { + if(d->undoButton->isVisible()) + d->currentWidget->resize(columnWidth(1) - d->undoButton->width(), d->currentWidget->height()); + else + d->currentWidget->resize( + columnWidth(1)-(d->currentWidget->leavesTheSpaceForRevertButton() ? d->undoButton->width() : 0), + d->currentWidget->height()); + }*/ + if(d->undoButton->isVisible()) + showUndoButton(true); + else + updateEditorGeometry(); +} + +QSize +Editor::sizeHint() const +{ + return QSize( QFontMetrics(font()).width(columnText(0)+columnText(1)+" "), + KListView::sizeHint().height()); +} + +void +Editor::setFocus() +{ + EditorItem *item = static_cast<EditorItem *>(selectedItem()); + if (item) { + if (!d->justClickedItem) + ensureItemVisible(item); + d->justClickedItem = false; + } + else { + //select an item before focusing + item = static_cast<EditorItem *>(itemAt(QPoint(10,1))); + if (item) { + ensureItemVisible(item); + setSelected(item, true); + } + } + if (d->currentWidget) { +// kopropertydbg << "d->currentWidget->setFocus()" << endl; + d->currentWidget->setFocus(); + } + else { +// kopropertydbg << "KListView::setFocus()" << endl; + KListView::setFocus(); + } +} + +void +Editor::resizeEvent(QResizeEvent *ev) +{ + KListView::resizeEvent(ev); + if(d->undoButton->isVisible()) + showUndoButton(true); + update(); + updateGroupLabelsPosition(); +} + +bool +Editor::eventFilter( QObject * watched, QEvent * e ) +{ + if ((watched==this || watched==viewport()) && e->type()==QEvent::KeyPress) { + if (handleKeyPress(static_cast<QKeyEvent*>(e))) + return true; + } + return KListView::eventFilter(watched, e); +} + +bool +Editor::handleKeyPress(QKeyEvent* ev) +{ + const int k = ev->key(); + const Qt::ButtonState s = ev->state(); + + //selection moving + QListViewItem *item = 0; + + if ( ((s == NoButton) && (k == Key_Up)) || (k==Key_BackTab) ) { + //find prev visible + item = selectedItem() ? selectedItem()->itemAbove() : 0; + while (item && (!item->isSelectable() || !item->isVisible())) + item = item->itemAbove(); + if (!item) + return true; + } + else if( (s == NoButton) && ((k == Key_Down) || (k == Key_Tab)) ) { + //find next visible + item = selectedItem() ? selectedItem()->itemBelow() : 0; + while (item && (!item->isSelectable() || !item->isVisible())) + item = item->itemBelow(); + if (!item) + return true; + } + else if( (s==NoButton) && (k==Key_Home) ) { + if (d->currentWidget && d->currentWidget->hasFocus()) + return false; + //find 1st visible + item = firstChild(); + while (item && (!item->isSelectable() || !item->isVisible())) + item = item->itemBelow(); + } + else if( (s==NoButton) && (k==Key_End) ) { + if (d->currentWidget && d->currentWidget->hasFocus()) + return false; + //find last visible + item = selectedItem(); + QListViewItem *lastVisible = item; + while (item) { // && (!item->isSelectable() || !item->isVisible())) + item = item->itemBelow(); + if (item && item->isSelectable() && item->isVisible()) + lastVisible = item; + } + item = lastVisible; + } + + if(item) { + ev->accept(); + ensureItemVisible(item); + setSelected(item, true); + return true; + } + return false; +} + +void +Editor::updateFont() +{ + setFont(parentWidget()->font()); + d->baseRowHeight = QFontMetrics(parentWidget()->font()).height() + itemMargin() * 2; + if (!d->currentItem) + d->undoButton->resize(d->baseRowHeight, d->baseRowHeight); + else { + showUndoButton(d->undoButton->isVisible()); + updateEditorGeometry(); + } + updateGroupLabelsPosition(); +} + +bool +Editor::event( QEvent * e ) +{ + if (e->type()==QEvent::ParentFontChange) { + updateFont(); + } + return KListView::event(e); +} + +void +Editor::contentsMousePressEvent( QMouseEvent * e ) +{ + QListViewItem *item = itemAt(e->pos()); + if (dynamic_cast<EditorGroupItem*>(item)) { + setOpen( item, !isOpen(item) ); + return; + } + KListView::contentsMousePressEvent(e); +} + +void +Editor::setSorting( int column, bool ascending ) +{ + if (d->set && d->set->groupNames().count()>1) //do not sort when groups are present (maybe reenable this later?) + return; + KListView::setSorting( column, ascending ); + updateEditorGeometry(); + updateGroupLabelsPosition(); + repaintContents(); + repaint(); +} + +#include "editor.moc" |