File indexing completed on 2022-09-27 13:43:07

0001 /* ============================================================
0002  *
0003  * This file is a part of KDE project
0004  *
0005  *
0006  * Date        : 2009-07-05
0007  * Description : A combobox delegate to display in image lists.
0008  *
0009  * Copyright (C) 2009 by Pieter Edelman <pieter dot edelman at gmx dot net>
0010  *
0011  * This program is free software; you can redistribute it
0012  * and/or modify it under the terms of the GNU General
0013  * Public License as published by the Free Software Foundation;
0014  * either version 2, or (at your option) any later version.
0015  *
0016  * This program is distributed in the hope that it will be useful,
0017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0019  * GNU General Public License for more details.
0020  *
0021  * ============================================================ */
0022 
0023 #include "comboboxdelegate.h"
0024 
0025 // Qt includes
0026 
0027 #include <QApplication>
0028 #include <QComboBox>
0029 #include <QPaintEvent>
0030 #include <QStyleOption>
0031 
0032 // Local includes
0033 
0034 #include "kipiplugins_debug.h"
0035 
0036 namespace KIPIFlickrPlugin
0037 {
0038 
0039 ComboBoxDelegate::ComboBoxDelegate(KPImagesList* const parent, const QMap<int, QString>& items)
0040     : QAbstractItemDelegate(parent),
0041       m_parent(parent),
0042       m_items(items),
0043       m_rowEdited(-1)
0044 {
0045     // Figure out the maximum width of a displayed item from the items list and
0046     // save it in the m_size parameter.
0047     QFontMetrics listFont = parent->fontMetrics();
0048     m_size                = QSize(0, listFont.height());
0049     int tmpWidth          = 0;
0050     QMapIterator<int, QString> i(m_items);
0051 
0052     while (i.hasNext())
0053     {
0054         i.next();
0055         tmpWidth = listFont.width(i.value());
0056 
0057         if (tmpWidth > m_size.width())
0058         {
0059             m_size.setWidth(tmpWidth);
0060         }
0061     }
0062 }
0063 
0064 void ComboBoxDelegate::startEditing(QTreeWidgetItem* item, int column)
0065 {
0066     // Start editing the item. This is part of a hack to make sure the item text
0067     // doesn't get painted whenever a combobox is drawn (otherwise the text can
0068     // be seen around the edges of the combobox. This method breaks the OO
0069     // paradigm.
0070     m_rowEdited = m_parent->listView()->currentIndex().row();
0071     item->setFlags(item->flags() | Qt::ItemIsEditable);
0072     m_parent->listView()->editItem(item, column);
0073     item->setFlags(item->flags() & ~Qt::ItemIsEditable);
0074 }
0075 
0076 void ComboBoxDelegate::paint(QPainter* painter,
0077                              const QStyleOptionViewItem& option,
0078                              const QModelIndex& index) const
0079 {
0080     // Draw a panel item primitive element as background.
0081     QStyle* const style = QApplication::style();
0082     style->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter);
0083 
0084     // If the element that gets painted is not currently edited, the item text
0085     // should be displayed.
0086     // Note that this method to detect which item is edited is a horrible hack
0087     // to work around the fact that there's no reliable way to detect if an item
0088     // is being edited from the parameters (although the documentation suggests
0089     // QStyle::State_Editing should be set in the option.flags parameter).
0090     if (m_rowEdited != index.row())
0091     {
0092         // Get the currently selected index in the items list.
0093         int currIndex = (index.data()).value<int>();
0094 
0095         // PE: These values are found by trial and error. I don't have any idea
0096         // if it's actually correct, but it seems to work across all themes.
0097         QPalette::ColorRole textColor = QPalette::Text;
0098 
0099         if (option.state & QStyle::State_Selected)
0100         {
0101             textColor = QPalette::HighlightedText;
0102         }
0103 
0104         // Draw the text.
0105         style->drawItemText(painter, option.rect, option.displayAlignment,
0106                             option.palette, true, m_items[currIndex],
0107                             textColor);
0108     }
0109 }
0110 
0111 QSize ComboBoxDelegate::sizeHint(const QStyleOptionViewItem&, const QModelIndex&) const
0112 {
0113     // Return the size based on the widest item in the items list.
0114     return m_size;
0115 }
0116 
0117 QWidget* ComboBoxDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option,
0118                                         const QModelIndex&) const
0119 {
0120     // This method returns the widget that should be used to edit the current
0121     // element, which is in this case a QComboBox with the items supplied by
0122     // the user items list on construction.
0123     QComboBox* const cb = new QComboBox(parent);
0124     QMapIterator<int, QString> i(m_items);
0125 
0126     while (i.hasNext())
0127     {
0128         i.next();
0129         cb->addItem(i.value(), QVariant(i.key()));
0130     }
0131 
0132     // Set the geometry
0133     cb->setGeometry(option.rect);
0134 
0135     // If the index is changed, the editing should be finished and the editor
0136     // destroyed.
0137     connect(cb, SIGNAL(activated(int)),
0138             this, SLOT(slotCommitAndCloseEditor(int)));
0139 
0140     // To keep track of the item being edited, the m_rowEdited parameter should
0141     // be reset when the editor is destroyed.
0142     connect(cb, SIGNAL(destroyed(QObject*)),
0143             this, SLOT(slotResetEditedState(QObject*)));
0144 
0145     return cb;
0146 }
0147 
0148 void ComboBoxDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
0149 {
0150     // Scroll the combobox to the current selected state on initialization.
0151     QComboBox* const cb = qobject_cast<QComboBox*>(editor);
0152 
0153     for (int i = 0; i < cb->count(); ++i)
0154     {
0155         if (cb->itemData(i).toInt() == index.data().toInt())
0156         {
0157             cb->setCurrentIndex(i);
0158         }
0159     }
0160 }
0161 
0162 void ComboBoxDelegate::setModelData(QWidget* editor, QAbstractItemModel* model,
0163                                     const QModelIndex& index) const
0164 {
0165     // Write the data to the model when finishing has completed.
0166     QComboBox* const cb = qobject_cast<QComboBox*>(editor);
0167     int selected        = cb->itemData(cb->currentIndex()).toInt();
0168     model->setData(index, selected);
0169 }
0170 
0171 void ComboBoxDelegate::slotCommitAndCloseEditor(int)
0172 {
0173     // Emit the proper signals when editing has finished.
0174     QComboBox* const editor = qobject_cast<QComboBox*>(sender());
0175     Q_EMIT commitData(editor);
0176     Q_EMIT closeEditor(editor);
0177 }
0178 
0179 void ComboBoxDelegate::slotResetEditedState(QObject*)
0180 {
0181     m_rowEdited = -1;
0182 }
0183 
0184 } // namespace KIPIFlickrPlugin