KDEUI
kwidgetitemdelegatepool.cpp
Go to the documentation of this file.
00001 00022 #include "kwidgetitemdelegatepool_p.h" 00023 00024 #include <math.h> 00025 00026 #include <QtCore/qobjectdefs.h> 00027 #include <QtCore/QMetaObject> 00028 #include <QtCore/QMetaMethod> 00029 #include <QtCore/QMetaProperty> 00030 #include <QtCore/QPair> 00031 #include <QtCore/QHash> 00032 #include <QtCore/QList> 00033 #include <QtGui/QWidget> 00034 #include <QtGui/QAbstractItemView> 00035 #include <QtGui/QApplication> 00036 #include <QtGui/QInputEvent> 00037 #include <QtGui/QAbstractProxyModel> 00038 00039 #include <kdebug.h> 00040 00041 #include "kwidgetitemdelegate.h" 00042 #include "kwidgetitemdelegate_p.h" 00043 00044 #define POOL_USAGE 0 00045 00046 Q_DECLARE_METATYPE(QModelIndex); 00047 00052 //@cond PRIVATE 00053 class KWidgetItemDelegateEventListener 00054 : public QObject 00055 { 00056 public: 00057 KWidgetItemDelegateEventListener(KWidgetItemDelegatePoolPrivate *poolPrivate, QObject *parent = 0) 00058 : QObject(parent) 00059 , poolPrivate(poolPrivate) 00060 { 00061 } 00062 00063 virtual bool eventFilter(QObject *watched, QEvent *event); 00064 00065 private: 00066 KWidgetItemDelegatePoolPrivate *poolPrivate; 00067 }; 00068 00069 KWidgetItemDelegatePoolPrivate::KWidgetItemDelegatePoolPrivate(KWidgetItemDelegate *d) 00070 : delegate(d) 00071 , eventListener(new KWidgetItemDelegateEventListener(this)) 00072 , clearing(false) 00073 { 00074 } 00075 00076 KWidgetItemDelegatePool::KWidgetItemDelegatePool(KWidgetItemDelegate *delegate) 00077 : d(new KWidgetItemDelegatePoolPrivate(delegate)) 00078 { 00079 } 00080 00081 KWidgetItemDelegatePool::~KWidgetItemDelegatePool() 00082 { 00083 delete d->eventListener; 00084 delete d; 00085 } 00086 00087 QList<QWidget*> KWidgetItemDelegatePool::findWidgets(const QPersistentModelIndex &idx, 00088 const QStyleOptionViewItem &option, 00089 UpdateWidgetsEnum updateWidgets) const 00090 { 00091 QList<QWidget*> result; 00092 00093 if (!idx.isValid()) { 00094 return result; 00095 } 00096 00097 QModelIndex index; 00098 if (const QAbstractProxyModel *proxyModel = qobject_cast<const QAbstractProxyModel*>(idx.model())) { 00099 index = proxyModel->mapToSource(idx); 00100 } else { 00101 index = idx; 00102 } 00103 00104 if (!index.isValid()) { 00105 return result; 00106 } 00107 00108 if (d->usedWidgets.contains(index)) { 00109 result = d->usedWidgets[index]; 00110 } else { 00111 // ### KDE5 This sets a property on the delegate because we can't add an argument to createItemWidgets 00112 d->delegate->setProperty("goya:creatingWidgetForIndex", QVariant::fromValue(index)); 00113 result = d->delegate->createItemWidgets(); 00114 d->delegate->setProperty("goya:creatingWidgetForIndex", QVariant()); 00115 d->allocatedWidgets << result; 00116 d->usedWidgets[index] = result; 00117 foreach (QWidget *widget, result) { 00118 d->widgetInIndex[widget] = index; 00119 widget->setParent(d->delegate->d->itemView->viewport()); 00120 widget->installEventFilter(d->eventListener); 00121 widget->setVisible(true); 00122 } 00123 } 00124 00125 if (updateWidgets == UpdateWidgets) { 00126 foreach (QWidget *widget, result) { 00127 widget->setVisible(true); 00128 } 00129 00130 d->delegate->updateItemWidgets(result, option, idx); 00131 00132 foreach (QWidget *widget, result) { 00133 widget->move(widget->x() + option.rect.left(), widget->y() + option.rect.top()); 00134 } 00135 } 00136 00137 return result; 00138 } 00139 00140 QList<QWidget*> KWidgetItemDelegatePool::invalidIndexesWidgets() const 00141 { 00142 QList<QWidget*> result; 00143 foreach (QWidget *widget, d->widgetInIndex.keys()) { 00144 const QAbstractProxyModel *proxyModel = qobject_cast<const QAbstractProxyModel*>(d->delegate->d->model); 00145 QModelIndex index; 00146 if (proxyModel) { 00147 index = proxyModel->mapFromSource(d->widgetInIndex[widget]); 00148 } else { 00149 index = d->widgetInIndex[widget]; 00150 } 00151 if (!index.isValid()) { 00152 result << widget; 00153 } 00154 } 00155 return result; 00156 } 00157 00158 void KWidgetItemDelegatePool::fullClear() 00159 { 00160 d->clearing = true; 00161 qDeleteAll(d->widgetInIndex.keys()); 00162 d->clearing = false; 00163 d->allocatedWidgets.clear(); 00164 d->usedWidgets.clear(); 00165 d->widgetInIndex.clear(); 00166 } 00167 00168 bool KWidgetItemDelegateEventListener::eventFilter(QObject *watched, QEvent *event) 00169 { 00170 QWidget *widget = static_cast<QWidget*>(watched); 00171 00172 if (event->type() == QEvent::Destroy && !poolPrivate->clearing) { 00173 kWarning() << "User of KWidgetItemDelegate should not delete widgets created by createItemWidgets!"; 00174 // assume the application has kept a list of widgets and tries to delete them manually 00175 // they have been reparented to the view in any case, so no leaking occurs 00176 poolPrivate->widgetInIndex.remove(widget); 00177 QWidget *viewport = poolPrivate->delegate->d->itemView->viewport(); 00178 QApplication::sendEvent(viewport, event); 00179 } 00180 if (dynamic_cast<QInputEvent*>(event) && !poolPrivate->delegate->blockedEventTypes(widget).contains(event->type())) { 00181 QWidget *viewport = poolPrivate->delegate->d->itemView->viewport(); 00182 switch(event->type()) { 00183 case QEvent::MouseMove: 00184 case QEvent::MouseButtonPress: 00185 case QEvent::MouseButtonRelease: 00186 case QEvent::MouseButtonDblClick: { 00187 QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event); 00188 QMouseEvent evt(event->type(), viewport->mapFromGlobal(mouseEvent->globalPos()), 00189 mouseEvent->button(), mouseEvent->buttons(), mouseEvent->modifiers()); 00190 QApplication::sendEvent(viewport, &evt); 00191 } 00192 break; 00193 case QEvent::Wheel: { 00194 QWheelEvent *wheelEvent = static_cast<QWheelEvent*>(event); 00195 QWheelEvent evt(viewport->mapFromGlobal(wheelEvent->globalPos()), 00196 wheelEvent->delta(), wheelEvent->buttons(), wheelEvent->modifiers(), 00197 wheelEvent->orientation()); 00198 QApplication::sendEvent(viewport, &evt); 00199 } 00200 break; 00201 case QEvent::TabletMove: 00202 case QEvent::TabletPress: 00203 case QEvent::TabletRelease: 00204 case QEvent::TabletEnterProximity: 00205 case QEvent::TabletLeaveProximity: { 00206 QTabletEvent *tabletEvent = static_cast<QTabletEvent*>(event); 00207 QTabletEvent evt(event->type(), viewport->mapFromGlobal(tabletEvent->globalPos()), 00208 tabletEvent->globalPos(), tabletEvent->hiResGlobalPos(), tabletEvent->device(), 00209 tabletEvent->pointerType(), tabletEvent->pressure(), tabletEvent->xTilt(), 00210 tabletEvent->yTilt(), tabletEvent->tangentialPressure(), tabletEvent->rotation(), 00211 tabletEvent->z(), tabletEvent->modifiers(), tabletEvent->uniqueId()); 00212 QApplication::sendEvent(viewport, &evt); 00213 } 00214 break; 00215 default: 00216 QApplication::sendEvent(viewport, event); 00217 break; 00218 } 00219 } 00220 00221 return QObject::eventFilter(watched, event); 00222 } 00223 //@endcond
KDE 4.7 API Reference