1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 Dmitry Savchenko
4 ** Copyright (C) 2016 Vasiliy Sorokin
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of Qt Creator.
8 **
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ****************************************************************************/
26 
27 #include "optionsdialog.h"
28 #include "ui_optionsdialog.h"
29 #include "keyworddialog.h"
30 #include "keyword.h"
31 #include "settings.h"
32 #include "constants.h"
33 
34 namespace Todo {
35 namespace Internal {
36 
37 class OptionsDialog final : public Core::IOptionsPageWidget
38 {
39     Q_DECLARE_TR_FUNCTIONS(Todo::Internal::TodoOptionsPage)
40 
41 public:
42     OptionsDialog(Settings *settings, const std::function<void ()> &onApply);
43 
44     void apply() final;
45 
46     void setSettings(const Settings &settings);
47 
48 private:
49     void addKeywordButtonClicked();
50     void editKeywordButtonClicked();
51     void removeKeywordButtonClicked();
52     void resetKeywordsButtonClicked();
53     void setKeywordsButtonsEnabled();
54     Settings settingsFromUi();
55     void addToKeywordsList(const Keyword &keyword);
56     void editKeyword(QListWidgetItem *item);
57     QSet<QString> keywordNames();
58 
59     Ui::OptionsDialog ui;
60     Settings *m_settings = nullptr;
61     std::function<void()> m_onApply;
62 };
63 
OptionsDialog(Settings * settings,const std::function<void ()> & onApply)64 OptionsDialog::OptionsDialog(Settings *settings, const std::function<void ()> &onApply)
65     : m_settings(settings), m_onApply(onApply)
66 {
67     ui.setupUi(this);
68     ui.keywordsList->setIconSize(QSize(16, 16));
69     setKeywordsButtonsEnabled();
70     connect(ui.addKeywordButton, &QAbstractButton::clicked,
71             this, &OptionsDialog::addKeywordButtonClicked);
72     connect(ui.removeKeywordButton, &QAbstractButton::clicked,
73             this, &OptionsDialog::removeKeywordButtonClicked);
74     connect(ui.editKeywordButton, &QAbstractButton::clicked,
75             this, &OptionsDialog::editKeywordButtonClicked);
76     connect(ui.resetKeywordsButton, &QAbstractButton::clicked,
77             this, &OptionsDialog::resetKeywordsButtonClicked);
78     connect(ui.keywordsList, &QListWidget::itemDoubleClicked,
79             this, &OptionsDialog::editKeyword);
80     connect(ui.keywordsList, &QListWidget::itemSelectionChanged,
81             this, &OptionsDialog::setKeywordsButtonsEnabled);
82 
83     setSettings(*m_settings);
84 }
85 
addToKeywordsList(const Keyword & keyword)86 void OptionsDialog::addToKeywordsList(const Keyword &keyword)
87 {
88     auto item = new QListWidgetItem(icon(keyword.iconType), keyword.name);
89     item->setData(Qt::UserRole, static_cast<int>(keyword.iconType));
90     item->setForeground(keyword.color);
91     ui.keywordsList->addItem(item);
92 }
93 
keywordNames()94 QSet<QString> OptionsDialog::keywordNames()
95 {
96     const KeywordList keywords = settingsFromUi().keywords;
97 
98     QSet<QString> result;
99     for (const Keyword &keyword : keywords)
100         result << keyword.name;
101 
102     return result;
103 }
104 
addKeywordButtonClicked()105 void OptionsDialog::addKeywordButtonClicked()
106 {
107     Keyword keyword;
108     KeywordDialog keywordDialog(keyword, keywordNames(), this);
109     if (keywordDialog.exec() == QDialog::Accepted) {
110         keyword = keywordDialog.keyword();
111         addToKeywordsList(keyword);
112     }
113 }
114 
editKeywordButtonClicked()115 void OptionsDialog::editKeywordButtonClicked()
116 {
117     QListWidgetItem *item = ui.keywordsList->currentItem();
118     editKeyword(item);
119 }
120 
editKeyword(QListWidgetItem * item)121 void OptionsDialog::editKeyword(QListWidgetItem *item)
122 {
123     Keyword keyword;
124     keyword.name = item->text();
125     keyword.iconType = static_cast<IconType>(item->data(Qt::UserRole).toInt());
126     keyword.color = item->foreground().color();
127 
128     QSet<QString> keywordNamesButThis = keywordNames();
129     keywordNamesButThis.remove(keyword.name);
130 
131     KeywordDialog keywordDialog(keyword, keywordNamesButThis, this);
132     if (keywordDialog.exec() == QDialog::Accepted) {
133         keyword = keywordDialog.keyword();
134         item->setIcon(icon(keyword.iconType));
135         item->setText(keyword.name);
136         item->setData(Qt::UserRole, static_cast<int>(keyword.iconType));
137         item->setForeground(keyword.color);
138     }
139 }
140 
removeKeywordButtonClicked()141 void OptionsDialog::removeKeywordButtonClicked()
142 {
143     delete ui.keywordsList->takeItem(ui.keywordsList->currentRow());
144 }
145 
resetKeywordsButtonClicked()146 void OptionsDialog::resetKeywordsButtonClicked()
147 {
148     Settings newSettings;
149     newSettings.setDefault();
150     setSettings(newSettings);
151 }
152 
setKeywordsButtonsEnabled()153 void OptionsDialog::setKeywordsButtonsEnabled()
154 {
155     const bool isSomethingSelected = !ui.keywordsList->selectedItems().isEmpty();
156     ui.removeKeywordButton->setEnabled(isSomethingSelected);
157     ui.editKeywordButton->setEnabled(isSomethingSelected);
158 }
159 
setSettings(const Settings & settings)160 void OptionsDialog::setSettings(const Settings &settings)
161 {
162     ui.scanInCurrentFileRadioButton->setChecked(settings.scanningScope == ScanningScopeCurrentFile);
163     ui.scanInProjectRadioButton->setChecked(settings.scanningScope == ScanningScopeProject);
164     ui.scanInSubprojectRadioButton->setChecked(settings.scanningScope == ScanningScopeSubProject);
165 
166     ui.keywordsList->clear();
167     for (const Keyword &keyword : qAsConst(settings.keywords))
168         addToKeywordsList(keyword);
169 }
170 
settingsFromUi()171 Settings OptionsDialog::settingsFromUi()
172 {
173     Settings settings;
174 
175     if (ui.scanInCurrentFileRadioButton->isChecked())
176         settings.scanningScope = ScanningScopeCurrentFile;
177     else if (ui.scanInSubprojectRadioButton->isChecked())
178         settings.scanningScope = ScanningScopeSubProject;
179     else
180         settings.scanningScope = ScanningScopeProject;
181 
182     settings.keywords.clear();
183     for (int i = 0; i < ui.keywordsList->count(); ++i) {
184         QListWidgetItem *item = ui.keywordsList->item(i);
185 
186         Keyword keyword;
187         keyword.name = item->text();
188         keyword.iconType = static_cast<IconType>(item->data(Qt::UserRole).toInt());
189         keyword.color = item->foreground().color();
190 
191         settings.keywords << keyword;
192     }
193 
194     return settings;
195 }
196 
apply()197 void OptionsDialog::apply()
198 {
199     Settings newSettings = settingsFromUi();
200 
201     // "apply" itself is interpreted as "use these keywords, also for other themes".
202     newSettings.keywordsEdited = true;
203 
204     if (newSettings == *m_settings)
205         return;
206 
207     *m_settings = newSettings;
208     m_onApply();
209 }
210 
211 // TodoOptionsPage
212 
TodoOptionsPage(Settings * settings,const std::function<void ()> & onApply)213 TodoOptionsPage::TodoOptionsPage(Settings *settings, const std::function<void ()> &onApply)
214 {
215     setId("TodoSettings");
216     setDisplayName(OptionsDialog::tr("To-Do"));
217     setCategory("To-Do");
218     setDisplayCategory(OptionsDialog::tr("To-Do"));
219     setCategoryIconPath(":/todoplugin/images/settingscategory_todo.png");
220     setWidgetCreator([settings, onApply] { return new OptionsDialog(settings, onApply); });
221 }
222 
223 } // namespace Internal
224 } // namespace Todo
225