File indexing completed on 2024-05-12 04:06:22
0001 /* 0002 SPDX-FileCopyrightText: 2010 Stefan Majewsky <majewsky@gmx.net> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #ifndef PALAPELI_TRIGGERLISTVIEW_P_H 0008 #define PALAPELI_TRIGGERLISTVIEW_P_H 0009 0010 #include "triggerlistview.h" 0011 #include "elidinglabel.h" 0012 #include "mouseinputbutton.h" 0013 #include <QApplication> 0014 #include <QCollator> 0015 #include <QHBoxLayout> 0016 #include <QLabel> 0017 #include <KCategorizedSortFilterProxyModel> 0018 #include <KWidgetItemDelegate> 0019 0020 namespace Palapeli 0021 { 0022 class TriggerListProxyModel : public KCategorizedSortFilterProxyModel 0023 { 0024 public: 0025 explicit TriggerListProxyModel(QObject* parent = nullptr) 0026 : KCategorizedSortFilterProxyModel(parent) 0027 { 0028 setCategorizedModel(true); 0029 m_collator.setCaseSensitivity(Qt::CaseSensitive); 0030 } 0031 protected: 0032 int compareCategories(const QModelIndex& left, const QModelIndex& right) const override 0033 { 0034 const int categoryLeft = left.data(KCategorizedSortFilterProxyModel::CategorySortRole).value<int>(); 0035 const int categoryRight = right.data(KCategorizedSortFilterProxyModel::CategorySortRole).value<int>(); 0036 return categoryRight - categoryLeft; 0037 } 0038 bool subSortLessThan(const QModelIndex& left, const QModelIndex& right) const override 0039 { 0040 const QString textLeft = left.data(Qt::DisplayRole).toString(); 0041 const QString textRight = right.data(Qt::DisplayRole).toString(); 0042 return m_collator.compare(textLeft, textRight) < 0; 0043 } 0044 private: 0045 QCollator m_collator; 0046 }; 0047 0048 class TriggerListDelegateWidget : public QWidget 0049 { 0050 Q_OBJECT 0051 public: 0052 explicit TriggerListDelegateWidget(QWidget* parent = nullptr) : QWidget(parent) 0053 { 0054 m_iconLabel = new QLabel(this); 0055 m_nameLabel = new Palapeli::ElidingLabel(this); 0056 m_inputButton = new Palapeli::MouseInputButton(this); 0057 connect(m_inputButton, &MouseInputButton::triggerChanged, this, &TriggerListDelegateWidget::triggerChanged); 0058 //construct layout 0059 QHBoxLayout* layout = new QHBoxLayout; 0060 setLayout(layout); 0061 layout->addWidget(m_iconLabel); 0062 m_iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 0063 m_iconLabel->setFixedSize(QSize(32, 32)); 0064 layout->addWidget(m_nameLabel); 0065 layout->addWidget(m_inputButton); 0066 m_inputButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 0067 } 0068 void setIcon(const QIcon& icon) 0069 { 0070 //TODO: respect global icon size configuration 0071 m_iconLabel->setPixmap(icon.pixmap(32)); 0072 } 0073 void setText(const QString& text) 0074 { 0075 m_nameLabel->setFullText(text); 0076 } 0077 void setTrigger(const Palapeli::Trigger& trigger) 0078 { 0079 m_inputButton->setTrigger(trigger); 0080 } 0081 void setInteractorType(Palapeli::InteractorType type) 0082 { 0083 m_inputButton->setMouseAllowed(type == Palapeli::MouseInteractor); 0084 m_inputButton->setWheelAllowed(type == Palapeli::WheelInteractor); 0085 } 0086 Q_SIGNALS: 0087 void triggerChanged(const Palapeli::Trigger& newTrigger); 0088 private: 0089 QLabel* m_iconLabel; 0090 Palapeli::ElidingLabel* m_nameLabel; 0091 Palapeli::MouseInputButton* m_inputButton; 0092 }; 0093 0094 class TriggerListDelegate : public KWidgetItemDelegate 0095 { 0096 Q_OBJECT 0097 public: 0098 explicit TriggerListDelegate(QAbstractItemView* view, QObject* parent = nullptr) : KWidgetItemDelegate(view, parent) 0099 { 0100 m_calculator = new Palapeli::TriggerListDelegateWidget(view); 0101 m_calculator->setVisible(false); 0102 } 0103 void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override 0104 { 0105 Q_UNUSED(index) 0106 QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter, nullptr); 0107 } 0108 QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override 0109 { 0110 updateItemWidgets(QList<QWidget*>() << m_calculator, option, index); 0111 return m_calculator->minimumSizeHint(); 0112 } 0113 protected: 0114 QList<QWidget*> createItemWidgets(const QModelIndex &index) const override 0115 { 0116 Q_UNUSED(index); 0117 return QList<QWidget*>() << new Palapeli::TriggerListDelegateWidget(itemView()); 0118 } 0119 void updateItemWidgets(const QList<QWidget*> &widgets, const QStyleOptionViewItem& option, const QPersistentModelIndex& index) const override 0120 { 0121 Palapeli::TriggerListDelegateWidget* widget = qobject_cast<Palapeli::TriggerListDelegateWidget*>(widgets[0]); 0122 //adjust widget contents 0123 widget->setIcon(index.data(Qt::DecorationRole).value<QIcon>()); 0124 widget->setText(index.data(Qt::DisplayRole).value<QString>()); 0125 disconnect(widget, nullptr, this, nullptr); 0126 widget->setTrigger(index.data(TriggerRole).value<Palapeli::Trigger>()); 0127 connect(widget, &TriggerListDelegateWidget::triggerChanged, this, &TriggerListDelegate::slotTriggerChanged); 0128 //adjust widget geometry 0129 QRect rect = option.rect; 0130 rect.moveTop(0); 0131 widget->setGeometry(rect); 0132 //adjust widget behavior 0133 widget->setInteractorType((Palapeli::InteractorType) index.data(Palapeli::InteractorTypeRole).toInt()); 0134 } 0135 Q_SIGNALS: 0136 void triggerChanged(); 0137 private Q_SLOTS: 0138 void slotTriggerChanged(const Palapeli::Trigger& newTrigger) 0139 { 0140 const QModelIndex index = focusedIndex(); 0141 QAbstractItemModel* model = const_cast<QAbstractItemModel*>(index.model()); 0142 model->setData(index, QVariant::fromValue(newTrigger), Palapeli::TriggerRole); 0143 Q_EMIT triggerChanged(); 0144 } 0145 private: 0146 Palapeli::TriggerListDelegateWidget* m_calculator; 0147 }; 0148 } 0149 0150 #endif // PALAPELI_TRIGGERLISTVIEW_P_H