1/*
2 * Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com)
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17#include "settingsdialog.h"
18#include "ui_settingsdialog.h"
19#include "settingswidget.h"
20#include "compilersetoptionwidget.h"
21#include "compilerautolinkwidget.h"
22#include "editorgeneralwidget.h"
23#include "editorfontwidget.h"
24#include "editorclipboardwidget.h"
25#include "editorcolorschemewidget.h"
26#include "editorcodecompletionwidget.h"
27#include "editorsyntaxcheckwidget.h"
28#include "editorsymbolcompletionwidget.h"
29#include "editortooltipswidget.h"
30#include "editorautosavewidget.h"
31#include "editorsnippetwidget.h"
32#include "editormiscwidget.h"
33#include "environmentappearencewidget.h"
34#include "environmentshortcutwidget.h"
35#include "environmentfolderswidget.h"
36#include "environmentperformancewidget.h"
37#include "executorgeneralwidget.h"
38#include "executorproblemsetwidget.h"
39#include "debuggeneralwidget.h"
40#include "formattergeneralwidget.h"
41#include "projectgeneralwidget.h"
42#include "projectfileswidget.h"
43#include "projectcompilerwidget.h"
44#include "projectcompileparamaterswidget.h"
45#include "projectdirectorieswidget.h"
46#include "projectprecompilewidget.h"
47#include "projectoutputwidget.h"
48#include "projectmakefilewidget.h"
49#include "projectdllhostwidget.h"
50#include "toolsgeneralwidget.h"
51#include "toolsgitwidget.h"
52#ifdef Q_OS_WIN
53#include "environmentfileassociationwidget.h"
54#include "projectversioninfowidget.h"
55#endif
56#ifdef Q_OS_LINUX
57#include "environmentprogramswidget.h"
58#include "formatterpathwidget.h"
59#endif
60#include <QDebug>
61#include <QMessageBox>
62#include <QModelIndex>
63#include <QDesktopWidget>
64
65SettingsDialog::SettingsDialog(QWidget *parent) :
66 QDialog(parent),
67 ui(new Ui::SettingsDialog)
68{
69 setWindowFlag(Qt::WindowContextHelpButtonHint,false);
70 ui->setupUi(this);
71
72 ui->widgetsView->setModel(&model);
73
74 model.setHorizontalHeaderLabels(QStringList());
75
76 ui->btnApply->setEnabled(false);
77
78 mAppShouldQuit = false;
79 resize(pSettings->ui().settingsDialogWidth(),pSettings->ui().settingsDialogHeight());
80
81 QList<int> sizes = ui->splitter->sizes();
82 int tabWidth = pSettings->ui().settingsDialogSplitterPos();
83 int totalSize = sizes[0] + sizes[1];
84 sizes[0] = tabWidth;
85 sizes[1] = std::max(1,totalSize - sizes[0]);
86 ui->splitter->setSizes(sizes);
87}
88
89SettingsDialog::~SettingsDialog()
90{
91 for (SettingsWidget* p:mSettingWidgets) {
92 p->setParent(nullptr);
93 delete p;
94 }
95 delete ui;
96}
97
98void SettingsDialog::addWidget(SettingsWidget *pWidget)
99{
100 pWidget->init();
101 QList<QStandardItem*> items = model.findItems(pWidget->group());
102 QStandardItem* pGroupItem;
103 if (items.count() == 0 ) {
104 pGroupItem = new QStandardItem(pWidget->group());
105 pGroupItem->setData(-1, GetWidgetIndexRole);
106 model.appendRow(pGroupItem);
107 } else {
108 pGroupItem = items[0];
109 }
110 mSettingWidgets.append(pWidget);
111 QStandardItem* pWidgetItem = new QStandardItem(pWidget->name());
112 pWidgetItem->setData(mSettingWidgets.count()-1, GetWidgetIndexRole);
113 pGroupItem->appendRow(pWidgetItem);
114 connect(pWidget, &SettingsWidget::settingsChanged,
115 this , &SettingsDialog::widget_settings_changed);
116}
117
118void SettingsDialog::selectFirstWidget()
119{
120 ui->widgetsView->expandAll();
121 //select the first widget of the first group
122 auto groupIndex = ui->widgetsView->model()->index(0,0);
123 auto widgetIndex = ui->widgetsView->model()->index(0,0, groupIndex);
124 ui->widgetsView->selectionModel()->setCurrentIndex(
125 widgetIndex,
126 QItemSelectionModel::Select
127 );
128 on_widgetsView_clicked(widgetIndex);
129}
130
131PSettingsDialog SettingsDialog::optionDialog()
132{
133 PSettingsDialog dialog = std::make_shared<SettingsDialog>();
134
135 dialog->setWindowTitle(tr("Options"));
136
137 SettingsWidget* widget;
138 widget = new EnvironmentAppearenceWidget(tr("Appearence"),tr("Environment"));
139 dialog->addWidget(widget);
140
141#ifdef Q_OS_WIN
142 widget = new EnvironmentFileAssociationWidget(tr("File Association"),tr("Environment"));
143 dialog->addWidget(widget);
144#endif
145
146 widget = new EnvironmentShortcutWidget(tr("Shortcuts"),tr("Environment"));
147 dialog->addWidget(widget);
148
149 widget = new EnvironmentFoldersWidget(tr("Folders"),tr("Environment"));
150 connect((EnvironmentFoldersWidget*)widget,
151 &EnvironmentFoldersWidget::shouldQuitApp,
152 dialog.get(),
153 &SettingsDialog::closeAndQuit);
154 dialog->addWidget(widget);
155
156#ifdef Q_OS_LINUX
157 widget = new EnvironmentProgramsWidget(tr("Terminal"),tr("Environment"));
158 dialog->addWidget(widget);
159#endif
160
161 widget = new EnvironmentPerformanceWidget(tr("Performance"),tr("Environment"));
162 dialog->addWidget(widget);
163
164 widget = new CompilerSetOptionWidget(tr("Compiler Set"),tr("Compiler"));
165 dialog->addWidget(widget);
166
167 widget = new CompilerAutolinkWidget(tr("Auto Link"),tr("Compiler"));
168 dialog->addWidget(widget);
169
170 widget = new EditorGeneralWidget(tr("General"),tr("Editor"));
171 dialog->addWidget(widget);
172
173 widget = new EditorFontWidget(tr("Font"),tr("Editor"));
174 dialog->addWidget(widget);
175
176 widget = new EditorClipboardWidget(tr("Copy & Export"),tr("Editor"));
177 dialog->addWidget(widget);
178
179 widget = new EditorColorSchemeWidget(tr("Color"),tr("Editor"));
180 dialog->addWidget(widget);
181
182 widget = new EditorCodeCompletionWidget(tr("Code Completion"),tr("Editor"));
183 dialog->addWidget(widget);
184
185 widget = new EditorSymbolCompletionWidget(tr("Symbol Completion"),tr("Editor"));
186 dialog->addWidget(widget);
187
188 widget = new EditorSnippetWidget(tr("Snippet"),tr("Editor"));
189 dialog->addWidget(widget);
190
191 widget = new EditorSyntaxCheckWidget(tr("Auto Syntax Checking"),tr("Editor"));
192 dialog->addWidget(widget);
193
194 widget = new EditorTooltipsWidget(tr("Tooltips"),tr("Editor"));
195 dialog->addWidget(widget);
196
197 widget = new EditorAutoSaveWidget(tr("Auto save"),tr("Editor"));
198 dialog->addWidget(widget);
199
200 widget = new EditorMiscWidget(tr("Misc"),tr("Editor"));
201 dialog->addWidget(widget);
202
203 widget = new ExecutorGeneralWidget(tr("General"),tr("Program Runner"));
204 dialog->addWidget(widget);
205
206 widget = new ExecutorProblemSetWidget(tr("Problem Set"),tr("Program Runner"));
207 dialog->addWidget(widget);
208
209 widget = new DebugGeneralWidget(tr("General"),tr("Debugger"));
210 dialog->addWidget(widget);
211
212 widget = new FormatterGeneralWidget(tr("General"),tr("Code Formatter"));
213 dialog->addWidget(widget);
214
215#ifdef Q_OS_LINUX
216 widget = new FormatterPathWidget(tr("Program"),tr("Code Formatter"));
217 dialog->addWidget(widget);
218#endif
219
220 widget = new ToolsGeneralWidget(tr("General"),tr("Tools"));
221 dialog->addWidget(widget);
222
223 widget = new ToolsGitWidget(tr("Git"),tr("Tools"));
224 dialog->addWidget(widget);
225
226
227 dialog->selectFirstWidget();
228
229 return dialog;
230}
231
232PSettingsDialog SettingsDialog::projectOptionDialog()
233{
234 PSettingsDialog dialog = std::make_shared<SettingsDialog>();
235
236 dialog->setWindowTitle(tr("Project Options"));
237
238 SettingsWidget* widget = new ProjectGeneralWidget(tr("General"),tr("Project"));
239 dialog->addWidget(widget);
240
241 widget = new ProjectFilesWidget(tr("Files"),tr("Project"));
242 dialog->addWidget(widget);
243
244 widget = new ProjectCompilerWidget(tr("Compiler Set"),tr("Project"));
245 dialog->addWidget(widget);
246
247 widget = new ProjectCompileParamatersWidget(tr("Custom Compile options"),tr("Project"));
248 dialog->addWidget(widget);
249
250 widget = new ProjectDirectoriesWidget(tr("Directories"),tr("Project"));
251 dialog->addWidget(widget);
252
253 widget = new ProjectPreCompileWidget(tr("Precompiled Header"),tr("Project"));
254 dialog->addWidget(widget);
255
256 widget = new ProjectMakefileWidget(tr("Makefile"),tr("Project"));
257 dialog->addWidget(widget);
258
259 widget = new ProjectOutputWidget(tr("Output"),tr("Project"));
260 dialog->addWidget(widget);
261
262 widget = new ProjectDLLHostWidget(tr("DLL host"),tr("Project"));
263 dialog->addWidget(widget);
264
265#ifdef Q_OS_WIN
266 widget = new ProjectVersionInfoWidget(tr("Version info"),tr("Project"));
267 dialog->addWidget(widget);
268#endif
269
270 dialog->selectFirstWidget();
271
272 return dialog;
273}
274
275bool SettingsDialog::setCurrentWidget(const QString &widgetName, const QString &groupName)
276{
277 QList<QStandardItem*> items = model.findItems(groupName);
278 if (items.isEmpty())
279 return false;
280 QStandardItem* pGroupItem = items[0];
281 for (int i=0;i<pGroupItem->rowCount();i++) {
282 QStandardItem* pWidgetItem = pGroupItem->child(i);
283 if (pWidgetItem->text() == widgetName) {
284 ui->widgetsView->setCurrentIndex(pWidgetItem->index());
285 on_widgetsView_clicked(pWidgetItem->index());
286 return true;
287 }
288 }
289 return false;
290}
291
292
293void SettingsDialog::on_widgetsView_clicked(const QModelIndex &index)
294{
295 if (!index.isValid())
296 return;
297 int i = index.data(GetWidgetIndexRole).toInt();
298 if (i>=0) {
299 saveCurrentPageSettings(true);
300 SettingsWidget* pWidget = mSettingWidgets[i];
301 if (ui->scrollArea->widget()!=nullptr) {
302 QWidget* w = ui->scrollArea->takeWidget();
303 w->setParent(nullptr);
304 }
305 ui->scrollArea->setWidget(pWidget);
306 ui->lblWidgetCaption->setText(QString("%1 > %2").arg(pWidget->group()).arg(pWidget->name()));
307
308 ui->btnApply->setEnabled(false);
309 } else if (model.hasChildren(index)) {
310 ui->widgetsView->expand(index);
311 QModelIndex childIndex = this->model.index(0,0,index);
312 emit ui->widgetsView->clicked(childIndex);
313 }
314}
315
316void SettingsDialog::widget_settings_changed(bool value)
317{
318 ui->btnApply->setEnabled(value);
319}
320
321void SettingsDialog::on_btnCancel_pressed()
322{
323 this->close();
324}
325
326void SettingsDialog::on_btnApply_pressed()
327{
328 saveCurrentPageSettings(false);
329}
330
331void SettingsDialog::on_btnOk_pressed()
332{
333 saveCurrentPageSettings(false);
334 this->close();
335}
336
337void SettingsDialog::saveCurrentPageSettings(bool confirm)
338{
339 if (ui->scrollArea->widget()==ui->scrollAreaWidgetContents)
340 return;
341 SettingsWidget* pWidget = (SettingsWidget*) ui->scrollArea->widget();
342 if (!pWidget->isSettingsChanged())
343 return;
344 if (confirm) {
345 if (QMessageBox::warning(this,tr("Save Changes"),
346 tr("There are changes in the settings, do you want to save them before swtich to other page?"),
347 QMessageBox::Yes, QMessageBox::No)!=QMessageBox::Yes) {
348 return;
349 }
350 }
351 pWidget->save();
352}
353
354void SettingsDialog::closeEvent(QCloseEvent *event)
355{
356 pSettings->ui().setSettingsDialogWidth(width());
357 pSettings->ui().setSettingsDialogHeight(height());
358
359 QList<int> sizes = ui->splitter->sizes();
360 pSettings->ui().setSettingsDialogSplitterPos(sizes[0]);
361
362 QDialog::closeEvent(event);
363}
364
365bool SettingsDialog::appShouldQuit() const
366{
367 return mAppShouldQuit;
368}
369
370void SettingsDialog::closeAndQuit()
371{
372 mAppShouldQuit = true;
373 close();
374}
375