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