1 /*
2  * SPDX-FileCopyrightText: 2006 Peter Penz <peter.penz@gmx.at>
3  *
4  * SPDX-License-Identifier: GPL-2.0-or-later
5  */
6 
7 #include "dolphinsettingsdialog.h"
8 
9 #include "dolphin_generalsettings.h"
10 #include "dolphinmainwindow.h"
11 #include "general/generalsettingspage.h"
12 #include "navigation/navigationsettingspage.h"
13 #include "contextmenu/contextmenusettingspage.h"
14 #include "startup/startupsettingspage.h"
15 #include "trash/trashsettingspage.h"
16 #include "viewmodes/viewsettingspage.h"
17 #include "config-kuserfeedback.h"
18 #ifdef HAVE_KUSERFEEDBACK
19 #include "userfeedback/dolphinfeedbackprovider.h"
20 #include "userfeedback/userfeedbacksettingspage.h"
21 #endif
22 
23 #include <KAuthorized>
24 #include <KLocalizedString>
25 #include <KWindowConfig>
26 #include <KMessageBox>
27 
28 #include <QCloseEvent>
29 #include <QPushButton>
30 
DolphinSettingsDialog(const QUrl & url,QWidget * parent,KActionCollection * actions)31 DolphinSettingsDialog::DolphinSettingsDialog(const QUrl& url, QWidget* parent, KActionCollection* actions) :
32     KPageDialog(parent),
33     m_pages(),
34     m_unsavedChanges(false)
35 
36 {
37     const QSize minSize = minimumSize();
38     setMinimumSize(QSize(540, minSize.height()));
39 
40     setFaceType(List);
41     setWindowTitle(i18nc("@title:window", "Configure"));
42     QDialogButtonBox* box = new QDialogButtonBox(QDialogButtonBox::Ok
43             | QDialogButtonBox::Apply | QDialogButtonBox::Cancel | QDialogButtonBox::RestoreDefaults);
44     box->button(QDialogButtonBox::Apply)->setEnabled(false);
45     box->button(QDialogButtonBox::Ok)->setDefault(true);
46     setButtonBox(box);
47 
48     connect(box->button(QDialogButtonBox::Ok), &QAbstractButton::clicked, this, &DolphinSettingsDialog::applySettings);
49     connect(box->button(QDialogButtonBox::Apply), &QAbstractButton::clicked, this, &DolphinSettingsDialog::applySettings);
50     connect(box->button(QDialogButtonBox::RestoreDefaults), &QAbstractButton::clicked, this, &DolphinSettingsDialog::restoreDefaults);
51 
52     // General
53     GeneralSettingsPage* generalSettingsPage = new GeneralSettingsPage(url, this);
54     KPageWidgetItem* generalSettingsFrame = addPage(generalSettingsPage,
55                                                     i18nc("@title:group General settings", "General"));
56     generalSettingsFrame->setIcon(QIcon::fromTheme(QStringLiteral("system-file-manager")));
57     connect(generalSettingsPage, &GeneralSettingsPage::changed, this, &DolphinSettingsDialog::enableApply);
58 
59     // Startup
60     StartupSettingsPage* startupSettingsPage = new StartupSettingsPage(url, this);
61     KPageWidgetItem* startupSettingsFrame = addPage(startupSettingsPage,
62                                                     i18nc("@title:group", "Startup"));
63     startupSettingsFrame->setIcon(QIcon::fromTheme(QStringLiteral("preferences-desktop-launch-feedback")));
64     connect(startupSettingsPage, &StartupSettingsPage::changed, this, &DolphinSettingsDialog::enableApply);
65 
66     // View Modes
67     ViewSettingsPage* viewSettingsPage = new ViewSettingsPage(this);
68     KPageWidgetItem* viewSettingsFrame = addPage(viewSettingsPage,
69                                                  i18nc("@title:group", "View Modes"));
70     viewSettingsFrame->setIcon(QIcon::fromTheme(QStringLiteral("preferences-desktop-icons")));
71     connect(viewSettingsPage, &ViewSettingsPage::changed, this, &DolphinSettingsDialog::enableApply);
72 
73     // Navigation
74     NavigationSettingsPage* navigationSettingsPage = new NavigationSettingsPage(this);
75     KPageWidgetItem* navigationSettingsFrame = addPage(navigationSettingsPage,
76                                                        i18nc("@title:group", "Navigation"));
77     navigationSettingsFrame->setIcon(QIcon::fromTheme(QStringLiteral("preferences-desktop-navigation")));
78     connect(navigationSettingsPage, &NavigationSettingsPage::changed, this, &DolphinSettingsDialog::enableApply);
79 
80     // Context Menu
81     auto contextMenuSettingsPage = new ContextMenuSettingsPage(this, actions, {
82         QStringLiteral("add_to_places"),
83         QStringLiteral("sort"),
84         QStringLiteral("view_mode"),
85         QStringLiteral("open_in_new_tab"),
86         QStringLiteral("open_in_new_window"),
87         QStringLiteral("copy_location"),
88         QStringLiteral("duplicate"),
89         QStringLiteral("open_terminal"),
90     });
91     KPageWidgetItem* contextMenuSettingsFrame = addPage(contextMenuSettingsPage,
92                                                         i18nc("@title:group", "Context Menu"));
93     contextMenuSettingsFrame->setIcon(QIcon::fromTheme(QStringLiteral("application-menu")));
94     connect(contextMenuSettingsPage, &ContextMenuSettingsPage::changed, this, &DolphinSettingsDialog::enableApply);
95 
96     // Trash
97     SettingsPageBase* trashSettingsPage = nullptr;
98 #ifndef Q_OS_WIN
99     trashSettingsPage = createTrashSettingsPage(this);
100 #endif
101     if (trashSettingsPage) {
102         trashSettings = addPage(trashSettingsPage,
103                                                      i18nc("@title:group", "Trash"));
104         trashSettings->setIcon(QIcon::fromTheme(QStringLiteral("user-trash")));
105         connect(trashSettingsPage, &TrashSettingsPage::changed, this, &DolphinSettingsDialog::enableApply);
106     }
107 
108 #ifdef HAVE_KUSERFEEDBACK
109     // User Feedback
110     UserFeedbackSettingsPage* feedbackSettingsPage = nullptr;
111     if (DolphinFeedbackProvider::instance()->isEnabled()) {
112         feedbackSettingsPage = new UserFeedbackSettingsPage(this);
113         auto feedbackSettingsFrame = addPage(feedbackSettingsPage, i18nc("@title:group", "User Feedback"));
114         feedbackSettingsFrame->setIcon(QIcon::fromTheme(QStringLiteral("preferences-desktop-locale")));
115         connect(feedbackSettingsPage, &UserFeedbackSettingsPage::changed, this, &DolphinSettingsDialog::enableApply);
116     }
117 #endif
118 
119     m_pages.append(generalSettingsPage);
120     m_pages.append(startupSettingsPage);
121     m_pages.append(viewSettingsPage);
122     m_pages.append(navigationSettingsPage);
123     m_pages.append(contextMenuSettingsPage);
124     if (trashSettingsPage) {
125         m_pages.append(trashSettingsPage);
126     }
127 #ifdef HAVE_KUSERFEEDBACK
128     if (feedbackSettingsPage) {
129         m_pages.append(feedbackSettingsPage);
130     }
131 #endif
132 
133     const KConfigGroup dialogConfig(KSharedConfig::openStateConfig(), "SettingsDialog");
134     KWindowConfig::restoreWindowSize(windowHandle(), dialogConfig);
135 }
136 
~DolphinSettingsDialog()137 DolphinSettingsDialog::~DolphinSettingsDialog()
138 {
139     KConfigGroup dialogConfig(KSharedConfig::openStateConfig(), "SettingsDialog");
140     KWindowConfig::saveWindowSize(windowHandle(), dialogConfig);
141 }
142 
enableApply()143 void DolphinSettingsDialog::enableApply()
144 {
145     buttonBox()->button(QDialogButtonBox::Apply)->setEnabled(true);
146     m_unsavedChanges = true;
147 }
148 
applySettings()149 void DolphinSettingsDialog::applySettings()
150 {
151     for (SettingsPageBase* page : qAsConst(m_pages)) {
152         page->applySettings();
153     }
154 
155     Q_EMIT settingsChanged();
156 
157     GeneralSettings* settings = GeneralSettings::self();
158     if (settings->modifiedStartupSettings()) {
159         // Reset the modified startup settings hint. The changed startup settings
160         // have been applied already due to emitting settingsChanged().
161         settings->setModifiedStartupSettings(false);
162         settings->save();
163     }
164     buttonBox()->button(QDialogButtonBox::Apply)->setEnabled(false);
165     m_unsavedChanges = false;
166 }
167 
restoreDefaults()168 void DolphinSettingsDialog::restoreDefaults()
169 {
170     for (SettingsPageBase* page : qAsConst(m_pages)) {
171         page->restoreDefaults();
172     }
173 }
174 
closeEvent(QCloseEvent * event)175 void DolphinSettingsDialog::closeEvent(QCloseEvent* event)
176 {
177     if (!m_unsavedChanges) {
178         event->accept();
179         return;
180     }
181 
182     const auto response = KMessageBox::warningYesNoCancel(this,
183                                         i18n("You have unsaved changes. Do you want to apply the changes or discard them?"),
184                                         i18n("Warning"),
185                                         KStandardGuiItem::save(),
186                                         KStandardGuiItem::discard(),
187                                         KStandardGuiItem::cancel());
188     switch (response) {
189         case KMessageBox::Yes:
190             applySettings();
191             Q_FALLTHROUGH();
192         case KMessageBox::No:
193             event->accept();
194             break;
195         case KMessageBox::Cancel:
196             event->ignore();
197             break;
198         default:
199             break;
200     }
201 }
202 
203 
createTrashSettingsPage(QWidget * parent)204 SettingsPageBase *DolphinSettingsDialog::createTrashSettingsPage(QWidget *parent)
205 {
206     if (!KAuthorized::authorizeControlModule(QStringLiteral("kcmtrash.desktop"))) {
207         return nullptr;
208     }
209 
210     return new TrashSettingsPage(parent);
211 }
212