ClassificationSheet.qml 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2012 Róbert Márki
  4. **
  5. ** This file is part of Web Feeds.
  6. **
  7. ** Web Feeds is free software: you can redistribute it and/or modify
  8. ** it under the terms of the GNU General Public License as published by
  9. ** the Free Software Foundation, either version 3 of the License, or
  10. ** (at your option) any later version.
  11. **
  12. ** Web Feeds is distributed in the hope that it will be useful,
  13. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. ** GNU General Public License for more details.
  16. **
  17. ** You should have received a copy of the GNU General Public License
  18. ** along with Web Feeds. If not, see <http://www.gnu.org/licenses/>.
  19. ****************************************************************************/
  20. import QtQuick 1.1
  21. import com.nokia.meego 1.0
  22. import WebFeeds 1.0
  23. import NewsBlur 1.0
  24. import "../../../../shared/qml" as Shared
  25. import "../../../../shared/qml/UIConstants.js" as UIConstants
  26. import "../misc" as Misc
  27. CommonNewsBlurSheet {
  28. id: root
  29. acceptButtonText: qsTr("Save")
  30. rejectButtonText: qsTr("Cancel")
  31. busyText: ""
  32. title: root.pageItem ? root.pageItem.title : ""
  33. iconSource: root.pageItem ? root.pageItem.iconSource : ""
  34. multilineTitle: true
  35. property variant __model
  36. onStatusChanged: {
  37. if((root.status == DialogStatus.Open)
  38. && !root.__model) {
  39. root.busy = true;
  40. service.loadFeedClassifiers(root.pageItem);
  41. if(root.pageItem.itemType == NewsBlurItem.StoryItem)
  42. storyTitleField.text = root.pageItem.title;
  43. }
  44. }
  45. QueryDialog {
  46. id: retryQueryDialog
  47. acceptButtonText: qsTr("Retry")
  48. rejectButtonText: qsTr("Cancel")
  49. titleText: qsTr("Network error")
  50. message: qsTr("Failed to retrieve the intelligence classifiers.")
  51. onAccepted: {
  52. root.busy = true;
  53. service.loadFeedClassifiers(root.pageItem);
  54. }
  55. onRejected: {
  56. root.close();
  57. }
  58. }
  59. Connections {
  60. target: root.service
  61. onFeedClassifiersLoaded: {
  62. if((result == NewsBlurEnum.SreNoError)
  63. || (result == NewsBlurEnum.SreAborted)) {
  64. root.__model = model;
  65. tagRepeater.model = root.__model.tags();
  66. titleRepeater.model = root.__model.titles();
  67. authorRepeater.model = root.__model.authors();
  68. root.busy = false;
  69. contentsRootItem.visible = true;
  70. root.busyText = qsTr("Saving classifications")
  71. } else {
  72. root.busy = false;
  73. retryQueryDialog.open();
  74. }
  75. }
  76. onFeedClassificationsSaved: {
  77. if((result == NewsBlurEnum.SreNoError)
  78. || (result == NewsBlurEnum.SreAborted)) {
  79. root.close();
  80. return;
  81. }
  82. root.busy = false;
  83. if(result == NewsBlurEnum.SreNetworkError)
  84. root.showMessage(qsTr("Network error"));
  85. else
  86. root.showMessage(qsTr("Failed to save classifications"));
  87. }
  88. }
  89. onAccepted: {
  90. root.busy = true;
  91. root.open();
  92. if(root.pageItem.itemType == NewsBlurItem.FeedItem)
  93. root.service.saveFeedClassifications(root.__model, root.pageItem.itemId);
  94. else if(root.pageItem.itemType == NewsBlurItem.StoryItem)
  95. root.service.saveFeedClassifications(root.__model, root.pageItem.feedId, root.pageItem.itemId);
  96. }
  97. onRejected: {
  98. if(root.busy) {
  99. root.open();
  100. root.service.abortLoadingFeedClassifiers(root.pageItem);
  101. root.service.abortSavingFeedClassifications();
  102. }
  103. }
  104. contentItem: Item {
  105. id: contentsRootItem
  106. anchors.fill: parent
  107. visible: false
  108. Flickable {
  109. id: flickable
  110. anchors.fill: parent
  111. anchors.bottomMargin: UIConstants.DEFAULT_MARGIN
  112. flickableDirection: Flickable.VerticalFlick
  113. contentWidth: contentColumn.width
  114. contentHeight: contentColumn.height
  115. clip: true
  116. Column {
  117. id: contentColumn
  118. anchors.left: parent.left
  119. anchors.leftMargin: UIConstants.DEFAULT_MARGIN
  120. width: flickable.width - (UIConstants.DEFAULT_MARGIN * 2)
  121. spacing: UIConstants.DEFAULT_MARGIN
  122. Column {
  123. visible: root.pageItem ? (root.pageItem.itemType == NewsBlurItem.StoryItem) : false
  124. spacing: UIConstants.DEFAULT_MARGIN
  125. width: parent.width
  126. Label {
  127. text: qsTr("Phrases to look for in future stories")
  128. wrapMode: Text.Wrap
  129. width: parent.width
  130. font.family: UIConstants.FONT_FAMILY_LIGHT
  131. }
  132. Shared.TextField {
  133. id: storyTitleField
  134. width: parent.width
  135. onTextChanged: {
  136. if(root.__model)
  137. root.__model.setNewTitleClassifierText(storyTitleField.text);
  138. }
  139. }
  140. Misc.ClassifierButton {
  141. id: highlightedPhrases
  142. width: parent.width
  143. text: storyTitleField.text
  144. classification: root.__model ? root.__model.newTitleClassifier : NewsBlurEnum.CvNeutralClassifier
  145. onClassificationSet: {
  146. root.__model.setNewTitleClassifierText(storyTitleField.text);
  147. root.__model.newTitleClassifier = newClassification;
  148. root.acceptButton.enabled = true;
  149. }
  150. }
  151. }
  152. Label {
  153. text: qsTr("Titles and phrases")
  154. visible: titleRepeater.count
  155. font.family: UIConstants.FONT_FAMILY_LIGHT
  156. }
  157. Column {
  158. width: parent.width
  159. Repeater {
  160. id: titleRepeater
  161. delegate: Misc.ClassifierButton {
  162. id: titleDelegate
  163. width: parent ? parent.width : 0
  164. property bool isFirst: !index
  165. property bool isLast: (index == (titleRepeater.count - 1))
  166. position: !(isFirst && isLast) ? (!isFirst ? (!isLast ? "center" : "bottom") : "top") : ""
  167. text: modelData
  168. classification: root.__model.titleClassification(modelData);
  169. onClassificationSet: {
  170. root.__model.setTitleClassification(modelData, newClassification);
  171. classification = root.__model.titleClassification(modelData);
  172. root.acceptButton.enabled = true;
  173. }
  174. }
  175. }
  176. }
  177. Label {
  178. text: qsTr("Authors")
  179. visible: authorRepeater.count
  180. font.family: UIConstants.FONT_FAMILY_LIGHT
  181. }
  182. Column {
  183. width: parent.width
  184. Repeater {
  185. id: authorRepeater
  186. delegate: Misc.ClassifierButton {
  187. id: authorDelegate
  188. width: parent ? parent.width : 0
  189. property bool isFirst: !index
  190. property bool isLast: (index == (authorRepeater.count - 1))
  191. position: !(isFirst && isLast) ? (!isFirst ? (!isLast ? "center" : "bottom") : "top") : ""
  192. text: modelData
  193. classification: root.__model.authorClassification(modelData);
  194. onClassificationSet: {
  195. root.__model.setAuthorClassification(modelData, newClassification);
  196. classification = root.__model.authorClassification(modelData);
  197. root.acceptButton.enabled = true;
  198. }
  199. }
  200. }
  201. }
  202. Label {
  203. text: qsTr("Categories and tags")
  204. visible: tagRepeater.count
  205. font.family: UIConstants.FONT_FAMILY_LIGHT
  206. }
  207. Column {
  208. width: parent.width
  209. Repeater {
  210. id: tagRepeater
  211. delegate: Misc.ClassifierButton {
  212. id: tagDelegate
  213. width: parent ? parent.width : 0
  214. property bool isFirst: !index
  215. property bool isLast: (index == (tagRepeater.count - 1))
  216. position: !(isFirst && isLast) ? (!isFirst ? (!isLast ? "center" : "bottom") : "top") : ""
  217. text: modelData
  218. classification: root.__model.tagClassification(modelData);
  219. onClassificationSet: {
  220. root.__model.setTagClassification(modelData, newClassification);
  221. classification = root.__model.tagClassification(modelData);
  222. root.acceptButton.enabled = true;
  223. }
  224. }
  225. }
  226. }
  227. Label {
  228. text: qsTr("Everything by this publisher")
  229. font.family: UIConstants.FONT_FAMILY_LIGHT
  230. }
  231. Misc.ClassifierButton {
  232. id: feedClassifierButton
  233. width: parent.width
  234. text: root.__model ? root.__model.feedTitle : ""
  235. classification: root.__model ? root.__model.feedClassification : NewsBlurEnum.CvNeutralClassifier
  236. onClassificationSet: {
  237. root.__model.feedClassification = newClassification;
  238. root.acceptButton.enabled = true;
  239. }
  240. }
  241. }
  242. }
  243. ScrollDecorator {
  244. flickableItem: flickable
  245. }
  246. }
  247. }