diff --git a/share/qtcreator/themes/dark.creatortheme b/share/qtcreator/themes/dark.creatortheme
index a7dcedd104a..c2846fa0940 100644
--- a/share/qtcreator/themes/dark.creatortheme
+++ b/share/qtcreator/themes/dark.creatortheme
@@ -1,4 +1,5 @@
[General]
+Includes=dark.figmatokens
ThemeName=Dark
PreferredStyles=
DefaultTextEditorColorScheme=dark.xml
@@ -406,39 +407,6 @@ Debugger_WatchItem_ValueChanged=ffff6666
Debugger_Breakpoint_TextMarkColor=ffff4040
-; Qt Creator Color Tokens - dark mode
-Token_Basic_Black=ff131313
-Token_Basic_White=fff8f8f8
-Token_Accent_Default=ff23b26a
-Token_Accent_Muted=ff1f9b5d
-Token_Accent_Subtle=ff1a8550
-Token_Background_Default=ff1f1f1f
-Token_Background_Muted=ff262626
-Token_Background_Subtle=ff2e2e2e
-Token_Foreground_Default=ff5a5a5a
-Token_Foreground_Muted=ff3e3e3e
-Token_Foreground_Subtle=ff303030
-Token_Text_Default=fff8f8f8
-Token_Text_Muted=ffaeaeae
-Token_Text_Subtle=ff595959
-Token_Stroke_Strong=ffeeeeee
-Token_Stroke_Muted=ff727272
-Token_Stroke_Subtle=ff3a3a3a
-Token_Notification_Alert=ffc98014
-Token_Notification_Success=ff1f9b5d
-Token_Notification_Neutral=ff016876
-Token_Notification_Danger=ffb22245
-
-Welcome_TextColor=text
-Welcome_ForegroundPrimaryColor=ffa3a3a3
-Welcome_ForegroundSecondaryColor=ff808080
-Welcome_BackgroundPrimaryColor=normalBackground
-Welcome_BackgroundSecondaryColor=shadowBackground
-Welcome_HoverColor=ff404040
-Welcome_AccentColor=ff57d658
-Welcome_LinkColor=ff67e668
-Welcome_DisabledLinkColor=textDisabled
-
Timeline_TextColor=text
Timeline_BackgroundColor1=normalBackground
Timeline_BackgroundColor2=ff444444
diff --git a/share/qtcreator/themes/dark.figmatokens b/share/qtcreator/themes/dark.figmatokens
new file mode 100644
index 00000000000..fdd98e80c10
--- /dev/null
+++ b/share/qtcreator/themes/dark.figmatokens
@@ -0,0 +1,31 @@
+; Qt Creator Color Tokens - dark mode
+
+[Colors]
+
+Token_Basic_Black=ff131313
+Token_Basic_White=fff8f8f8
+
+Token_Accent_Default=ff23b26a
+Token_Accent_Muted=ff1f9b5d
+Token_Accent_Subtle=ff1a8550
+
+Token_Background_Default=ff1f1f1f
+Token_Background_Muted=ff262626
+Token_Background_Subtle=ff2e2e2e
+
+Token_Foreground_Default=ff5a5a5a
+Token_Foreground_Muted=ff3e3e3e
+Token_Foreground_Subtle=ff303030
+
+Token_Text_Default=fff8f8f8
+Token_Text_Muted=ffaeaeae
+Token_Text_Subtle=ff595959
+
+Token_Stroke_Strong=ffeeeeee
+Token_Stroke_Muted=ff727272
+Token_Stroke_Subtle=ff3a3a3a
+
+Token_Notification_Alert=ffc98014
+Token_Notification_Success=ff1f9b5d
+Token_Notification_Neutral=ff016876
+Token_Notification_Danger=ffb22245
diff --git a/share/qtcreator/themes/default.creatortheme b/share/qtcreator/themes/default.creatortheme
index 2dee7ab2469..f2c4c7f7a43 100644
--- a/share/qtcreator/themes/default.creatortheme
+++ b/share/qtcreator/themes/default.creatortheme
@@ -1,4 +1,5 @@
[General]
+Includes=light.figmatokens
ThemeName=Classic
PreferredStyles=
@@ -398,39 +399,6 @@ Debugger_WatchItem_ValueChanged=ffc80000
Debugger_Breakpoint_TextMarkColor=ffff4040
-; Qt Creator Color Tokens - light mode
-Token_Basic_Black=ff131313
-Token_Basic_White=fff2f2f2
-Token_Accent_Default=ff23b26a
-Token_Accent_Muted=ff1f9b5d
-Token_Accent_Subtle=ff1a8550
-Token_Background_Default=ffe3e3e3
-Token_Background_Muted=ffeeeeee
-Token_Background_Subtle=fffbfbfb
-Token_Foreground_Default=ffcdcdcd
-Token_Foreground_Muted=ffd5d5d5
-Token_Foreground_Subtle=ffdddddd
-Token_Text_Default=ff393939
-Token_Text_Muted=ff7c7c7c
-Token_Text_Subtle=ffbebebe
-Token_Stroke_Strong=ff464646
-Token_Stroke_Muted=ff727272
-Token_Stroke_Subtle=ffcdcdcd
-Token_Notification_Alert=ffeb991f
-Token_Notification_Success=ff23b26a
-Token_Notification_Neutral=ff0e7887
-Token_Notification_Danger=ffdc1343
-
-Welcome_TextColor=ff000000
-Welcome_ForegroundPrimaryColor=shadowBackground
-Welcome_ForegroundSecondaryColor=ff939393
-Welcome_BackgroundPrimaryColor=fffafafa
-Welcome_BackgroundSecondaryColor=ffffffff
-Welcome_HoverColor=ffefefef
-Welcome_AccentColor=ff45ce55
-Welcome_LinkColor=ff20a020
-Welcome_DisabledLinkColor=textDisabled
-
Timeline_TextColor=darkText
Timeline_BackgroundColor1=ffffffff
Timeline_BackgroundColor2=fff6f6f6
diff --git a/share/qtcreator/themes/design-light.creatortheme b/share/qtcreator/themes/design-light.creatortheme
index 8931b620424..41a9f07ba84 100644
--- a/share/qtcreator/themes/design-light.creatortheme
+++ b/share/qtcreator/themes/design-light.creatortheme
@@ -1,4 +1,5 @@
[General]
+Includes=light.figmatokens
ThemeName=Design Light
PreferredStyles=
@@ -410,39 +411,6 @@ Debugger_WatchItem_ValueChanged=ffbf0303
Debugger_Breakpoint_TextMarkColor=ffff4040
-; Qt Creator Color Tokens - light mode
-Token_Basic_Black=ff131313
-Token_Basic_White=fff2f2f2
-Token_Accent_Default=ff23b26a
-Token_Accent_Muted=ff1f9b5d
-Token_Accent_Subtle=ff1a8550
-Token_Background_Default=ffe3e3e3
-Token_Background_Muted=ffeeeeee
-Token_Background_Subtle=fffbfbfb
-Token_Foreground_Default=ffcdcdcd
-Token_Foreground_Muted=ffd5d5d5
-Token_Foreground_Subtle=ffdddddd
-Token_Text_Default=ff393939
-Token_Text_Muted=ff7c7c7c
-Token_Text_Subtle=ffbebebe
-Token_Stroke_Strong=ff464646
-Token_Stroke_Muted=ff727272
-Token_Stroke_Subtle=ffcdcdcd
-Token_Notification_Alert=ffeb991f
-Token_Notification_Success=ff23b26a
-Token_Notification_Neutral=ff0e7887
-Token_Notification_Danger=ffdc1343
-
-Welcome_TextColor=ff000000
-Welcome_ForegroundPrimaryColor=ff404040
-Welcome_ForegroundSecondaryColor=ff727272
-Welcome_BackgroundPrimaryColor=ffeaeaea
-Welcome_BackgroundSecondaryColor=ffefefef
-Welcome_HoverColor=ffe1e1e1
-Welcome_AccentColor=ff25709a
-Welcome_LinkColor=ff104090
-Welcome_DisabledLinkColor=textDisabled
-
Timeline_TextColor=text
Timeline_BackgroundColor1=normalBackground
Timeline_BackgroundColor2=fff6f6f6
diff --git a/share/qtcreator/themes/design.creatortheme b/share/qtcreator/themes/design.creatortheme
index e29240a3cf6..11022bd7e5d 100644
--- a/share/qtcreator/themes/design.creatortheme
+++ b/share/qtcreator/themes/design.creatortheme
@@ -1,4 +1,5 @@
[General]
+Includes=dark.figmatokens
ThemeName=Design Dark
PreferredStyles=
DefaultTextEditorColorScheme=creator-dark.xml
@@ -414,39 +415,6 @@ Debugger_WatchItem_ValueChanged=ffff6666
Debugger_Breakpoint_TextMarkColor=ffff4040
-; Qt Creator Color Tokens - dark mode
-Token_Basic_Black=ff131313
-Token_Basic_White=fff8f8f8
-Token_Accent_Default=ff23b26a
-Token_Accent_Muted=ff1f9b5d
-Token_Accent_Subtle=ff1a8550
-Token_Background_Default=ff1f1f1f
-Token_Background_Muted=ff262626
-Token_Background_Subtle=ff2e2e2e
-Token_Foreground_Default=ff5a5a5a
-Token_Foreground_Muted=ff3e3e3e
-Token_Foreground_Subtle=ff303030
-Token_Text_Default=fff8f8f8
-Token_Text_Muted=ffaeaeae
-Token_Text_Subtle=ff595959
-Token_Stroke_Strong=ffeeeeee
-Token_Stroke_Muted=ff727272
-Token_Stroke_Subtle=ff3a3a3a
-Token_Notification_Alert=ffc98014
-Token_Notification_Success=ff1f9b5d
-Token_Notification_Neutral=ff016876
-Token_Notification_Danger=ffb22245
-
-Welcome_TextColor=text
-Welcome_ForegroundPrimaryColor=ffa3a3a3
-Welcome_ForegroundSecondaryColor=ff808080
-Welcome_BackgroundPrimaryColor=ff242424
-Welcome_BackgroundSecondaryColor=ff1c1c1c
-Welcome_HoverColor=ff2b2a2a
-Welcome_AccentColor=ff3f8ccc
-Welcome_LinkColor=ff5fafef
-Welcome_DisabledLinkColor=textDisabled
-
Timeline_TextColor=text
Timeline_BackgroundColor1=normalBackground
Timeline_BackgroundColor2=ff444444
diff --git a/share/qtcreator/themes/flat-dark.creatortheme b/share/qtcreator/themes/flat-dark.creatortheme
index 7e94645b743..9737e9cd53e 100644
--- a/share/qtcreator/themes/flat-dark.creatortheme
+++ b/share/qtcreator/themes/flat-dark.creatortheme
@@ -1,4 +1,5 @@
[General]
+Includes=dark.figmatokens
ThemeName=Flat Dark
PreferredStyles=
DefaultTextEditorColorScheme=creator-dark.xml
@@ -410,39 +411,6 @@ Debugger_WatchItem_ValueChanged=ffff6666
Debugger_Breakpoint_TextMarkColor=ffff4040
-; Qt Creator Color Tokens - dark mode
-Token_Basic_Black=ff131313
-Token_Basic_White=fff8f8f8
-Token_Accent_Default=ff23b26a
-Token_Accent_Muted=ff1f9b5d
-Token_Accent_Subtle=ff1a8550
-Token_Background_Default=ff1f1f1f
-Token_Background_Muted=ff262626
-Token_Background_Subtle=ff2e2e2e
-Token_Foreground_Default=ff5a5a5a
-Token_Foreground_Muted=ff3e3e3e
-Token_Foreground_Subtle=ff303030
-Token_Text_Default=fff8f8f8
-Token_Text_Muted=ffaeaeae
-Token_Text_Subtle=ff595959
-Token_Stroke_Strong=ffeeeeee
-Token_Stroke_Muted=ff727272
-Token_Stroke_Subtle=ff3a3a3a
-Token_Notification_Alert=ffc98014
-Token_Notification_Success=ff1f9b5d
-Token_Notification_Neutral=ff016876
-Token_Notification_Danger=ffb22245
-
-Welcome_TextColor=text
-Welcome_ForegroundPrimaryColor=ff999999
-Welcome_ForegroundSecondaryColor=ff808080
-Welcome_BackgroundPrimaryColor=normalBackground
-Welcome_BackgroundSecondaryColor=ff242628
-Welcome_HoverColor=ff404243
-Welcome_AccentColor=ff36c148
-Welcome_LinkColor=ff5fcf4f
-Welcome_DisabledLinkColor=textDisabled
-
Timeline_TextColor=text
Timeline_BackgroundColor1=normalBackground
Timeline_BackgroundColor2=ff444444
diff --git a/share/qtcreator/themes/flat-light.creatortheme b/share/qtcreator/themes/flat-light.creatortheme
index eddf38971d2..1ff8a7a3ff4 100644
--- a/share/qtcreator/themes/flat-light.creatortheme
+++ b/share/qtcreator/themes/flat-light.creatortheme
@@ -1,4 +1,5 @@
[General]
+Includes=light.figmatokens
ThemeName=Flat Light
PreferredStyles=
@@ -407,39 +408,6 @@ Debugger_WatchItem_ValueChanged=ffbf0303
Debugger_Breakpoint_TextMarkColor=ffff4040
-; Qt Creator Color Tokens - light mode
-Token_Basic_Black=ff131313
-Token_Basic_White=fff2f2f2
-Token_Accent_Default=ff23b26a
-Token_Accent_Muted=ff1f9b5d
-Token_Accent_Subtle=ff1a8550
-Token_Background_Default=ffe3e3e3
-Token_Background_Muted=ffeeeeee
-Token_Background_Subtle=fffbfbfb
-Token_Foreground_Default=ffcdcdcd
-Token_Foreground_Muted=ffd5d5d5
-Token_Foreground_Subtle=ffdddddd
-Token_Text_Default=ff393939
-Token_Text_Muted=ff7c7c7c
-Token_Text_Subtle=ffbebebe
-Token_Stroke_Strong=ff464646
-Token_Stroke_Muted=ff727272
-Token_Stroke_Subtle=ffcdcdcd
-Token_Notification_Alert=ffeb991f
-Token_Notification_Success=ff23b26a
-Token_Notification_Neutral=ff0e7887
-Token_Notification_Danger=ffdc1343
-
-Welcome_TextColor=ff000000
-Welcome_ForegroundPrimaryColor=ff232323
-Welcome_ForegroundSecondaryColor=ff939393
-Welcome_BackgroundPrimaryColor=fffafafa
-Welcome_BackgroundSecondaryColor=ffffffff
-Welcome_HoverColor=ffefefef
-Welcome_AccentColor=ff45ce55
-Welcome_LinkColor=ff20a020
-Welcome_DisabledLinkColor=textDisabled
-
Timeline_TextColor=text
Timeline_BackgroundColor1=normalBackground
Timeline_BackgroundColor2=fff6f6f6
diff --git a/share/qtcreator/themes/flat.creatortheme b/share/qtcreator/themes/flat.creatortheme
index 08697334f40..f479077889e 100644
--- a/share/qtcreator/themes/flat.creatortheme
+++ b/share/qtcreator/themes/flat.creatortheme
@@ -1,4 +1,5 @@
[General]
+Includes=light.figmatokens
ThemeName=Flat
PreferredStyles=
@@ -405,39 +406,6 @@ Debugger_WatchItem_ValueChanged=ffbf0303
Debugger_Breakpoint_TextMarkColor=ffff4040
-; Qt Creator Color Tokens - light mode
-Token_Basic_Black=ff131313
-Token_Basic_White=fff2f2f2
-Token_Accent_Default=ff23b26a
-Token_Accent_Muted=ff1f9b5d
-Token_Accent_Subtle=ff1a8550
-Token_Background_Default=ffe3e3e3
-Token_Background_Muted=ffeeeeee
-Token_Background_Subtle=fffbfbfb
-Token_Foreground_Default=ffcdcdcd
-Token_Foreground_Muted=ffd5d5d5
-Token_Foreground_Subtle=ffdddddd
-Token_Text_Default=ff393939
-Token_Text_Muted=ff7c7c7c
-Token_Text_Subtle=ffbebebe
-Token_Stroke_Strong=ff464646
-Token_Stroke_Muted=ff727272
-Token_Stroke_Subtle=ffcdcdcd
-Token_Notification_Alert=ffeb991f
-Token_Notification_Success=ff23b26a
-Token_Notification_Neutral=ff0e7887
-Token_Notification_Danger=ffdc1343
-
-Welcome_TextColor=ff000000
-Welcome_ForegroundPrimaryColor=shadowBackground
-Welcome_ForegroundSecondaryColor=ff939393
-Welcome_BackgroundPrimaryColor=fffafafa
-Welcome_BackgroundSecondaryColor=ffffffff
-Welcome_HoverColor=ffefefef
-Welcome_AccentColor=ff45ce55
-Welcome_LinkColor=ff20a020
-Welcome_DisabledLinkColor=textDisabled
-
Timeline_TextColor=text
Timeline_BackgroundColor1=normalBackground
Timeline_BackgroundColor2=fff6f6f6
diff --git a/share/qtcreator/themes/light.figmatokens b/share/qtcreator/themes/light.figmatokens
new file mode 100644
index 00000000000..a4d1bfcaa8d
--- /dev/null
+++ b/share/qtcreator/themes/light.figmatokens
@@ -0,0 +1,31 @@
+; Qt Creator Color Tokens - light mode
+
+[Colors]
+
+Token_Basic_Black=ff131313
+Token_Basic_White=fff2f2f2
+
+Token_Accent_Default=ff23b26a
+Token_Accent_Muted=ff1f9b5d
+Token_Accent_Subtle=ff1a8550
+
+Token_Background_Default=fffcfcfc
+Token_Background_Muted=ffefefef
+Token_Background_Subtle=ffe7e7e7
+
+Token_Foreground_Default=ffcdcdcd
+Token_Foreground_Muted=ffd5d5d5
+Token_Foreground_Subtle=ffdddddd
+
+Token_Text_Default=ff393939
+Token_Text_Muted=ff6a6a6a
+Token_Text_Subtle=ffbebebe
+
+Token_Stroke_Strong=ff464646
+Token_Stroke_Muted=ff727272
+Token_Stroke_Subtle=ffcdcdcd
+
+Token_Notification_Alert=ffeb991f
+Token_Notification_Success=ff23b26a
+Token_Notification_Neutral=ff0e7887
+Token_Notification_Danger=ffdc1343
diff --git a/src/libs/utils/stylehelper.cpp b/src/libs/utils/stylehelper.cpp
index ffb7efc417c..991b43df528 100644
--- a/src/libs/utils/stylehelper.cpp
+++ b/src/libs/utils/stylehelper.cpp
@@ -933,7 +933,17 @@ QColor StyleHelper::ensureReadableOn(const QColor &background, const QColor &des
return foreground;
}
-static QStringList brandFontFamilies()
+static const QStringList &applicationFontFamilies()
+{
+ const static QStringList families = [] {
+ constexpr QLatin1String familyName("Inter");
+ // Font is either installed in the system, or was loaded from share/qtcreator/fonts/
+ return QFontDatabase::hasFamily(familyName) ? QStringList(familyName) : QStringList();
+ }();
+ return families;
+}
+
+static const QStringList &brandFontFamilies()
{
const static QStringList families = []{
const int id = QFontDatabase::addApplicationFont(":/studiofonts/TitilliumWeb-Regular.ttf");
@@ -959,10 +969,14 @@ static const UiFontMetrics& uiFontMetrics(StyleHelper::UiElement element)
{StyleHelper::UiElementH5, {14, 16, QFont::DemiBold}},
{StyleHelper::UiElementH6, {12, 14, QFont::DemiBold}},
{StyleHelper::UiElementH6Capital, {12, 14, QFont::DemiBold}},
+ {StyleHelper::UiElementBody1, {14, 20, QFont::Light}},
+ {StyleHelper::UiElementBody2, {12, 20, QFont::Light}},
+ {StyleHelper::UiElementButtonMedium, {12, 16, QFont::Bold}},
+ {StyleHelper::UiElementButtonSmall, {10, 12, QFont::Bold}},
{StyleHelper::UiElementCaptionStrong, {10, 12, QFont::DemiBold}},
{StyleHelper::UiElementCaption, {10, 12, QFont::Normal}},
- {StyleHelper::UIElementIconStandard, {12, 16, QFont::Normal}},
- {StyleHelper::UIElementIconActive, {12, 16, QFont::DemiBold}},
+ {StyleHelper::UiElementIconStandard, {12, 16, QFont::Medium}},
+ {StyleHelper::UiElementIconActive, {12, 16, QFont::DemiBold}},
};
QTC_ASSERT(metrics.count(element) > 0, return metrics.at(StyleHelper::UiElementCaptionStrong));
return metrics.at(element);
@@ -983,8 +997,10 @@ QFont StyleHelper::uiFont(UiElement element)
case UiElementH3:
case UiElementH6Capital:
font.setCapitalization(QFont::AllUppercase);
- break;
+ [[fallthrough]];
default:
+ if (!applicationFontFamilies().isEmpty())
+ font.setFamilies(applicationFontFamilies());
break;
}
diff --git a/src/libs/utils/stylehelper.h b/src/libs/utils/stylehelper.h
index 4b986c68313..7d434925e66 100644
--- a/src/libs/utils/stylehelper.h
+++ b/src/libs/utils/stylehelper.h
@@ -42,15 +42,15 @@ constexpr char C_TOOLBAR_ACTIONWIDGET[] = "toolbar_actionWidget";
constexpr char C_QT_SCALE_FACTOR_ROUNDING_POLICY[] = "QT_SCALE_FACTOR_ROUNDING_POLICY";
namespace SpacingTokens {
- constexpr int VPaddingXXS = 4; // Top and bottom padding within the component
- constexpr int HPaddingXXS = 4; // Left and right padding within the component
- constexpr int VGapXXS = 4; // Vertical Space between TEXT LINE within the Component
- constexpr int HGapXXS = 4; // Horizontal Space between elements within the Component
+ constexpr int VPaddingXxs = 4; // Top and bottom padding within the component
+ constexpr int HPaddingXxs = 4; // Left and right padding within the component
+ constexpr int VGapXxs = 4; // Vertical Space between TEXT LINE within the Component
+ constexpr int HGapXxs = 4; // Horizontal Space between elements within the Component
- constexpr int VPaddingXS = 8;
- constexpr int HPaddingXS = 8;
- constexpr int VGapXS = 4;
- constexpr int HGapXS = 8;
+ constexpr int VPaddingXs = 8;
+ constexpr int HPaddingXs = 8;
+ constexpr int VGapXs = 4;
+ constexpr int HGapXs = 8;
constexpr int VPaddingS = 8;
constexpr int HPaddingS = 16;
@@ -62,10 +62,15 @@ namespace SpacingTokens {
constexpr int VGapM = 4;
constexpr int HGapM = 16;
- constexpr int VPaddingL = 12;
+ constexpr int VPaddingL = 16;
constexpr int HPaddingL = 24;
constexpr int VGapL = 8;
constexpr int HGapL = 16;
+
+ constexpr int ExPaddingGapS = 2;
+ constexpr int ExPaddingGapM = 6;
+ constexpr int ExPaddingGapL = 12;
+ constexpr int ExVPaddingGapXl = 24;
}
enum ToolbarStyle {
@@ -82,10 +87,14 @@ enum UiElement {
UiElementH5,
UiElementH6,
UiElementH6Capital,
+ UiElementBody1,
+ UiElementBody2,
+ UiElementButtonMedium,
+ UiElementButtonSmall,
UiElementCaptionStrong,
UiElementCaption,
- UIElementIconStandard,
- UIElementIconActive,
+ UiElementIconStandard,
+ UiElementIconActive,
};
// Height of the project explorer navigation bar
diff --git a/src/libs/utils/theme/theme.h b/src/libs/utils/theme/theme.h
index 2e4d61d943b..65d0ee91eaf 100644
--- a/src/libs/utils/theme/theme.h
+++ b/src/libs/utils/theme/theme.h
@@ -247,18 +247,6 @@ public:
Token_Notification_Neutral,
Token_Notification_Danger,
- /* Welcome Plugin */
-
- Welcome_TextColor,
- Welcome_ForegroundPrimaryColor,
- Welcome_ForegroundSecondaryColor,
- Welcome_BackgroundPrimaryColor,
- Welcome_BackgroundSecondaryColor,
- Welcome_HoverColor,
- Welcome_AccentColor,
- Welcome_LinkColor,
- Welcome_DisabledLinkColor,
-
/* Timeline Library */
Timeline_TextColor,
Timeline_BackgroundColor1,
diff --git a/src/plugins/coreplugin/core.qrc b/src/plugins/coreplugin/core.qrc
index ff855e3f4b8..239bd946121 100644
--- a/src/plugins/coreplugin/core.qrc
+++ b/src/plugins/coreplugin/core.qrc
@@ -1,5 +1,9 @@
+ images/expandarrow.png
+ images/expandarrow@2x.png
+ images/search.png
+ images/search@2x.png
images/settingscategory_core.png
images/settingscategory_core@2x.png
images/settingscategory_design.png
diff --git a/src/plugins/coreplugin/images/expandarrow.png b/src/plugins/coreplugin/images/expandarrow.png
new file mode 100644
index 00000000000..c463d0236d1
Binary files /dev/null and b/src/plugins/coreplugin/images/expandarrow.png differ
diff --git a/src/plugins/coreplugin/images/expandarrow@2x.png b/src/plugins/coreplugin/images/expandarrow@2x.png
new file mode 100644
index 00000000000..9b8341673fe
Binary files /dev/null and b/src/plugins/coreplugin/images/expandarrow@2x.png differ
diff --git a/src/plugins/coreplugin/images/search.png b/src/plugins/coreplugin/images/search.png
new file mode 100644
index 00000000000..398e2fe2bb1
Binary files /dev/null and b/src/plugins/coreplugin/images/search.png differ
diff --git a/src/plugins/coreplugin/images/search@2x.png b/src/plugins/coreplugin/images/search@2x.png
new file mode 100644
index 00000000000..aaae492449a
Binary files /dev/null and b/src/plugins/coreplugin/images/search@2x.png differ
diff --git a/src/plugins/coreplugin/iwelcomepage.cpp b/src/plugins/coreplugin/iwelcomepage.cpp
index 3eb63d80312..beef33f40d6 100644
--- a/src/plugins/coreplugin/iwelcomepage.cpp
+++ b/src/plugins/coreplugin/iwelcomepage.cpp
@@ -3,25 +3,8 @@
#include "iwelcomepage.h"
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-using namespace Utils;
-
namespace Core {
-const char WITHACCENTCOLOR_PROPERTY_NAME[] = "_withAccentColor";
-
static QList g_welcomePages;
const QList IWelcomePage::allWelcomePages()
@@ -39,171 +22,4 @@ IWelcomePage::~IWelcomePage()
g_welcomePages.removeOne(this);
}
-QPalette WelcomePageFrame::buttonPalette(bool isActive, bool isCursorInside, bool forText)
-{
- QPalette pal;
- pal.setBrush(QPalette::Window, {});
- pal.setBrush(QPalette::WindowText, {});
-
- Theme *theme = Utils::creatorTheme();
- if (isActive) {
- if (forText) {
- pal.setColor(QPalette::Window, theme->color(Theme::Welcome_ForegroundPrimaryColor));
- pal.setColor(QPalette::WindowText, theme->color(Theme::Welcome_BackgroundPrimaryColor));
- } else {
- pal.setColor(QPalette::Window, theme->color(Theme::Welcome_AccentColor));
- pal.setColor(QPalette::WindowText, theme->color(Theme::Welcome_AccentColor));
- }
- } else {
- if (isCursorInside) {
- if (forText) {
- pal.setColor(QPalette::Window, theme->color(Theme::Welcome_HoverColor));
- pal.setColor(QPalette::WindowText, theme->color(Theme::Welcome_TextColor));
- } else {
- pal.setColor(QPalette::Window, theme->color(Theme::Welcome_HoverColor));
- pal.setColor(QPalette::WindowText, theme->color(Theme::Welcome_ForegroundSecondaryColor));
- }
- } else {
- if (forText) {
- pal.setColor(QPalette::Window, theme->color(Theme::Welcome_ForegroundPrimaryColor));
- pal.setColor(QPalette::WindowText, theme->color(Theme::Welcome_TextColor));
- } else {
- pal.setColor(QPalette::Window, theme->color(Theme::Welcome_BackgroundPrimaryColor));
- pal.setColor(QPalette::WindowText, theme->color(Theme::Welcome_ForegroundSecondaryColor));
- }
- }
- }
- return pal;
-}
-
-WelcomePageFrame::WelcomePageFrame(QWidget *parent)
- : QWidget(parent)
-{
- setContentsMargins(1, 1, 1, 1);
-}
-
-void WelcomePageFrame::paintEvent(QPaintEvent *event)
-{
- QWidget::paintEvent(event);
- QPainter p(this);
-
- qDrawPlainRect(&p, rect(), palette().color(QPalette::WindowText), 1);
-
- if (property(WITHACCENTCOLOR_PROPERTY_NAME).toBool()) {
- const int accentRectWidth = 10;
- const QRect accentRect = rect().adjusted(width() - accentRectWidth, 0, 0, 0);
- p.fillRect(accentRect, creatorTheme()->color(Theme::Welcome_AccentColor));
- }
-}
-
-class WelcomePageButtonPrivate
-{
-public:
- explicit WelcomePageButtonPrivate(WelcomePageButton *parent)
- : q(parent) {}
- bool isActive() const;
- void doUpdate(bool cursorInside);
-
- WelcomePageButton *q;
- QHBoxLayout *m_layout = nullptr;
- QLabel *m_label = nullptr;
-
- std::function onClicked;
- std::function activeChecker;
-};
-
-WelcomePageButton::WelcomePageButton(QWidget *parent)
- : WelcomePageFrame(parent), d(new WelcomePageButtonPrivate(this))
-{
- setAutoFillBackground(true);
- setPalette(buttonPalette(false, false, false));
- setContentsMargins(0, 1, 0, 1);
-
- d->m_label = new QLabel(this);
- d->m_label->setPalette(buttonPalette(false, false, true));
- d->m_label->setAlignment(Qt::AlignCenter);
-
- d->m_layout = new QHBoxLayout;
- d->m_layout->setSpacing(0);
- d->m_layout->addWidget(d->m_label);
- setSize(SizeLarge);
- setLayout(d->m_layout);
-}
-
-WelcomePageButton::~WelcomePageButton()
-{
- delete d;
-}
-
-void WelcomePageButton::mousePressEvent(QMouseEvent *)
-{
- if (d->onClicked)
- d->onClicked();
-}
-
-void WelcomePageButton::enterEvent(QEnterEvent *)
-{
- d->doUpdate(true);
-}
-
-void WelcomePageButton::leaveEvent(QEvent *)
-{
- d->doUpdate(false);
-}
-
-bool WelcomePageButtonPrivate::isActive() const
-{
- return activeChecker && activeChecker();
-}
-
-void WelcomePageButtonPrivate::doUpdate(bool cursorInside)
-{
- const bool active = isActive();
- q->setPalette(WelcomePageFrame::buttonPalette(active, cursorInside, false));
- const QPalette lpal = WelcomePageFrame::buttonPalette(active, cursorInside, true);
- m_label->setPalette(lpal);
- q->update();
-}
-
-void WelcomePageButton::setText(const QString &text)
-{
- d->m_label->setText(text);
-}
-
-void WelcomePageButton::setSize(Size size)
-{
- const int hMargin = size == SizeSmall ? 12 : 26;
- const int vMargin = size == SizeSmall ? 2 : 4;
- d->m_layout->setContentsMargins(hMargin, vMargin, hMargin, vMargin);
-}
-
-void WelcomePageButton::setWithAccentColor(bool withAccent)
-{
- setProperty(WITHACCENTCOLOR_PROPERTY_NAME, withAccent);
-}
-
-void WelcomePageButton::setActiveChecker(const std::function &value)
-{
- d->activeChecker = value;
-}
-
-void WelcomePageButton::recheckActive()
-{
- bool isActive = d->isActive();
- d->doUpdate(isActive);
-}
-
-void WelcomePageButton::click()
-{
- if (d->onClicked)
- d->onClicked();
-}
-
-void WelcomePageButton::setOnClicked(const std::function &value)
-{
- d->onClicked = value;
- if (d->isActive())
- click();
-}
-
} // namespace Core
diff --git a/src/plugins/coreplugin/iwelcomepage.h b/src/plugins/coreplugin/iwelcomepage.h
index 9a64dd3a701..1f59a791195 100644
--- a/src/plugins/coreplugin/iwelcomepage.h
+++ b/src/plugins/coreplugin/iwelcomepage.h
@@ -7,13 +7,10 @@
#include
-#include
#include
-#include
-
QT_BEGIN_NAMESPACE
-class QPixmap;
+class QWidget;
QT_END_NAMESPACE
namespace Core {
@@ -37,43 +34,4 @@ public:
static const QList allWelcomePages();
};
-class WelcomePageButtonPrivate;
-
-class CORE_EXPORT WelcomePageFrame : public QWidget
-{
-public:
- WelcomePageFrame(QWidget *parent);
-
- void paintEvent(QPaintEvent *event) override;
-
- static QPalette buttonPalette(bool isActive, bool isCursorInside, bool forText);
-};
-
-class CORE_EXPORT WelcomePageButton : public WelcomePageFrame
-{
-public:
- enum Size {
- SizeSmall,
- SizeLarge,
- };
-
- explicit WelcomePageButton(QWidget *parent = nullptr);
- ~WelcomePageButton() override;
-
- void mousePressEvent(QMouseEvent *) override;
- void enterEvent(QEnterEvent *) override;
- void leaveEvent(QEvent *) override;
-
- void setText(const QString &text);
- void setSize(enum Size);
- void setWithAccentColor(bool withAccent);
- void setOnClicked(const std::function &value);
- void setActiveChecker(const std::function &value);
- void recheckActive();
- void click();
-
-private:
- WelcomePageButtonPrivate *d;
-};
-
} // Core
diff --git a/src/plugins/coreplugin/session.cpp b/src/plugins/coreplugin/session.cpp
index c188f6812c3..921046ffed4 100644
--- a/src/plugins/coreplugin/session.cpp
+++ b/src/plugins/coreplugin/session.cpp
@@ -267,6 +267,11 @@ QDateTime SessionManager::lastActiveTime(const QString &session)
return d->m_lastActiveTimes.value(session);
}
+int SessionManager::sessionsCount()
+{
+ return d->m_sessions.count();
+}
+
FilePath SessionManager::sessionNameToFileName(const QString &session)
{
return ICore::userResourcePath(session + ".qws");
diff --git a/src/plugins/coreplugin/session.h b/src/plugins/coreplugin/session.h
index 962db5172b5..ef51228b018 100644
--- a/src/plugins/coreplugin/session.h
+++ b/src/plugins/coreplugin/session.h
@@ -34,6 +34,7 @@ public:
static QStringList sessions();
static QDateTime sessionDateTime(const QString &session);
static QDateTime lastActiveTime(const QString &session);
+ static int sessionsCount();
static bool createSession(const QString &session);
diff --git a/src/plugins/coreplugin/welcomepagehelper.cpp b/src/plugins/coreplugin/welcomepagehelper.cpp
index 44fc75270dd..636888d6b47 100644
--- a/src/plugins/coreplugin/welcomepagehelper.cpp
+++ b/src/plugins/coreplugin/welcomepagehelper.cpp
@@ -7,6 +7,7 @@
#include
#include
+#include
#include
#include
#include
@@ -26,36 +27,34 @@
#include
+
+QT_BEGIN_NAMESPACE
+void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed = 0);
+QT_END_NAMESPACE
+
using namespace Utils;
namespace Core {
using namespace WelcomePageHelpers;
+using namespace StyleHelper::SpacingTokens;
static QColor themeColor(Theme::Color role)
{
return creatorTheme()->color(role);
}
-static QFont sizedFont(int size, const QWidget *widget)
-{
- QFont f = widget->font();
- f.setPixelSize(size);
- return f;
-}
-
namespace WelcomePageHelpers {
-QWidget *panelBar(QWidget *parent)
+void setBackgroundColor(QWidget *widget, Theme::Color colorRole)
{
- auto frame = new QWidget(parent);
- frame->setAutoFillBackground(true);
- frame->setMinimumWidth(WelcomePageHelpers::HSpacing);
- QPalette pal;
- pal.setBrush(QPalette::Window, {});
- pal.setColor(QPalette::Window, themeColor(Theme::Welcome_BackgroundPrimaryColor));
- frame->setPalette(pal);
- return frame;
+ QPalette palette = creatorTheme()->palette();
+ const QPalette::ColorRole role = QPalette::Window;
+ palette.setBrush(role, {});
+ palette.setColor(role, creatorTheme()->color(colorRole));
+ widget->setPalette(palette);
+ widget->setBackgroundRole(role);
+ widget->setAutoFillBackground(true);
}
void drawCardBackground(QPainter *painter, const QRectF &rect,
@@ -77,30 +76,351 @@ void drawCardBackground(QPainter *painter, const QRectF &rect,
painter->restore();
}
+QWidget *createRule(Qt::Orientation orientation, QWidget *parent)
+{
+ auto rule = new QWidget(parent);
+ if (orientation == Qt::Horizontal)
+ rule->setFixedHeight(1);
+ else
+ rule->setFixedWidth(1);
+ setBackgroundColor(rule, Theme::Token_Stroke_Subtle);
+ return rule;
+}
+
} // namespace WelcomePageHelpers
-SearchBox::SearchBox(QWidget *parent)
- : WelcomePageFrame(parent)
+enum WidgetState {
+ WidgetStateDefault,
+ WidgetStateChecked,
+ WidgetStateHovered,
+};
+
+static const TextFormat &buttonTF(Button::Role role, WidgetState state)
{
- setAutoFillBackground(true);
+ using namespace WelcomePageHelpers;
+ static const TextFormat mediumPrimaryTF
+ {Theme::Token_Basic_White, StyleHelper::UiElement::UiElementButtonMedium,
+ Qt::AlignCenter | Qt::TextDontClip};
+ static const TextFormat mediumSecondaryTF
+ {Theme::Token_Text_Default, mediumPrimaryTF.uiElement, mediumPrimaryTF.drawTextFlags};
+ static const TextFormat smallPrimaryTF
+ {mediumPrimaryTF.themeColor, StyleHelper::UiElement::UiElementButtonSmall,
+ mediumPrimaryTF.drawTextFlags};
+ static const TextFormat smallSecondaryTF
+ {mediumSecondaryTF.themeColor, smallPrimaryTF.uiElement, smallPrimaryTF.drawTextFlags};
+ static const TextFormat smallListDefaultTF
+ {Theme::Token_Text_Default, StyleHelper::UiElement::UiElementIconStandard,
+ Qt::AlignLeft | Qt::AlignVCenter | Qt::TextDontClip};
+ static const TextFormat smallListCheckedTF
+ {smallListDefaultTF.themeColor, StyleHelper::UiElement::UiElementIconActive,
+ smallListDefaultTF.drawTextFlags};
+ static const TextFormat smallLinkDefaultTF
+ {Theme::Token_Text_Default, smallListDefaultTF.uiElement, smallListDefaultTF.drawTextFlags};
+ static const TextFormat smallLinkHoveredTF
+ {Theme::Token_Accent_Default, smallListCheckedTF.uiElement,
+ smallLinkDefaultTF.drawTextFlags};
- m_lineEdit = new FancyLineEdit;
- m_lineEdit->setFiltering(true);
- m_lineEdit->setFrame(false);
- m_lineEdit->setMinimumHeight(33);
- m_lineEdit->setAttribute(Qt::WA_MacShowFocusRect, false);
+ switch (role) {
+ case Button::MediumPrimary: return mediumPrimaryTF;
+ case Button::MediumSecondary: return mediumSecondaryTF;
+ case Button::SmallPrimary: return smallPrimaryTF;
+ case Button::SmallSecondary: return smallSecondaryTF;
+ case Button::SmallList: return (state == WidgetStateDefault) ? smallListDefaultTF
+ : smallListCheckedTF;
+ case Button::SmallLink: return (state == WidgetStateDefault) ? smallLinkDefaultTF
+ : smallLinkHoveredTF;
+ }
+ return mediumPrimaryTF;
+}
- QPalette pal = buttonPalette(false, false, true);
- // for the margins
- pal.setColor(QPalette::Window, m_lineEdit->palette().color(QPalette::Base));
- // for macOS dark mode
- pal.setColor(QPalette::WindowText, themeColor(Theme::Welcome_ForegroundPrimaryColor));
- pal.setColor(QPalette::Text, themeColor(Theme::Welcome_TextColor));
+Button::Button(const QString &text, Role role, QWidget *parent)
+ : QPushButton(text, parent)
+ , m_role(role)
+{
+ // Prevent QMacStyle::subElementRect(SE_PushButtonLayoutItem) from changing our geometry
+ setFlat(true);
+
+ updateMargins();
+ if (m_role == SmallList)
+ setCheckable(true);
+ else if (m_role == SmallLink)
+ setCursor(Qt::PointingHandCursor);
+}
+
+QSize Button::minimumSizeHint() const
+{
+ const TextFormat &tf = buttonTF(m_role, WidgetStateHovered);
+ const QFontMetrics fm(tf.font());
+ const QSize textS = fm.size(Qt::TextShowMnemonic, text());
+ const QMargins margins = contentsMargins();
+ return {margins.left() + textS.width() + margins.right(),
+ margins.top() + tf.lineHeight() + margins.bottom()};
+}
+
+void Button::paintEvent(QPaintEvent *event)
+{
+ // Without pixmap
+ // +----------------+----------------+----------------+
+ // | |(VPadding[S|XS])| |
+ // | +----------------+----------------+
+ // |(HPadding[S|XS])|
Error: %1
").arg(message);
m_errorLabel->setText(txt);
m_errorLabel->setVisible(true);
- searchBox->setVisible(false);
+ m_searcher->setVisible(false);
connect(m_errorLabel, &QLabel::linkActivated,
this, []() { QDesktopServices::openUrl(QUrl("https://marketplace.qt.io")); });
});
diff --git a/src/plugins/projectexplorer/projectwelcomepage.cpp b/src/plugins/projectexplorer/projectwelcomepage.cpp
index 45524bdb169..431fa8ee1d0 100644
--- a/src/plugins/projectexplorer/projectwelcomepage.cpp
+++ b/src/plugins/projectexplorer/projectwelcomepage.cpp
@@ -21,6 +21,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -28,9 +29,6 @@
#include
#include
-#include
-#include
-#include
#include
#include
#include
@@ -42,16 +40,52 @@
using namespace Core;
using namespace Core::WelcomePageHelpers;
using namespace Utils;
+using namespace Utils::StyleHelper::SpacingTokens;
-const int LINK_HEIGHT = 35;
-const int TEXT_OFFSET_HORIZONTAL = 36;
-const int SESSION_LINE_HEIGHT = 28;
-const int SESSION_ARROW_RECT_WIDTH = 24;
const char PROJECT_BASE_ID[] = "Welcome.OpenRecentProject";
namespace ProjectExplorer {
namespace Internal {
+constexpr TextFormat projectNameTF {Theme::Token_Accent_Default, StyleHelper::UiElementH5};
+constexpr TextFormat projectPathTF {Theme::Token_Text_Muted, StyleHelper::UiElementIconActive};
+constexpr TextFormat sessionNameTF {projectNameTF.themeColor, projectNameTF.uiElement};
+constexpr TextFormat sessionProjetNameTF {Theme::Token_Text_Default, projectNameTF.uiElement};
+constexpr TextFormat shortcutNumberTF {Theme::Token_Text_Default,
+ StyleHelper::UiElementCaptionStrong,
+ Qt::AlignCenter | Qt::TextDontClip};
+constexpr TextFormat actionTF {Theme::Token_Text_Default, StyleHelper::UiElementIconActive,
+ Qt::AlignCenter | Qt::TextDontClip};
+constexpr TextFormat actionDisabledTF {Theme::Token_Text_Subtle, actionTF.uiElement,
+ actionTF.drawTextFlags};
+constexpr int shortcutNumberWidth = 16;
+constexpr int actionSepWidth = 1;
+constexpr int sessionScrollBarGap = HPaddingXs;
+
+static int s(const int metric)
+{
+ constexpr int shrinkWhenAbove = 150; // Above this session count, increasingly reduce scale
+ constexpr qreal maxScale = 1.0; // Spacings as defined by design
+ constexpr qreal minScale = 0.2; // Maximum "condensed" layout
+
+ const int sessionsCount = SessionManager::sessionsCount();
+ const qreal scaling = sessionsCount < shrinkWhenAbove
+ ? maxScale
+ : qMax(minScale,
+ maxScale - (sessionsCount - shrinkWhenAbove) * 0.065);
+ return int(qMax(1.0, scaling * metric));
+}
+
+static int itemSpacing()
+{
+ return qMax(int(s(VGapL)), VGapS);
+}
+
+static bool withIcon()
+{
+ return s(100) > 60; // Hide icons if spacings are scaled to below 60%
+}
+
ProjectModel::ProjectModel(QObject *parent)
: QAbstractListModel(parent)
{
@@ -61,7 +95,7 @@ ProjectModel::ProjectModel(QObject *parent)
int ProjectModel::rowCount(const QModelIndex &) const
{
- return m_projects.count();
+ return int(m_projects.count());
}
QVariant ProjectModel::data(const QModelIndex &index, int role) const
@@ -190,21 +224,24 @@ static QColor themeColor(Theme::Color role)
return Utils::creatorTheme()->color(role);
}
-static QFont sizedFont(int size, const QWidget *widget,
- bool underline = false)
-{
- QFont f = widget->font();
- f.setPixelSize(size);
- f.setUnderline(underline);
- return f;
-}
-
-static QPixmap pixmap(const QString &id, const Theme::Color &color)
+static QPixmap pixmap(const QString &id, const Theme::Color color)
{
const QString fileName = QString(":/welcome/images/%1.png").arg(id);
return Icon({{FilePath::fromString(fileName), color}}, Icon::Tint).pixmap();
}
+static void drawBackgroundRect(QPainter *painter, const QRectF &rect, bool hovered)
+{
+ const QColor fill(themeColor(hovered ? Theme::Token_Foreground_Muted
+ : Theme::Token_Background_Muted));
+ const QPen pen(themeColor(hovered ? Theme::Token_Foreground_Muted
+ : Theme::Token_Stroke_Subtle));
+
+ const qreal rounding = s(defaultCardBackgroundRounding * 1000) / 1000.0;
+ const qreal saneRounding = rounding <= 2 ? 0 : rounding;
+ WelcomePageHelpers::drawCardBackground(painter, rect, fill, pen, saneRounding);
+}
+
class BaseDelegate : public QAbstractItemDelegate
{
protected:
@@ -244,6 +281,11 @@ protected:
class SessionDelegate : public BaseDelegate
{
protected:
+ bool expanded(const QModelIndex &idx) const
+ {
+ return m_expandedSessions.contains(idx.data(Qt::DisplayRole).toString());
+ }
+
QString entryType() override
{
return Tr::tr("session", "Appears in \"Open session \"");
@@ -252,150 +294,287 @@ protected:
{
// in expanded state bottom contains 'Clone', 'Rename', etc links, where the tool tip
// would be confusing
- const bool expanded = m_expandedSessions.contains(idx.data(Qt::DisplayRole).toString());
- return expanded ? itemRect.adjusted(0, 0, 0, -LINK_HEIGHT) : itemRect;
+ return expanded(idx) ? itemRect.adjusted(0, 0, 0, -actionButtonHeight()) : itemRect;
+ }
+
+ int shortcutRole() const override
+ {
+ return SessionModel::ShortcutRole;
+ }
+
+ static int actionButtonHeight()
+ {
+ return s(VPaddingXxs) + actionTF.lineHeight() + s(VPaddingXxs);
+ }
+
+ static const QPixmap &icon()
+ {
+ static const QPixmap icon = pixmap("session", Theme::Token_Text_Muted);
+ return icon;
}
- int shortcutRole() const override { return SessionModel::ShortcutRole; }
public:
- void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &idx) const final
+ void paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &idx) const final
{
- static const QPixmap sessionIcon = pixmap("session", Theme::Welcome_ForegroundSecondaryColor);
-
- const QRect rc = option.rect;
- const QString sessionName = idx.data(Qt::DisplayRole).toString();
+ // visible on withIcon() Gap + arrow visible on hover Extra margin right of project item
+ // | | |
+ // +----------+----------+ +--------+-------+ +----------+----------+
+ // | | | | | |
+ //
+ // +------------+--------+--------+------------+--------+-------------+--------+-------+------------+---------------------+ --+
+ // | | | |(VPaddingXs)| |(VPaddingXs) | | | | | |
+ // | | | +------------+ +-------------+ | | | | |
+ // |(HPaddingXs)||(HGapXs)| |(HGapXs)||(HGapXs)|| | | +-- Header
+ // | |(16x16) | +------------+ +-------------+ | | | | |
+ // | | | |(VPaddingXs)| |(VPaddingXs) | | | | | |
+ // |------------+--------+--------+------------+--------+-------------+--------+-------+ | | --+
+ // | +-- | (VPaddingXs) | | | |
+ // | | +------------------------------+(HPaddingXs)| | |
+ // | | | | | | |
+ // | | +------------------------------+ | | |
+ // | Per project in session --+ | (EXSPaddingGapS) | |(sessionScrollBarGap)| |
+ // | | +------------------------------+ | | |
+ // | | | | | | |
+ // | | +------------------------------+ | | +-- Expansion
+ // | +-- | (VPaddingXs) | | | |
+ // +----------------------------------------------+------------------------------------+------------+ | |
+ // | (VPaddingXs) | | |
+ // +----------------------------------------+--------------+----------------------------------------+ | |
+ // +-- | || | | |
+ // | +----------------------------------------+--------------+----------------------------------------+ | |
+ // | | (VPaddingXs) | | |
+ // | +------------------------------------------------------------------------------------------------+---------------------+ --+
+ // | | (VGapL) | +-- Gap between session items
+ // | +----------------------------------------------------------------------------------------------------------------------+ --+
+ // |
+ // \ session action "buttons" and dividers
+ // +-----------------------------------------------+--------+---------+--------+
+ // | (VGapXs) | | | |
+ // +----------------+-------------+----------------+ | | |
+ // |(EXSPaddingGapM)||(EXSPaddingGapM)|(HGapXs)||(HGapXs)|
+ // +----------------+-------------+----------------+ |(w:1) | |
+ // | (VGapXs) | | | |
+ // +-----------------------------------------------+--------+---------+--------+
+ //
+ // | |
+ // +-------------+-------------+
+ // |
+ // omitted after last button
const QPoint mousePos = option.widget->mapFromGlobal(QCursor::pos());
- //const bool hovered = option.state & QStyle::State_MouseOver;
const bool hovered = option.rect.contains(mousePos);
- const bool expanded = m_expandedSessions.contains(sessionName);
- painter->fillRect(rc, themeColor(Theme::Welcome_BackgroundSecondaryColor));
- painter->fillRect(rc.adjusted(0, 0, 0, -ItemGap),
- hovered ? hoverColor : backgroundPrimaryColor);
+ const bool expanded = this->expanded(idx);
- const int x = rc.x();
- const int x1 = x + TEXT_OFFSET_HORIZONTAL;
- const int y = rc.y();
- const int firstBase = y + 18;
+ const QRect bgR = option.rect.adjusted(0, 0, -sessionScrollBarGap, -itemSpacing());
+ const QRect hdR(bgR.topLeft(), QSize(bgR.width(), expanded ? headerHeight()
+ : bgR.height()));
- painter->drawPixmap(x + 11, y + 6, sessionIcon);
+ const QSize iconS = icon().deviceIndependentSize().toSize();
+ static const QPixmap arrow = Icon({{FilePath::fromString(":/core/images/expandarrow"),
+ Theme::Token_Text_Muted}}, Icon::Tint).pixmap();
+ const QSize arrowS = arrow.deviceIndependentSize().toSize();
+ const bool arrowVisible = hovered || expanded;
- if (hovered && !expanded) {
- const QRect arrowRect = rc.adjusted(rc.width() - SESSION_ARROW_RECT_WIDTH, 0, 0, 0);
- const bool arrowRectHovered = arrowRect.contains(mousePos);
- painter->fillRect(arrowRect.adjusted(0, 0, 0, -ItemGap),
- arrowRectHovered ? hoverColor : backgroundPrimaryColor);
+ const QString sessionName = idx.data(Qt::DisplayRole).toString();
+
+ const int x = bgR.x();
+ const int y = bgR.y();
+
+ const int numberX = x + s(HPaddingXs);
+ const int iconX = numberX + shortcutNumberWidth + s(HGapXs);
+ const int arrowX = bgR.right() - s(HPaddingXs) - arrowS.width();
+ const QRect arrowHoverR(arrowX - s(HGapXs) + 1, y,
+ s(HGapXs) + arrowS.width() + s(HPaddingXs), hdR.height());
+ const int textX = withIcon() ? iconX + iconS.width() + s(HGapXs) : iconX;
+
+ const int iconY = y + (hdR.height() - iconS.height()) / 2;
+ const int arrowY = y + (hdR.height() - arrowS.height()) / 2;
+
+ {
+ drawBackgroundRect(painter, bgR, hovered);
}
-
- if (hovered || expanded) {
- static const QPixmap arrowUp = pixmap("expandarrow",Theme::Welcome_ForegroundSecondaryColor);
- static const QPixmap arrowDown = QPixmap::fromImage(arrowUp.toImage().mirrored(false, true));
- painter->drawPixmap(rc.right() - 19, y + 6, expanded ? arrowDown : arrowUp);
- }
-
if (idx.row() < 9) {
- painter->setPen(foregroundSecondaryColor);
- painter->setFont(sizedFont(10, option.widget));
- painter->drawText(x + 3, firstBase, QString::number(idx.row() + 1));
+ painter->setPen(shortcutNumberTF.color());
+ painter->setFont(shortcutNumberTF.font());
+ const QRect numberR(numberX, y, shortcutNumberWidth, hdR.height());
+ const QString numberString = QString::number(idx.row() + 1);
+ painter->drawText(numberR, shortcutNumberTF.drawTextFlags, numberString);
+ }
+ if (withIcon()) {
+ painter->drawPixmap(iconX, iconY, icon());
+ }
+ {
+ const bool isLastSession = idx.data(SessionModel::LastSessionRole).toBool();
+ const bool isActiveSession = idx.data(SessionModel::ActiveSessionRole).toBool();
+ const bool isDefaultVirgin = SessionManager::isDefaultVirgin();
+
+ const int sessionNameWidth = hdR.right()
+ - (arrowVisible ? arrowHoverR.width(): s(HPaddingXs))
+ - textX;
+ const int sessionNameHeight = sessionNameTF.lineHeight();
+ const int sessionNameY = y + (hdR.height() - sessionNameHeight) / 2;
+ const QRect sessionNameR(textX, sessionNameY, sessionNameWidth, sessionNameHeight);
+
+ QString fullSessionName = sessionName;
+ if (isLastSession && isDefaultVirgin)
+ fullSessionName = Tr::tr("%1 (last session)").arg(fullSessionName);
+ if (isActiveSession && !isDefaultVirgin)
+ fullSessionName = Tr::tr("%1 (current session)").arg(fullSessionName);
+ const QRect switchR(x, y, hdR.width() - arrowHoverR.width(),
+ hdR.height() + s(VGapL));
+ const bool switchActive = switchR.contains(mousePos);
+ painter->setPen(sessionNameTF.color());
+ painter->setFont(sessionNameTF.font(switchActive));
+ const QString fullSessionNameElided = painter->fontMetrics().elidedText(
+ fullSessionName, Qt::ElideRight, sessionNameWidth);
+ painter->drawText(sessionNameR, sessionNameTF.drawTextFlags,
+ fullSessionNameElided);
+ if (switchActive)
+ m_activeSwitchToRect = switchR;
+ }
+ if (arrowVisible) {
+ if (arrowHoverR.adjusted(0, 0, 0, s(VGapL)).contains(mousePos)) {
+ m_activeExpandRect = arrowHoverR;
+ } else {
+ painter->save();
+ painter->setClipRect(arrowHoverR);
+ drawBackgroundRect(painter, bgR, false);
+ painter->restore();
+ }
+ static const QPixmap arrowDown =
+ QPixmap::fromImage(arrow.toImage().mirrored(false, true));
+ painter->drawPixmap(arrowX, arrowY, expanded ? arrowDown : arrow);
}
- const bool isLastSession = idx.data(SessionModel::LastSessionRole).toBool();
- const bool isActiveSession = idx.data(SessionModel::ActiveSessionRole).toBool();
- const bool isDefaultVirgin = SessionManager::isDefaultVirgin();
-
- QString fullSessionName = sessionName;
- if (isLastSession && isDefaultVirgin)
- fullSessionName = Tr::tr("%1 (last session)").arg(fullSessionName);
- if (isActiveSession && !isDefaultVirgin)
- fullSessionName = Tr::tr("%1 (current session)").arg(fullSessionName);
-
- const QRect switchRect = QRect(x, y, rc.width() - SESSION_ARROW_RECT_WIDTH, SESSION_LINE_HEIGHT);
- const bool switchActive = switchRect.contains(mousePos);
- const int textSpace = rc.width() - TEXT_OFFSET_HORIZONTAL - 6;
- const int sessionNameTextSpace =
- textSpace -(hovered || expanded ? SESSION_ARROW_RECT_WIDTH : 0);
- painter->setPen(linkColor);
- painter->setFont(sizedFont(13, option.widget, switchActive));
- const QString fullSessionNameElided = painter->fontMetrics().elidedText(
- fullSessionName, Qt::ElideRight, sessionNameTextSpace);
- painter->drawText(x1, firstBase, fullSessionNameElided);
- if (switchActive)
- m_activeSwitchToRect = switchRect;
-
+ int yy = hdR.bottom();
if (expanded) {
- painter->setPen(textColor);
- painter->setFont(sizedFont(12, option.widget));
+ const QFont projectNameFont = sessionProjetNameTF.font();
+ const QFontMetrics projectNameFm(projectNameFont);
+ const int projectNameLineHeight = sessionProjetNameTF.lineHeight();
+ const QFont projectPathFont = projectPathTF.font();
+ const QFontMetrics projectPathFm(projectPathFont);
+ const int projectPathLineHeight = projectPathTF.lineHeight();
+ const int textWidth = bgR.right() - s(HPaddingXs) - textX;
+
const FilePaths projects = ProjectManager::projectsForSessionName(sessionName);
- int yy = firstBase + SESSION_LINE_HEIGHT - 3;
- QFontMetrics fm(option.widget->font());
for (const FilePath &projectPath : projects) {
- // Project name.
- QString completeBase = projectPath.completeBaseName();
- painter->setPen(textColor);
- painter->drawText(x1, yy, fm.elidedText(completeBase, Qt::ElideMiddle, textSpace));
- yy += 18;
-
- // Project path.
- const QString displayPath =
- projectPath.osType() == OsTypeWindows ? projectPath.displayName()
- : projectPath.withTildeHomePath();
- painter->setPen(foregroundPrimaryColor);
- painter->drawText(x1, yy, fm.elidedText(displayPath, Qt::ElideMiddle, textSpace));
- yy += 22;
+ yy += s(VPaddingXs);
+ {
+ painter->setFont(projectNameFont);
+ painter->setPen(sessionProjetNameTF.color());
+ const QRect projectNameR(textX, yy, textWidth, projectNameLineHeight);
+ const QString projectNameElided =
+ projectNameFm.elidedText(projectPath.completeBaseName(), Qt::ElideMiddle,
+ textWidth);
+ painter->drawText(projectNameR, sessionProjetNameTF.drawTextFlags,
+ projectNameElided);
+ yy += projectNameLineHeight;
+ yy += s(ExPaddingGapS);
+ }
+ {
+ const QString displayPath =
+ projectPath.osType() == OsTypeWindows ? projectPath.displayName()
+ : projectPath.withTildeHomePath();
+ painter->setFont(projectPathFont);
+ painter->setPen(projectPathTF.color());
+ const QRect projectPathR(textX, yy, textWidth, projectPathLineHeight);
+ const QString projectPathElided =
+ projectPathFm.elidedText(displayPath, Qt::ElideMiddle, textWidth);
+ painter->drawText(projectPathR, projectPathTF.drawTextFlags,
+ projectPathElided);
+ yy += projectPathLineHeight;
+ }
+ yy += s(VPaddingXs);
}
+ yy += s(VGapXs);
- yy += 3;
- int xx = x1;
const QStringList actions = {
Tr::tr("Clone"),
Tr::tr("Rename"),
- Tr::tr("Delete")
+ Tr::tr("Delete"),
};
- for (int i = 0; i < 3; ++i) {
+
+ const QFont actionFont = actionTF.font();
+ const QFontMetrics actionFm(actionTF.font());
+
+ const int gapWidth = s(HGapXs) + actionSepWidth + s(HGapXs);
+ int actionsTotalWidth = gapWidth * int(actions.count() - 1); // dividers
+ const auto textWidths = Utils::transform(actions, [&] (const QString &action) {
+ const int width = actionFm.horizontalAdvance(action);
+ actionsTotalWidth += s(ExPaddingGapM) + width + s(ExPaddingGapM);
+ return width;
+ });
+
+ const int buttonHeight = this->actionButtonHeight();
+ int xx = (bgR.width() - actionsTotalWidth) / 2;
+ for (int i = 0; i < actions.count(); ++i) {
const QString &action = actions.at(i);
- const int ww = fm.horizontalAdvance(action);
- const int spacing = 7; // Between action link and separator line
- const QRect actionRect =
- QRect(xx, yy - 10, ww, 15).adjusted(-spacing, -spacing, spacing, spacing);
- const bool isForcedDisabled = (i != 0 && sessionName == "default");
- const bool isActive = actionRect.contains(mousePos) && !isForcedDisabled;
- painter->setPen(isForcedDisabled ? disabledLinkColor : linkColor);
- painter->setFont(sizedFont(12, option.widget, isActive));
- painter->drawText(xx, yy, action);
- if (i < 2) {
- xx += ww + 2 * spacing;
- int pp = xx - spacing;
- painter->setPen(textColor);
- painter->drawLine(pp, yy - 10, pp, yy);
+ const int ww = textWidths.at(i);
+ const QRect actionR(xx, yy, s(ExPaddingGapM) + ww + s(ExPaddingGapM), buttonHeight);
+ const bool isDisabled = i > 0 && SessionManager::isDefaultSession(sessionName);
+ const bool isActive = actionR.adjusted(-s(VPaddingXs), 0, s(VPaddingXs) + 1, 0)
+ .contains(mousePos) && !isDisabled;
+ if (isActive) {
+ WelcomePageHelpers::drawCardBackground(painter, actionR, Qt::transparent,
+ themeColor(Theme::Token_Text_Muted));
+ m_activeActionRects[i] = actionR;
}
- if (isActive)
- m_activeActionRects[i] = actionRect;
+ painter->setFont(actionFont);
+ painter->setPen((isDisabled ? actionDisabledTF : actionTF).color());
+ const QRect actionTextR = actionR.adjusted(0, 0, 0, -1);
+ painter->drawText(actionTextR, actionTF.drawTextFlags, action);
+ xx += actionR.width();
+ if (i < actions.count() - 1) {
+ const QRect dividerR(xx + s(HGapXs), yy, actionSepWidth, buttonHeight);
+ painter->fillRect(dividerR, themeColor(Theme::Token_Text_Muted));
+ }
+ xx += gapWidth;
}
+ yy += buttonHeight;
+ yy += s(VGapXs);
}
+ QTC_CHECK(option.rect.bottom() == yy + itemSpacing());
+ }
+
+ static int headerHeight()
+ {
+ const int paddingsHeight = s(VPaddingXs + VPaddingXs);
+ const int heightForSessionName = sessionNameTF.lineHeight() + paddingsHeight;
+ const int heightForIcon =
+ withIcon() ? int(icon().deviceIndependentSize().height()) + paddingsHeight : 0;
+ return qMax(heightForSessionName, heightForIcon);
}
QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &idx) const final
{
- int h = SESSION_LINE_HEIGHT;
- QString sessionName = idx.data(Qt::DisplayRole).toString();
- if (m_expandedSessions.contains(sessionName)) {
+ int h = headerHeight();
+ if (expanded(idx)) {
+ const QString sessionName = idx.data(Qt::DisplayRole).toString();
const FilePaths projects = ProjectManager::projectsForSessionName(sessionName);
- h += projects.size() * 40 + LINK_HEIGHT - 6;
+ const int projectEntryHeight =
+ s(VPaddingXs)
+ + projectNameTF.lineHeight()
+ + s(ExPaddingGapS)
+ + projectPathTF.lineHeight()
+ + s(VPaddingXs);
+ h += projects.size() * projectEntryHeight
+ + s(VGapXs)
+ + actionButtonHeight()
+ + s(VGapXs);
}
- return QSize(380, h + ItemGap);
+ return QSize(-1, h + itemSpacing());
}
bool editorEvent(QEvent *ev, QAbstractItemModel *model,
- const QStyleOptionViewItem &option, const QModelIndex &idx) final
+ const QStyleOptionViewItem &, const QModelIndex &idx) final
{
if (ev->type() == QEvent::MouseButtonRelease) {
const QMouseEvent *mouseEvent = static_cast(ev);
const Qt::MouseButtons button = mouseEvent->button();
const QPoint pos = static_cast(ev)->pos();
- const QRect rc(option.rect.right() - SESSION_ARROW_RECT_WIDTH, option.rect.top(),
- SESSION_ARROW_RECT_WIDTH, SESSION_LINE_HEIGHT);
const QString sessionName = idx.data(Qt::DisplayRole).toString();
- if (rc.contains(pos) || button == Qt::RightButton) {
+ if (m_activeExpandRect.contains(pos) || button == Qt::RightButton) {
// The expand/collapse "button".
if (m_expandedSessions.contains(sessionName))
m_expandedSessions.removeOne(sessionName);
@@ -421,23 +600,15 @@ public:
}
if (ev->type() == QEvent::MouseMove) {
emit model->layoutChanged({QPersistentModelIndex(idx)}); // Somewhat brutish.
- //update(option.rect);
return false;
}
return false;
}
private:
- const QColor hoverColor = themeColor(Theme::Welcome_HoverColor);
- const QColor textColor = themeColor(Theme::Welcome_TextColor);
- const QColor linkColor = themeColor(Theme::Welcome_LinkColor);
- const QColor disabledLinkColor = themeColor(Theme::Welcome_DisabledLinkColor);
- const QColor backgroundPrimaryColor = themeColor(Theme::Welcome_BackgroundPrimaryColor);
- const QColor foregroundPrimaryColor = themeColor(Theme::Welcome_ForegroundPrimaryColor);
- const QColor foregroundSecondaryColor = themeColor(Theme::Welcome_ForegroundSecondaryColor);
-
QStringList m_expandedSessions;
+ mutable QRect m_activeExpandRect;
mutable QRect m_activeSwitchToRect;
mutable QRect m_activeActionRects[3];
};
@@ -453,58 +624,89 @@ class ProjectDelegate : public BaseDelegate
public:
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &idx) const final
{
- QRect rc = option.rect;
+ // visible on withIcon() Extra margin right of project item
+ // | |
+ // +-------+-------+ +------+-----+
+ // | | | |
+ //
+ // +------------+--------+--------+------+--------+-------------+------------+------------+
+ // | | | | | | (VPaddingXs)| | |
+ // | | | | | +-------------+ | |
+ // | | | | | || | |
+ // | | | | | +-------------+ | |
+ // |(HPaddingXs)||(HGapXs)||(HGapXs)| (VGapXs) |(HPaddingXs)|(HPaddingXs)|
+ // | |(16x16) | | | +-------------+ | |
+ // | | | | | || | |
+ // | | | | | +-------------+ | |
+ // | | | | | | (VPaddingXs)| | |
+ // +------------+--------+--------+------+--------+-------------+------------+------------+ --+
+ // | (VGapL) | +-- Gap between project items
+ // +--------------------------------------------------------------------------------------+ --+
- const bool hovered = option.widget->isActiveWindow() && option.state & QStyle::State_MouseOver;
- const QRect bgRect = rc.adjusted(0, 0, -ItemGap, -ItemGap);
- painter->fillRect(rc, themeColor(Theme::Welcome_BackgroundSecondaryColor));
- painter->fillRect(bgRect, themeColor(hovered ? Theme::Welcome_HoverColor
- : Theme::Welcome_BackgroundPrimaryColor));
+ const bool hovered = option.widget->isActiveWindow()
+ && option.state & QStyle::State_MouseOver;
- const int x = rc.x();
- const int y = rc.y();
- const int firstBase = y + 18;
- const int secondBase = firstBase + 19;
+ const QRect bgR = option.rect.adjusted(0, 0, -s(HPaddingXs), -itemSpacing());
- static const QPixmap projectIcon =
- pixmap("project", Theme::Welcome_ForegroundSecondaryColor);
- painter->drawPixmap(x + 11, y + 6, projectIcon);
+ static const QPixmap icon = pixmap("project", Theme::Token_Text_Muted);
+ const QSize iconS = icon.deviceIndependentSize().toSize();
- QString projectName = idx.data(Qt::DisplayRole).toString();
- FilePath projectPath = FilePath::fromVariant(idx.data(ProjectModel::FilePathRole));
+ const int x = bgR.x();
+ const int numberX = x + s(HPaddingXs);
+ const int iconX = numberX + shortcutNumberWidth + s(HGapXs);
+ const int iconWidth = iconS.width();
+ const int textX = withIcon() ? iconX + iconWidth + s(HGapXs) : iconX;
+ const int textWidth = bgR.width() - s(HPaddingXs) - textX;
- painter->setPen(themeColor(Theme::Welcome_ForegroundSecondaryColor));
- painter->setFont(sizedFont(10, option.widget));
+ const int y = bgR.y();
+ const int iconHeight = iconS.height();
+ const int iconY = y + (bgR.height() - iconHeight) / 2;
+ const int projectNameY = y + s(VPaddingXs);
+ const QRect projectNameR(textX, projectNameY, textWidth, projectNameTF.lineHeight());
+ const int projectPathY = projectNameY + projectNameR.height() + s(VGapXs);
+ const QRect projectPathR(textX, projectPathY, textWidth, projectPathTF.lineHeight());
- if (idx.row() < 9)
- painter->drawText(x + 3, firstBase, QString::number(idx.row() + 1));
+ QTC_CHECK(option.rect.bottom() == projectPathR.bottom() + s(VPaddingXs) + itemSpacing());
- const int textSpace = rc.width() - TEXT_OFFSET_HORIZONTAL - ItemGap - 6;
-
- painter->setPen(themeColor(Theme::Welcome_LinkColor));
- painter->setFont(sizedFont(13, option.widget, hovered));
- const QString projectNameElided =
- painter->fontMetrics().elidedText(projectName, Qt::ElideRight, textSpace);
- painter->drawText(x + TEXT_OFFSET_HORIZONTAL, firstBase, projectNameElided);
-
- painter->setPen(themeColor(Theme::Welcome_ForegroundPrimaryColor));
- painter->setFont(sizedFont(13, option.widget));
- const QString displayPath =
- projectPath.osType() == OsTypeWindows ? projectPath.displayName()
- : projectPath.withTildeHomePath();
- const QString displayPathElided =
- painter->fontMetrics().elidedText(displayPath, Qt::ElideMiddle, textSpace);
- painter->drawText(x + TEXT_OFFSET_HORIZONTAL, secondBase, displayPathElided);
+ {
+ drawBackgroundRect(painter, bgR, hovered);
+ }
+ if (idx.row() < 9) {
+ painter->setPen(shortcutNumberTF.color());
+ painter->setFont(shortcutNumberTF.font());
+ const QRect numberR(numberX, y, shortcutNumberWidth, bgR.height());
+ const QString numberString = QString::number(idx.row() + 1);
+ painter->drawText(numberR, shortcutNumberTF.drawTextFlags, numberString);
+ }
+ if (withIcon()) {
+ painter->drawPixmap(iconX, iconY, icon);
+ }
+ {
+ painter->setPen(projectNameTF.color());
+ painter->setFont(projectNameTF.font(hovered));
+ const QString projectName = idx.data(Qt::DisplayRole).toString();
+ const QString projectNameElided =
+ painter->fontMetrics().elidedText(projectName, Qt::ElideRight, textWidth);
+ painter->drawText(projectNameR, projectNameTF.drawTextFlags, projectNameElided);
+ }
+ {
+ painter->setPen(projectPathTF.color());
+ painter->setFont(projectPathTF.font());
+ const FilePath projectPath =
+ FilePath::fromVariant(idx.data(ProjectModel::FilePathRole));
+ const QString displayPath =
+ projectPath.osType() == OsTypeWindows ? projectPath.displayName()
+ : projectPath.withTildeHomePath();
+ const QString displayPathElided =
+ painter->fontMetrics().elidedText(displayPath, Qt::ElideMiddle, textWidth);
+ painter->drawText(projectPathR, projectPathTF.drawTextFlags, displayPathElided);
+ }
}
- QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &idx) const final
+ QSize sizeHint([[maybe_unused]] const QStyleOptionViewItem &option,
+ [[maybe_unused]] const QModelIndex &idx) const override
{
- QString projectName = idx.data(Qt::DisplayRole).toString();
- QString projectPath = idx.data(ProjectModel::FilePathRole).toString();
- QFontMetrics fm(sizedFont(13, option.widget));
- int width = std::max(fm.horizontalAdvance(projectName),
- fm.horizontalAdvance(projectPath)) + TEXT_OFFSET_HORIZONTAL;
- return QSize(width, 47 + ItemGap);
+ return QSize(-1, itemHeight() + itemSpacing());
}
bool editorEvent(QEvent *ev, QAbstractItemModel *model,
@@ -541,6 +743,18 @@ public:
}
return false;
}
+
+private:
+ static int itemHeight()
+ {
+ const int height =
+ s(VPaddingXs)
+ + projectNameTF.lineHeight()
+ + s(VGapXs)
+ + projectPathTF.lineHeight()
+ + s(VPaddingXs);
+ return height;
+ }
};
class TreeView : public QTreeView
@@ -559,10 +773,7 @@ public:
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
setFocusPolicy(Qt::NoFocus);
-
- QPalette pal;
- pal.setColor(QPalette::Base, themeColor(Theme::Welcome_BackgroundSecondaryColor));
- viewport()->setPalette(pal);
+ setBackgroundColor(viewport(), Theme::Token_Background_Default);
}
};
@@ -577,54 +788,63 @@ public:
if (!projectWelcomePage->m_projectModel)
projectWelcomePage->m_projectModel = new ProjectModel(this);
- auto manageSessionsButton = new WelcomePageButton(this);
- manageSessionsButton->setText(Tr::tr("Manage..."));
- manageSessionsButton->setWithAccentColor(true);
- manageSessionsButton->setOnClicked([] { SessionManager::showSessionManager(); });
+ using namespace Layouting;
- auto sessionsLabel = new QLabel(this);
- sessionsLabel->setText(Tr::tr("Sessions"));
+ auto sessions = new QWidget;
+ {
+ auto sessionsLabel = new Label(Tr::tr("Sessions"), Label::Primary);
+ auto manageSessionsButton = new Button(Tr::tr("Manage..."), Button::MediumSecondary);
+ auto sessionsList = new TreeView(this, "Sessions");
+ sessionsList->setModel(projectWelcomePage->m_sessionModel);
+ sessionsList->header()->setSectionHidden(1, true); // The "last modified" column.
+ sessionsList->setItemDelegate(&m_sessionDelegate);
+ sessionsList->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ QSizePolicy sessionsSp(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ sessionsSp.setHorizontalStretch(3);
+ sessions->setSizePolicy(sessionsSp);
+ Column {
+ Row {
+ sessionsLabel,
+ st,
+ manageSessionsButton,
+ customMargin({HPaddingS, 0, sessionScrollBarGap, 0}),
+ },
+ sessionsList,
+ spacing(ExPaddingGapL),
+ customMargin({ExVPaddingGapXl, ExVPaddingGapXl, 0, 0}),
+ }.attachTo(sessions);
+ connect(manageSessionsButton, &Button::clicked,
+ this, &SessionManager::showSessionManager);
+ }
- auto recentProjectsLabel = new QLabel(this);
- recentProjectsLabel->setText(Tr::tr("Projects"));
+ auto projects = new QWidget;
+ {
+ auto projectsLabel = new Label(Tr::tr("Projects"), Label::Primary);
+ auto projectsList = new TreeView(this, "Recent Projects");
+ projectsList->setUniformRowHeights(true);
+ projectsList->setModel(projectWelcomePage->m_projectModel);
+ projectsList->setItemDelegate(&m_projectDelegate);
+ projectsList->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ QSizePolicy projectsSP(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ projectsSP.setHorizontalStretch(5);
+ projects->setSizePolicy(projectsSP);
+ Column {
+ Row {
+ projectsLabel,
+ customMargin({HPaddingS, 0, 0, 0}),
+ },
+ projectsList,
+ spacing(ExPaddingGapL),
+ customMargin({ExVPaddingGapXl - sessionScrollBarGap, ExVPaddingGapXl, 0, 0}),
+ }.attachTo(projects);
+ }
- auto sessionsList = new TreeView(this, "Sessions");
- sessionsList->setModel(projectWelcomePage->m_sessionModel);
- sessionsList->header()->setSectionHidden(1, true); // The "last modified" column.
- sessionsList->setItemDelegate(&m_sessionDelegate);
- sessionsList->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
-
- auto projectsList = new TreeView(this, "Recent Projects");
- projectsList->setUniformRowHeights(true);
- projectsList->setModel(projectWelcomePage->m_projectModel);
- projectsList->setItemDelegate(&m_projectDelegate);
- projectsList->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
-
- auto sessionHeader = panelBar(this);
- auto hbox11 = new QHBoxLayout(sessionHeader);
- hbox11->setContentsMargins(12, 0, 0, 0);
- hbox11->addWidget(sessionsLabel);
- hbox11->addStretch(1);
- hbox11->addWidget(manageSessionsButton);
-
- auto projectsHeader = panelBar(this);
- auto hbox21 = new QHBoxLayout(projectsHeader);
- hbox21->setContentsMargins(hbox11->contentsMargins());
- hbox21->addWidget(recentProjectsLabel);
-
- auto grid = new QGridLayout(this);
- grid->setContentsMargins(0, 0, 0, ItemGap);
- grid->setHorizontalSpacing(0);
- grid->setVerticalSpacing(ItemGap);
- grid->addWidget(panelBar(this), 0, 0);
- grid->addWidget(sessionHeader, 0, 1);
- grid->addWidget(sessionsList, 1, 1);
- grid->addWidget(panelBar(this), 0, 2);
- grid->setColumnStretch(1, 9);
- grid->setColumnMinimumWidth(1, 200);
- grid->addWidget(projectsHeader, 0, 3);
- grid->addWidget(projectsList, 1, 3);
- grid->setColumnStretch(3, 20);
+ Row {
+ sessions,
+ projects,
+ spacing(0),
+ noMargin(),
+ }.attachTo(this);
}
SessionDelegate m_sessionDelegate;
diff --git a/src/plugins/qtsupport/exampleslistmodel.cpp b/src/plugins/qtsupport/exampleslistmodel.cpp
index 18aa6cc3811..e81535acb42 100644
--- a/src/plugins/qtsupport/exampleslistmodel.cpp
+++ b/src/plugins/qtsupport/exampleslistmodel.cpp
@@ -250,7 +250,7 @@ static QPixmap fetchPixmapAndUpdatePixmapCache(const QString &url)
const int dpr = qApp->devicePixelRatio();
// boundedTo -> don't scale thumbnails up
const QSize scaledSize =
- WelcomePageHelpers::GridItemImageSize.boundedTo(img.size()) * dpr;
+ WelcomePageHelpers::WelcomeThumbnailSize.boundedTo(img.size()) * dpr;
const QImage scaled = img.isNull() ? img
: img.scaled(scaledSize,
Qt::KeepAspectRatio,
diff --git a/src/plugins/qtsupport/gettingstartedwelcomepage.cpp b/src/plugins/qtsupport/gettingstartedwelcomepage.cpp
index f5b5c0ac49f..f02a433fbe7 100644
--- a/src/plugins/qtsupport/gettingstartedwelcomepage.cpp
+++ b/src/plugins/qtsupport/gettingstartedwelcomepage.cpp
@@ -21,13 +21,13 @@
#include
#include
+#include
#include
#include
#include
#include
#include
-#include
#include
#include
#include
@@ -249,8 +249,9 @@ protected:
painter->setFont(option.font);
painter->setCompositionMode(QPainter::CompositionMode_Difference);
painter->setPen(Qt::white);
- painter->drawText(currentPixmapRect.translated(0, -WelcomePageHelpers::ItemGap),
- exampleItem->videoLength, Qt::AlignBottom | Qt::AlignHCenter);
+ painter->drawText(
+ currentPixmapRect.translated(0, -StyleHelper::SpacingTokens::VPaddingXxs),
+ exampleItem->videoLength, Qt::AlignBottom | Qt::AlignHCenter);
painter->restore();
static const QPixmap playOverlay =
StyleHelper::dpiSpecificImageFile(":/qtsupport/images/icons/playoverlay.png");
@@ -274,29 +275,25 @@ public:
{
m_exampleDelegate.setShowExamples(isExamples);
- auto searchBox = new SearchBox(this);
- m_searcher = searchBox->m_lineEdit;
+ using namespace StyleHelper::SpacingTokens;
- auto grid = new QGridLayout(this);
- grid->setContentsMargins(0, 0, 0, WelcomePageHelpers::ItemGap);
- grid->setHorizontalSpacing(0);
- grid->setVerticalSpacing(WelcomePageHelpers::ItemGap);
+ using namespace Layouting;
+ Row titleRow {
+ customMargin({0, 0, ExVPaddingGapXl, 0}),
+ spacing(ExVPaddingGapXl),
+ };
- auto searchBar = WelcomePageHelpers::panelBar(this);
- auto hbox = new QHBoxLayout(searchBar);
- hbox->setContentsMargins(0, 0, 0, 0);
+ m_searcher = new SearchBox;
if (m_isExamples) {
m_searcher->setPlaceholderText(Tr::tr("Search in Examples..."));
- auto exampleSetSelector = new QComboBox(this);
- QPalette pal = exampleSetSelector->palette();
- // for macOS dark mode
- pal.setColor(QPalette::Text, Utils::creatorTheme()->color(Theme::Welcome_TextColor));
- exampleSetSelector->setPalette(pal);
- exampleSetSelector->setMinimumWidth(Core::WelcomePageHelpers::GridItemWidth);
- exampleSetSelector->setMaximumWidth(Core::WelcomePageHelpers::GridItemWidth);
+ auto exampleSetSelector = new ComboBox;
+ exampleSetSelector->setSizeAdjustPolicy(QComboBox::AdjustToContents);
+ exampleSetSelector->setMinimumWidth(ListItemDelegate::itemSize().width()
+ - ExVPaddingGapXl);
exampleSetSelector->setModel(s_exampleSetModel);
exampleSetSelector->setCurrentIndex(s_exampleSetModel->selectedExampleSet());
+ titleRow.addItem(exampleSetSelector);
connect(exampleSetSelector,
&QComboBox::activated,
s_exampleSetModel,
@@ -305,23 +302,23 @@ public:
&ExampleSetModel::selectedExampleSetChanged,
exampleSetSelector,
&QComboBox::setCurrentIndex);
-
- hbox->setSpacing(Core::WelcomePageHelpers::HSpacing);
- hbox->addWidget(exampleSetSelector);
} else {
m_searcher->setPlaceholderText(Tr::tr("Search in Tutorials..."));
}
- hbox->addWidget(searchBox);
- grid->addWidget(WelcomePageHelpers::panelBar(this), 0, 0);
- grid->addWidget(searchBar, 0, 1);
- grid->addWidget(WelcomePageHelpers::panelBar(this), 0, 2);
+ titleRow.addItem(m_searcher);
- auto gridView = new SectionedGridView(this);
+ auto gridView = new SectionedGridView;
m_viewController
= new ExamplesViewController(s_exampleSetModel, gridView, m_searcher, isExamples, this);
gridView->setItemDelegate(&m_exampleDelegate);
- grid->addWidget(gridView, 1, 1, 1, 2);
+
+ Column {
+ titleRow,
+ gridView,
+ spacing(ExVPaddingGapXl),
+ customMargin({ExVPaddingGapXl, ExVPaddingGapXl, 0, 0}),
+ }.attachTo(this);
connect(&m_exampleDelegate, &ExampleDelegate::tagClicked,
this, &ExamplesPageWidget::onTagClicked);
diff --git a/src/plugins/welcome/images/expandarrow.png b/src/plugins/welcome/images/expandarrow.png
deleted file mode 100644
index 1c80e4eaac4..00000000000
Binary files a/src/plugins/welcome/images/expandarrow.png and /dev/null differ
diff --git a/src/plugins/welcome/images/expandarrow@2x.png b/src/plugins/welcome/images/expandarrow@2x.png
deleted file mode 100644
index 30b7d23aed7..00000000000
Binary files a/src/plugins/welcome/images/expandarrow@2x.png and /dev/null differ
diff --git a/src/plugins/welcome/images/link.png b/src/plugins/welcome/images/link.png
new file mode 100644
index 00000000000..3fff0753bc9
Binary files /dev/null and b/src/plugins/welcome/images/link.png differ
diff --git a/src/plugins/welcome/images/link@2x.png b/src/plugins/welcome/images/link@2x.png
new file mode 100644
index 00000000000..be4f2789aef
Binary files /dev/null and b/src/plugins/welcome/images/link@2x.png differ
diff --git a/src/plugins/welcome/images/project.png b/src/plugins/welcome/images/project.png
index 1fd5370e7e5..30862beb287 100644
Binary files a/src/plugins/welcome/images/project.png and b/src/plugins/welcome/images/project.png differ
diff --git a/src/plugins/welcome/images/project@2x.png b/src/plugins/welcome/images/project@2x.png
index df357dfa95f..c5cc11155be 100644
Binary files a/src/plugins/welcome/images/project@2x.png and b/src/plugins/welcome/images/project@2x.png differ
diff --git a/src/plugins/welcome/images/session.png b/src/plugins/welcome/images/session.png
index 7a1e2c51d25..aa14f11de84 100644
Binary files a/src/plugins/welcome/images/session.png and b/src/plugins/welcome/images/session.png differ
diff --git a/src/plugins/welcome/images/session@2x.png b/src/plugins/welcome/images/session@2x.png
index d146a1a3e9c..c53cf12bfa6 100644
Binary files a/src/plugins/welcome/images/session@2x.png and b/src/plugins/welcome/images/session@2x.png differ
diff --git a/src/plugins/welcome/welcome.qrc b/src/plugins/welcome/welcome.qrc
index 6734370f951..3158be85682 100644
--- a/src/plugins/welcome/welcome.qrc
+++ b/src/plugins/welcome/welcome.qrc
@@ -8,8 +8,8 @@
images/project@2x.png
images/session.png
images/session@2x.png
- images/expandarrow.png
- images/expandarrow@2x.png
images/border.png
+ images/link.png
+ images/link@2x.png
diff --git a/src/plugins/welcome/welcomeplugin.cpp b/src/plugins/welcome/welcomeplugin.cpp
index 0590823ea63..2513ebaa10f 100644
--- a/src/plugins/welcome/welcomeplugin.cpp
+++ b/src/plugins/welcome/welcomeplugin.cpp
@@ -22,12 +22,14 @@
#include
#include
#include
+#include
#include
#include
#include
#include
#include
+#include
#include
#include
#include
@@ -42,31 +44,15 @@ using namespace Core;
using namespace Core::WelcomePageHelpers;
using namespace ExtensionSystem;
using namespace Utils;
+using namespace StyleHelper::SpacingTokens;
namespace Welcome {
namespace Internal {
class TopArea;
class SideArea;
-class BottomArea;
const char currentPageSettingsKeyC[] = "Welcome2Tab";
-constexpr int buttonSpacing = 16;
-
-static QColor themeColor(Theme::Color role)
-{
- return Utils::creatorTheme()->color(role);
-}
-
-static void addWeakVerticalSpacerToLayout(QVBoxLayout *layout, int maximumSize)
-{
- auto weakSpacer = new QWidget;
- weakSpacer->setMaximumHeight(maximumSize);
- weakSpacer->setMinimumHeight(buttonSpacing);
- weakSpacer->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Maximum);
- layout->addWidget(weakSpacer);
- layout->setStretchFactor(weakSpacer, 1);
-}
class WelcomeMode : public IMode
{
@@ -85,9 +71,9 @@ private:
QStackedWidget *m_pageStack;
TopArea *m_topArea;
SideArea *m_sideArea;
- BottomArea *m_bottomArea;
QList m_pluginList;
- QList m_pageButtons;
+ QList m_pageButtons;
+ QButtonGroup *m_buttonGroup;
Id m_activePage;
Id m_defaultPage;
};
@@ -140,55 +126,43 @@ public:
TopArea(QWidget *parent = nullptr)
: QWidget(parent)
{
- setAutoFillBackground(true);
- setMinimumHeight(11); // For compact state
- setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
- setPalette(themeColor(Theme::Welcome_BackgroundPrimaryColor));
+ setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
- m_title = new QWidget;
-
- auto hbox = new QHBoxLayout(m_title);
- hbox->setSpacing(0);
- hbox->setContentsMargins(HSpacing - 5, 2, 0, 2);
+ constexpr TextFormat welcomeTF {Theme::Token_Text_Default, StyleHelper::UiElementH2};
+ auto ideIconLabel = new QLabel;
{
- auto ideIconLabel = new QLabel;
const QPixmap logo = Core::Icons::QTCREATORLOGO_BIG.pixmap();
- ideIconLabel->setPixmap(logo.scaled(logo.size() * 0.6, Qt::IgnoreAspectRatio,
- Qt::SmoothTransformation));
- hbox->addWidget(ideIconLabel, 0);
-
- hbox->addSpacing(16);
-
- const QFont welcomeFont = StyleHelper::uiFont(StyleHelper::UiElementH1);
-
- auto welcomeLabel = new QLabel("Welcome to");
- welcomeLabel->setFont(welcomeFont);
- hbox->addWidget(welcomeLabel, 0);
-
- hbox->addSpacing(8);
-
- auto ideNameLabel = new QLabel(QGuiApplication::applicationDisplayName());
- ideNameLabel->setFont(welcomeFont);
- ideNameLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
- QPalette pal = palette();
- pal.setColor(QPalette::WindowText, themeColor(Theme::Welcome_AccentColor));
- ideNameLabel->setPalette(pal);
- hbox->addWidget(ideNameLabel, 1);
+ const int size = logo.width();
+ const QRect cropR = size == 128 ? QRect(9, 22, 110, 84) : QRect(17, 45, 222, 166);
+ const QPixmap croppedLogo = logo.copy(cropR);
+ const int lineHeight = welcomeTF.lineHeight();
+ const QPixmap scaledCroppedLogo =
+ croppedLogo.scaledToHeight((lineHeight - 12) * devicePixelRatioF(),
+ Qt::SmoothTransformation);
+ ideIconLabel->setPixmap(scaledCroppedLogo);
+ ideIconLabel->setFixedHeight(lineHeight);
}
- auto mainLayout = new QHBoxLayout(this);
- mainLayout->setContentsMargins(0, 0, 0, 0);
- mainLayout->addWidget(m_title);
- }
+ auto welcomeLabel = new QLabel(Tr::tr("Welcome to %1")
+ .arg(QGuiApplication::applicationDisplayName()));
+ {
+ welcomeLabel->setFont(welcomeTF.font());
+ QPalette pal = palette();
+ pal.setColor(QPalette::WindowText, welcomeTF.color());
+ welcomeLabel->setPalette(pal);
+ }
- void setCompact(bool compact)
- {
- m_title->setVisible(!compact);
- }
+ using namespace Layouting;
-private:
- QWidget *m_title;
+ Row {
+ ideIconLabel,
+ welcomeLabel,
+ st,
+ spacing(ExVPaddingGapXl),
+ customMargin({HPaddingM, VPaddingM, HPaddingM, VPaddingM}),
+ }.attachTo(this);
+ }
};
class SideArea : public QScrollArea
@@ -201,114 +175,103 @@ public:
{
setWidgetResizable(true);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setFrameShape(QFrame::NoFrame);
- setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Ignored);
+ setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored);
- auto mainWidget = new QWidget(this);
- mainWidget->setAutoFillBackground(true);
- mainWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
- mainWidget->setPalette(themeColor(Theme::Welcome_BackgroundPrimaryColor));
+ using namespace Layouting;
- auto vbox = new QVBoxLayout(mainWidget);
- vbox->setSpacing(0);
- vbox->setContentsMargins(HSpacing, 0, HSpacing, 0);
+ Column mainLayout {
+ spacing(0),
+ customMargin({ExVPaddingGapXl, 0, ExVPaddingGapXl, 0}),
+ };
+
+ m_essentials = new QWidget;
+ Column essentials {
+ spacing(0),
+ noMargin(),
+ };
{
- auto projectVBox = new QVBoxLayout;
- projectVBox->setSpacing(buttonSpacing);
- auto newButton = new WelcomePageButton(mainWidget);
- newButton->setText(Tr::tr("Create Project..."));
- newButton->setWithAccentColor(true);
- newButton->setOnClicked([] {
- QAction *openAction = ActionManager::command(Core::Constants::NEW)->action();
- openAction->trigger();
- });
+ auto newButton = new Button(Tr::tr("Create Project..."), Button::MediumPrimary);
+ auto openButton = new Button(Tr::tr("Open Project..."), Button::MediumSecondary);
- auto openButton = new WelcomePageButton(mainWidget);
- openButton->setText(Tr::tr("Open Project..."));
- openButton->setWithAccentColor(true);
- openButton->setOnClicked([] {
+ Column projectButtons {
+ newButton,
+ openButton,
+ spacing(ExPaddingGapL),
+ customMargin({0, ExVPaddingGapXl, 0, ExVPaddingGapXl}),
+ };
+
+ essentials.addItem(projectButtons);
+
+ connect(openButton, &Button::clicked, this, [] {
QAction *openAction = ActionManager::command(Core::Constants::OPEN)->action();
openAction->trigger();
});
-
- projectVBox->addWidget(newButton);
- projectVBox->addWidget(openButton);
- vbox->addItem(projectVBox);
- }
-
- addWeakVerticalSpacerToLayout(vbox, 34);
-
- {
- auto newVBox = new QVBoxLayout;
- newVBox->setSpacing(buttonSpacing / 3);
- vbox->addItem(newVBox);
-
- auto newLabel = new QLabel(Tr::tr("New to Qt?"), mainWidget);
- newLabel->setAlignment(Qt::AlignHCenter);
- newVBox->addWidget(newLabel);
-
- auto getStartedButton = new WelcomePageButton(mainWidget);
- getStartedButton->setText(Tr::tr("Get Started"));
- getStartedButton->setOnClicked([] {
- QDesktopServices::openUrl(
- QString("qthelp://org.qt-project.qtcreator/doc/creator-getting-started.html"));
+ connect(newButton, &Button::clicked, this, [] {
+ QAction *openAction = ActionManager::command(Core::Constants::NEW)->action();
+ openAction->trigger();
});
- newVBox->addWidget(getStartedButton);
}
- addWeakVerticalSpacerToLayout(vbox, 56);
-
{
auto l = m_pluginButtons = new QVBoxLayout;
- l->setSpacing(buttonSpacing);
- vbox->addItem(l);
+ l->setSpacing(VGapL);
+ l->setContentsMargins({});
+ essentials.addItem(l);
}
- vbox->addStretch(1);
+ essentials.attachTo(m_essentials);
+ mainLayout.addItem(m_essentials);
+ mainLayout.addItem(st);
+ {
+ auto label = new Label(Tr::tr("Explore more"), Label::Secondary);
+ label->setContentsMargins(HPaddingXxs, 0, 0, 0); // Is indented in Figma design
+
+ Column linksLayout {
+ label,
+ spacing(VGapS),
+ customMargin({0, VGapL, 0, ExVPaddingGapXl}),
+ };
+
+ const struct {
+ const QString label;
+ const QString url;
+ } links [] =
+ {
+ { Tr::tr("Get Started"), "qthelp://org.qt-project.qtcreator/doc/creator-getting-started.html" },
+ { Tr::tr("Get Qt"), "https://www.qt.io/download" },
+ { Tr::tr("Qt Account"), "https://account.qt.io" },
+ { Tr::tr("Online Community"), "https://forum.qt.io" },
+ { Tr::tr("Blogs"), "https://planet.qt.io" },
+ { Tr::tr("User Guide"), "qthelp://org.qt-project.qtcreator/doc/index.html" },
+ };
+ for (auto &link : links) {
+ auto button = new Button(link.label, Button::SmallLink, this);
+ connect(button, &Button::clicked, this, [link]{
+ QDesktopServices::openUrl(link.url);});
+ button->setToolTip(link.url);
+ static const QPixmap icon = Icon({{":/welcome/images/link.png",
+ Theme::Token_Accent_Default}},
+ Icon::Tint).pixmap();
+ button->setPixmap(icon);
+ linksLayout.addItem(button);
+ }
+
+ m_links = new QWidget;
+ linksLayout.attachTo(m_links);
+ mainLayout.addItem(m_links);
+ }
+
+ QWidget *mainWidget = mainLayout.emerge();
setWidget(mainWidget);
}
QVBoxLayout *m_pluginButtons = nullptr;
-};
-
-class BottomArea : public QWidget
-{
- Q_OBJECT
-
-public:
- BottomArea(QWidget *parent = nullptr)
- : QWidget(parent)
- {
- setAutoFillBackground(true);
- setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
- setPalette(themeColor(Theme::Welcome_BackgroundPrimaryColor));
-
- auto hbox = new QHBoxLayout(this);
- hbox->setSpacing(0);
- hbox->setContentsMargins(0, 2 * ItemGap, HSpacing, 2 * ItemGap);
-
- const QList > links {
- { Tr::tr("Get Qt"), "https://www.qt.io/download" },
- { Tr::tr("Qt Account"), "https://account.qt.io" },
- { Tr::tr("Online Community"), "https://forum.qt.io" },
- { Tr::tr("Blogs"), "https://planet.qt.io" },
- { Tr::tr("User Guide"), "qthelp://org.qt-project.qtcreator/doc/index.html" },
- };
- for (const QPair &link : links) {
- auto button = new WelcomePageButton(this);
- button->setSize(WelcomePageButton::SizeSmall);
- button->setText(link.first);
- button->setOnClicked([link]{ QDesktopServices::openUrl(link.second); });
- button->setWithAccentColor(true);
- button->setMaximumWidth(220);
- button->setToolTip(link.second);
- if (hbox->count() > 0)
- hbox->addStretch(1);
- hbox->addWidget(button, 20);
- }
- }
+ QWidget *m_essentials = nullptr;
+ QWidget *m_links = nullptr;
};
WelcomeMode::WelcomeMode()
@@ -327,41 +290,51 @@ WelcomeMode::WelcomeMode()
setContextHelp("Qt Creator Manual");
setContext(Context(Constants::C_WELCOME_MODE));
- QPalette palette = creatorTheme()->palette();
- palette.setColor(QPalette::Window, themeColor(Theme::Welcome_BackgroundPrimaryColor));
-
m_modeWidget = new ResizeSignallingWidget;
- m_modeWidget->setPalette(palette);
+ setBackgroundColor(m_modeWidget, Theme::Token_Background_Default);
connect(m_modeWidget, &ResizeSignallingWidget::resized, this,
[this](const QSize &size, const QSize &) {
- const bool hideSideArea = size.width() <= 750;
- const bool hideBottomArea = size.width() <= 850;
- const bool compactVertically = size.height() <= 530;
- m_sideArea->setVisible(!hideSideArea);
- m_bottomArea->setVisible(!(hideBottomArea || compactVertically));
- m_topArea->setCompact(compactVertically);
+ const QSize essentialsS = m_sideArea->m_essentials->size();
+ const QSize linksS = m_sideArea->m_links->size();
+ const QSize sideAreaS = m_sideArea->size();
+ const QSize topAreaS = m_topArea->size();
+ const QSize mainWindowS = ICore::mainWindow()->size();
+
+ const bool showSideArea = sideAreaS.width() < size.width() / 4;
+ const bool showTopArea = topAreaS.height() < mainWindowS.height() / 7.75;
+ const bool showLinks =
+ linksS.height() + essentialsS.height() < sideAreaS.height() && showTopArea;
+
+ m_sideArea->m_links->setVisible(showLinks);
+ m_sideArea->setVisible(showSideArea);
+ m_topArea->setVisible(showTopArea);
});
m_sideArea = new SideArea(m_modeWidget);
+ m_buttonGroup = new QButtonGroup(m_modeWidget);
+ m_buttonGroup->setExclusive(true);
+
m_pageStack = new QStackedWidget(m_modeWidget);
- palette.setColor(QPalette::Window, themeColor(Theme::Welcome_BackgroundSecondaryColor));
- m_pageStack->setPalette(palette);
m_pageStack->setObjectName("WelcomeScreenStackedWidget");
m_pageStack->setAutoFillBackground(true);
m_topArea = new TopArea;
- m_bottomArea = new BottomArea;
- auto layout = new QGridLayout(m_modeWidget);
- layout->addWidget(new StyledBar(m_modeWidget), 0, 0, 1, 2);
- layout->addWidget(m_topArea, 1, 0, 1, 2);
- layout->addWidget(m_sideArea, 2, 0, 2, 1);
- layout->addWidget(m_pageStack, 2, 1, 1, 1);
- layout->setColumnStretch(1, 10);
- layout->addWidget(m_bottomArea, 3, 1, 1, 1);
- layout->setContentsMargins(0, 0, 0, 0);
- layout->setSpacing(0);
+ using namespace Layouting;
+
+ Column {
+ new StyledBar,
+ m_topArea,
+ createRule(Qt::Horizontal),
+ Row {
+ m_sideArea,
+ createRule(Qt::Vertical),
+ m_pageStack,
+ },
+ noMargin(),
+ spacing(0),
+ }.attachTo(m_modeWidget);
setWidget(m_modeWidget);
}
@@ -402,11 +375,11 @@ void WelcomeMode::addPage(IWelcomePage *page)
if (m_pluginList.at(idx)->priority() >= pagePriority)
break;
}
- auto pageButton = new WelcomePageButton(m_sideArea->widget());
+ auto pageButton = new Button(page->title(), Button::SmallList, m_sideArea->widget());
auto pageId = page->id();
pageButton->setText(page->title());
- pageButton->setActiveChecker([this, pageId] { return m_activePage == pageId; });
+ m_buttonGroup->addButton(pageButton);
m_pluginList.insert(idx, page);
m_pageButtons.insert(idx, pageButton);
@@ -417,6 +390,7 @@ void WelcomeMode::addPage(IWelcomePage *page)
m_pageStack->insertWidget(idx, stackPage);
connect(page, &QObject::destroyed, this, [this, page, stackPage, pageButton] {
+ m_buttonGroup->removeButton(pageButton);
m_pluginList.removeOne(page);
m_pageButtons.removeOne(pageButton);
delete pageButton;
@@ -426,13 +400,13 @@ void WelcomeMode::addPage(IWelcomePage *page)
auto onClicked = [this, pageId, stackPage] {
m_activePage = pageId;
m_pageStack->setCurrentWidget(stackPage);
- for (WelcomePageButton *pageButton : std::as_const(m_pageButtons))
- pageButton->recheckActive();
};
- pageButton->setOnClicked(onClicked);
- if (pageId == m_activePage)
+ connect(pageButton, &Button::clicked, this, onClicked);
+ if (pageId == m_activePage) {
onClicked();
+ pageButton->setChecked(true);
+ }
}
} // namespace Internal
diff --git a/src/tools/icons/qtcreatoricons.svg b/src/tools/icons/qtcreatoricons.svg
index 07452dc8c1e..9ced69d3199 100644
--- a/src/tools/icons/qtcreatoricons.svg
+++ b/src/tools/icons/qtcreatoricons.svg
@@ -664,6 +664,14 @@
width="100%"
height="100%"
transform="matrix(1.5,0,0,1.5,0,-242)" />
+
-
+
+ id="path8101"
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linejoin:round"
+ d="m 219,210 6,4 -6,4 z m -7,-5 h 18 v 18 h -18 z" />
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+