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();
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)
141 QWidget *extender = static_cast<QWidget *>(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);
185 ret = QStyledItemDelegate::sizeHint(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()) {
240 QStyledItemDelegate::paint(painter, itemOption, index);
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();
267 QStyledItemDelegate::paint(painter, itemOption, index);
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);
294 QStyledItemDelegate::paint(painter, itemOption, index);
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" QPixmap extendPixmap()
Return the pixmap that is displayed to extend an item.
void contractItem(const QModelIndex &index)
Remove the extender of item at index from the view.
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
Re-implemented for internal reasons.
bool isExtended(const QModelIndex &index) const
Return whether there is an extender that belongs to index.
virtual ~KExtendableItemDelegate()
void contractAll()
Close all extenders and delete all extender widgets.
void setExtendPixmap(const QPixmap &pixmap)
The pixmap that is displayed to extend an item.
void extendItem(QWidget *extender, const QModelIndex &index)
Insert the extender for item at index into the view.
QPixmap contractPixmap()
Return the pixmap that is displayed to contract an item.
virtual void updateExtenderGeometry(QWidget *extender, const QStyleOptionViewItem &option, const QModelIndex &index) const
Reimplement this function to adjust the internal geometry of the extender.
QRect extenderRect(QWidget *extender, const QStyleOptionViewItem &option, const QModelIndex &index) const
Reimplement this function to fine-tune the position of the extender.
KExtendableItemDelegate(QAbstractItemView *parent)
Create a new KExtendableItemDelegate that belongs to parent.
void setContractPixmap(const QPixmap &pixmap)
The pixmap that is displayed to contract an item.
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
Re-implemented for internal reasons.
void extenderCreated(QWidget *extender, const QModelIndex &index)
This signal indicates that the item at index was extended with extender.