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