Unity 8
PreviewRatingInput.qml
1 /*
2  * Copyright (C) 2014,2015 Canonical, Ltd.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 3.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 import QtQuick 2.4
18 import Ubuntu.Components 1.3
19 import "../../Components"
20 
21 /*! \brief Preview widget for rating.
22 
23  The widget can show a rating widget and a field to enter a comment.
24  The visibility of the two widgets is specified by widgetData["visible"],
25  accepting "both", "rating" or "review".
26  The requirement of the review is specified by widgetData["visible"],
27  accepting "both", "rating" or "review".
28  It is possible to customise labels, widgetData["rating-label"] for the rating,
29  widgetData["rewiew-label"] for the comment field and widgetData["submit-label"]
30  for the submit button.
31  The icons used in the rating widget can be customised with
32  widgetData["rating-icon-empty"] and widgetData["rating-icon-full"].
33  The successeful submit emits triggered(widgetId, widgetData["required"], data),
34  with data being {"rating": rating value, "review": review comment, "author": null (for now)}.
35 */
36 
37 PreviewWidget {
38  id: root
39  implicitHeight: {
40  switch(widgetData["visible"]) {
41  default:
42  case "both":
43  return ratingLabelAndWidgetContainer.implicitHeight + (reviewContainer.visible ? reviewContainer.implicitHeight : 0);
44  case "rating":
45  return ratingLabelAndWidgetContainer.implicitHeight;
46  case "review":
47  return reviewContainer.implicitHeight;
48  }
49  }
50 
51  clip: reviewContainer.visible
52 
53  property alias ratingValue: rating.value
54  property alias reviewText: reviewTextArea.text
55 
56  function submit() {
57  // checks rating-input requirements
58  if (((widgetData["required"] === "both" ||
59  widgetData["required"] === "rating") &&
60  rating.value < 0) ||
61  ((widgetData["required"] === "both" ||
62  widgetData["required"] === "review") &&
63  reviewTextArea.text === "")) return;
64 
65  var data = {"rating": rating.value, "review": reviewTextArea.text, "author": null};
66  triggered(root.widgetId, "rated", data);
67  }
68 
69  Column {
70  id: ratingLabelAndWidgetContainer
71  anchors { left: parent.left; right: parent.right; }
72  spacing: units.gu(0.5)
73  visible: widgetData["visible"] !== "review"
74 
75  Label {
76  id: ratingLabel
77  objectName: "ratingLabel"
78  anchors { left: parent.left; right: parent.right; }
79  fontSize: "large"
80  color: root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText
81  opacity: .8
82  text: widgetData["rating-label"] || i18n.tr("Rate this")
83  }
84 
85  Rating {
86  id: rating
87  objectName: "rating"
88  anchors.left: parent.left
89  size: 5
90  height: units.gu(4)
91  onValueChanged: {
92  if (widgetData["visible"] === "rating") root.submit();
93  }
94 
95  property var urlIconEmpty: widgetData["rating-icon-empty"] || "image://theme/non-starred"
96  property var urlIconFull: widgetData["rating-icon-full"] || "image://theme/starred"
97  }
98  }
99 
100  Item {
101  id: reviewContainer
102  objectName: "reviewContainer"
103  implicitHeight: visible ? reviewSubmitContainer.implicitHeight + anchors.topMargin : 0
104 
105  readonly property real innerMargin: units.gu(1)
106 
107  anchors {
108  left: parent.left
109  right: parent.right
110  top: ratingLabelAndWidgetContainer.visible ? ratingLabelAndWidgetContainer.bottom : parent.top
111  bottom: parent.bottom
112  topMargin: ratingLabelAndWidgetContainer.visible ? innerMargin : 0
113  }
114  visible: {
115  switch(widgetData["visible"]) {
116  default:
117  case "both":
118  return widgetData["required"] === "review" || rating.value > 0;
119  case "rating":
120  return false;
121  case "review":
122  return true;
123  }
124  }
125 
126  Behavior on implicitHeight {
127  UbuntuNumberAnimation {
128  duration: UbuntuAnimation.FastDuration
129  easing.type: Easing.OutCubic
130  }
131  }
132 
133  Item {
134  id: reviewSubmitContainer
135  objectName: "reviewSubmitContainer"
136  anchors.fill: parent
137  implicitHeight: reviewTextArea.implicitHeight + anchors.topMargin
138 
139  TextArea {
140  id: reviewTextArea
141  objectName: "reviewTextArea"
142  property bool inputMethodVisible: Qt.inputMethod.visible
143  onInputMethodVisibleChanged: {
144  if(inputMethodVisible && activeFocus)
145  root.makeSureVisible(reviewTextArea);
146  }
147  onVisibleChanged: {
148  if (visible && widgetData["visible"] !== "review")
149  focus = true;
150  }
151  anchors {
152  top: parent.top
153  left: parent.left
154  right: submitButton.left
155  rightMargin: reviewContainer.innerMargin
156  }
157  placeholderText: widgetData["review-label"] || i18n.tr("Add a review")
158  }
159 
160  Button {
161  id: submitButton
162  objectName: "submitButton"
163 
164  readonly property bool readyToSubmit: {
165  if ((widgetData["required"] !== "review" && rating.value < 0) ||
166  (widgetData["required"] !== "rating" && reviewTextArea.text === "")) return false;
167  else return true;
168  }
169 
170  anchors {
171  top: parent.top
172  right: parent.right
173  }
174  enabled: readyToSubmit
175  text: widgetData["submit-label"] || i18n.tr("Send")
176  onClicked: root.submit()
177  }
178  }
179  }
180 }