File indexing completed on 2024-11-10 04:16:15
0001 /* This file is part of the KDE project 0002 Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr> 0003 Copyright (C) 2008-2018 Jarosław Staniek <staniek@kde.org> 0004 Copyright (C) 2018 Dmitry Baryshev <dmitrymq@gmail.com> 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 "window.h" 0023 0024 #include <KProperty> 0025 #include <KPropertyComposedUrl> 0026 #include <KPropertyListData> 0027 #include <KPropertyEditorView> 0028 0029 #include <QDate> 0030 #include <QDateTime> 0031 #include <QPixmap> 0032 #include <QCursor> 0033 #include <QApplication> 0034 #include <QDesktopWidget> 0035 #include <QVBoxLayout> 0036 #include <QIcon> 0037 #include <QCommandLineParser> 0038 #include <QDebug> 0039 #include <QDate> 0040 #include <QCheckBox> 0041 #include <QUrl> 0042 #include <QDir> 0043 0044 Window::Window() 0045 : QWidget() 0046 , m_set(this) 0047 , m_flatOption("flat", QCoreApplication::translate("main", 0048 "Flat display: do not display groups\n(useful for testing)")) 0049 , m_fontSizeOption("font-size", QCoreApplication::translate("main", 0050 "Set font size to <size> (in points)\n(useful for testing whether editors keep the font settings)"), 0051 QCoreApplication::translate("main", "size")) 0052 , m_propertyOption("property", QCoreApplication::translate("main", 0053 "Display only specified property\n(useful when we want to focus on testing a single\nproperty editor)"), 0054 QCoreApplication::translate("main", "name")) 0055 , m_roOption("ro", QCoreApplication::translate("main", 0056 "Set all properties as read-only:\n(useful for testing read-only mode)")) 0057 { 0058 setObjectName("kpropertyexamplewindow"); 0059 setWindowIcon(QIcon::fromTheme("document-properties")); 0060 m_parser.setApplicationDescription(QCoreApplication::translate("main", "An example application for the KProperty library.")); 0061 m_parser.addHelpOption(); 0062 m_parser.addVersionOption(); 0063 parseCommandLine(); 0064 0065 const QString singleProperty = m_parser.value(m_propertyOption); 0066 bool ok; 0067 const int fontSize = m_parser.value(m_fontSizeOption).toInt(&ok); 0068 if (fontSize > 0 && ok) { 0069 QFont f(font()); 0070 f.setPointSize(fontSize); 0071 setFont(f); 0072 } 0073 0074 /* First, create a KPropertySet which will hold the properties. */ 0075 connect(&m_set, &KPropertySet::propertyChanged, this, &Window::propertyChanged); 0076 0077 KProperty *p = nullptr; 0078 m_set.setReadOnly(m_parser.isSet(m_roOption)); 0079 QByteArray group; 0080 const bool addGroups = !m_parser.isSet(m_flatOption); 0081 if (addGroups) { 0082 group = "BasicGroup"; 0083 m_set.setGroupCaption(group, "Basic Properties"); 0084 } 0085 if (singleProperty.isEmpty() || singleProperty=="String") { 0086 m_set.addProperty(p = new KProperty("String", "String"), group); 0087 p->setValueSyncPolicy(KProperty::ValueSyncPolicy::Auto); 0088 p->setReadOnly(false); // this should not work: 0089 // - not needed if the property set is read-write 0090 // - ignored if the property set is read-only 0091 } 0092 if (singleProperty.isEmpty() || singleProperty=="MultiLine") { 0093 m_set.addProperty(p = new KProperty("MultiLine", "Multi\nLine\nContent"), group); 0094 p->setValueSyncPolicy(KProperty::ValueSyncPolicy::Auto); 0095 p->setOption("multiLine", true); 0096 } 0097 0098 if (singleProperty.isEmpty() || singleProperty=="Int") { 0099 m_set.addProperty(new KProperty("Int", 2, "Int"), group); 0100 } 0101 if (singleProperty.isEmpty() || singleProperty=="Double") { 0102 m_set.addProperty(p = new KProperty("Double", 3.14159, "Double"), group); 0103 p->setOption("precision", 4); // will round to 3.1416 0104 } 0105 if (singleProperty.isEmpty() || singleProperty=="Bool") { 0106 m_set.addProperty(new KProperty("Bool", QVariant(true), "Bool"), group); 0107 } 0108 if (singleProperty.isEmpty() || singleProperty=="NullBool") { 0109 m_set.addProperty(new KProperty("NullBool", QVariant(), "Null Bool", QString(), KProperty::Bool), group); 0110 } 0111 if (singleProperty.isEmpty() || singleProperty=="3-State") { 0112 m_set.addProperty(p = new KProperty("3-State", QVariant(), "3 States", QString(), 0113 KProperty::Bool), group); 0114 p->setOption("3State", true); 0115 } 0116 if (singleProperty.isEmpty() || singleProperty=="Date") { 0117 m_set.addProperty(p = new KProperty("Date", QDate::currentDate(), "Date"), group); 0118 p->setIconName("date"); 0119 } 0120 if (singleProperty.isEmpty() || singleProperty=="Time") { 0121 m_set.addProperty(new KProperty("Time", QTime::currentTime(), "Time"), group); 0122 } 0123 if (singleProperty.isEmpty() || singleProperty=="DateTime") { 0124 m_set.addProperty(new KProperty("DateTime", QDateTime::currentDateTime(), "Date/Time"), group); 0125 } 0126 0127 QStringList name_list({"First Item", "Second Item", "Third Item"}); //strings 0128 if (singleProperty.isEmpty() || singleProperty=="List") { 0129 const QStringList keys({"1stitem", "2nditem", "3rditem"}); 0130 KPropertyListData *listData = new KPropertyListData(keys, name_list); 0131 m_set.addProperty(new KProperty("List", listData, QVariant(keys[1]), "List"), group); 0132 } 0133 0134 QVariantList list_keys({1, 2, 3}); 0135 if (singleProperty.isEmpty() || singleProperty=="List2") { 0136 // A valueFromList property matching strings with ints (could be any type supported by QVariant) 0137 KPropertyListData *listData = new KPropertyListData; 0138 listData->setKeys(list_keys); 0139 listData->setNamesAsStringList(name_list); 0140 m_set.addProperty(new KProperty("List2", listData, list_keys.last(), "List 2"), group); 0141 } 0142 if (singleProperty.isEmpty() || singleProperty=="EditableList") { 0143 // A valueFromList property matching strings with ints (could be any type supported by QVariant) 0144 KPropertyListData *listData = new KPropertyListData; 0145 listData->setKeys(list_keys); 0146 listData->setNamesAsStringList(name_list); 0147 p = new KProperty("EditableList", listData, list_keys.first(), "Editable List"); 0148 p->setOption("extraValueAllowed", true); 0149 m_set.addProperty(p, group); 0150 } 0151 0152 // Complex 0153 if (addGroups) { 0154 group = "ComposedGroup"; 0155 m_set.setGroupCaption(group, "Composed Properties"); 0156 } 0157 if (singleProperty.isEmpty() || singleProperty=="Point") { 0158 m_set.addProperty(new KProperty("Point", QPoint(3, 4), "Point"), group); 0159 } 0160 if (singleProperty.isEmpty() || singleProperty=="Size") { 0161 m_set.addProperty(new KProperty("Size", QSize(10, 20), "Size"), group); 0162 } 0163 if (singleProperty.isEmpty() || singleProperty=="Rect") { 0164 m_set.addProperty(new KProperty("Rect", QRect(5,11,100,200), "Rect"), group); 0165 } 0166 if (singleProperty.isEmpty() || singleProperty=="PointF") { 0167 m_set.addProperty(new KProperty("PointF", QPointF(3.14, 4.15), "PointF"), group); 0168 } 0169 if (singleProperty.isEmpty() || singleProperty=="SizeF") { 0170 m_set.addProperty(new KProperty("SizeF", QSizeF(1.1, 2.45), "SizeF"), group); 0171 } 0172 if (singleProperty.isEmpty() || singleProperty == "RectF") { 0173 m_set.addProperty( 0174 new KProperty("RectF", QRectF(0.1, 0.5, 10.72, 18.21), "RectF"), group); 0175 } 0176 0177 // With suffixes and prefixes 0178 if (addGroups) { 0179 group = "PrefixesSuffixesGroup"; 0180 m_set.setGroupCaption(group, "Prefixes & Suffixes"); 0181 } 0182 if (singleProperty.isEmpty() || singleProperty=="dollars") { 0183 m_set.addProperty(p = new KProperty("dollars", 100, "Dollars"), group); 0184 p->setOption("prefix", "$"); 0185 } 0186 if (singleProperty.isEmpty() || singleProperty == "billions") { 0187 m_set.addProperty(p = new KProperty("billions", 5.0, "Billions"), group); 0188 p->setOption("prefix", "£"); 0189 p->setOption("suffix", "bn"); 0190 // default precision == 2 and step == 0.01 0191 } 0192 if (singleProperty.isEmpty() || singleProperty == "PointF-mm") { 0193 m_set.addProperty( 0194 p = new KProperty("PointF-mm", QPointF(2.5, 3.5), "PointF [mm]"), group); 0195 p->setOption("suffix", "mm"); 0196 p->setOption("step", 0.1); 0197 p->setOption("precision", 2); 0198 } 0199 if (singleProperty.isEmpty() || singleProperty == "SizeF-dm") { 0200 m_set.addProperty( 0201 p = new KProperty("SizeF-dm", QSizeF(7.0, 6.5), "SizeF [dm]"), group); 0202 p->setOption("suffix", "dm"); 0203 p->setOption("step", 0.001); 0204 p->setOption("precision", 3); 0205 } 0206 if (singleProperty.isEmpty() || singleProperty=="RectF-px") { 0207 m_set.addProperty( 0208 p = new KProperty("RectF-px", QRectF(21.2, 22.2, 9.1, 1.0), "RectF [px]"), 0209 group); 0210 p->setOption("suffix", "px"); 0211 p->setOption("step", 0.1); 0212 p->setOption("precision", 1); 0213 } 0214 0215 // Limits 0216 if (addGroups) { 0217 group = "LimitsGroup"; 0218 m_set.setGroupCaption(group, "Limits"); 0219 } 0220 if (singleProperty.isEmpty() || singleProperty=="uint") { 0221 m_set.addProperty(new KProperty("uint", 3, "Unsigned Int", QString(), KProperty::UInt), group); 0222 } 0223 if (singleProperty.isEmpty() || singleProperty=="uint+mintext") { 0224 m_set.addProperty(p = new KProperty("uint+mintext", 0, "Unsigned Int\n+min.text", QString(), KProperty::UInt), group); 0225 p->setOption("minValueText", "Minimum value"); 0226 } 0227 if (singleProperty.isEmpty() || singleProperty=="limit0_10") { 0228 m_set.addProperty(p = new KProperty("limit0_10", 9, "0..10", QString(), KProperty::UInt), group); 0229 p->setOption("max", 10); 0230 } 0231 if (singleProperty.isEmpty() || singleProperty == "limit1_5+mintext") { 0232 // This is a good test for fixing value out of range: "Could not assign value 9 larger than 0233 // maximum 5 -- setting to 5" warning is displayed and 5 is assigned. 0234 m_set.addProperty(p = new KProperty("limit1_5+mintext", 9, "1..5\n+mintext", QString(), 0235 KProperty::UInt), group); 0236 p->setOption("min", 1); 0237 p->setOption("max", 5); 0238 p->setOption("minValueText", "Minimum value"); 0239 } 0240 if (singleProperty.isEmpty() || singleProperty=="negative-int") { 0241 m_set.addProperty(p = new KProperty("negative-int", -2, "Negative Int", QString(), KProperty::Int), group); 0242 p->setOption("max", -1); 0243 } 0244 if (singleProperty.isEmpty() || singleProperty=="double-unlimited") { 0245 m_set.addProperty(p = new KProperty("double-unlimited", -1.11, "Double unlimited"), group); 0246 p->setOption("min", KPROPERTY_MIN_PRECISE_DOUBLE); 0247 p->setOption("precision", 1); 0248 p->setOption("step", 0.1); 0249 } 0250 if (singleProperty.isEmpty() || singleProperty=="double-negative") { 0251 m_set.addProperty(p = new KProperty("double-negative", -0.2, "Double negative"), group); 0252 p->setOption("min", KPROPERTY_MIN_PRECISE_DOUBLE); 0253 p->setOption("max", -0.1); 0254 p->setOption("precision", 1); 0255 p->setOption("step", 0.1); 0256 } 0257 if (singleProperty.isEmpty() || singleProperty=="double-minus1-0+mintext") { 0258 // This is a good test for fixing value out of range: "Could not assign value -9.0 smaller than 0259 // minimum -1.0 -- setting to -1.0" warning is displayed and -1.0 is assigned. 0260 m_set.addProperty(p = new KProperty("double-minus1-0+mintext", -9.0, "Double -1..0\n+mintext"), group); 0261 p->setOption("min", -1.0); 0262 p->setOption("max", 0.0); 0263 p->setOption("precision", 1); 0264 p->setOption("step", 0.1); 0265 p->setOption("minValueText", "Minimum value"); 0266 } 0267 0268 // Appearance 0269 if (addGroups) { 0270 group = "AppearanceGroup"; 0271 m_set.setGroupCaption(group, "Appearance"); 0272 m_set.setGroupIconName(group, "appearance"); 0273 } 0274 if (singleProperty.isEmpty() || singleProperty=="Color") { 0275 m_set.addProperty(new KProperty("Color", palette().color(QPalette::Active, QPalette::Background), "Color"), group); 0276 } 0277 if (singleProperty.isEmpty() || singleProperty=="Pixmap") { 0278 QPixmap pm(QIcon::fromTheme("network-wired").pixmap(QSize(64, 64))); 0279 m_set.addProperty(p = new KProperty("Pixmap", pm, "Pixmap"), group); 0280 p->setIconName("kpaint"); 0281 } 0282 if (singleProperty.isEmpty() || singleProperty=="Font") { 0283 QFont myFont("Times New Roman", 12); 0284 myFont.setUnderline(true); 0285 m_set.addProperty(p = new KProperty("Font", myFont, "Font"), group); 0286 p->setIconName("fonts"); 0287 } 0288 if (singleProperty.isEmpty() || singleProperty=="Cursor") { 0289 m_set.addProperty(new KProperty("Cursor", QCursor(Qt::WaitCursor), "Cursor"), group); 0290 } 0291 if (singleProperty.isEmpty() || singleProperty=="LineStyle") { 0292 m_set.addProperty(new KProperty("LineStyle", 3, "Line Style", QString(), 0293 KProperty::LineStyle), group); 0294 } 0295 if (singleProperty.isEmpty() || singleProperty=="SizePolicy") { 0296 QSizePolicy sp(sizePolicy()); 0297 sp.setHorizontalStretch(1); 0298 sp.setVerticalStretch(2); 0299 m_set.addProperty(new KProperty("SizePolicy", sp, "Size Policy"), group); 0300 } 0301 if (singleProperty.isEmpty() || singleProperty=="Invisible") { 0302 m_set.addProperty(p = new KProperty("Invisible", "I am invisible", "Invisible"), group); 0303 p->setVisible(false); 0304 } 0305 if (singleProperty.isEmpty() || singleProperty=="Url") { 0306 m_set.addProperty(p = new KProperty("Url", QUrl("https://community.kde.org/KProperty"), "Url"), group); 0307 } 0308 if (singleProperty.isEmpty() || singleProperty=="RelativeComposedUrl") { 0309 const KPropertyComposedUrl composedUrl(QUrl::fromLocalFile(QApplication::applicationDirPath()), 0310 QLatin1String("data/icons/kproperty_breeze.rcc")); 0311 p = new KProperty("RelativeComposedUrl", QVariant::fromValue(composedUrl), "ComposedUrl with\nrelative path", 0312 QString(), KProperty::ComposedUrl); 0313 m_set.addProperty(p, group); 0314 } 0315 if (singleProperty.isEmpty() || singleProperty=="AbsoluteComposedUrl") { 0316 const KPropertyComposedUrl composedUrl(QUrl::fromLocalFile(QApplication::applicationDirPath()), 0317 QUrl("https://community.kde.org/KProperty")); 0318 p = new KProperty("AbsoluteComposedUrl", QVariant::fromValue(composedUrl), "ComposedUrl with\nabsolute URL", 0319 QString(), KProperty::ComposedUrl); 0320 m_set.addProperty(p, group); 0321 } 0322 if (singleProperty.isEmpty() || singleProperty=="ExistingFile") { 0323 m_set.addProperty(p = new KProperty("ExistingFile", 0324 QUrl::fromLocalFile(QCoreApplication::applicationFilePath()), "Existing\nFile"), group); 0325 p->setOption("fileMode", "existingFile"); 0326 } 0327 if (singleProperty.isEmpty() || singleProperty=="OverwriteFile") { 0328 m_set.addProperty(p = new KProperty("OverwriteFile", 0329 QUrl::fromLocalFile(QDir::homePath() + "/" + QCoreApplication::applicationName() + ".txt"), 0330 "New File or\nOverwrite Existing"), group); 0331 p->setOption("confirmOverwrites", true); 0332 } 0333 if (singleProperty.isEmpty() || singleProperty=="Dir") { 0334 m_set.addProperty(p = new KProperty("Dir", QUrl::fromLocalFile(QDir::homePath()), "Dir"), group); 0335 p->setOption("fileMode", "dirsOnly"); 0336 } 0337 if (singleProperty.isEmpty() || singleProperty=="ReadOnly") { 0338 m_set.addProperty(p = new KProperty("Read-Only", "Read-only string"), group); 0339 p->setReadOnly(true); 0340 } 0341 0342 // Properties for testing tooltips 0343 if (singleProperty.isEmpty() || singleProperty == "StaticToolTip") { 0344 m_set.addProperty(new KProperty("StaticToolTip", "Some value", "Static Tooltip", 0345 "This is a static tooltip based on value of KProperty::description()"), group); 0346 m_set.addProperty( 0347 m_dynamicToolTipProperty = new KProperty("DynamicToolTip", "Some dynamic value", 0348 "Dynamic Tooltip"), group); 0349 propertyChanged(m_set, *m_dynamicToolTipProperty); // this updates description 0350 } 0351 0352 QVBoxLayout *lyr = new QVBoxLayout(this); 0353 m_editorView = new KPropertyEditorView(this); 0354 m_editorView->setToolTipsVisible(true); 0355 lyr->addWidget(m_editorView); 0356 m_editorView->changeSet(&m_set); 0357 m_editorView->resizeColumnToContents(0); 0358 lyr->addSpacing(lyr->spacing()); 0359 0360 QHBoxLayout *hlyr = new QHBoxLayout; 0361 lyr->addLayout(hlyr); 0362 0363 QCheckBox *showGrid = new QCheckBox("Show grid"); 0364 showGrid->setChecked(true); 0365 connect(showGrid, &QCheckBox::stateChanged, this, &Window::showGrid); 0366 hlyr->addWidget(showGrid); 0367 0368 QCheckBox *showFrame = new QCheckBox("Show frame"); 0369 showFrame->setChecked(true); 0370 connect(showFrame, &QCheckBox::stateChanged, this, &Window::showFrame); 0371 hlyr->addWidget(showFrame); 0372 0373 QCheckBox *showGroups = new QCheckBox("Show groups"); 0374 if (addGroups) { 0375 connect(showGroups, &QCheckBox::toggled, m_editorView, &KPropertyEditorView::setGroupsVisible); 0376 showGroups->setChecked(m_editorView->groupsVisible()); 0377 } else { 0378 showGroups->setEnabled(false); 0379 } 0380 hlyr->addWidget(showGroups); 0381 0382 QCheckBox *showToolTips = new QCheckBox("Show tooltips"); 0383 connect(showToolTips, &QCheckBox::toggled, m_editorView, &KPropertyEditorView::setToolTipsVisible); 0384 showToolTips->setChecked(m_editorView->toolTipsVisible()); 0385 hlyr->addWidget(showToolTips); 0386 0387 QCheckBox *readOnly = new QCheckBox("Read-only"); 0388 connect(readOnly, &QCheckBox::toggled, &m_set, &KPropertySet::setReadOnly); 0389 readOnly->setChecked(m_set.isReadOnly()); 0390 hlyr->addWidget(readOnly); 0391 0392 hlyr->addStretch(1); 0393 resize(400, qApp->desktop()->height() - 200); 0394 m_editorView->setFocus(); 0395 qDebug() << m_set; 0396 } 0397 0398 Window::~Window() 0399 { 0400 } 0401 0402 void Window::parseCommandLine() 0403 { 0404 m_parser.addOption(m_flatOption); 0405 m_parser.addOption(m_fontSizeOption); 0406 m_parser.addOption(m_propertyOption); 0407 m_parser.addOption(m_roOption); 0408 m_parser.process(*(QCoreApplication::instance())); 0409 } 0410 0411 void Window::showGrid(int state) 0412 { 0413 m_editorView->setGridLineColor( 0414 state == Qt::Checked ? KPropertyEditorView::defaultGridLineColor() : QColor()); 0415 } 0416 0417 void Window::showFrame(int state) 0418 { 0419 m_editorView->setFrameStyle(state == Qt::Checked ? QFrame::Box : QFrame::NoFrame); 0420 } 0421 0422 void Window::propertyChanged(KPropertySet& set, KProperty& property) 0423 { 0424 Q_UNUSED(set) 0425 if (&property == m_dynamicToolTipProperty) { 0426 property.setDescription(QString::fromLatin1("This is a dynamic tooltip based on value of " 0427 "\"%1\" property which is currently \"%2\"") 0428 .arg(property.caption(), property.value().toString())); 0429 } 0430 }