File indexing completed on 2024-04-14 04:36:10
0001 /* This file is part of the KDE project 0002 Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr> 0003 Copyright (C) 2004 Alexander Dymo <cloudtemple@mskat.net> 0004 Copyright (C) 2008-2015 Jarosław Staniek <staniek@kde.org> 0005 0006 This library is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Library General Public 0008 License as published by the Free Software Foundation; either 0009 version 2 of the License, or (at your option) any later version. 0010 0011 This library is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 Library General Public License for more details. 0015 0016 You should have received a copy of the GNU Library General Public License 0017 along with this library; see the file COPYING.LIB. If not, write to 0018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #include "combobox.h" 0023 #include "KPropertyEditorView.h" 0024 #include "KPropertyListData.h" 0025 #include "KPropertyUtils.h" 0026 #include "KPropertyUtils_p.h" 0027 #include "KPropertyWidgetsFactory.h" 0028 #include "kproperty_debug.h" 0029 0030 #include <QCompleter> 0031 #include <QGuiApplication> 0032 0033 KPropertyComboBoxEditorOptions::KPropertyComboBoxEditorOptions() 0034 : extraValueAllowed(false) 0035 { 0036 } 0037 0038 KPropertyComboBoxEditorOptions::KPropertyComboBoxEditorOptions( 0039 const KPropertyComboBoxEditorOptions &other) 0040 { 0041 *this = other; 0042 } 0043 0044 KPropertyComboBoxEditorOptions::~KPropertyComboBoxEditorOptions() 0045 { 0046 delete iconProvider; 0047 } 0048 0049 KPropertyComboBoxEditorOptions& KPropertyComboBoxEditorOptions::operator=(const KPropertyComboBoxEditorOptions &other) 0050 { 0051 if (this != &other) { 0052 if (other.iconProvider) { 0053 iconProvider = other.iconProvider->clone(); 0054 } else { 0055 delete iconProvider; 0056 iconProvider = nullptr; 0057 } 0058 extraValueAllowed = other.extraValueAllowed; 0059 } 0060 return *this; 0061 } 0062 0063 0064 class Q_DECL_HIDDEN KPropertyComboBoxEditor::Private 0065 { 0066 public: 0067 Private() 0068 { 0069 } 0070 ~Private() 0071 { 0072 delete completer; 0073 } 0074 KPropertyListData listData; 0075 bool setValueEnabled = true; 0076 KPropertyComboBoxEditorOptions options; 0077 QCompleter *completer = nullptr; 0078 }; 0079 0080 KPropertyComboBoxEditor::KPropertyComboBoxEditor(const KPropertyListData &listData, 0081 const KPropertyComboBoxEditorOptions &options, 0082 QWidget *parent) 0083 : QComboBox(parent), d(new Private) 0084 { 0085 d->options = options; 0086 setEditable(d->options.extraValueAllowed); 0087 setInsertPolicy(QComboBox::NoInsert); 0088 setAutoCompletion(true); 0089 setContextMenuPolicy(Qt::NoContextMenu); 0090 setListData(listData); 0091 connect(this, SIGNAL(activated(int)), this, SLOT(slotValueChanged(int))); 0092 0093 int paddingTop = 2; 0094 int paddingLeft = 3; 0095 const QString style(parent->style()->objectName()); 0096 if (!KPropertyUtilsPrivate::gridLineColor(this).isValid()) { 0097 setFrame(false); 0098 paddingTop = 0; 0099 } 0100 if (style == QLatin1String("windowsvista") || style == QLatin1String("fusion")) { 0101 paddingLeft = 2; 0102 } 0103 0104 //Set the stylesheet to a plain style 0105 QString styleSheet = QString::fromLatin1("QComboBox { \ 0106 %1 \ 0107 padding-top: %2px; padding-left: %3px; }").arg(borderSheet(this)).arg(paddingTop).arg(paddingLeft); 0108 setStyleSheet(styleSheet); 0109 } 0110 0111 KPropertyComboBoxEditor::~KPropertyComboBoxEditor() 0112 { 0113 delete d; 0114 } 0115 0116 //static 0117 QString KPropertyComboBoxEditor::borderSheet(const QWidget *widget) 0118 { 0119 Q_ASSERT(widget); 0120 const QString style(widget->parentWidget() ? widget->parentWidget()->style()->objectName() : QString()); 0121 if (style == QLatin1String("windowsvista") // a hack 0122 || style == QLatin1String("fusion")) 0123 { 0124 return QString(); 0125 } 0126 return QLatin1String("border: 0px; "); 0127 } 0128 0129 bool KPropertyComboBoxEditor::listDataKeysAvailable() const 0130 { 0131 return !d->listData.keys().isEmpty(); 0132 } 0133 0134 QVariant KPropertyComboBoxEditor::value() const 0135 { 0136 if (!listDataKeysAvailable()) 0137 return QVariant(); 0138 0139 const int idx = currentIndex(); 0140 if (idx < 0 || idx >= d->listData.keys().count() 0141 || d->listData.names()[idx].toString() != currentText().trimmed()) 0142 { 0143 if (!d->options.extraValueAllowed || currentText().isEmpty()) 0144 return QVariant(); 0145 return currentText().trimmed(); //trimmed 4 safety 0146 } 0147 return d->listData.keys()[idx]; 0148 } 0149 0150 void KPropertyComboBoxEditor::setValue(const QVariant &value) 0151 { 0152 if (!d->setValueEnabled) 0153 return; 0154 const int idx = d->listData.keys().isEmpty() ? -1 : d->listData.keys().indexOf(value); 0155 // kprDebug() << "**********" << idx << "" << value.toString(); 0156 if (idx >= 0 && idx < count()) { 0157 setCurrentIndex(idx); 0158 } 0159 else { 0160 if (idx < 0) { 0161 if (d->options.extraValueAllowed) { 0162 setCurrentIndex(-1); 0163 setEditText(value.toString()); 0164 } 0165 kprWarning() << "NO SUCH KEY:" << value.toString() 0166 << "property=" << objectName(); 0167 } else { 0168 QStringList list; 0169 for (int i = 0; i < count(); i++) 0170 list += itemText(i); 0171 kprWarning() << "NO SUCH INDEX WITHIN COMBOBOX:" << idx 0172 << "count=" << count() << "value=" << value.toString() 0173 << "property=" << objectName() << "\nActual combobox contents" 0174 << list; 0175 } 0176 setItemText(currentIndex(), QString()); 0177 } 0178 } 0179 0180 void KPropertyComboBoxEditor::fillValues() 0181 { 0182 delete d->completer; 0183 clear(); 0184 if (!listDataKeysAvailable()) 0185 return; 0186 0187 int index = 0; 0188 for (const QString &itemName : d->listData.namesAsStringList()) { 0189 addItem(itemName); 0190 if (d->options.iconProvider) { 0191 QIcon icon = d->options.iconProvider->icon(index); 0192 setItemIcon(index, icon); 0193 } 0194 index++; 0195 } 0196 if (isEditable()) { 0197 d->completer = new QCompleter(d->listData.namesAsStringList()); 0198 d->completer->setWidget(this); 0199 } 0200 } 0201 0202 void KPropertyComboBoxEditor::setListData(const KPropertyListData & listData) 0203 { 0204 d->listData = listData; 0205 fillValues(); 0206 } 0207 0208 void KPropertyComboBoxEditor::slotValueChanged(int) 0209 { 0210 emit commitData( this ); 0211 } 0212 0213 void KPropertyComboBoxEditor::paintEvent( QPaintEvent * event ) 0214 { 0215 QComboBox::paintEvent(event); 0216 KPropertyWidgetsFactory::paintTopGridLine(this); 0217 } 0218 0219 //----------------------- 0220 0221 KPropertyComboBoxDelegate::KPropertyComboBoxDelegate() 0222 { 0223 options()->setBordersVisible(true); 0224 } 0225 0226 QString KPropertyComboBoxDelegate::propertyValueToString(const KProperty* property, const QLocale &locale) const 0227 { 0228 Q_UNUSED(locale) 0229 KPropertyListData *listData = property->listData(); 0230 if (!listData) 0231 return property->value().toString(); 0232 if (property->value().isNull()) 0233 return QString(); 0234 //kprDebug() << "property->value()==" << property->value(); 0235 const int idx = listData->keys().indexOf(property->value()); 0236 //kprDebug() << "idx==" << idx; 0237 if (idx == -1) { 0238 if (!property->option("extraValueAllowed").toBool()) 0239 return QString(); 0240 else 0241 return property->value().toString(); 0242 } 0243 return property->listData()->names()[idx].toString(); 0244 } 0245 0246 QString KPropertyComboBoxDelegate::valueToString(const QVariant& value, const QLocale &locale) const 0247 { 0248 Q_UNUSED(locale) 0249 return value.toString(); 0250 } 0251 0252 QWidget* KPropertyComboBoxDelegate::createEditor( int type, QWidget *parent, 0253 const QStyleOptionViewItem & option, const QModelIndex & index ) const 0254 { 0255 Q_UNUSED(type); 0256 Q_UNUSED(option); 0257 0258 KProperty *property = KPropertyUtils::propertyForIndex(index); 0259 if (!property) { 0260 return nullptr; 0261 } 0262 KPropertyComboBoxEditorOptions options; 0263 options.extraValueAllowed = property->option("extraValueAllowed", false).toBool(); 0264 KPropertyComboBoxEditor *cb = new KPropertyComboBoxEditor(*property->listData(), options, parent); 0265 return cb; 0266 }