File indexing completed on 2025-01-05 04:00:03

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2008-04-18
0007  * Description : User interface for searches
0008  *
0009  * SPDX-FileCopyrightText: 2008-2012 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0010  *
0011  * SPDX-License-Identifier: GPL-2.0-or-later
0012  *
0013  * ============================================================ */
0014 
0015 #include "choicesearchutilities.h"
0016 
0017 // Qt includes
0018 
0019 #include <QTreeView>
0020 
0021 // Local includes
0022 
0023 #include "digikam_debug.h"
0024 #include "searchutilities.h"
0025 
0026 namespace Digikam
0027 {
0028 
0029 ChoiceSearchModel::Entry::Entry()
0030     : m_checkState(false)
0031 {
0032 }
0033 
0034 ChoiceSearchModel::Entry::Entry(const QVariant& key, const QString& userDisplay)
0035     : m_key       (key),
0036       m_display   (userDisplay),
0037       m_checkState(false)
0038 {
0039 }
0040 
0041 bool ChoiceSearchModel::Entry::operator==(const Entry& other) const
0042 {
0043     return (m_key == other.m_key);
0044 }
0045 
0046 ChoiceSearchModel::ChoiceSearchModel(QObject* const parent)
0047     : QAbstractListModel(parent)
0048 {
0049 }
0050 
0051 void ChoiceSearchModel::setChoice(const QMap<int, QString>& data)
0052 {
0053     if (m_entries.size())
0054     {
0055         beginResetModel();
0056         m_entries.clear();
0057         endResetModel();
0058     }
0059 
0060     for (QMap<int, QString>::const_iterator it = data.constBegin() ; it != data.constEnd() ; ++it)
0061     {
0062         m_entries << Entry(it.key(), it.value());
0063     }
0064 }
0065 
0066 void ChoiceSearchModel::setChoice(const QVariantList& data)
0067 {
0068     if (m_entries.size())
0069     {
0070         beginResetModel();
0071         m_entries.clear();
0072         endResetModel();
0073     }
0074 
0075     Q_ASSERT(data.size() % 2 == 0);
0076 
0077     for (QVariantList::const_iterator it = data.constBegin() ; it != data.constEnd() ; )
0078     {
0079         QVariant key  = *it;
0080         ++it;
0081         QString value = (*it).toString();
0082         ++it;
0083         m_entries << Entry(key, value);
0084     }
0085 }
0086 
0087 void ChoiceSearchModel::setChoice(const QStringList& data)
0088 {
0089     if (m_entries.size())
0090     {
0091         beginResetModel();
0092         m_entries.clear();
0093         endResetModel();
0094     }
0095 
0096     Q_ASSERT(data.size() % 2 == 0);
0097 
0098     for (QStringList::const_iterator it = data.constBegin() ; it != data.constEnd() ; )
0099     {
0100         QVariant key  = *it;
0101         ++it;
0102         QString value = *it;
0103         ++it;
0104         m_entries << Entry(key, value);
0105     }
0106 }
0107 
0108 QVariantList ChoiceSearchModel::checkedKeys() const
0109 {
0110     QVariantList list;
0111 
0112     for (QList<Entry>::const_iterator it = m_entries.constBegin() ; it != m_entries.constEnd() ; ++it)
0113     {
0114         if ((*it).m_checkState)
0115         {
0116             list << (*it).m_key;
0117         }
0118     }
0119 
0120     return list;
0121 }
0122 
0123 QStringList ChoiceSearchModel::checkedDisplayTexts() const
0124 {
0125     QStringList list;
0126 
0127     for (QList<Entry>::const_iterator it = m_entries.constBegin() ; it != m_entries.constEnd() ; ++it)
0128     {
0129         if ((*it).m_checkState)
0130         {
0131             list << (*it).m_display;
0132         }
0133     }
0134 
0135     return list;
0136 }
0137 
0138 void ChoiceSearchModel::setChecked(int i, bool checked)
0139 {
0140     m_entries[i].m_checkState = checked;
0141     QModelIndex modelIndex    = index(i);
0142 
0143     Q_EMIT dataChanged(modelIndex, modelIndex);
0144     Q_EMIT checkStateChanged(m_entries.at(i).m_key, checked);
0145 }
0146 
0147 void ChoiceSearchModel::resetChecked()
0148 {
0149     for (int i = 0 ; i < m_entries.size() ; ++i)
0150     {
0151         if (m_entries.at(i).m_checkState)
0152         {
0153             setChecked(i, false);
0154         }
0155     }
0156 }
0157 
0158 int ChoiceSearchModel::rowCount(const QModelIndex& parent) const
0159 {
0160     if (parent.isValid())
0161     {
0162         return 0;
0163     }
0164 
0165     return m_entries.count();
0166 }
0167 
0168 QVariant ChoiceSearchModel::data(const QModelIndex& index, int role) const
0169 {
0170     if (index.isValid())
0171     {
0172         if      (role == Qt::DisplayRole)
0173         {
0174             return m_entries.at(index.row()).m_display;
0175         }
0176         else if (role == Qt::CheckStateRole)
0177         {
0178             return m_entries.at(index.row()).m_checkState ? Qt::Checked : Qt::Unchecked;
0179         }
0180         else if (role == IdRole)
0181         {
0182             return m_entries.at(index.row()).m_key;
0183         }
0184     }
0185 
0186     return QVariant();
0187 }
0188 
0189 QModelIndex ChoiceSearchModel::index(int row, int column, const QModelIndex& parent) const
0190 {
0191     if (parent.isValid() || (column != 0) || (row >= m_entries.size()))
0192     {
0193         return QModelIndex();
0194     }
0195 
0196     return createIndex(row, 0);
0197 }
0198 
0199 Qt::ItemFlags ChoiceSearchModel::flags(const QModelIndex& index) const
0200 {
0201     return QAbstractListModel::flags(index) | Qt::ItemIsUserCheckable;
0202 }
0203 
0204 bool ChoiceSearchModel::setData(const QModelIndex& index, const QVariant& value, int role)
0205 {
0206     if (role == Qt::CheckStateRole)
0207     {
0208         Qt::CheckState state = (Qt::CheckState)value.toInt();
0209         setChecked(index.row(), state == Qt::Checked);
0210 
0211         return true;
0212     }
0213     else
0214     {
0215         return QAbstractListModel::setData(index, value, role);
0216     }
0217 }
0218 
0219 // --------------------------------------------------------------------------------------
0220 
0221 ChoiceSearchComboBox::ChoiceSearchComboBox(QWidget* const parent)
0222     : ListViewComboBox(parent),
0223       m_label         (nullptr)
0224 {
0225 }
0226 
0227 void ChoiceSearchComboBox::setSearchModel(ChoiceSearchModel* model)
0228 {
0229     ModelIndexBasedComboBox::setModel(model);
0230     installView();
0231 }
0232 
0233 ChoiceSearchModel* ChoiceSearchComboBox::model() const
0234 {
0235     return static_cast<ChoiceSearchModel*>(ListViewComboBox::model());
0236 }
0237 
0238 DSqueezedClickLabel* ChoiceSearchComboBox::label() const
0239 {
0240     return m_label;
0241 }
0242 
0243 void ChoiceSearchComboBox::setLabelText(const QString& text)
0244 {
0245     m_label->setAdjustedText(text);
0246 }
0247 
0248 void ChoiceSearchComboBox::labelClicked()
0249 {
0250     qCDebug(DIGIKAM_GENERAL_LOG) << "labelClicked";
0251     showPopup();
0252 }
0253 
0254 void ChoiceSearchComboBox::installView(QAbstractItemView* v)
0255 {
0256     // make protected again
0257 
0258     ListViewComboBox::installView(v);
0259 /*
0260     view()->setHeaderHidden(true);
0261 */
0262     view()->setAlternatingRowColors(true);
0263 
0264     // create the label
0265 
0266     m_label = new DSqueezedClickLabel;
0267 
0268     if (layoutDirection() == Qt::RightToLeft)
0269     {
0270         m_label->setElideMode(Qt::ElideRight);
0271     }
0272     else
0273     {
0274         m_label->setElideMode(Qt::ElideLeft);
0275     }
0276 
0277     // set a line edit that carries the label
0278 
0279     ProxyClickLineEdit* const lineEdit = new ProxyClickLineEdit;
0280     lineEdit->setCursor(m_label->cursor());
0281     lineEdit->setWidget(m_label);
0282     setLineEdit(lineEdit);
0283 
0284     // connect clicks on upper area (both line edit and widget within) to showPopup
0285 
0286     connect(lineEdit, SIGNAL(leftClicked()),
0287             this, SLOT(labelClicked()));
0288 
0289     connect(m_label, SIGNAL(activated()),
0290             this, SLOT(labelClicked()));
0291 }
0292 
0293 } // namespace Digikam
0294 
0295 #include "moc_choicesearchutilities.cpp"