configurationdialog.cpp
1 //------------------------------------------------------------------------------
2 // configurationdialog.cpp
3 //------------------------------------------------------------------------------
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 // 02110-1301, USA.
19 //
20 //------------------------------------------------------------------------------
21 // Copyright (C) 2009 "Zalewa" <zalewapl@gmail.com>
22 //------------------------------------------------------------------------------
23 #include "configurationdialog.h"
24 #include "ui_configurationdialog.h"
25 
26 #include "configurationbasebox.h"
27 #include "qtmetapointer.h"
28 #include <Qt>
29 #include <QDebug>
30 #include <QKeyEvent>
31 #include <QStandardItemModel>
32 #include <QStandardItem>
33 #include <QTreeView>
34 #include <QAbstractButton>
35 
36 DClass<ConfigurationDialog> : public Ui::ConfigurationDialog
37 {
38 public:
39  QList<ConfigurationBaseBox*> configBoxesList;
40  QWidget* currentlyDisplayedCfgBox;
41 };
42 
43 DPointered(ConfigurationDialog)
44 
46 : QDialog(parent)
47 {
48  d->setupUi(this);
49 
50  d->tvOptionsList->setHeaderHidden(true);
51  d->tvOptionsList->setModel(new QStandardItemModel(this));
52 
53  d->currentlyDisplayedCfgBox = NULL;
54  connect(d->buttonBox, SIGNAL( clicked(QAbstractButton *) ), this, SLOT ( btnClicked(QAbstractButton *) ));
55  this->connect(d->tvOptionsList->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)),
56  SLOT(onOptionListCurrentChanged(QModelIndex, QModelIndex)));
57 }
58 
59 ConfigurationDialog::~ConfigurationDialog()
60 {
61  for(int i = 0; i < d->configBoxesList.count(); ++i)
62  {
63  delete d->configBoxesList[i];
64  }
65 }
66 
67 QStandardItem* ConfigurationDialog::addConfigurationBox(QStandardItem* rootItem, ConfigurationBaseBox* pConfigurationBox, int position)
68 {
69  if (!canConfigurationBoxBeAddedToList(pConfigurationBox))
70  {
71  return NULL;
72  }
73 
74  QStandardItemModel* pModel = (QStandardItemModel*)d->tvOptionsList->model();
75  if (rootItem == NULL)
76  {
77  rootItem = pModel->invisibleRootItem();
78  }
79 
80  if (!this->hasItemOnList(rootItem))
81  {
82  return NULL;
83  }
84 
85  QStandardItem* pNewItem = new QStandardItem(pConfigurationBox->name());
86  pNewItem->setIcon(pConfigurationBox->icon());
87 
88  void* pointerConfigurationBox = pConfigurationBox;
89  QtMetaPointer metaPointer = pointerConfigurationBox;
90  QVariant variantConfigurationBox = qVariantFromValue(metaPointer);
91  pNewItem->setData(variantConfigurationBox);
92 
93  if (position < 0)
94  {
95  rootItem->appendRow(pNewItem);
96  }
97  else
98  {
99  rootItem->insertRow(position, pNewItem);
100  }
101 
102  d->configBoxesList.push_back(pConfigurationBox);
103 
104  return pNewItem;
105 }
106 
107 QStandardItem* ConfigurationDialog::addLabel(QStandardItem* rootItem, const QString& label, int position)
108 {
109  QStandardItemModel* pModel = (QStandardItemModel*)d->tvOptionsList->model();
110  if (rootItem == NULL)
111  {
112  rootItem = pModel->invisibleRootItem();
113  }
114 
115  if (!this->hasItemOnList(rootItem))
116  {
117  return NULL;
118  }
119 
120  QtMetaPointer metaPointer = (void*)NULL;
121  QVariant variantMetaPointer = qVariantFromValue(metaPointer);
122 
123  QStandardItem* pNewItem = new QStandardItem(label);
124  pNewItem->setData(variantMetaPointer);
125 
126  if (position < 0)
127  {
128  rootItem->appendRow(pNewItem);
129  }
130  else
131  {
132  rootItem->insertRow(position, pNewItem);
133  }
134 
135  return pNewItem;
136 }
137 
138 void ConfigurationDialog::btnClicked(QAbstractButton *button)
139 {
140  // Figure out what button we pressed and perform its action.
141  switch(d->buttonBox->standardButton(button))
142  {
143  default:
144  break;
145 
146  case QDialogButtonBox::Ok: // Also does the same as Apply
147  if (this->validate())
148  {
149  this->accept();
150  this->saveSettings();
151  }
152  break;
153 
154  case QDialogButtonBox::Apply:
155  if (this->validate())
156  {
157  this->saveSettings();
158  }
159  break;
160 
161  case QDialogButtonBox::Cancel:
162  this->reject();
163  break;
164  }
165 }
166 
167 bool ConfigurationDialog::canConfigurationBoxBeAddedToList(ConfigurationBaseBox* pConfigurationBox)
168 {
169  return isConfigurationBoxInfoValid(pConfigurationBox) && !isConfigurationBoxOnTheList(pConfigurationBox);
170 }
171 
172 bool ConfigurationDialog::isConfigurationBoxInfoValid(ConfigurationBaseBox* pConfigurationBox)
173 {
174  return pConfigurationBox != NULL && !pConfigurationBox->name().isEmpty();
175 }
176 
177 bool ConfigurationDialog::isConfigurationBoxOnTheList(ConfigurationBaseBox* pConfigurationBox)
178 {
179  foreach (ConfigurationBaseBox* pBoxOnTheList, d->configBoxesList)
180  {
181  if (pConfigurationBox == pBoxOnTheList)
182  {
183  return true;
184  }
185  }
186 
187  return false;
188 }
189 
190 void ConfigurationDialog::keyPressEvent(QKeyEvent* e)
191 {
192  switch (e->key())
193  {
194  case Qt::Key_Enter:
195  case Qt::Key_Return:
196  // Suppress the dialog being accepted on pressing ENTER key.
197  // Dialog would close even in line edits that had "returnPressed()"
198  // signals connected. That wasn't good.
199  e->ignore();
200  break;
201  default:
202  QDialog::keyPressEvent(e);
203  }
204 }
205 
206 bool ConfigurationDialog::hasItemOnList(QStandardItem* pItem) const
207 {
208  if (pItem == NULL)
209  {
210  return false;
211  }
212 
213  QStandardItemModel* pModel = (QStandardItemModel*)d->tvOptionsList->model();
214 
215  // Calling index methods on the invisible root items will always return
216  // invalid values.
217 
218  return pModel->invisibleRootItem() == pItem
219  || pModel->indexFromItem(pItem).isValid();
220 }
221 
222 void ConfigurationDialog::onOptionListCurrentChanged(const QModelIndex &current, const QModelIndex &previous)
223 {
224  if (current.isValid() && current != previous)
225  {
226  switchToItem(current);
227  }
228 }
229 
230 void ConfigurationDialog::switchToItem(const QModelIndex& index)
231 {
232  QStandardItemModel* model = static_cast<QStandardItemModel*>(d->tvOptionsList->model());
233  QStandardItem* item = model->itemFromIndex(index);
234 
235  QtMetaPointer metaPointer = qVariantValue<QtMetaPointer>(item->data());
236  void* pointer = metaPointer;
237  ConfigurationBaseBox* pConfigBox = (ConfigurationBaseBox*)pointer;
238 
239  // Something with sense was selected, display this something
240  // and hide previous box.
241  if (isConfigurationBoxInfoValid(pConfigBox))
242  {
243  if (!pConfigBox->areSettingsAlreadyRead())
244  {
245  pConfigBox->read();
246  }
247  pConfigBox->setAllowSave(true);
248  showConfigurationBox(pConfigBox);
249  }
250 }
251 
253 {
254  return d->tvOptionsList;
255 }
256 
257 void ConfigurationDialog::saveSettings()
258 {
259  // Iterate through every engine and execute it's saving method
260  for (int i = 0; i < d->configBoxesList.count(); ++i)
261  {
262  d->configBoxesList[i]->save();
263  }
264 
265  doSaveSettings();
266 
267  if(isVisible())
268  {
269  // Allow panels such as the one for Wadseeker update their contents.
270  for (int i = 0; i < d->configBoxesList.count(); ++i)
271  {
272  d->configBoxesList[i]->read();
273  }
274  }
275 }
276 
277 
279 {
280  if (d->currentlyDisplayedCfgBox != NULL)
281  {
282  d->currentlyDisplayedCfgBox->hide();
283  d->mainPanel->setTitle(QString());
284  }
285  d->currentlyDisplayedCfgBox = widget;
286 
287  if (widget != NULL)
288  {
289  d->mainPanel->layout()->addWidget(widget);
290  d->mainPanel->setTitle(widget->title());
291  widget->show();
292  }
293 }
void showConfigurationBox(ConfigurationBaseBox *widget)
QTreeView * optionsTree()
Returns pointer to the tree widget that contains configuration sections list.
bool areSettingsAlreadyRead()
true if settings for this page have already been loaded at least once.
virtual QString name() const =0
Reimplement this to return a list-displayable name for this ConfigurationBaseBox. ...
QStandardItem * addLabel(QStandardItem *rootItem, const QString &label, int position=-1)
Adds a label node to the options tree view.
void read()
Read configuration from persistence to page contents.
virtual QStandardItem * addConfigurationBox(QStandardItem *rootItem, ConfigurationBaseBox *pConfigurationBox, int position=-1)
Adds a new configuration box to the options tree view.
void setAllowSave(bool b)
Change whether settings on this page can be stored in persisting configuration.
virtual QIcon icon() const =0
Reimplement this to return a displayable icon for the ConfigurationBaseBox.
virtual QString title() const
Page title, by default returns the same string as name().
Base class for configuration pages.