File indexing completed on 2024-04-28 04:41:51

0001 /***************************************************************************
0002  *   Copyright (C) 2017 by Emmanuel Lepage Vallee                          *
0003  *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@kde.org>             *
0004  *                                                                         *
0005  *   This program is free software; you can redistribute it and/or modify  *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 3 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  *                                                                         *
0010  *   This program is distributed in the hope that it will be useful,       *
0011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0013  *   GNU General Public License for more details.                          *
0014  *                                                                         *
0015  *   You should have received a copy of the GNU General Public License     *
0016  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
0017  **************************************************************************/
0018 #include "comboboxview.h"
0019 
0020 // Qt
0021 #include <QQmlEngine>
0022 #include <QQmlContext>
0023 #include <QQuickWindow>
0024 
0025 class ComboBoxViewPrivate final : public QObject
0026 {
0027     Q_OBJECT
0028 public:
0029     QItemSelectionModel* m_pSelectionModel {nullptr};
0030     QQuickItem*          m_pItem           {nullptr};
0031 
0032     ComboBoxView* q_ptr;
0033 
0034 public Q_SLOTS:
0035     void slotWindowChanged(QQuickWindow *window);
0036     void slotActivated(int index);
0037     void slotCurrentChanged(const QModelIndex& idx);
0038     void slotResize();
0039 };
0040 
0041 ComboBoxView::ComboBoxView(QQuickItem* parent) : QQuickItem(parent),
0042     d_ptr(new ComboBoxViewPrivate)
0043 {
0044     d_ptr->q_ptr = this;
0045 
0046     connect(this, &QQuickItem::windowChanged,
0047         d_ptr, &ComboBoxViewPrivate::slotWindowChanged);
0048 
0049     setHeight(40);
0050 }
0051 
0052 ComboBoxView::~ComboBoxView()
0053 {
0054     if (d_ptr->m_pItem)
0055         delete d_ptr->m_pItem;
0056 
0057     delete d_ptr;
0058 }
0059 
0060 QItemSelectionModel* ComboBoxView::selectionModel() const
0061 {
0062     return d_ptr->m_pSelectionModel;
0063 }
0064 
0065 void ComboBoxView::setSelectionModel(QItemSelectionModel* s)
0066 {
0067     if (s && d_ptr->m_pSelectionModel && d_ptr->m_pSelectionModel != s)
0068         disconnect(d_ptr->m_pSelectionModel, &QItemSelectionModel::currentChanged,
0069             d_ptr, &ComboBoxViewPrivate::slotCurrentChanged);
0070 
0071     d_ptr->m_pSelectionModel = s;
0072 
0073     if (s && d_ptr->m_pItem) {
0074         d_ptr->blockSignals(true);
0075         d_ptr->m_pItem->setProperty("model", QVariant::fromValue(s->model()));
0076         if (s->currentIndex().isValid())
0077             d_ptr->m_pItem->setProperty("currentIndex", s->currentIndex().row());
0078         d_ptr->blockSignals(false);
0079     }
0080 
0081     connect(d_ptr->m_pSelectionModel, &QItemSelectionModel::currentChanged,
0082         d_ptr, &ComboBoxViewPrivate::slotCurrentChanged);
0083 }
0084 
0085 void ComboBoxViewPrivate::slotWindowChanged(QQuickWindow *window)
0086 {
0087     if (!window)
0088         return;
0089 
0090     if (!m_pItem) {
0091         QQmlEngine *engine = QQmlEngine::contextForObject(q_ptr)->engine();
0092 
0093         Q_ASSERT(engine);
0094 
0095         QQmlComponent cbb(engine, q_ptr);
0096         cbb.setData("import QtQuick 2.4; import QtQuick.Controls 2.0;"\
0097         "ComboBox {textRole: \"display\"; anchors.fill: parent;}", {});
0098         m_pItem = qobject_cast<QQuickItem*>(cbb.create());
0099 
0100         if (m_pSelectionModel)
0101             q_ptr->setSelectionModel(m_pSelectionModel);
0102 
0103         connect(m_pItem, SIGNAL(activated(int)),
0104             this, SLOT(slotActivated(int)));
0105 
0106         connect(m_pItem, SIGNAL(implicitWidthChanged()),
0107             this, SLOT(slotResize()));
0108 
0109         q_ptr->setHeight(m_pItem->height());
0110         m_pItem->setParentItem(q_ptr);
0111         engine->setObjectOwnership(m_pItem, QQmlEngine::CppOwnership);
0112         slotResize();
0113     }
0114 }
0115 
0116 void ComboBoxViewPrivate::slotResize()
0117 {
0118     q_ptr->setImplicitWidth(m_pItem->implicitWidth());
0119     q_ptr->setImplicitHeight(m_pItem->implicitHeight());
0120 }
0121 
0122 void ComboBoxViewPrivate::slotActivated(int index)
0123 {
0124     if (!m_pSelectionModel)
0125         return;
0126 
0127     auto m = m_pSelectionModel->model();
0128 
0129     Q_ASSERT(m);
0130     Q_ASSERT(index >= 0 && index < m->rowCount());
0131 
0132     if (m_pSelectionModel)
0133         m_pSelectionModel->setCurrentIndex(
0134             m->index(index, 0),QItemSelectionModel::ClearAndSelect
0135         );
0136 
0137     slotResize();
0138 }
0139 
0140 void ComboBoxViewPrivate::slotCurrentChanged(const QModelIndex& idx)
0141 {
0142     if (!m_pItem)
0143         return;
0144 
0145     if (!idx.isValid())
0146         return;
0147 
0148     m_pItem->setProperty("currentIndex", idx.row());
0149 }
0150 
0151 #include <comboboxview.moc>