10#include "ui_settingsdialog.h"
12#include <QItemSelectionModel>
16#include <QStringBuilder>
35 , m_currentCategory(nullptr)
36 , m_tabBarAlwaysVisible(true)
39 makeHeading(m_ui->headingLabel);
40 setStyleSheet(dialogStyleForPalette(palette()));
43 m_categoryFilterModel->setSourceModel(m_categoryModel);
44 m_ui->categoriesListView->setModel(m_categoryFilterModel);
48 connect(m_ui->categoriesListView->selectionModel(), &QItemSelectionModel::currentChanged,
this, &SettingsDialog::currentCategoryChanged);
50 connect(m_ui->abortPushButton, &QPushButton::clicked,
this, &SettingsDialog::reject);
52 connect(m_ui->okPushButton, &QPushButton::clicked,
this, &SettingsDialog::accept);
57 connect(m_ui->filterLineEdit, &QLineEdit::textChanged, m_categoryFilterModel, &OptionCategoryFilterModel::setFilterFixedString);
58 connect(m_ui->filterLineEdit, &QLineEdit::textChanged,
this, &SettingsDialog::updateTabWidget);
74 m_tabBarAlwaysVisible = value;
75 if (m_currentCategory) {
76 m_ui->pagesTabWidget->tabBar()->setHidden(!value && m_currentCategory->
pages().size() == 1);
88 return m_categoryModel->
category(categoryIndex);
101 if (pageIndex < category->pages().length()) {
113 if (
event->spontaneous()) {
132void SettingsDialog::currentCategoryChanged(
const QModelIndex &index)
143 if (m_currentCategory) {
144 m_currentCategory->
setCurrentIndex(m_ui->pagesTabWidget->currentIndex());
147 if (m_currentCategory !=
category) {
152 m_currentCategory =
nullptr;
153 m_ui->headingLabel->setText(tr(
"No category selected"));
183 const bool hasSingleCategory = singleCategory !=
nullptr;
184 m_ui->filterLineEdit->setHidden(hasSingleCategory);
185 m_ui->categoriesListView->setHidden(hasSingleCategory);
186 m_ui->headingLabel->setHidden(hasSingleCategory);
187 if (hasSingleCategory) {
188 m_ui->filterLineEdit->clear();
199 return m_ui->pagesTabWidget->cornerWidget(corner);
207 m_ui->pagesTabWidget->setCornerWidget(widget, corner);
215 m_ui->headingLayout->addWidget(widget);
223 m_categoryFilterModel->setFilterFixedString(QString());
224 m_ui->filterLineEdit->clear();
226 m_ui->categoriesListView->selectionModel()->select(
227 m_categoryFilterModel->mapFromSource(m_categoryModel->index(categoryIndex)), QItemSelectionModel::ClearAndSelect);
228 m_ui->pagesTabWidget->setCurrentIndex(pageIndex);
234void SettingsDialog::updateTabWidget()
236 if (!m_currentCategory) {
237 m_ui->pagesTabWidget->clear();
240 m_ui->pagesTabWidget->setUpdatesEnabled(
false);
242 const auto searchKeyWord = m_ui->filterLineEdit->text();
243 int index = 0, pageIndex = 0;
244 for (OptionPage *
const page : m_currentCategory->
pages()) {
248 widget->setParent(
nullptr);
251 QScrollArea *scrollArea;
252 if (index < m_ui->pagesTabWidget->count()) {
253 scrollArea = qobject_cast<QScrollArea *>(m_ui->pagesTabWidget->widget(index));
254 scrollArea->takeWidget();
255 m_ui->pagesTabWidget->setTabText(index, widget->windowTitle());
256 m_ui->pagesTabWidget->setTabIcon(index, widget->windowIcon());
258 scrollArea =
new QScrollArea(m_ui->pagesTabWidget);
259 scrollArea->setFrameStyle(QFrame::NoFrame);
260 scrollArea->setBackgroundRole(QPalette::Base);
261 scrollArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
262 scrollArea->setWidgetResizable(
true);
263 m_ui->pagesTabWidget->addTab(scrollArea, widget->windowTitle());
264 m_ui->pagesTabWidget->setTabIcon(index, widget->windowIcon());
266 if (
auto *
const layout = widget->layout()) {
267 layout->setAlignment(Qt::AlignTop | Qt::AlignLeft);
269 scrollArea->setWidget(widget);
273 m_ui->pagesTabWidget->setCurrentIndex(pageIndex);
279 while (index < m_ui->pagesTabWidget->count()) {
280 auto *
const scrollArea = qobject_cast<QScrollArea *>(m_ui->pagesTabWidget->widget(index));
281 scrollArea->takeWidget();
282 m_ui->pagesTabWidget->removeTab(index);
286 m_ui->pagesTabWidget->tabBar()->setHidden(!m_tabBarAlwaysVisible && m_ui->pagesTabWidget->count() == 1);
287 m_ui->pagesTabWidget->setUpdatesEnabled(
true);
293void SettingsDialog::retranslateTabWidget()
295 for (
auto index = 0; index < m_ui->pagesTabWidget->count(); ++index) {
296 const auto *
const scrollArea = qobject_cast<const QScrollArea *>(m_ui->pagesTabWidget->widget(index));
297 const auto *
const widget = scrollArea->widget();
298 m_ui->pagesTabWidget->setTabText(index, widget->windowTitle());
310 QString errorMessage;
319 if (errorMessage.isEmpty()) {
320 errorMessage = tr(
"<p><b>Errors occurred when applying changes:</b></p><ul>");
323 if (errors.isEmpty()) {
325 % QStringLiteral(
"</i>: ") % tr(
"unknown error") % QStringLiteral(
"</li>"));
327 for (
const QString &error : errors) {
329 % QStringLiteral(
"</i>: ") % error % QStringLiteral(
"</li>"));
337 if (!errorMessage.isEmpty()) {
338 errorMessage.append(QStringLiteral(
"</ul>"));
339 QMessageBox::warning(
this, windowTitle(), errorMessage);
344 return errorMessage.isEmpty();
361 const auto res = QDialog::event(
event);
362 switch (
event->type()) {
363 case QEvent::PaletteChange:
364 setStyleSheet(dialogStyleForPalette(palette()));
366 case QEvent::LanguageChange:
367 m_ui->retranslateUi(
this);
368 retranslateTabWidget();
The OptionCategoryFilterModel class is used by SettingsDialog to filter option categories.
The OptionCategoryModel class is used by SettingsDialog to store and display option categories.
OptionCategory * category(const QModelIndex &index) const
Returns the category for the specified model index.
QList< OptionCategory * > categories
void setCategories(const QList< OptionCategory * > &categories)
Sets the categories for the model.
The OptionCategory class wraps associated option pages.
void setCurrentIndex(int currentIndex)
Sets the current index.
void setDisplayName(const QString &displayName)
Sets the display name of the category.
int currentIndex() const
Returns the index of the currently shown page.
void resetAllPages()
Resets all pages.
QList< OptionPage * > pages
The OptionPage class is the base class for SettingsDialog pages.
virtual void reset()=0
Discards altered settings and resets relevant widgets.
virtual bool apply()=0
Applies altered settings.
bool matches(const QString &searchKeyWord)
Returns whether the pages matches the specified searchKeyWord.
bool hasBeenShown() const
Returns an indication whether the option page has been shown yet.
QWidget * widget()
Returns the widget for the option page.
The SettingsDialog class provides a framework for creating settings dialogs with different categories...
OptionCategoryModel * categoryModel()
Returns the category model used by the settings dialog to manage the categories.
void setTabBarAlwaysVisible(bool value)
Sets whether the tab bar is always visible.
OptionCategory * category(int categoryIndex) const
Returns the category for the specified categoryIndex.
SettingsDialog(QWidget *parent=nullptr)
Constructs a settings dialog.
void retranslationRequired()
void showCategory(OptionCategory *category)
Sets the current category to the specified category and updates the relevant widgets to show it.
bool event(QEvent *event) override
OptionPage * page(int categoryIndex, int pageIndex) const
Returns the page for the specified categoryIndex and the specified pageIndex.
void reset()
Resets all changes.
bool apply()
Applies all changes.
void addHeadingWidget(QWidget *widget)
Adds a widget next to the heading.
QWidget * cornerWidget(Qt::Corner corner=Qt::TopRightCorner) const
Returns the tab-widget's corner widget.
~SettingsDialog() override
Destroys the settings dialog.
void translateCategory(OptionCategory *category, const std::function< QString()> &translator)
Allows to set the categories display name so that it is retranslated as needed.
void showEvent(QShowEvent *event) override
Resets all pages before the dialog is shown by the application.
void setSingleCategory(OptionCategory *singleCategory)
Enables single-category mode to show only the specified singleCategory.
void setCornerWidget(QWidget *widget, Qt::Corner corner=Qt::TopRightCorner)
Sets the tab-widget's corner widget.
void selectPage(int categoryIndex, int pageIndex)
Selects the specified page within the specified category.