Changeset View
Standalone View
cuttlefish/package/contents/ui/Preview.qml
Show All 14 Lines | |||||
15 | * You should have received a copy of the GNU General Public License * | 15 | * You should have received a copy of the GNU General Public License * | ||
16 | * along with this program; if not, write to the * | 16 | * along with this program; if not, write to the * | ||
17 | * Free Software Foundation, Inc., * | 17 | * Free Software Foundation, Inc., * | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * | 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * | ||
19 | * * | 19 | * * | ||
20 | ***************************************************************************/ | 20 | ***************************************************************************/ | ||
21 | 21 | | |||
22 | import QtQuick 2.2 | 22 | import QtQuick 2.2 | ||
23 | import QtQuick.Controls 1.0 | 23 | import QtQuick.Controls 2.5 as QQC2 | ||
24 | import QtQuick.Layouts 1.0 | 24 | import QtQuick.Layouts 1.0 | ||
25 | import QtQuick.Dialogs 1.3 | ||||
25 | 26 | | |||
26 | import org.kde.plasma.core 2.0 as PlasmaCore | 27 | import org.kde.kirigami 2.8 as Kirigami | ||
27 | import org.kde.plasma.components 2.0 as PlasmaComponents | | |||
28 | import org.kde.plasma.extras 2.0 as PlasmaExtras | | |||
29 | | ||||
30 | 28 | | |||
31 | Rectangle { | 29 | Rectangle { | ||
30 | property alias iconPreview: iconPreview | ||||
31 | property alias dualMont: dualMont | ||||
32 | 32 | | |||
33 | id: preview | 33 | color: Kirigami.Theme.backgroundColor | ||
34 | | ||||
35 | color: PlasmaCore.ColorScope.backgroundColor | | |||
36 | | ||||
37 | property string iconName: "plasma" | | |||
38 | property string fullPath: "" | | |||
39 | property string category: "" | | |||
40 | property string fileName: "" | | |||
41 | property string type: "" | | |||
42 | property string iconTheme: "" | | |||
43 | property variant sizes: [] | | |||
44 | property bool scalable: true | | |||
45 | 34 | | |||
46 | function clipboard(text) { | 35 | function clipboard(text) { | ||
47 | if (!pickerMode) { | 36 | if (!pickerMode) { | ||
48 | clipboardHelper.text = text; | 37 | clipboardHelper.text = text; | ||
49 | clipboardHelper.selectAll(); | 38 | clipboardHelper.selectAll(); | ||
50 | clipboardHelper.copy(); | 39 | clipboardHelper.copy(); | ||
51 | } else { | 40 | } else { | ||
52 | iconModel.output(text); | 41 | iconModel.output(text); | ||
53 | } | 42 | } | ||
54 | 43 | | |||
55 | } | 44 | } | ||
56 | TextEdit { | 45 | TextEdit { | ||
57 | id: clipboardHelper | 46 | id: clipboardHelper | ||
58 | visible: false | 47 | visible: false | ||
59 | } | 48 | } | ||
60 | 49 | | |||
50 | FileDialog { | ||||
51 | id: ssPicker | ||||
52 | selectExisting: false | ||||
53 | selectMultiple: false | ||||
54 | selectFolder: false | ||||
55 | onAccepted: { | ||||
56 | iconPreview.grabToImage(function(result) { | ||||
57 | ssPicker.resetColors() | ||||
58 | res = result.saveToFile(ssPicker.fileUrl.toString().slice(7)) | ||||
59 | }); | ||||
60 | } | ||||
61 | onRejected: { | ||||
62 | ssPicker.resetColors() | ||||
63 | } | ||||
64 | function resetColors() { | ||||
65 | iconPreview.screenshotting = false | ||||
66 | iconPreview.Kirigami.Theme.textColor = Kirigami.Theme.textColor | ||||
67 | iconPreview.Kirigami.Theme.backgroundColor = Kirigami.Theme.backgroundColor | ||||
68 | iconPreview.Kirigami.Theme.highlightColor = Kirigami.Theme.highlightColor | ||||
69 | iconPreview.Kirigami.Theme.highlightedTextColor = Kirigami.Theme.highlightedTextColor | ||||
70 | iconPreview.Kirigami.Theme.positiveTextColor = Kirigami.Theme.positiveTextColor | ||||
71 | iconPreview.Kirigami.Theme.neutralTextColor = Kirigami.Theme.neutralTextColor | ||||
72 | iconPreview.Kirigami.Theme.negativeTextColor = Kirigami.Theme.negativeTextColor | ||||
73 | iconPreview.Kirigami.Theme.inherit = true | ||||
74 | } | ||||
75 | nameFilters: [ "PNG screenshot files (*.png)" ] | ||||
76 | } | ||||
61 | 77 | | |||
62 | ColumnLayout { | 78 | ColumnLayout { | ||
63 | anchors.margins: units.gridUnit | | |||
64 | anchors.rightMargin: units.gridUnit * 2 | | |||
65 | anchors.fill: parent | 79 | anchors.fill: parent | ||
66 | spacing: units.gridUnit / 2 | 80 | spacing: Kirigami.Units.largeSpacing | ||
ngraham: A GridLayout with one column is just a ColumnLayout; use that instead | |||||
67 | 81 | | |||
68 | Item { height: units.gridUnit / 2 } | 82 | Kirigami.Heading { | ||
69 | 83 | level: 1 | |||
GB_2: Maybe add `wrapMode: Text.Wrap`, so the heading can have multiple lines. | |||||
70 | PlasmaExtras.Heading { | 84 | Layout.fillWidth: true | ||
71 | level: 3 | 85 | horizontalAlignment: Text.AlignHCenter | ||
72 | elide: Text.ElideRight | 86 | elide: Text.ElideRight | ||
87 | text: preview.iconName | ||||
88 | } | ||||
89 | Kirigami.FormLayout { | ||||
73 | Layout.fillWidth: true | 90 | Layout.fillWidth: true | ||
74 | Layout.fillHeight: false | 91 | Layout.topMargin: Kirigami.Units.largeSpacing | ||
75 | wrapMode: Text.Wrap | 92 | QQC2.Label { | ||
76 | text: iconName | 93 | Layout.maximumWidth: Kirigami.Units.gridUnit * 15 | ||
77 | } | 94 | Kirigami.FormData.label: i18n("File name:") | ||
78 | RowLayout { | 95 | elide: Text.ElideRight | ||
79 | Layout.fillWidth: false | 96 | text: preview.fileName | ||
80 | Layout.fillHeight: false | 97 | } | ||
81 | Layout.preferredHeight: indexToSize(4) | 98 | QQC2.Label { | ||
82 | anchors.horizontalCenter: parent.horizontalCenter | 99 | Kirigami.FormData.label: i18n("Category:") | ||
83 | 100 | font.capitalization: Font.Capitalize | |||
84 | PlasmaCore.IconItem { | 101 | text: preview.category | ||
85 | source: iconName | 102 | } | ||
86 | usesPlasmaTheme: cuttlefish.usesPlasmaTheme | 103 | QQC2.Label { | ||
87 | colorGroup: PlasmaCore.ColorScope.colorGroup | 104 | Kirigami.FormData.label: i18n("Scalable:") | ||
88 | Layout.preferredWidth: indexToSize(0) | 105 | text: preview.scalable ? i18n("yes") : i18n("no") | ||
89 | Layout.preferredHeight: indexToSize(0) | 106 | font.capitalization: Font.Capitalize | ||
90 | } | | |||
91 | PlasmaCore.IconItem { | | |||
92 | source: iconName | | |||
93 | usesPlasmaTheme: cuttlefish.usesPlasmaTheme | | |||
94 | colorGroup: PlasmaCore.ColorScope.colorGroup | | |||
95 | Layout.preferredWidth: indexToSize(1) | | |||
96 | Layout.preferredHeight: indexToSize(1) | | |||
97 | } | | |||
98 | PlasmaCore.IconItem { | | |||
99 | source: iconName | | |||
100 | usesPlasmaTheme: cuttlefish.usesPlasmaTheme | | |||
101 | colorGroup: PlasmaCore.ColorScope.colorGroup | | |||
102 | Layout.preferredWidth: indexToSize(2) | | |||
103 | Layout.preferredHeight: indexToSize(2) | | |||
104 | } | | |||
105 | PlasmaCore.IconItem { | | |||
106 | source: iconName | | |||
107 | usesPlasmaTheme: cuttlefish.usesPlasmaTheme | | |||
108 | colorGroup: PlasmaCore.ColorScope.colorGroup | | |||
109 | Layout.preferredWidth: indexToSize(3) | | |||
110 | Layout.preferredHeight: indexToSize(3) | | |||
111 | } | | |||
112 | PlasmaCore.IconItem { | | |||
113 | source: iconName | | |||
114 | usesPlasmaTheme: cuttlefish.usesPlasmaTheme | | |||
115 | colorGroup: PlasmaCore.ColorScope.colorGroup | | |||
116 | Layout.preferredWidth: indexToSize(4) | | |||
117 | Layout.preferredHeight: indexToSize(4) | | |||
118 | } | 107 | } | ||
119 | } | 108 | } | ||
109 | Rectangle { | ||||
110 | id: iconPreview | ||||
ngraham: Center this button horizontally | |||||
111 | | ||||
112 | property bool screenshotting: false | ||||
113 | | ||||
114 | color: Kirigami.Theme.backgroundColor | ||||
120 | 115 | | |||
121 | PlasmaCore.IconItem { | 116 | Behavior on color { | ||
122 | source: iconName | 117 | ColorAnimation { | ||
123 | usesPlasmaTheme: cuttlefish.usesPlasmaTheme | 118 | duration: Kirigami.Units.longDuration | ||
This feature will be missing. Despite still having the checkbox for it. davidedmundson: This feature will be missing. Despite still having the checkbox for it.
| |||||
124 | colorGroup: PlasmaCore.ColorScope.colorGroup | 119 | } | ||
125 | Layout.fillHeight: false | 120 | } | ||
126 | Layout.preferredWidth: parent.width | 121 | Behavior on Layout.preferredHeight { | ||
127 | Layout.preferredHeight: parent.width | 122 | NumberAnimation { | ||
123 | duration: Kirigami.Units.longDuration | ||||
124 | } | ||||
128 | } | 125 | } | ||
129 | 126 | | |||
130 | GridLayout { | 127 | Layout.fillWidth: true | ||
131 | columns: 2 | 128 | Layout.preferredHeight: screenshotting ? previewGrid.height + (Kirigami.Units.gridUnit * 4) : previewGrid.height | ||
132 | 129 | | |||
133 | PlasmaComponents.Label { | 130 | Layout.topMargin: Kirigami.Units.largeSpacing | ||
134 | text: i18n("Name:") | 131 | Layout.bottomMargin: Kirigami.Units.largeSpacing * 4 | ||
132 | | ||||
133 | GridLayout { | ||||
134 | id: previewGrid | ||||
135 | anchors.horizontalCenter: parent.horizontalCenter | ||||
136 | anchors.verticalCenter: parent.verticalCenter | ||||
137 | columns: sizes.length | ||||
138 | rows: 2 | ||||
139 | property var sizes: [8, 16, 22, 32, 48, 64, 128] | ||||
140 | Repeater { | ||||
141 | model: previewGrid.sizes.length | ||||
142 | delegate: Kirigami.Icon { | ||||
143 | Layout.alignment: Qt.AlignBottom | ||||
144 | source: preview.iconName | ||||
145 | width: previewGrid.sizes[index] | ||||
146 | height: previewGrid.sizes[index] | ||||
147 | } | ||||
148 | } | ||||
149 | Repeater { | ||||
150 | model: previewGrid.sizes.length | ||||
151 | delegate: QQC2.Label { | ||||
152 | Layout.alignment: Qt.AlignTop | Qt.AlignHCenter | ||||
153 | text: previewGrid.sizes[index] | ||||
154 | Behavior on color { | ||||
155 | ColorAnimation { | ||||
156 | duration: Kirigami.Units.longDuration | ||||
135 | } | 157 | } | ||
136 | PlasmaComponents.Label { | | |||
137 | text: iconName | | |||
138 | wrapMode: Text.Wrap | | |||
139 | } | 158 | } | ||
140 | PlasmaComponents.Label { | | |||
141 | text: i18n("Filename:") | | |||
142 | } | 159 | } | ||
143 | PlasmaComponents.Label { | | |||
144 | text: fileName | | |||
145 | wrapMode: Text.Wrap | | |||
146 | verticalAlignment: Text.AlignVCenter | | |||
147 | } | 160 | } | ||
148 | PlasmaComponents.Label { | | |||
149 | text: i18n("Category:") | | |||
150 | } | 161 | } | ||
151 | PlasmaComponents.Label { | 162 | Row { | ||
152 | text: category | 163 | opacity: iconPreview.screenshotting ? 1 : 0 | ||
153 | wrapMode: Text.WordWrap | 164 | anchors.top: parent.top | ||
165 | anchors.left: parent.left | ||||
166 | anchors.margins: Kirigami.Units.smallSpacing | ||||
167 | Kirigami.Icon { | ||||
168 | height: 32 | ||||
169 | width: 32 | ||||
170 | source: "cuttlefish" | ||||
171 | } | ||||
172 | QQC2.Label { | ||||
173 | anchors.verticalCenter: parent.verticalCenter | ||||
174 | text: "Montage made with Cuttlefish" | ||||
175 | } | ||||
176 | Behavior on opacity { | ||||
177 | OpacityAnimator { | ||||
178 | duration: Kirigami.Units.longDuration | ||||
179 | } | ||||
180 | } | ||||
181 | } | ||||
182 | function shot(type) { | ||||
183 | iconPreview.screenshotting = true | ||||
184 | if (type == "normal") { | ||||
185 | iconPreview.Kirigami.Theme.inherit = false | ||||
186 | iconPreview.Kirigami.Theme.textColor = "#232629" | ||||
187 | iconPreview.Kirigami.Theme.backgroundColor = "#eff0f1" | ||||
188 | iconPreview.Kirigami.Theme.highlightColor = "#3daee9" | ||||
189 | iconPreview.Kirigami.Theme.highlightedTextColor = "#eff0f1" | ||||
190 | iconPreview.Kirigami.Theme.positiveTextColor = "#27ae60" | ||||
191 | iconPreview.Kirigami.Theme.neutralTextColor = "#f67400" | ||||
192 | iconPreview.Kirigami.Theme.negativeTextColor = "#da4453" | ||||
193 | } else if (type == "dark") { | ||||
194 | iconPreview.Kirigami.Theme.inherit = false | ||||
195 | iconPreview.Kirigami.Theme.textColor = "#eff0f1" | ||||
196 | iconPreview.Kirigami.Theme.backgroundColor = "#31363b" | ||||
197 | iconPreview.Kirigami.Theme.highlightColor = "#3daee9" | ||||
198 | iconPreview.Kirigami.Theme.highlightedTextColor = "#eff0f1" | ||||
199 | iconPreview.Kirigami.Theme.positiveTextColor = "#27ae60" | ||||
200 | iconPreview.Kirigami.Theme.neutralTextColor = "#f67400" | ||||
201 | iconPreview.Kirigami.Theme.negativeTextColor = "#da4453" | ||||
202 | } else if (type == "active") { | ||||
203 | iconPreview.Kirigami.Theme.inherit = true | ||||
204 | } | ||||
205 | ssPicker.open() | ||||
206 | } | ||||
207 | } | ||||
208 | QQC2.Button { | ||||
209 | Layout.alignment: Qt.AlignHCenter | ||||
210 | text: i18n("Open icon with external program") | ||||
211 | icon.name: "document-open" | ||||
212 | onClicked: Qt.openUrlExternally(preview.fullPath) | ||||
213 | } | ||||
214 | QQC2.Button { | ||||
215 | Layout.alignment: Qt.AlignHCenter | ||||
216 | text: i18n("Copy icon name to clipboard") | ||||
217 | icon.name: "edit-copy" | ||||
218 | onClicked: { | ||||
219 | clipboard(preview.iconName) | ||||
220 | cuttlefish.showPassiveNotification(i18n("Icon name copied to clipboard"), "short") | ||||
154 | } | 221 | } | ||
155 | PlasmaComponents.Label { | | |||
156 | text: i18n("Scalable:") | | |||
157 | } | 222 | } | ||
158 | PlasmaComponents.Label { | 223 | QQC2.Button { | ||
159 | text: scalable ? i18n("yes") : i18n("no") | 224 | Layout.alignment: Qt.AlignHCenter | ||
225 | visible: !iconPreview.screenshotting | ||||
226 | icon.name: "camera-web-symbolic" | ||||
227 | text: i18n("Create screenshot of icon") | ||||
228 | | ||||
229 | onClicked: { | ||||
230 | screenshotActions.popup() | ||||
160 | } | 231 | } | ||
161 | PlasmaComponents.Label { | 232 | | ||
162 | text: i18n("Sizes:") | 233 | QQC2.Menu { | ||
234 | id: screenshotActions | ||||
235 | QQC2.MenuItem { | ||||
236 | text: i18n("Screenshot with Breeze Colors") | ||||
237 | onTriggered: { | ||||
238 | iconPreview.shot("normal") | ||||
Needs a tooltip saying that this will copy the name to the clipboard (the icon isn't enough) ngraham: Needs a tooltip saying that this will copy the name to the clipboard (the icon isn't enough) | |||||
163 | } | 239 | } | ||
164 | PlasmaComponents.Label { | | |||
165 | text: (sizes != undefined) ? sizes.join(", ") : "" | | |||
166 | } | 240 | } | ||
241 | QQC2.MenuItem { | ||||
This is going to shock people, but I might even suggest displaying a Kirigami PassiveNotification saying "<text> copied to clipboard" when this is clicked. Otherwise it looks like nothing happens when you click the button. ngraham: This is going to shock people, but I might even suggest displaying a Kirigami… | |||||
242 | text: i18n("Screenshot with Breeze Dark Colors") | ||||
243 | onTriggered: { | ||||
244 | iconPreview.shot("dark") | ||||
167 | } | 245 | } | ||
168 | Item { | | |||
169 | Layout.fillHeight: true | | |||
170 | } | 246 | } | ||
171 | PlasmaComponents.ToolButton { | 247 | QQC2.MenuItem { | ||
172 | text: pickerMode ? i18n("Insert icon name") : i18n("Copy icon name to clipboard") | 248 | text: i18n("Screenshot with Breeze (Normal) and Breeze Dark") | ||
Needs a tooltip saying that this will open the image in an external app (the icon isn't enough, though making it actually use the icon of the app that it will open with would help with that) ngraham: Needs a tooltip saying that this will open the image in an external app (the icon isn't enough… | |||||
173 | iconSource: "edit-copy" | 249 | onTriggered: { | ||
174 | Layout.fillWidth: true | 250 | dualMont.shot() | ||
175 | onClicked: clipboard(preview.iconName); | 251 | } | ||
252 | } | ||||
253 | QQC2.MenuItem { | ||||
254 | text: i18n("Screenshot with Active Colorscheme") | ||||
ngraham: Colorscheme -> Color Scheme | |||||
255 | onTriggered: { | ||||
256 | iconPreview.shot("active") | ||||
257 | } | ||||
176 | } | 258 | } | ||
Use a Kirigami.FormLayout for this (if not using it was deliberate because of layout bugs, let's fix those) ngraham: Use a Kirigami.FormLayout for this (if not using it was deliberate because of layout bugs… | |||||
177 | PlasmaComponents.ToolButton { | | |||
178 | text: pickerMode ? i18n("Insert QtQuick code") : i18n("Copy QtQuick code to clipboard") | | |||
179 | iconSource: "edit-copy" | | |||
180 | Layout.fillWidth: true | | |||
181 | onClicked: { | | |||
182 | var code = "/* Don't forget to import...\n\ | | |||
183 | import org.kde.plasma.core 2.0 as PlasmaCore\n\ | | |||
184 | */\n\ | | |||
185 | PlasmaCore.IconItem {\n\ | | |||
186 | source: \"" + preview.iconName + "\"\n\ | | |||
187 | Layout.preferredWidth: units.iconSizes.medium\n\ | | |||
188 | Layout.preferredHeight: units.iconSizes.medium\n\ | | |||
189 | }\n\ | | |||
190 | "; | | |||
191 | clipboard(code); | | |||
192 | } | 259 | } | ||
193 | } | 260 | } | ||
194 | PlasmaComponents.CheckBox { | 261 | Item { | ||
195 | text: i18n("Update preview on hover") | 262 | Layout.fillHeight: true | ||
There's plenty of space for a button that has visible text. I'd recommend doing that instead of using a tiny icons-only button. ngraham: There's plenty of space for a button that has visible text. I'd recommend doing that instead of… | |||||
196 | onCheckedChanged: hoveredHighlight = checked | | |||
197 | } | 263 | } | ||
264 | DualMontage { id: dualMont } | ||||
198 | } | 265 | } | ||
199 | 266 | | |||
200 | Rectangle { | 267 | Kirigami.Separator { | ||
201 | color: theme.highlightColor | 268 | width: 1 | ||
202 | width: Math.round(units.gridUnit / 20) | | |||
203 | anchors { | 269 | anchors { | ||
204 | left: parent.left | 270 | right: parent.right | ||
205 | top: parent.top | | |||
206 | bottom: parent.bottom | 271 | bottom: parent.bottom | ||
272 | top: parent.top | ||||
207 | } | 273 | } | ||
208 | } | 274 | } | ||
209 | } | 275 | } |
A GridLayout with one column is just a ColumnLayout; use that instead