HAL
main_settings_widget.cpp
Go to the documentation of this file.
5 
8 #include "gui/gui_globals.h"
9 //#include "checkbox_setting.h"
10 //#include "dropdown_setting.h"
12 //#include "spinbox_setting.h"
13 //#include "text_setting.h"
15 
16 #include <QFrame>
17 #include <QHBoxLayout>
18 #include <QHeaderView>
19 #include <QMessageBox>
20 #include <QPushButton>
21 #include <QScrollArea>
22 #include <QScrollBar>
23 #include <QVBoxLayout>
24 #include <QTextEdit>
25 
26 namespace hal
27 {
29  {
30  for (SettingsWidget* widget : *this)
31  delete widget;
32  }
33 
34  void MainSettingsList::registerWidget(const QString& sectionName, SettingsWidget* widget)
35  {
36  append(widget);
37  mSectionMap[sectionName].append(widget);
38  }
39 
41  {
42  for (SettingsWidget* widget : *this)
43  widget->clearEditor();
44  }
45 
47  {
49  for (SettingsWidget* widget : *this)
50  retval.append(widget->settingsItem());
51  return retval;
52  }
53 
55  {
56  for (auto it = mSectionMap.begin(); it != mSectionMap.end(); ++it)
57  {
58  auto jt = it->begin();
59  while (jt != it->end())
60  if (*jt == widget)
61  jt = it->erase(jt);
62  else
63  ++jt;
64  }
65  int n = removeAll(widget);
66  if (n > 0)
67  {
68  widget->close();
69  widget->deleteLater();
70  }
71  }
72 
74  {
75  QStringList retval;
76  for (auto it = mSectionMap.constBegin(); it != mSectionMap.constEnd(); ++it)
77  if (it.value().isEmpty())
78  retval.append(it.key());
79  return retval;
80  }
81 
83  : QWidget(parent), mLayout(new QHBoxLayout()), mExpandingListWidget(new ExpandingListWidget()), mVerticalLayout(new QVBoxLayout()), mScrollbar(new QScrollBar()),
84  mScrollArea(new QScrollArea()), mContent(new QFrame()),
85  mContentLayout(new QHBoxLayout()), mSettingsContainer(new QFrame()),
86  mContainerLayout(new QVBoxLayout()), mButtonLayout(new QHBoxLayout()),
87  mDescriptionText(new QTextEdit(this)), mRestoreDefaults(new QPushButton()),
88  mCancel(new QPushButton()), mOk(new QPushButton())
89  {
90  mSearchbarContainer = new QFrame(this);
91  mSearchbarLayout = new QHBoxLayout();
92  mSearchbar = new Searchbar(mSearchbarContainer);
93 
94 
96 
97  setLayout(mLayout);
98  mLayout->setContentsMargins(0, 0, 0, 0);
99  mLayout->setSpacing(0);
100  mLayout->addWidget(mExpandingListWidget);
101  mLayout->addLayout(mVerticalLayout);
102  //mLayout->addWidget(mScrollbar);
103 
104  mVerticalLayout->setContentsMargins(0, 0, 0, 0);
105  mVerticalLayout->setSpacing(0);
106  mVerticalLayout->addWidget(mSearchbarContainer);
107 
108  mSearchbarContainer->setObjectName("Searchbar-container");
109  mSearchbarContainer->setLayout(mSearchbarLayout);
110  mSearchbarLayout->setContentsMargins(0, 0, 0, 0);
111  mSearchbarLayout->setSpacing(0);
112  mSearchbarLayout->addWidget(mSearchbar);
113 
114  mScrollArea->setFrameStyle(QFrame::NoFrame);
115  mVerticalLayout->addWidget(mScrollArea);
116 
117  mContent->setFrameStyle(QFrame::NoFrame);
118 
119  mContentLayout->setAlignment(Qt::AlignHCenter | Qt::AlignTop);
120  mContentLayout->setContentsMargins(0, 0, 0, 0);
121  mContentLayout->setSpacing(0);
122  mContent->setLayout(mContentLayout);
123 
124  mScrollArea->setWidget(mContent);
125  mScrollArea->setWidgetResizable(true);
126 
128  mSettingsContainer->setFrameStyle(QFrame::NoFrame);
129 
130  mContainerLayout->setAlignment(Qt::AlignLeft);
131  mContainerLayout->setContentsMargins(0, 0, 0, 0);
132  mContainerLayout->setSpacing(0);
133  mSettingsContainer->setLayout(mContainerLayout);
134 
135  mContentLayout->addWidget(mSettingsContainer);
136 
137  mButtonLayout->setContentsMargins(10, 10, 10, 10);
138  mButtonLayout->setSpacing(20);
139  mButtonLayout->setAlignment(Qt::AlignRight);
140 
141  mDescriptionText->setMaximumHeight(120);
142  mVerticalLayout->addWidget(mDescriptionText);
143 
144  mVerticalLayout->addLayout(mButtonLayout);
145 
146  mRestoreDefaults->setText("Restore default values for all settings");
147  mRestoreDefaults->setToolTip("Clear user preferences for this page");
148  mCancel->setText("Cancel");
149  mOk->setText("OK");
153 
154  QWidget* spacer = new QWidget();
156 
157  mButtonLayout->addWidget(mRestoreDefaults, Qt::AlignLeft);
158  mButtonLayout->addWidget(spacer);
159  mButtonLayout->addWidget(mCancel, Qt::AlignRight);
160  mButtonLayout->addWidget(mOk, Qt::AlignRight);
161 
165 
168  }
169 
170  void MainSettingsWidget::initWidgets()
171  {
174  QSet<QString> registeredCategories = QSet<QString>::fromList(mSectionNames.values());
175  for (SettingsItem* si : SettingsManager::instance()->mSettingsList)
176  {
177  if (registeredItems.contains(si))
178  continue;
179 
180  QString catg = si->category();
181  if (catg.isEmpty()) catg = "Other";
182  if (!registeredCategories.contains(catg))
183  {
184  makeSection(catg);
185  registeredCategories.insert(catg);
186  }
187 
188  SettingsWidget* widget = si->editWidget();
191  mSettingsList.registerWidget(catg,widget);
192  registeredItems.insert(si);
193  mContainerLayout->addWidget(widget);
194  }
195 
196  // show only buttons with non-empty sections
197  for (ExpandingListButton* btn : mSectionNames.keys())
198  btn->show();
199  for (QString sectionName : mSettingsList.emptySections() )
200  {
201  for (auto it = mSectionNames.begin(); it!= mSectionNames.end(); ++it)
202  if (it.value() == sectionName)
203  it.key()->hide();
204  }
205  }
206 
207  void MainSettingsWidget::makeSection(const QString& label)
208  {
209  int colon = label.indexOf(':');
210  QString topLabel;
211  QString subLabel;
212  int level = 0;
213  if (colon<0)
214  subLabel = label;
215  else
216  {
217  topLabel = label.left(colon);
218  subLabel = label.mid(colon+1);
219  if (!mExpandingListWidget->hasGroup(topLabel))
220  {
221  ExpandingListButton* topBtn = new ExpandingListButton(0);
222  topBtn->setObjectName(topLabel);
223  topBtn->setText(topLabel);
224  topBtn->setDefaultIcon(topLabel);
225  mExpandingListWidget->appendItem(topBtn);
226  mSectionNames.insert(topBtn,topLabel);
227  }
228  level = 1;
229  }
230  ExpandingListButton* btn = new ExpandingListButton(level);
231  btn->setObjectName(subLabel);
232  btn->setText(subLabel);
233  btn->setDefaultIcon(subLabel);
234  //btn->setIconPath(iconPath);
235  mExpandingListWidget->appendItem(btn,topLabel);
236  mSectionNames.insert(btn, label);
237  }
238 
240  {
241  mContainerLayout->removeWidget(widget);
242  mSettingsList.unregisterWidget(widget);
243  }
244 
246  {
247  bool dirty = false;
248  for (SettingsWidget* widget : mSettingsList)
249  {
250  if (widget->dirty())
251  {
252  dirty = true;
253  break;
254  }
255  }
256  if (dirty)
257  {
258  QMessageBox::StandardButton input = QMessageBox::question(this, "Unsaved settings", "You have unsaved settings that would be discarded.\nSave before leaving the settings page?", QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel);
259  if (input == QMessageBox::Cancel)
260  return false;
261  if (input == QMessageBox::Yes)
262  return saveSettings();
263 // if (input == QMessageBox::No)
264 // rollbackSettings();
265  }
266  return true;
267  }
268 
270  {
271  for (SettingsWidget* widget : mSettingsList)
272  {
273  widget->handleSetDefaultValue(true);
274  }
275  }
276 
278  {
279  Q_EMIT close();
280  }
281 
283  {
284  saveSettings();
285  Q_EMIT close();
286  }
287 
289  {
290  initWidgets();
291 
292  mExpandingListWidget->selectFirstItem();
293  mExpandingListWidget->repolish();
294 
295  mSettingsList.clearAll();
296 
297  for (SettingsWidget* widget : mSettingsList)
298  {
299  if (widget)
300  widget->loadCurrentValue();
301  }
302  }
303 
305  {
306  if (!activeSettingsItem)
307  {
308  mDescriptionText->clear();
309  return;
310  }
311  QString html = QString("<html><body><h3>%1</h3><p>%2</p></body></html>")
312  .arg(activeSettingsItem->label()).arg(activeSettingsItem->description());
313  mDescriptionText->setHtml(html);
314  }
315 
317  {
318  mResetToFirstElement = false;
319  mResetToFirstElement = true;
320 
321  hideAllSettings();
322 // removeAllHighlights();
323 
324  if (!button) return;
325 
326  QString sectionName = mSectionNames.value(button);
327  mActiveSection = sectionName;
328  QList<SettingsWidget*> widgetList = mSettingsList.section(sectionName);
329 
330  for (SettingsWidget* widget : widgetList)
331  {
332  if (widget)
333  widget->show();
334  }
335  }
336 
337  void MainSettingsWidget::hideAllSettings()
338  {
339  for (SettingsWidget* widget : mSettingsList)
340  widget->hide();
341  }
342 
344  {
345  for (ExpandingListButton* but : mSectionNames.keys())
346  but->setSelected(false);
347  for (SettingsWidget* widget : mSettingsList)
348  widget->show();
349  }
350 
352  {
353  mSearchOptions = searchOpts;
354  mActiveSection.clear();
355  if (mExpandingListWidget)
356  mExpandingListWidget->clearSelected();
357  for (ExpandingListButton* but : mSectionNames.keys())
358  but->setSelected(false);
359  for (SettingsWidget* widget : mSettingsList)
360  if (isMatching(needle, widget->getLabel()))
361  {
362  if (mActiveSection.isEmpty())
363  mActiveSection = widget->settingsItem()->label();
364  widget->show();
365  }
366  else
367  widget->hide();
368  }
369 
370  bool MainSettingsWidget::saveSettings()
371  {
372  bool changed = false;
373  for (SettingsWidget* widget : mSettingsList)
374  {
375  if (widget->dirty())
376  {
377  changed = true;
378  widget->acceptValue();
379  }
380  }
381  if (changed)
382  {
384  }
385  return true;
386  }
387 
388  bool MainSettingsWidget::isMatching(QString searchString, QString stringToCheck)
389  {
390  if(!mSearchOptions.isExactMatch() && !mSearchOptions.isRegularExpression()){
391  //check if stringToCheck contains the searchString
392  return stringToCheck.contains(searchString, mSearchOptions.isCaseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive);
393  }
394  else if(mSearchOptions.isExactMatch()){
395  //check if the stringToCheck is the same as the searchString - also checks CaseSensitivity
396 
397  return 0 == QString::compare(searchString, stringToCheck, mSearchOptions.isCaseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive);
398  }
399  else if(mSearchOptions.isRegularExpression()){
400  //checks if the stringToCheck matches the regEx given by searchString
402  return regEx.match(stringToCheck).hasMatch();
403  }
404  return false;
405  }
406 }
static AssignedKeybindMap * instance()
One button of the ExpandingListWidget.
A selection menu with a hierarchic structure.
void appendItem(ExpandingListButton *button, const QString &groupName=QString())
void buttonSelected(ExpandingListButton *button)
bool hasGroup(const QString &groupName) const
QList< SettingsWidget * > section(const QString &s) const
void registerWidget(const QString &sectionName, SettingsWidget *widget)
QList< const SettingsItem * > getItems() const
QStringList emptySections() const
void unregisterWidget(SettingsWidget *widget)
MainSettingsWidget(QWidget *parent=nullptr)
void searchSettings(const QString &needle, SearchOptions searchOpts)
void handleButtonSelected(ExpandingListButton *button)
void handleDescriptionUpdate(SettingsItem *activeSettingsItem)
bool isMatching(QString searchString, QString stringToCheck)
void handleWidgetRemove(SettingsWidget *widget)
bool isExactMatch() const
bool isCaseSensitive() const
bool isRegularExpression() const
A QFrame with a QLineEdit that can be used to input a substring to search for.
Definition: searchbar.h:48
void triggerNewSearch(const QString &text, int searchOptions)
The interface for the logical part of a setting.
Definition: settings_item.h:46
virtual QString label() const
virtual QString description() const
static SettingsManager * instance()
The base class for all specific SettingsWidgets.
virtual void clearEditor()
void triggerRemoveWidget(SettingsWidget *widget)
void triggerDescriptionUpdate(SettingsItem *item)
const SettingsItem * settingsItem() const
n
Definition: test.py:6
void clicked(bool checked)
void setText(const QString &text)
void addLayout(QLayout *layout, int stretch)
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
void setSpacing(int spacing)
void setFrameStyle(int style)
void removeWidget(QWidget *widget)
bool setAlignment(QWidget *w, Qt::Alignment alignment)
void setContentsMargins(int left, int top, int right, int bottom)
void append(const T &value)
int removeAll(const T &value)
QMessageBox::StandardButton question(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void deleteLater()
void setObjectName(const QString &name)
void setWidget(QWidget *widget)
void setWidgetResizable(bool resizable)
bool contains(const T &value) const const
QSet< T > fromList(const QList< T > &list)
QSet::iterator insert(const T &value)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
void clear()
int compare(const QString &other, Qt::CaseSensitivity cs) const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QString left(int n) const const
QString mid(int position, int n) const const
AlignHCenter
CaseSensitive
ApplicationModal
void clear()
void setHtml(const QString &text)
QWidget(QWidget *parent, Qt::WindowFlags f)
bool close()
void setMaximumHeight(int maxh)
void setLayout(QLayout *layout)
void setSizePolicy(QSizePolicy)
void setToolTip(const QString &)
void setWindowModality(Qt::WindowModality windowModality)