diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2017-05-09 14:06:31 +0200 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2017-05-09 17:09:02 +0200 |
commit | 77218b487ac7dafcd166becec75278ab2a87bcc9 (patch) | |
tree | cb4dcb18febd980d767072a35a6ee97fec6847cb | |
parent | bd16ad8dc3f7fe2427a84712c679a909e73c38ff (diff) | |
download | kube-77218b487ac7dafcd166becec75278ab2a87bcc9.tar.gz kube-77218b487ac7dafcd166becec75278ab2a87bcc9.zip |
A simple timeline/log/history/notification view
For now this will just be a place to display notifications and some
status information.
-rw-r--r-- | components/kube/contents/ui/Kube.qml | 11 | ||||
-rw-r--r-- | components/kube/contents/ui/LogView.qml | 232 | ||||
-rw-r--r-- | framework/src/sinkfabric.cpp | 22 |
3 files changed, 260 insertions, 5 deletions
diff --git a/components/kube/contents/ui/Kube.qml b/components/kube/contents/ui/Kube.qml index 438666d0..115123b7 100644 --- a/components/kube/contents/ui/Kube.qml +++ b/components/kube/contents/ui/Kube.qml | |||
@@ -132,6 +132,10 @@ Controls2.ApplicationWindow { | |||
132 | iconName: Kube.Icons.user_inverted | 132 | iconName: Kube.Icons.user_inverted |
133 | onClicked: kubeViews.setPeopleView() | 133 | onClicked: kubeViews.setPeopleView() |
134 | } | 134 | } |
135 | Kube.IconButton { | ||
136 | iconName: Kube.Icons.error_inverted | ||
137 | onClicked: kubeViews.setLogView() | ||
138 | } | ||
135 | } | 139 | } |
136 | Column { | 140 | Column { |
137 | anchors { | 141 | anchors { |
@@ -173,6 +177,9 @@ Controls2.ApplicationWindow { | |||
173 | function setAccountsView() { | 177 | function setAccountsView() { |
174 | kubeViews.push({item: accountsView, replace: true, immediate: true}) | 178 | kubeViews.push({item: accountsView, replace: true, immediate: true}) |
175 | } | 179 | } |
180 | function setLogView() { | ||
181 | kubeViews.push({item: logView, replace: true, immediate: true}) | ||
182 | } | ||
176 | 183 | ||
177 | function openComposer() { | 184 | function openComposer() { |
178 | kubeViews.push({item: composerView, immediate: true}) | 185 | kubeViews.push({item: composerView, immediate: true}) |
@@ -187,6 +194,10 @@ Controls2.ApplicationWindow { | |||
187 | PeopleView { | 194 | PeopleView { |
188 | id: peopleView | 195 | id: peopleView |
189 | } | 196 | } |
197 | //Not a component because otherwise we can't log stuff | ||
198 | LogView { | ||
199 | id: logView | ||
200 | } | ||
190 | //A component so it's always destroyed when we're done | 201 | //A component so it's always destroyed when we're done |
191 | Component { | 202 | Component { |
192 | id: composerView | 203 | id: composerView |
diff --git a/components/kube/contents/ui/LogView.qml b/components/kube/contents/ui/LogView.qml new file mode 100644 index 00000000..a9b70c59 --- /dev/null +++ b/components/kube/contents/ui/LogView.qml | |||
@@ -0,0 +1,232 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 Michael Bohlender, <michael.bohlender@kdemail.net> | ||
3 | * Copyright (C) 2017 Christian Mollekopf, <mollekopf@kolabsys.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along | ||
16 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
18 | */ | ||
19 | |||
20 | import QtQuick 2.4 | ||
21 | import QtQuick.Layouts 1.1 | ||
22 | import QtQuick.Controls 1.3 as Controls | ||
23 | import QtQuick.Controls 2.0 as Controls2 | ||
24 | import org.kube.framework 1.0 as Kube | ||
25 | |||
26 | Controls.SplitView { | ||
27 | Item { | ||
28 | id: accountList | ||
29 | width: parent.width/2 | ||
30 | Layout.fillHeight: true | ||
31 | |||
32 | Kube.Listener { | ||
33 | filter: Kube.Messages.notification | ||
34 | onMessageReceived: { | ||
35 | logModel.insert(0, {message: message.message, timestamp: new Date(), resource: message.resource}); | ||
36 | } | ||
37 | } | ||
38 | |||
39 | Item { | ||
40 | id: statusBar | ||
41 | anchors { | ||
42 | topMargin: Kube.Units.smallSpacing | ||
43 | top: parent.top | ||
44 | left: parent.left | ||
45 | right: parent.right | ||
46 | } | ||
47 | |||
48 | height: Kube.Units.gridUnit * 2 | ||
49 | |||
50 | Repeater { | ||
51 | model: Kube.AccountsModel { | ||
52 | id: accountsModel | ||
53 | } | ||
54 | |||
55 | Column { | ||
56 | anchors.fill: statusBar | ||
57 | spacing: Kube.Units.smallSpacing | ||
58 | Row { | ||
59 | Kube.Label { | ||
60 | color: Kube.Colors.textColor | ||
61 | text: "Account: " + model.name | ||
62 | } | ||
63 | Kube.Label { | ||
64 | id: statusText | ||
65 | color: Kube.Colors.textColor | ||
66 | visible: false | ||
67 | states: [ | ||
68 | State { | ||
69 | name: "disconnected"; when: accountsModel.status == Kube.AccountsModel.OfflineStatus | ||
70 | PropertyChanges { target: statusText; text: "Offline"; visible: true } | ||
71 | }, | ||
72 | State { | ||
73 | name: "busy"; when: accountsModel.status == Kube.AccountsModel.BusyStatus | ||
74 | PropertyChanges { target: statusText; text: "Busy"; visible: true } | ||
75 | PropertyChanges { target: progressBar; visible: true } | ||
76 | } | ||
77 | ] | ||
78 | } | ||
79 | } | ||
80 | Controls2.ProgressBar { | ||
81 | id: progressBar | ||
82 | indeterminate: true | ||
83 | visible: false | ||
84 | height: Kube.Units.smallSpacing | ||
85 | width: parent.width | ||
86 | |||
87 | background: Rectangle { | ||
88 | color: Kube.Colors.backgroundColor | ||
89 | radius: 3 | ||
90 | } | ||
91 | |||
92 | contentItem: Item { | ||
93 | Rectangle { | ||
94 | width: progressBar.visualPosition * parent.width | ||
95 | height: parent.height | ||
96 | radius: 2 | ||
97 | color: Kube.Colors.highlightColor | ||
98 | } | ||
99 | } | ||
100 | |||
101 | |||
102 | Kube.Listener { | ||
103 | filter: Kube.Messages.progressNotification | ||
104 | onMessageReceived: { | ||
105 | progressBar.indeterminate = false | ||
106 | progressBar.from = 0 | ||
107 | progressBar.to = message.total | ||
108 | progressBar.value = message.progress | ||
109 | } | ||
110 | } | ||
111 | } | ||
112 | } | ||
113 | } | ||
114 | } | ||
115 | |||
116 | ListView { | ||
117 | id: listView | ||
118 | |||
119 | anchors { | ||
120 | top: statusBar.bottom | ||
121 | left: parent.left | ||
122 | right: parent.right | ||
123 | bottom: parent.bottom | ||
124 | topMargin: Kube.Units.largeSpacing | ||
125 | } | ||
126 | |||
127 | clip: true | ||
128 | |||
129 | model: ListModel { | ||
130 | id: logModel | ||
131 | } | ||
132 | |||
133 | onCurrentItemChanged: { | ||
134 | details.resourceId = currentItem.currentData.resource | ||
135 | details.message = currentItem.currentData.message | ||
136 | details.timestamp = currentItem.currentData.timestamp | ||
137 | } | ||
138 | |||
139 | delegate: Rectangle { | ||
140 | property variant currentData: model | ||
141 | height: Kube.Units.gridUnit * 3 | ||
142 | width: listView.width | ||
143 | |||
144 | border.color: Kube.Colors.buttonColor | ||
145 | border.width: 1 | ||
146 | color: listView.currentIndex == index ? Kube.Colors.highlightColor : Kube.Colors.viewBackgroundColor | ||
147 | |||
148 | Kube.Label { | ||
149 | id: resource | ||
150 | anchors { | ||
151 | top: parent.top | ||
152 | topMargin: Kube.Units.smallSpacing | ||
153 | left: parent.left | ||
154 | leftMargin: Kube.Units.largeSpacing | ||
155 | } | ||
156 | height: Kube.Units.gridUnit | ||
157 | width: parent.width - Kube.Units.largeSpacing * 2 | ||
158 | text: "Resource: " + model.resource | ||
159 | } | ||
160 | |||
161 | Kube.Label { | ||
162 | id: message | ||
163 | anchors { | ||
164 | topMargin: Kube.Units.smallSpacing | ||
165 | top: resource.bottom | ||
166 | left: parent.left | ||
167 | leftMargin: Kube.Units.largeSpacing | ||
168 | } | ||
169 | height: Kube.Units.gridUnit | ||
170 | width: parent.width - Kube.Units.largeSpacing * 2 | ||
171 | maximumLineCount: 1 | ||
172 | elide: Text.ElideRight | ||
173 | |||
174 | text: model.message | ||
175 | } | ||
176 | |||
177 | Kube.Label { | ||
178 | id: date | ||
179 | |||
180 | anchors { | ||
181 | right: parent.right | ||
182 | bottom: parent.bottom | ||
183 | } | ||
184 | text: Qt.formatDateTime(model.timestamp, " hh:mm:ss dd MMM yyyy") | ||
185 | font.italic: true | ||
186 | color: Kube.Colors.disabledTextColor | ||
187 | font.pointSize: 9 | ||
188 | } | ||
189 | |||
190 | MouseArea { | ||
191 | id: mouseArea | ||
192 | anchors.fill: parent | ||
193 | onClicked: { | ||
194 | listView.currentIndex = index | ||
195 | } | ||
196 | } | ||
197 | } | ||
198 | } | ||
199 | } | ||
200 | Rectangle { | ||
201 | id: details | ||
202 | property date timestamp | ||
203 | property string message | ||
204 | property variant resourceId | ||
205 | GridLayout { | ||
206 | anchors.fill: parent | ||
207 | columns: 2 | ||
208 | Kube.Label { | ||
209 | text: "Resource:" | ||
210 | } | ||
211 | Kube.Label { | ||
212 | text: details.resourceId | ||
213 | } | ||
214 | Kube.Label { | ||
215 | text: "Timestamp:" | ||
216 | } | ||
217 | Kube.Label { | ||
218 | text: Qt.formatDateTime(details.timestamp, " hh:mm:ss dd MMM yyyy") | ||
219 | } | ||
220 | Kube.Label { | ||
221 | text: "Message:" | ||
222 | } | ||
223 | Kube.Label { | ||
224 | text: details.message | ||
225 | } | ||
226 | Item { | ||
227 | Layout.columnSpan: 2 | ||
228 | Layout.fillHeight: true | ||
229 | } | ||
230 | } | ||
231 | } | ||
232 | } | ||
diff --git a/framework/src/sinkfabric.cpp b/framework/src/sinkfabric.cpp index 67d37292..f8c7e351 100644 --- a/framework/src/sinkfabric.cpp +++ b/framework/src/sinkfabric.cpp | |||
@@ -144,11 +144,23 @@ public: | |||
144 | return; | 144 | return; |
145 | } | 145 | } |
146 | } else if (notification.type == Sink::Notification::Error) { | 146 | } else if (notification.type == Sink::Notification::Error) { |
147 | if (notification.code == Sink::ApplicationDomain::ConnectionError) { | 147 | message["type"] = Notification::Warning; |
148 | message["type"] = Notification::Warning; | 148 | message["resource"] = QString{notification.resource}; |
149 | message["message"] = "Failed to connect to server."; | 149 | switch(notification.code) { |
150 | } else { | 150 | case Sink::ApplicationDomain::ConnectionError: |
151 | return; | 151 | message["message"] = "Failed to connect to server."; |
152 | break; | ||
153 | case Sink::ApplicationDomain::NoServerError: | ||
154 | message["message"] = "Host not found."; | ||
155 | break; | ||
156 | case Sink::ApplicationDomain::LoginError: | ||
157 | message["message"] = "Failed to login."; | ||
158 | break; | ||
159 | case Sink::ApplicationDomain::ConfigurationError: | ||
160 | message["message"] = "Configuration error."; | ||
161 | break; | ||
162 | default: | ||
163 | message["message"] = "An unknown error occurred: " + notification.message; | ||
152 | } | 164 | } |
153 | } else if (notification.type == Sink::Notification::Info) { | 165 | } else if (notification.type == Sink::Notification::Info) { |
154 | if (notification.code == Sink::ApplicationDomain::TransmissionSuccess) { | 166 | if (notification.code == Sink::ApplicationDomain::TransmissionSuccess) { |