aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--share/qtcreator/static.pro1
-rw-r--r--share/qtcreator/themes/dark.creatortheme129
-rw-r--r--share/qtcreator/themes/default.creatortheme118
-rw-r--r--share/qtcreator/welcomescreen/develop.qml4
-rw-r--r--share/qtcreator/welcomescreen/welcomescreen.qml3
-rw-r--r--share/qtcreator/welcomescreen/widgets/Button.qml29
-rw-r--r--share/qtcreator/welcomescreen/widgets/Delegate.qml6
-rw-r--r--share/qtcreator/welcomescreen/widgets/IconAndLink.qml2
-rw-r--r--share/qtcreator/welcomescreen/widgets/LinkedText.qml7
-rw-r--r--share/qtcreator/welcomescreen/widgets/ProjectItem.qml6
-rw-r--r--share/qtcreator/welcomescreen/widgets/RecentProjects.qml1
-rw-r--r--share/qtcreator/welcomescreen/widgets/SearchBar.qml6
-rw-r--r--share/qtcreator/welcomescreen/widgets/SessionItem.qml13
-rw-r--r--share/qtcreator/welcomescreen/widgets/SideBar.qml30
-rw-r--r--share/share.qbs1
-rw-r--r--src/libs/utils/detailsbutton.cpp54
-rw-r--r--src/libs/utils/detailswidget.cpp32
-rw-r--r--src/libs/utils/outputformatter.cpp21
-rw-r--r--src/libs/utils/outputformatter.h2
-rw-r--r--src/libs/utils/theme/theme.cpp356
-rw-r--r--src/libs/utils/theme/theme.h217
-rw-r--r--src/libs/utils/theme/theme_p.cpp47
-rw-r--r--src/libs/utils/theme/theme_p.h59
-rw-r--r--src/libs/utils/theme/welcometheme.cpp87
-rw-r--r--src/libs/utils/theme/welcometheme.h87
-rw-r--r--src/libs/utils/utils-lib.pri10
-rw-r--r--src/libs/utils/utils.qbs13
-rw-r--r--src/plugins/coreplugin/Core.json.in5
-rw-r--r--src/plugins/coreplugin/core.qrc4
-rw-r--r--src/plugins/coreplugin/coreconstants.h3
-rw-r--r--src/plugins/coreplugin/coreplugin.cpp59
-rw-r--r--src/plugins/coreplugin/coreplugin.pro26
-rw-r--r--src/plugins/coreplugin/coreplugin.qbs24
-rw-r--r--src/plugins/coreplugin/editormanager/editorview.cpp19
-rw-r--r--src/plugins/coreplugin/fancyactionbar.cpp62
-rw-r--r--src/plugins/coreplugin/fancytabwidget.cpp100
-rw-r--r--src/plugins/coreplugin/find/searchresultwidget.cpp21
-rw-r--r--src/plugins/coreplugin/images/dark_fileicon.pngbin0 -> 288 bytes
-rw-r--r--src/plugins/coreplugin/images/dark_foldericon.pngbin0 -> 265 bytes
-rw-r--r--src/plugins/coreplugin/images/dark_magnifier.pngbin0 -> 488 bytes
-rw-r--r--src/plugins/coreplugin/images/dark_magnifier@2x.pngbin0 -> 589 bytes
-rw-r--r--src/plugins/coreplugin/mainwindow.cpp8
-rw-r--r--src/plugins/coreplugin/mainwindow.h3
-rw-r--r--src/plugins/coreplugin/manhattanstyle.cpp114
-rw-r--r--src/plugins/coreplugin/manhattanstyle.h4
-rw-r--r--src/plugins/coreplugin/outputpanemanager.cpp59
-rw-r--r--src/plugins/coreplugin/progressmanager/futureprogress.cpp11
-rw-r--r--src/plugins/coreplugin/progressmanager/progressbar.cpp33
-rw-r--r--src/plugins/coreplugin/progressmanager/progressmanager.cpp7
-rw-r--r--src/plugins/coreplugin/themeeditor/colorrole.cpp58
-rw-r--r--src/plugins/coreplugin/themeeditor/colorrole.h67
-rw-r--r--src/plugins/coreplugin/themeeditor/colorvariable.cpp73
-rw-r--r--src/plugins/coreplugin/themeeditor/colorvariable.h77
-rw-r--r--src/plugins/coreplugin/themeeditor/sectionedtablemodel.cpp124
-rw-r--r--src/plugins/coreplugin/themeeditor/sectionedtablemodel.h69
-rw-r--r--src/plugins/coreplugin/themeeditor/themecolors.cpp76
-rw-r--r--src/plugins/coreplugin/themeeditor/themecolors.h71
-rw-r--r--src/plugins/coreplugin/themeeditor/themecolorstableview.cpp62
-rw-r--r--src/plugins/coreplugin/themeeditor/themecolorstableview.h (renamed from share/qtcreator/welcomescreen/widgets/CustomColors.qml)33
-rw-r--r--src/plugins/coreplugin/themeeditor/themeeditorwidget.cpp142
-rw-r--r--src/plugins/coreplugin/themeeditor/themeeditorwidget.h78
-rw-r--r--src/plugins/coreplugin/themeeditor/themeeditorwidget.ui45
-rw-r--r--src/plugins/coreplugin/themeeditor/themesettingsitemdelegate.cpp227
-rw-r--r--src/plugins/coreplugin/themeeditor/themesettingsitemdelegate.h78
-rw-r--r--src/plugins/coreplugin/themeeditor/themesettingstablemodel.cpp297
-rw-r--r--src/plugins/coreplugin/themeeditor/themesettingstablemodel.h94
-rw-r--r--src/plugins/coreplugin/themesettings.cpp465
-rw-r--r--src/plugins/coreplugin/themesettings.h72
-rw-r--r--src/plugins/coreplugin/themesettings.ui73
-rw-r--r--src/plugins/cppeditor/cppeditor.qrc3
-rw-r--r--src/plugins/cppeditor/cppeditorplugin.cpp9
-rw-r--r--src/plugins/cppeditor/images/dark_qt_c.pngbin0 -> 341 bytes
-rw-r--r--src/plugins/cppeditor/images/dark_qt_cpp.pngbin0 -> 266 bytes
-rw-r--r--src/plugins/cppeditor/images/dark_qt_h.pngbin0 -> 502 bytes
-rw-r--r--src/plugins/help/helpplugin.cpp11
-rw-r--r--src/plugins/projectexplorer/doubletabwidget.cpp146
-rw-r--r--src/plugins/projectexplorer/miniprojecttargetselector.cpp48
-rw-r--r--src/plugins/projectexplorer/panelswidget.cpp29
-rw-r--r--src/plugins/qmakeprojectmanager/images/dark_headers.pngbin0 -> 502 bytes
-rw-r--r--src/plugins/qmakeprojectmanager/images/dark_sources.pngbin0 -> 266 bytes
-rw-r--r--src/plugins/qmakeprojectmanager/images/dark_unknown.pngbin0 -> 356 bytes
-rw-r--r--src/plugins/qmakeprojectmanager/profileeditor.cpp8
-rw-r--r--src/plugins/qmakeprojectmanager/qmakenodes.cpp10
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeprojectmanager.qrc3
-rw-r--r--src/plugins/qtsupport/images/dark_forms.pngbin0 -> 565 bytes
-rw-r--r--src/plugins/qtsupport/images/dark_qml.pngbin0 -> 287 bytes
-rw-r--r--src/plugins/qtsupport/images/dark_qt_project.pngbin0 -> 186 bytes
-rw-r--r--src/plugins/qtsupport/images/dark_qt_qrc.pngbin0 -> 424 bytes
-rw-r--r--src/plugins/qtsupport/qtoutputformatter.cpp5
-rw-r--r--src/plugins/qtsupport/qtsupport.qrc4
-rw-r--r--src/plugins/qtsupport/qtsupportconstants.h1
-rw-r--r--src/plugins/texteditor/texteditor.cpp8
-rw-r--r--src/plugins/todo/todoitemsmodel.cpp8
-rw-r--r--src/plugins/welcome/welcomeplugin.cpp25
94 files changed, 4139 insertions, 363 deletions
diff --git a/share/qtcreator/static.pro b/share/qtcreator/static.pro
index 6b4d50fd52..360fbf39cb 100644
--- a/share/qtcreator/static.pro
+++ b/share/qtcreator/static.pro
@@ -28,6 +28,7 @@ DATA_DIRS = \
examplebrowser \
snippets \
templates \
+ themes \
designer \
schemes \
styles \
diff --git a/share/qtcreator/themes/dark.creatortheme b/share/qtcreator/themes/dark.creatortheme
new file mode 100644
index 0000000000..4223600e39
--- /dev/null
+++ b/share/qtcreator/themes/dark.creatortheme
@@ -0,0 +1,129 @@
+[General]
+ThemeName=dark
+
+[Palette]
+shadowBackground=ff232323
+text=ffe7e7e7
+textDisabled=ffa0a0a4
+hoverBackground=ff515151
+selectedBackground=ff151515
+normalBackground=ff333333
+alternateBackground=ff515151
+error=ffff0000
+
+[Colors]
+BackgroundColorAlternate=alternateBackground
+BackgroundColorDark=shadowBackground
+BackgroundColorHover=hoverBackground
+BackgroundColorNormal=normalBackground
+BackgroundColorSelected=selectedBackground
+BadgeLabelBackgroundColorChecked=normalBackground
+BadgeLabelBackgroundColorUnchecked=selectedBackground
+BadgeLabelTextColorChecked=text
+BadgeLabelTextColorUnchecked=text
+CanceledSearchTextColor=ff0000
+ComboBoxArrowColor=text
+ComboBoxArrowColorDisabled=text
+ComboBoxTextColor=text
+DetailsButtonBackgroundColorHover=hoverBackground
+DetailsWidgetBackgroundColor=ff4a4a4a
+DockWidgetResizeHandleColor=shadowBackground
+DoubleTabWidget1stEmptyAreaBackgroundColor=normalBackground
+DoubleTabWidget1stSeparatorColor=hoverBackground
+DoubleTabWidget1stTabActiveTextColor=text
+DoubleTabWidget1stTabBackgroundColor=ff4a4a4a
+DoubleTabWidget1stTabInactiveTextColor=textDisabled
+DoubleTabWidget2ndSeparatorColor=hoverBackground
+DoubleTabWidget2ndTabActiveTextColor=text
+DoubleTabWidget2ndTabBackgroundColor=ff434343
+DoubleTabWidget2ndTabInactiveTextColor=textDisabled
+EditorPlaceholderColor=normalBackground
+FancyTabBarBackgroundColor=shadowBackground
+FancyTabWidgetDisabledSelectedTextColor=textDisabled
+FancyTabWidgetDisabledUnselectedTextColor=textDisabled
+FancyTabWidgetEnabledSelectedTextColor=text
+FancyTabWidgetEnabledUnselectedTextColor=text
+FancyToolButtonHoverColor=hoverBackground
+FancyToolButtonSelectedColor=selectedBackground
+FutureProgressBackgroundColor=shadowBackground
+MenuBarEmptyAreaBackgroundColor=shadowBackground
+MenuBarItemBackgroundColor=shadowBackground
+MenuBarItemTextColorDisabled=textDisabled
+MenuBarItemTextColorNormal=text
+MiniProjectTargetSelectorBackgroundColor=shadowBackground
+MiniProjectTargetSelectorBorderColor=shadowBackground
+MiniProjectTargetSelectorSummaryBackgroundColor=shadowBackground
+MiniProjectTargetSelectorTextColor=text
+OutputFormatter_DebugTextColor=text
+OutputFormatter_ErrorMessageTextColor=error
+OutputFormatter_NormalMessageTextColor=text
+OutputFormatter_StdErrTextColor=error
+OutputFormatter_StdOutTextColor=text
+OutputPaneButtonFlashColor=error
+OutputPaneToggleButtonTextColorChecked=text
+OutputPaneToggleButtonTextColorUnchecked=text
+PanelButtonToolBackgroundColorHover=hoverBackground
+PanelStatusBarBackgroundColor=shadowBackground
+PanelTextColor=text
+PanelsWidgetSeparatorLineColor=0
+ProgressBarColorError=error
+ProgressBarColorFinished=ff5aaa3c
+ProgressBarColorNormal=hoverBackground
+ProgressBarTitleColor=text
+QtOutputFormatter_LinkTextColor=ff0000ff
+SearchResultWidgetBackgroundColor=shadowBackground
+SearchResultWidgetTextColor=text
+TextColorDisabled=textDisabled
+TextColorHighlight=ffff0000
+TextColorNormal=text
+TodoItemTextColor=ff000000
+ToggleButtonBackgroundColor=shadowBackground
+ToolBarBackgroundColor=shadowBackground
+TreeViewArrowColorNormal=hoverBackground
+TreeViewArrowColorSelected=text
+Welcome_BackgroundColorNormal=normalBackground
+Welcome_Button_BorderColor=0
+Welcome_Button_TextColorNormal=ffe7e7e7
+Welcome_Button_TextColorPressed=ffffffff
+Welcome_Caption_TextColorNormal=ff4acb47
+Welcome_DividerColor=ff232323
+Welcome_Link_BackgroundColor=ff333333
+Welcome_Link_TextColorActive=fff0f0f0
+Welcome_Link_TextColorNormal=text
+Welcome_ProjectItem_BackgroundColorHover=0
+Welcome_ProjectItem_TextColorFilepath=textDisabled
+Welcome_SessionItemExpanded_BackgroundColor=selectedBackground
+Welcome_SessionItem_BackgroundColorHover=hoverBackground
+Welcome_SessionItem_BackgroundColorNormal=0
+Welcome_SideBar_BackgroundColor=ff434343
+Welcome_TextColorHeading=text
+Welcome_TextColorNormal=text
+
+[Flags]
+ComboBoxDrawTextShadow=false
+DerivePaletteFromTheme=true
+DrawIndicatorBranch=true
+DrawProgressBarSunken=false
+DrawSearchResultWidgetFrame=false
+DrawTargetSelectorBottom=false
+
+[Gradients]
+DetailsWidgetHeaderGradient\1\color=0
+DetailsWidgetHeaderGradient\1\pos=1
+DetailsWidgetHeaderGradient\size=1
+
+[IconOverlay]
+CSourceMimetype=:/cppeditor/images/dark_qt_c.png
+CppHeaderMimetype=:/cppeditor/images/dark_qt_h.png
+CppSourceMimetype=:/cppeditor/images/dark_qt_cpp.png
+PrfMimetype=:/qtsupport/images/dark_qt_project.png
+PriMimetype=:/qtsupport/images/dark_qt_project.png
+ProMimetype=:/qtsupport/images/dark_qt_project.png
+
+#TODO: needs to be ported to new ini format!
+[StandardIcons]
+SP_FileIcon=:/core/images/dark_fileicon.png
+SP_DirIcon=:/core/images/dark_foldericon.png
+
+[Style]
+WidgetStyle=StyleFlat
diff --git a/share/qtcreator/themes/default.creatortheme b/share/qtcreator/themes/default.creatortheme
new file mode 100644
index 0000000000..b16dd8dbd6
--- /dev/null
+++ b/share/qtcreator/themes/default.creatortheme
@@ -0,0 +1,118 @@
+[General]
+ThemeName=default
+
+[Palette]
+brightText = ffffffff
+darkText = ff000000
+
+[Colors]
+BackgroundColorAlternate=ff3d3d3d
+BackgroundColorDark=ff232323
+BackgroundColorHover=ff515151
+BackgroundColorNormal=ffffffff
+BackgroundColorSelected=ff151515
+BadgeLabelBackgroundColorChecked=ffe0e0e0
+BadgeLabelBackgroundColorUnchecked=ff808080
+BadgeLabelTextColorChecked=ff606060
+BadgeLabelTextColorUnchecked=ffffffff
+CanceledSearchTextColor=ffff0000
+ComboBoxArrowColor=ffb8b5b2
+ComboBoxArrowColorDisabled=ffdcdcdc
+ComboBoxTextColor=ffffffff
+DetailsButtonBackgroundColorHover=b4ffffff
+DetailsWidgetBackgroundColor=28ffffff
+DockWidgetResizeHandleColor=ff000000
+DoubleTabWidget1stEmptyAreaBackgroundColor=ffff0000
+DoubleTabWidget1stSeparatorColor=ffff0000
+DoubleTabWidget1stTabActiveTextColor=ff000000
+DoubleTabWidget1stTabBackgroundColor=ffff0000
+DoubleTabWidget1stTabInactiveTextColor=ff000000
+DoubleTabWidget2ndSeparatorColor=ffff0000
+DoubleTabWidget2ndTabActiveTextColor=ffffffff
+DoubleTabWidget2ndTabBackgroundColor=ffff0000
+DoubleTabWidget2ndTabInactiveTextColor=ff000000
+EditorPlaceholderColor=ffe0dcd8
+FancyTabBarBackgroundColor=ffff0000
+FancyTabWidgetDisabledSelectedTextColor=ffffffff
+FancyTabWidgetDisabledUnselectedTextColor=78ffffff
+FancyTabWidgetEnabledSelectedTextColor=ff3c3c3c
+FancyTabWidgetEnabledUnselectedTextColor=ffffffff
+FancyToolButtonHoverColor=28ffffff
+FancyToolButtonSelectedColor=32000000
+FutureProgressBackgroundColor=ffff0000
+MenuBarEmptyAreaBackgroundColor=ffff0000
+MenuBarItemBackgroundColor=ffff0000
+MenuBarItemTextColorDisabled=ffa0a0a4
+MenuBarItemTextColorNormal=ff000000
+MiniProjectTargetSelectorBackgroundColor=ffa0a0a0
+MiniProjectTargetSelectorBorderColor=ff000000
+MiniProjectTargetSelectorSummaryBackgroundColor=ff464646
+MiniProjectTargetSelectorTextColor=a0ffffff
+OutputFormatter_DebugTextColor=ffaa00aa
+OutputFormatter_ErrorMessageTextColor=ffaa0000
+OutputFormatter_NormalMessageTextColor=ff0000aa
+OutputFormatter_StdErrTextColor=ffaa0000
+OutputFormatter_StdOutTextColor=ff000000
+OutputPaneButtonFlashColor=ffff0000
+OutputPaneToggleButtonTextColorChecked=ffffffff
+OutputPaneToggleButtonTextColorUnchecked=ff000000
+PanelTextColor=brightText
+PanelButtonToolBackgroundColorHover=25ffffff
+PanelStatusBarBackgroundColor=ffff0000
+PanelsWidgetSeparatorLineColor=ffbfbcb8
+ProgressBarColorError=d2ff3c00
+ProgressBarColorFinished=ff5aaa3c
+ProgressBarColorNormal=b4ffffff
+ProgressBarTitleColor=ffffffff
+QtOutputFormatter_LinkTextColor=ff0000aa
+SearchResultWidgetBackgroundColor=ffffffff
+SearchResultWidgetTextColor=ff000000
+TextColorDisabled=ff000000
+TextColorHighlight=ffa0a0a4
+TextColorNormal=ff000000
+TodoItemTextColor=ff000000
+ToggleButtonBackgroundColor=ffff0000
+ToolBarBackgroundColor=ffff0000
+TreeViewArrowColorNormal=ffff0000
+TreeViewArrowColorSelected=ffff0000
+Welcome_BackgroundColorNormal=ffffffff
+Welcome_Button_BorderColor=ff737373
+Welcome_Button_TextColorNormal=ff000000
+Welcome_Button_TextColorPressed=ffc0c0c0
+Welcome_Caption_TextColorNormal=ff328930
+Welcome_DividerColor=ff737373
+Welcome_Link_BackgroundColor=ff909090
+Welcome_Link_TextColorActive=fff0f0f0
+Welcome_Link_TextColorNormal=ff328930
+Welcome_ProjectItem_BackgroundColorHover=fff9f9f9
+Welcome_ProjectItem_TextColorFilepath=ff6b6b6b
+Welcome_SessionItemExpanded_BackgroundColor=fff1f1f1
+Welcome_SessionItem_BackgroundColorHover=fff9f9f9
+Welcome_SessionItem_BackgroundColorNormal=19f9f9f9
+Welcome_SideBar_BackgroundColor=ffebebeb
+Welcome_TextColorHeading=ff535353
+Welcome_TextColorNormal=ff000000
+
+[Flags]
+ComboBoxDrawTextShadow=true
+DerivePaletteFromTheme=false
+DrawIndicatorBranch=false
+DrawProgressBarSunken=true
+DrawSearchResultWidgetFrame=true
+DrawTargetSelectorBottom=true
+
+[Gradients]
+DetailsWidgetHeaderGradient\1\color=ffffff
+DetailsWidgetHeaderGradient\1\pos=1
+DetailsWidgetHeaderGradient\size=1
+
+[IconOverlay]
+CSourceMimetype=:/cppeditor/images/qt_c.png
+CppHeaderMimetype=:/cppeditor/images/qt_h.png
+CppSourceMimetype=:/cppeditor/images/qt_cpp.png
+PrfMimetype=:/qtsupport/images/qt_project.png
+PriMimetype=:/qtsupport/images/qt_project.png
+ProMimetype=:/qtsupport/images/qt_project.png
+
+[Style]
+WidgetStyle=StyleDefault
diff --git a/share/qtcreator/welcomescreen/develop.qml b/share/qtcreator/welcomescreen/develop.qml
index 4681e2f3a0..dc0f9dc658 100644
--- a/share/qtcreator/welcomescreen/develop.qml
+++ b/share/qtcreator/welcomescreen/develop.qml
@@ -66,7 +66,7 @@ Controls.ScrollView {
x: 32
y: screenDependHeightDistance + 77
- color: "#535353"
+ color: creatorTheme.textColorHeading
text: qsTr("Sessions")
font.pixelSize: 16
font.family: "Helvetica"
@@ -78,7 +78,7 @@ Controls.ScrollView {
x: 406
y: screenDependHeightDistance + 77
- color: "#535353"
+ color: creatorTheme.textColorHeading
text: qsTr("Recent Projects")
anchors.left: sessionsTitle.right
anchors.leftMargin: 280
diff --git a/share/qtcreator/welcomescreen/welcomescreen.qml b/share/qtcreator/welcomescreen/welcomescreen.qml
index 91174ede31..67c5bab9e5 100644
--- a/share/qtcreator/welcomescreen/welcomescreen.qml
+++ b/share/qtcreator/welcomescreen/welcomescreen.qml
@@ -35,7 +35,6 @@ Item {
id: root
property var fonts: CustomFonts {}
- property var colors: CustomColors { }
property int screenDependHeightDistance: Math.min(50, Math.max(16, height / 30))
@@ -48,7 +47,7 @@ Item {
Rectangle {
id: splitter
- color: "#737373"
+ color: creatorTheme.dividerColor; // divider between left and right pane
width: 1
anchors.top: parent.top
anchors.bottom: parent.bottom
diff --git a/share/qtcreator/welcomescreen/widgets/Button.qml b/share/qtcreator/welcomescreen/widgets/Button.qml
index ec048f3f3a..9e860d7c8e 100644
--- a/share/qtcreator/welcomescreen/widgets/Button.qml
+++ b/share/qtcreator/welcomescreen/widgets/Button.qml
@@ -61,61 +61,60 @@ Button {
Rectangle {
anchors.fill: parent
antialiasing: true
- radius: 3
+ radius: (creatorTheme.widgetStyle === 'flat') ? 0 : 3
visible: !(button.pressed || button.checked)
gradient: Gradient {
GradientStop {
position: 0
- color: "#f9f9f9"
+ color: (theme==='dark') ? "#232323" : "#f9f9f9"
}
GradientStop {
position: 0.49
- color: "#f9f9f9"
+ color: (theme === 'dark') ? "#232323" : "#f9f9f9"
}
GradientStop {
position: 0.5
- color: "#eeeeee"
+ color: (theme === 'dark') ? "#232323" : "#eeeeee"
}
GradientStop {
position: 1
- color: "#eeeeee"
+ color: (theme === 'dark') ? "#232323" : "#eeeeee"
}
}
- border.color: "#737373"
-
+ border.color: creatorTheme.button_BorderColor
}
Rectangle {
anchors.fill: parent
antialiasing: true
- radius: 3
+ radius: (creatorTheme.widgetStyle === 'flat') ? 0 : 3
visible: button.pressed || button.checked
gradient: Gradient {
GradientStop {
position: 0.00;
- color: "#4c4c4c";
+ color: (theme === "dark") ? "#151515" : "#4c4c4c"
}
GradientStop {
position: 0.49;
- color: "#4c4c4c";
+ color: (theme === "dark") ? "#151515" : "#4c4c4c"
}
GradientStop {
position: 0.50;
- color: "#424242";
+ color: (theme === "dark") ? "#151515" : "#424242"
}
GradientStop {
position: 1.00;
- color: "#424242";
+ color: (theme === "dark") ? "#151515" : "#424242"
}
}
- border.color: "#333333"
+ border.color: creatorTheme.button_BorderColor
}
}
@@ -124,7 +123,9 @@ Button {
renderType: Text.NativeRendering
verticalAlignment: Text.AlignVCenter
text: button.text
- color: button.pressed || button.checked ? "lightGray" : "black"
+ color: button.pressed || button.checked
+ ? creatorTheme.button_TextColorPressed
+ : creatorTheme.button_TextColorNormal
font.pixelSize: 15
font.bold: false
smooth: true
diff --git a/share/qtcreator/welcomescreen/widgets/Delegate.qml b/share/qtcreator/welcomescreen/widgets/Delegate.qml
index 10dbd2298f..f7fcbfa059 100644
--- a/share/qtcreator/welcomescreen/widgets/Delegate.qml
+++ b/share/qtcreator/welcomescreen/widgets/Delegate.qml
@@ -34,6 +34,7 @@ Rectangle {
id: delegate
height: 240
width: 216
+ color: creatorTheme.backgroundColorNormal
property alias caption: captionItem.text
property alias imageSource: imageItem.source
@@ -106,7 +107,7 @@ Rectangle {
y: 161
width: 200
height: 69
- color: "#ffffff"
+ color: creatorTheme.backgroundColorNormal
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.left: parent.left
@@ -116,7 +117,7 @@ Rectangle {
id: captionItem
x: 16
y: 170
- color: colors.strongForegroundColor
+ color: creatorTheme.caption_TextColorNormal
text: qsTr("2D PAINTING EXAMPLE long description")
elide: Text.ElideRight
anchors.right: parent.right
@@ -163,6 +164,7 @@ Rectangle {
x: 16
y: 198
text: qsTr("Tags:")
+ color: creatorTheme.textColorNormal
smooth: true
font.italic: false
font.pixelSize: 11
diff --git a/share/qtcreator/welcomescreen/widgets/IconAndLink.qml b/share/qtcreator/welcomescreen/widgets/IconAndLink.qml
index 0e8aec6c91..3621653fda 100644
--- a/share/qtcreator/welcomescreen/widgets/IconAndLink.qml
+++ b/share/qtcreator/welcomescreen/widgets/IconAndLink.qml
@@ -44,7 +44,7 @@ Row {
LinkedText {
text: title
font.pixelSize: 11
- color: "black"
+ color: creatorTheme.textColorNormal // 'Qt Account' .. 'User Guide' on lower left
onClicked: {
if (openUrl)
gettingStarted.openUrl(openUrl);
diff --git a/share/qtcreator/welcomescreen/widgets/LinkedText.qml b/share/qtcreator/welcomescreen/widgets/LinkedText.qml
index 5c878538c4..c8c061a9d9 100644
--- a/share/qtcreator/welcomescreen/widgets/LinkedText.qml
+++ b/share/qtcreator/welcomescreen/widgets/LinkedText.qml
@@ -33,7 +33,8 @@ import QtQuick 2.1
NativeText {
id: root
height: 16
- color: active ? "#f0f0f0" : colors.linkColor
+ color: active ? creatorTheme.link_TextColorActive
+ : creatorTheme.link_TextColorNormal
verticalAlignment: Text.AlignVCenter
font: fonts.linkFont
@@ -53,7 +54,7 @@ NativeText {
property bool enlargeMouseArea: true
Rectangle {
- color: "#909090"
+ color: "#909090" // FIXME: theming: Where is this ever visible?
radius: 6
opacity: root.active
z: -1
@@ -65,7 +66,7 @@ NativeText {
}
Rectangle {
- color: "#909090"
+ color: "#909090" // FIXME: theming: Where is this ever visible?
opacity: root.active
z: -1
anchors.rightMargin: -6
diff --git a/share/qtcreator/welcomescreen/widgets/ProjectItem.qml b/share/qtcreator/welcomescreen/widgets/ProjectItem.qml
index 1216ac10f2..922eef5065 100644
--- a/share/qtcreator/welcomescreen/widgets/ProjectItem.qml
+++ b/share/qtcreator/welcomescreen/widgets/ProjectItem.qml
@@ -35,9 +35,9 @@ Item {
width: row.width + 8
height: text.height
- Rectangle {
+ Rectangle { // background shown on hover over project item
anchors.fill: parent
- color: "#f9f9f9"
+ color: creatorTheme.projectItem_BackgroundColorHover
visible: mouseArea.containsMouse
}
@@ -67,7 +67,7 @@ Item {
NativeText {
id: pathText
height: 20
- color: "#6b6b6b"
+ color: creatorTheme.projectItem_TextColorFilepath
font: fonts.smallPath
}
}
diff --git a/share/qtcreator/welcomescreen/widgets/RecentProjects.qml b/share/qtcreator/welcomescreen/widgets/RecentProjects.qml
index bd59444e23..e6f1c6ee01 100644
--- a/share/qtcreator/welcomescreen/widgets/RecentProjects.qml
+++ b/share/qtcreator/welcomescreen/widgets/RecentProjects.qml
@@ -34,6 +34,7 @@ import QtQuick.Controls 1.0
Rectangle {
id: projectList
height: column.height + 200
+ color: creatorTheme.backgroundColorNormal
property alias model: repeater.model
// Behavior on verticalScrollBar.opacity {
diff --git a/share/qtcreator/welcomescreen/widgets/SearchBar.qml b/share/qtcreator/welcomescreen/widgets/SearchBar.qml
index 9d4ce68536..1578445f59 100644
--- a/share/qtcreator/welcomescreen/widgets/SearchBar.qml
+++ b/share/qtcreator/welcomescreen/widgets/SearchBar.qml
@@ -37,9 +37,9 @@ Rectangle {
width: 930
height: 27
- color: "#ffffff"
+ color: creatorTheme.backgroundColorNormal
radius: 6
- border.color: "#cccccc"
+ border.color: "#cccccc" // FIXME: make themable
property alias placeholderText: lineEdit.placeholderText
property alias text: lineEdit.text
@@ -56,6 +56,8 @@ Rectangle {
font.pixelSize: 14
placeholderText: qsTr("Search...")
style: TextFieldStyle {
+ placeholderTextColor: creatorTheme.textColorNormal
+ textColor: creatorTheme.textColorNormal
background: Item {
}
}
diff --git a/share/qtcreator/welcomescreen/widgets/SessionItem.qml b/share/qtcreator/welcomescreen/widgets/SessionItem.qml
index 2d2f5ceaf6..3f8bfbf451 100644
--- a/share/qtcreator/welcomescreen/widgets/SessionItem.qml
+++ b/share/qtcreator/welcomescreen/widgets/SessionItem.qml
@@ -67,7 +67,10 @@ Item {
Rectangle {
z: -4
- color: "#f9f9f9"
+ // background of session item
+ color: (iArea.hovered || text.hovered || area2.hovered)
+ ? creatorTheme.sessionItem_BackgroundColorHover
+ : creatorTheme.sessionItem_BackgroundColorNormal
anchors.fill: parent
visible: iArea.containsMouse || text.hovered
anchors.topMargin: 1
@@ -115,6 +118,7 @@ Item {
NativeText {
text: projectsName[index]
font: fonts.boldDescription
+ color: creatorTheme.textColorNormal
}
NativeText {
x: 4
@@ -139,7 +143,7 @@ Item {
maximumLineCount: 2
elide: Text.ElideRight
height: lineCount == 2 ? font.pixelSize * 2 + 4 : font.pixelSize + 2
- color: "#6b6b6b"
+ color: creatorTheme.projectItem_TextColorFilepath
width: delegate.ListView.view.width - 48
MouseArea {
anchors.fill: parent
@@ -222,7 +226,8 @@ Item {
id: collapseButton
visible: text.hovered || iArea.containsMouse || delegate.expanded
- property color color: iArea.containsMouse ? "#E9E9E9" : "#f1f1f1"
+ property color color: iArea.containsMouse ? creatorTheme.sessionItem_BackgroundColorHover
+ : creatorTheme.sessionItemExpanded_BackgroundColor
anchors.fill: parent
Image {
@@ -238,7 +243,7 @@ Item {
Rectangle {
color: collapseButton.color
z: -1
- radius: 6
+ radius: creatorTheme.widgetStyle === 'flat' ? 0 : 6
anchors.fill: parent
anchors.topMargin: 1
anchors.bottomMargin: 1
diff --git a/share/qtcreator/welcomescreen/widgets/SideBar.qml b/share/qtcreator/welcomescreen/widgets/SideBar.qml
index 8c1931099c..9c92901f09 100644
--- a/share/qtcreator/welcomescreen/widgets/SideBar.qml
+++ b/share/qtcreator/welcomescreen/widgets/SideBar.qml
@@ -48,10 +48,24 @@ ColumnLayout {
Layout.preferredWidth: tabs.width + 16 * 2
Layout.preferredHeight: tabs.height + screenDependHeightDistance * 2
- Image {
- fillMode: Image.Tile
- source: "images/background.png"
+ Component {
+ id: imageBackground
+ Image {
+ fillMode: Image.Tile
+ source: "images/background.png"
+ anchors.fill: parent
+ }
+ }
+ Component {
+ id: flatBackground
+ Rectangle {
+ color: creatorTheme.sideBar_BackgroundColor
+ }
+ }
+ Loader {
+ id: topLeftLoader
anchors.fill: parent
+ sourceComponent: creatorTheme.widgetStyle === 'flat' ? flatBackground : imageBackground;
}
Tabs {
@@ -64,7 +78,7 @@ ColumnLayout {
}
Rectangle {
- color: "#737373"
+ color: creatorTheme.widgetStyle === 'flat' ? creatorTheme.sideBar_BackgroundColor : creatorTheme.dividerColor
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
@@ -73,7 +87,7 @@ ColumnLayout {
}
Rectangle {
- color: "#737373"
+ color: creatorTheme.widgetStyle === 'flat' ? creatorTheme.sideBar_BackgroundColor : creatorTheme.dividerColor
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
@@ -83,7 +97,7 @@ ColumnLayout {
}
Rectangle {
- color: "#737373"
+ color: creatorTheme.widgetStyle === 'flat' ? creatorTheme.sideBar_BackgroundColor : creatorTheme.dividerColor
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
@@ -94,7 +108,7 @@ ColumnLayout {
}
Rectangle {
- color: "#ebebeb"
+ color: creatorTheme.sideBar_BackgroundColor
Layout.fillWidth: true
Layout.preferredWidth: innerColumn.width + 20
@@ -115,6 +129,7 @@ ColumnLayout {
NativeText {
text: qsTr("New to Qt?")
+ color: creatorTheme.textColorNormal
font.pixelSize: 18
}
@@ -124,6 +139,7 @@ ColumnLayout {
Layout.preferredWidth: innerColumn.width
text: qsTr("Learn how to develop your own applications and explore Qt Creator.")
+ color: creatorTheme.textColorNormal
font.pixelSize: 12
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
}
diff --git a/share/share.qbs b/share/share.qbs
index f048f5d98d..354844a62d 100644
--- a/share/share.qbs
+++ b/share/share.qbs
@@ -21,6 +21,7 @@ Product {
"snippets",
"styles",
"templates",
+ "themes",
"welcomescreen"
]
}
diff --git a/src/libs/utils/detailsbutton.cpp b/src/libs/utils/detailsbutton.cpp
index cfbfc1044f..3e36c12cb4 100644
--- a/src/libs/utils/detailsbutton.cpp
+++ b/src/libs/utils/detailsbutton.cpp
@@ -29,8 +29,8 @@
****************************************************************************/
#include "detailsbutton.h"
-
-#include <utils/hostosinfo.h>
+#include "hostosinfo.h"
+#include "theme/theme.h"
#include <QGraphicsOpacityEffect>
#include <QGuiApplication>
@@ -122,8 +122,15 @@ void DetailsButton::paintEvent(QPaintEvent *e)
QPainter p(this);
// draw hover animation
- if (!HostOsInfo::isMacHost() && !isDown() && m_fader > 0)
- p.fillRect(rect().adjusted(1, 1, -2, -2), QColor(255, 255, 255, int(m_fader*180)));
+ if (!HostOsInfo::isMacHost() && !isDown() && m_fader > 0) {
+ QColor c = creatorTheme()->color(Theme::DetailsButtonBackgroundColorHover);
+ c.setAlpha (int(m_fader * c.alpha()));
+
+ QRect r = rect();
+ if (creatorTheme()->widgetStyle() == Theme::StyleDefault)
+ r.adjust(1, 1, -2, -2);
+ p.fillRect(r, c);
+ }
if (isChecked()) {
if (m_checkedPixmap.isNull() || m_checkedPixmap.size() / m_checkedPixmap.devicePixelRatio() != contentsRect().size())
@@ -148,10 +155,6 @@ void DetailsButton::paintEvent(QPaintEvent *e)
QPixmap DetailsButton::cacheRendering(const QSize &size, bool checked)
{
- QLinearGradient lg;
- lg.setCoordinateMode(QGradient::ObjectBoundingMode);
- lg.setFinalStop(0, 1);
-
const qreal pixelRatio = devicePixelRatio();
QPixmap pixmap(size * pixelRatio);
pixmap.setDevicePixelRatio(pixelRatio);
@@ -159,23 +162,30 @@ QPixmap DetailsButton::cacheRendering(const QSize &size, bool checked)
QPainter p(&pixmap);
p.setRenderHint(QPainter::Antialiasing, true);
p.translate(0.5, 0.5);
- p.setPen(Qt::NoPen);
- if (!checked) {
- lg.setColorAt(0, QColor(0, 0, 0, 10));
- lg.setColorAt(1, QColor(0, 0, 0, 16));
+
+ if (creatorTheme()->widgetStyle() == Theme::StyleDefault) {
+ QLinearGradient lg;
+ lg.setCoordinateMode(QGradient::ObjectBoundingMode);
+ lg.setFinalStop(0, 1);
+ if (!checked) {
+ lg.setColorAt(0, QColor(0, 0, 0, 10));
+ lg.setColorAt(1, QColor(0, 0, 0, 16));
+ } else {
+ lg.setColorAt(0, QColor(255, 255, 255, 0));
+ lg.setColorAt(1, QColor(255, 255, 255, 50));
+ }
+ p.setBrush(lg);
+ p.setPen(QColor(255,255,255,140));
+ p.drawRoundedRect(1, 1, size.width()-3, size.height()-3, 1, 1);
+ p.setPen(QPen(QColor(0, 0, 0, 40)));
+ p.drawLine(0, 1, 0, size.height() - 2);
+ if (checked)
+ p.drawLine(1, size.height() - 1, size.width() - 1, size.height() - 1);
} else {
- lg.setColorAt(0, QColor(255, 255, 255, 0));
- lg.setColorAt(1, QColor(255, 255, 255, 50));
+ p.setPen(Qt::NoPen);
+ p.drawRoundedRect(0, 0, size.width(), size.height(), 1, 1);
}
- p.setBrush(lg);
- p.setPen(QColor(255,255,255,140));
- p.drawRoundedRect(1, 1, size.width()-3, size.height()-3, 1, 1);
- p.setPen(QPen(QColor(0, 0, 0, 40)));
- p.drawLine(0, 1, 0, size.height() - 2);
- if (checked)
- p.drawLine(1, size.height() - 1, size.width() - 1, size.height() - 1);
-
p.setPen(palette().color(QPalette::Text));
QRect textRect = p.fontMetrics().boundingRect(text());
diff --git a/src/libs/utils/detailswidget.cpp b/src/libs/utils/detailswidget.cpp
index 68320d76c5..5218916cf7 100644
--- a/src/libs/utils/detailswidget.cpp
+++ b/src/libs/utils/detailswidget.cpp
@@ -31,6 +31,7 @@
#include "detailswidget.h"
#include "detailsbutton.h"
#include "hostosinfo.h"
+#include "theme/theme.h"
#include <QGridLayout>
#include <QLabel>
@@ -148,21 +149,22 @@ QPixmap DetailsWidget::createBackground(const QSize &size, int topHeight, QWidge
if (HostOsInfo::isMacHost())
p.fillRect(fullRect, qApp->palette().window().color());
else
- p.fillRect(fullRect, QColor(255, 255, 255, 40));
-
- QLinearGradient lg(topRect.topLeft(), topRect.bottomLeft());
- lg.setColorAt(0, QColor(255, 255, 255, 130));
- lg.setColorAt(1, QColor(255, 255, 255, 0));
- p.fillRect(topRect, lg);
- p.setRenderHint(QPainter::Antialiasing, true);
- p.translate(0.5, 0.5);
- p.setPen(QColor(0, 0, 0, 40));
- p.setBrush(Qt::NoBrush);
- p.drawRoundedRect(fullRect.adjusted(0, 0, -1, -1), 2, 2);
- p.setBrush(Qt::NoBrush);
- p.setPen(QColor(255,255,255,140));
- p.drawRoundedRect(fullRect.adjusted(1, 1, -2, -2), 2, 2);
- p.setPen(QPen(widget->palette().color(QPalette::Mid)));
+ p.fillRect(fullRect, creatorTheme()->color(Theme::DetailsWidgetBackgroundColor));
+
+ if (creatorTheme()->widgetStyle () == Theme::StyleDefault) {
+ QLinearGradient lg(topRect.topLeft(), topRect.bottomLeft());
+ lg.setStops(creatorTheme()->gradient(Theme::DetailsWidgetHeaderGradient));
+ p.fillRect(topRect, lg);
+ p.setRenderHint(QPainter::Antialiasing, true);
+ p.translate(0.5, 0.5);
+ p.setPen(QColor(0, 0, 0, 40));
+ p.setBrush(Qt::NoBrush);
+ p.drawRoundedRect(fullRect.adjusted(0, 0, -1, -1), 2, 2);
+ p.setBrush(Qt::NoBrush);
+ p.setPen(QColor(255,255,255,140));
+ p.drawRoundedRect(fullRect.adjusted(1, 1, -2, -2), 2, 2);
+ p.setPen(QPen(widget->palette().color(QPalette::Mid)));
+ }
return pixmap;
}
diff --git a/src/libs/utils/outputformatter.cpp b/src/libs/utils/outputformatter.cpp
index 5d952d2ed9..ca745e3f8a 100644
--- a/src/libs/utils/outputformatter.cpp
+++ b/src/libs/utils/outputformatter.cpp
@@ -28,10 +28,11 @@
**
****************************************************************************/
+#include "ansiescapecodehandler.h"
#include "outputformatter.h"
+#include "theme/theme.h"
#include <QPlainTextEdit>
-#include <utils/ansiescapecodehandler.h>
using namespace Utils;
@@ -110,12 +111,6 @@ void OutputFormatter::clearLastLine()
cursor.removeSelectedText();
}
-QColor OutputFormatter::mixColors(const QColor &a, const QColor &b)
-{
- return QColor((a.red() + 2 * b.red()) / 3, (a.green() + 2 * b.green()) / 3,
- (a.blue() + 2* b.blue()) / 3, (a.alpha() + 2 * b.alpha()) / 3);
-}
-
void OutputFormatter::initFormats()
{
if (!plainTextEdit())
@@ -127,26 +122,28 @@ void OutputFormatter::initFormats()
m_formats = new QTextCharFormat[NumberOfFormats];
+ Theme *theme = creatorTheme();
+
// NormalMessageFormat
m_formats[NormalMessageFormat].setFont(boldFont);
- m_formats[NormalMessageFormat].setForeground(mixColors(p.color(QPalette::Text), QColor(Qt::blue)));
+ m_formats[NormalMessageFormat].setForeground(theme->color(Theme::OutputFormatter_NormalMessageTextColor));
// ErrorMessageFormat
m_formats[ErrorMessageFormat].setFont(boldFont);
- m_formats[ErrorMessageFormat].setForeground(mixColors(p.color(QPalette::Text), QColor(Qt::red)));
+ m_formats[ErrorMessageFormat].setForeground(theme->color(Theme::OutputFormatter_ErrorMessageTextColor));
// StdOutFormat
m_formats[StdOutFormat].setFont(m_font);
- m_formats[StdOutFormat].setForeground(p.color(QPalette::Text));
+ m_formats[StdOutFormat].setForeground(theme->color(Theme::OutputFormatter_StdOutTextColor));
m_formats[StdOutFormatSameLine] = m_formats[StdOutFormat];
// StdErrFormat
m_formats[StdErrFormat].setFont(m_font);
- m_formats[StdErrFormat].setForeground(mixColors(p.color(QPalette::Text), QColor(Qt::red)));
+ m_formats[StdErrFormat].setForeground(theme->color(Theme::OutputFormatter_StdErrTextColor));
m_formats[StdErrFormatSameLine] = m_formats[StdErrFormat];
m_formats[DebugFormat].setFont(m_font);
- m_formats[DebugFormat].setForeground(mixColors(p.color(QPalette::Text), QColor(Qt::magenta)));
+ m_formats[DebugFormat].setForeground(theme->color(Theme::OutputFormatter_DebugTextColor));
}
void OutputFormatter::handleLink(const QString &href)
diff --git a/src/libs/utils/outputformatter.h b/src/libs/utils/outputformatter.h
index 2f29a195bf..6dba8e5f10 100644
--- a/src/libs/utils/outputformatter.h
+++ b/src/libs/utils/outputformatter.h
@@ -73,8 +73,6 @@ protected:
QTextCharFormat charFormat(OutputFormat format) const;
void append(QTextCursor &cursor, const QString &text, const QTextCharFormat &format);
- static QColor mixColors(const QColor &a, const QColor &b);
-
private:
QPlainTextEdit *m_plainTextEdit;
QTextCharFormat *m_formats;
diff --git a/src/libs/utils/theme/theme.cpp b/src/libs/utils/theme/theme.cpp
new file mode 100644
index 0000000000..97d1627115
--- /dev/null
+++ b/src/libs/utils/theme/theme.cpp
@@ -0,0 +1,356 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "theme.h"
+#include "theme_p.h"
+#include "qtcassert.h"
+
+#include <QApplication>
+#include <QFileInfo>
+#include <QMetaEnum>
+#include <QSettings>
+
+namespace Utils {
+
+static Theme *m_creatorTheme = 0;
+
+Theme *creatorTheme()
+{
+ return m_creatorTheme;
+}
+
+void setCreatorTheme(Theme *theme)
+{
+ // TODO: memory management of theme object
+ m_creatorTheme = theme;
+}
+
+Theme::Theme(QObject *parent)
+ : QObject(parent)
+ , d(new ThemePrivate)
+{
+}
+
+Theme::~Theme()
+{
+ delete d;
+}
+
+void Theme::drawIndicatorBranch(QPainter *painter, const QRect &rect, QStyle::State state) const
+{
+ Q_UNUSED(painter);
+ Q_UNUSED(rect);
+ Q_UNUSED(state);
+}
+
+Theme::WidgetStyle Theme::widgetStyle() const
+{
+ return d->widgetStyle;
+}
+
+bool Theme::flag(Theme::Flag f) const
+{
+ return d->flags[f];
+}
+
+QColor Theme::color(Theme::ColorRole role) const
+{
+ return d->colors[role].first;
+}
+
+QGradientStops Theme::gradient(Theme::GradientRole role) const
+{
+ return d->gradientStops[role];
+}
+
+QString Theme::iconOverlay(Theme::MimeType mimetype) const
+{
+ return d->iconOverlays[mimetype];
+}
+
+QString Theme::dpiSpecificImageFile(const QString &fileName) const
+{
+ return dpiSpecificImageFile(fileName, QLatin1String(""));
+}
+
+QString Theme::dpiSpecificImageFile(const QString &fileName, const QString &themePrefix) const
+{
+ // See QIcon::addFile()
+ const QFileInfo fi(fileName);
+
+ bool at2x = (qApp->devicePixelRatio() > 1.0);
+
+ const QString at2xFileName = fi.path() + QStringLiteral("/")
+ + fi.completeBaseName() + QStringLiteral("@2x.") + fi.suffix();
+ const QString themedAt2xFileName = fi.path() + QStringLiteral("/") + themePrefix
+ + fi.completeBaseName() + QStringLiteral("@2x.") + fi.suffix();
+ const QString themedFileName = fi.path() + QStringLiteral("/") + themePrefix
+ + fi.completeBaseName() + QStringLiteral(".") + fi.suffix();
+
+ if (at2x) {
+ if (QFile::exists(themedAt2xFileName))
+ return themedAt2xFileName;
+ else if (QFile::exists(themedFileName))
+ return themedFileName;
+ else if (QFile::exists(at2xFileName))
+ return at2xFileName;
+ return fileName;
+ } else {
+ if (QFile::exists(themedFileName))
+ return themedFileName;
+ return fileName;
+ }
+}
+
+QPair<QColor, QString> Theme::readNamedColor(const QString &color) const
+{
+ if (d->palette.contains(color))
+ return qMakePair(d->palette[color], color);
+
+ bool ok = true;
+ const QRgb rgba = color.toLongLong(&ok, 16);
+ if (!ok) {
+ qWarning("Color '%s' is neither a named color nor a valid color", qPrintable(color));
+ return qMakePair(Qt::black, QString());
+ }
+ return qMakePair(QColor::fromRgba(rgba), QString());
+}
+
+QString Theme::imageFile(const QString &fileName) const
+{
+ return fileName;
+}
+
+QString Theme::fileName() const
+{
+ return d->fileName;
+}
+
+void Theme::setName(const QString &name)
+{
+ d->name = name;
+}
+
+static QColor readColor(const QString &color)
+{
+ bool ok = true;
+ const QRgb rgba = color.toLongLong(&ok, 16);
+ return QColor::fromRgba(rgba);
+}
+
+static QString writeColor(const QColor &color)
+{
+ return QString::number(color.rgba(), 16);
+}
+
+// reading, writing of .creatortheme ini file ////////////////////////////////
+void Theme::writeSettings(const QString &filename) const
+{
+ QSettings settings(filename, QSettings::IniFormat);
+
+ const QMetaObject &m = *metaObject();
+ {
+ settings.setValue(QLatin1String("ThemeName"), d->name);
+ }
+ {
+ settings.beginGroup(QLatin1String("Palette"));
+ for (int i = 0, total = d->colors.size(); i < total; ++i) {
+ const QPair<QColor, QString> var = d->colors[i];
+ if (var.second.isEmpty())
+ continue;
+ settings.setValue(var.second, writeColor(var.first));
+ }
+ settings.endGroup();
+ }
+ {
+ settings.beginGroup(QLatin1String("Colors"));
+ const QMetaEnum e = m.enumerator(m.indexOfEnumerator("ColorRole"));
+ for (int i = 0, total = e.keyCount(); i < total; ++i) {
+ const QString key = QLatin1String(e.key(i));
+ const QPair<QColor, QString> var = d->colors[i];
+ if (!var.second.isEmpty())
+ settings.setValue(key, var.second); // named color
+ else
+ settings.setValue(key, writeColor(var.first));
+ }
+ settings.endGroup();
+ }
+ {
+ settings.beginGroup(QLatin1String("Gradients"));
+ const QMetaEnum e = m.enumerator(m.indexOfEnumerator("GradientRole"));
+ for (int i = 0, total = e.keyCount(); i < total; ++i) {
+ const QString key = QLatin1String(e.key(i));
+ QGradientStops stops = gradient(static_cast<Theme::GradientRole>(i));
+ settings.beginWriteArray(key);
+ int k = 0;
+ foreach (const QGradientStop stop, stops) {
+ settings.setArrayIndex(k);
+ settings.setValue(QLatin1String("pos"), stop.first);
+ settings.setValue(QLatin1String("color"), writeColor(stop.second));
+ ++k;
+ }
+ settings.endArray();
+ }
+ settings.endGroup();
+ }
+ {
+ settings.beginGroup(QLatin1String("IconOverlay"));
+ const QMetaEnum e = m.enumerator(m.indexOfEnumerator("MimeType"));
+ for (int i = 0, total = e.keyCount(); i < total; ++i) {
+ const QString key = QLatin1String(e.key(i));
+ settings.setValue(key, iconOverlay(static_cast<Theme::MimeType>(i)));
+ }
+ settings.endGroup();
+ }
+ {
+ settings.beginGroup(QLatin1String("Flags"));
+ const QMetaEnum e = m.enumerator(m.indexOfEnumerator("Flag"));
+ for (int i = 0, total = e.keyCount(); i < total; ++i) {
+ const QString key = QLatin1String(e.key(i));
+ settings.setValue(key, flag(static_cast<Theme::Flag>(i)));
+ }
+ settings.endGroup();
+ }
+
+ {
+ settings.beginGroup(QLatin1String("Style"));
+ const QMetaEnum e = m.enumerator(m.indexOfEnumerator("WidgetStyle"));
+ settings.setValue(QLatin1String("WidgetStyle"), QLatin1String(e.valueToKey(widgetStyle ())));
+ settings.endGroup();
+ }
+}
+
+void Theme::readSettings(QSettings &settings)
+{
+ d->fileName = settings.fileName();
+ const QMetaObject &m = *metaObject();
+
+ {
+ d->name = settings.value(QLatin1String("ThemeName"), QLatin1String("unnamed")).toString();
+ }
+ {
+ settings.beginGroup(QLatin1String("Palette"));
+ foreach (const QString &key, settings.allKeys()) {
+ QColor c = readColor(settings.value(key).toString());
+ d->palette[key] = c;
+ }
+ settings.endGroup();
+ }
+ {
+ settings.beginGroup(QLatin1String("Style"));
+ QMetaEnum e = m.enumerator(m.indexOfEnumerator("WidgetStyle"));
+ QString val = settings.value(QLatin1String("WidgetStyle")).toString();
+ d->widgetStyle = static_cast<Theme::WidgetStyle>(e.keysToValue (val.toLatin1().data()));
+ settings.endGroup();
+ }
+ {
+ settings.beginGroup(QLatin1String("Colors"));
+ QMetaEnum e = m.enumerator(m.indexOfEnumerator("ColorRole"));
+ for (int i = 0, total = e.keyCount(); i < total; ++i) {
+ const QString key = QLatin1String(e.key(i));
+ QTC_ASSERT(settings.contains(key), return);;
+ d->colors[i] = readNamedColor(settings.value(key).toString());
+ }
+ settings.endGroup();
+ }
+ {
+ settings.beginGroup(QLatin1String("Gradients"));
+ QMetaEnum e = m.enumerator(m.indexOfEnumerator("GradientRole"));
+ for (int i = 0, total = e.keyCount(); i < total; ++i) {
+ const QString key = QLatin1String(e.key(i));
+ QGradientStops stops;
+ int size = settings.beginReadArray(key);
+ for (int j = 0; j < size; ++j) {
+ settings.setArrayIndex(j);
+ QTC_ASSERT(settings.contains(QLatin1String("pos")), return);;
+ double pos = settings.value(QLatin1String("pos")).toDouble();
+ QTC_ASSERT(settings.contains(QLatin1String("color")), return);;
+ QColor c = readColor(settings.value(QLatin1String("color")).toString());
+ stops.append(qMakePair(pos, c));
+ }
+ settings.endArray();
+ d->gradientStops[i] = stops;
+ }
+ settings.endGroup();
+ }
+ {
+ settings.beginGroup(QLatin1String("IconOverlay"));
+ QMetaEnum e = m.enumerator(m.indexOfEnumerator("MimeType"));
+ for (int i = 0, total = e.keyCount(); i < total; ++i) {
+ const QString key = QLatin1String(e.key(i));
+ QTC_ASSERT(settings.contains(key), return);;
+ d->iconOverlays[i] = settings.value(key).toString();
+ }
+ settings.endGroup();
+ }
+ {
+ settings.beginGroup(QLatin1String("Flags"));
+ QMetaEnum e = m.enumerator(m.indexOfEnumerator("Flag"));
+ for (int i = 0, total = e.keyCount(); i < total; ++i) {
+ const QString key = QLatin1String(e.key(i));
+ QTC_ASSERT(settings.contains(key), return);;
+ d->flags[i] = settings.value(key).toBool();
+ }
+ settings.endGroup();
+ }
+}
+
+QIcon Theme::standardIcon(QStyle::StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget) const
+{
+ Q_UNUSED(standardPixmap);
+ Q_UNUSED(opt);
+ Q_UNUSED(widget);
+ return QIcon();
+}
+
+QPalette Theme::palette(const QPalette &base) const
+{
+ if (!flag(DerivePaletteFromTheme))
+ return base;
+
+ // FIXME: introduce some more color roles for this
+
+ QPalette pal = base;
+ pal.setColor(QPalette::All, QPalette::Window, color(Theme::BackgroundColorNormal));
+ pal.setBrush(QPalette::All, QPalette::WindowText, color(Theme::TextColorNormal));
+ pal.setColor(QPalette::All, QPalette::Base, color(Theme::BackgroundColorNormal));
+ pal.setColor(QPalette::All, QPalette::AlternateBase, color(Theme::BackgroundColorAlternate));
+ pal.setColor(QPalette::All, QPalette::Button, color(Theme::BackgroundColorDark));
+ pal.setColor(QPalette::All, QPalette::BrightText, Qt::red);
+ pal.setBrush(QPalette::All, QPalette::Text, color(Theme::TextColorNormal));
+ pal.setBrush(QPalette::All, QPalette::ButtonText, color(Theme::TextColorNormal));
+ pal.setBrush(QPalette::All, QPalette::ToolTipBase, color(Theme::BackgroundColorSelected));
+ pal.setColor(QPalette::Highlight, color(Theme::BackgroundColorSelected));
+ pal.setColor(QPalette::HighlightedText, Qt::white);
+ pal.setColor(QPalette::ToolTipText, color(Theme::TextColorNormal));
+ return pal;
+}
+
+} // namespace Utils
diff --git a/src/libs/utils/theme/theme.h b/src/libs/utils/theme/theme.h
new file mode 100644
index 0000000000..4a55bdc409
--- /dev/null
+++ b/src/libs/utils/theme/theme.h
@@ -0,0 +1,217 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef THEME_H
+#define THEME_H
+
+#include "../utils_global.h"
+
+#include <QStyle>
+#include <QFlags>
+
+QT_FORWARD_DECLARE_CLASS(QSettings)
+
+namespace Utils {
+
+class ThemePrivate;
+
+class QTCREATOR_UTILS_EXPORT Theme : public QObject
+{
+ Q_OBJECT
+
+ Q_ENUMS(ColorRole)
+ Q_ENUMS(GradientRole)
+ Q_ENUMS(MimeType)
+ Q_ENUMS(Flag)
+ Q_ENUMS(WidgetStyle)
+
+public:
+ Theme(QObject *parent = 0);
+ ~Theme();
+
+ enum ColorRole {
+ BackgroundColorAlternate,
+ BackgroundColorDark,
+ BackgroundColorHover,
+ BackgroundColorNormal,
+ BackgroundColorSelected,
+ BadgeLabelBackgroundColorChecked,
+ BadgeLabelBackgroundColorUnchecked,
+ BadgeLabelTextColorChecked,
+ BadgeLabelTextColorUnchecked,
+ CanceledSearchTextColor,
+ ComboBoxArrowColor,
+ ComboBoxArrowColorDisabled,
+ ComboBoxTextColor,
+ DetailsWidgetBackgroundColor,
+ DetailsButtonBackgroundColorHover,
+ DockWidgetResizeHandleColor,
+ DoubleTabWidget1stEmptyAreaBackgroundColor,
+ DoubleTabWidget1stSeparatorColor,
+ DoubleTabWidget2ndSeparatorColor,
+ DoubleTabWidget1stTabBackgroundColor,
+ DoubleTabWidget2ndTabBackgroundColor,
+ DoubleTabWidget1stTabActiveTextColor,
+ DoubleTabWidget1stTabInactiveTextColor,
+ DoubleTabWidget2ndTabActiveTextColor,
+ DoubleTabWidget2ndTabInactiveTextColor,
+ EditorPlaceholderColor,
+ FancyTabBarBackgroundColor,
+ FancyTabWidgetEnabledSelectedTextColor,
+ FancyTabWidgetEnabledUnselectedTextColor,
+ FancyTabWidgetDisabledSelectedTextColor,
+ FancyTabWidgetDisabledUnselectedTextColor,
+ FancyToolButtonHoverColor,
+ FancyToolButtonSelectedColor,
+ FutureProgressBackgroundColor,
+ MenuBarEmptyAreaBackgroundColor,
+ MenuBarItemBackgroundColor,
+ MenuBarItemTextColorDisabled,
+ MenuBarItemTextColorNormal,
+ MiniProjectTargetSelectorBackgroundColor,
+ MiniProjectTargetSelectorBorderColor,
+ MiniProjectTargetSelectorSummaryBackgroundColor,
+ MiniProjectTargetSelectorTextColor,
+ OutputPaneButtonFlashColor,
+ OutputPaneToggleButtonTextColorChecked,
+ OutputPaneToggleButtonTextColorUnchecked,
+ PanelButtonToolBackgroundColorHover,
+ PanelTextColor,
+ PanelsWidgetSeparatorLineColor,
+ PanelStatusBarBackgroundColor,
+ ProgressBarTitleColor,
+ ProgressBarColorError,
+ ProgressBarColorFinished,
+ ProgressBarColorNormal,
+ SearchResultWidgetBackgroundColor,
+ SearchResultWidgetTextColor,
+ TextColorDisabled,
+ TextColorHighlight,
+ TextColorNormal,
+ TodoItemTextColor,
+ ToggleButtonBackgroundColor,
+ ToolBarBackgroundColor,
+ TreeViewArrowColorNormal,
+ TreeViewArrowColorSelected,
+
+ OutputFormatter_NormalMessageTextColor,
+ OutputFormatter_ErrorMessageTextColor,
+ OutputFormatter_StdOutTextColor,
+ OutputFormatter_StdErrTextColor,
+ OutputFormatter_DebugTextColor,
+
+ QtOutputFormatter_LinkTextColor,
+
+ /* Welcome Plugin */
+
+ Welcome_TextColorNormal,
+ Welcome_TextColorHeading, // #535353 // Sessions, Recent Projects
+ Welcome_BackgroundColorNormal, // #ffffff
+ Welcome_DividerColor, // #737373
+ Welcome_Button_BorderColor,
+ Welcome_Button_TextColorNormal,
+ Welcome_Button_TextColorPressed,
+ Welcome_Link_TextColorNormal,
+ Welcome_Link_TextColorActive,
+ Welcome_Link_BackgroundColor,
+ Welcome_Caption_TextColorNormal,
+ Welcome_SideBar_BackgroundColor,
+
+ Welcome_ProjectItem_TextColorFilepath,
+ Welcome_ProjectItem_BackgroundColorHover,
+
+ Welcome_SessionItem_BackgroundColorNormal,
+ Welcome_SessionItem_BackgroundColorHover,
+ Welcome_SessionItemExpanded_BackgroundColor
+ };
+
+ enum GradientRole {
+ DetailsWidgetHeaderGradient,
+ Welcome_Button_GradientNormal,
+ Welcome_Button_GradientPressed
+ };
+
+ enum MimeType {
+ CppSourceMimetype,
+ CSourceMimetype,
+ CppHeaderMimetype,
+ ProMimetype,
+ PriMimetype,
+ PrfMimetype
+ };
+
+ enum Flag {
+ DrawTargetSelectorBottom,
+ DrawSearchResultWidgetFrame,
+ DrawProgressBarSunken,
+ DrawIndicatorBranch,
+ ComboBoxDrawTextShadow,
+ DerivePaletteFromTheme
+ };
+
+ enum WidgetStyle {
+ StyleDefault,
+ StyleFlat
+ };
+
+ WidgetStyle widgetStyle() const;
+ bool flag(Flag f) const;
+ QColor color(ColorRole role) const;
+ QGradientStops gradient(GradientRole role) const;
+ QString iconOverlay(MimeType mimetype) const;
+ QPalette palette(const QPalette &base) const;
+ QString dpiSpecificImageFile(const QString &fileName) const;
+ void drawIndicatorBranch(QPainter *painter, const QRect &rect, QStyle::State state) const;
+ QIcon standardIcon(QStyle::StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget) const;
+ QString imageFile(const QString &fileName) const;
+
+ QString fileName() const;
+ void setName(const QString &name);
+
+ void writeSettings(const QString &filename) const;
+ void readSettings(QSettings &settings);
+ ThemePrivate *d;
+
+signals:
+ void changed();
+
+protected:
+ QString dpiSpecificImageFile(const QString &fileName, const QString &themePrefix) const;
+
+private:
+ QPair<QColor, QString> readNamedColor(const QString &color) const;
+};
+
+QTCREATOR_UTILS_EXPORT Theme *creatorTheme();
+QTCREATOR_UTILS_EXPORT void setCreatorTheme(Theme *theme);
+
+} // namespace Utils
+
+#endif // THEME_H
diff --git a/src/libs/utils/theme/theme_p.cpp b/src/libs/utils/theme/theme_p.cpp
new file mode 100644
index 0000000000..05c7916722
--- /dev/null
+++ b/src/libs/utils/theme/theme_p.cpp
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "theme_p.h"
+
+#include <QMetaEnum>
+
+namespace Utils {
+
+ThemePrivate::ThemePrivate()
+ : widgetStyle(Theme::StyleDefault)
+{
+ const QMetaObject &m = Theme::staticMetaObject;
+ colors.resize (m.enumerator(m.indexOfEnumerator("ColorRole")).keyCount());
+ gradientStops.resize (m.enumerator(m.indexOfEnumerator("GradientRole")).keyCount());
+ iconOverlays.resize (m.enumerator(m.indexOfEnumerator("MimeType")).keyCount());
+ flags.resize (m.enumerator(m.indexOfEnumerator("Flag")).keyCount());
+}
+
+} // namespace Utils
diff --git a/src/libs/utils/theme/theme_p.h b/src/libs/utils/theme/theme_p.h
new file mode 100644
index 0000000000..d507becafc
--- /dev/null
+++ b/src/libs/utils/theme/theme_p.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef THEME_P_H
+#define THEME_P_H
+
+#include "theme.h"
+#include "../utils_global.h"
+
+#include <QColor>
+#include <QMap>
+
+namespace Utils {
+
+class QTCREATOR_UTILS_EXPORT ThemePrivate
+{
+public:
+ ThemePrivate();
+
+ QString fileName;
+ QString name;
+ QVector<QPair<QColor, QString> > colors;
+ QVector<QString> iconOverlays;
+ QVector<QGradientStops> gradientStops;
+ QVector<bool> flags;
+ Theme::WidgetStyle widgetStyle;
+ QMap<QString, QColor> palette;
+};
+
+} // namespace Utils
+
+#endif // THEME_P_H
diff --git a/src/libs/utils/theme/welcometheme.cpp b/src/libs/utils/theme/welcometheme.cpp
new file mode 100644
index 0000000000..e8581a7d7d
--- /dev/null
+++ b/src/libs/utils/theme/welcometheme.cpp
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "welcometheme.h"
+
+#include "theme.h"
+
+using namespace Utils;
+
+#define IMPL_COLOR_PROPERTY(propName, enumName) \
+ QColor WelcomeTheme::propName () const { \
+ return creatorTheme()->color(Theme::enumName); \
+ }
+
+#define GRADIENT(x) \
+ QGradient grad; \
+ grad.setStops(creatorTheme()->gradient(Theme::x)); \
+ return grad;
+
+WelcomeTheme::WelcomeTheme(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QString WelcomeTheme::widgetStyle() const
+{
+ switch (creatorTheme()->widgetStyle()) {
+ case Theme::StyleDefault:
+ return QLatin1String("default");
+ case Theme::StyleFlat:
+ return QLatin1String("flat");
+ }
+ return QString::null;
+}
+
+void WelcomeTheme::notifyThemeChanged()
+{
+ emit themeChanged();
+}
+
+IMPL_COLOR_PROPERTY(textColorNormal , Welcome_TextColorNormal )
+IMPL_COLOR_PROPERTY(textColorHeading , Welcome_TextColorHeading )
+IMPL_COLOR_PROPERTY(backgroundColorNormal , Welcome_BackgroundColorNormal )
+IMPL_COLOR_PROPERTY(dividerColor , Welcome_DividerColor )
+IMPL_COLOR_PROPERTY(button_BorderColor , Welcome_Button_BorderColor )
+IMPL_COLOR_PROPERTY(button_TextColorNormal , Welcome_Button_TextColorNormal )
+IMPL_COLOR_PROPERTY(button_TextColorPressed, Welcome_Button_TextColorPressed)
+IMPL_COLOR_PROPERTY(link_TextColorNormal , Welcome_Link_TextColorNormal )
+IMPL_COLOR_PROPERTY(link_TextColorActive , Welcome_Link_TextColorActive )
+IMPL_COLOR_PROPERTY(link_BackgroundColor , Welcome_Link_BackgroundColor )
+IMPL_COLOR_PROPERTY(caption_TextColorNormal, Welcome_Caption_TextColorNormal)
+IMPL_COLOR_PROPERTY(sideBar_BackgroundColor, Welcome_SideBar_BackgroundColor)
+IMPL_COLOR_PROPERTY(projectItem_TextColorFilepath, Welcome_ProjectItem_TextColorFilepath)
+IMPL_COLOR_PROPERTY(projectItem_BackgroundColorHover, Welcome_ProjectItem_BackgroundColorHover)
+IMPL_COLOR_PROPERTY(sessionItem_BackgroundColorNormal, Welcome_SessionItem_BackgroundColorNormal)
+IMPL_COLOR_PROPERTY(sessionItemExpanded_BackgroundColor, Welcome_SessionItemExpanded_BackgroundColor)
+IMPL_COLOR_PROPERTY(sessionItem_BackgroundColorHover, Welcome_SessionItem_BackgroundColorHover)
+
+QGradient WelcomeTheme::button_GradientNormal () const { GRADIENT(Welcome_Button_GradientNormal); }
+QGradient WelcomeTheme::button_GradientPressed () const { GRADIENT(Welcome_Button_GradientPressed); }
diff --git a/src/libs/utils/theme/welcometheme.h b/src/libs/utils/theme/welcometheme.h
new file mode 100644
index 0000000000..ec9f36c844
--- /dev/null
+++ b/src/libs/utils/theme/welcometheme.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef WELCOMETHEME_H
+#define WELCOMETHEME_H
+
+#include "../utils_global.h"
+
+#include <QStyle>
+
+#define DECLARE_COLOR_PROPERTY(propName) \
+ Q_PROPERTY(QColor propName READ propName NOTIFY themeChanged) \
+ QColor propName () const;
+
+/*!
+ * Expose theme properties to QML (for welcomeplugin)
+ */
+class QTCREATOR_UTILS_EXPORT WelcomeTheme : public QObject
+{
+ Q_OBJECT
+
+public:
+ WelcomeTheme(QObject *parent);
+
+ DECLARE_COLOR_PROPERTY(textColorNormal)
+ DECLARE_COLOR_PROPERTY(textColorHeading)
+ DECLARE_COLOR_PROPERTY(backgroundColorNormal)
+ DECLARE_COLOR_PROPERTY(dividerColor)
+ DECLARE_COLOR_PROPERTY(button_BorderColor)
+ DECLARE_COLOR_PROPERTY(button_TextColorNormal)
+ DECLARE_COLOR_PROPERTY(button_TextColorPressed)
+ DECLARE_COLOR_PROPERTY(link_TextColorNormal)
+ DECLARE_COLOR_PROPERTY(link_TextColorActive)
+ DECLARE_COLOR_PROPERTY(link_BackgroundColor)
+ DECLARE_COLOR_PROPERTY(sideBar_BackgroundColor)
+ DECLARE_COLOR_PROPERTY(caption_TextColorNormal)
+ DECLARE_COLOR_PROPERTY(projectItem_TextColorFilepath)
+ DECLARE_COLOR_PROPERTY(projectItem_BackgroundColorHover)
+ DECLARE_COLOR_PROPERTY(sessionItem_BackgroundColorNormal)
+ DECLARE_COLOR_PROPERTY(sessionItemExpanded_BackgroundColor)
+ DECLARE_COLOR_PROPERTY(sessionItem_BackgroundColorHover)
+
+ Q_PROPERTY(QGradient button_GradientNormal READ button_GradientNormal NOTIFY themeChanged)
+ Q_PROPERTY(QGradient button_GradientPressed READ button_GradientPressed NOTIFY themeChanged)
+
+ Q_PROPERTY(QString widgetStyle READ widgetStyle CONSTANT)
+
+ QString widgetStyle() const;
+
+ QGradient button_GradientNormal () const;
+ QGradient button_GradientPressed () const;
+
+public slots:
+ void notifyThemeChanged();
+
+signals:
+ void themeChanged();
+};
+
+#endif // WELCOMETHEME_H
diff --git a/src/libs/utils/utils-lib.pri b/src/libs/utils/utils-lib.pri
index 8b0257ba6e..087bcba89e 100644
--- a/src/libs/utils/utils-lib.pri
+++ b/src/libs/utils/utils-lib.pri
@@ -92,7 +92,10 @@ SOURCES += $$PWD/environment.cpp \
$$PWD/treemodel.cpp \
$$PWD/treeviewcombobox.cpp \
$$PWD/proxycredentialsdialog.cpp \
- $$PWD/macroexpander.cpp
+ $$PWD/macroexpander.cpp \
+ $$PWD/theme/theme.cpp \
+ $$PWD/theme/theme_p.cpp \
+ $$PWD/theme/welcometheme.cpp
win32:SOURCES += $$PWD/consoleprocess_win.cpp
else:SOURCES += $$PWD/consoleprocess_unix.cpp
@@ -189,7 +192,10 @@ HEADERS += \
$$PWD/algorithm.h \
$$PWD/QtConcurrentTools \
$$PWD/proxycredentialsdialog.h \
- $$PWD/macroexpander.h
+ $$PWD/macroexpander.h \
+ $$PWD/theme/theme.h \
+ $$PWD/theme/theme_p.h \
+ $$PWD/theme/welcometheme.h
FORMS += $$PWD/filewizardpage.ui \
$$PWD/projectintropage.ui \
diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs
index a665cfc3ba..a5a92af87a 100644
--- a/src/libs/utils/utils.qbs
+++ b/src/libs/utils/utils.qbs
@@ -205,6 +205,19 @@ QtcLibrary {
]
Group {
+ name: "Theme"
+ prefix: "theme/"
+ files: [
+ "theme.cpp",
+ "theme.h",
+ "theme_p.cpp",
+ "theme_p.h",
+ "welcometheme.cpp",
+ "welcometheme.h",
+ ]
+ }
+
+ Group {
name: "Tooltip"
prefix: "tooltip/"
files: [
diff --git a/src/plugins/coreplugin/Core.json.in b/src/plugins/coreplugin/Core.json.in
index 25d8507502..8e792dfa28 100644
--- a/src/plugins/coreplugin/Core.json.in
+++ b/src/plugins/coreplugin/Core.json.in
@@ -23,6 +23,11 @@
\"Description\" : \"Override selected UI color\"
},
{
+ \"Name\" : \"-theme\",
+ \"Parameter\" : \"default|dark\",
+ \"Description\" : \"Choose a built-in theme or pass a .creatortheme file\"
+ },
+ {
\"Name\" : \"-presentationMode\",
\"Description\" : \"Enable presentation mode with pop-ups for key combos\"
}
diff --git a/src/plugins/coreplugin/core.qrc b/src/plugins/coreplugin/core.qrc
index db87f15a30..35ae643470 100644
--- a/src/plugins/coreplugin/core.qrc
+++ b/src/plugins/coreplugin/core.qrc
@@ -26,6 +26,8 @@
<file>images/locked@2x.png</file>
<file>images/magnifier.png</file>
<file>images/magnifier@2x.png</file>
+ <file>images/dark_magnifier.png</file>
+ <file>images/dark_magnifier@2x.png</file>
<file>images/minus.png</file>
<file>images/next.png</file>
<file>images/panel_button.png</file>
@@ -103,5 +105,7 @@
<file>images/warning@2x.png</file>
<file>images/info.png</file>
<file>images/info@2x.png</file>
+ <file>images/dark_fileicon.png</file>
+ <file>images/dark_foldericon.png</file>
</qresource>
</RCC>
diff --git a/src/plugins/coreplugin/coreconstants.h b/src/plugins/coreplugin/coreconstants.h
index b2e716097f..d4bf58227a 100644
--- a/src/plugins/coreplugin/coreconstants.h
+++ b/src/plugins/coreplugin/coreconstants.h
@@ -101,6 +101,7 @@ const char OPTIONS[] = "QtCreator.Options";
const char TOGGLE_SIDEBAR[] = "QtCreator.ToggleSidebar";
const char TOGGLE_MODE_SELECTOR[] = "QtCreator.ToggleModeSelector";
const char TOGGLE_FULLSCREEN[] = "QtCreator.ToggleFullScreen";
+const char THEMEOPTIONS[] = "QtCreator.ThemeOptions";
const char TR_SHOW_SIDEBAR[] = QT_TRANSLATE_NOOP("Core", "Show Sidebar");
const char TR_HIDE_SIDEBAR[] = QT_TRANSLATE_NOOP("Core", "Hide Sidebar");
@@ -241,6 +242,8 @@ const char SETTINGS_ID_MIMETYPES[] = "D.MimeTypes";
const char SETTINGS_DEFAULTTEXTENCODING[] = "General/DefaultFileEncoding";
+const char SETTINGS_THEME[] = "Core/CreatorTheme";
+
const char ALL_FILES_FILTER[] = QT_TRANSLATE_NOOP("Core", "All Files (*)");
const char TR_CLEAR_MENU[] = QT_TRANSLATE_NOOP("Core", "Clear Menu");
diff --git a/src/plugins/coreplugin/coreplugin.cpp b/src/plugins/coreplugin/coreplugin.cpp
index a63d533e05..63739045ef 100644
--- a/src/plugins/coreplugin/coreplugin.cpp
+++ b/src/plugins/coreplugin/coreplugin.cpp
@@ -42,23 +42,30 @@
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/find/findplugin.h>
#include <coreplugin/locator/locator.h>
+#include <coreplugin/coreconstants.h>
#include <utils/macroexpander.h>
#include <utils/savefile.h>
+#include <utils/stringutils.h>
+#include <utils/theme/theme.h>
#include <QtPlugin>
#include <QDebug>
#include <QDateTime>
+#include <QDir>
using namespace Core;
using namespace Core::Internal;
-
-CorePlugin::CorePlugin() : m_editMode(0), m_designMode(0)
+using namespace Utils;
+
+CorePlugin::CorePlugin()
+ : m_mainWindow(0)
+ , m_editMode(0)
+ , m_designMode(0)
+ , m_findPlugin(0)
+ , m_locator(0)
{
qRegisterMetaType<Core::Id>();
- m_mainWindow = new MainWindow;
- m_findPlugin = new FindPlugin;
- m_locator = new Locator;
}
CorePlugin::~CorePlugin()
@@ -84,15 +91,55 @@ CorePlugin::~CorePlugin()
void CorePlugin::parseArguments(const QStringList &arguments)
{
+ QString themeName = QLatin1String("default");
+ QColor overrideColor;
+ bool overrideTheme = false;
+
for (int i = 0; i < arguments.size(); ++i) {
if (arguments.at(i) == QLatin1String("-color")) {
const QString colorcode(arguments.at(i + 1));
- m_mainWindow->setOverrideColor(QColor(colorcode));
+ overrideColor = QColor(colorcode);
i++; // skip the argument
}
if (arguments.at(i) == QLatin1String("-presentationMode"))
ActionManager::setPresentationModeEnabled(true);
+ if (arguments.at(i) == QLatin1String("-theme")) {
+ overrideTheme = true;
+ themeName = arguments.at(i + 1);
+ i++;
+ }
}
+
+ QSettings *settings = Core::ICore::settings();
+ QString themeURI = settings->value(QLatin1String(Core::Constants::SETTINGS_THEME)).toString();
+
+ if (!QFileInfo::exists(themeURI) || overrideTheme) {
+ const QString builtInTheme = QStringLiteral("%1/themes/%2.creatortheme")
+ .arg(ICore::resourcePath()).arg(themeName);
+ if (QFile::exists(builtInTheme)) {
+ themeURI = builtInTheme;
+ } else if (themeName.endsWith(QLatin1String(".creatortheme"))) {
+ themeURI = themeName;
+ } else { // TODO: Fallback to default theme
+ qCritical("%s", qPrintable(QCoreApplication::translate("Application", "No valid theme '%1'")
+ .arg(themeName)));
+ }
+ }
+
+ QSettings themeSettings(themeURI, QSettings::IniFormat);
+ Theme *theme = new Theme(qApp);
+ theme->readSettings(themeSettings);
+ setCreatorTheme(theme);
+ qApp->setPalette(creatorTheme()->palette(qApp->palette()));
+
+ // defer creation of these widgets until here,
+ // because they need a valid theme set
+ m_mainWindow = new MainWindow;
+ m_findPlugin = new FindPlugin;
+ m_locator = new Locator;
+
+ if (overrideColor.isValid())
+ m_mainWindow->setOverrideColor(overrideColor);
}
bool CorePlugin::initialize(const QStringList &arguments, QString *errorMessage)
diff --git a/src/plugins/coreplugin/coreplugin.pro b/src/plugins/coreplugin/coreplugin.pro
index e9f5ef867b..e822521e6a 100644
--- a/src/plugins/coreplugin/coreplugin.pro
+++ b/src/plugins/coreplugin/coreplugin.pro
@@ -16,6 +16,7 @@ SOURCES += corejsextensions.cpp \
fancyactionbar.cpp \
fancytabwidget.cpp \
generalsettings.cpp \
+ themesettings.cpp \
id.cpp \
icontext.cpp \
jsexpander.cpp \
@@ -101,7 +102,15 @@ SOURCES += corejsextensions.cpp \
ioutputpane.cpp \
patchtool.cpp \
windowsupport.cpp \
- opendocumentstreeview.cpp
+ opendocumentstreeview.cpp \
+ themeeditor/themecolors.cpp \
+ themeeditor/themecolorstableview.cpp \
+ themeeditor/colorvariable.cpp \
+ themeeditor/themeeditorwidget.cpp \
+ themeeditor/colorrole.cpp \
+ themeeditor/themesettingstablemodel.cpp \
+ themeeditor/sectionedtablemodel.cpp \
+ themeeditor/themesettingsitemdelegate.cpp
HEADERS += corejsextensions.h \
mainwindow.h \
@@ -111,6 +120,7 @@ HEADERS += corejsextensions.h \
fancyactionbar.h \
fancytabwidget.h \
generalsettings.h \
+ themesettings.h \
id.h \
jsexpander.h \
messagemanager.h \
@@ -206,18 +216,28 @@ HEADERS += corejsextensions.h \
dialogs/addtovcsdialog.h \
patchtool.h \
windowsupport.h \
- opendocumentstreeview.h
+ opendocumentstreeview.h \
+ themeeditor/themecolors.h \
+ themeeditor/themecolorstableview.h \
+ themeeditor/colorvariable.h \
+ themeeditor/themeeditorwidget.h \
+ themeeditor/colorrole.h \
+ themeeditor/themesettingstablemodel.h \
+ themeeditor/sectionedtablemodel.h \
+ themeeditor/themesettingsitemdelegate.h \
FORMS += dialogs/newdialog.ui \
dialogs/saveitemsdialog.ui \
dialogs/readonlyfilesdialog.ui \
dialogs/openwithdialog.ui \
generalsettings.ui \
+ themesettings.ui \
dialogs/externaltoolconfig.ui \
mimetypesettingspage.ui \
mimetypemagicdialog.ui \
removefiledialog.ui \
- dialogs/addtovcsdialog.ui
+ dialogs/addtovcsdialog.ui \
+ themeeditor/themeeditorwidget.ui
RESOURCES += core.qrc \
fancyactionbar.qrc
diff --git a/src/plugins/coreplugin/coreplugin.qbs b/src/plugins/coreplugin/coreplugin.qbs
index 33cf4ff513..0e3773bfc7 100644
--- a/src/plugins/coreplugin/coreplugin.qbs
+++ b/src/plugins/coreplugin/coreplugin.qbs
@@ -285,6 +285,30 @@ QtcPlugin {
]
}
+ Group {
+ name: "ThemeEditor"
+ prefix: "themeeditor/"
+ files: [
+ "colorrole.cpp",
+ "colorrole.h",
+ "colorvariable.cpp",
+ "colorvariable.h",
+ "sectionedtablemodel.cpp",
+ "sectionedtablemodel.h",
+ "themecolors.cpp",
+ "themecolors.h",
+ "themecolorstableview.cpp",
+ "themecolorstableview.h",
+ "themeeditorwidget.cpp",
+ "themeeditorwidget.h",
+ "themeeditorwidget.ui",
+ "themesettingsitemdelegate.cpp",
+ "themesettingsitemdelegate.h",
+ "themesettingstablemodel.cpp",
+ "themesettingstablemodel.h",
+ ]
+ }
+
Export {
Depends { name: "Aggregation" }
Depends { name: "Utils" }
diff --git a/src/plugins/coreplugin/editormanager/editorview.cpp b/src/plugins/coreplugin/editormanager/editorview.cpp
index 01df7f5657..044d72cdfa 100644
--- a/src/plugins/coreplugin/editormanager/editorview.cpp
+++ b/src/plugins/coreplugin/editormanager/editorview.cpp
@@ -42,6 +42,7 @@
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/findplaceholder.h>
#include <utils/qtcassert.h>
+#include <utils/theme/theme.h>
#include <QDebug>
@@ -56,7 +57,7 @@
using namespace Core;
using namespace Core::Internal;
-
+using namespace Utils;
// ================EditorView====================
@@ -244,11 +245,17 @@ void EditorView::paintEvent(QPaintEvent *)
// Discreet indication where an editor would be if there is none
QPainter painter(this);
- painter.setRenderHint(QPainter::Antialiasing, true);
- painter.setPen(Qt::NoPen);
- painter.setBrush(palette().color(QPalette::Background).darker(107));
- const int r = 3;
- painter.drawRoundedRect(m_container->geometry().adjusted(r , r, -r, -r), r * 2, r * 2);
+
+ QRect rect = m_container->geometry();
+ if (creatorTheme()->widgetStyle() == Theme::StyleDefault) {
+ painter.setRenderHint(QPainter::Antialiasing, true);
+ painter.setPen(Qt::NoPen);
+ painter.setBrush(creatorTheme()->color(Theme::EditorPlaceholderColor));
+ const int r = 3;
+ painter.drawRoundedRect(rect.adjusted(r , r, -r, -r), r * 2, r * 2);
+ } else {
+ painter.fillRect(rect, creatorTheme()->color(Theme::EditorPlaceholderColor));
+ }
}
void EditorView::mousePressEvent(QMouseEvent *e)
diff --git a/src/plugins/coreplugin/fancyactionbar.cpp b/src/plugins/coreplugin/fancyactionbar.cpp
index 926fa088c4..a411ef7d97 100644
--- a/src/plugins/coreplugin/fancyactionbar.cpp
+++ b/src/plugins/coreplugin/fancyactionbar.cpp
@@ -36,6 +36,7 @@
#include <utils/stringutils.h>
#include <utils/tooltip/tooltip.h>
#include <utils/tooltip/tipcontents.h>
+#include <utils/theme/theme.h>
#include <QPainter>
#include <QVBoxLayout>
@@ -145,30 +146,41 @@ void FancyToolButton::paintEvent(QPaintEvent *event)
if (!Utils::HostOsInfo::isMacHost() // Mac UIs usually don't hover
&& m_fader > 0 && isEnabled() && !isDown() && !isChecked()) {
painter.save();
- int fader = int(40 * m_fader);
- QLinearGradient grad(rect().topLeft(), rect().topRight());
- grad.setColorAt(0, Qt::transparent);
- grad.setColorAt(0.5, QColor(255, 255, 255, fader));
- grad.setColorAt(1, Qt::transparent);
- painter.fillRect(rect(), grad);
- painter.setPen(QPen(grad, 1.0));
- painter.drawLine(rect().topLeft(), rect().topRight());
- painter.drawLine(rect().bottomLeft(), rect().bottomRight());
+ const QColor hoverColor = creatorTheme()->color(Theme::FancyToolButtonHoverColor);
+ QColor fadedHoverColor = hoverColor;
+ fadedHoverColor.setAlpha(int(m_fader * hoverColor.alpha()));
+ if (creatorTheme()->widgetStyle() == Theme::StyleDefault) {
+ QLinearGradient grad(rect().topLeft(), rect().topRight());
+ grad.setColorAt(0, Qt::transparent);
+ grad.setColorAt(0.5, fadedHoverColor);
+ grad.setColorAt(1, Qt::transparent);
+ painter.fillRect(rect(), grad);
+ painter.setPen(QPen(grad, 1.0));
+ painter.drawLine(rect().topLeft(), rect().topRight());
+ painter.drawLine(rect().bottomLeft(), rect().bottomRight());
+ } else {
+ painter.fillRect(rect(), fadedHoverColor);
+ }
painter.restore();
} else if (isDown() || isChecked()) {
painter.save();
- QLinearGradient grad(rect().topLeft(), rect().topRight());
- grad.setColorAt(0, Qt::transparent);
- grad.setColorAt(0.5, QColor(0, 0, 0, 50));
- grad.setColorAt(1, Qt::transparent);
- painter.fillRect(rect(), grad);
- painter.setPen(QPen(grad, 1.0));
- painter.drawLine(rect().topLeft(), rect().topRight());
- painter.drawLine(rect().topLeft(), rect().topRight());
- painter.drawLine(rect().topLeft() + QPoint(0,1), rect().topRight() + QPoint(0,1));
- painter.drawLine(rect().bottomLeft(), rect().bottomRight());
- painter.drawLine(rect().bottomLeft(), rect().bottomRight());
- painter.drawLine(rect().topLeft() - QPoint(0,1), rect().topRight() - QPoint(0,1));
+ const QColor selectedColor = creatorTheme()->color(Theme::FancyToolButtonSelectedColor);
+ if (creatorTheme()->widgetStyle() == Theme::StyleDefault) {
+ QLinearGradient grad(rect().topLeft(), rect().topRight());
+ grad.setColorAt(0, Qt::transparent);
+ grad.setColorAt(0.5, selectedColor);
+ grad.setColorAt(1, Qt::transparent);
+ painter.fillRect(rect(), grad);
+ painter.setPen(QPen(grad, 1.0));
+ painter.drawLine(rect().topLeft(), rect().topRight());
+ painter.drawLine(rect().topLeft(), rect().topRight());
+ painter.drawLine(rect().topLeft() + QPoint(0,1), rect().topRight() + QPoint(0,1));
+ painter.drawLine(rect().bottomLeft(), rect().bottomRight());
+ painter.drawLine(rect().bottomLeft(), rect().bottomRight());
+ painter.drawLine(rect().topLeft() - QPoint(0,1), rect().topRight() - QPoint(0,1));
+ } else {
+ painter.fillRect(rect(), selectedColor);
+ }
painter.restore();
}
@@ -261,7 +273,13 @@ void FancyToolButton::paintEvent(QPaintEvent *event)
void FancyActionBar::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
- Q_UNUSED(event)
+
+ if (creatorTheme()->widgetStyle () == Theme::StyleFlat) {
+ // this paints the background of the bottom portion of the
+ // left tab bar
+ painter.fillRect(event->rect(), creatorTheme()->color(Theme::FancyTabBarBackgroundColor));
+ }
+
QColor light = Utils::StyleHelper::sidebarHighlight();
QColor dark = Utils::StyleHelper::sidebarShadow();
painter.setPen(dark);
diff --git a/src/plugins/coreplugin/fancytabwidget.cpp b/src/plugins/coreplugin/fancytabwidget.cpp
index ebf73bf69a..b4095138fd 100644
--- a/src/plugins/coreplugin/fancytabwidget.cpp
+++ b/src/plugins/coreplugin/fancytabwidget.cpp
@@ -32,6 +32,7 @@
#include <utils/hostosinfo.h>
#include <utils/stylehelper.h>
#include <utils/styledbar.h>
+#include <utils/theme/theme.h>
#include <QDebug>
@@ -47,6 +48,7 @@
using namespace Core;
using namespace Internal;
+using namespace Utils;
const int FancyTabBar::m_rounding = 22;
const int FancyTabBar::m_textPadding = 4;
@@ -115,8 +117,12 @@ QSize FancyTabBar::tabSizeHint(bool minimum) const
void FancyTabBar::paintEvent(QPaintEvent *event)
{
- Q_UNUSED(event)
QPainter p(this);
+ if (creatorTheme()->widgetStyle() == Theme::StyleFlat) {
+ // draw background of upper part of left tab widget
+ // (Welcome, ... Help)
+ p.fillRect (event->rect(), creatorTheme()->color(Theme::FancyTabBarBackgroundColor));
+ }
for (int i = 0; i < count(); ++i)
if (i != currentIndex())
@@ -245,29 +251,35 @@ void FancyTabBar::paintTab(QPainter *painter, int tabIndex) const
bool enabled = isTabEnabled(tabIndex);
if (selected) {
- //background
- painter->save();
- QLinearGradient grad(rect.topLeft(), rect.topRight());
- grad.setColorAt(0, QColor(255, 255, 255, 140));
- grad.setColorAt(1, QColor(255, 255, 255, 210));
- painter->fillRect(rect.adjusted(0, 0, 0, -1), grad);
- painter->restore();
-
- //shadows
- painter->setPen(QColor(0, 0, 0, 110));
- painter->drawLine(rect.topLeft() + QPoint(1,-1), rect.topRight() - QPoint(0,1));
- painter->drawLine(rect.bottomLeft(), rect.bottomRight());
- painter->setPen(QColor(0, 0, 0, 40));
- painter->drawLine(rect.topLeft(), rect.bottomLeft());
-
- //highlights
- painter->setPen(QColor(255, 255, 255, 50));
- painter->drawLine(rect.topLeft() + QPoint(0, -2), rect.topRight() - QPoint(0,2));
- painter->drawLine(rect.bottomLeft() + QPoint(0, 1), rect.bottomRight() + QPoint(0,1));
- painter->setPen(QColor(255, 255, 255, 40));
- painter->drawLine(rect.topLeft() + QPoint(0, 0), rect.topRight());
- painter->drawLine(rect.topRight() + QPoint(0, 1), rect.bottomRight() - QPoint(0, 1));
- painter->drawLine(rect.bottomLeft() + QPoint(0,-1), rect.bottomRight()-QPoint(0,1));
+ if (creatorTheme()->widgetStyle() == Theme::StyleFlat) {
+ // background color of a fancy tab that is active
+ painter->fillRect(rect.adjusted(0, 0, 0, -1),
+ creatorTheme()->color(Theme::BackgroundColorSelected));
+ } else {
+ //background
+ painter->save();
+ QLinearGradient grad(rect.topLeft(), rect.topRight());
+ grad.setColorAt(0, QColor(255, 255, 255, 140));
+ grad.setColorAt(1, QColor(255, 255, 255, 210));
+ painter->fillRect(rect.adjusted(0, 0, 0, -1), grad);
+ painter->restore();
+
+ //shadows
+ painter->setPen(QColor(0, 0, 0, 110));
+ painter->drawLine(rect.topLeft() + QPoint(1,-1), rect.topRight() - QPoint(0,1));
+ painter->drawLine(rect.bottomLeft(), rect.bottomRight());
+ painter->setPen(QColor(0, 0, 0, 40));
+ painter->drawLine(rect.topLeft(), rect.bottomLeft());
+
+ //highlights
+ painter->setPen(QColor(255, 255, 255, 50));
+ painter->drawLine(rect.topLeft() + QPoint(0, -2), rect.topRight() - QPoint(0,2));
+ painter->drawLine(rect.bottomLeft() + QPoint(0, 1), rect.bottomRight() + QPoint(0,1));
+ painter->setPen(QColor(255, 255, 255, 40));
+ painter->drawLine(rect.topLeft() + QPoint(0, 0), rect.topRight());
+ painter->drawLine(rect.topRight() + QPoint(0, 1), rect.bottomRight() - QPoint(0, 1));
+ painter->drawLine(rect.bottomLeft() + QPoint(0,-1), rect.bottomRight()-QPoint(0,1));
+ }
}
QString tabText(this->tabText(tabIndex));
@@ -281,23 +293,24 @@ void FancyTabBar::paintTab(QPainter *painter, int tabIndex) const
painter->setFont(boldFont);
painter->setPen(selected ? QColor(255, 255, 255, 160) : QColor(0, 0, 0, 110));
const int textFlags = Qt::AlignCenter | (drawIcon ? Qt::AlignBottom : Qt::AlignVCenter) | Qt::TextWordWrap;
- if (enabled) {
- painter->drawText(tabTextRect, textFlags, tabText);
- painter->setPen(selected ? QColor(60, 60, 60) : Utils::StyleHelper::panelTextColor());
- } else {
- painter->setPen(selected ? Utils::StyleHelper::panelTextColor() : QColor(255, 255, 255, 120));
- }
+
if (!Utils::HostOsInfo::isMacHost() && !selected && enabled) {
painter->save();
int fader = int(m_tabs[tabIndex]->fader());
- QLinearGradient grad(rect.topLeft(), rect.topRight());
- grad.setColorAt(0, Qt::transparent);
- grad.setColorAt(0.5, QColor(255, 255, 255, fader));
- grad.setColorAt(1, Qt::transparent);
- painter->fillRect(rect, grad);
- painter->setPen(QPen(grad, 1.0));
- painter->drawLine(rect.topLeft(), rect.topRight());
- painter->drawLine(rect.bottomLeft(), rect.bottomRight());
+ if (creatorTheme()->widgetStyle() == Theme::StyleFlat) {
+ QColor c = creatorTheme()->color(Theme::BackgroundColorHover);
+ c.setAlpha(int(255 * fader/40.0)); // FIXME: hardcoded end value 40
+ painter->fillRect(rect, c);
+ } else {
+ QLinearGradient grad(rect.topLeft(), rect.topRight());
+ grad.setColorAt(0, Qt::transparent);
+ grad.setColorAt(0.5, QColor(255, 255, 255, fader));
+ grad.setColorAt(1, Qt::transparent);
+ painter->fillRect(rect, grad);
+ painter->setPen(QPen(grad, 1.0));
+ painter->drawLine(rect.topLeft(), rect.topRight());
+ painter->drawLine(rect.bottomLeft(), rect.bottomRight());
+ }
painter->restore();
}
@@ -310,8 +323,19 @@ void FancyTabBar::paintTab(QPainter *painter, int tabIndex) const
Utils::StyleHelper::drawIconWithShadow(tabIcon(tabIndex), tabIconRect, painter, enabled ? QIcon::Normal : QIcon::Disabled);
}
+ painter->setOpacity(1.0); //FIXME: was 0.7 before?
+ if (enabled) {
+ painter->setPen(selected
+ ? creatorTheme()->color(Theme::FancyTabWidgetEnabledSelectedTextColor)
+ : creatorTheme()->color(Theme::FancyTabWidgetEnabledUnselectedTextColor));
+ } else {
+ painter->setPen(selected
+ ? creatorTheme()->color(Theme::FancyTabWidgetDisabledSelectedTextColor)
+ : creatorTheme()->color(Theme::FancyTabWidgetDisabledUnselectedTextColor));
+ }
painter->translate(0, -1);
painter->drawText(tabTextRect, textFlags, tabText);
+
painter->restore();
}
diff --git a/src/plugins/coreplugin/find/searchresultwidget.cpp b/src/plugins/coreplugin/find/searchresultwidget.cpp
index 683af3b374..a484699ac9 100644
--- a/src/plugins/coreplugin/find/searchresultwidget.cpp
+++ b/src/plugins/coreplugin/find/searchresultwidget.cpp
@@ -39,6 +39,7 @@
#include <aggregation/aggregate.h>
#include <coreplugin/coreplugin.h>
+#include <utils/theme/theme.h>
#include <QDir>
#include <QFrame>
@@ -52,6 +53,8 @@
static const int SEARCHRESULT_WARNING_LIMIT = 200000;
static const char SIZE_WARNING_ID[] = "sizeWarningLabel";
+using namespace Utils;
+
namespace Core {
namespace Internal {
@@ -93,11 +96,13 @@ SearchResultWidget::SearchResultWidget(QWidget *parent) :
QFrame *topWidget = new QFrame;
QPalette pal;
- pal.setColor(QPalette::Window, QColor(255, 255, 225));
- pal.setColor(QPalette::WindowText, Qt::black);
+ pal.setColor(QPalette::Window, creatorTheme()->color(Theme::SearchResultWidgetBackgroundColor));
+ pal.setColor(QPalette::WindowText, creatorTheme()->color(Theme::SearchResultWidgetTextColor));
topWidget->setPalette(pal);
- topWidget->setFrameStyle(QFrame::Panel | QFrame::Raised);
- topWidget->setLineWidth(1);
+ if (creatorTheme()->flag(Theme::DrawSearchResultWidgetFrame)) {
+ topWidget->setFrameStyle(QFrame::Panel | QFrame::Raised);
+ topWidget->setLineWidth(1);
+ }
topWidget->setAutoFillBackground(true);
QHBoxLayout *topLayout = new QHBoxLayout(topWidget);
topLayout->setMargin(2);
@@ -105,10 +110,12 @@ SearchResultWidget::SearchResultWidget(QWidget *parent) :
layout->addWidget(topWidget);
m_messageWidget = new QFrame;
- pal.setColor(QPalette::WindowText, Qt::red);
+ pal.setColor(QPalette::WindowText, creatorTheme()->color(Theme::CanceledSearchTextColor));
m_messageWidget->setPalette(pal);
- m_messageWidget->setFrameStyle(QFrame::Panel | QFrame::Raised);
- m_messageWidget->setLineWidth(1);
+ if (creatorTheme()->flag(Theme::DrawSearchResultWidgetFrame)) {
+ m_messageWidget->setFrameStyle(QFrame::Panel | QFrame::Raised);
+ m_messageWidget->setLineWidth(1);
+ }
m_messageWidget->setAutoFillBackground(true);
QHBoxLayout *messageLayout = new QHBoxLayout(m_messageWidget);
messageLayout->setMargin(2);
diff --git a/src/plugins/coreplugin/images/dark_fileicon.png b/src/plugins/coreplugin/images/dark_fileicon.png
new file mode 100644
index 0000000000..3581d3331f
--- /dev/null
+++ b/src/plugins/coreplugin/images/dark_fileicon.png
Binary files differ
diff --git a/src/plugins/coreplugin/images/dark_foldericon.png b/src/plugins/coreplugin/images/dark_foldericon.png
new file mode 100644
index 0000000000..dc7a50431e
--- /dev/null
+++ b/src/plugins/coreplugin/images/dark_foldericon.png
Binary files differ
diff --git a/src/plugins/coreplugin/images/dark_magnifier.png b/src/plugins/coreplugin/images/dark_magnifier.png
new file mode 100644
index 0000000000..322a542a0e
--- /dev/null
+++ b/src/plugins/coreplugin/images/dark_magnifier.png
Binary files differ
diff --git a/src/plugins/coreplugin/images/dark_magnifier@2x.png b/src/plugins/coreplugin/images/dark_magnifier@2x.png
new file mode 100644
index 0000000000..ed82c37dd0
--- /dev/null
+++ b/src/plugins/coreplugin/images/dark_magnifier@2x.png
Binary files differ
diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp
index 0cfebe0951..dbff065a40 100644
--- a/src/plugins/coreplugin/mainwindow.cpp
+++ b/src/plugins/coreplugin/mainwindow.cpp
@@ -37,6 +37,7 @@
#include "fancytabwidget.h"
#include "documentmanager.h"
#include "generalsettings.h"
+#include "themesettings.h"
#include "helpmanager.h"
#include "idocumentfactory.h"
#include "messagemanager.h"
@@ -78,6 +79,7 @@
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
#include <utils/stylehelper.h>
+#include <utils/theme/theme.h>
#include <utils/stringutils.h>
#include <extensionsystem/pluginmanager.h>
@@ -130,6 +132,7 @@ MainWindow::MainWindow() :
m_rightPaneWidget(0),
m_versionDialog(0),
m_generalSettings(new GeneralSettings),
+ m_themeSettings(new ThemeSettings),
m_shortcutSettings(new ShortcutSettings),
m_toolSettings(new ToolSettings),
m_mimeTypeSettings(new MimeTypeSettings),
@@ -252,6 +255,7 @@ MainWindow::~MainWindow()
ExtensionSystem::PluginManager::removeObject(m_shortcutSettings);
ExtensionSystem::PluginManager::removeObject(m_generalSettings);
+ ExtensionSystem::PluginManager::removeObject(m_themeSettings);
ExtensionSystem::PluginManager::removeObject(m_toolSettings);
ExtensionSystem::PluginManager::removeObject(m_mimeTypeSettings);
ExtensionSystem::PluginManager::removeObject(m_systemEditor);
@@ -263,6 +267,8 @@ MainWindow::~MainWindow()
m_shortcutSettings = 0;
delete m_generalSettings;
m_generalSettings = 0;
+ delete m_themeSettings;
+ m_themeSettings = 0;
delete m_toolSettings;
m_toolSettings = 0;
delete m_mimeTypeSettings;
@@ -320,6 +326,7 @@ bool MainWindow::init(QString *errorMessage)
m_progressManager->init(); // needs the status bar manager
ExtensionSystem::PluginManager::addObject(m_generalSettings);
+ ExtensionSystem::PluginManager::addObject(m_themeSettings);
ExtensionSystem::PluginManager::addObject(m_shortcutSettings);
ExtensionSystem::PluginManager::addObject(m_toolSettings);
ExtensionSystem::PluginManager::addObject(m_mimeTypeSettings);
@@ -628,6 +635,7 @@ void MainWindow::registerDefaultActions()
// Options Action
mtools->appendGroup(Constants::G_TOOLS_OPTIONS);
mtools->addSeparator(globalContext, Constants::G_TOOLS_OPTIONS);
+
m_optionsAction = new QAction(tr("&Options..."), this);
cmd = ActionManager::registerAction(m_optionsAction, Constants::OPTIONS, globalContext);
if (UseMacShortcuts) {
diff --git a/src/plugins/coreplugin/mainwindow.h b/src/plugins/coreplugin/mainwindow.h
index 267ca3413a..da6ec54016 100644
--- a/src/plugins/coreplugin/mainwindow.h
+++ b/src/plugins/coreplugin/mainwindow.h
@@ -72,6 +72,7 @@ namespace Internal {
class ActionManagerPrivate;
class FancyTabWidget;
class GeneralSettings;
+class ThemeSettings;
class ProgressManagerPrivate;
class ShortcutSettings;
class ToolSettings;
@@ -191,6 +192,7 @@ private:
QMap<QWidget *, IContext *> m_contextWidgets;
GeneralSettings *m_generalSettings;
+ ThemeSettings *m_themeSettings;
ShortcutSettings *m_shortcutSettings;
ToolSettings *m_toolSettings;
MimeTypeSettings *m_mimeTypeSettings;
@@ -206,6 +208,7 @@ private:
QAction *m_optionsAction;
QAction *m_toggleSideBarAction;
QAction *m_toggleModeSelectorAction;
+ QAction *m_themeAction;
QToolButton *m_toggleSideBarButton;
QColor m_overrideColor;
diff --git a/src/plugins/coreplugin/manhattanstyle.cpp b/src/plugins/coreplugin/manhattanstyle.cpp
index 889e18d265..0722e31110 100644
--- a/src/plugins/coreplugin/manhattanstyle.cpp
+++ b/src/plugins/coreplugin/manhattanstyle.cpp
@@ -38,6 +38,7 @@
#include <utils/stylehelper.h>
#include <utils/fancymainwindow.h>
+#include <utils/theme/theme.h>
#include <QApplication>
#include <QComboBox>
@@ -53,6 +54,8 @@
#include <QToolBar>
#include <QToolButton>
+using namespace Utils;
+
// We define a currently unused state for indicating animations
const QStyle::State State_Animating = QStyle::State(0x00000040);
@@ -242,7 +245,8 @@ void ManhattanStyle::unpolish(QApplication *app)
QPalette panelPalette(const QPalette &oldPalette, bool lightColored = false)
{
- QColor color = Utils::StyleHelper::panelTextColor(lightColored);
+ Q_UNUSED(lightColored);
+ QColor color = creatorTheme()->color(Theme::PanelTextColor);
QPalette pal = oldPalette;
pal.setBrush(QPalette::All, QPalette::WindowText, color);
pal.setBrush(QPalette::All, QPalette::ButtonText, color);
@@ -310,17 +314,12 @@ void ManhattanStyle::polish(QPalette &pal)
QProxyStyle::polish(pal);
}
-QIcon ManhattanStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const
+QIcon ManhattanStyle::standardIcon(StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget) const
{
- QIcon icon;
- switch (standardIcon) {
- case QStyle::SP_TitleBarCloseButton:
- case QStyle::SP_ToolBarHorizontalExtensionButton:
- return QIcon(standardPixmap(standardIcon, option, widget));
- default:
- icon = baseStyle()->standardIcon(standardIcon, option, widget);
- }
- return icon;
+ QIcon ico = creatorTheme()->standardIcon(standardPixmap, opt, widget);
+ if (!ico.isNull())
+ return ico;
+ return QProxyStyle::standardIcon(standardPixmap, opt, widget);
}
QPixmap ManhattanStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt,
@@ -377,8 +376,13 @@ int ManhattanStyle::styleHint(StyleHint hint, const QStyleOption *option, const
void ManhattanStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option,
QPainter *painter, const QWidget *widget) const
{
- if (!panelWidget(widget))
+ if (!panelWidget(widget)) {
+ if (creatorTheme()->flag(Theme::DrawIndicatorBranch) && element == PE_IndicatorBranch) {
+ creatorTheme()->drawIndicatorBranch(painter, option->rect, option->state);
+ return;
+ }
return QProxyStyle::drawPrimitive(element, option, painter, widget);
+ }
bool animating = (option->state & State_Animating);
int state = option->state;
@@ -437,7 +441,7 @@ void ManhattanStyle::drawPrimitive(PrimitiveElement element, const QStyleOption
switch (element) {
case PE_IndicatorDockWidgetResizeHandle:
- painter->fillRect(option->rect, Utils::StyleHelper::borderColor());
+ painter->fillRect(option->rect, creatorTheme()->color(Theme::DockWidgetResizeHandleColor));
break;
case PE_FrameDockWidget:
QCommonStyle::drawPrimitive(element, option, painter, widget);
@@ -491,8 +495,7 @@ void ManhattanStyle::drawPrimitive(PrimitiveElement element, const QStyleOption
QColor highlight(255, 255, 255, 30);
painter->setPen(highlight);
} else if (option->state & State_Enabled && option->state & State_MouseOver) {
- QColor lighter(255, 255, 255, 37);
- painter->fillRect(rect, lighter);
+ painter->fillRect(rect, creatorTheme()->color(Theme::PanelButtonToolBackgroundColorHover));
} else if (widget && widget->property("highlightWidget").toBool()) {
QColor shade(0, 0, 0, 128);
painter->fillRect(rect, shade);
@@ -513,15 +516,19 @@ void ManhattanStyle::drawPrimitive(PrimitiveElement element, const QStyleOption
case PE_PanelStatusBar:
{
- painter->save();
- QLinearGradient grad = Utils::StyleHelper::statusBarGradient(rect);
- painter->fillRect(rect, grad);
- painter->setPen(QColor(255, 255, 255, 60));
- painter->drawLine(rect.topLeft() + QPoint(0,1),
- rect.topRight()+ QPoint(0,1));
- painter->setPen(Utils::StyleHelper::borderColor().darker(110));
- painter->drawLine(rect.topLeft(), rect.topRight());
- painter->restore();
+ if (creatorTheme()->widgetStyle() == Theme::StyleDefault) {
+ painter->save();
+ QLinearGradient grad = Utils::StyleHelper::statusBarGradient(rect);
+ painter->fillRect(rect, grad);
+ painter->setPen(QColor(255, 255, 255, 60));
+ painter->drawLine(rect.topLeft() + QPoint(0,1),
+ rect.topRight()+ QPoint(0,1));
+ painter->setPen(Utils::StyleHelper::borderColor().darker(110)); //TODO: make themable
+ painter->drawLine(rect.topLeft(), rect.topRight());
+ painter->restore();
+ } else {
+ painter->fillRect(rect, creatorTheme()->color(Theme::PanelStatusBarBackgroundColor));
+ }
}
break;
@@ -639,13 +646,20 @@ void ManhattanStyle::drawControl(ControlElement element, const QStyleOption *opt
painter->save();
if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
QColor highlightOutline = Utils::StyleHelper::borderColor().lighter(120);
- bool act = mbi->state & (State_Sunken | State_Selected);
- bool dis = !(mbi->state & State_Enabled);
- Utils::StyleHelper::menuGradient(painter, option->rect, option->rect);
+ const bool act = mbi->state & (State_Sunken | State_Selected);
+ const bool dis = !(mbi->state & State_Enabled);
+
+ if (creatorTheme()->widgetStyle() == Theme::StyleFlat)
+ painter->fillRect(option->rect, creatorTheme()->color(Theme::MenuBarItemBackgroundColor));
+ else
+ Utils::StyleHelper::menuGradient(painter, option->rect, option->rect);
+
QStyleOptionMenuItem item = *mbi;
item.rect = mbi->rect;
QPalette pal = mbi->palette;
- pal.setBrush(QPalette::ButtonText, dis ? Qt::gray : Qt::black);
+ pal.setBrush(QPalette::ButtonText, dis
+ ? creatorTheme()->color(Theme::MenuBarItemTextColorDisabled)
+ : creatorTheme()->color(Theme::MenuBarItemTextColorNormal));
item.palette = pal;
QCommonStyle::drawControl(element, &item, painter, widget);
@@ -725,13 +739,15 @@ void ManhattanStyle::drawControl(ControlElement element, const QStyleOption *opt
}
text.prepend(option->fontMetrics.elidedText(cb->currentText, Qt::ElideRight, elideWidth));
- if ((option->state & State_Enabled)) {
+ if (creatorTheme()->flag(Theme::ComboBoxDrawTextShadow)
+ && (option->state & State_Enabled))
+ {
painter->setPen(QColor(0, 0, 0, 70));
painter->drawText(editRect.adjusted(1, 0, -1, 0), Qt::AlignLeft | Qt::AlignVCenter, text);
- } else {
- painter->setOpacity(0.8);
}
- painter->setPen(Utils::StyleHelper::panelTextColor());
+ if (option->state & State_Enabled)
+ painter->setOpacity(0.8);
+ painter->setPen(creatorTheme()->color(Theme::ComboBoxTextColor));
painter->drawText(editRect.adjusted(1, 0, -1, 0), Qt::AlignLeft | Qt::AlignVCenter, text);
painter->restore();
@@ -775,12 +791,16 @@ void ManhattanStyle::drawControl(ControlElement element, const QStyleOption *opt
break;
case CE_MenuBarEmptyArea: {
- Utils::StyleHelper::menuGradient(painter, option->rect, option->rect);
- painter->save();
- painter->setPen(Utils::StyleHelper::borderColor());
- painter->drawLine(option->rect.bottomLeft() + QPointF(0.5, 0.5),
- option->rect.bottomRight() + QPointF(0.5, 0.5));
- painter->restore();
+ if (creatorTheme()->widgetStyle() == Theme::StyleDefault) {
+ Utils::StyleHelper::menuGradient(painter, option->rect, option->rect);
+ painter->save();
+ painter->setPen(Utils::StyleHelper::borderColor());
+ painter->drawLine(option->rect.bottomLeft() + QPointF(0.5, 0.5),
+ option->rect.bottomRight() + QPointF(0.5, 0.5));
+ painter->restore();
+ } else {
+ painter->fillRect(option->rect, creatorTheme()->color(Theme::MenuBarEmptyAreaBackgroundColor));
+ }
}
break;
@@ -799,12 +819,22 @@ void ManhattanStyle::drawControl(ControlElement element, const QStyleOption *opt
bool drawLightColored = lightColored(widget);
if (horizontal)
- Utils::StyleHelper::horizontalGradient(painter, gradientSpan, rect, drawLightColored);
- else
- Utils::StyleHelper::verticalGradient(painter, gradientSpan, rect, drawLightColored);
+ {
+ // draws the background of the 'Type hierarchy', 'Projects' headers
+ if (creatorTheme()->widgetStyle() == Theme::StyleFlat)
+ painter->fillRect (rect, creatorTheme()->color(Theme::ToolBarBackgroundColor));
+ else
+ Utils::StyleHelper::horizontalGradient(painter, gradientSpan, rect, drawLightColored);
+ } else {
+ if (creatorTheme()->widgetStyle() == Theme::StyleFlat)
+ painter->fillRect (rect, creatorTheme()->color(Theme::ToolBarBackgroundColor));
+ else
+ Utils::StyleHelper::verticalGradient(painter, gradientSpan, rect, drawLightColored);
+ }
- if (!drawLightColored)
+ if (!drawLightColored) {
painter->setPen(Utils::StyleHelper::borderColor());
+ }
else
painter->setPen(QColor(0x888888));
diff --git a/src/plugins/coreplugin/manhattanstyle.h b/src/plugins/coreplugin/manhattanstyle.h
index c4b9571227..e67ea49c09 100644
--- a/src/plugins/coreplugin/manhattanstyle.h
+++ b/src/plugins/coreplugin/manhattanstyle.h
@@ -56,6 +56,7 @@ public:
SubControl hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option, const QPoint &pos, const QWidget *widget = 0) const;
QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget = 0) const;
+ QIcon standardIcon(StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget = 0) const;
int styleHint(StyleHint hint, const QStyleOption *option = 0, const QWidget *widget = 0, QStyleHintReturn *returnData = 0) const;
QRect itemRect(QPainter *p, const QRect &r, int flags, bool enabled, const QPixmap *pixmap, const QString &text, int len = -1) const;
QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *opt) const;
@@ -71,9 +72,6 @@ public:
void unpolish(QWidget *widget);
void unpolish(QApplication *app);
-protected slots:
- QIcon standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const;
-
private:
void drawButtonSeparator(QPainter *painter, const QRect &rect, bool reverse) const;
diff --git a/src/plugins/coreplugin/outputpanemanager.cpp b/src/plugins/coreplugin/outputpanemanager.cpp
index 4b02e079f8..c8a60c0c60 100644
--- a/src/plugins/coreplugin/outputpanemanager.cpp
+++ b/src/plugins/coreplugin/outputpanemanager.cpp
@@ -49,6 +49,7 @@
#include <utils/styledbar.h>
#include <utils/stylehelper.h>
#include <utils/qtcassert.h>
+#include <utils/theme/theme.h>
#include <QDebug>
@@ -65,6 +66,8 @@
#include <QToolButton>
#include <QTimeLine>
+using namespace Utils;
+
namespace Core {
namespace Internal {
@@ -675,24 +678,44 @@ void OutputPaneToggleButton::paintEvent(QPaintEvent*)
styleOption.initFrom(this);
const bool hovered = !Utils::HostOsInfo::isMacHost() && (styleOption.state & QStyle::State_MouseOver);
- QImage const* image = 0;
- if (isDown())
- image = &panelButtonPressed;
- else if (isChecked())
- image = hovered ? &panelButtonCheckedHover : &panelButtonChecked;
- else
- image = hovered ? &panelButtonHover : &panelButton;
- if (image)
- Utils::StyleHelper::drawCornerImage(*image, &p, rect(), numberAreaWidth, buttonBorderWidth, buttonBorderWidth, buttonBorderWidth);
+ const QImage *image = 0;
+ if (creatorTheme()->widgetStyle() == Theme::StyleDefault) {
+ if (isDown())
+ image = &panelButtonPressed;
+ else if (isChecked())
+ image = hovered ? &panelButtonCheckedHover : &panelButtonChecked;
+ else
+ image = hovered ? &panelButtonHover : &panelButton;
+ if (image)
+ Utils::StyleHelper::drawCornerImage(*image, &p, rect(), numberAreaWidth, buttonBorderWidth, buttonBorderWidth, buttonBorderWidth);
+ } else {
+ QColor c;
+ if (isChecked()) {
+ c = creatorTheme()->color(hovered ? Theme::BackgroundColorHover
+ : Theme::BackgroundColorSelected);
+ } else if (isDown()) {
+ c = creatorTheme()->color(Theme::BackgroundColorSelected);
+ } else {
+ c = creatorTheme()->color(hovered ? Theme::BackgroundColorHover
+ : Theme::BackgroundColorDark);
+ }
+ p.fillRect(rect(), c);
+ }
if (m_flashTimer->state() == QTimeLine::Running)
- p.fillRect(rect().adjusted(numberAreaWidth, 1, -1, -1), QBrush(QColor(255, 0, 0, m_flashTimer->currentFrame())));
+ {
+ QColor c = creatorTheme()->color(Theme::OutputPaneButtonFlashColor);
+ c.setAlpha (m_flashTimer->currentFrame());
+ QRect r = (creatorTheme()->widgetStyle() == Theme::StyleFlat)
+ ? rect() : rect().adjusted(numberAreaWidth, 1, -1, -1);
+ p.fillRect(r, c);
+ }
p.setFont(font());
- p.setPen(Qt::white);
+ p.setPen(creatorTheme()->color(Theme::OutputPaneToggleButtonTextColorChecked));
p.drawText((numberAreaWidth - numberWidth) / 2, baseLine, m_number);
if (!isChecked())
- p.setPen(Qt::black);
+ p.setPen(creatorTheme()->color(Theme::OutputPaneToggleButtonTextColorUnchecked));
int leftPart = numberAreaWidth + buttonBorderWidth;
int labelWidth = 0;
if (!m_badgeNumberLabel.text().isEmpty()) {
@@ -751,8 +774,10 @@ QSize OutputPaneManageButton::sizeHint() const
void OutputPaneManageButton::paintEvent(QPaintEvent*)
{
QPainter p(this);
- static const QImage button(Utils::StyleHelper::dpiSpecificImageFile(QStringLiteral(":/core/images/panel_manage_button.png")));
- Utils::StyleHelper::drawCornerImage(button, &p, rect(), buttonBorderWidth, buttonBorderWidth, buttonBorderWidth, buttonBorderWidth);
+ if (creatorTheme()->widgetStyle() == Theme::StyleDefault) {
+ static const QImage button(Utils::StyleHelper::dpiSpecificImageFile(QStringLiteral(":/core/images/panel_manage_button.png")));
+ Utils::StyleHelper::drawCornerImage(button, &p, rect(), buttonBorderWidth, buttonBorderWidth, buttonBorderWidth, buttonBorderWidth);
+ }
QStyle *s = style();
QStyleOption arrowOpt;
arrowOpt.initFrom(this);
@@ -775,13 +800,15 @@ void BadgeLabel::paint(QPainter *p, int x, int y, bool isChecked)
const QRectF rect(QRect(QPoint(x, y), m_size));
p->save();
- p->setBrush(isChecked ? QColor(0xe0, 0xe0, 0xe0) : Qt::darkGray);
+ p->setBrush(creatorTheme()->color(isChecked? Theme::BadgeLabelBackgroundColorChecked
+ : Theme::BadgeLabelBackgroundColorUnchecked));
p->setPen(Qt::NoPen);
p->setRenderHint(QPainter::Antialiasing, true);
p->drawRoundedRect(rect, m_padding, m_padding, Qt::AbsoluteSize);
p->setFont(m_font);
- p->setPen(isChecked ? QColor(0x60, 0x60, 0x60) : Qt::white);
+ p->setPen(creatorTheme()->color(isChecked ? Theme::BadgeLabelTextColorChecked
+ : Theme::BadgeLabelTextColorUnchecked));
p->drawText(rect, Qt::AlignCenter, m_text);
p->restore();
diff --git a/src/plugins/coreplugin/progressmanager/futureprogress.cpp b/src/plugins/coreplugin/progressmanager/futureprogress.cpp
index fec6376eab..eb61772d89 100644
--- a/src/plugins/coreplugin/progressmanager/futureprogress.cpp
+++ b/src/plugins/coreplugin/progressmanager/futureprogress.cpp
@@ -32,6 +32,7 @@
#include "progressbar.h"
#include <utils/stylehelper.h>
+#include <utils/theme/theme.h>
#include <QCoreApplication>
#include <QFutureWatcher>
@@ -48,6 +49,8 @@
const int notificationTimeout = 8000;
const int shortNotificationTimeout = 1000;
+using namespace Utils;
+
namespace Core {
class FutureProgressPrivate : public QObject
@@ -295,8 +298,12 @@ void FutureProgress::mousePressEvent(QMouseEvent *event)
void FutureProgress::paintEvent(QPaintEvent *)
{
QPainter p(this);
- QLinearGradient grad = Utils::StyleHelper::statusBarGradient(rect());
- p.fillRect(rect(), grad);
+ if (creatorTheme()->widgetStyle() == Theme::StyleFlat) {
+ p.fillRect(rect(), creatorTheme()->color(Theme::FutureProgressBackgroundColor));
+ } else {
+ QLinearGradient grad = Utils::StyleHelper::statusBarGradient(rect());
+ p.fillRect(rect(), grad);
+ }
}
/*!
diff --git a/src/plugins/coreplugin/progressmanager/progressbar.cpp b/src/plugins/coreplugin/progressmanager/progressbar.cpp
index 682a4f6e65..d5366e05d3 100644
--- a/src/plugins/coreplugin/progressmanager/progressbar.cpp
+++ b/src/plugins/coreplugin/progressmanager/progressbar.cpp
@@ -31,6 +31,7 @@
#include "progressbar.h"
#include <utils/stylehelper.h>
+#include <utils/theme/theme.h>
#include <QPropertyAnimation>
#include <QPainter>
@@ -40,6 +41,7 @@
using namespace Core;
using namespace Core::Internal;
+using namespace Utils;
static const int PROGRESSBAR_HEIGHT = 13;
static const int CANCELBUTTON_WIDTH = 16;
@@ -277,7 +279,7 @@ void ProgressBar::paintEvent(QPaintEvent *)
p.setPen(QColor(0, 0, 0, 120));
p.drawText(textRect, alignment | Qt::AlignBottom, elidedtitle);
p.translate(0, -1);
- p.setPen(Utils::StyleHelper::panelTextColor());
+ p.setPen(creatorTheme()->color(Theme::ProgressBarTitleColor));
p.drawText(textRect, alignment | Qt::AlignBottom, elidedtitle);
p.translate(0, 1);
}
@@ -287,23 +289,23 @@ void ProgressBar::paintEvent(QPaintEvent *)
// draw outer rect
const QRect rect(INDENT - 1, titleHeight + separatorHeight + (m_titleVisible ? 4 : 3),
size().width() - 2 * INDENT + 1, m_progressHeight);
- Utils::StyleHelper::drawCornerImage(bar, &p, rect, 3, 3, 3, 3);
+
+ if (creatorTheme()->flag(Theme::DrawProgressBarSunken))
+ Utils::StyleHelper::drawCornerImage(bar, &p, rect, 3, 3, 3, 3);
// draw inner rect
- QColor c = Utils::StyleHelper::panelTextColor();
- c.setAlpha(180);
+ QColor c = creatorTheme()->color(Theme::ProgressBarColorNormal);
p.setPen(Qt::NoPen);
QRectF inner = rect.adjusted(2, 2, -2, -2);
inner.adjust(0, 0, qRound((percent - 1) * inner.width()), 0);
if (m_error) {
- QColor red(255, 60, 0, 210);
- c = red;
+ c = creatorTheme()->color(Theme::ProgressBarColorError);
// avoid too small red bar
if (inner.width() < 10)
inner.adjust(0, 0, 10 - inner.width(), 0);
} else if (m_finished) {
- c = QColor(90, 170, 60);
+ c = creatorTheme()->color(Theme::ProgressBarColorFinished);
}
// Draw line and shadow after the gradient fill
@@ -311,13 +313,18 @@ void ProgressBar::paintEvent(QPaintEvent *)
p.fillRect(QRect(inner.right(), inner.top(), 2, inner.height()), QColor(0, 0, 0, 20));
p.fillRect(QRect(inner.right(), inner.top(), 1, inner.height()), QColor(0, 0, 0, 60));
}
- QLinearGradient grad(inner.topLeft(), inner.bottomLeft());
- grad.setColorAt(0, c.lighter(130));
- grad.setColorAt(0.4, c.lighter(106));
- grad.setColorAt(0.41, c.darker(106));
- grad.setColorAt(1, c.darker(130));
p.setPen(Qt::NoPen);
- p.setBrush(grad);
+ if (creatorTheme()->widgetStyle() == Theme::StyleFlat) {
+ //draw the progress bar
+ p.setBrush (c);
+ } else {
+ QLinearGradient grad(inner.topLeft(), inner.bottomLeft());
+ grad.setColorAt(0, c.lighter(130));
+ grad.setColorAt(0.4, c.lighter(106));
+ grad.setColorAt(0.41, c.darker(106));
+ grad.setColorAt(1, c.darker(130));
+ p.setBrush(grad);
+ }
p.drawRect(inner);
p.setBrush(Qt::NoBrush);
p.setPen(QPen(QColor(0, 0, 0, 30), 1));
diff --git a/src/plugins/coreplugin/progressmanager/progressmanager.cpp b/src/plugins/coreplugin/progressmanager/progressmanager.cpp
index caed00017f..14a9600f97 100644
--- a/src/plugins/coreplugin/progressmanager/progressmanager.cpp
+++ b/src/plugins/coreplugin/progressmanager/progressmanager.cpp
@@ -43,6 +43,7 @@
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
#include <utils/stylehelper.h>
+#include <utils/theme/theme.h>
#include <QAction>
#include <QEvent>
@@ -62,6 +63,7 @@ static const char kDetailsPinned[] = "DetailsPinned";
using namespace Core;
using namespace Core::Internal;
+using namespace Utils;
/*!
\mainclass
@@ -703,6 +705,11 @@ ToggleButton::ToggleButton(QWidget *parent)
: QToolButton(parent)
{
setToolButtonStyle(Qt::ToolButtonIconOnly);
+ if (creatorTheme()->widgetStyle() == Theme::StyleFlat) {
+ QPalette p = palette();
+ p.setBrush(QPalette::Base, creatorTheme()->color(Theme::ToggleButtonBackgroundColor));
+ setPalette(p);
+ }
}
QSize ToggleButton::sizeHint() const
diff --git a/src/plugins/coreplugin/themeeditor/colorrole.cpp b/src/plugins/coreplugin/themeeditor/colorrole.cpp
new file mode 100644
index 0000000000..1fe016226e
--- /dev/null
+++ b/src/plugins/coreplugin/themeeditor/colorrole.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "colorrole.h"
+#include "colorvariable.h"
+
+namespace Core {
+namespace Internal {
+namespace ThemeEditor {
+
+ColorRole::ColorRole(const QString &roleName, QSharedPointer<ColorVariable> colorVariable)
+ : m_roleName(roleName),
+ m_roleVariable(colorVariable)
+{
+ m_roleVariable->addReference(this);
+}
+
+QSharedPointer<ColorVariable> ColorRole::colorVariable() const
+{
+ return m_roleVariable;
+}
+
+void ColorRole::assignColorVariable(ColorVariable::Ptr namedColor)
+{
+ namedColor->addReference(this);
+ m_roleVariable = namedColor;
+}
+
+} // namespace ThemeEditor
+} // namespace Internal
+} // namespace Core
diff --git a/src/plugins/coreplugin/themeeditor/colorrole.h b/src/plugins/coreplugin/themeeditor/colorrole.h
new file mode 100644
index 0000000000..bf7704b8f6
--- /dev/null
+++ b/src/plugins/coreplugin/themeeditor/colorrole.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef COLORROLE_H
+#define COLORROLE_H
+
+#include <QString>
+#include <QColor>
+#include <QSharedPointer>
+
+namespace Core {
+namespace Internal {
+namespace ThemeEditor {
+
+class ColorVariable;
+class ThemeColors;
+
+class ColorRole
+{
+public:
+ friend class ThemeColors;
+
+ typedef QSharedPointer<ColorRole> Ptr;
+
+ QString roleName() const { return m_roleName; }
+ QSharedPointer<ColorVariable> colorVariable() const;
+ void assignColorVariable(QSharedPointer<ColorVariable> colorVariable);
+
+private:
+ explicit ColorRole(const QString &roleName, QSharedPointer<ColorVariable> colorVariable);
+ QString m_roleName;
+ QString m_roleDescription;
+ QSharedPointer<ColorVariable> m_roleVariable;
+};
+
+} // namespace ThemeEditor
+} // namespace Internal
+} // namespace Core
+
+#endif // COLORROLE_H
diff --git a/src/plugins/coreplugin/themeeditor/colorvariable.cpp b/src/plugins/coreplugin/themeeditor/colorvariable.cpp
new file mode 100644
index 0000000000..40294691ec
--- /dev/null
+++ b/src/plugins/coreplugin/themeeditor/colorvariable.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "colorvariable.h"
+#include "colorrole.h"
+#include <utils/qtcassert.h>
+
+namespace Core {
+namespace Internal {
+namespace ThemeEditor {
+
+ColorVariable::ColorVariable(const QColor &color, const QString &name)
+ : m_variableValue(color)
+ , m_variableName(name)
+{
+}
+
+ColorVariable::~ColorVariable()
+{
+}
+
+void ColorVariable::setColor(const QColor &newColor)
+{
+ m_variableValue = newColor;
+}
+
+void ColorVariable::addReference(ColorRole *t)
+{
+ m_references.insert(t);
+}
+
+void ColorVariable::removeReference(ColorRole *t)
+{
+ QTC_ASSERT(m_references.contains(t), return);
+ m_references.remove(t);
+}
+
+
+QSet<ColorRole *> ColorVariable::references() const
+{
+ return m_references;
+}
+
+} // namespace ThemeEditor
+} // namespace Internal
+} // namespace Core
diff --git a/src/plugins/coreplugin/themeeditor/colorvariable.h b/src/plugins/coreplugin/themeeditor/colorvariable.h
new file mode 100644
index 0000000000..1c2b1e3bd2
--- /dev/null
+++ b/src/plugins/coreplugin/themeeditor/colorvariable.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef COLORVARIABLE_H
+#define COLORVARIABLE_H
+
+#include <QSharedPointer>
+#include <QColor>
+#include <QString>
+#include <QSet>
+
+namespace Core {
+namespace Internal {
+namespace ThemeEditor {
+
+class ColorRole;
+class ThemeColors;
+
+class ColorVariable
+{
+public:
+ friend class ThemeColors;
+ typedef QSharedPointer<ColorVariable> Ptr;
+
+ ~ColorVariable();
+
+ // name of this variable
+ QString variableName() const { return m_variableName; }
+
+ // value of this variable
+ QColor color() const { return m_variableValue; }
+ void setColor(const QColor &color);
+
+ // which theme colors are referencing this variable?
+ void addReference(ColorRole *t);
+ void removeReference(ColorRole *t);
+ QSet<ColorRole *> references() const;
+
+private:
+ explicit ColorVariable(const QColor &color, const QString &variableName = QString());
+ QColor m_variableValue;
+ QString m_variableName;
+ QSet<ColorRole *> m_references;
+};
+
+} // namespace ThemeEditor
+} // namespace Internal
+} // namespace Core
+
+#endif // COLORVARIABLE_H
diff --git a/src/plugins/coreplugin/themeeditor/sectionedtablemodel.cpp b/src/plugins/coreplugin/themeeditor/sectionedtablemodel.cpp
new file mode 100644
index 0000000000..8808dc428e
--- /dev/null
+++ b/src/plugins/coreplugin/themeeditor/sectionedtablemodel.cpp
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "sectionedtablemodel.h"
+
+#include <QSize>
+
+namespace Core {
+namespace Internal {
+namespace ThemeEditor {
+
+SectionedTableModel::SectionedTableModel(QObject *parent) :
+ QAbstractTableModel(parent)
+{
+}
+
+int SectionedTableModel::sectionHeader(int row) const
+{
+ int currRow = 0;
+ int i = 0;
+ do {
+ if (row == currRow)
+ return i;
+ currRow += sectionRowCount(i) + 1; //account for next header
+ ++i;
+ } while (i < sectionCount());
+ return -1;
+}
+
+int SectionedTableModel::inSectionBody(int row) const
+{
+ int currRow = 0;
+ int i = 0;
+ do {
+ ++currRow;
+ if (row >= currRow && row < currRow + sectionRowCount(i))
+ return i;
+ currRow += sectionRowCount(i);
+ ++i;
+ } while (i < sectionCount());
+ return -1;
+}
+
+int SectionedTableModel::modelToSectionRow(int row) const
+{
+ int currRow = 0;
+ for (int i = 0; i < sectionCount(); ++i) {
+ ++currRow;
+ if (row >= currRow && row < currRow + sectionRowCount(i))
+ return row-currRow;
+ currRow += sectionRowCount(i);
+ }
+ return row;
+}
+
+QSize SectionedTableModel::span(const QModelIndex &index) const
+{
+ if (sectionHeader(index.row()) >= 0 && index.column() == 0)
+ return QSize(1, columnCount(index));
+ return QSize(1, 1);
+}
+
+int SectionedTableModel::rowCount(const QModelIndex &index) const
+{
+ if (index.isValid())
+ return 0;
+
+ int r = 0;
+ for (int i = 0; i < sectionCount(); ++i)
+ r += sectionRowCount(i) + 1;
+ return r;
+}
+
+QVariant SectionedTableModel::data(const QModelIndex &index, int role) const
+{
+ int header = sectionHeader(index.row());
+ if (header >= 0)
+ return (index.column() == 0) ? sectionHeaderData(header, role)
+ : QVariant(QString());
+ return sectionBodyData(inSectionBody(index.row()),
+ modelToSectionRow(index.row()),
+ index.column(),
+ role);
+}
+
+Qt::ItemFlags SectionedTableModel::flags(const QModelIndex &index) const
+{
+ if (int h = sectionHeader(index.row()) >= 0)
+ return sectionHeaderFlags(h);
+ return sectionBodyFlags(inSectionBody(index.row()),
+ modelToSectionRow(index.row()),
+ index.column());
+}
+
+} // namespace ThemeEditor
+} // namespace Internal
+} // namespace Core
diff --git a/src/plugins/coreplugin/themeeditor/sectionedtablemodel.h b/src/plugins/coreplugin/themeeditor/sectionedtablemodel.h
new file mode 100644
index 0000000000..5706f3c775
--- /dev/null
+++ b/src/plugins/coreplugin/themeeditor/sectionedtablemodel.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef SECTIONEDTABLEMODEL_H
+#define SECTIONEDTABLEMODEL_H
+
+#include <QAbstractTableModel>
+
+namespace Core {
+namespace Internal {
+namespace ThemeEditor {
+
+class SectionedTableModel : public QAbstractTableModel
+{
+ Q_OBJECT
+
+public:
+ explicit SectionedTableModel(QObject *parent = 0);
+
+ virtual int sectionRowCount(int section) const = 0;
+ virtual QVariant sectionBodyData(int section, int row, int column, int role) const = 0;
+ virtual QVariant sectionHeaderData(int section, int role) const = 0;
+ virtual Qt::ItemFlags sectionBodyFlags(int section, int row, int column) const = 0;
+ virtual Qt::ItemFlags sectionHeaderFlags(int section) const = 0;
+ virtual int sectionCount() const = 0;
+ QSize span(const QModelIndex &index) const Q_DECL_OVERRIDE;
+
+ int inSectionBody(int row) const;
+ int modelToSectionRow(int row) const;
+ int sectionHeader(int row) const;
+
+protected:
+ int rowCount(const QModelIndex &index) const Q_DECL_OVERRIDE;
+ QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
+ Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE;
+};
+
+} // namespace ThemeEditor
+} // namespace Internal
+} // namespace Core
+
+#endif // SECTIONEDTABLEMODEL_H
diff --git a/src/plugins/coreplugin/themeeditor/themecolors.cpp b/src/plugins/coreplugin/themeeditor/themecolors.cpp
new file mode 100644
index 0000000000..2549d3e0cb
--- /dev/null
+++ b/src/plugins/coreplugin/themeeditor/themecolors.cpp
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "themecolors.h"
+#include "colorvariable.h"
+#include <utils/qtcassert.h>
+
+namespace Core {
+namespace Internal {
+namespace ThemeEditor {
+
+QSharedPointer<ColorVariable> ThemeColors::createVariable(const QColor &variableColor, const QString &variableName)
+{
+ ColorVariable::Ptr var(new ColorVariable(variableColor, variableName));
+ insert(var);
+ return var;
+}
+
+ColorRole::Ptr ThemeColors::createRole(const QString &roleName, QSharedPointer<ColorVariable> colorVariable)
+{
+ ColorRole::Ptr role(new ColorRole(roleName, colorVariable));
+ insert(role);
+ return role;
+}
+
+void ThemeColors::insert(ColorRole::Ptr color)
+{
+ m_colorRoles.append(color);
+}
+
+void ThemeColors::insert(ColorVariable::Ptr color)
+{
+ m_colorVariables.insert(color);
+}
+
+QSet<QSharedPointer<ColorVariable> > ThemeColors::colorVariables()
+{
+ return m_colorVariables;
+}
+
+void ThemeColors::removeVariable(QSharedPointer<ColorVariable> variable)
+{
+ QTC_ASSERT(m_colorVariables.contains(variable), return);
+ m_colorVariables.remove(variable);
+}
+
+} // namespace ThemeEditor
+} // namespace Internal
+} // namespace Core
diff --git a/src/plugins/coreplugin/themeeditor/themecolors.h b/src/plugins/coreplugin/themeeditor/themecolors.h
new file mode 100644
index 0000000000..da47d6b213
--- /dev/null
+++ b/src/plugins/coreplugin/themeeditor/themecolors.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef THEMECOLORS_H
+#define THEMECOLORS_H
+
+#include "colorrole.h"
+
+#include <QSet>
+
+namespace Core {
+namespace Internal {
+namespace ThemeEditor {
+
+class ColorVariable;
+
+class ThemeColors
+{
+public:
+ typedef QSharedPointer<ThemeColors> Ptr;
+
+ int numColorRoles() const { return m_colorRoles.size(); }
+ ColorRole::Ptr const colorRole(int index) { return m_colorRoles.at(index); }
+
+ QSharedPointer<ColorVariable> createVariable(const QColor &variableColor, const QString &variableName = QString());
+ ColorRole::Ptr createRole(const QString &roleName, QSharedPointer<ColorVariable> colorVariable);
+
+ QSet<QSharedPointer<ColorVariable> > colorVariables();
+
+ void removeVariable(QSharedPointer<ColorVariable> variable);
+
+private:
+ void insert(ColorRole::Ptr color);
+ void insert(QSharedPointer<ColorVariable> color);
+
+ QList<ColorRole::Ptr> m_colorRoles;
+ QSet<QSharedPointer<ColorVariable> > m_colorVariables;
+};
+
+} // namespace ThemeEditor
+} // namespace Internal
+} // namespace Core
+
+#endif // THEMECOLORS_H
diff --git a/src/plugins/coreplugin/themeeditor/themecolorstableview.cpp b/src/plugins/coreplugin/themeeditor/themecolorstableview.cpp
new file mode 100644
index 0000000000..07274b2062
--- /dev/null
+++ b/src/plugins/coreplugin/themeeditor/themecolorstableview.cpp
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "themecolorstableview.h"
+#include "themesettingsitemdelegate.h"
+#include "themesettingstablemodel.h"
+
+#include <QMouseEvent>
+
+namespace Core {
+namespace Internal {
+namespace ThemeEditor {
+
+ThemeColorsTableView::ThemeColorsTableView(QWidget *parent)
+ : QTreeView(parent)
+{
+}
+
+void ThemeColorsTableView::mousePressEvent(QMouseEvent *event)
+{
+ if (event->button() == Qt::LeftButton) {
+ QModelIndex index = indexAt(event->pos());
+ if (model()->flags(index) & Qt::ItemIsEditable && index.column() == 1) {
+ setCurrentIndex(index);
+ edit(index);
+ // TODO: only applies to editing colors
+ static_cast<ThemeSettingsItemDelegate *>(itemDelegate())->popupMenu();
+ }
+ }
+ QTreeView::mousePressEvent(event);
+}
+
+} // namespace ThemeEditor
+} // namespace Internal
+} // namespace Core
diff --git a/share/qtcreator/welcomescreen/widgets/CustomColors.qml b/src/plugins/coreplugin/themeeditor/themecolorstableview.h
index 5ee98e6f13..346caf250d 100644
--- a/share/qtcreator/welcomescreen/widgets/CustomColors.qml
+++ b/src/plugins/coreplugin/themeeditor/themecolorstableview.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
@@ -28,11 +28,28 @@
**
****************************************************************************/
-import QtQuick 2.1
+#ifndef THEMECOLORSTABLEVIEW_H
+#define THEMECOLORSTABLEVIEW_H
-QtObject {
- property color linkColor: "#328930"
- //property color linkColor: "#70b332"
- //property color strongForegroundColor: "#58595b"
- property color strongForegroundColor: "#328930"
-}
+#include <QTreeView>
+
+namespace Core {
+namespace Internal {
+namespace ThemeEditor {
+
+class ThemeColorsTableView : public QTreeView
+{
+ Q_OBJECT
+
+public:
+ ThemeColorsTableView(QWidget *parent = 0);
+
+protected:
+ void mousePressEvent(QMouseEvent *event);
+};
+
+} // namespace ThemeEditor
+} // namespace Internal
+} // namespace Core
+
+#endif // THEMECOLORSTABLEVIEW_H
diff --git a/src/plugins/coreplugin/themeeditor/themeeditorwidget.cpp b/src/plugins/coreplugin/themeeditor/themeeditorwidget.cpp
new file mode 100644
index 0000000000..4b7abdcb42
--- /dev/null
+++ b/src/plugins/coreplugin/themeeditor/themeeditorwidget.cpp
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "themeeditorwidget.h"
+#include "ui_themeeditorwidget.h"
+
+#include "colorvariable.h"
+#include "colorrole.h"
+#include "themecolors.h"
+#include "themesettingstablemodel.h"
+#include "themesettingsitemdelegate.h"
+
+#include <QAbstractButton>
+#include <QAbstractItemModel>
+#include <QColorDialog>
+#include <QDir>
+#include <QFileInfo>
+#include <QMetaEnum>
+#include <QSortFilterProxyModel>
+#include <QTimer>
+#include <QSharedPointer>
+#include <QWeakPointer>
+
+namespace Core {
+namespace Internal {
+namespace ThemeEditor {
+
+ThemeEditorWidget::ThemeEditorWidget(QWidget *parent) :
+ QWidget(parent),
+ m_ui(new Ui::ThemeEditorWidget),
+ m_readOnly(false),
+ m_model(0)
+{
+ m_ui->setupUi(this);
+
+ m_proxyModel = new QSortFilterProxyModel(this);
+ m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
+ m_proxyModel->setFilterKeyColumn(0);
+
+ m_ui->tableView->setModel(m_proxyModel);
+ ThemeSettingsItemDelegate *cbid = new ThemeSettingsItemDelegate(this);
+ m_ui->tableView->setItemDelegate(cbid);
+ connect(m_ui->filter, &QLineEdit::textChanged, m_proxyModel,
+ static_cast<void (QSortFilterProxyModel:: *)(const QString &)>(&QSortFilterProxyModel::setFilterRegExp));
+ connect(m_ui->tableView, &QAbstractItemView::doubleClicked, this, &ThemeEditorWidget::changeColor);
+}
+
+ThemeEditorWidget::~ThemeEditorWidget()
+{
+ delete m_ui;
+}
+
+void ThemeEditorWidget::changeColor(const QModelIndex &index)
+{
+ if (m_model->inSectionBody(index.row()) != ThemeSettingsTableModel::SectionColors)
+ return;
+ if (index.column() == 1)
+ return;
+
+ int row = m_model->modelToSectionRow(index.row());
+ ColorRole::Ptr themeColor = m_model->colors()->colorRole(row);
+
+ QColor currentColor = themeColor->colorVariable()->color();
+
+ // FIXME: 'currentColor' is correct, but QColorDialog won't show
+ // it as the correct initial color. Why?
+
+ QColorDialog dlg(this);
+ dlg.setOption(QColorDialog::ShowAlphaChannel);
+ dlg.setCurrentColor(currentColor);
+
+ const int customCount = QColorDialog::customCount();
+ for (int i = 0; i < customCount; ++i)
+ QColorDialog::setCustomColor(i, Qt::transparent); // invalid
+
+ int i = 0;
+ foreach (ColorVariable::Ptr namedColor, m_model->colors()->colorVariables())
+ QColorDialog::setCustomColor(i++, namedColor->color().toRgb());
+
+ int ret = dlg.exec();
+ if (ret == QDialog::Accepted) {
+ themeColor->colorVariable()->setColor(dlg.currentColor());
+ m_model->markEverythingChanged();
+ }
+}
+
+void ThemeEditorWidget::setReadOnly(bool readOnly)
+{
+ m_readOnly = readOnly;
+ m_ui->tableView->setEnabled(!readOnly);
+ m_ui->filter->setEnabled(!readOnly);
+}
+
+void ThemeEditorWidget::initFrom(Utils::Theme *theme)
+{
+ if (m_model) {
+ m_model->setParent(0);
+ delete m_model;
+ }
+ m_model = new ThemeSettingsTableModel(this);
+ m_model->initFrom(theme);
+ m_proxyModel->setSourceModel(m_model);
+
+ m_ui->tableView->setColumnWidth(0, 400);
+ m_ui->tableView->setColumnWidth(1, 300);
+}
+
+ThemeSettingsTableModel *ThemeEditorWidget::model()
+{
+ return m_model;
+}
+
+} // namespace ThemeEditor
+} // namespace Internal
+} // namespace Core
diff --git a/src/plugins/coreplugin/themeeditor/themeeditorwidget.h b/src/plugins/coreplugin/themeeditor/themeeditorwidget.h
new file mode 100644
index 0000000000..ea759882fc
--- /dev/null
+++ b/src/plugins/coreplugin/themeeditor/themeeditorwidget.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef THEMEEDITORWIDGET_H
+#define THEMEEDITORWIDGET_H
+
+#include <QWidget>
+
+QT_BEGIN_NAMESPACE
+class QSortFilterProxyModel;
+QT_END_NAMESPACE
+
+namespace Utils { class Theme; }
+
+namespace Core {
+namespace Internal {
+namespace ThemeEditor {
+
+namespace Ui { class ThemeEditorWidget; }
+
+class ThemeSettingsTableModel;
+
+class ThemeEditorWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit ThemeEditorWidget(QWidget *parent = 0);
+ ~ThemeEditorWidget();
+
+ void initFrom(Utils::Theme *theme);
+
+ ThemeSettingsTableModel *model();
+
+ void setReadOnly(bool readOnly);
+
+private slots:
+ void changeColor(const QModelIndex &index);
+
+private:
+ Ui::ThemeEditorWidget *m_ui;
+ bool m_readOnly;
+ ThemeSettingsTableModel *m_model;
+ QSortFilterProxyModel *m_proxyModel;
+};
+
+} // namespace ThemeEditor
+} // namespace Internal
+} // namespace Core
+
+#endif // THEMEEDITORWIDGET_H
diff --git a/src/plugins/coreplugin/themeeditor/themeeditorwidget.ui b/src/plugins/coreplugin/themeeditor/themeeditorwidget.ui
new file mode 100644
index 0000000000..41022847f5
--- /dev/null
+++ b/src/plugins/coreplugin/themeeditor/themeeditorwidget.ui
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Core::Internal::ThemeEditor::ThemeEditorWidget</class>
+ <widget class="QWidget" name="Core::Internal::ThemeEditor::ThemeEditorWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Theme Editor</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Filter:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="filter"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="Core::Internal::ThemeEditor::ThemeColorsTableView" name="tableView"/>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>Core::Internal::ThemeEditor::ThemeColorsTableView</class>
+ <extends>QTableView</extends>
+ <header location="global">coreplugin/themeeditor/themecolorstableview.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/coreplugin/themeeditor/themesettingsitemdelegate.cpp b/src/plugins/coreplugin/themeeditor/themesettingsitemdelegate.cpp
new file mode 100644
index 0000000000..c21766d989
--- /dev/null
+++ b/src/plugins/coreplugin/themeeditor/themesettingsitemdelegate.cpp
@@ -0,0 +1,227 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "themesettingsitemdelegate.h"
+
+#include "colorvariable.h"
+#include "themesettingstablemodel.h"
+#include <utils/qtcassert.h>
+#include <utils/theme/theme.h>
+
+#include <QAbstractProxyModel>
+#include <QComboBox>
+#include <QEvent>
+#include <QInputDialog>
+#include <QMetaEnum>
+
+using namespace Utils;
+
+static QAbstractItemModel *sourceModel(QAbstractItemModel *model)
+{
+ if (QAbstractProxyModel *m = qobject_cast<QAbstractProxyModel *>(model))
+ return m->sourceModel();
+ return model;
+}
+
+static const QAbstractItemModel *sourceModel(const QAbstractItemModel *model)
+{
+ if (const QAbstractProxyModel *m = qobject_cast<const QAbstractProxyModel *>(model))
+ return m->sourceModel();
+ return model;
+}
+
+static QIcon makeIcon(const QColor &color)
+{
+ QImage img(QSize(24,24), QImage::Format_ARGB32);
+ img.fill(color.rgba());
+ QIcon ico = QIcon(QPixmap::fromImage(img));
+ return ico;
+}
+
+namespace Core {
+namespace Internal {
+namespace ThemeEditor {
+
+ThemeSettingsItemDelegate::ThemeSettingsItemDelegate(QObject *parent)
+ : QStyledItemDelegate(parent),
+ m_comboBox(0)
+{
+}
+
+QWidget *ThemeSettingsItemDelegate::createColorEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ const ThemeSettingsTableModel *model = qobject_cast<const ThemeSettingsTableModel*>(sourceModel(index.model()));
+
+ Q_UNUSED(option);
+ const int row = model->modelToSectionRow(index.row());
+ QComboBox *cb = new QComboBox(parent);
+ ColorRole::Ptr colorRole = model->m_colors->colorRole(row);
+
+ const bool isUnnamed = colorRole->colorVariable()->variableName().isEmpty();
+ const QColor currentColor = colorRole->colorVariable()->color();
+
+ int k = 0;
+ if (isUnnamed) {
+ cb->addItem(makeIcon(currentColor), tr("<unnamed> (current)"));
+ ++k;
+ } else {
+ cb->addItem(makeIcon(currentColor),
+ colorRole->colorVariable()->variableName()+QString(tr(" (current)")));
+ ++k;
+ }
+
+ foreach (ColorVariable::Ptr namedColor, model->m_colors->colorVariables()) {
+ if (namedColor->variableName().isEmpty())
+ continue;
+ if (colorRole->colorVariable() == namedColor) {
+ continue;
+ } else {
+ cb->addItem(makeIcon(namedColor->color()), namedColor->variableName());
+ m_actions[k++] = qMakePair(Action_ChooseNamedColor, namedColor);
+ }
+ }
+
+ if (!isUnnamed) {
+ cb->addItem(tr("Make unnamed"));
+ m_actions[k++] = qMakePair(Action_MakeUnnamed, QSharedPointer<ColorVariable>(0));
+ }
+ cb->addItem(tr("Create new name..."));
+ m_actions[k++] = qMakePair(Action_CreateNew, QSharedPointer<ColorVariable>(0));
+
+ connect(cb, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ this, [this, cb]() {
+ ThemeSettingsItemDelegate *me = const_cast<ThemeSettingsItemDelegate *>(this);
+ emit me->commitData(cb);
+ emit me->closeEditor(cb);
+ });
+
+ m_comboBox = cb;
+ return cb;
+}
+
+QWidget *ThemeSettingsItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ const ThemeSettingsTableModel *model = qobject_cast<const ThemeSettingsTableModel*>(sourceModel(index.model()));
+
+ const int section = model->inSectionBody(index.row());
+ QTC_ASSERT(section >= 0, return 0);
+
+ switch (section) {
+ case ThemeSettingsTableModel::SectionWidgetStyle: {
+ QComboBox *cb = new QComboBox(parent);
+ QMetaEnum e = Theme::staticMetaObject.enumerator(Theme::staticMetaObject.indexOfEnumerator("WidgetStyle"));
+ for (int i = 0, total = e.keyCount(); i < total; ++i)
+ cb->addItem(QLatin1String(e.key(i)));
+ connect(cb, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
+ this, [this, cb]() {
+ ThemeSettingsItemDelegate *me = const_cast<ThemeSettingsItemDelegate *>(this);
+ emit me->commitData(cb);
+ emit me->closeEditor(cb);
+ });
+ m_comboBox = cb;
+ return cb;
+ }
+ case ThemeSettingsTableModel::SectionColors: {
+ return createColorEditor(parent, option, index);
+ }
+ case ThemeSettingsTableModel::SectionFlags: {
+ return QStyledItemDelegate::createEditor(parent, option, index);
+ }
+ default: {
+ qWarning("unhandled section");
+ return 0;
+ }
+ } // switch
+}
+
+void ThemeSettingsItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
+{
+ QStyledItemDelegate::setEditorData(editor, index);
+}
+
+void ThemeSettingsItemDelegate::setModelData (QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
+{
+ ThemeSettingsTableModel *themeSettingsModel = qobject_cast<ThemeSettingsTableModel *>(sourceModel(model));
+
+ const int row = themeSettingsModel->modelToSectionRow(index.row());
+ const int section = themeSettingsModel->inSectionBody(index.row());
+
+ switch (section) {
+ case ThemeSettingsTableModel::SectionWidgetStyle:
+ if (QComboBox *cb = qobject_cast<QComboBox *>(editor))
+ themeSettingsModel->m_widgetStyle = static_cast<Theme::WidgetStyle>(cb->currentIndex());
+ return;
+ case ThemeSettingsTableModel::SectionColors: {
+ if (QComboBox *cb = qobject_cast<QComboBox *>(editor)) {
+ ColorRole::Ptr themeColor = themeSettingsModel->m_colors->colorRole(row);
+
+ Action act = m_actions[cb->currentIndex()].first;
+ ColorVariable::Ptr previousVariable = themeColor->colorVariable();
+ ColorVariable::Ptr newVariable = m_actions[cb->currentIndex()].second;
+
+ if (act == Action_NoAction) {
+ return;
+ } else if (act == Action_ChooseNamedColor) {
+ previousVariable->removeReference(themeColor.data());
+ QTC_ASSERT(newVariable, return);
+ themeColor->assignColorVariable(newVariable);
+ } else if (act == Action_MakeUnnamed) {
+ previousVariable->removeReference(themeColor.data());
+ if (previousVariable->references().size() == 0)
+ themeSettingsModel->m_colors->removeVariable(previousVariable);
+ ColorVariable::Ptr anonymousColor = themeSettingsModel->m_colors->createVariable(previousVariable->color());
+ themeColor->assignColorVariable(anonymousColor);
+ } else if (act == Action_CreateNew) {
+ QString name = QInputDialog::getText(editor, tr("New variable name"), tr("Variable name:"));
+ if (!name.isEmpty()) {
+ previousVariable->removeReference(themeColor.data());
+
+ // TODO: check for name collision
+ ColorVariable::Ptr newVariable = themeSettingsModel->m_colors->createVariable(previousVariable->color(), name);
+
+ themeColor->assignColorVariable(newVariable);
+ }
+ }
+ }
+ return;
+ }
+ default:
+ return QStyledItemDelegate::setModelData(editor, model, index);
+ }
+}
+
+void ThemeSettingsItemDelegate::popupMenu()
+{
+ m_comboBox->showPopup();
+}
+
+} // namespace ThemeEditor
+} // namespace Internal
+} // namespace Core
diff --git a/src/plugins/coreplugin/themeeditor/themesettingsitemdelegate.h b/src/plugins/coreplugin/themeeditor/themesettingsitemdelegate.h
new file mode 100644
index 0000000000..02023284ba
--- /dev/null
+++ b/src/plugins/coreplugin/themeeditor/themesettingsitemdelegate.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef THEMESETTINGSITEMDELEGATE_H
+#define THEMESETTINGSITEMDELEGATE_H
+
+#include "themecolors.h"
+#include "colorvariable.h"
+
+#include <QStyledItemDelegate>
+
+QT_BEGIN_NAMESPACE
+class QComboBox;
+QT_END_NAMESPACE
+
+namespace Core {
+namespace Internal {
+namespace ThemeEditor {
+
+class ThemeSettingsItemDelegate : public QStyledItemDelegate
+{
+ Q_OBJECT
+
+ enum Action {
+ Action_NoAction,
+ Action_ChooseNamedColor,
+ Action_MakeUnnamed,
+ Action_CreateNew
+ };
+
+public:
+ ThemeSettingsItemDelegate(QObject *parent);
+
+ QWidget *createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
+ void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE;
+ void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const Q_DECL_OVERRIDE;
+
+ void popupMenu();
+
+private:
+ QWidget *createColorEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
+
+ mutable QMap<int, QPair<Action, ColorVariable::Ptr> > m_actions;
+ mutable QComboBox *m_comboBox;
+};
+
+} // namespace ThemeEditor
+} // namespace Internal
+} // namespace Core
+
+#endif // THEMESETTINGSITEMDELEGATE_H
diff --git a/src/plugins/coreplugin/themeeditor/themesettingstablemodel.cpp b/src/plugins/coreplugin/themeeditor/themesettingstablemodel.cpp
new file mode 100644
index 0000000000..e3eebce56e
--- /dev/null
+++ b/src/plugins/coreplugin/themeeditor/themesettingstablemodel.cpp
@@ -0,0 +1,297 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "themesettingstablemodel.h"
+#include "colorvariable.h"
+#include <utils/qtcassert.h>
+#include <utils/theme/theme.h>
+#include <utils/theme/theme_p.h>
+
+#include <QApplication>
+#include <QImage>
+#include <QMetaEnum>
+#include <QPainter>
+#include <QPalette>
+
+using namespace Utils;
+
+namespace Core {
+namespace Internal {
+namespace ThemeEditor {
+
+ThemeSettingsTableModel::ThemeSettingsTableModel(QObject *parent)
+ : SectionedTableModel(parent),
+ m_colors(new ThemeColors),
+ m_hasChanges(false)
+{
+}
+
+int ThemeSettingsTableModel::columnCount(const QModelIndex &index) const
+{
+ Q_UNUSED(index);
+ return 2;
+}
+
+int ThemeSettingsTableModel::sectionRowCount(int section) const
+{
+ switch (static_cast<Section>(section)) {
+ case SectionWidgetStyle: return 1;
+ case SectionColors: return m_colors->numColorRoles();
+ case SectionFlags: return m_flags.size();
+ case SectionIconOverlays: return m_iconOverlays.size();
+ default: return 0;
+ }
+}
+
+QVariant ThemeSettingsTableModel::sectionBodyData(int section, int row, int column, int role) const
+{
+ auto makeDecoration = [](const QColor &c) -> QImage {
+ QImage img(QSize(32,32), QImage::Format_ARGB32);
+ img.fill(Qt::transparent);
+ QPainter p(&img);
+ p.fillRect(QRect(4,4,24,24), c);
+ return img;
+ };
+
+ switch (static_cast<Section>(section)) {
+ case SectionWidgetStyle: {
+ if (role != Qt::DisplayRole)
+ return QVariant();
+ if (column == 0)
+ return QLatin1String("WidgetStyle");
+ else
+ return m_widgetStyle == Theme::StyleFlat ? QLatin1String("StyleFlat") : QLatin1String("StyleDefault");
+ }
+ case SectionColors: {
+ ColorRole::Ptr colorRole = m_colors->colorRole(row);
+ if (column == 0 && role == Qt::DecorationRole)
+ return QVariant::fromValue(makeDecoration(colorRole->colorVariable()->color()));
+ if (role == Qt::DisplayRole) {
+ if (column == 0)
+ return colorRole->roleName();
+ else
+ return colorRole->colorVariable()->variableName();
+ }
+ return QVariant();
+ }
+ case SectionFlags: {
+ if (column == 0 && role == Qt::DisplayRole)
+ return m_flags[row].first;
+ else if (column == 1 && role == Qt::CheckStateRole)
+ return m_flags[row].second ? Qt::Checked : Qt::Unchecked;
+ else if (column == 0 && role == Qt::DecorationRole)
+ return QVariant::fromValue(makeDecoration(Qt::transparent));
+ return QVariant();
+ }
+ case SectionIconOverlays: {
+ if (column == 0 && role == Qt::DisplayRole)
+ return m_iconOverlays[row].first;
+ else if (column == 1 && role == Qt::DisplayRole)
+ return m_iconOverlays[row].second;
+ else if (column == 0 && role == Qt::DecorationRole)
+ return QVariant::fromValue(makeDecoration(Qt::transparent));
+ return QVariant();
+ }
+ default:
+ return QVariant();
+ }
+}
+
+QVariant ThemeSettingsTableModel::sectionHeaderData(int section, int role) const
+{
+ if (role == Qt::DisplayRole) {
+ switch (static_cast<Section>(section)) {
+ case SectionWidgetStyle: return tr("Widget Style");
+ case SectionColors: return tr("Colors");
+ case SectionFlags: return tr("Flags");
+ case SectionIconOverlays: return tr("Icon Overlays");
+ default: return QString();
+ }
+ }
+ if (role == Qt::FontRole) {
+ QFont font;
+ font.setPointSizeF(font.pointSizeF() * 1.25);
+ font.setBold(true);
+ return font;
+ }
+ if (role == Qt::SizeHintRole)
+ return QSize(50, 50);
+ return QVariant();
+}
+
+Qt::ItemFlags ThemeSettingsTableModel::sectionBodyFlags(int section, int row, int column) const
+{
+ Q_UNUSED(row);
+ switch (static_cast<Section>(section)) {
+ case SectionWidgetStyle:
+ return (column == 0) ? Qt::ItemIsEnabled
+ : Qt::ItemIsEnabled | Qt::ItemIsEditable;
+ case SectionColors:
+ return (column == 0) ? Qt::ItemIsEnabled
+ : Qt::ItemIsEnabled | Qt::ItemIsEditable;
+ case SectionFlags:
+ return (column == 0) ? Qt::ItemIsEnabled
+ : Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
+ case SectionIconOverlays:
+ return Qt::ItemIsEnabled;
+ default: return Qt::ItemIsEnabled;
+ }
+}
+
+bool ThemeSettingsTableModel::setData(const QModelIndex &idx, const QVariant &value, int role)
+{
+ m_hasChanges = true;
+ Q_UNUSED(role);
+
+ int section = inSectionBody(idx.row());
+ int row = modelToSectionRow(idx.row());
+ switch (static_cast<Section>(section)) {
+ case SectionFlags: {
+ Qt::CheckState checkState = static_cast<Qt::CheckState>(value.toInt());
+ bool checked = checkState == Qt::Checked;
+ m_flags[row].second = checked;
+ emit dataChanged(idx, idx);
+ return true;
+ }
+ default: {
+ // don't bother tracking changes, just mark the whole table as changed
+ markEverythingChanged();
+ return true;
+ }
+ } // switch
+}
+
+void ThemeSettingsTableModel::markEverythingChanged()
+{
+ m_hasChanges = true;
+ QModelIndex i;
+ emit dataChanged(index(0, 0, i), index(rowCount(i), columnCount(i), i));
+}
+
+void ThemeSettingsTableModel::initFrom(Theme *theme)
+{
+ const QMetaObject &metaObject = Theme::staticMetaObject;
+ // Colors
+ {
+ QMetaEnum e = metaObject.enumerator(metaObject.indexOfEnumerator("ColorRole"));
+ QMap<QString, ColorVariable::Ptr> varLookup;
+ for (int i = 0, total = e.keyCount(); i < total; ++i) {
+ const QString key = QLatin1String(e.key(i));
+ QPair<QColor, QString> c = theme->d->colors[static_cast<Theme::ColorRole>(i)];
+ if (c.second.isEmpty()) {
+ ColorVariable::Ptr v = colors()->createVariable(c.first);
+ colors()->createRole(key, v);
+ } else if (varLookup.contains(c.second)) {
+ colors()->createRole(key, varLookup[c.second]);
+ } else {
+ ColorVariable::Ptr v = colors()->createVariable(c.first, c.second);
+ colors()->createRole(key, v);
+ varLookup[c.second] = v;
+ }
+ }
+ }
+ // Flags
+ {
+ QMetaEnum e = metaObject.enumerator(metaObject.indexOfEnumerator("Flag"));
+ for (int i = 0, total = e.keyCount(); i < total; ++i) {
+ const QString key = QLatin1String(e.key(i));
+ m_flags.append(qMakePair(key, theme->flag(static_cast<Theme::Flag>(i))));
+ }
+ }
+ // IconOverlays
+ {
+ QMetaEnum e = metaObject.enumerator(metaObject.indexOfEnumerator("MimeType"));
+ for (int i = 0, total = e.keyCount(); i < total; ++i) {
+ const QString key = QLatin1String(e.key(i));
+ m_iconOverlays.append(qMakePair(key, theme->iconOverlay(static_cast<Theme::MimeType>(i))));
+ }
+ }
+
+ m_widgetStyle = theme->widgetStyle();
+ m_name = theme->d->name;
+}
+
+void ThemeSettingsTableModel::toTheme(Theme *t) const
+{
+ ThemePrivate *theme = t->d;
+ // Colors
+ {
+ QMetaEnum e = Theme::staticMetaObject.enumerator(Theme::staticMetaObject.indexOfEnumerator("ColorRole"));
+ for (int i = 0, total = e.keyCount(); i < total; ++i) {
+ ColorRole::Ptr role = colors()->colorRole(i);
+ ColorVariable::Ptr var = role->colorVariable();
+ theme->colors[i] = qMakePair(var->color(), var->variableName());
+ }
+ }
+ // Flags
+ {
+ QTC_ASSERT(theme->flags.size() == m_flags.size(), return);
+ for (int i = 0; i < theme->flags.size(); ++i)
+ theme->flags[i] = m_flags[i].second;
+ }
+ // IconOveralys
+ {
+ const int nOverlays = theme->iconOverlays.size();
+ QTC_ASSERT(nOverlays == m_iconOverlays.size(), return);
+ for (int i = 0; i < nOverlays; ++i)
+ theme->iconOverlays[i] = m_iconOverlays[i].second;
+ }
+
+ theme->widgetStyle = m_widgetStyle;
+ theme->name = m_name;
+ emit t->changed();
+}
+
+Qt::ItemFlags ThemeSettingsTableModel::sectionHeaderFlags(int section) const
+{
+ Q_UNUSED(section);
+ return Qt::ItemIsEnabled;
+}
+
+int ThemeSettingsTableModel::sectionCount() const
+{
+ return SectionInvalid;
+}
+
+QVariant ThemeSettingsTableModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (role == Qt::DisplayRole) {
+ if (orientation == Qt::Horizontal) {
+ if (section == 0)
+ return tr("Role");
+ return tr("Value");
+ }
+ }
+ return QVariant();
+}
+
+} // namespace ThemeEditor
+} // namespace Internal
+} // namespace Core
diff --git a/src/plugins/coreplugin/themeeditor/themesettingstablemodel.h b/src/plugins/coreplugin/themeeditor/themesettingstablemodel.h
new file mode 100644
index 0000000000..7af96458cc
--- /dev/null
+++ b/src/plugins/coreplugin/themeeditor/themesettingstablemodel.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef THEMESETTINGSTABLEMODEL_H
+#define THEMESETTINGSTABLEMODEL_H
+
+#include <QAbstractTableModel>
+
+#include "themecolors.h"
+#include "sectionedtablemodel.h"
+#include <utils/theme/theme.h>
+
+namespace Core {
+namespace Internal {
+namespace ThemeEditor {
+
+class ThemeSettingsTableModel : public SectionedTableModel
+{
+ Q_OBJECT
+
+public:
+ friend class ThemeSettingsItemDelegate;
+
+ enum Section {
+ SectionWidgetStyle,
+ SectionColors,
+ SectionFlags,
+ SectionIconOverlays,
+ SectionInvalid // end
+ };
+
+ ThemeSettingsTableModel(QObject *parent = 0);
+
+ bool setData(const QModelIndex &index, const QVariant &value, int role) Q_DECL_OVERRIDE;
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const Q_DECL_OVERRIDE;
+ int columnCount(const QModelIndex &index) const Q_DECL_OVERRIDE;
+ int sectionRowCount(int section) const Q_DECL_OVERRIDE;
+ QVariant sectionBodyData(int section, int row, int column, int role) const Q_DECL_OVERRIDE;
+ QVariant sectionHeaderData(int section, int role) const Q_DECL_OVERRIDE;
+ Qt::ItemFlags sectionBodyFlags(int section, int row, int column) const Q_DECL_OVERRIDE;
+ Qt::ItemFlags sectionHeaderFlags(int section) const Q_DECL_OVERRIDE;
+ int sectionCount() const Q_DECL_OVERRIDE;
+
+ ThemeColors::Ptr colors() const { return m_colors; }
+
+ bool hasChanges() const { return m_hasChanges; }
+
+ void markEverythingChanged();
+
+ void initFrom(Utils::Theme *theme);
+ void toTheme(Utils::Theme *theme) const;
+
+ QString m_name;
+
+public:
+ ThemeColors::Ptr m_colors;
+ QList<QPair<QString, bool> > m_flags;
+ QList<QPair<QString, QString> > m_iconOverlays;
+ Utils::Theme::WidgetStyle m_widgetStyle;
+ bool m_hasChanges;
+};
+
+} // namespace ThemeEditor
+} // namespace Internal
+} // namespace Core
+
+#endif // THEMESETTINGSTABLEMODEL_H
diff --git a/src/plugins/coreplugin/themesettings.cpp b/src/plugins/coreplugin/themesettings.cpp
new file mode 100644
index 0000000000..c21dc4ad44
--- /dev/null
+++ b/src/plugins/coreplugin/themesettings.cpp
@@ -0,0 +1,465 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "themesettings.h"
+#include "coreconstants.h"
+#include "icore.h"
+#include "editormanager/editormanager_p.h"
+#include "themeeditor/themesettingstablemodel.h"
+
+#include <utils/qtcassert.h>
+
+#include <QDebug>
+#include <QDir>
+#include <QInputDialog>
+#include <QMessageBox>
+#include <QSettings>
+
+#include "ui_themesettings.h"
+
+using namespace Utils;
+
+namespace Core {
+namespace Internal {
+
+const char themeNameKey[] = "ThemeName";
+
+static QString customThemesPath()
+{
+ QString path = Core::ICore::userResourcePath();
+ path.append(QLatin1String("/themes/"));
+ return path;
+}
+
+static QString createThemeFileName(const QString &pattern)
+{
+ const QString stylesPath = customThemesPath();
+ QString baseFileName = stylesPath;
+ baseFileName += pattern;
+
+ // Find an available file name
+ int i = 1;
+ QString fileName;
+ do {
+ fileName = baseFileName.arg((i == 1) ? QString() : QString::number(i));
+ ++i;
+ } while (QFile::exists(fileName));
+
+ // Create the base directory when it doesn't exist
+ if (!QFile::exists(stylesPath) && !QDir().mkpath(stylesPath)) {
+ qWarning() << "Failed to create theme directory:" << stylesPath;
+ return QString();
+ }
+ return fileName;
+}
+
+
+struct ThemeEntry
+{
+ ThemeEntry() {}
+ ThemeEntry(const QString &fileName, bool readOnly):
+ m_fileName(fileName),
+ m_readOnly(readOnly)
+ { }
+
+ QString fileName() const { return m_fileName; }
+ QString name() const;
+ bool readOnly() const { return m_readOnly; }
+
+private:
+ QString m_fileName;
+ bool m_readOnly;
+};
+
+QString ThemeEntry::name() const
+{
+ QSettings settings(m_fileName, QSettings::IniFormat);
+ QString n = settings.value(QLatin1String(themeNameKey), QCoreApplication::tr("unnamed")).toString();
+ return m_readOnly ? QCoreApplication::tr("%1 (built-in)").arg(n) : n;
+}
+
+
+class ThemeListModel : public QAbstractListModel
+{
+public:
+ ThemeListModel(QObject *parent = 0):
+ QAbstractListModel(parent)
+ {
+ }
+
+ int rowCount(const QModelIndex &parent) const
+ {
+ return parent.isValid() ? 0 : m_themes.size();
+ }
+
+ QVariant data(const QModelIndex &index, int role) const
+ {
+ if (role == Qt::DisplayRole)
+ return m_themes.at(index.row()).name();
+ return QVariant();
+ }
+
+ void removeTheme(int index)
+ {
+ beginRemoveRows(QModelIndex(), index, index);
+ m_themes.removeAt(index);
+ endRemoveRows();
+ }
+
+ void setThemes(const QList<ThemeEntry> &themes)
+ {
+ beginResetModel();
+ m_themes = themes;
+ endResetModel();
+ }
+
+ const ThemeEntry &themeAt(int index) const
+ {
+ return m_themes.at(index);
+ }
+
+private:
+ QList<ThemeEntry> m_themes;
+};
+
+
+class ThemeSettingsPrivate
+{
+public:
+ ThemeSettingsPrivate();
+ ~ThemeSettingsPrivate();
+
+public:
+ ThemeListModel *m_themeListModel;
+ bool m_refreshingThemeList;
+ Ui::ThemeSettings *m_ui;
+ QPointer<QWidget> m_widget;
+ ThemeEntry m_currentTheme;
+};
+
+ThemeSettingsPrivate::ThemeSettingsPrivate()
+ : m_themeListModel(new ThemeListModel)
+ , m_refreshingThemeList(false)
+ , m_ui(0)
+{
+ m_currentTheme = ThemeEntry(creatorTheme()->fileName(), true);
+}
+
+ThemeSettingsPrivate::~ThemeSettingsPrivate()
+{
+ delete m_themeListModel;
+}
+
+ThemeSettings::ThemeSettings()
+{
+ setId(Core::Constants::SETTINGS_ID_ENVIRONMENT);
+ setDisplayName(tr("Theme"));
+ setCategory(Core::Constants::SETTINGS_CATEGORY_CORE);
+ setDisplayCategory(QCoreApplication::translate("Core", Core::Constants::SETTINGS_TR_CATEGORY_CORE));
+ setCategoryIcon(QLatin1String(Core::Constants::SETTINGS_CATEGORY_CORE_ICON));
+
+ d = new ThemeSettingsPrivate();
+}
+
+ThemeSettings::~ThemeSettings()
+{
+ delete d;
+}
+
+void ThemeSettings::refreshThemeList()
+{
+ QList<ThemeEntry> themes;
+
+ QString resourcePath = Core::ICore::resourcePath();
+ QDir themeDir(resourcePath + QLatin1String("/themes"));
+ themeDir.setNameFilters(QStringList() << QLatin1String("*.creatortheme"));
+ themeDir.setFilter(QDir::Files);
+
+ int selected = 0;
+
+ QStringList themeList = themeDir.entryList();
+ QString defaultTheme = QFileInfo(defaultThemeFileName()).fileName();
+ if (themeList.removeAll(defaultTheme))
+ themeList.prepend(defaultTheme);
+ foreach (const QString &file, themeList) {
+ const QString fileName = themeDir.absoluteFilePath(file);
+ if (d->m_currentTheme.fileName() == fileName)
+ selected = themes.size();
+ themes.append(ThemeEntry(fileName, true));
+ }
+
+ if (themes.isEmpty())
+ qWarning() << "Warning: no themes found in path:" << themeDir.path();
+
+ themeDir.setPath(customThemesPath());
+ foreach (const QString &file, themeDir.entryList()) {
+ const QString fileName = themeDir.absoluteFilePath(file);
+ if (d->m_currentTheme.fileName() == fileName)
+ selected = themes.size();
+ themes.append(ThemeEntry(fileName, false));
+ }
+
+ d->m_currentTheme = themes[selected];
+
+ d->m_refreshingThemeList = true;
+ d->m_themeListModel->setThemes(themes);
+ d->m_ui->themeComboBox->setCurrentIndex(selected);
+ d->m_refreshingThemeList = false;
+}
+
+QString ThemeSettings::defaultThemeFileName(const QString &fileName)
+{
+ QString defaultScheme = Core::ICore::resourcePath();
+ defaultScheme += QLatin1String("/themes/");
+
+ if (!fileName.isEmpty() && QFile::exists(defaultScheme + fileName))
+ defaultScheme += fileName;
+ else
+ defaultScheme += QLatin1String("default.creatortheme");
+
+ return defaultScheme;
+}
+
+void ThemeSettings::themeSelected(int index)
+{
+ bool readOnly = true;
+ if (index != -1) {
+ // Check whether we're switching away from a changed theme
+ if (!d->m_refreshingThemeList)
+ maybeSaveTheme();
+
+ const ThemeEntry &entry = d->m_themeListModel->themeAt(index);
+ readOnly = entry.readOnly();
+ d->m_currentTheme = entry;
+
+ QSettings settings(entry.fileName(), QSettings::IniFormat);
+ Theme theme;
+ theme.readSettings(settings);
+ d->m_ui->editor->initFrom(&theme);
+ }
+ d->m_ui->copyButton->setEnabled(index != -1);
+ d->m_ui->deleteButton->setEnabled(!readOnly);
+ d->m_ui->renameButton->setEnabled(!readOnly);
+ d->m_ui->editor->setReadOnly(readOnly);
+}
+
+QWidget *ThemeSettings::widget()
+{
+ if (!d->m_widget) {
+ d->m_widget = new QWidget;
+ d->m_ui = new Ui::ThemeSettings();
+ d->m_ui->setupUi(d->m_widget);
+ d->m_ui->themeComboBox->setModel(d->m_themeListModel);
+
+ connect(d->m_ui->themeComboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ this, &ThemeSettings::themeSelected);
+ connect(d->m_ui->copyButton, &QAbstractButton::clicked, this, &ThemeSettings::copyTheme);
+ connect(d->m_ui->renameButton, &QAbstractButton::clicked, this, &ThemeSettings::renameTheme);
+ connect(d->m_ui->deleteButton, &QAbstractButton::clicked, this, &ThemeSettings::confirmDeleteTheme);
+
+ refreshThemeList();
+ }
+ return d->m_widget;
+}
+
+void ThemeSettings::confirmDeleteTheme()
+{
+ const int index = d->m_ui->themeComboBox->currentIndex();
+ if (index == -1)
+ return;
+
+ const ThemeEntry &entry = d->m_themeListModel->themeAt(index);
+ if (entry.readOnly())
+ return;
+
+ QMessageBox *messageBox = new QMessageBox(QMessageBox::Warning,
+ tr("Delete Theme"),
+ tr("Are you sure you want to delete the theme '%1' permanently?").arg(entry.name()),
+ QMessageBox::Discard | QMessageBox::Cancel,
+ d->m_ui->deleteButton->window());
+
+ // Change the text and role of the discard button
+ QPushButton *deleteButton = static_cast<QPushButton*>(messageBox->button(QMessageBox::Discard));
+ deleteButton->setText(tr("Delete"));
+ messageBox->addButton(deleteButton, QMessageBox::AcceptRole);
+ messageBox->setDefaultButton(deleteButton);
+
+ connect(deleteButton, &QAbstractButton::clicked, messageBox, &QDialog::accept);
+ connect(messageBox, &QDialog::accepted, this, &ThemeSettings::deleteTheme);
+ messageBox->setAttribute(Qt::WA_DeleteOnClose);
+ messageBox->open();
+}
+
+void ThemeSettings::deleteTheme()
+{
+ const int index = d->m_ui->themeComboBox->currentIndex();
+ QTC_ASSERT(index != -1, return);
+
+ const ThemeEntry &entry = d->m_themeListModel->themeAt(index);
+ QTC_ASSERT(!entry.readOnly(), return);
+
+ if (QFile::remove(entry.fileName()))
+ d->m_themeListModel->removeTheme(index);
+}
+
+void ThemeSettings::copyTheme()
+{
+ QInputDialog *dialog = new QInputDialog(d->m_ui->copyButton->window());
+ dialog->setAttribute(Qt::WA_DeleteOnClose);
+ dialog->setInputMode(QInputDialog::TextInput);
+ dialog->setWindowTitle(tr("Copy Theme"));
+ dialog->setLabelText(tr("Theme name:"));
+
+ //TODO
+ //dialog->setTextValue(tr("%1 (copy)").arg(d_ptr->m_value.colorScheme().displayName()));
+
+ connect(dialog, &QInputDialog::textValueSelected, this, &ThemeSettings::copyThemeByName);
+ dialog->open();
+}
+
+void ThemeSettings::maybeSaveTheme()
+{
+ if (!d->m_ui->editor->model()->hasChanges())
+ return;
+
+ QMessageBox *messageBox = new QMessageBox(QMessageBox::Warning,
+ tr("Theme Changed"),
+ tr("The theme \"%1\" was modified, do you want to save the changes?")
+ .arg(d->m_currentTheme.name()),
+ QMessageBox::Discard | QMessageBox::Save,
+ d->m_ui->themeComboBox->window());
+
+ // Change the text of the discard button
+ QPushButton *discardButton = static_cast<QPushButton*>(messageBox->button(QMessageBox::Discard));
+ discardButton->setText(tr("Discard"));
+ messageBox->addButton(discardButton, QMessageBox::DestructiveRole);
+ messageBox->setDefaultButton(QMessageBox::Save);
+
+ if (messageBox->exec() == QMessageBox::Save) {
+ Theme newTheme;
+ d->m_ui->editor->model()->toTheme(&newTheme);
+ newTheme.writeSettings(d->m_currentTheme.fileName());
+ }
+}
+
+void ThemeSettings::renameTheme()
+{
+ int index = d->m_ui->themeComboBox->currentIndex();
+ if (index == -1)
+ return;
+ const ThemeEntry &entry = d->m_themeListModel->themeAt(index);
+
+ maybeSaveTheme();
+
+ QInputDialog *dialog = new QInputDialog(d->m_ui->renameButton->window());
+ dialog->setInputMode(QInputDialog::TextInput);
+ dialog->setWindowTitle(tr("Rename Theme"));
+ dialog->setLabelText(tr("Theme name:"));
+ dialog->setTextValue(d->m_ui->editor->model()->m_name);
+ int ret = dialog->exec();
+ QString newName = dialog->textValue();
+ delete dialog;
+
+ if (ret != QDialog::Accepted || newName.isEmpty())
+ return;
+
+ // overwrite file with new name
+ Theme newTheme;
+ d->m_ui->editor->model()->toTheme(&newTheme);
+ newTheme.setName(newName);
+ newTheme.writeSettings(entry.fileName());
+
+ refreshThemeList();
+}
+
+void ThemeSettings::copyThemeByName(const QString &name)
+{
+ int index = d->m_ui->themeComboBox->currentIndex();
+ if (index == -1)
+ return;
+
+ const ThemeEntry &entry = d->m_themeListModel->themeAt(index);
+
+ QString baseFileName = QFileInfo(entry.fileName()).completeBaseName();
+ baseFileName += QLatin1String("_copy%1.creatortheme");
+ QString fileName = createThemeFileName(baseFileName);
+
+ if (fileName.isEmpty())
+ return;
+
+ // Ask about saving any existing modifactions
+ maybeSaveTheme();
+
+ Theme newTheme;
+ d->m_ui->editor->model()->toTheme(&newTheme);
+ newTheme.setName(name);
+ newTheme.writeSettings(fileName);
+
+ d->m_currentTheme = ThemeEntry(fileName, true);
+
+ refreshThemeList();
+}
+
+void ThemeSettings::apply()
+{
+ if (!d->m_ui) // wasn't shown, can't be changed
+ return;
+
+ {
+ d->m_ui->editor->model()->toTheme(creatorTheme());
+ QPalette newPalette = creatorTheme()->palette(qApp->palette());
+ qApp->setPalette(newPalette);
+ foreach (QWidget *w, QApplication::topLevelWidgets())
+ w->update();
+ }
+
+ // save definition of theme
+ if (!d->m_currentTheme.readOnly()) {
+ Theme newTheme;
+ d->m_ui->editor->model()->toTheme(&newTheme);
+ newTheme.writeSettings(d->m_currentTheme.fileName());
+ }
+
+ // save filename of selected theme in global config
+ QSettings *settings = Core::ICore::settings();
+ settings->setValue(QLatin1String(Core::Constants::SETTINGS_THEME), d->m_currentTheme.fileName());
+}
+
+void ThemeSettings::finish()
+{
+ delete d->m_widget;
+ if (!d->m_ui) // page was never shown
+ return
+ delete d->m_ui;
+ d->m_ui = 0;
+}
+
+} // namespace Internal
+} // namespace Core
diff --git a/src/plugins/coreplugin/themesettings.h b/src/plugins/coreplugin/themesettings.h
new file mode 100644
index 0000000000..a204acd7a1
--- /dev/null
+++ b/src/plugins/coreplugin/themesettings.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef THEMESETTINGS_H
+#define THEMESETTINGS_H
+
+#include <coreplugin/dialogs/ioptionspage.h>
+
+namespace Core {
+namespace Internal {
+
+class ThemeSettingsPrivate;
+
+class ThemeSettings : public IOptionsPage
+{
+ Q_OBJECT
+
+public:
+ ThemeSettings();
+ ~ThemeSettings();
+
+ QWidget *widget();
+ void apply();
+ void finish();
+
+ static QString defaultThemeFileName(const QString &fileName = QString());
+
+private slots:
+ void themeSelected(int index);
+ void copyTheme();
+ void renameTheme();
+ void copyThemeByName(const QString &);
+ void confirmDeleteTheme();
+ void deleteTheme();
+ void maybeSaveTheme();
+
+private:
+ void refreshThemeList();
+ ThemeSettingsPrivate *d;
+};
+
+} // namespace Internal
+} // namespace Core
+
+#endif // THEMESETTINGS_H
diff --git a/src/plugins/coreplugin/themesettings.ui b/src/plugins/coreplugin/themesettings.ui
new file mode 100644
index 0000000000..80fce6544d
--- /dev/null
+++ b/src/plugins/coreplugin/themesettings.ui
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Core::Internal::ThemeSettings</class>
+ <widget class="QWidget" name="Core::Internal::ThemeSettings">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>527</width>
+ <height>359</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QComboBox" name="themeComboBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="renameButton">
+ <property name="text">
+ <string>Rename...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="copyButton">
+ <property name="text">
+ <string>Copy...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="deleteButton">
+ <property name="text">
+ <string>Delete</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="Core::Internal::ThemeEditor::ThemeEditorWidget" name="editor" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>Core::Internal::ThemeEditor::ThemeEditorWidget</class>
+ <extends>QWidget</extends>
+ <header location="global">coreplugin/themeeditor/themeeditorwidget.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources>
+ <include location="core.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/plugins/cppeditor/cppeditor.qrc b/src/plugins/cppeditor/cppeditor.qrc
index 6e5f83fba6..e3091a0d9b 100644
--- a/src/plugins/cppeditor/cppeditor.qrc
+++ b/src/plugins/cppeditor/cppeditor.qrc
@@ -4,5 +4,8 @@
<file>images/qt_h.png</file>
<file>CppEditor.mimetypes.xml</file>
<file>images/qt_c.png</file>
+ <file>images/dark_qt_cpp.png</file>
+ <file>images/dark_qt_h.png</file>
+ <file>images/dark_qt_c.png</file>
</qresource>
</RCC>
diff --git a/src/plugins/cppeditor/cppeditorplugin.cpp b/src/plugins/cppeditor/cppeditorplugin.cpp
index c02327802d..577ec4949a 100644
--- a/src/plugins/cppeditor/cppeditorplugin.cpp
+++ b/src/plugins/cppeditor/cppeditorplugin.cpp
@@ -59,11 +59,14 @@
#include <utils/hostosinfo.h>
+#include <utils/theme/theme.h>
+
#include <QCoreApplication>
#include <QStringList>
using namespace Core;
using namespace TextEditor;
+using namespace Utils;
namespace CppEditor {
namespace Internal {
@@ -103,9 +106,9 @@ public:
addHoverHandler(new CppHoverHandler);
if (!Utils::HostOsInfo::isMacHost() && !Utils::HostOsInfo::isWindowsHost()) {
- FileIconProvider::registerIconOverlayForMimeType(":/cppeditor/images/qt_cpp.png", Constants::CPP_SOURCE_MIMETYPE);
- FileIconProvider::registerIconOverlayForMimeType(":/cppeditor/images/qt_c.png", Constants::C_SOURCE_MIMETYPE);
- FileIconProvider::registerIconOverlayForMimeType(":/cppeditor/images/qt_h.png", Constants::CPP_HEADER_MIMETYPE);
+ FileIconProvider::registerIconOverlayForMimeType(creatorTheme()->iconOverlay(Theme::CppSourceMimetype).toLatin1().data(), Constants::CPP_SOURCE_MIMETYPE);
+ FileIconProvider::registerIconOverlayForMimeType(creatorTheme()->iconOverlay(Theme::CSourceMimetype).toLatin1().data(), Constants::C_SOURCE_MIMETYPE);
+ FileIconProvider::registerIconOverlayForMimeType(creatorTheme()->iconOverlay(Theme::CppHeaderMimetype).toLatin1().data(), Constants::CPP_HEADER_MIMETYPE);
}
}
};
diff --git a/src/plugins/cppeditor/images/dark_qt_c.png b/src/plugins/cppeditor/images/dark_qt_c.png
new file mode 100644
index 0000000000..269b5e3938
--- /dev/null
+++ b/src/plugins/cppeditor/images/dark_qt_c.png
Binary files differ
diff --git a/src/plugins/cppeditor/images/dark_qt_cpp.png b/src/plugins/cppeditor/images/dark_qt_cpp.png
new file mode 100644
index 0000000000..c809be82ab
--- /dev/null
+++ b/src/plugins/cppeditor/images/dark_qt_cpp.png
Binary files differ
diff --git a/src/plugins/cppeditor/images/dark_qt_h.png b/src/plugins/cppeditor/images/dark_qt_h.png
new file mode 100644
index 0000000000..1cf8eab6f9
--- /dev/null
+++ b/src/plugins/cppeditor/images/dark_qt_h.png
Binary files differ
diff --git a/src/plugins/help/helpplugin.cpp b/src/plugins/help/helpplugin.cpp
index b58557dff3..c686f7eec7 100644
--- a/src/plugins/help/helpplugin.cpp
+++ b/src/plugins/help/helpplugin.cpp
@@ -76,6 +76,7 @@
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
#include <utils/styledbar.h>
+#include <utils/theme/theme.h>
#include <QDir>
#include <QFileInfo>
@@ -101,6 +102,7 @@ static const char kExternalWindowStateKey[] = "Help/ExternalWindowState";
#define IMAGEPATH ":/help/images/"
using namespace Core;
+using namespace Utils;
HelpPlugin::HelpPlugin()
: m_mode(0),
@@ -565,8 +567,13 @@ void HelpPlugin::showContextHelp()
// No link found or no context object
viewer->setSource(QUrl(Help::Constants::AboutBlank));
viewer->setHtml(tr("<html><head><title>No Documentation</title>"
- "</head><body><br/><center><b>%1</b><br/>No documentation "
- "available.</center></body></html>").arg(idFromContext));
+ "</head><body><br/><center>"
+ "<font color=\"%1\"><b>%2</b></font><br/>"
+ "<font color=\"%3\">No documentation available.</font>"
+ "</center></body></html>")
+ .arg(creatorTheme()->color(Theme::TextColorNormal).name())
+ .arg(idFromContext)
+ .arg(creatorTheme()->color(Theme::TextColorNormal).name()));
} else {
const QUrl &oldSource = viewer->source();
if (source != oldSource) {
diff --git a/src/plugins/projectexplorer/doubletabwidget.cpp b/src/plugins/projectexplorer/doubletabwidget.cpp
index c6e360f459..8c00a81ef7 100644
--- a/src/plugins/projectexplorer/doubletabwidget.cpp
+++ b/src/plugins/projectexplorer/doubletabwidget.cpp
@@ -32,6 +32,7 @@
#include "ui_doubletabwidget.h"
#include <utils/stylehelper.h>
+#include <utils/theme/theme.h>
#include <QRect>
#include <QPainter>
@@ -42,6 +43,7 @@
#include <QDebug>
using namespace ProjectExplorer::Internal;
+using namespace Utils;
static const int MIN_LEFT_MARGIN = 50;
static const int MARGIN = 12;
@@ -53,35 +55,45 @@ static const int OVERFLOW_DROPDOWN_WIDTH = Utils::StyleHelper::navigationWidgetH
static void drawFirstLevelSeparator(QPainter *painter, QPoint top, QPoint bottom)
{
QLinearGradient grad(top, bottom);
- grad.setColorAt(0, QColor(255, 255, 255, 20));
- grad.setColorAt(0.4, QColor(255, 255, 255, 60));
- grad.setColorAt(0.7, QColor(255, 255, 255, 50));
- grad.setColorAt(1, QColor(255, 255, 255, 40));
- painter->setPen(QPen(grad, 0));
- painter->drawLine(top, bottom);
- grad.setColorAt(0, QColor(0, 0, 0, 30));
- grad.setColorAt(0.4, QColor(0, 0, 0, 70));
- grad.setColorAt(0.7, QColor(0, 0, 0, 70));
- grad.setColorAt(1, QColor(0, 0, 0, 40));
- painter->setPen(QPen(grad, 0));
- painter->drawLine(top - QPoint(1,0), bottom - QPoint(1,0));
+ if (creatorTheme()->widgetStyle() == Theme::StyleDefault) {
+ grad.setColorAt(0, QColor(255, 0, 255, 20));
+ grad.setColorAt(0.4, QColor(255, 0, 255, 60));
+ grad.setColorAt(0.7, QColor(255, 0, 255, 50));
+ grad.setColorAt(1, QColor(255, 0, 255, 40));
+ painter->setPen(QPen(grad, 0));
+ painter->drawLine(top, bottom);
+ grad.setColorAt(0, QColor(0, 0, 0, 30));
+ grad.setColorAt(0.4, QColor(0, 0, 0, 70));
+ grad.setColorAt(0.7, QColor(0, 0, 0, 70));
+ grad.setColorAt(1, QColor(0, 0, 0, 40));
+ painter->setPen(QPen(grad, 0));
+ painter->drawLine(top - QPoint(1,0), bottom - QPoint(1,0));
+ } else {
+ painter->setPen(QPen(creatorTheme()->color(Theme::DoubleTabWidget1stSeparatorColor), 0));
+ painter->drawLine(top, bottom);
+ }
}
static void drawSecondLevelSeparator(QPainter *painter, QPoint top, QPoint bottom)
{
QLinearGradient grad(top, bottom);
- grad.setColorAt(0, QColor(255, 255, 255, 0));
- grad.setColorAt(0.4, QColor(255, 255, 255, 100));
- grad.setColorAt(0.7, QColor(255, 255, 255, 100));
- grad.setColorAt(1, QColor(255, 255, 255, 0));
- painter->setPen(QPen(grad, 0));
- painter->drawLine(top, bottom);
- grad.setColorAt(0, QColor(0, 0, 0, 0));
- grad.setColorAt(0.4, QColor(0, 0, 0, 100));
- grad.setColorAt(0.7, QColor(0, 0, 0, 100));
- grad.setColorAt(1, QColor(0, 0, 0, 0));
- painter->setPen(QPen(grad, 0));
- painter->drawLine(top - QPoint(1,0), bottom - QPoint(1,0));
+ if (creatorTheme()->widgetStyle() == Theme::StyleDefault) {
+ grad.setColorAt(0, QColor(255, 255, 255, 20));
+ grad.setColorAt(0.4, QColor(255, 255, 255, 60));
+ grad.setColorAt(0.7, QColor(255, 255, 255, 50));
+ grad.setColorAt(1, QColor(255, 255, 255, 40));
+ painter->setPen(QPen(grad, 0));
+ painter->drawLine(top, bottom);
+ grad.setColorAt(0, QColor(0, 0, 0, 0));
+ grad.setColorAt(0.4, QColor(0, 0, 0, 100));
+ grad.setColorAt(0.7, QColor(0, 0, 0, 100));
+ grad.setColorAt(1, QColor(0, 0, 0, 0));
+ painter->setPen(QPen(grad, 0));
+ painter->drawLine(top - QPoint(1,0), bottom - QPoint(1,0));
+ } else {
+ painter->setPen(QPen(creatorTheme()->color(Theme::DoubleTabWidget2ndSeparatorColor), 0));
+ painter->drawLine(top, bottom);
+ }
}
DoubleTabWidget::DoubleTabWidget(QWidget *parent) :
@@ -352,16 +364,18 @@ void DoubleTabWidget::paintEvent(QPaintEvent *event)
// draw top level tab bar
r.setHeight(Utils::StyleHelper::navigationWidgetHeight());
- QPoint offset = window()->mapToGlobal(QPoint(0, 0)) - mapToGlobal(r.topLeft());
- QRect gradientSpan = QRect(offset, window()->size());
- Utils::StyleHelper::horizontalGradient(&painter, gradientSpan, r);
-
- painter.setPen(Utils::StyleHelper::borderColor());
-
- QColor lighter(255, 255, 255, 40);
- painter.drawLine(r.bottomLeft(), r.bottomRight());
- painter.setPen(lighter);
- painter.drawLine(r.topLeft(), r.topRight());
+ if (creatorTheme()->widgetStyle () == Theme::StyleDefault) {
+ QPoint offset = window()->mapToGlobal(QPoint(0, 0)) - mapToGlobal(r.topLeft());
+ QRect gradientSpan = QRect(offset, window()->size());
+ Utils::StyleHelper::horizontalGradient(&painter, gradientSpan, r);
+ painter.setPen(Utils::StyleHelper::borderColor());
+ QColor lighter(255, 255, 255, 40);
+ painter.drawLine(r.bottomLeft(), r.bottomRight());
+ painter.setPen(lighter);
+ painter.drawLine(r.topLeft(), r.topRight());
+ } else {
+ painter.fillRect(r, creatorTheme()->color(Theme::DoubleTabWidget1stEmptyAreaBackgroundColor));
+ }
QFontMetrics fm(font());
int baseline = (r.height() + fm.ascent()) / 2 - 1;
@@ -373,17 +387,23 @@ void DoubleTabWidget::paintEvent(QPaintEvent *event)
}
QLinearGradient grad(QPoint(0, 0), QPoint(0, r.height() + OTHER_HEIGHT - 1));
- grad.setColorAt(0, QColor(247, 247, 247));
- grad.setColorAt(1, QColor(205, 205, 205));
+ if (creatorTheme()->widgetStyle() == Theme::StyleFlat) {
+ grad.setColorAt(0, creatorTheme()->color(Theme::DoubleTabWidget1stTabBackgroundColor));
+ } else {
+ grad.setColorAt(0, QColor(247, 247, 247));
+ grad.setColorAt(1, QColor(205, 205, 205));
+ }
// draw background of second bar
painter.fillRect(QRect(0, r.height(), r.width(), OTHER_HEIGHT), grad);
- painter.setPen(QColor(0x505050));
- painter.drawLine(0, r.height() + OTHER_HEIGHT,
- r.width(), r.height() + OTHER_HEIGHT);
- painter.setPen(Qt::white);
- painter.drawLine(0, r.height(),
- r.width(), r.height());
+ if (creatorTheme()->widgetStyle() == Theme::StyleDefault) {
+ painter.setPen(QColor(0x505050));
+ painter.drawLine(0, r.height() + OTHER_HEIGHT,
+ r.width(), r.height() + OTHER_HEIGHT);
+ painter.setPen(Qt::white);
+ painter.drawLine(0, r.height(),
+ r.width(), r.height());
+ }
// top level tabs
int x = m_title.isEmpty() ? 0 :
@@ -464,26 +484,28 @@ void DoubleTabWidget::paintEvent(QPaintEvent *event)
r.height() + 1),
grad);
- if (actualIndex != 0) {
+ if (actualIndex != 0 && creatorTheme()->widgetStyle() == Theme::StyleDefault) {
painter.setPen(QColor(255, 255, 255, 170));
painter.drawLine(x, 0, x, r.height());
}
x += MARGIN;
- painter.setPen(Qt::black);
+ painter.setPen(creatorTheme()->color(Theme::DoubleTabWidget1stTabActiveTextColor));
painter.drawText(x, baseline, tab.displayName());
x += nameWidth.at(actualIndex);
x += MARGIN;
- painter.setPen(Utils::StyleHelper::borderColor());
- painter.drawLine(x, 0, x, r.height() - 1);
- painter.setPen(QColor(0, 0, 0, 20));
- painter.drawLine(x + 1, 0, x + 1, r.height() - 1);
- painter.setPen(QColor(255, 255, 255, 170));
- painter.drawLine(x - 1, 0, x - 1, r.height());
+ if (creatorTheme()->widgetStyle() == Theme::StyleDefault) {
+ painter.setPen(Utils::StyleHelper::borderColor());
+ painter.drawLine(x, 0, x, r.height() - 1);
+ painter.setPen(QColor(0, 0, 0, 20));
+ painter.drawLine(x + 1, 0, x + 1, r.height() - 1);
+ painter.setPen(QColor(255, 255, 255, 170));
+ painter.drawLine(x - 1, 0, x - 1, r.height());
+ }
} else {
- if (i == 0)
+ if (i == 0 && creatorTheme()->widgetStyle() == Theme::StyleDefault)
drawFirstLevelSeparator(&painter, QPoint(x, 0), QPoint(x, r.height()-1));
x += MARGIN;
- painter.setPen(Utils::StyleHelper::panelTextColor());
+ painter.setPen(creatorTheme()->color(Theme::DoubleTabWidget1stTabInactiveTextColor));
painter.drawText(x + 1, baseline, tab.displayName());
x += nameWidth.at(actualIndex);
x += MARGIN;
@@ -512,14 +534,20 @@ void DoubleTabWidget::paintEvent(QPaintEvent *event)
x += MARGIN;
int textWidth = fm.width(subTabs.at(i));
if (currentTab.currentSubTab == i) {
- painter.setPen(Qt::white);
- painter.drawPixmap(x, y, m_left);
- painter.drawPixmap(QRect(x + SELECTION_IMAGE_WIDTH, y,
- textWidth, imageHeight),
- m_mid, QRect(0, 0, m_mid.width(), m_mid.height()));
- painter.drawPixmap(x + SELECTION_IMAGE_WIDTH + textWidth, y, m_right);
+ if (creatorTheme()->widgetStyle() == Theme::StyleDefault) {
+ painter.drawPixmap(x, y, m_left);
+ painter.drawPixmap(QRect(x + SELECTION_IMAGE_WIDTH, y,
+ textWidth, imageHeight),
+ m_mid, QRect(0, 0, m_mid.width(), m_mid.height()));
+ painter.drawPixmap(x + SELECTION_IMAGE_WIDTH + textWidth, y, m_right);
+ } else {
+ painter.setBrush(creatorTheme()->color(Theme::DoubleTabWidget2ndTabBackgroundColor));
+ painter.setPen(Qt::NoPen);
+ painter.drawRoundedRect(QRect(x,y,2*SELECTION_IMAGE_WIDTH+textWidth, m_mid.height()), 5,5);
+ }
+ painter.setPen(creatorTheme()->color(Theme::DoubleTabWidget2ndTabActiveTextColor));
} else {
- painter.setPen(Qt::black);
+ painter.setPen(creatorTheme()->color(Theme::DoubleTabWidget2ndTabInactiveTextColor));
}
x += SELECTION_IMAGE_WIDTH;
painter.drawText(x, y + (imageHeight + fm.ascent()) / 2. - 1,
diff --git a/src/plugins/projectexplorer/miniprojecttargetselector.cpp b/src/plugins/projectexplorer/miniprojecttargetselector.cpp
index 600e768d50..ba78e46eb0 100644
--- a/src/plugins/projectexplorer/miniprojecttargetselector.cpp
+++ b/src/plugins/projectexplorer/miniprojecttargetselector.cpp
@@ -37,6 +37,7 @@
#include <utils/algorithm.h>
#include <utils/styledbar.h>
#include <utils/stylehelper.h>
+#include <utils/theme/theme.h>
#include <coreplugin/icore.h>
#include <coreplugin/coreconstants.h>
@@ -89,6 +90,7 @@ static QIcon createCenteredIcon(const QIcon &icon, const QIcon &overlay)
using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;
+using namespace Utils;
static bool projectLesserThan(Project *p1, Project *p2)
{
@@ -133,17 +135,21 @@ void TargetSelectorDelegate::paint(QPainter *painter,
selectionGradient.load(QLatin1String(":/projectexplorer/images/targetpanel_gradient.png"));
if (option.state & QStyle::State_Selected) {
- QColor color =(option.state & QStyle::State_HasFocus) ?
- option.palette.highlight().color() :
- option.palette.dark().color();
- painter->fillRect(option.rect, color.darker(140));
- Utils::StyleHelper::drawCornerImage(selectionGradient, painter, option.rect.adjusted(0, 0, 0, -1), 5, 5, 5, 5);
- painter->setPen(QColor(255, 255, 255, 60));
- painter->drawLine(option.rect.topLeft(), option.rect.topRight());
- painter->setPen(QColor(255, 255, 255, 30));
- painter->drawLine(option.rect.bottomLeft() - QPoint(0,1), option.rect.bottomRight() - QPoint(0,1));
- painter->setPen(QColor(0, 0, 0, 80));
- painter->drawLine(option.rect.bottomLeft(), option.rect.bottomRight());
+ if (creatorTheme()->widgetStyle() == Theme::StyleFlat) {
+ painter->fillRect(option.rect, creatorTheme()->color(Theme::BackgroundColorSelected));
+ } else {
+ QColor color =(option.state & QStyle::State_HasFocus) ?
+ option.palette.highlight().color() :
+ option.palette.dark().color();
+ painter->fillRect(option.rect, color.darker(140));
+ Utils::StyleHelper::drawCornerImage(selectionGradient, painter, option.rect.adjusted(0, 0, 0, -1), 5, 5, 5, 5);
+ painter->setPen(QColor(255, 255, 255, 60));
+ painter->drawLine(option.rect.topLeft(), option.rect.topRight());
+ painter->setPen(QColor(255, 255, 255, 30));
+ painter->drawLine(option.rect.bottomLeft() - QPoint(0,1), option.rect.bottomRight() - QPoint(0,1));
+ painter->setPen(QColor(0, 0, 0, 80));
+ painter->drawLine(option.rect.bottomLeft(), option.rect.bottomRight());
+ }
}
QFontMetrics fm(option.font);
@@ -640,7 +646,7 @@ MiniProjectTargetSelector::MiniProjectTargetSelector(QAction *targetSelectorActi
m_hideOnRelease(false)
{
QPalette p;
- p.setColor(QPalette::Text, QColor(255, 255, 255, 160));
+ p.setColor(QPalette::Text, creatorTheme()->color(Theme::MiniProjectTargetSelectorTextColor));
setPalette(p);
setProperty("panelwidget", true);
setContentsMargins(QMargins(0, 1, 1, 8));
@@ -654,7 +660,8 @@ MiniProjectTargetSelector::MiniProjectTargetSelector(QAction *targetSelectorActi
m_summaryLabel = new QLabel(this);
m_summaryLabel->setMargin(3);
m_summaryLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop);
- m_summaryLabel->setStyleSheet(QString::fromLatin1("background: #464646;"));
+ m_summaryLabel->setStyleSheet(QString::fromLatin1("background: %1;")
+ .arg(creatorTheme()->color(Theme::MiniProjectTargetSelectorSummaryBackgroundColor).name()));
m_summaryLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
m_summaryLabel->setTextInteractionFlags(m_summaryLabel->textInteractionFlags() | Qt::LinksAccessibleByMouse);
@@ -1575,15 +1582,18 @@ void MiniProjectTargetSelector::updateSummary()
void MiniProjectTargetSelector::paintEvent(QPaintEvent *)
{
QPainter painter(this);
- painter.setBrush(QBrush(QColor(160, 160, 160, 255)));
+ painter.setBrush(creatorTheme()->color(Theme::MiniProjectTargetSelectorBackgroundColor));
painter.drawRect(rect());
- painter.setPen(Utils::StyleHelper::borderColor());
+ painter.setPen(creatorTheme()->color(Theme::MiniProjectTargetSelectorBackgroundColor));
+ // draw border on top and right
painter.drawLine(rect().topLeft(), rect().topRight());
painter.drawLine(rect().topRight(), rect().bottomRight());
-
- QRect bottomRect(0, rect().height() - 8, rect().width(), 8);
- static QImage image(QLatin1String(":/projectexplorer/images/targetpanel_bottom.png"));
- Utils::StyleHelper::drawCornerImage(image, &painter, bottomRect, 1, 1, 1, 1);
+ if (creatorTheme()->flag(Theme::DrawTargetSelectorBottom)) {
+ // draw thicker border on the bottom
+ QRect bottomRect(0, rect().height() - 8, rect().width(), 8);
+ static QImage image(QLatin1String(":/projectexplorer/images/targetpanel_bottom.png"));
+ Utils::StyleHelper::drawCornerImage(image, &painter, bottomRect, 1, 1, 1, 1);
+ }
}
void MiniProjectTargetSelector::switchToProjectsMode()
diff --git a/src/plugins/projectexplorer/panelswidget.cpp b/src/plugins/projectexplorer/panelswidget.cpp
index 85506bb1d7..c379ad5986 100644
--- a/src/plugins/projectexplorer/panelswidget.cpp
+++ b/src/plugins/projectexplorer/panelswidget.cpp
@@ -36,6 +36,7 @@
#include <QLabel>
#include <utils/stylehelper.h>
+#include <utils/theme/theme.h>
#include <utils/qtcassert.h>
namespace {
@@ -53,6 +54,7 @@ const int PANEL_LEFT_MARGIN = 70;
/// \brief The OnePixelBlackLine class
using namespace ProjectExplorer;
+using namespace Utils;
namespace {
class OnePixelBlackLine : public QWidget
@@ -69,8 +71,7 @@ public:
{
Q_UNUSED(e);
QPainter p(this);
- QColor fillColor = Utils::StyleHelper::mergedColors(
- palette().button().color(), Qt::black, 80);
+ QColor fillColor = creatorTheme()->color(Theme::PanelsWidgetSeparatorLineColor);
p.fillRect(contentsRect(), fillColor);
}
};
@@ -88,16 +89,19 @@ void RootWidget::paintEvent(QPaintEvent *e)
{
QWidget::paintEvent(e);
- QPainter painter(this);
- QColor light = Utils::StyleHelper::mergedColors(
- palette().button().color(), Qt::white, 30);
- QColor dark = Utils::StyleHelper::mergedColors(
- palette().button().color(), Qt::black, 85);
-
- painter.setPen(light);
- painter.drawLine(rect().topRight(), rect().bottomRight());
- painter.setPen(dark);
- painter.drawLine(rect().topRight() - QPoint(1,0), rect().bottomRight() - QPoint(1,0));
+ if (creatorTheme()->widgetStyle() == Theme::StyleDefault) {
+ // draw separator line to the right of the settings panel
+ QPainter painter(this);
+ QColor light = Utils::StyleHelper::mergedColors(
+ palette().button().color(), Qt::white, 30);
+ QColor dark = Utils::StyleHelper::mergedColors(
+ palette().button().color(), Qt::black, 85);
+
+ painter.setPen(light);
+ painter.drawLine(rect().topRight(), rect().bottomRight());
+ painter.setPen(dark);
+ painter.drawLine(rect().topRight() - QPoint(1,0), rect().bottomRight() - QPoint(1,0));
+ }
}
}
@@ -176,6 +180,7 @@ void PanelsWidget::addPropertiesPanel(PropertiesPanel *panel)
nameLabel->setText(panel->displayName());
QPalette palette = nameLabel->palette();
for (int i = QPalette::Active; i < QPalette::NColorGroups; ++i ) {
+ // FIXME: theming
QColor foregroundColor = palette.color(QPalette::ColorGroup(i), QPalette::Foreground);
foregroundColor.setAlpha(110);
palette.setBrush(QPalette::ColorGroup(i), QPalette::Foreground, foregroundColor);
diff --git a/src/plugins/qmakeprojectmanager/images/dark_headers.png b/src/plugins/qmakeprojectmanager/images/dark_headers.png
new file mode 100644
index 0000000000..1cf8eab6f9
--- /dev/null
+++ b/src/plugins/qmakeprojectmanager/images/dark_headers.png
Binary files differ
diff --git a/src/plugins/qmakeprojectmanager/images/dark_sources.png b/src/plugins/qmakeprojectmanager/images/dark_sources.png
new file mode 100644
index 0000000000..c809be82ab
--- /dev/null
+++ b/src/plugins/qmakeprojectmanager/images/dark_sources.png
Binary files differ
diff --git a/src/plugins/qmakeprojectmanager/images/dark_unknown.png b/src/plugins/qmakeprojectmanager/images/dark_unknown.png
new file mode 100644
index 0000000000..8bfd1fa3dc
--- /dev/null
+++ b/src/plugins/qmakeprojectmanager/images/dark_unknown.png
Binary files differ
diff --git a/src/plugins/qmakeprojectmanager/profileeditor.cpp b/src/plugins/qmakeprojectmanager/profileeditor.cpp
index 89cf2600da..0b5ae42613 100644
--- a/src/plugins/qmakeprojectmanager/profileeditor.cpp
+++ b/src/plugins/qmakeprojectmanager/profileeditor.cpp
@@ -42,6 +42,7 @@
#include <qtsupport/qtsupportconstants.h>
#include <texteditor/texteditoractionhandler.h>
#include <utils/qtcassert.h>
+#include <utils/theme/theme.h>
#include <QCoreApplication>
#include <QFileInfo>
@@ -49,6 +50,7 @@
#include <QTextBlock>
using namespace TextEditor;
+using namespace Utils;
namespace QmakeProjectManager {
namespace Internal {
@@ -222,9 +224,9 @@ ProFileEditorFactory::ProFileEditorFactory()
addHoverHandler(new ProFileHoverHandler(keywords));
setSyntaxHighlighterCreator([keywords]() { return new ProFileHighlighter(keywords); });
- Core::FileIconProvider::registerIconOverlayForSuffix(QtSupport::Constants::ICON_QT_PROJECT, "pro");
- Core::FileIconProvider::registerIconOverlayForSuffix(QtSupport::Constants::ICON_QT_PROJECT, "pri");
- Core::FileIconProvider::registerIconOverlayForSuffix(QtSupport::Constants::ICON_QT_PROJECT, "prf");
+ Core::FileIconProvider::registerIconOverlayForSuffix(creatorTheme()->iconOverlay(Theme::ProMimetype).toLatin1().data(), "pro");
+ Core::FileIconProvider::registerIconOverlayForSuffix(creatorTheme()->iconOverlay(Theme::PriMimetype).toLatin1().data(), "pri");
+ Core::FileIconProvider::registerIconOverlayForSuffix(creatorTheme()->iconOverlay(Theme::PrfMimetype).toLatin1().data(), "prf");
}
} // namespace Internal
diff --git a/src/plugins/qmakeprojectmanager/qmakenodes.cpp b/src/plugins/qmakeprojectmanager/qmakenodes.cpp
index dc8efe1b11..085ce968d4 100644
--- a/src/plugins/qmakeprojectmanager/qmakenodes.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakenodes.cpp
@@ -60,6 +60,7 @@
#include <utils/algorithm.h>
#include <utils/hostosinfo.h>
#include <utils/stringutils.h>
+#include <utils/theme/theme.h>
#include <proparser/prowriter.h>
#include <proparser/qmakevfs.h>
@@ -73,6 +74,7 @@
#include <utils/QtConcurrentTools>
using namespace Core;
+using namespace Utils;
// Static cached data in struct QmakeNodeStaticData providing information and icons
// for file types and the project. Do some magic via qAddPostRoutine()
@@ -150,7 +152,10 @@ QmakeNodeStaticData::QmakeNodeStaticData()
const QSize desiredSize = QSize(16, 16);
for (unsigned i = 0 ; i < count; ++i) {
- const QIcon overlayIcon = QIcon(QLatin1String(fileTypeDataStorage[i].icon));
+ QIcon overlayIcon;
+ QString iconFile = QString::fromLatin1(fileTypeDataStorage[i].icon);
+ iconFile = creatorTheme()->imageFile(iconFile);
+ overlayIcon = QIcon(iconFile);
const QPixmap folderPixmap =
Core::FileIconProvider::overlayIcon(QStyle::SP_DirIcon,
overlayIcon, desiredSize);
@@ -161,7 +166,8 @@ QmakeNodeStaticData::QmakeNodeStaticData()
desc, folderIcon));
}
// Project icon
- const QIcon projectBaseIcon(QLatin1String(":/qtsupport/images/qt_project.png"));
+ const QLatin1String fname(":/qtsupport/images/qt_project.png");
+ const QIcon projectBaseIcon(creatorTheme()->imageFile(fname));
const QPixmap projectPixmap = Core::FileIconProvider::overlayIcon(QStyle::SP_DirIcon,
projectBaseIcon,
desiredSize);
diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qrc b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qrc
index 6c6e8857d6..af8684afce 100644
--- a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qrc
+++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qrc
@@ -6,5 +6,8 @@
<file>images/headers.png</file>
<file>images/sources.png</file>
<file>images/unknown.png</file>
+ <file>images/dark_headers.png</file>
+ <file>images/dark_sources.png</file>
+ <file>images/dark_unknown.png</file>
</qresource>
</RCC>
diff --git a/src/plugins/qtsupport/images/dark_forms.png b/src/plugins/qtsupport/images/dark_forms.png
new file mode 100644
index 0000000000..c6c54c082f
--- /dev/null
+++ b/src/plugins/qtsupport/images/dark_forms.png
Binary files differ
diff --git a/src/plugins/qtsupport/images/dark_qml.png b/src/plugins/qtsupport/images/dark_qml.png
new file mode 100644
index 0000000000..65f445a873
--- /dev/null
+++ b/src/plugins/qtsupport/images/dark_qml.png
Binary files differ
diff --git a/src/plugins/qtsupport/images/dark_qt_project.png b/src/plugins/qtsupport/images/dark_qt_project.png
new file mode 100644
index 0000000000..5f4df3aa35
--- /dev/null
+++ b/src/plugins/qtsupport/images/dark_qt_project.png
Binary files differ
diff --git a/src/plugins/qtsupport/images/dark_qt_qrc.png b/src/plugins/qtsupport/images/dark_qt_qrc.png
new file mode 100644
index 0000000000..81b68ba39f
--- /dev/null
+++ b/src/plugins/qtsupport/images/dark_qt_qrc.png
Binary files differ
diff --git a/src/plugins/qtsupport/qtoutputformatter.cpp b/src/plugins/qtsupport/qtoutputformatter.cpp
index 68983363bc..0e337590f5 100644
--- a/src/plugins/qtsupport/qtoutputformatter.cpp
+++ b/src/plugins/qtsupport/qtoutputformatter.cpp
@@ -32,6 +32,7 @@
#include <coreplugin/editormanager/editormanager.h>
#include <projectexplorer/project.h>
+#include <utils/theme/theme.h>
#include <QPlainTextEdit>
#include <QTextCursor>
@@ -39,6 +40,7 @@
using namespace ProjectExplorer;
using namespace QtSupport;
+using namespace Utils;
// "file" or "qrc", colon, optional '//', '/' and further characters
#define QML_URL_REGEXP \
@@ -181,8 +183,7 @@ void QtOutputFormatter::appendLine(QTextCursor &cursor, const LinkResult &lr,
cursor.insertText(line.left(lr.start), normalFormat);
QTextCharFormat linkFormat = normalFormat;
- const QColor textColor = plainTextEdit()->palette().color(QPalette::Text);
- linkFormat.setForeground(mixColors(textColor, QColor(Qt::blue)));
+ linkFormat.setForeground(creatorTheme()->color(Theme::QtOutputFormatter_LinkTextColor));
linkFormat.setUnderlineStyle(QTextCharFormat::SingleUnderline);
linkFormat.setAnchor(true);
linkFormat.setAnchorHref(lr.href);
diff --git a/src/plugins/qtsupport/qtsupport.qrc b/src/plugins/qtsupport/qtsupport.qrc
index 351b129134..e97078e35b 100644
--- a/src/plugins/qtsupport/qtsupport.qrc
+++ b/src/plugins/qtsupport/qtsupport.qrc
@@ -4,6 +4,10 @@
<file>images/qml.png</file>
<file>images/qt_project.png</file>
<file>images/qt_qrc.png</file>
+ <file>images/dark_forms.png</file>
+ <file>images/dark_qml.png</file>
+ <file>images/dark_qt_project.png</file>
+ <file>images/dark_qt_qrc.png</file>
<file>QtSupport.mimetypes.xml</file>
</qresource>
</RCC>
diff --git a/src/plugins/qtsupport/qtsupportconstants.h b/src/plugins/qtsupport/qtsupportconstants.h
index 343d6865aa..dae80d1012 100644
--- a/src/plugins/qtsupport/qtsupportconstants.h
+++ b/src/plugins/qtsupport/qtsupportconstants.h
@@ -100,6 +100,7 @@ const char IOS_PLATFORM_TR[] = QT_TRANSLATE_NOOP("QtSupport", "iOS");
const char QML_WIZARD_ICON[] = ":/qmlproject/images/qml_wizard.png";
const char ICON_QT_PROJECT[] = ":/qtsupport/images/qt_project.png";
+const char DARK_ICON_QT_PROJECT[] = ":/qtsupport/images/dark_qt_project.png";
} // namepsace Constants
} // namepsace QtSupport
diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp
index c7512b961b..82bddcaac5 100644
--- a/src/plugins/texteditor/texteditor.cpp
+++ b/src/plugins/texteditor/texteditor.cpp
@@ -2509,7 +2509,13 @@ bool TextEditorWidget::event(QEvent *e)
e->ignore(); // we are a really nice citizen
d->m_maybeFakeTooltipEvent = false;
return true;
- break;
+ case QEvent::ApplicationPaletteChange: {
+ // slight hack: ignore palette changes
+ // at this point the palette has changed already,
+ // so undo it by re-setting the palette:
+ applyFontSettings();
+ return true;
+ }
default:
break;
}
diff --git a/src/plugins/todo/todoitemsmodel.cpp b/src/plugins/todo/todoitemsmodel.cpp
index 4822928d05..183f1d927e 100644
--- a/src/plugins/todo/todoitemsmodel.cpp
+++ b/src/plugins/todo/todoitemsmodel.cpp
@@ -34,8 +34,12 @@
#include <utils/algorithm.h>
+#include <utils/theme/theme.h>
+
#include <QIcon>
+using namespace Utils;
+
namespace Todo {
namespace Internal {
@@ -83,6 +87,10 @@ QVariant TodoItemsModel::data(const QModelIndex &index, int role) const
if (role == Qt::BackgroundColorRole)
return item.color;
+ if (role == Qt::TextColorRole)
+ return creatorTheme()->color(Theme::TodoItemTextColor);
+ if (role == Qt::ForegroundRole)
+ return creatorTheme()->color(Theme::TodoItemTextColor);
switch (index.column()) {
diff --git a/src/plugins/welcome/welcomeplugin.cpp b/src/plugins/welcome/welcomeplugin.cpp
index e84fcd233b..e1e0b1595c 100644
--- a/src/plugins/welcome/welcomeplugin.cpp
+++ b/src/plugins/welcome/welcomeplugin.cpp
@@ -44,6 +44,9 @@
#include <utils/styledbar.h>
#include <utils/iwelcomepage.h>
+#include <utils/theme/theme.h>
+#include <utils/theme/welcometheme.h>
+
#include <QVBoxLayout>
#include <QMessageBox>
@@ -86,6 +89,8 @@ public:
// bool eventFilter(QObject *, QEvent *);
public slots:
+ void onThemeChanged();
+
void setActivePlugin(int pos)
{
if (m_activePlugin != pos) {
@@ -108,11 +113,13 @@ private:
QuickContainer *m_welcomePage;
QList<QObject*> m_pluginList;
int m_activePlugin;
+ WelcomeTheme *m_welcomeTheme;
};
// --- WelcomeMode
WelcomeMode::WelcomeMode() :
- m_activePlugin(0)
+ m_activePlugin(0),
+ m_welcomeTheme(new WelcomeTheme(this))
{
setDisplayName(tr("Welcome"));
setIcon(QIcon(QLatin1String(":/welcome/images/mode_welcome.png")));
@@ -128,6 +135,7 @@ WelcomeMode::WelcomeMode() :
layout->setSpacing(0);
m_welcomePage = new QuickContainer();
+ onThemeChanged(); //initialize background color
m_welcomePage->setResizeMode(QuickContainer::SizeRootObjectToView);
m_welcomePage->setObjectName(QLatin1String("WelcomePage"));
@@ -154,6 +162,12 @@ WelcomeMode::WelcomeMode() :
setWidget(m_modeWidget);
}
+void WelcomeMode::onThemeChanged()
+{
+ m_welcomePage->setColor(creatorTheme()->color(Theme::BackgroundColorNormal));
+ m_welcomeTheme->notifyThemeChanged();
+}
+
WelcomeMode::~WelcomeMode()
{
QSettings *settings = Core::ICore::settings();
@@ -243,6 +257,15 @@ void WelcomeMode::initPlugins()
ctx->setContextProperty(QLatin1String("pagesModel"), QVariant::fromValue(m_pluginList));
+ connect(creatorTheme(), &Theme::changed, this, &WelcomeMode::onThemeChanged);
+ ctx->setContextProperty(QLatin1String("creatorTheme"), m_welcomeTheme);
+
+ // FIXME: pass theme class to QML somehow
+ if (creatorTheme()->widgetStyle() == Theme::StyleFlat)
+ ctx->setContextProperty(QLatin1String("theme"), QLatin1String("dark"));
+ else
+ ctx->setContextProperty(QLatin1String("theme"), QLatin1String("default"));
+
QString path = resourcePath() + QLatin1String("/welcomescreen/welcomescreen.qml");
// finally, load the root page