23 #include <QModelIndex>
27 #include <QApplication>
30 class KExtendableItemDelegate::Private {
42 void _k_extenderDestructionHandler(
QObject *destroyed);
43 void _k_verticalScroll();
45 QSize maybeExtendedSize(
const QStyleOptionViewItem &option,
const QModelIndex &index)
const;
46 QModelIndex indexOfExtendedColumnInSameRow(
const QModelIndex &index)
const;
47 void scheduleUpdateViewLayout();
54 void deleteExtenders();
57 QHash<QPersistentModelIndex, QWidget *> extenders;
58 QHash<QWidget *, QPersistentModelIndex> extenderIndices;
59 QHash<QWidget *, QPersistentModelIndex> deletionQueue;
65 QModelIndex cachedParentIndex;
75 connect(parent->verticalScrollBar(), SIGNAL(valueChanged(
int)),
76 this, SLOT(_k_verticalScroll()));
90 if (!ext || !index.isValid()) {
98 QAbstractItemView *aiv = qobject_cast<QAbstractItemView *>(parent());
102 ext->setParent(aiv->viewport());
103 d->extenders.insert(index, ext);
104 d->extenderIndices.insert(ext, index);
105 connect(ext, SIGNAL(destroyed(
QObject*)),
this, SLOT(_k_extenderDestructionHandler(
QObject*)));
107 d->scheduleUpdateViewLayout();
113 QWidget *extender = d->extenders.value(index);
119 extender->deleteLater();
121 QPersistentModelIndex persistentIndex = d->extenderIndices.take(extender);
122 d->extenders.remove(persistentIndex);
124 d->deletionQueue.insert(extender, persistentIndex);
126 d->scheduleUpdateViewLayout();
132 d->deleteExtenders();
137 void KExtendableItemDelegate::Private::_k_extenderDestructionHandler(
QObject *destroyed)
144 QPersistentModelIndex persistentIndex = deletionQueue.take(extender);
145 if (persistentIndex.isValid() &&
146 q->receivers(SIGNAL(extenderDestroyed(
QWidget*,QModelIndex)))) {
148 QModelIndex index = persistentIndex;
149 emit q->extenderDestroyed(extender, index);
152 scheduleUpdateViewLayout();
157 void KExtendableItemDelegate::Private::_k_verticalScroll()
159 foreach (
QWidget *extender, extenders) {
174 return d->extenders.value(index);
182 if (!d->extenders.isEmpty()) {
183 ret = d->maybeExtendedSize(option, index);
188 bool showExtensionIndicator = index.model() ?
190 if (showExtensionIndicator) {
191 ret.rwidth() += d->extendPixmap.width();
203 QStyleOptionViewItemV4 indicatorOption(option);
204 initStyleOption(&indicatorOption, index);
205 if (index.column() == 0) {
206 indicatorOption.viewItemPosition = QStyleOptionViewItemV4::Beginning;
207 }
else if (index.column() == index.model()->columnCount() - 1) {
210 indicatorOption.viewItemPosition = QStyleOptionViewItemV4::Middle;
213 QStyleOptionViewItemV4 itemOption(option);
214 initStyleOption(&itemOption, index);
215 if (index.column() == 0) {
216 itemOption.viewItemPosition = QStyleOptionViewItemV4::Beginning;
217 }
else if (index.column() == index.model()->columnCount() - 1) {
220 itemOption.viewItemPosition = QStyleOptionViewItemV4::Middle;
225 if (showExtensionIndicator) {
226 if (QApplication::isRightToLeft()) {
227 indicatorX = option.rect.right() - d->extendPixmap.width();
228 itemOption.rect.setRight(option.rect.right() - d->extendPixmap.width());
229 indicatorOption.rect.setLeft(option.rect.right() - d->extendPixmap.width());
231 indicatorX = option.rect.left();
232 indicatorOption.rect.setRight(option.rect.left() + d->extendPixmap.width());
233 itemOption.rect.setLeft(option.rect.left() + d->extendPixmap.width());
235 indicatorY = option.rect.top() + ((option.rect.height() - d->extendPixmap.height()) >> 1);
239 if (d->extenders.isEmpty()) {
241 if (showExtensionIndicator) {
243 QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &indicatorOption,
246 painter->drawPixmap(indicatorX, indicatorY, d->extendPixmap);
251 int row = index.row();
252 QModelIndex parentIndex = index.parent();
255 if (row != d->cachedRow || d->cachedStateTick != d->stateTick
256 || d->cachedParentIndex != parentIndex) {
257 d->extender = d->extenders.value(d->indexOfExtendedColumnInSameRow(index));
258 d->cachedStateTick = d->stateTick;
260 d->cachedParentIndex = parentIndex;
262 d->extenderHeight = d->extender->sizeHint().height();
268 if (showExtensionIndicator) {
270 QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &indicatorOption,
273 painter->drawPixmap(indicatorX, indicatorY, d->extendPixmap);
280 QStyleOptionViewItemV4 extOption(option);
281 initStyleOption(&extOption, index);
282 extOption.rect =
extenderRect(d->extender, option, index);
289 indicatorOption.rect.setHeight(option.rect.height() - d->extenderHeight);
290 itemOption.rect.setHeight(option.rect.height() - d->extenderHeight);
296 if (showExtensionIndicator) {
298 indicatorY = indicatorOption.rect.top() + ((indicatorOption.rect.height() -
299 d->extendPixmap.height()) >> 1);
301 QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &indicatorOption,
305 if (d->extenders.contains(index)) {
306 painter->drawPixmap(indicatorX, indicatorY, d->contractPixmap);
308 painter->drawPixmap(indicatorX, indicatorY, d->extendPixmap);
317 QRect rect(option.rect);
318 rect.setTop(rect.bottom() + 1 - extender->sizeHint().height());
321 if (QTreeView *tv = qobject_cast<QTreeView *>(parent())) {
323 for (QModelIndex idx(index.parent()); idx.isValid(); idx = idx.parent()) {
326 if (tv->rootIsDecorated()) {
329 indentation = indentSteps * tv->indentation();
332 QAbstractScrollArea *container = qobject_cast<QAbstractScrollArea *>(parent());
334 if (qApp->isLeftToRight()) {
335 rect.setLeft(indentation);
336 rect.setRight(container->viewport()->width() - 1);
338 rect.setRight(container->viewport()->width() - 1 - indentation);
345 QSize KExtendableItemDelegate::Private::maybeExtendedSize(
const QStyleOptionViewItem &option,
const QModelIndex &index)
const
347 QWidget *extender = extenders.value(index);
348 QSize size(q->QStyledItemDelegate::sizeHint(option, index));
353 int itemHeight = size.height();
355 int row = index.row();
356 int thisColumn = index.column();
359 for (
int column = 0; index.model()->columnCount() < column; column++) {
360 if (column == thisColumn) {
363 QModelIndex neighborIndex(index.sibling(row, column));
364 if (!neighborIndex.isValid()) {
367 itemHeight = qMax(itemHeight, q->QStyledItemDelegate::sizeHint(option, neighborIndex).height());
371 size.rheight() = itemHeight + extender->sizeHint().height();
376 QModelIndex KExtendableItemDelegate::Private::indexOfExtendedColumnInSameRow(
const QModelIndex &index)
const
379 const QModelIndex parentIndex(index.parent());
380 const int row = index.row();
381 const int columnCount = model->columnCount();
384 for (
int column = 0; column < columnCount; column++) {
385 QModelIndex indexOfExt(model->index(row, column, parentIndex));
386 if (extenders.value(indexOfExt)) {
391 return QModelIndex();
396 const QModelIndex &index)
const
399 extender->setGeometry(option.rect);
403 void KExtendableItemDelegate::Private::deleteExtenders()
405 foreach (
QWidget *ext, extenders) {
409 deletionQueue.unite(extenderIndices);
411 extenderIndices.clear();
417 void KExtendableItemDelegate::Private::scheduleUpdateViewLayout()
419 QAbstractItemView *aiv = qobject_cast<QAbstractItemView *>(q->parent());
423 aiv->setRootIndex(aiv->rootIndex());
430 d->extendPixmap = pixmap;
436 d->contractPixmap = pixmap;
442 return d->extendPixmap;
448 return d->contractPixmap;
451 #include "kextendableitemdelegate.moc"