1 /*************************************************************************** 2 * file klfadvancedconfigeditor_p.h 3 * This file is part of the KLatexFormula Project. 4 * Copyright (C) 2012 by Philippe Faist 5 * philippe.faist at bluewin.ch 6 * * 7 * This program is free software; you can redistribute it and/or modify * 8 * it under the terms of the GNU General Public License as published by * 9 * the Free Software Foundation; either version 2 of the License, or * 10 * (at your option) any later version. * 11 * * 12 * This program is distributed in the hope that it will be useful, * 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 15 * GNU General Public License for more details. * 16 * * 17 * You should have received a copy of the GNU General Public License * 18 * along with this program; if not, write to the * 19 * Free Software Foundation, Inc., * 20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 21 ***************************************************************************/ 22 /* $Id: klfadvancedconfigeditor_p.h 988 2017-01-02 09:25:34Z phfaist $ */ 23 24 /** \file 25 * This header contains (in principle private) auxiliary classes for 26 * library routines defined in klfadvancedconfigeditor.cpp */ 27 28 #ifndef KLFADVANCEDCONFIGEDITOR_P_H 29 #define KLFADVANCEDCONFIGEDITOR_P_H 30 31 #include <QAbstractItemModel> 32 #include <QStyledItemDelegate> 33 #include <QLineEdit> 34 #include <QStandardItemModel> 35 #include <QMessageBox> 36 #include <QFontDialog> 37 38 39 #include <klfdefs.h> 40 #include <klfdatautil.h> 41 42 #include "klfadvancedconfigeditor.h" 43 #include <ui_klfadvancedconfigeditor.h> 44 45 46 #define CONFIG_VIEW_ROLE_PROPNAME (Qt::UserRole) 47 #define CONFIG_VIEW_ROLE_TYPENAME (Qt::UserRole+1) 48 #define CONFIG_VIEW_ROLE_INNERTYPENAME (Qt::UserRole+2) 49 50 51 // --------------------------------------------- 52 53 class KLFAdvancedConfigItemDelegate : public QStyledItemDelegate 54 { 55 Q_OBJECT 56 public: KLFAdvancedConfigItemDelegate(QObject * parent)57 KLFAdvancedConfigItemDelegate(QObject *parent) : QStyledItemDelegate(parent) 58 { 59 } 60 createEditor(QWidget * parent,const QStyleOptionViewItem & option,const QModelIndex & index)61 virtual QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem& option, 62 const QModelIndex& index) const 63 { 64 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ; 65 if (index.column() < 2) 66 return QStyledItemDelegate::createEditor(parent, option, index); 67 return new QLineEdit(parent); 68 } 69 setEditorData(QWidget * editor,const QModelIndex & index)70 virtual void setEditorData(QWidget *editor, const QModelIndex& index) const 71 { 72 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ; 73 klfDbg("editor="<<editor<<", index="<<index) ; 74 75 if (index.column() < 2) 76 return QStyledItemDelegate::setEditorData(editor, index); 77 // else: 78 QLineEdit * e = qobject_cast<QLineEdit*>(editor); 79 KLF_ASSERT_NOT_NULL(e, "Editor is NULL or not a QLineEdit!", return ; ) ; 80 QVariant value = index.data(Qt::EditRole); 81 klfDbg("value is "<<value) ; 82 e->setText(klfSaveVariantToText(value)); 83 } 84 setModelData(QWidget * editor,QAbstractItemModel * model,const QModelIndex & index)85 virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const 86 { 87 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ; 88 klfDbg("editor="<<editor<<", model="<<model<<", index="<<index) ; 89 90 if (index.column() < 2) { 91 klfDbg("letting base class handle this.") ; 92 return QStyledItemDelegate::setModelData(editor, model, index); 93 } 94 // else: 95 QLineEdit * e = qobject_cast<QLineEdit*>(editor); 96 KLF_ASSERT_NOT_NULL(e, "Editor is NULL or not a QLineEdit!", return ; ) ; 97 KLF_ASSERT_NOT_NULL(model, "Model is NULL!", return ; ) ; 98 QByteArray datavalue = e->text().toLatin1(); 99 QByteArray typname = model->data(index, CONFIG_VIEW_ROLE_TYPENAME).toByteArray(); 100 QByteArray innertypname = model->data(index, CONFIG_VIEW_ROLE_INNERTYPENAME).toByteArray(); 101 QVariant value = klfLoadVariantFromText(datavalue, typname, innertypname); 102 klfDbg("value is "<<value) ; 103 model->setData(index, value, Qt::EditRole); 104 } 105 106 protected: 107 editorEvent(QEvent * event,QAbstractItemModel * model,const QStyleOptionViewItem & option,const QModelIndex & index)108 virtual bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem& option, 109 const QModelIndex& index) 110 { 111 // Note: editor closes and doesn't apply new value for colors, which open a separate popup 112 // widget... (MAC OS X ONLY) SOLUTION: use an actual dialog as the widget, this is handled nicely. 113 return QStyledItemDelegate::editorEvent(event, model, option, index); 114 } 115 }; 116 117 118 // --------------------------------------------------------------- 119 120 121 struct KLFAdvancedConfigEditorPrivate : public QObject 122 { 123 Q_OBJECT 124 public: KLF_PRIVATE_QOBJ_HEADKLFAdvancedConfigEditorPrivate125 KLF_PRIVATE_QOBJ_HEAD(KLFAdvancedConfigEditor, QObject) 126 { 127 pConfigBase = NULL; 128 pCurrentInternalUpdate = false; 129 _are_resetting_config = false; 130 } 131 132 KLFConfigBase * pConfigBase; 133 134 bool _are_resetting_config; 135 136 QStandardItemModel *pConfModel; 137 138 bool pCurrentInternalUpdate; 139 140 public slots: // public is just for us... the class is still private :) 141 configEntryEditedKLFAdvancedConfigEditorPrivate142 void configEntryEdited(QStandardItem *item) 143 { 144 KLF_DEBUG_BLOCK(KLF_FUNC_NAME); 145 klfDbg( "item="<<item<<"" ) ; 146 KLF_ASSERT_NOT_NULL(item, "item is NULL!", return; ) ; 147 148 if (pCurrentInternalUpdate) 149 return; 150 151 if (item->column() < 1 || item->column() > 2) 152 return; // false edit 153 154 klfDbg("config entry edited..."); 155 156 QVariant value = item->data(Qt::EditRole); 157 QString pname = item->data(CONFIG_VIEW_ROLE_PROPNAME).toString(); 158 KLFConfigPropBase *p = pConfigBase->property(pname); 159 KLF_ASSERT_NOT_NULL(p, "Property is NULL!", return; ) ; 160 QVariant oldvalue = p->toVariant(); 161 162 if (value == oldvalue) { 163 // never mind, the user didn't change anything. 164 // but still update the row, because otherwise the wrong string representation is shown (why?) 165 updateConfigEntry(item->row()); 166 return; 167 } 168 169 QMessageBox msgBox; 170 msgBox.setText(tr("You are changing an advanced config setting. Please confirm your action.")); 171 msgBox.setIcon(QMessageBox::Information); 172 msgBox.setInformativeText(tr("Change config entry %1 from %2 to %3?") 173 .arg( "<b>"+pname+"</b>" , 174 "<b>"+klfSaveVariantToText(oldvalue)+"</b> <i>("+oldvalue.typeName()+")</i>" , 175 "<b>"+klfSaveVariantToText(value)+"</b> <i>("+value.typeName()+")</i>")); 176 msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Cancel); 177 msgBox.setDefaultButton(QMessageBox::Save); 178 int r = msgBox.exec(); 179 if (r != QMessageBox::Save) { 180 updateConfigEntry(item->row()); 181 return; 182 } 183 184 r = p->setValue(value); 185 if ( ! r ) { 186 QMessageBox::critical(K, tr("Error"), 187 tr("Failed to set config entry `%1'.").arg(pname)); 188 } 189 updateConfigEntry(item->row()); 190 if (!_are_resetting_config) 191 emit K->configModified(pname); 192 } 193 194 #define EDITTYPE_TEST_FOR(t, x) if ((t) == x) { return true; } is_editable_typeKLFAdvancedConfigEditorPrivate195 static bool is_editable_type(int t) 196 { 197 EDITTYPE_TEST_FOR(t, QVariant::Bool); 198 EDITTYPE_TEST_FOR(t, QVariant::Double); 199 EDITTYPE_TEST_FOR(t, QVariant::Int); 200 EDITTYPE_TEST_FOR(t, QVariant::UInt); 201 EDITTYPE_TEST_FOR(t, QVariant::Date); 202 EDITTYPE_TEST_FOR(t, QVariant::Time); 203 EDITTYPE_TEST_FOR(t, QVariant::DateTime); 204 EDITTYPE_TEST_FOR(t, QVariant::String); 205 EDITTYPE_TEST_FOR(t, QVariant::Color); 206 EDITTYPE_TEST_FOR(t, QVariant::Font); 207 return false; 208 } 209 updateConfigViewKLFAdvancedConfigEditorPrivate210 void updateConfigView() 211 { 212 pConfModel->setRowCount(0); 213 int k; 214 QStringList props = pConfigBase->propertyList(); 215 QPalette pal = K->u->configView->palette(); 216 for (k = 0; k < props.size(); ++k) { 217 QString pname = props[k]; 218 KLFConfigPropBase *p = pConfigBase->property(pname); 219 QVariant val = p->toVariant(); 220 // Config Entry 221 QStandardItem *i1 = new QStandardItem(pname); 222 i1->setEditable(false); 223 // Config Value (edit type directly) 224 QStandardItem *i2 = new QStandardItem(val.toString()); 225 bool editable = pConfigBase->okChangeProperty(p, QVariant(), QVariant()); 226 bool varianteditable = editable && is_editable_type(val.userType()); 227 i2->setEditable(varianteditable); 228 QPalette::ColorGroup cg = varianteditable ? QPalette::Active : QPalette::Disabled; 229 i2->setForeground(pal.brush(cg, QPalette::Text)); 230 i2->setBackground(pal.brush(cg, QPalette::Base)); 231 // klfDbg("Adding value: val="<<val<<"; displaystring="<<displayString(val)) ; 232 i2->setData(val, Qt::EditRole); 233 i2->setData(displayString(val), Qt::DisplayRole); 234 i2->setData(pname, CONFIG_VIEW_ROLE_PROPNAME); // user data is property name 235 // Config Value (config text representation) 236 QByteArray savedtype, savedinnertype; 237 QByteArray datavalue = klfSaveVariantToText(val, false, &savedtype, &savedinnertype); 238 klfDbg("i3: datavalue="<<datavalue) ; 239 QStandardItem *i3 = new QStandardItem(QString::fromLatin1(datavalue)); 240 cg = editable ? QPalette::Active : QPalette::Disabled; 241 i3->setForeground(pal.brush(cg, QPalette::Text)); 242 i3->setBackground(pal.brush(cg, QPalette::Base)); 243 i3->setData(val, Qt::EditRole); 244 i3->setData(QString::fromLatin1(datavalue), Qt::DisplayRole); 245 i3->setData(pname, CONFIG_VIEW_ROLE_PROPNAME); 246 i3->setData(savedtype, CONFIG_VIEW_ROLE_TYPENAME); 247 i3->setData(savedinnertype, CONFIG_VIEW_ROLE_INNERTYPENAME); 248 pConfModel->appendRow(QList<QStandardItem*>() << i1 << i2 << i3); 249 } 250 } updateConfigEntryKLFAdvancedConfigEditorPrivate251 void updateConfigEntry(int row) 252 { 253 pCurrentInternalUpdate = true; 254 QStandardItem *i2 = pConfModel->item(row, 1); 255 QStandardItem *i3 = pConfModel->item(row, 2); 256 QString pname = i2->data(CONFIG_VIEW_ROLE_PROPNAME).toString(); 257 KLF_ASSERT_CONDITION(pname == i3->data(CONFIG_VIEW_ROLE_PROPNAME).toString(), 258 "BUG?! pnames don't match for both config items", 259 return ; ); 260 QVariant val = pConfigBase->property(pname)->toVariant(); 261 i2->setText(val.toString()); 262 i2->setData(val, Qt::EditRole); 263 i2->setData(displayString(val), Qt::DisplayRole); 264 i3->setData(val, Qt::EditRole); 265 i3->setData(klfSaveVariantToText(val), Qt::DisplayRole); 266 pCurrentInternalUpdate = false; 267 } 268 resetDefaultKLFAdvancedConfigEditorPrivate269 void resetDefault() 270 { 271 QModelIndex index = K->u->configView->currentIndex(); 272 if (index == QModelIndex()) 273 return; 274 int row = index.row(); 275 QStandardItem *i2 = pConfModel->item(row, 1); 276 QStandardItem *i3 = pConfModel->item(row, 2); 277 QString pname = i2->data(CONFIG_VIEW_ROLE_PROPNAME).toString(); 278 KLF_ASSERT_CONDITION(pname == i3->data(CONFIG_VIEW_ROLE_PROPNAME).toString(), 279 "BUG?! pnames don't match for both config items", 280 return ; ); 281 KLFConfigPropBase *p = pConfigBase->property(pname); 282 KLF_ASSERT_NOT_NULL(p, "Property is NULL!", return; ) ; 283 QVariant oldvalue = p->toVariant(); 284 QVariant defval = p->defaultValueVariant(); 285 286 QMessageBox msgBox; 287 msgBox.setText(tr("You are resetting an advanced config setting to its factory default value. " 288 "Please confirm your action.")); 289 msgBox.setIcon(QMessageBox::Information); 290 msgBox.setInformativeText(tr("Change config entry %1 from %2 to its factory default value %3?") 291 .arg( "<b>"+pname+"</b>" , 292 "<b>"+klfSaveVariantToText(oldvalue)+"</b> <i>("+oldvalue.typeName()+")</i>" , 293 "<b>"+klfSaveVariantToText(defval)+"</b> <i>("+defval.typeName()+")</i>")); 294 msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Cancel); 295 msgBox.setDefaultButton(QMessageBox::Save); 296 int r = msgBox.exec(); 297 if (r != QMessageBox::Save) { 298 updateConfigEntry(row); 299 return; 300 } 301 302 // save the default value 303 r = p->setValue(defval); 304 if ( ! r ) { 305 QMessageBox::critical(K, tr("Error"), 306 tr("Failed to set config entry `%1'.").arg(pname)); 307 } 308 updateConfigEntry(row); 309 } 310 311 private: 312 // QString displayString(QVariant val) { 313 // if (val.type() == QVariant::Color) { 314 // QColor c = val.value<QColor>(); 315 // if (c.alpha() == 255) 316 // return c.name(); 317 // return c.name()+" ("+QString::number(c.alpha()*100/255)+"%)"; 318 // } 319 // return val.toString(); 320 // } 321 322 // If a string DisplayRole is set, then the list pops up the wrong editor. (Bug in Qt?) displayStringKLFAdvancedConfigEditorPrivate323 inline QVariant displayString(QVariant v) { 324 return v; 325 } 326 }; 327 328 329 330 331 // ------------------------ 332 333 334 class KLFFontDialog : public QFontDialog 335 { 336 Q_OBJECT 337 338 // just expose this property as the USER property, which is not done in QFontDialog. 339 Q_PROPERTY(QFont theFont READ currentFont WRITE setCurrentFont USER true); 340 public: 341 KLFFontDialog(QWidget *parent = 0) QFontDialog(parent)342 : QFontDialog(parent) 343 { 344 } 345 ~KLFFontDialog()346 virtual ~KLFFontDialog() 347 { 348 } 349 }; 350 351 352 #endif 353