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 "formattergeneralwidget.h"
18#include "ui_formattergeneralwidget.h"
19#include "../settings.h"
20
21FormatterGeneralWidget::FormatterGeneralWidget(const QString& name, const QString& group, QWidget *parent):
22 SettingsWidget(name,group,parent),
23 ui(new Ui::FormatterGeneralWidget)
24{
25 ui->setupUi(this);
26 ui->cbBraceStyle->setModel(&mStylesModel);
27 connect(ui->cbBraceStyle, QOverload<int>::of(&QComboBox::currentIndexChanged),
28 this, &FormatterGeneralWidget::onBraceStyleChanged);
29 ui->editDemo->setReadOnly(true);
30 connect(this, &SettingsWidget::settingsChanged,
31 this, &FormatterGeneralWidget::updateDemo);
32}
33
34FormatterGeneralWidget::~FormatterGeneralWidget()
35{
36 delete ui;
37}
38
39void FormatterGeneralWidget::onBraceStyleChanged()
40{
41 PFormatterStyleItem item = mStylesModel.getStyle(ui->cbBraceStyle->currentIndex());
42 if (item) {
43 ui->lblBraceStyle->setText(item->description);
44 }
45}
46
47void FormatterGeneralWidget::doLoad()
48{
49 Settings::CodeFormatter& format = pSettings->codeFormatter();
50 for (int i=0;i<mStylesModel.rowCount(QModelIndex());i++) {
51 PFormatterStyleItem item = mStylesModel.getStyle(i);
52 if (item->style == format.braceStyle()) {
53 ui->cbBraceStyle->setCurrentIndex(i);
54 break;
55 }
56 }
57 if (format.indentStyle() == FormatterIndentType::fitSpace) {
58 ui->rbIndentSpaces->setChecked(true);
59 } else {
60 ui->rbIndentTabs->setChecked(true);
61 }
62 ui->spinTabSize->setValue(format.tabWidth());
63 ui->chkAttachNamespaces->setChecked(format.attachNamespaces());
64 ui->chkAttachClasses->setChecked(format.attachClasses());
65 ui->chkAttachInline->setChecked(format.attachInlines());
66 ui->chkAttachExternC->setChecked(format.attachExternC());
67 ui->chkAttachClosingWhile->setChecked(format.attachClosingWhile());
68 ui->chkIndentClasses->setChecked(format.indentClasses());
69 ui->chkIndentModifiers->setChecked(format.indentModifiers());
70 ui->chkIndentSwiches->setChecked(format.indentSwitches());
71 ui->chkIndentCases->setChecked(format.indentCases());
72 ui->chkIndentNamespaces->setChecked(format.indentNamespaces());
73 ui->chkIndentAfterParens->setChecked(format.indentAfterParens());
74 ui->spinIndentContinuation->setValue(format.indentContinuation());
75 ui->chkIndentLabels->setChecked(format.indentLabels());
76 ui->chkIndentPreprocBlock->setChecked(format.indentPreprocBlock());
77 ui->chkIndentPreprocCond->setChecked(format.indentPreprocCond());
78 ui->chkIndentPreprocDefine->setChecked(format.indentPreprocDefine());
79 ui->chkIndentCol1Comments->setChecked(format.indentCol1Comments());
80 ui->spinMinConditionalIndent->setValue(format.minConditionalIndent());
81 ui->spinMaxContinuationIndent->setValue(format.maxContinuationIndent());
82 ui->chkBreakBlocks->setChecked(format.breakBlocks());
83 ui->chkBreakBlocksAll->setChecked(format.breakBlocksAll());
84 ui->chkPadOper->setChecked(format.padOper());
85 ui->chkPadComma->setChecked(format.padComma());
86 ui->chkPadParen->setChecked(format.padParen());
87 ui->chkPadParenOut->setChecked(format.padParenOut());
88 ui->chkPadFirstParenOut->setChecked(format.padFirstParenOut());
89 ui->chkPadParenIn->setChecked(format.padParenIn());
90 ui->chkPadHeader->setChecked(format.padHeader());
91 ui->chkUnpadParen->setChecked(format.unpadParen());
92 ui->chkDeleteEmptyLines->setChecked(format.deleteEmptyLines());
93 ui->chkDeleteMultipleEmptyLines->setChecked(format.deleteMultipleEmptyLines());
94 ui->chkFillEmptyLines->setChecked(format.fillEmptyLines());
95 switch(format.alignPointerStyle()) {
96 case FormatterOperatorAlign::foaNone:
97 ui->rbAlignPointNone->setChecked(true);
98 break;
99 case FormatterOperatorAlign::foaType:
100 ui->rbAlignPointType->setChecked(true);
101 break;
102 case FormatterOperatorAlign::foaMiddle:
103 ui->rbAlignPointerMiddle->setChecked(true);
104 break;
105 case FormatterOperatorAlign::foaName:
106 ui->rbAlignPointerName->setChecked(true);
107 break;
108 }
109 switch(format.alignReferenceStyle()) {
110 case FormatterOperatorAlign::foaNone:
111 ui->rbAlignReferenceNone->setChecked(true);
112 break;
113 case FormatterOperatorAlign::foaType:
114 ui->rbAlignReferenceType->setChecked(true);
115 break;
116 case FormatterOperatorAlign::foaMiddle:
117 ui->rbAlignReferenceMiddle->setChecked(true);
118 break;
119 case FormatterOperatorAlign::foaName:
120 ui->rbAlignReferenceName->setChecked(true);
121 break;
122 }
123 ui->chkBreakClosingBraces->setChecked(format.breakClosingBraces());
124 ui->chkBreakElseIf->setChecked(format.breakElseIf());
125 ui->chkBreakOneLineHeaders->setChecked(format.breakOneLineHeaders());
126 ui->chkAddBraces->setChecked(format.addBraces());
127 ui->chkAddOneLineBraces->setChecked(format.addOneLineBraces());
128 ui->chkRemoveBraces->setChecked(format.removeBraces());
129 ui->chkBreakReturnType->setChecked(format.breakReturnType());
130 ui->chkBreakReturnTypeDecl->setChecked(format.breakReturnTypeDecl());
131 ui->chkAttachReturnType->setChecked(format.attachReturnType());
132 ui->chkAttachReturnTypeDecl->setChecked(format.attachReturnTypeDecl());
133 ui->chkKeepOneLineBlocks->setChecked(format.keepOneLineBlocks());
134 ui->chkKeepOneLineStatements->setChecked(format.keepOneLineStatements());
135 ui->chkConvertTabs->setChecked(format.convertTabs());
136 ui->chkCloseTemplates->setChecked(format.closeTemplates());
137 ui->chkRemoveCommentPrefix->setChecked(format.removeCommentPrefix());
138 ui->chkBreakMaxCodeLength->setChecked(format.breakMaxCodeLength());
139 ui->spinMaxCodeLength->setValue(format.maxCodeLength());
140 ui->chkBreakAfterLogical->setChecked(format.breakAfterLogical());
141 updateDemo();
142}
143
144void FormatterGeneralWidget::doSave()
145{
146 Settings::CodeFormatter& format = pSettings->codeFormatter();
147 updateCodeFormatter(format);
148 format.save();
149}
150
151FormatterStyleModel::FormatterStyleModel(QObject *parent):QAbstractListModel(parent)
152{
153 mStyles.append(
154 std::make_shared<FormatterStyleItem>(
155 tr("Default"),
156 tr("The opening braces will not be changed and closing braces will be broken from the preceding line."),
157 FormatterBraceStyle::fbsDefault)
158 );
159 mStyles.append(
160 std::make_shared<FormatterStyleItem>(
161 tr("Allman"),
162 tr("Broken braces."),
163 FormatterBraceStyle::fbsAllman)
164 );
165 mStyles.append(
166 std::make_shared<FormatterStyleItem>(
167 tr("Java"),
168 tr("Attached braces."),
169 FormatterBraceStyle::fbsJava)
170 );
171 mStyles.append(
172 std::make_shared<FormatterStyleItem>(
173 tr("K&R"),
174 tr("Linux braces."),
175 FormatterBraceStyle::fbsKR)
176 );
177 mStyles.append(
178 std::make_shared<FormatterStyleItem>(
179 tr("Stroustrup"),
180 tr("Linux braces, with broken closing headers."),
181 FormatterBraceStyle::fbsStroustrup)
182 );
183 mStyles.append(
184 std::make_shared<FormatterStyleItem>(
185 tr("Whitesmith"),
186 tr("Broken, indented braces.")
187 + " "
188 +tr("Indented class blocks and switch blocks."),
189 FormatterBraceStyle::fbsWitesmith)
190 );
191 mStyles.append(
192 std::make_shared<FormatterStyleItem>(
193 tr("VTK"),
194 tr("Broken, indented braces except for the opening braces."),
195 FormatterBraceStyle::fbsVtk)
196 );
197 mStyles.append(
198 std::make_shared<FormatterStyleItem>(
199 tr("Ratliff"),
200 tr("Attached, indented braces."),
201 FormatterBraceStyle::fbsRatliff)
202 );
203 mStyles.append(
204 std::make_shared<FormatterStyleItem>(
205 tr("GNU"),
206 tr("Broken braces, indented blocks."),
207 FormatterBraceStyle::fbsGNU)
208 );
209 mStyles.append(
210 std::make_shared<FormatterStyleItem>(
211 tr("Linux"),
212 tr("Linux braces, minimum conditional indent is one-half indent."),
213 FormatterBraceStyle::fbsLinux)
214 );
215 mStyles.append(
216 std::make_shared<FormatterStyleItem>(
217 tr("Horstmann"),
218 tr("Run-in braces, indented switches."),
219 FormatterBraceStyle::fbsHorstmann)
220 );
221 mStyles.append(
222 std::make_shared<FormatterStyleItem>(
223 tr("One True Brace"),
224 tr("Linux braces, add braces to all conditionals."),
225 FormatterBraceStyle::fbs1TBS)
226 );
227 mStyles.append(
228 std::make_shared<FormatterStyleItem>(
229 tr("Google"),
230 tr("Attached braces, indented class modifiers."),
231 FormatterBraceStyle::fbsGoogle)
232 );
233 mStyles.append(
234 std::make_shared<FormatterStyleItem>(
235 tr("Mozilla"),
236 tr("Linux braces, with broken braces for structs and enums, and attached braces for namespaces."),
237 FormatterBraceStyle::fbsMozilla)
238 );
239 mStyles.append(
240 std::make_shared<FormatterStyleItem>(
241 tr("Webkit"),
242 tr("Linux braces, with attached closing headers."),
243 FormatterBraceStyle::fbsWebkit)
244 );
245 mStyles.append(
246 std::make_shared<FormatterStyleItem>(
247 tr("Pico"),
248 tr("Run-in opening braces and attached closing braces.")
249 +" "+
250 tr("Uses keep one line blocks and keep one line statements."),
251 FormatterBraceStyle::fbsPico)
252 );
253 mStyles.append(
254 std::make_shared<FormatterStyleItem>(
255 tr("Lisp"),
256 tr("Attached opening braces and attached closing braces.")
257 +" "+
258 tr("Uses keep one line statements."),
259 FormatterBraceStyle::fbsLisp)
260 );
261}
262
263int FormatterStyleModel::rowCount(const QModelIndex &) const
264{
265 return mStyles.count();
266}
267
268QVariant FormatterStyleModel::data(const QModelIndex &index, int role) const
269{
270 if (!index.isValid())
271 return QVariant();
272 int row = index.row();
273 if (row<0 || row>=mStyles.count())
274 return QVariant();
275 PFormatterStyleItem item = mStyles[row];
276 switch (role) {
277 case Qt::DisplayRole:
278 return item->name;
279 case Qt::ToolTipRole:
280 return item->description;
281 }
282 return QVariant();
283}
284
285PFormatterStyleItem FormatterStyleModel::getStyle(const QModelIndex &index)
286{
287 if (index.isValid()) {
288 return getStyle(index.row());
289 } else {
290 return PFormatterStyleItem();
291 }
292}
293
294PFormatterStyleItem FormatterStyleModel::getStyle(int index)
295{
296 if (index<0 || index>=mStyles.count())
297 return PFormatterStyleItem();
298 return mStyles[index];
299}
300
301FormatterStyleItem::FormatterStyleItem(const QString &name, const QString &description, FormatterBraceStyle style)
302{
303 this->name = name;
304 this->description = description;
305 this->style = style;
306}
307
308void FormatterGeneralWidget::on_chkBreakMaxCodeLength_stateChanged(int)
309{
310 ui->spinMaxCodeLength->setEnabled(ui->chkBreakMaxCodeLength->isChecked());
311 ui->chkBreakAfterLogical->setEnabled(ui->chkBreakMaxCodeLength->isChecked());
312}
313
314void FormatterGeneralWidget::updateDemo()
315{
316 QFile file(":/codes/formatdemo.cpp");
317 if (!file.open(QFile::ReadOnly))
318 return;
319 QByteArray content = file.readAll();
320
321 Settings::CodeFormatter formatter(nullptr);
322 updateCodeFormatter(formatter);
323
324 QByteArray newContent = runAndGetOutput("astyle.exe",
325 pSettings->dirs().appDir(),
326 formatter.getArguments(),
327 content);
328 ui->editDemo->document()->setText(newContent);
329}
330
331void FormatterGeneralWidget::updateCodeFormatter(Settings::CodeFormatter &format)
332{
333 PFormatterStyleItem item = mStylesModel.getStyle(ui->cbBraceStyle->currentIndex());
334 if (item)
335 format.setBraceStyle(item->style);
336 if (ui->rbIndentSpaces->isChecked()) {
337 format.setIndentStyle(FormatterIndentType::fitSpace);
338 } else {
339 format.setIndentStyle(FormatterIndentType::fitTab);
340 }
341 format.setTabWidth(ui->spinTabSize->value());
342 format.setAttachNamespaces(ui->chkAttachNamespaces->isChecked());
343 format.setAttachClasses(ui->chkAttachClasses->isChecked());
344 format.setAttachInlines(ui->chkAttachInline->isChecked());
345 format.setAttachExternC(ui->chkAttachExternC->isChecked());
346 format.setAttachClosingWhile(ui->chkAttachClosingWhile->isChecked());
347 format.setIndentClasses(ui->chkIndentClasses->isChecked());
348 format.setIndentModifiers(ui->chkIndentModifiers->isChecked());
349 format.setIndentSwitches(ui->chkIndentSwiches->isChecked());
350 format.setIndentCases(ui->chkIndentCases->isChecked());
351 format.setIndentNamespaces(ui->chkIndentNamespaces->isChecked());
352 format.setIndentAfterParens(ui->chkIndentAfterParens->isChecked());
353 format.setIndentContinuation(ui->spinIndentContinuation->value());
354 format.setIndentLabels(ui->chkIndentLabels->isChecked());
355 format.setIndentPreprocBlock(ui->chkIndentPreprocBlock->isChecked());
356 format.setIndentPreprocCond(ui->chkIndentPreprocCond->isChecked());
357 format.setIndentPreprocDefine(ui->chkIndentPreprocDefine->isChecked());
358 format.setIndentCol1Comments(ui->chkIndentCol1Comments->isChecked());
359 format.setMinConditionalIndent(ui->spinMinConditionalIndent->value());
360 format.setMaxContinuationIndent(ui->spinMaxContinuationIndent->value());
361 format.setBreakBlocks(ui->chkBreakBlocks->isChecked());
362 format.setBreakBlocksAll(ui->chkBreakBlocksAll->isChecked());
363 format.setPadOper(ui->chkPadOper->isChecked());
364 format.setPadComma(ui->chkPadComma->isChecked());
365 format.setPadParen(ui->chkPadParen->isChecked());
366 format.setPadParenOut(ui->chkPadParenOut->isChecked());
367 format.setPadFirstParenOut(ui->chkPadFirstParenOut->isChecked());
368 format.setPadParenIn(ui->chkPadParenIn->isChecked());
369 format.setPadHeader(ui->chkPadHeader->isChecked());
370 format.setUnpadParen(ui->chkUnpadParen->isChecked());
371 format.setDeleteEmptyLines(ui->chkDeleteEmptyLines->isChecked());
372 format.setDeleteMultipleEmptyLines(ui->chkDeleteMultipleEmptyLines->isChecked());
373 format.setFillEmptyLines(ui->chkFillEmptyLines->isChecked());
374 if (ui->rbAlignPointNone->isChecked()) {
375 format.setAlignPointerStyle(FormatterOperatorAlign::foaNone);
376 } else if (ui->rbAlignPointType->isChecked()) {
377 format.setAlignPointerStyle(FormatterOperatorAlign::foaType);
378 } else if (ui->rbAlignPointerMiddle->isChecked()) {
379 format.setAlignPointerStyle(FormatterOperatorAlign::foaMiddle);
380 } else if (ui->rbAlignPointerName->isChecked()) {
381 format.setAlignPointerStyle(FormatterOperatorAlign::foaName);
382 }
383 if (ui->rbAlignReferenceNone->isChecked()) {
384 format.setAlignReferenceStyle(FormatterOperatorAlign::foaNone);
385 } else if (ui->rbAlignReferenceType->isChecked()) {
386 format.setAlignReferenceStyle(FormatterOperatorAlign::foaType);
387 } else if (ui->rbAlignReferenceMiddle->isChecked()) {
388 format.setAlignReferenceStyle(FormatterOperatorAlign::foaMiddle);
389 } else if (ui->rbAlignReferenceName->isChecked()) {
390 format.setAlignReferenceStyle(FormatterOperatorAlign::foaName);
391 }
392 format.setBreakClosingBraces(ui->chkBreakClosingBraces->isChecked());
393 format.setBreakElseIf(ui->chkBreakElseIf->isChecked());
394 format.setBreakOneLineHeaders(ui->chkBreakOneLineHeaders->isChecked());
395 format.setAddBraces(ui->chkAddBraces->isChecked());
396 format.setAddOneLineBraces(ui->chkAddOneLineBraces->isChecked());
397 format.setRemoveBraces(ui->chkRemoveBraces->isChecked());
398 format.setBreakReturnType(ui->chkBreakReturnType->isChecked());
399 format.setBreakReturnTypeDecl(ui->chkBreakReturnTypeDecl->isChecked());
400 format.setAttachReturnType(ui->chkAttachReturnType->isChecked());
401 format.setAttachReturnTypeDecl(ui->chkAttachReturnTypeDecl->isChecked());
402 format.setKeepOneLineBlocks(ui->chkKeepOneLineBlocks->isChecked());
403 format.setKeepOneLineStatements(ui->chkKeepOneLineStatements->isChecked());
404 format.setConvertTabs(ui->chkConvertTabs->isChecked());
405 format.setCloseTemplates(ui->chkCloseTemplates->isChecked());
406 format.setRemoveCommentPrefix(ui->chkRemoveCommentPrefix->isChecked());
407 format.setBreakMaxCodeLength(ui->chkBreakMaxCodeLength->isChecked());
408 format.setMaxCodeLength(ui->spinMaxCodeLength->value());
409 format.setBreakAfterLogical(ui->chkBreakAfterLogical->isChecked());
410}
411
412