1 /****************************************************************************
2 **
3 ** Copyright (C) 2020 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25 
26 #pragma once
27 
28 #include "fileutils.h"
29 #include "id.h"
30 #include "infolabel.h"
31 #include "macroexpander.h"
32 #include "optional.h"
33 #include "pathchooser.h"
34 
35 #include <functional>
36 #include <memory>
37 
38 QT_BEGIN_NAMESPACE
39 class QAction;
40 class QGroupBox;
41 class QSettings;
42 QT_END_NAMESPACE
43 
44 namespace Utils {
45 
46 class AspectContainer;
47 class BoolAspect;
48 class LayoutBuilder;
49 
50 namespace Internal {
51 class AspectContainerPrivate;
52 class BaseAspectPrivate;
53 class BoolAspectPrivate;
54 class DoubleAspectPrivate;
55 class IntegerAspectPrivate;
56 class MultiSelectionAspectPrivate;
57 class SelectionAspectPrivate;
58 class StringAspectPrivate;
59 class StringListAspectPrivate;
60 class TextDisplayPrivate;
61 } // Internal
62 
63 class QTCREATOR_UTILS_EXPORT BaseAspect : public QObject
64 {
65     Q_OBJECT
66 
67 public:
68     BaseAspect();
69     ~BaseAspect() override;
70 
71     Utils::Id id() const;
72     void setId(Utils::Id id);
73 
74     QVariant value() const;
75     void setValue(const QVariant &value);
76     bool setValueQuietly(const QVariant &value);
77 
78     QVariant defaultValue() const;
79     void setDefaultValue(const QVariant &value);
80 
81     QString settingsKey() const;
82     void setSettingsKey(const QString &settingsKey);
83     void setSettingsKey(const QString &group, const QString &key);
84 
85     QString displayName() const;
86     void setDisplayName(const QString &displayName);
87 
88     QString toolTip() const;
89     void setToolTip(const QString &tooltip);
90 
91     bool isVisible() const;
92     void setVisible(bool visible);
93 
94     bool isAutoApply() const;
95     void setAutoApply(bool on);
96 
97     bool isEnabled() const;
98     void setEnabled(bool enabled);
99     void setEnabler(BoolAspect *checker);
100 
101     bool isReadOnly() const;
102     void setReadOnly(bool enabled);
103 
104     void setSpan(int x, int y = 1);
105 
106     QString labelText() const;
107     void setLabelText(const QString &labelText);
108     void setLabelPixmap(const QPixmap &labelPixmap);
109     void setIcon(const QIcon &labelIcon);
110 
111     using ConfigWidgetCreator = std::function<QWidget *()>;
112     void setConfigWidgetCreator(const ConfigWidgetCreator &configWidgetCreator);
113     QWidget *createConfigWidget() const;
114 
115     virtual QAction *action();
116 
117     virtual void fromMap(const QVariantMap &map);
118     virtual void toMap(QVariantMap &map) const;
toActiveMap(QVariantMap & map)119     virtual void toActiveMap(QVariantMap &map) const { toMap(map); }
120     virtual void acquaintSiblings(const AspectContainer &);
121 
122     virtual void addToLayout(LayoutBuilder &builder);
123 
124     virtual QVariant volatileValue() const;
125     virtual void setVolatileValue(const QVariant &val);
emitChangedValue()126     virtual void emitChangedValue() {}
127 
128     virtual void readSettings(const QSettings *settings);
129     virtual void writeSettings(QSettings *settings) const;
130 
131     using SavedValueTransformation = std::function<QVariant(const QVariant &)>;
132     void setFromSettingsTransformation(const SavedValueTransformation &transform);
133     void setToSettingsTransformation(const SavedValueTransformation &transform);
134     QVariant toSettingsValue(const QVariant &val) const;
135     QVariant fromSettingsValue(const QVariant &val) const;
136 
137     virtual void apply();
138     virtual void cancel();
139     virtual void finish();
140     bool isDirty() const;
141     bool hasAction() const;
142 
143 signals:
144     void changed();
145 
146 protected:
147     QLabel *label() const;
148     void setupLabel();
149     void addLabeledItem(LayoutBuilder &builder, QWidget *widget);
150 
151     template <class Widget, typename ...Args>
createSubWidget(Args &&...args)152     Widget *createSubWidget(Args && ...args) {
153         auto w = new Widget(args...);
154         registerSubWidget(w);
155         return w;
156     }
157 
158     void registerSubWidget(QWidget *widget);
159     static void saveToMap(QVariantMap &data, const QVariant &value,
160                           const QVariant &defaultValue, const QString &key);
161 
162 private:
163     std::unique_ptr<Internal::BaseAspectPrivate> d;
164 };
165 
166 class QTCREATOR_UTILS_EXPORT BoolAspect : public BaseAspect
167 {
168     Q_OBJECT
169 
170 public:
171     explicit BoolAspect(const QString &settingsKey = QString());
172     ~BoolAspect() override;
173 
174     void addToLayout(LayoutBuilder &builder) override;
175 
176     QAction *action() override;
177 
178     QVariant volatileValue() const override;
179     void setVolatileValue(const QVariant &val) override;
180     void emitChangedValue() override;
181 
182     bool value() const;
183     void setValue(bool val);
184     void setDefaultValue(bool val);
185 
186     enum class LabelPlacement { AtCheckBox, AtCheckBoxWithoutDummyLabel, InExtraLabel };
187     void setLabel(const QString &labelText,
188                   LabelPlacement labelPlacement = LabelPlacement::InExtraLabel);
189     void setLabelPlacement(LabelPlacement labelPlacement);
190     void setHandlesGroup(QGroupBox *box);
191 
192 signals:
193     void valueChanged(bool newValue);
194     void volatileValueChanged(bool newValue);
195 
196 private:
197     std::unique_ptr<Internal::BoolAspectPrivate> d;
198 };
199 
200 class QTCREATOR_UTILS_EXPORT SelectionAspect : public BaseAspect
201 {
202     Q_OBJECT
203 
204 public:
205     SelectionAspect();
206     ~SelectionAspect() override;
207 
208     void addToLayout(LayoutBuilder &builder) override;
209     QVariant volatileValue() const override;
210     void setVolatileValue(const QVariant &val) override;
211     void finish() override;
212 
213     int value() const;
214     void setValue(int val);
215     void setStringValue(const QString &val);
216     void setDefaultValue(int val);
217     void setDefaultValue(const QString &val);
218 
219     QString stringValue() const;
220     QVariant itemValue() const;
221 
222     enum class DisplayStyle { RadioButtons, ComboBox };
223     void setDisplayStyle(DisplayStyle style);
224 
225     class Option
226     {
227     public:
Option(const QString & displayName,const QString & toolTip,const QVariant & itemData)228         Option(const QString &displayName, const QString &toolTip, const QVariant &itemData)
229             : displayName(displayName), tooltip(toolTip), itemData(itemData)
230         {}
231         QString displayName;
232         QString tooltip;
233         QVariant itemData;
234         bool enabled = true;
235     };
236 
237     void addOption(const QString &displayName, const QString &toolTip = {});
238     void addOption(const Option &option);
239     int indexForDisplay(const QString &displayName) const;
240     QString displayForIndex(int index) const;
241     int indexForItemValue(const QVariant &value) const;
242     QVariant itemValueForIndex(int index) const;
243 
244 signals:
245     void volatileValueChanged(int newValue);
246 
247 private:
248     std::unique_ptr<Internal::SelectionAspectPrivate> d;
249 };
250 
251 class QTCREATOR_UTILS_EXPORT MultiSelectionAspect : public BaseAspect
252 {
253     Q_OBJECT
254 
255 public:
256     MultiSelectionAspect();
257     ~MultiSelectionAspect() override;
258 
259     void addToLayout(LayoutBuilder &builder) override;
260 
261     enum class DisplayStyle { ListView };
262     void setDisplayStyle(DisplayStyle style);
263 
264     QStringList value() const;
265     void setValue(const QStringList &val);
266 
267     QStringList allValues() const;
268     void setAllValues(const QStringList &val);
269 
270 private:
271     std::unique_ptr<Internal::MultiSelectionAspectPrivate> d;
272 };
273 
274 class QTCREATOR_UTILS_EXPORT StringAspect : public BaseAspect
275 {
276     Q_OBJECT
277 
278 public:
279     StringAspect();
280     ~StringAspect() override;
281 
282     void addToLayout(LayoutBuilder &builder) override;
283 
284     QVariant volatileValue() const override;
285     void setVolatileValue(const QVariant &val) override;
286     void emitChangedValue() override;
287 
288     // Hook between UI and StringAspect:
289     using ValueAcceptor = std::function<Utils::optional<QString>(const QString &, const QString &)>;
290     void setValueAcceptor(ValueAcceptor &&acceptor);
291     QString value() const;
292     void setValue(const QString &val);
293     void setDefaultValue(const QString &val);
294 
295     void setShowToolTipOnLabel(bool show);
296 
297     void setDisplayFilter(const std::function<QString (const QString &)> &displayFilter);
298     void setPlaceHolderText(const QString &placeHolderText);
299     void setHistoryCompleter(const QString &historyCompleterKey);
300     void setExpectedKind(const Utils::PathChooser::Kind expectedKind);
301     void setEnvironment(const Utils::Environment &env);
302     void setBaseFileName(const Utils::FilePath &baseFileName);
303     void setUndoRedoEnabled(bool readOnly);
304     void setAcceptRichText(bool acceptRichText);
305     void setMacroExpanderProvider(const Utils::MacroExpanderProvider &expanderProvider);
306     void setUseGlobalMacroExpander();
307     void setUseResetButton();
308     void setValidationFunction(const Utils::FancyLineEdit::ValidationFunction &validator);
309     void setOpenTerminalHandler(const std::function<void()> &openTerminal);
310     void setAutoApplyOnEditingFinished(bool applyOnEditingFinished);
311 
312     void validateInput();
313 
314     enum class UncheckedSemantics { Disabled, ReadOnly };
315     enum class CheckBoxPlacement { Top, Right };
316     void setUncheckedSemantics(UncheckedSemantics semantics);
317     bool isChecked() const;
318     void setChecked(bool checked);
319     void makeCheckable(CheckBoxPlacement checkBoxPlacement, const QString &optionalLabel,
320                        const QString &optionalBaseKey);
321 
322     enum DisplayStyle {
323         LabelDisplay,
324         LineEditDisplay,
325         TextEditDisplay,
326         PathChooserDisplay
327     };
328     void setDisplayStyle(DisplayStyle style);
329 
330     void fromMap(const QVariantMap &map) override;
331     void toMap(QVariantMap &map) const override;
332 
333     Utils::FilePath filePath() const;
334     void setFilePath(const Utils::FilePath &value);
335 
336     PathChooser *pathChooser() const; // Avoid to use.
337 
338 signals:
339     void checkedChanged();
340     void valueChanged(const QString &newValue);
341 
342 protected:
343     void update();
344 
345     std::unique_ptr<Internal::StringAspectPrivate> d;
346 };
347 
348 class QTCREATOR_UTILS_EXPORT IntegerAspect : public BaseAspect
349 {
350     Q_OBJECT
351 
352 public:
353     IntegerAspect();
354     ~IntegerAspect() override;
355 
356     void addToLayout(LayoutBuilder &builder) override;
357 
358     QVariant volatileValue() const override;
359     void setVolatileValue(const QVariant &val) override;
360 
361     qint64 value() const;
362     void setValue(qint64 val);
363     void setDefaultValue(qint64 defaultValue);
364 
365     void setRange(qint64 min, qint64 max);
366     void setLabel(const QString &label); // FIXME: Use setLabelText
367     void setPrefix(const QString &prefix);
368     void setSuffix(const QString &suffix);
369     void setDisplayIntegerBase(int base);
370     void setDisplayScaleFactor(qint64 factor);
371     void setSpecialValueText(const QString &specialText);
372     void setSingleStep(qint64 step);
373 
374 private:
375     std::unique_ptr<Internal::IntegerAspectPrivate> d;
376 };
377 
378 class QTCREATOR_UTILS_EXPORT DoubleAspect : public BaseAspect
379 {
380     Q_OBJECT
381 
382 public:
383     DoubleAspect();
384     ~DoubleAspect() override;
385 
386     void addToLayout(LayoutBuilder &builder) override;
387 
388     QVariant volatileValue() const override;
389     void setVolatileValue(const QVariant &val) override;
390 
391     double value() const;
392     void setValue(double val);
393     void setDefaultValue(double defaultValue);
394 
395     void setRange(double min, double max);
396     void setPrefix(const QString &prefix);
397     void setSuffix(const QString &suffix);
398     void setSpecialValueText(const QString &specialText);
399     void setSingleStep(double step);
400 
401 private:
402     std::unique_ptr<Internal::DoubleAspectPrivate> d;
403 };
404 
405 class QTCREATOR_UTILS_EXPORT TriState
406 {
407     enum Value { EnabledValue, DisabledValue, DefaultValue };
TriState(Value v)408     explicit TriState(Value v) : m_value(v) {}
409 
410 public:
411     TriState() = default;
412 
toVariant()413     QVariant toVariant() const { return int(m_value); }
414     static TriState fromVariant(const QVariant &variant);
415 
416     static const TriState Enabled;
417     static const TriState Disabled;
418     static const TriState Default;
419 
420     friend bool operator==(TriState a, TriState b) { return a.m_value == b.m_value; }
421     friend bool operator!=(TriState a, TriState b) { return a.m_value != b.m_value; }
422 
423 private:
424     Value m_value = DefaultValue;
425 };
426 
427 class QTCREATOR_UTILS_EXPORT TriStateAspect : public SelectionAspect
428 {
429     Q_OBJECT
430 public:
431     TriStateAspect(
432             const QString onString = tr("Enable"),
433             const QString &offString = tr("Disable"),
434             const QString &defaultString = tr("Leave at Default"));
435 
436     TriState value() const;
437     void setValue(TriState setting);
438     void setDefaultValue(TriState setting);
439 };
440 
441 class QTCREATOR_UTILS_EXPORT StringListAspect : public BaseAspect
442 {
443     Q_OBJECT
444 
445 public:
446     StringListAspect();
447     ~StringListAspect() override;
448 
449     void addToLayout(LayoutBuilder &builder) override;
450 
451     QStringList value() const;
452     void setValue(const QStringList &val);
453 
454     void appendValue(const QString &value, bool allowDuplicates = true);
455     void removeValue(const QString &value);
456     void appendValues(const QStringList &values, bool allowDuplicates = true);
457     void removeValues(const QStringList &values);
458 
459 private:
460     std::unique_ptr<Internal::StringListAspectPrivate> d;
461 };
462 
463 class QTCREATOR_UTILS_EXPORT IntegersAspect : public BaseAspect
464 {
465     Q_OBJECT
466 
467 public:
468     IntegersAspect();
469     ~IntegersAspect() override;
470 
471     void addToLayout(LayoutBuilder &builder) override;
472     void emitChangedValue() override;
473 
474     QList<int> value() const;
475     void setValue(const QList<int> &value);
476     void setDefaultValue(const QList<int> &value);
477 
478 signals:
479     void valueChanged(const QList<int> &values);
480 };
481 
482 class QTCREATOR_UTILS_EXPORT TextDisplay : public BaseAspect
483 {
484     Q_OBJECT
485 
486 public:
487     TextDisplay(const QString &message = {},
488                 Utils::InfoLabel::InfoType type = Utils::InfoLabel::None);
489     ~TextDisplay() override;
490 
491     void addToLayout(LayoutBuilder &builder) override;
492 
493     void setIconType(Utils::InfoLabel::InfoType t);
494     void setText(const QString &message);
495 
496 private:
497     std::unique_ptr<Internal::TextDisplayPrivate> d;
498 };
499 
500 class QTCREATOR_UTILS_EXPORT AspectContainer : public QObject
501 {
502     Q_OBJECT
503 
504 public:
505     AspectContainer(QObject *parent = nullptr);
506     ~AspectContainer();
507 
508     AspectContainer(const AspectContainer &) = delete;
509     AspectContainer &operator=(const AspectContainer &) = delete;
510 
511     void registerAspect(BaseAspect *aspect);
512     void registerAspects(const AspectContainer &aspects);
513 
514     template <class Aspect, typename ...Args>
addAspect(Args &&...args)515     Aspect *addAspect(Args && ...args)
516     {
517         auto aspect = new Aspect(args...);
518         registerAspect(aspect);
519         return aspect;
520     }
521 
522     void fromMap(const QVariantMap &map);
523     void toMap(QVariantMap &map) const;
524 
525     void readSettings(QSettings *settings);
526     void writeSettings(QSettings *settings) const;
527 
528     void setSettingsGroup(const QString &groupKey);
529     void setSettingsGroups(const QString &groupKey, const QString &subGroupKey);
530 
531     void apply();
532     void cancel();
533     void finish();
534 
535     void reset();
536     bool equals(const AspectContainer &other) const;
537     void copyFrom(const AspectContainer &other);
538     void setAutoApply(bool on);
539     void setOwnsSubAspects(bool on);
540     bool isDirty() const;
541 
aspect()542     template <typename T> T *aspect() const
543     {
544         for (BaseAspect *aspect : aspects())
545             if (T *result = qobject_cast<T *>(aspect))
546                 return result;
547         return nullptr;
548     }
549 
550     BaseAspect *aspect(Utils::Id id) const;
551 
aspect(Utils::Id id)552     template <typename T> T *aspect(Utils::Id id) const
553     {
554         return qobject_cast<T*>(aspect(id));
555     }
556 
557     void forEachAspect(const std::function<void(BaseAspect *)> &run) const;
558 
559     const QList<BaseAspect *> &aspects() const;
560 
561     using const_iterator = QList<BaseAspect *>::const_iterator;
562     using value_type = QList<BaseAspect *>::value_type;
563 
564     const_iterator begin() const;
565     const_iterator end() const;
566 
567 signals:
568     void applied();
569     void fromMapFinished();
570 
571 private:
572     std::unique_ptr<Internal::AspectContainerPrivate> d;
573 };
574 
575 } // namespace Utils
576