File indexing completed on 2024-04-21 04:41:00

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 "cursoredit.h"
0023 #include "KProperty.h"
0024 #include "KPropertyCoreUtils_p.h"
0025 #include "KPropertyListData.h"
0026 #include "KPropertyUtils_p.h"
0027 
0028 #include "xpm/blank_cursor.xpm"
0029 #include "xpm/arrow_cursor.xpm"
0030 #include "xpm/bdiag_cursor.xpm"
0031 #include "xpm/busy_cursor.xpm"
0032 #include "xpm/closedhand_cursor.xpm"
0033 #include "xpm/cross_cursor.xpm"
0034 #include "xpm/fdiag_cursor.xpm"
0035 #include "xpm/forbidden_cursor.xpm"
0036 #include "xpm/hand_cursor.xpm"
0037 #include "xpm/ibeam_cursor.xpm"
0038 #include "xpm/openhand_cursor.xpm"
0039 #include "xpm/sizeall_cursor.xpm"
0040 #include "xpm/sizehor_cursor.xpm"
0041 #include "xpm/sizever_cursor.xpm"
0042 #include "xpm/splith_cursor.xpm"
0043 #include "xpm/splitv_cursor.xpm"
0044 #include "xpm/uparrow_cursor.xpm"
0045 #include "xpm/wait_cursor.xpm"
0046 #include "xpm/whatsthis_cursor.xpm"
0047 
0048 #include <QVariant>
0049 #include <QCursor>
0050 
0051 class CursorListData : public KPropertyListData
0052 {
0053 public:
0054     CursorListData() : KPropertyListData(keysInternal(), stringsInternal())
0055     {
0056     }
0057 
0058     Qt::CursorShape indexToShape(int index) const
0059     {
0060         return static_cast<Qt::CursorShape>(
0061             keys().value(index, static_cast<int>(Qt::ArrowCursor)).toInt());
0062     }
0063 
0064     int shapeToIndex(Qt::CursorShape _shape) const
0065     {
0066         int index = 0;
0067         for (const QVariant &shape : keys()) {
0068             if (shape.toInt() == _shape)
0069                 return index;
0070             index++;
0071         }
0072         return 0;
0073     }
0074 
0075     QPixmap pixmapForIndex(int index, const QPalette& pal, bool transparentBackground = false) const
0076     {
0077         if (index < 0 || index > 18)
0078             index = 0;
0079         QPixmap xpm(m_xpms[index]);
0080         if (transparentBackground)
0081             return xpm;
0082         QPixmap px(xpm.size());
0083         QColor bg( pal.color(QPalette::Base) ); // paint bg with to avoid invisible black-on-black painting
0084         bg.setAlpha(127);
0085         px.fill(bg);
0086         QPainter p(&px);
0087         p.drawPixmap(0, 2, xpm);
0088         return px;
0089     }
0090 private:
0091     static QList<QVariant> keysInternal() {
0092         QList<QVariant> keys;
0093         keys
0094         << int(Qt::BlankCursor)
0095         << int(Qt::ArrowCursor)
0096         << int(Qt::UpArrowCursor)
0097         << int(Qt::CrossCursor)
0098         << int(Qt::WaitCursor)
0099         << int(Qt::IBeamCursor)
0100         << int(Qt::SizeVerCursor)
0101         << int(Qt::SizeHorCursor)
0102         << int(Qt::SizeBDiagCursor)
0103         << int(Qt::SizeFDiagCursor)
0104         << int(Qt::SizeAllCursor)
0105         << int(Qt::SplitVCursor)
0106         << int(Qt::SplitHCursor)
0107         << int(Qt::PointingHandCursor)
0108         << int(Qt::ForbiddenCursor)
0109         << int(Qt::WhatsThisCursor)
0110         << int(Qt::BusyCursor)
0111         << int(Qt::OpenHandCursor)
0112         << int(Qt::ClosedHandCursor);
0113         return keys;
0114     }
0115 
0116     static QStringList stringsInternal() {
0117         QStringList strings;
0118         strings << QObject::tr("No cursor", "Mouse Cursor Shape") //0
0119         << QObject::tr("Arrow", "Mouse Cursor Shape") //1
0120         << QObject::tr("Up arrow", "Mouse Cursor Shape") //2
0121         << QObject::tr("Cross", "Mouse Cursor Shape") //3
0122         << QObject::tr("Waiting", "Mouse Cursor Shape") //4
0123         << QObject::tr("Text cursor", "Mouse Cursor Shape") //5
0124         << QObject::tr("Size vertical", "Mouse Cursor Shape") //6
0125         << QObject::tr("Size horizontal", "Mouse Cursor Shape") //7
0126         << QObject::tr("Size slash", "Mouse Cursor Shape") //8
0127         << QObject::tr("Size backslash", "Mouse Cursor Shape") //9
0128         << QObject::tr("Size all", "Mouse Cursor Shape") //10
0129         << QObject::tr("Split vertical", "Mouse Cursor Shape") //11
0130         << QObject::tr("Split horizontal", "Mouse Cursor Shape") //12
0131         << QObject::tr("Pointing hand", "Mouse Cursor Shape") //13
0132         << QObject::tr("Forbidden", "Mouse Cursor Shape") //14
0133         << QObject::tr("What's this?", "Mouse Cursor Shape") //15
0134         << QObject::tr("Busy", "Mouse Cursor Shape") //16
0135         << QObject::tr("Open hand", "Mouse Cursor Shape") //17
0136         << QObject::tr("Closed hand", "Mouse Cursor Shape"); //18
0137         return strings;
0138     }
0139     static const char * const * const m_xpms[];
0140 };
0141 
0142 const char * const * const CursorListData::m_xpms[] =
0143 {
0144     blank_cursor_xpm,
0145     arrow_cursor_xpm,
0146     uparrow_cursor_xpm,
0147     cross_cursor_xpm,
0148     wait_cursor_xpm,
0149     ibeam_cursor_xpm,
0150     sizever_cursor_xpm,
0151     sizehor_cursor_xpm,
0152     bdiag_cursor_xpm,
0153     fdiag_cursor_xpm,
0154     sizeall_cursor_xpm,
0155     splitv_cursor_xpm,
0156     splith_cursor_xpm,
0157     hand_cursor_xpm,
0158     forbidden_cursor_xpm,
0159     whatsthis_cursor_xpm,
0160     busy_cursor_xpm,
0161     openhand_cursor_xpm,
0162     closedhand_cursor_xpm
0163 };
0164 
0165 Q_GLOBAL_STATIC(CursorListData, s_cursorListData)
0166 
0167 //----------------------
0168 
0169 class CursorIconProvider : public KPropertyComboBoxEditorIconProviderInterface
0170 {
0171 public:
0172     explicit CursorIconProvider(QWidget* parent) : m_parent(parent) {}
0173     QIcon icon(int index) const override
0174     {
0175           return s_cursorListData->pixmapForIndex(index, m_parent->palette());
0176     }
0177     KPropertyComboBoxEditorIconProviderInterface *clone() const override
0178     {
0179         return new CursorIconProvider(m_parent);
0180     }
0181     QWidget* m_parent;
0182 };
0183 
0184 //----------------------
0185 
0186 static KPropertyComboBoxEditorOptions initComboBoxOptions(QWidget* parent)
0187 {
0188     KPropertyComboBoxEditorOptions options;
0189     options.iconProvider = new CursorIconProvider(parent);
0190     return options;
0191 }
0192 
0193 class Q_DECL_HIDDEN KPropertyCursorEditor::Private
0194 {
0195 public:
0196     Private()
0197     {
0198     }
0199 };
0200 
0201 KPropertyCursorEditor::KPropertyCursorEditor(QWidget *parent)
0202         : KPropertyComboBoxEditor(*s_cursorListData, initComboBoxOptions( this ), parent),
0203           d(new Private)
0204 {
0205     int paddingTop = 1;
0206     int paddingLeft = 2;
0207     const QString style(parent->style()->objectName());
0208     if (!KPropertyUtilsPrivate::gridLineColor(this).isValid()) {
0209         setFrame(false);
0210         paddingTop = 0;
0211     }
0212     if (style == QLatin1String("windowsvista") || style == QLatin1String("fusion")) {
0213         paddingLeft = 1;
0214     }
0215     QString styleSheet = QString::fromLatin1("QComboBox { \
0216         %1 \
0217         padding-top: %2px; padding-left: %3px; }").arg(KPropertyComboBoxEditor::borderSheet(this))
0218             .arg(paddingTop).arg(paddingLeft);
0219     setStyleSheet(styleSheet);
0220 }
0221 
0222 KPropertyCursorEditor::~KPropertyCursorEditor()
0223 {
0224     delete d;
0225 }
0226 
0227 QCursor KPropertyCursorEditor::cursorValue() const
0228 {
0229     return QCursor((Qt::CursorShape)KPropertyComboBoxEditor::value().toInt());
0230 }
0231 
0232 void KPropertyCursorEditor::setCursorValue(const QCursor &value)
0233 {
0234     KPropertyComboBoxEditor::setValue( (int)(value.shape()) );
0235 }
0236 
0237 //---------------
0238 
0239 KPropertyCursorDelegate::KPropertyCursorDelegate()
0240 {
0241     options()->setBordersVisible(true);
0242 }
0243 
0244 QWidget * KPropertyCursorDelegate::createEditor( int type, QWidget *parent,
0245     const QStyleOptionViewItem & option, const QModelIndex & index ) const
0246 {
0247     Q_UNUSED(type);
0248     Q_UNUSED(option);
0249     Q_UNUSED(index);
0250     return new KPropertyCursorEditor(parent);
0251 }
0252 
0253 void KPropertyCursorDelegate::paint( QPainter * painter,
0254     const QStyleOptionViewItem & option, const QModelIndex & index ) const
0255 {
0256     const KPropertyUtilsPrivate::PainterSaver saver(painter);
0257     int comboIndex = s_cursorListData->shapeToIndex( index.data(Qt::EditRole).value<QCursor>().shape() );
0258     int pmSize = (option.rect.height() >= 32) ? 32 : 16;
0259     const QPixmap pm( s_cursorListData->pixmapForIndex(comboIndex, option.palette)
0260         .scaled(pmSize, pmSize, Qt::KeepAspectRatio, Qt::SmoothTransformation) );
0261     QPoint pmPoint(option.rect.topLeft() + QPoint(2, 1));
0262     painter->drawPixmap(pmPoint, pm);
0263     QRect r(option.rect);
0264     r.setLeft(7 + r.left() + 1 + pm.width());
0265     painter->drawText(r, Qt::AlignVCenter | Qt::AlignLeft, valueToString(index.data(Qt::EditRole), QLocale()));
0266 }
0267 
0268 QString KPropertyCursorDelegate::valueToString(const QVariant& value, const QLocale &locale) const
0269 {
0270     const Qt::CursorShape shape = value.value<QCursor>().shape();
0271     if (locale.language() == QLocale::C) {
0272         return KPropertyUtils::keyForEnumValue("CursorShape", shape);
0273     }
0274     const int comboIndex = s_cursorListData->shapeToIndex(shape);
0275     return s_cursorListData->names().value(comboIndex).toString();
0276 }