File indexing completed on 2025-01-19 06:54:48
0001 // 0002 // C++ Implementation: clisteditor 0003 // 0004 // Description: list editor widget - base class 0005 // 0006 /* 0007 Copyright 2008-2011 Tomas Mecir <kmuddy@kmuddy.com> 0008 0009 This program is free software; you can redistribute it and/or 0010 modify it under the terms of the GNU General Public License as 0011 published by the Free Software Foundation; either version 2 of 0012 the License, or (at your option) any later version. 0013 0014 This program is distributed in the hope that it will be useful, 0015 but WITHOUT ANY WARRANTY; without even the implied warranty of 0016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0017 GNU General Public License for more details. 0018 0019 You should have received a copy of the GNU General Public License 0020 along with this program. If not, see <http://www.gnu.org/licenses/>. 0021 */ 0022 0023 #include "clisteditor.h" 0024 #include "clist.h" 0025 #include "clistmanager.h" 0026 0027 #include <QLabel> 0028 #include <QCheckBox> 0029 #include <QPushButton> 0030 #include <QSpinBox> 0031 #include <QVBoxLayout> 0032 0033 #include <KLocalizedString> 0034 #include <kmessagebox.h> 0035 #include <klineedit.h> 0036 0037 struct cListEditor::Private { 0038 cListObject *obj; 0039 int objNum; 0040 cListObjectData data; // data from the object 0041 cListObjectData guiData; // data, as filled into the GUI 0042 0043 // GUI elements of the common attrib editor 0044 QSpinBox *edpriority; 0045 QCheckBox *chkenabled; 0046 KLineEdit *edname; 0047 0048 QWidget *centralBar; 0049 bool guiCreated; 0050 bool saving; 0051 }; 0052 0053 cListEditor::cListEditor (QWidget *parent) 0054 : QWidget (parent) 0055 { 0056 d = new Private; 0057 d->objNum = 0; 0058 d->obj = nullptr; 0059 d->guiCreated = false; 0060 d->saving = false; 0061 0062 // set our policy to expanding, and give us a grid layout. 0063 QSizePolicy qsp (QSizePolicy::Expanding, QSizePolicy::Expanding); 0064 setSizePolicy (qsp); 0065 QVBoxLayout *layout = new QVBoxLayout (this); 0066 layout->setSpacing (5); 0067 0068 d->centralBar = new QWidget (this); 0069 d->centralBar->setSizePolicy (qsp); 0070 QWidget *buttonBar = new QWidget (this); 0071 QHBoxLayout *buttonLayout = new QHBoxLayout (buttonBar); 0072 buttonLayout->setSpacing (20); 0073 buttonLayout->setAlignment (Qt::AlignCenter); 0074 0075 QPushButton *saveButton = new QPushButton (i18n ("&Apply changes"), buttonBar); 0076 QPushButton *undoButton = new QPushButton (i18n ("&Undo changes"), buttonBar); 0077 connect (saveButton, &QPushButton::clicked, this, &cListEditor::saveClicked); 0078 connect (undoButton, &QPushButton::clicked, this, &cListEditor::undoClicked); 0079 0080 layout->addWidget (d->centralBar); 0081 layout->addWidget (buttonBar); 0082 // row 1 is fixed, row 0 will grow to fill the available space. 0083 layout->setStretchFactor (d->centralBar, 1); 0084 buttonLayout->addWidget (saveButton); 0085 buttonLayout->addWidget (undoButton); 0086 } 0087 0088 cListEditor::~cListEditor () 0089 { 0090 delete d; 0091 } 0092 0093 void cListEditor::setObject (cListObject *obj) 0094 { 0095 if (d->obj) { 0096 disconnect (d->obj, &cListObject::changed, this, &cListEditor::objectChanged); 0097 d->obj = nullptr; 0098 } 0099 0100 if (!obj) return; 0101 if (!d->guiCreated) 0102 { 0103 d->guiCreated = true; 0104 createGUI (d->centralBar); 0105 } 0106 0107 d->obj = obj; 0108 d->objNum = cListManager::self()->objectId (obj); 0109 connect (d->obj, &cListObject::changed, this, &cListEditor::objectChanged); 0110 loadDataFromObject (); 0111 fillGUI (d->data); 0112 } 0113 0114 cListObject *cListEditor::object () 0115 { 0116 return d->obj; 0117 } 0118 0119 void cListEditor::objectChanged (cListObject *obj) 0120 { 0121 if (d->saving) return; // ignore events triggered by our saving 0122 if (obj != d->obj) return; // this should never happen 0123 0124 // okay, so merge in the changes 0125 // we have three lists - original object data, new object data, and data from the dialog 0126 // we replace original data with new data except where something changed in the dialog 0127 cListObjectData oldData = d->data; 0128 loadDataFromObject (); 0129 getDataFromGUI (&d->guiData); 0130 0131 oldData.name = (d->guiData.name == oldData.name) ? d->data.name : d->guiData.name; 0132 oldData.priority = (d->guiData.priority == oldData.priority) ? d->data.priority : d->guiData.priority; 0133 oldData.enabled = (d->guiData.enabled == oldData.enabled) ? d->data.enabled : d->guiData.enabled; 0134 std::map<QString, int>::iterator it1; 0135 for (it1 = d->guiData.intValues.begin(); it1 != d->guiData.intValues.end(); ++it1) 0136 oldData.intValues[it1->first] = (it1->second == oldData.intValues[it1->first]) ? d->data.intValues[it1->first] : it1->second; 0137 std::map<QString, QString>::iterator it2; 0138 for (it2 = d->guiData.strValues.begin(); it2 != d->guiData.strValues.end(); ++it2) 0139 oldData.strValues[it2->first] = (it2->second == oldData.strValues[it2->first]) ? d->data.strValues[it2->first] : it2->second; 0140 std::map<QString, bool>::iterator it3;; 0141 for (it3 = d->guiData.boolValues.begin(); it3 != d->guiData.boolValues.end(); ++it3) 0142 oldData.boolValues[it3->first] = (it3->second == oldData.boolValues[it3->first]) ? d->data.boolValues[it3->first] : it3->second; 0143 0144 fillGUI (oldData); 0145 } 0146 0147 bool cListEditor::objectValid () 0148 { 0149 if (!d->obj) return false; 0150 return (cListManager::self()->objectId (d->obj) != 0); 0151 } 0152 0153 void cListEditor::getGUIData () 0154 { 0155 // set some sane default, in case that getDataFromGUI doesn't fill something in 0156 d->guiData.name = d->data.name; 0157 d->guiData.enabled = d->data.enabled; 0158 d->guiData.priority = d->data.priority; 0159 d->guiData.intValues.clear(); 0160 d->guiData.strValues.clear(); 0161 d->guiData.boolValues.clear(); 0162 getDataFromGUI (&d->guiData); 0163 } 0164 0165 bool cListEditor::changed () 0166 { 0167 if (!objectValid()) return false; 0168 0169 // retrieve data 0170 getGUIData (); 0171 cListObject *obj = d->obj; 0172 0173 // compare data 0174 if (d->guiData.name != obj->name()) return true; 0175 if (d->guiData.priority != obj->priority()) return true; 0176 if (d->guiData.enabled != obj->enabled()) return true; 0177 std::map<QString, int>::iterator it1; 0178 for (it1 = d->guiData.intValues.begin(); it1 != d->guiData.intValues.end(); ++it1) 0179 if (obj->intVal (it1->first) != it1->second) 0180 return true; 0181 std::map<QString, QString>::iterator it2; 0182 for (it2 = d->guiData.strValues.begin(); it2 != d->guiData.strValues.end(); ++it2) 0183 if (obj->strVal (it2->first) != it2->second) 0184 return true; 0185 std::map<QString, bool>::iterator it3;; 0186 for (it3 = d->guiData.boolValues.begin(); it3 != d->guiData.boolValues.end(); ++it3) 0187 if (obj->boolVal (it3->first) != it3->second) 0188 return true; 0189 return false; // no difference 0190 } 0191 0192 void cListEditor::saveChanges () 0193 { 0194 getGUIData (); 0195 saveDataToObject (); 0196 // update our internal data, so that subsequent attempts to undo restore 0197 // the current status 0198 loadDataFromObject (); 0199 } 0200 0201 void cListEditor::saveClicked () 0202 { 0203 saveChanges (); 0204 } 0205 0206 void cListEditor::undoClicked () 0207 { 0208 // TODO: ask the user if he really means it 0209 fillGUI (d->data); 0210 } 0211 0212 QWidget *cListEditor::createCommonAttribEditor (QWidget *parent) 0213 { 0214 QWidget *widget = new QWidget (parent); 0215 QGridLayout *layout = new QGridLayout (widget); 0216 layout->setSpacing (5); 0217 d->chkenabled = new QCheckBox (i18n ("&Enabled"), widget); 0218 d->edpriority = new QSpinBox (widget); 0219 d->edpriority->setRange (1, 1000); 0220 d->edname = new KLineEdit (widget); 0221 d->edname->setValidator (new QRegExpValidator (QRegExp("^[0-9A-Za-z_ ]+$"), this)); 0222 QLabel *plabel = new QLabel (i18n("&Priority"), widget); 0223 plabel->setBuddy (d->edpriority); 0224 QLabel *label = new QLabel (i18n("&Name"), widget); 0225 label->setBuddy (d->edname); 0226 layout->addWidget (d->chkenabled, 0, 0, 1, 2); 0227 layout->addWidget (plabel, 1, 0); 0228 layout->addWidget (d->edpriority, 1, 1); 0229 layout->addWidget (label, 2, 0); 0230 layout->addWidget (d->edname, 2, 1); 0231 return widget; 0232 } 0233 0234 void cListEditor::fillCommonAttribEditor (const cListObjectData &data) 0235 { 0236 d->chkenabled->setChecked (data.enabled); 0237 d->edname->setText (data.name); 0238 d->edpriority->setValue (data.priority); 0239 } 0240 0241 void cListEditor::getDataFromCommonAttribEditor (cListObjectData *data) 0242 { 0243 data->enabled = d->chkenabled->isChecked (); 0244 data->name = d->edname->text(); 0245 data->priority = d->edpriority->value (); 0246 } 0247 0248 0249 void cListEditor::loadDataFromObject () 0250 { 0251 if (!objectValid()) return; 0252 d->data = d->obj->data(); 0253 0254 // add default property values 0255 const std::map<QString, cListProperty> props = d->obj->list()->getPropertyList (); 0256 std::map<QString, cListProperty>::const_iterator it; 0257 for (it = props.begin(); it != props.end(); ++it) { 0258 switch (it->second.type) { 0259 case Int: 0260 if (d->data.intValues.count (it->second.name)) break; // we have a value 0261 // no value - assign default 0262 d->data.intValues[it->second.name] = it->second.defIntValue; 0263 break; 0264 case String: 0265 if (d->data.strValues.count (it->second.name)) break; // we have a value 0266 // no value - assign default 0267 d->data.strValues[it->second.name] = it->second.defStrValue; 0268 break; 0269 case Bool: 0270 if (d->data.boolValues.count (it->second.name)) break; // we have a value 0271 // no value - assign default 0272 d->data.boolValues[it->second.name] = it->second.defBoolValue; 0273 break; 0274 }; 0275 } 0276 } 0277 0278 void cListEditor::saveDataToObject () 0279 { 0280 cListObject *obj = d->obj; 0281 d->saving = true; 0282 if (d->guiData.name != obj->name()) { 0283 if (obj->isGroup()) { 0284 cListGroup *g = obj->list()->group (d->guiData.name); 0285 if (g) { 0286 KMessageBox::error (this, i18n ("Cannot rename the group, as a group with this name already exists.")); 0287 return; 0288 } 0289 obj->list()->renameGroup ((cListGroup *) obj, d->guiData.name); 0290 } else { 0291 cListObject *o = obj->list()->getObject (d->guiData.name); 0292 if (o) { 0293 KMessageBox::error (this, i18n ("Cannot rename the object, as an object with this name already exists.")); 0294 return; 0295 } 0296 obj->list()->setObjectName (obj, d->guiData.name); 0297 } 0298 } 0299 if (d->guiData.priority != obj->priority()) 0300 obj->setPriority (d->guiData.priority); 0301 if (d->guiData.enabled != obj->enabled()) 0302 obj->setEnabled (d->guiData.enabled); 0303 0304 std::map<QString, int>::iterator it1; 0305 for (it1 = d->guiData.intValues.begin(); it1 != d->guiData.intValues.end(); ++it1) 0306 obj->setInt (it1->first, it1->second); 0307 std::map<QString, QString>::iterator it2; 0308 for (it2 = d->guiData.strValues.begin(); it2 != d->guiData.strValues.end(); ++it2) 0309 obj->setStr (it2->first, it2->second); 0310 std::map<QString, bool>::iterator it3;; 0311 for (it3 = d->guiData.boolValues.begin(); it3 != d->guiData.boolValues.end(); ++it3) 0312 obj->setBool (it3->first, it3->second); 0313 d->saving = false; 0314 } 0315 0316 #include "moc_clisteditor.cpp"