HAL  v4.5.0-136-gbce33ee73
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
main_settings_widget.cpp
Go to the documentation of this file.
5 
9 #include "gui/gui_globals.h"
10 //#include "checkbox_setting.h"
11 //#include "dropdown_setting.h"
13 //#include "spinbox_setting.h"
14 //#include "text_setting.h"
16 
17 #include <QFrame>
18 #include <QHBoxLayout>
19 #include <QHeaderView>
20 #include <QMessageBox>
21 #include <QPushButton>
22 #include <QScrollArea>
23 #include <QScrollBar>
24 #include <QVBoxLayout>
25 #include <QTextEdit>
26 
27 namespace hal
28 {
30  {
31  for (SettingsWidget* widget : *this)
32  delete widget;
33  }
34 
35  void MainSettingsList::registerWidget(const QString& sectionName, SettingsWidget* widget)
36  {
37  append(widget);
38  mSectionMap[sectionName].append(widget);
39  }
40 
42  {
43  for (SettingsWidget* widget : *this)
44  widget->clearEditor();
45  }
46 
48  {
50  for (SettingsWidget* widget : *this)
51  retval.append(widget->settingsItem());
52  return retval;
53  }
54 
56  {
57  for (auto it = mSectionMap.begin(); it != mSectionMap.end(); ++it)
58  {
59  auto jt = it->begin();
60  while (jt != it->end())
61  if (*jt == widget)
62  jt = it->erase(jt);
63  else
64  ++jt;
65  }
66  int n = removeAll(widget);
67  if (n > 0)
68  {
69  widget->close();
70  widget->deleteLater();
71  }
72  }
73 
75  {
76  QStringList retval;
77  for (auto it = mSectionMap.constBegin(); it != mSectionMap.constEnd(); ++it)
78  if (it.value().isEmpty())
79  retval.append(it.key());
80  return retval;
81  }
82 
84  : QWidget(parent), mLayout(new QHBoxLayout()), mExpandingListWidget(new ExpandingListWidget()), mVerticalLayout(new QVBoxLayout()), mScrollbar(new QScrollBar()),
85  mScrollArea(new QScrollArea()), mContent(new QFrame()),
86  mContentLayout(new QHBoxLayout()), mSettingsContainer(new QFrame()),
87  mContainerLayout(new QVBoxLayout()), mButtonLayout(new QHBoxLayout()),
88  mDescriptionText(new QTextEdit(this)), mRestoreDefaults(new QPushButton()),
89  mCancel(new QPushButton()), mOk(new QPushButton())
90  {
91  mSearchbarContainer = new QFrame(this);
92  mSearchbarLayout = new QHBoxLayout();
93  mSearchbar = new Searchbar(mSearchbarContainer);
94 
95 
97 
98  setLayout(mLayout);
99  mLayout->setContentsMargins(0, 0, 0, 0);
100  mLayout->setSpacing(0);
101  mLayout->addWidget(mExpandingListWidget);
102  mLayout->addLayout(mVerticalLayout);
103  //mLayout->addWidget(mScrollbar);
104 
105  mVerticalLayout->setContentsMargins(0, 0, 0, 0);
106  mVerticalLayout->setSpacing(0);
107  mVerticalLayout->addWidget(mSearchbarContainer);
108 
109  mSearchbarContainer->setObjectName("Searchbar-container");
110  mSearchbarContainer->setLayout(mSearchbarLayout);
111  mSearchbarLayout->setContentsMargins(0, 0, 0, 0);
112  mSearchbarLayout->setSpacing(0);
113  mSearchbarLayout->addWidget(mSearchbar);
114 
115  mScrollArea->setFrameStyle(QFrame::NoFrame);
116  mVerticalLayout->addWidget(mScrollArea);
117 
118  mContent->setFrameStyle(QFrame::NoFrame);
119 
120  mContentLayout->setAlignment(Qt::AlignHCenter | Qt::AlignTop);
121  mContentLayout->setContentsMargins(0, 0, 0, 0);
122  mContentLayout->setSpacing(0);
123  mContent->setLayout(mContentLayout);
124 
125  mScrollArea->setWidget(mContent);
126  mScrollArea->setWidgetResizable(true);
127 
129  mSettingsContainer->setFrameStyle(QFrame::NoFrame);
130 
131  mContainerLayout->setAlignment(Qt::AlignLeft);
132  mContainerLayout->setContentsMargins(0, 0, 0, 0);
133  mContainerLayout->setSpacing(0);
134  mSettingsContainer->setLayout(mContainerLayout);
135 
136  mContentLayout->addWidget(mSettingsContainer);
137 
138  mButtonLayout->setContentsMargins(10, 10, 10, 10);
139  mButtonLayout->setSpacing(20);
140  mButtonLayout->setAlignment(Qt::AlignRight);
141 
142  mDescriptionText->setMaximumHeight(120);
143  mVerticalLayout->addWidget(mDescriptionText);
144 
145  mVerticalLayout->addLayout(mButtonLayout);
146 
147  mRestoreDefaults->setText("Restore default values for all settings");
148  mRestoreDefaults->setToolTip("Clear user preferences for this page");
149  mCancel->setText("Cancel");
150  mOk->setText("OK");
154 
155  QWidget* spacer = new QWidget();
157 
158  mButtonLayout->addWidget(mRestoreDefaults, Qt::AlignLeft);
159  mButtonLayout->addWidget(spacer);
160  mButtonLayout->addWidget(mCancel, Qt::AlignRight);
161  mButtonLayout->addWidget(mOk, Qt::AlignRight);
162 
166 
169  }
170 
171  void MainSettingsWidget::initWidgets()
172  {
174  QSet<const SettingsItem*> registeredItems = QtCompat::listToSet<const SettingsItem*>(mSettingsList.getItems());
175  QSet<QString> registeredCategories = QtCompat::listToSet<QString>(mSectionNames.values());
176  for (SettingsItem* si : SettingsManager::instance()->mSettingsList)
177  {
178  if (registeredItems.contains(si))
179  continue;
180 
181  QString catg = si->category();
182  if (catg.isEmpty()) catg = "Other";
183  if (!registeredCategories.contains(catg))
184  {
185  makeSection(catg);
186  registeredCategories.insert(catg);
187  }
188 
189  SettingsWidget* widget = si->editWidget();
192  mSettingsList.registerWidget(catg,widget);
193  registeredItems.insert(si);
194  mContainerLayout->addWidget(widget);
195  }
196 
197  // show only buttons with non-empty sections
198  for (ExpandingListButton* btn : mSectionNames.keys())
199  btn->show();
200  for (QString sectionName : mSettingsList.emptySections() )
201  {
202  for (auto it = mSectionNames.begin(); it!= mSectionNames.end(); ++it)
203  if (it.value() == sectionName)
204  it.key()->hide();
205  }
206  }
207 
208  void MainSettingsWidget::makeSection(const QString& label)
209  {
210  int colon = label.indexOf(':');
211  QString topLabel;
212  QString subLabel;
213  int level = 0;
214  if (colon<0)
215  subLabel = label;
216  else
217  {
218  topLabel = label.left(colon);
219  subLabel = label.mid(colon+1);
220  if (!mExpandingListWidget->hasGroup(topLabel))
221  {
222  ExpandingListButton* topBtn = new ExpandingListButton(0);
223  topBtn->setObjectName(topLabel);
224  topBtn->setText(topLabel);
225  topBtn->setDefaultIcon(topLabel);
226  mExpandingListWidget->appendItem(topBtn);
227  mSectionNames.insert(topBtn,topLabel);
228  }
229  level = 1;
230  }
231  ExpandingListButton* btn = new ExpandingListButton(level);
232  btn->setObjectName(subLabel);
233  btn->setText(subLabel);
234  btn->setDefaultIcon(subLabel);
235  //btn->setIconPath(iconPath);
236  mExpandingListWidget->appendItem(btn,topLabel);
237  mSectionNames.insert(btn, label);
238  }
239 
241  {
242  mContainerLayout->removeWidget(widget);
243  mSettingsList.unregisterWidget(widget);
244  }
245 
247  {
248  bool dirty = false;
249  for (SettingsWidget* widget : mSettingsList)
250  {
251  if (widget->dirty())
252  {
253  dirty = true;
254  break;
255  }
256  }
257  if (dirty)
258  {
259  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);
260  if (input == QMessageBox::Cancel)
261  return false;
262  if (input == QMessageBox::Yes)
263  return saveSettings();
264 // if (input == QMessageBox::No)
265 // rollbackSettings();
266  }
267  return true;
268  }
269 
271  {
272  for (SettingsWidget* widget : mSettingsList)
273  {
274  widget->handleSetDefaultValue(true);
275  }
276  }
277 
279  {
280  Q_EMIT close();
281  }
282 
284  {
285  saveSettings();
286  Q_EMIT close();
287  }
288 
290  {
291  initWidgets();
292 
293  mExpandingListWidget->selectFirstItem();
294  mExpandingListWidget->repolish();
295 
296  mSettingsList.clearAll();
297 
298  for (SettingsWidget* widget : mSettingsList)
299  {
300  if (widget)
301  widget->loadCurrentValue();
302  }
303  }
304 
306  {
307  if (!activeSettingsItem)
308  {
309  mDescriptionText->clear();
310  return;
311  }
312  QString html = QString("<html><body><h3>%1</h3><p>%2</p></body></html>")
313  .arg(activeSettingsItem->label()).arg(activeSettingsItem->description());
314  mDescriptionText->setHtml(html);
315  }
316 
318  {
319  mResetToFirstElement = false;
320  mResetToFirstElement = true;
321 
322  hideAllSettings();
323 // removeAllHighlights();
324 
325  if (!button) return;
326 
327  QString sectionName = mSectionNames.value(button);
328  mActiveSection = sectionName;
329  QList<SettingsWidget*> widgetList = mSettingsList.section(sectionName);
330 
331  for (SettingsWidget* widget : widgetList)
332  {
333  if (widget)
334  widget->show();
335  }
336  }
337 
338  void MainSettingsWidget::hideAllSettings()
339  {
340  for (SettingsWidget* widget : mSettingsList)
341  widget->hide();
342  }
343 
345  {
346  for (ExpandingListButton* but : mSectionNames.keys())
347  but->setSelected(false);
348  for (SettingsWidget* widget : mSettingsList)
349  widget->show();
350  }
351 
353  {
354  mSearchOptions = searchOpts;
355  mActiveSection.clear();
356  if (mExpandingListWidget)
357  mExpandingListWidget->clearSelected();
358  for (ExpandingListButton* but : mSectionNames.keys())
359  but->setSelected(false);
360  for (SettingsWidget* widget : mSettingsList)
361  if (isMatching(needle, widget->getLabel()))
362  {
363  if (mActiveSection.isEmpty())
364  mActiveSection = widget->settingsItem()->label();
365  widget->show();
366  }
367  else
368  widget->hide();
369  }
370 
371  bool MainSettingsWidget::saveSettings()
372  {
373  bool changed = false;
374  for (SettingsWidget* widget : mSettingsList)
375  {
376  if (widget->dirty())
377  {
378  changed = true;
379  widget->acceptValue();
380  }
381  }
382  if (changed)
383  {
385  }
386  return true;
387  }
388 
389  bool MainSettingsWidget::isMatching(QString searchString, QString stringToCheck)
390  {
391  if(!mSearchOptions.isExactMatch() && !mSearchOptions.isRegularExpression()){
392  //check if stringToCheck contains the searchString
393  return stringToCheck.contains(searchString, mSearchOptions.isCaseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive);
394  }
395  else if(mSearchOptions.isExactMatch()){
396  //check if the stringToCheck is the same as the searchString - also checks CaseSensitivity
397 
398  return 0 == QString::compare(searchString, stringToCheck, mSearchOptions.isCaseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive);
399  }
400  else if(mSearchOptions.isRegularExpression()){
401  //checks if the stringToCheck matches the regEx given by searchString
403  return regEx.match(stringToCheck).hasMatch();
404  }
405  return false;
406  }
407 }
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
Definition: defines.h:45
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::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)