00001
00022 #include "kwidgetitemdelegate.h"
00023 #include "kwidgetitemdelegate_p.h"
00024
00025 #include <QIcon>
00026 #include <QSize>
00027 #include <QStyle>
00028 #include <QEvent>
00029 #include <QHoverEvent>
00030 #include <QFocusEvent>
00031 #include <QCursor>
00032 #include <QTimer>
00033 #include <QBitmap>
00034 #include <QLayout>
00035 #include <QPainter>
00036 #include <QScrollBar>
00037 #include <QKeyEvent>
00038 #include <QApplication>
00039 #include <QStyleOption>
00040 #include <QPaintEngine>
00041 #include <QCoreApplication>
00042 #include <QAbstractItemView>
00043 #include <QAbstractProxyModel>
00044
00045 #include "kwidgetitemdelegatepool_p.h"
00046
00047 Q_DECLARE_METATYPE(QList<QEvent::Type>)
00048
00049
00053
00054 KWidgetItemDelegatePrivate::KWidgetItemDelegatePrivate(KWidgetItemDelegate *q, QObject *parent)
00055 : QObject(parent)
00056 , itemView(0)
00057 , widgetPool(new KWidgetItemDelegatePool(q))
00058 , model(0)
00059 , q(q)
00060 {
00061 }
00062
00063 KWidgetItemDelegatePrivate::~KWidgetItemDelegatePrivate()
00064 {
00065 delete widgetPool;
00066 }
00067
00068 void KWidgetItemDelegatePrivate::_k_slotRowsInserted(const QModelIndex &parent, int start, int end)
00069 {
00070 updateRowRange(parent, start, end, false);
00071 }
00072
00073 void KWidgetItemDelegatePrivate::_k_slotRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
00074 {
00075 updateRowRange(parent, start, end, true);
00076 }
00077
00078 void KWidgetItemDelegatePrivate::_k_slotDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
00079 {
00080 for (int i = topLeft.row(); i <= bottomRight.row(); ++i) {
00081 for (int j = topLeft.column(); j <= bottomRight.column(); ++j) {
00082 const QModelIndex index = model->index(i, j, topLeft.parent());
00083 QStyleOptionViewItemV4 optionView;
00084 optionView.initFrom(itemView->viewport());
00085 optionView.rect = itemView->visualRect(index);
00086 widgetPool->findWidgets(index, optionView);
00087 }
00088 }
00089 }
00090
00091 void KWidgetItemDelegatePrivate::_k_slotLayoutChanged()
00092 {
00093 foreach (QWidget *widget, widgetPool->invalidIndexesWidgets()) {
00094 widget->setVisible(false);
00095 }
00096 QTimer::singleShot(0, this, SLOT(initializeModel()));
00097 }
00098
00099 void KWidgetItemDelegatePrivate::_k_slotModelReset()
00100 {
00101 widgetPool->fullClear();
00102 QTimer::singleShot(0, this, SLOT(initializeModel()));
00103 }
00104
00105 void KWidgetItemDelegatePrivate::updateRowRange(const QModelIndex &parent, int start, int end, bool isRemoving)
00106 {
00107 int i = start;
00108 while (i <= end) {
00109 for (int j = 0; j < model->columnCount(parent); ++j) {
00110 const QModelIndex index = model->index(i, j, parent);
00111 QStyleOptionViewItemV4 optionView;
00112 optionView.initFrom(itemView->viewport());
00113 optionView.rect = itemView->visualRect(index);
00114
00115 QList<QWidget*> widgetList = widgetPool->findWidgets(index, optionView, isRemoving ? KWidgetItemDelegatePool::NotUpdateWidgets
00116 : KWidgetItemDelegatePool::UpdateWidgets);
00117 if (isRemoving) {
00118 widgetPool->d->allocatedWidgets.removeAll(widgetList);
00119 foreach (QWidget *widget, widgetList) {
00120 const QModelIndex idx = widgetPool->d->widgetInIndex[widget];
00121 widgetPool->d->usedWidgets.remove(idx);
00122 widgetPool->d->widgetInIndex.remove(widget);
00123 delete widget;
00124 }
00125 }
00126 }
00127 i++;
00128 }
00129 }
00130
00131 void KWidgetItemDelegatePrivate::initializeModel(const QModelIndex &parent)
00132 {
00133 for (int i = 0; i < model->rowCount(parent); ++i) {
00134 for (int j = 0; j < model->columnCount(parent); ++j) {
00135 const QModelIndex index = model->index(i, j, parent);
00136 if (index.isValid()) {
00137 QStyleOptionViewItemV4 optionView;
00138 optionView.initFrom(itemView->viewport());
00139 optionView.rect = itemView->visualRect(index);
00140 widgetPool->findWidgets(index, optionView);
00141 }
00142 }
00143
00144
00145 const QModelIndex index = model->index(i, 0, parent);
00146 if (index.isValid() && model->hasChildren(index)) {
00147 initializeModel(index);
00148 }
00149 }
00150 }
00151
00152
00153 KWidgetItemDelegate::KWidgetItemDelegate(QAbstractItemView *itemView, QObject *parent)
00154 : QAbstractItemDelegate(parent)
00155 , d(new KWidgetItemDelegatePrivate(this))
00156 {
00157 Q_ASSERT(itemView);
00158
00159 itemView->setMouseTracking(true);
00160 itemView->viewport()->setAttribute(Qt::WA_Hover);
00161
00162 d->itemView = itemView;
00163
00164 itemView->viewport()->installEventFilter(d);
00165 itemView->installEventFilter(d);
00166 }
00167
00168 KWidgetItemDelegate::~KWidgetItemDelegate()
00169 {
00170 delete d;
00171 }
00172
00173 QAbstractItemView *KWidgetItemDelegate::itemView() const
00174 {
00175 return d->itemView;
00176 }
00177
00178 QPersistentModelIndex KWidgetItemDelegate::focusedIndex() const
00179 {
00180 const QPersistentModelIndex idx = d->widgetPool->d->widgetInIndex.value(QApplication::focusWidget());
00181 if (idx.isValid()) {
00182 return idx;
00183 }
00184
00185 const QPoint pos = d->itemView->viewport()->mapFromGlobal(QCursor::pos());
00186 return d->itemView->indexAt(pos);
00187 }
00188
00189 void KWidgetItemDelegate::paintWidgets(QPainter *painter, const QStyleOptionViewItem &option,
00190 const QPersistentModelIndex &index) const
00191 {
00192 Q_UNUSED(painter);
00193 Q_UNUSED(option);
00194 Q_UNUSED(index);
00195 }
00196
00197
00198 bool KWidgetItemDelegatePrivate::eventFilter(QObject *watched, QEvent *event)
00199 {
00200 if (event->type() == QEvent::Destroy) {
00201 return false;
00202 }
00203
00204 Q_UNUSED(watched);
00205 Q_ASSERT(itemView);
00206
00207 if (model != itemView->model()) {
00208 if (model) {
00209 disconnect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), q, SLOT(_k_slotRowsInserted(QModelIndex,int,int)));
00210 disconnect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), q, SLOT(_k_slotRowsAboutToBeRemoved(QModelIndex,int,int)));
00211 disconnect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), q, SLOT(_k_slotDataChanged(QModelIndex,QModelIndex)));
00212 disconnect(model, SIGNAL(layoutChanged()), q, SLOT(_k_slotLayoutChanged()));
00213 disconnect(model, SIGNAL(modelReset()), q, SLOT(_k_slotModelReset()));
00214 }
00215 model = itemView->model();
00216 connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), q, SLOT(_k_slotRowsInserted(QModelIndex,int,int)));
00217 connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), q, SLOT(_k_slotRowsAboutToBeRemoved(QModelIndex,int,int)));
00218 connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), q, SLOT(_k_slotDataChanged(QModelIndex,QModelIndex)));
00219 connect(model, SIGNAL(layoutChanged()), q, SLOT(_k_slotLayoutChanged()));
00220 connect(model, SIGNAL(modelReset()), q, SLOT(_k_slotModelReset()));
00221 QTimer::singleShot(0, this, SLOT(initializeModel()));
00222 }
00223
00224 switch (event->type()) {
00225 case QEvent::Polish:
00226 case QEvent::Resize:
00227 if (!qobject_cast<QAbstractItemView*>(watched)) {
00228 QTimer::singleShot(0, this, SLOT(initializeModel()));
00229 }
00230 break;
00231 default:
00232 break;
00233 }
00234
00235 return QObject::eventFilter(watched, event);
00236 }
00237
00238
00239 void KWidgetItemDelegate::setBlockedEventTypes(QWidget *widget, QList<QEvent::Type> types) const
00240 {
00241 widget->setProperty("goya:blockedEventTypes", qVariantFromValue(types));
00242 }
00243
00244 QList<QEvent::Type> KWidgetItemDelegate::blockedEventTypes(QWidget *widget) const
00245 {
00246 return widget->property("goya:blockedEventTypes").value<QList<QEvent::Type> >();
00247 }
00248
00249 #include "kwidgetitemdelegate.moc"
00250 #include "kwidgetitemdelegate_p.moc"