Merge lp:~verzegnassi-stefano/ubuntu-docviewer-app/advanced-text-editor into lp:ubuntu-docviewer-app/trunk
- advanced-text-editor
- Merge into trunk
Status: | Rejected | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Rejected by: | Stefano Verzegnassi | ||||||||||||
Proposed branch: | lp:~verzegnassi-stefano/ubuntu-docviewer-app/advanced-text-editor | ||||||||||||
Merge into: | lp:ubuntu-docviewer-app/trunk | ||||||||||||
Diff against target: |
1599 lines (+1309/-51) 22 files modified
debian/changelog (+6/-0) debian/control (+1/-0) manifest.json.in (+1/-1) po/com.ubuntu.docviewer.pot (+82/-14) src/app/qml/textView/TextView.qml (+37/-35) src/app/qml/textView/TextViewDefaultHeader.qml (+21/-0) src/app/qml/textView/TextViewSelectionHeader.qml (+81/-0) src/app/qml/textView/TextViewSettingsPage.qml (+127/-0) src/app/qml/ubuntu-docviewer-app.qml (+2/-0) src/plugin/CMakeLists.txt (+1/-0) src/plugin/text-qml-plugin/CMakeLists.txt (+38/-0) src/plugin/text-qml-plugin/LineNumberColumn.qml (+66/-0) src/plugin/text-qml-plugin/TextEditor.qml (+332/-0) src/plugin/text-qml-plugin/TextEditorStyle.qml (+35/-0) src/plugin/text-qml-plugin/backend.cpp (+37/-0) src/plugin/text-qml-plugin/backend.h (+34/-0) src/plugin/text-qml-plugin/documenthandler.cpp (+108/-0) src/plugin/text-qml-plugin/documenthandler.h (+85/-0) src/plugin/text-qml-plugin/filereader.cpp (+110/-0) src/plugin/text-qml-plugin/filereader.h (+97/-0) src/plugin/text-qml-plugin/qmldir (+7/-0) tests/autopilot/ubuntu_docviewer_app/tests/test_docviewer.py (+1/-1) |
||||||||||||
To merge this branch: | bzr merge lp:~verzegnassi-stefano/ubuntu-docviewer-app/advanced-text-editor | ||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alan Pope πΊπ§π± π¦ (community) | Needs Fixing | ||
Ubuntu Phone Apps Jenkins Bot | continuous-integration | Approve | |
Review via email: mp+257943@code.launchpad.net |
Commit message
Introducing a brand-new TextEditor, from DocumentViewer.Text module
Description of the change
- Added a new QML module that provides a new TextArea component, which will be extended in future with a syntax highlighter.
- Bumped app version to 0.4, since this update introduces a new feature.
### Details
Text files are now read by a C++ class, that works asynchronously.
Default header in TextView has been updated, and now provides a "search" action (not enabled yet), a "selection" mode and a settings page.
We provide a separated "selection" mode for the header, because of a number of issues in the UITK. See "Notes" section in this description of the change.
Text settings - the new TextEditor component supports the following settings: show line numbers, wrap text, highlight current line and show right margin at column xx.
Line numbers in TextEditor are provided by a C++ class. I preferred this implementation for keeping the code clean and fast.
DocumentHandler class is BSD licensed, and it's a fork of a demo project from Digia. BSD license is compatible with GPL v3, so there should be no issue with it.
### Notes
Here's some thoughts about the current UITK.
I had to partially fork the upstream TextArea component, because it does not provide a way to access to the "textDocument" property of the internal TextEdit (known issue).
Another issue I found is that it wasn't possible to implement the text selection used in UITK.TextArea: the components are declared as internals and/or depends on some features which are not exported via the Ubuntu.Components module.
I'd like to see the internal components of Ubuntu.Components module exposed as Ubuntu.
About the "text selection" mode:
There are two issues here.
A first implementation of the selection mode used the standard PageHead.actions. It seems that the actions popover in the header forwards mouse events to the component below: if an user clicks on an action (e.g. "copy), that click also affects the TextEditor below the popover, deselecting the text before it's effectively copied.
The second issue is a known one, and it's about the alignment of PageHead.contents. Actions in TextViewSelecti
- 144. By Stefano Verzegnassi
-
Added a category for TextView settings entries
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:144
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 145. By Stefano Verzegnassi
-
Fixed TextView test
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:145
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alan Pope πΊπ§π± π¦ (popey) wrote : | # |
This is looking great for viewing small text files.
A few issues:-
* "Large" text files can lock up / crash the app. By "large" I mean 910kB such as https:/
* First line number gets messed up with large files http://
* Edits don't get saved. If I create a small file (using vim/nano) then edit it in docviewer, and go back, the changes don't get saved to disk.
Stefano Verzegnassi (verzegnassi-stefano) wrote : | # |
I'll answer point by point:
1) Yes, that happens also with the current code.
The issue is not about the reading of the file (which happens asynchronously although it's not really a time-waster process), but the issue is due to the filling of the text in the TextEdit component, which happens in the main threads (I don't know if the in GUI one, or the other).
I will have a look if it's possible to work around it, by using a Loader component.
Since the issue lives in an upstream component (TextEdit is provided by the Qt library), it may become very hard to fix.
2) I had hard times in order to reproduce it. Sure, it needs some fix!
3) Do we want to save them? As far as I remember, we discussed about it during some meeting and we decided to provide just a viewer.
I think we should provide the documents in a read-only mode, but eventually still allow to copy/paste text (which we said it's broken in the platform).
Alan Pope πΊπ§π± π¦ (popey) wrote : | # |
I agree that it should "only" view and not edit. So we should remove the buttons that make it editable, right?
Stefano Verzegnassi (verzegnassi-stefano) wrote : | # |
Ideally, we may want to keep the selection mode/buttons: although the content is read-only, it should anyway be possible to copy a part of the text.
We should see if it's better to make some of the buttons (paste, copy, undo, redo) not visible, rather than simply disable them (but keep them still visible).
About the read-only mode, we should find out a way to provide some feedback to the user.
Since the new component looks like a text editor (and in future it will probably be), it may be useful to inform the user that the document is not editable.
A simple way to archieve this may be: https:/
Anyway I feel it's better to ask to the UX team, in order to have an organic, well-designed thing.
About the performance of the new component with huge text files, I saw that there are a few bottleneck that should be fixed before to have this branch merged.
The most relevant are:
- Binding from the FileReader output to the textProperty of the TextEdit
- Generation of line numbers (expecially when resizing the application window)
Unmerged revisions
- 145. By Stefano Verzegnassi
-
Fixed TextView test
- 144. By Stefano Verzegnassi
-
Added a category for TextView settings entries
- 143. By Stefano Verzegnassi
-
Bump Document Viewer version to 0.4
- 142. By Stefano Verzegnassi
-
Make CMake working for building DocumentViewer.Text module
- 141. By Stefano Verzegnassi
-
Updated theming stuff in DocumentViewer.Text plugin
- 140. By Stefano Verzegnassi
-
Updated translations
- 139. By Stefano Verzegnassi
-
Added settings for TextEditor component
- 138. By Stefano Verzegnassi
-
[textView] Added selection mode
- 137. By Stefano Verzegnassi
-
Added DocumentViewer.Text plugin
Preview Diff
1 | === modified file 'debian/changelog' |
2 | --- debian/changelog 2015-02-23 12:49:52 +0000 |
3 | +++ debian/changelog 2015-04-30 18:50:23 +0000 |
4 | @@ -1,3 +1,9 @@ |
5 | +ubuntu-docviewer-app (0.4.0) utopic; urgency=medium |
6 | + |
7 | + * Improved text editor |
8 | + |
9 | + -- Stefano Verzegnassi <verzegnassi.stefano@gmail.com> Thu, 30 Apr 2015 19:12:24 +0200 |
10 | + |
11 | ubuntu-docviewer-app (0.3.0) utopic; urgency=medium |
12 | |
13 | * Improved content-hub support |
14 | |
15 | === modified file 'debian/control' |
16 | --- debian/control 2015-02-23 12:49:52 +0000 |
17 | +++ debian/control 2015-04-30 18:50:23 +0000 |
18 | @@ -28,6 +28,7 @@ |
19 | Architecture: any |
20 | Depends: qtdeclarative5-qtquick2-plugin, |
21 | qtdeclarative5-ubuntu-ui-toolkit-plugin, |
22 | + qml-module-qt-labs-settings, |
23 | ${misc:Depends} |
24 | Description: Document Viewer application |
25 | Core Document Viewer application |
26 | |
27 | === modified file 'manifest.json.in' |
28 | --- manifest.json.in 2015-02-13 15:30:01 +0000 |
29 | +++ manifest.json.in 2015-04-30 18:50:23 +0000 |
30 | @@ -13,7 +13,7 @@ |
31 | "urls": "@URLS_FILE@" |
32 | } |
33 | }, |
34 | - "version": "0.3.@BZR_REVNO@", |
35 | + "version": "0.4.@BZR_REVNO@", |
36 | "maintainer": "Ubuntu App Cats <ubuntu-touch-coreapps@lists.launchpad.net>", |
37 | "x-source": { |
38 | "vcs-bzr": "@BZR_SOURCE@", |
39 | |
40 | === modified file 'po/com.ubuntu.docviewer.pot' |
41 | --- po/com.ubuntu.docviewer.pot 2015-04-27 16:02:40 +0000 |
42 | +++ po/com.ubuntu.docviewer.pot 2015-04-30 18:50:23 +0000 |
43 | @@ -8,7 +8,7 @@ |
44 | msgstr "" |
45 | "Project-Id-Version: \n" |
46 | "Report-Msgid-Bugs-To: \n" |
47 | -"POT-Creation-Date: 2015-04-27 18:02+0200\n" |
48 | +"POT-Creation-Date: 2015-04-30 19:09+0200\n" |
49 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
50 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
51 | "Language-Team: LANGUAGE <LL@li.org>\n" |
52 | @@ -34,13 +34,13 @@ |
53 | |
54 | #: ../src/app/docviewer-application.cpp:164 |
55 | #: ../src/app/qml/documentPage/DocumentPage.qml:25 |
56 | -#: /home/stefano/tmp/build-ch-imported-documents-name-Desktop-Default/po/com.ubuntu.docviewer.desktop.in.in.h:1 |
57 | +#: /home/stefano/Progetti/doc-viewer/build-advanced-text-editor-UbuntuSDK_for_armhf_GCC_ubuntu_sdk_14_10_utopic-Default/po/com.ubuntu.docviewer.desktop.in.in.h:1 |
58 | msgid "Document Viewer" |
59 | msgstr "" |
60 | |
61 | #: ../src/app/qml/common/DetailsPage.qml:27 |
62 | #: ../src/app/qml/pdfView/PdfViewDefaultHeader.qml:97 |
63 | -#: ../src/app/qml/textView/TextViewDefaultHeader.qml:83 |
64 | +#: ../src/app/qml/textView/TextViewDefaultHeader.qml:104 |
65 | msgid "Details" |
66 | msgstr "" |
67 | |
68 | @@ -77,7 +77,7 @@ |
69 | #: ../src/app/qml/common/RejectedImportDialog.qml:38 |
70 | #: ../src/app/qml/documentPage/DocumentPageSelectionModeHeader.qml:32 |
71 | #: ../src/app/qml/pdfView/PdfViewDefaultHeader.qml:61 |
72 | -#: ../src/app/qml/textView/TextViewDefaultHeader.qml:61 |
73 | +#: ../src/app/qml/textView/TextViewDefaultHeader.qml:63 |
74 | msgid "Close" |
75 | msgstr "" |
76 | |
77 | @@ -274,7 +274,7 @@ |
78 | msgstr "" |
79 | |
80 | #: ../src/app/qml/pdfView/PdfViewDefaultHeader.qml:61 |
81 | -#: ../src/app/qml/textView/TextViewDefaultHeader.qml:61 |
82 | +#: ../src/app/qml/textView/TextViewDefaultHeader.qml:63 |
83 | msgid "Back" |
84 | msgstr "" |
85 | |
86 | @@ -283,12 +283,12 @@ |
87 | msgstr "" |
88 | |
89 | #: ../src/app/qml/pdfView/PdfViewDefaultHeader.qml:91 |
90 | -#: ../src/app/qml/textView/TextViewDefaultHeader.qml:77 |
91 | +#: ../src/app/qml/textView/TextViewDefaultHeader.qml:92 |
92 | msgid "Disable night mode" |
93 | msgstr "" |
94 | |
95 | #: ../src/app/qml/pdfView/PdfViewDefaultHeader.qml:91 |
96 | -#: ../src/app/qml/textView/TextViewDefaultHeader.qml:77 |
97 | +#: ../src/app/qml/textView/TextViewDefaultHeader.qml:92 |
98 | msgid "Enable night mode" |
99 | msgstr "" |
100 | |
101 | @@ -305,20 +305,88 @@ |
102 | msgid "GO!" |
103 | msgstr "" |
104 | |
105 | -#: ../src/app/qml/textView/TextView.qml:42 |
106 | -msgid "Loading..." |
107 | -msgstr "" |
108 | - |
109 | -#: ../src/app/qml/ubuntu-docviewer-app.qml:183 |
110 | +#: ../src/app/qml/textView/TextViewDefaultHeader.qml:86 |
111 | +msgid "Enable selection mode" |
112 | +msgstr "" |
113 | + |
114 | +#: ../src/app/qml/textView/TextViewDefaultHeader.qml:98 |
115 | +msgid "Settings" |
116 | +msgstr "" |
117 | + |
118 | +#: ../src/app/qml/textView/TextViewSelectionHeader.qml:36 |
119 | +msgid "Select all" |
120 | +msgstr "" |
121 | + |
122 | +#: ../src/app/qml/textView/TextViewSelectionHeader.qml:42 |
123 | +msgid "Paste" |
124 | +msgstr "" |
125 | + |
126 | +#: ../src/app/qml/textView/TextViewSelectionHeader.qml:48 |
127 | +msgid "Cut" |
128 | +msgstr "" |
129 | + |
130 | +#: ../src/app/qml/textView/TextViewSelectionHeader.qml:54 |
131 | +msgid "Copy" |
132 | +msgstr "" |
133 | + |
134 | +#: ../src/app/qml/textView/TextViewSelectionHeader.qml:60 |
135 | +msgid "Redo" |
136 | +msgstr "" |
137 | + |
138 | +#: ../src/app/qml/textView/TextViewSelectionHeader.qml:67 |
139 | +msgid "Undo" |
140 | +msgstr "" |
141 | + |
142 | +#: ../src/app/qml/textView/TextViewSelectionHeader.qml:75 |
143 | +msgid "Exit selection mode" |
144 | +msgstr "" |
145 | + |
146 | +#: ../src/app/qml/textView/TextViewSettingsPage.qml:24 |
147 | +msgid "Text settings" |
148 | +msgstr "" |
149 | + |
150 | +#: ../src/app/qml/textView/TextViewSettingsPage.qml:45 |
151 | +msgid "Show line numbers" |
152 | +msgstr "" |
153 | + |
154 | +#: ../src/app/qml/textView/TextViewSettingsPage.qml:61 |
155 | +msgid "Enable text wrapping" |
156 | +msgstr "" |
157 | + |
158 | +#: ../src/app/qml/textView/TextViewSettingsPage.qml:77 |
159 | +msgid "Highlight current line" |
160 | +msgstr "" |
161 | + |
162 | +#: ../src/app/qml/textView/TextViewSettingsPage.qml:88 |
163 | +msgid "Right margin settings" |
164 | +msgstr "" |
165 | + |
166 | +#: ../src/app/qml/textView/TextViewSettingsPage.qml:95 |
167 | +msgid "Show right margin" |
168 | +msgstr "" |
169 | + |
170 | +#: ../src/app/qml/textView/TextViewSettingsPage.qml:111 |
171 | +msgid "Show at column (default = 80):" |
172 | +msgstr "" |
173 | + |
174 | +#: ../src/app/qml/ubuntu-docviewer-app.qml:185 |
175 | msgid "Document successfully imported!" |
176 | msgid_plural "Documents successfully imported!" |
177 | msgstr[0] "" |
178 | msgstr[1] "" |
179 | |
180 | -#: ../src/app/qml/ubuntu-docviewer-app.qml:186 |
181 | +#: ../src/app/qml/ubuntu-docviewer-app.qml:188 |
182 | msgid "Open" |
183 | msgstr "" |
184 | |
185 | -#: /home/stefano/tmp/build-ch-imported-documents-name-Desktop-Default/po/com.ubuntu.docviewer.desktop.in.in.h:2 |
186 | +#: ../src/plugin/text-qml-plugin/filereader.cpp:90 |
187 | +msgid "Could not open file for reading." |
188 | +msgstr "" |
189 | + |
190 | +#: ../src/plugin/text-qml-plugin/filereader.cpp:107 |
191 | +msgid "No file specified." |
192 | +msgstr "" |
193 | + |
194 | +#: /home/stefano/Progetti/doc-viewer/build-advanced-text-editor-UbuntuSDK_for_armhf_GCC_ubuntu_sdk_14_10_utopic-Default/po/com.ubuntu.docviewer.desktop.in.in.h:2 |
195 | msgid "documents;viewer;pdf;reader;" |
196 | msgstr "" |
197 | |
198 | === modified file 'src/app/qml/textView/TextView.qml' |
199 | --- src/app/qml/textView/TextView.qml 2015-03-26 13:58:31 +0000 |
200 | +++ src/app/qml/textView/TextView.qml 2015-04-30 18:50:23 +0000 |
201 | @@ -16,7 +16,8 @@ |
202 | |
203 | import QtQuick 2.3 |
204 | import Ubuntu.Components 1.1 |
205 | -import Ubuntu.Components.Themes.Ambiance 0.1 |
206 | +import DocumentViewer.Text 1.0 |
207 | +import Qt.labs.settings 1.0 |
208 | |
209 | import "../common/utils.js" as Utils |
210 | |
211 | @@ -24,50 +25,51 @@ |
212 | id: textPage |
213 | title: Utils.getNameOfFile(file.path); |
214 | |
215 | + property bool selectionModeEnabled: false |
216 | + property alias editor: editor |
217 | + |
218 | // Reset night mode shader settings when closing the page |
219 | // Component.onDestruction: mainView.nightModeEnabled = false |
220 | |
221 | - TextArea { |
222 | - id: textAreaMain |
223 | - objectName: "textAreaMain" |
224 | - |
225 | - property bool isLoading: true |
226 | - |
227 | + Settings { |
228 | + category: "TextViewer" |
229 | + |
230 | + property alias displayLineNumbers: editor.displayLineNumbers |
231 | + property alias textWrap: editor.textWrap |
232 | + property alias rightMarginAtColumn: editor.rightMarginAtColumn |
233 | + property alias showRightMargin: editor.showRightMargin |
234 | + property alias highlightCurrentLine: editor.highlightCurrentLine |
235 | + } |
236 | + |
237 | + TextReader { |
238 | + id: reader |
239 | + path: file.path |
240 | + |
241 | + onErrorStringChanged: console.log(errorString) |
242 | + } |
243 | + |
244 | + TextEditor { |
245 | + id: editor |
246 | + objectName: "editor" |
247 | anchors.fill: parent |
248 | |
249 | - // FIXME: If set to true, some of the keyboard hooks are disabled |
250 | - // And it's not possible to move the cursor with arrow keys. |
251 | - readOnly: true |
252 | - |
253 | - text: i18n.tr("Loading...") |
254 | - font.family: "UbuntuMono" |
255 | - |
256 | - Component.onCompleted: { |
257 | - var xhr = new XMLHttpRequest; |
258 | - |
259 | - xhr.open("GET", file.path); |
260 | - xhr.onreadystatechange = function() { |
261 | - if (xhr.readyState === XMLHttpRequest.DONE) { |
262 | - textAreaMain.text = xhr.responseText; |
263 | - textAreaMain.isLoading = false |
264 | - } |
265 | - }; |
266 | - |
267 | - xhr.send(); |
268 | - } |
269 | - |
270 | - style: TextAreaStyle { |
271 | - background: Rectangle { color: "white" } |
272 | - } |
273 | + selectionMode: textPage.selectionModeEnabled |
274 | + text: reader.fileString |
275 | } |
276 | |
277 | // *** HEADER *** |
278 | - state: "default" |
279 | states: [ |
280 | TextViewDefaultHeader { |
281 | - name: "default" |
282 | - targetPage: textPage |
283 | - activityRunning: textAreaMain.isLoading |
284 | + when: !textPage.selectionModeEnabled |
285 | + |
286 | + targetPage: textPage |
287 | + activityRunning: reader.status == TextReader.Loading |
288 | + }, |
289 | + |
290 | + TextViewSelectionHeader { |
291 | + when: textPage.selectionModeEnabled |
292 | + |
293 | + targetPage: textPage |
294 | } |
295 | ] |
296 | } |
297 | |
298 | === modified file 'src/app/qml/textView/TextViewDefaultHeader.qml' |
299 | --- src/app/qml/textView/TextViewDefaultHeader.qml 2015-03-26 13:58:31 +0000 |
300 | +++ src/app/qml/textView/TextViewDefaultHeader.qml 2015-04-30 18:50:23 +0000 |
301 | @@ -31,6 +31,8 @@ |
302 | anchors.fill: parent |
303 | spacing: units.gu(1) |
304 | |
305 | + visible: !targetPage.selectionModeEnabled |
306 | + |
307 | ActivityIndicator { id: activity } |
308 | |
309 | Column { |
310 | @@ -73,12 +75,31 @@ |
311 | |
312 | actions: [ |
313 | Action { |
314 | + iconName: "search" |
315 | + // onTriggered: target.state = "search" |
316 | + //Disable it until we provide search in Text plugin. |
317 | + enabled: false |
318 | + }, |
319 | + |
320 | + Action { |
321 | + iconName: "edit-select-all" |
322 | + text: i18n.tr("Enable selection mode") |
323 | + onTriggered: targetPage.selectionModeEnabled = true |
324 | + }, |
325 | + |
326 | + Action { |
327 | iconName: "night-mode" |
328 | text: mainView.nightModeEnabled ? i18n.tr("Disable night mode") : i18n.tr("Enable night mode") |
329 | onTriggered: mainView.nightModeEnabled = !mainView.nightModeEnabled |
330 | }, |
331 | |
332 | Action { |
333 | + iconName: "settings" |
334 | + text: i18n.tr("Settings") |
335 | + onTriggered: pageStack.push(Qt.resolvedUrl("TextViewSettingsPage.qml"), { textPage: targetPage }) |
336 | + }, |
337 | + |
338 | + Action { |
339 | objectName: "detailsAction" |
340 | text: i18n.tr("Details") |
341 | iconName: "info" |
342 | |
343 | === added file 'src/app/qml/textView/TextViewSelectionHeader.qml' |
344 | --- src/app/qml/textView/TextViewSelectionHeader.qml 1970-01-01 00:00:00 +0000 |
345 | +++ src/app/qml/textView/TextViewSelectionHeader.qml 2015-04-30 18:50:23 +0000 |
346 | @@ -0,0 +1,81 @@ |
347 | +/* |
348 | + * Copyright (C) 2014-2015 Canonical, Ltd. |
349 | + * |
350 | + * This program is free software; you can redistribute it and/or modify |
351 | + * it under the terms of the GNU General Public License as published by |
352 | + * the Free Software Foundation; version 3. |
353 | + * |
354 | + * This program is distributed in the hope that it will be useful, |
355 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
356 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
357 | + * GNU General Public License for more details. |
358 | + * |
359 | + * You should have received a copy of the GNU General Public License |
360 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
361 | + */ |
362 | + |
363 | +import QtQuick 2.3 |
364 | +import Ubuntu.Components 1.1 |
365 | +import "../upstreamComponents" |
366 | + |
367 | +PageHeadState { |
368 | + id: rootItem |
369 | + |
370 | + property Page targetPage |
371 | + head: targetPage.head |
372 | + |
373 | + contents: Row { |
374 | + width: parent ? parent.width : 0 |
375 | + height: parent ? parent.height : 0 |
376 | + |
377 | + layoutDirection: Qt.RightToLeft |
378 | + visible: targetPage.selectionModeEnabled |
379 | + |
380 | + HeaderButton { |
381 | + iconName: "edit-select-all" |
382 | + text: i18n.tr("Select all") |
383 | + onTriggered: targetPage.editor.selectAll() |
384 | + } |
385 | + |
386 | + HeaderButton { |
387 | + iconName: "edit-paste" |
388 | + text: i18n.tr("Paste") |
389 | + onTriggered: targetPage.editor.paste() |
390 | + } |
391 | + |
392 | + HeaderButton { |
393 | + iconName: "edit-cut" |
394 | + text: i18n.tr("Cut") |
395 | + onTriggered: targetPage.editor.cut() |
396 | + } |
397 | + |
398 | + HeaderButton { |
399 | + iconName: "edit-copy" |
400 | + text: i18n.tr("Copy") |
401 | + onTriggered: targetPage.editor.copy() |
402 | + } |
403 | + |
404 | + HeaderButton { |
405 | + iconName: "edit-redo" |
406 | + text: i18n.tr("Redo") |
407 | + onTriggered: targetPage.editor.redo() |
408 | + enabled: targetPage.editor.canRedo |
409 | + } |
410 | + |
411 | + HeaderButton { |
412 | + iconName: "edit-undo" |
413 | + text: i18n.tr("Undo") |
414 | + onTriggered: targetPage.editor.undo() |
415 | + enabled: targetPage.editor.canUndo |
416 | + } |
417 | + } |
418 | + |
419 | + backAction: Action { |
420 | + iconName: "back" |
421 | + text: i18n.tr("Exit selection mode") |
422 | + onTriggered: { |
423 | + targetPage.editor.deselect() |
424 | + targetPage.selectionModeEnabled = false; |
425 | + } |
426 | + } |
427 | +} |
428 | |
429 | === added file 'src/app/qml/textView/TextViewSettingsPage.qml' |
430 | --- src/app/qml/textView/TextViewSettingsPage.qml 1970-01-01 00:00:00 +0000 |
431 | +++ src/app/qml/textView/TextViewSettingsPage.qml 2015-04-30 18:50:23 +0000 |
432 | @@ -0,0 +1,127 @@ |
433 | +/* |
434 | + * Copyright (C) 2015 Canonical, Ltd. |
435 | + * |
436 | + * This program is free software; you can redistribute it and/or modify |
437 | + * it under the terms of the GNU General Public License as published by |
438 | + * the Free Software Foundation; version 3. |
439 | + * |
440 | + * This program is distributed in the hope that it will be useful, |
441 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
442 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
443 | + * GNU General Public License for more details. |
444 | + * |
445 | + * You should have received a copy of the GNU General Public License |
446 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
447 | + */ |
448 | + |
449 | +import QtQuick 2.3 |
450 | +import Ubuntu.Components 1.1 |
451 | +import QtQuick.Layouts 1.1 |
452 | +import Ubuntu.Components.ListItems 1.0 as ListItem |
453 | + |
454 | +Page { |
455 | + id: textSettingsPage |
456 | + title: i18n.tr("Text settings") |
457 | + |
458 | + property var textPage |
459 | + |
460 | + Component.onCompleted: { |
461 | + // Get settings |
462 | + lineNumbersCheckBox.checked = textPage.editor.displayLineNumbers |
463 | + textWrapCheckbox.checked = textPage.editor.textWrap |
464 | + highlightCurrentLineCheckbox.checked = textPage.editor.highlightCurrentLine |
465 | + rightMarginCheckbox.checked = textPage.editor.showRightMargin |
466 | + rightMarginTextField.text = textPage.editor.rightMarginAtColumn |
467 | + } |
468 | + |
469 | + Column { |
470 | + anchors.fill: parent |
471 | + |
472 | + ListItem.Base { |
473 | + RowLayout { |
474 | + anchors.fill: parent |
475 | + |
476 | + Label { |
477 | + text: i18n.tr("Show line numbers") |
478 | + Layout.fillWidth: true |
479 | + } |
480 | + |
481 | + CheckBox { |
482 | + id: lineNumbersCheckBox |
483 | + onCheckedChanged: textPage.editor.displayLineNumbers = checked; |
484 | + } |
485 | + } |
486 | + } |
487 | + |
488 | + ListItem.Base { |
489 | + RowLayout { |
490 | + anchors.fill: parent |
491 | + |
492 | + Label { |
493 | + text: i18n.tr("Enable text wrapping") |
494 | + Layout.fillWidth: true |
495 | + } |
496 | + |
497 | + CheckBox { |
498 | + id: textWrapCheckbox |
499 | + onCheckedChanged: textPage.editor.textWrap = checked |
500 | + } |
501 | + } |
502 | + } |
503 | + |
504 | + ListItem.Base { |
505 | + RowLayout { |
506 | + anchors.fill: parent |
507 | + |
508 | + Label { |
509 | + text: i18n.tr("Highlight current line") |
510 | + Layout.fillWidth: true |
511 | + } |
512 | + |
513 | + CheckBox { |
514 | + id: highlightCurrentLineCheckbox |
515 | + onCheckedChanged: textPage.editor.highlightCurrentLine = checked |
516 | + } |
517 | + } |
518 | + } |
519 | + |
520 | + ListItem.Header { text: i18n.tr("Right margin settings") } |
521 | + |
522 | + ListItem.Base { |
523 | + RowLayout { |
524 | + anchors.fill: parent |
525 | + |
526 | + Label { |
527 | + text: i18n.tr("Show right margin") |
528 | + Layout.fillWidth: true |
529 | + } |
530 | + |
531 | + CheckBox { |
532 | + id: rightMarginCheckbox |
533 | + onCheckedChanged: textPage.editor.showRightMargin = checked |
534 | + } |
535 | + } |
536 | + } |
537 | + |
538 | + ListItem.Base { |
539 | + RowLayout { |
540 | + anchors.fill: parent |
541 | + |
542 | + Label { |
543 | + text: i18n.tr("Show at column (default = 80):") |
544 | + |
545 | + Layout.fillWidth: true |
546 | + } |
547 | + |
548 | + TextField { |
549 | + id: rightMarginTextField |
550 | + implicitWidth: units.gu(12) |
551 | + inputMethodHints: Qt.ImhDigitsOnly |
552 | + validator: IntValidator { bottom: 1; top: 150 } |
553 | + |
554 | + onTextChanged: textPage.editor.rightMarginAtColumn = parseInt(text) |
555 | + } |
556 | + } |
557 | + } |
558 | + } |
559 | +} |
560 | |
561 | === modified file 'src/app/qml/ubuntu-docviewer-app.qml' |
562 | --- src/app/qml/ubuntu-docviewer-app.qml 2015-04-14 14:16:16 +0000 |
563 | +++ src/app/qml/ubuntu-docviewer-app.qml 2015-04-30 18:50:23 +0000 |
564 | @@ -34,7 +34,9 @@ |
565 | |
566 | applicationName: "com.ubuntu.docviewer" |
567 | useDeprecatedToolbar: false |
568 | + |
569 | automaticOrientation: true |
570 | + anchorToKeyboard: true |
571 | |
572 | width: units.gu(50) |
573 | height: units.gu(75) |
574 | |
575 | === modified file 'src/plugin/CMakeLists.txt' |
576 | --- src/plugin/CMakeLists.txt 2014-10-20 21:38:36 +0000 |
577 | +++ src/plugin/CMakeLists.txt 2015-04-30 18:50:23 +0000 |
578 | @@ -1,2 +1,3 @@ |
579 | add_subdirectory(file-qml-plugin) |
580 | add_subdirectory(poppler-qml-plugin) |
581 | +add_subdirectory(text-qml-plugin) |
582 | |
583 | === added directory 'src/plugin/text-qml-plugin' |
584 | === added file 'src/plugin/text-qml-plugin/CMakeLists.txt' |
585 | --- src/plugin/text-qml-plugin/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
586 | +++ src/plugin/text-qml-plugin/CMakeLists.txt 2015-04-30 18:50:23 +0000 |
587 | @@ -0,0 +1,38 @@ |
588 | +set(PLUGIN_DIR DocumentViewer/Text) |
589 | +include_directories( |
590 | + ${CMAKE_CURRENT_SOURCE_DIR} |
591 | + ${CMAKE_CURRENT_BINARY_DIR} |
592 | +) |
593 | + |
594 | +#add QML resources |
595 | +file(GLOB_RECURSE QML_SRCS |
596 | + RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} |
597 | + *.qml *.js qmldir |
598 | +) |
599 | + |
600 | +#add the sources to compile |
601 | +set(textqmlplugin_SRCS |
602 | + backend.cpp |
603 | + documenthandler.cpp |
604 | + filereader.cpp |
605 | + ${QML_SRCS} |
606 | +) |
607 | + |
608 | +add_library(textqmlplugin MODULE ${textqmlplugin_SRCS}) |
609 | +qt5_use_modules(textqmlplugin Qml Quick) |
610 | + |
611 | +# Copy the plugin, the qmldir file and other assets to the build dir for running in QtCreator |
612 | +if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}") |
613 | + add_custom_command(TARGET textqmlplugin POST_BUILD |
614 | + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/../${PLUGIN_DIR} |
615 | + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/qmldir ${CMAKE_CURRENT_BINARY_DIR}/../${PLUGIN_DIR} |
616 | + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/LineNumberColumn.qml ${CMAKE_CURRENT_BINARY_DIR}/../${PLUGIN_DIR} |
617 | + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/TextEditor.qml ${CMAKE_CURRENT_BINARY_DIR}/../${PLUGIN_DIR} |
618 | + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/TextEditorStyle.qml ${CMAKE_CURRENT_BINARY_DIR}/../${PLUGIN_DIR} |
619 | + COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:textqmlplugin> ${CMAKE_CURRENT_BINARY_DIR}/../${PLUGIN_DIR} |
620 | + ) |
621 | +endif(NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}") |
622 | + |
623 | +# Install plugin file |
624 | +install(TARGETS textqmlplugin DESTINATION ${QT_IMPORTS_DIR}/${PLUGIN_DIR}) |
625 | +install(FILES ${QML_SRCS} DESTINATION ${QT_IMPORTS_DIR}/${PLUGIN_DIR}) |
626 | |
627 | === added file 'src/plugin/text-qml-plugin/LineNumberColumn.qml' |
628 | --- src/plugin/text-qml-plugin/LineNumberColumn.qml 1970-01-01 00:00:00 +0000 |
629 | +++ src/plugin/text-qml-plugin/LineNumberColumn.qml 2015-04-30 18:50:23 +0000 |
630 | @@ -0,0 +1,66 @@ |
631 | +/* |
632 | + * Copyright (C) 2015 Canonical, Ltd. |
633 | + * |
634 | + * This program is free software; you can redistribute it and/or modify |
635 | + * it under the terms of the GNU General Public License as published by |
636 | + * the Free Software Foundation; version 3. |
637 | + * |
638 | + * This program is distributed in the hope that it will be useful, |
639 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
640 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
641 | + * GNU General Public License for more details. |
642 | + * |
643 | + * You should have received a copy of the GNU General Public License |
644 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
645 | + */ |
646 | + |
647 | +import QtQuick 2.3 |
648 | +import Ubuntu.Components 1.1 |
649 | + |
650 | +Rectangle { |
651 | + id: lineColumn |
652 | + |
653 | + width: visible ? units.gu(3.5) + lineNumberRepeater.itemAt(lineNumberRepeater.count - 1).paintedWidth : 0 |
654 | + |
655 | + property int topMargin |
656 | + property alias model: lineNumberRepeater.model |
657 | + property var font |
658 | + |
659 | + property alias dividerColor: divider.color |
660 | + property alias dividerWidth: divider.width |
661 | + property color fontColor |
662 | + |
663 | + Rectangle { |
664 | + id: divider |
665 | + height: parent.height |
666 | + anchors.right: parent.right |
667 | + color: lineColumn.dividerColor |
668 | + } |
669 | + |
670 | + Column { |
671 | + id: layout |
672 | + anchors { |
673 | + top: parent.top |
674 | + left: parent.left |
675 | + right: parent.right |
676 | + topMargin: lineColumn.topMargin |
677 | + rightMargin: units.gu(2) |
678 | + leftMargin: units.gu(1.5) |
679 | + } |
680 | + |
681 | + Repeater { |
682 | + id: lineNumberRepeater |
683 | + |
684 | + delegate: Text { |
685 | + width: layout.width |
686 | + height: modelData.lineHeight |
687 | + text: modelData.lineNumber + 1 |
688 | + |
689 | + horizontalAlignment: Text.AlignRight |
690 | + |
691 | + font: lineColumn.font |
692 | + color: lineColumn.fontColor |
693 | + } |
694 | + } |
695 | + } |
696 | +} |
697 | |
698 | === added file 'src/plugin/text-qml-plugin/TextEditor.qml' |
699 | --- src/plugin/text-qml-plugin/TextEditor.qml 1970-01-01 00:00:00 +0000 |
700 | +++ src/plugin/text-qml-plugin/TextEditor.qml 2015-04-30 18:50:23 +0000 |
701 | @@ -0,0 +1,332 @@ |
702 | +/* |
703 | + * Copyright (C) 2015 Canonical, Ltd. |
704 | + * |
705 | + * This program is free software; you can redistribute it and/or modify |
706 | + * it under the terms of the GNU General Public License as published by |
707 | + * the Free Software Foundation; version 3. |
708 | + * |
709 | + * This program is distributed in the hope that it will be useful, |
710 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
711 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
712 | + * GNU General Public License for more details. |
713 | + * |
714 | + * You should have received a copy of the GNU General Public License |
715 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
716 | + */ |
717 | + |
718 | +import QtQuick 2.3 |
719 | +import Ubuntu.Components 1.1 |
720 | +import DocumentViewer.Text 1.0 |
721 | + |
722 | +StyledItem { |
723 | + id: rootItem |
724 | + |
725 | + property alias text: textArea.text |
726 | + property alias readOnly: textArea.readOnly |
727 | + |
728 | + property alias mouseSelectionMode: textArea.mouseSelectionMode |
729 | + property alias selectionMode: textArea.selectByMouse |
730 | + |
731 | + property bool displayLineNumbers: true |
732 | + property bool textWrap: false |
733 | + property int rightMarginAtColumn: 80 |
734 | + property bool showRightMargin: true |
735 | + property bool highlightCurrentLine: false |
736 | + |
737 | + property alias canPaste: textArea.canPaste |
738 | + property alias canRedo: textArea.canRedo |
739 | + property alias canUndo: textArea.canUndo |
740 | + |
741 | + // functions |
742 | + /*! |
743 | + Copies the currently selected text to the system clipboard. |
744 | + */ |
745 | + function copy() |
746 | + { |
747 | + textArea.copy(); |
748 | + } |
749 | + |
750 | + /*! |
751 | + Moves the currently selected text to the system clipboard. |
752 | + */ |
753 | + function cut() |
754 | + { |
755 | + textArea.cut(); |
756 | + } |
757 | + |
758 | + /*! |
759 | + Removes active text selection. |
760 | + */ |
761 | + function deselect() |
762 | + { |
763 | + textArea.deselect(); |
764 | + } |
765 | + |
766 | + /*! |
767 | + Inserts text into the TextArea at position. |
768 | + */ |
769 | + function insert(position, text) |
770 | + { |
771 | + textArea.insert(position, text); |
772 | + } |
773 | + |
774 | + /*! |
775 | + Returns the text position closest to pixel position (x, y). |
776 | + |
777 | + Position 0 is before the first character, position 1 is after the first |
778 | + character but before the second, and so on until position text.length, |
779 | + which is after all characters. |
780 | + */ |
781 | + function positionAt(x, y) |
782 | + { |
783 | + return textArea.positionAt(x, y); |
784 | + } |
785 | + |
786 | + /*! |
787 | + Returns true if the natural reading direction of the textArea text found |
788 | + between positions start and end is right to left. |
789 | + */ |
790 | + function isRightToLeft(start, end) |
791 | + { |
792 | + return textArea.isRightToLeft(start, end) |
793 | + } |
794 | + |
795 | + /*! |
796 | + Moves the cursor to position and updates the selection according to the |
797 | + optional mode parameter. (To only move the cursor, set the cursorPosition |
798 | + property.) |
799 | + |
800 | + When this method is called it additionally sets either the selectionStart |
801 | + or the selectionEnd (whichever was at the previous cursor position) to the |
802 | + specified position. This allows you to easily extend and contract the selected |
803 | + text range. |
804 | + |
805 | + The selection mode specifies whether the selection is updated on a per character |
806 | + or a per word basis. If not specified the selection mode will default to whatever |
807 | + is given in the mouseSelectionMode property. |
808 | + */ |
809 | + function moveCursorSelection(position, mode) |
810 | + { |
811 | + if (mode === undefined) |
812 | + textArea.moveCursorSelection(position, mouseSelectionMode); |
813 | + else |
814 | + textArea.moveCursorSelection(position, mode); |
815 | + } |
816 | + |
817 | + /*! |
818 | + Places the clipboard or the data given as parameter into the text input. |
819 | + The selected text will be replaces with the data. |
820 | + */ |
821 | + function paste(data) { |
822 | + if ((data !== undefined) && (typeof data === "string") && !textArea.readOnly) { |
823 | + var selTxt = textArea.selectedText; |
824 | + var txt = textArea.text; |
825 | + var pos = (selTxt !== "") ? txt.indexOf(selTxt) : textArea.cursorPosition |
826 | + if (selTxt !== "") { |
827 | + textArea.text = txt.substring(0, pos) + data + txt.substr(pos + selTxt.length); |
828 | + } else { |
829 | + textArea.text = txt.substring(0, pos) + data + txt.substr(pos); |
830 | + } |
831 | + textArea.cursorPosition = pos + data.length; |
832 | + } else |
833 | + textArea.paste(); |
834 | + } |
835 | + |
836 | + /*! |
837 | + Returns the rectangle at the given position in the text. The x, y, and height |
838 | + properties correspond to the cursor that would describe that position. |
839 | + */ |
840 | + function positionToRectangle(position) |
841 | + { |
842 | + return textArea.positionToRectangle(position); |
843 | + } |
844 | + |
845 | + /*! |
846 | + Redoes the last operation if redo is \l{canRedo}{available}. |
847 | + */ |
848 | + function redo() |
849 | + { |
850 | + textArea.redo(); |
851 | + } |
852 | + |
853 | + /*! |
854 | + Causes the text from start to end to be selected. |
855 | + |
856 | + If either start or end is out of range, the selection is not changed. |
857 | + |
858 | + After calling this, selectionStart will become the lesser and selectionEnd |
859 | + will become the greater (regardless of the order passed to this method). |
860 | + |
861 | + See also selectionStart and selectionEnd. |
862 | + */ |
863 | + function select(start, end) |
864 | + { |
865 | + textArea.select(start, end); |
866 | + } |
867 | + |
868 | + /*! |
869 | + Causes all text to be selected. |
870 | + */ |
871 | + function selectAll() |
872 | + { |
873 | + textArea.selectAll(); |
874 | + } |
875 | + |
876 | + /*! |
877 | + Causes the word closest to the current cursor position to be selected. |
878 | + */ |
879 | + function selectWord() |
880 | + { |
881 | + textArea.selectWord(); |
882 | + } |
883 | + |
884 | + /*! |
885 | + Returns the section of text that is between the start and end positions. |
886 | + |
887 | + The returned text does not include any rich text formatting. A getText(0, length) |
888 | + will result in the same value as displayText. |
889 | + */ |
890 | + function getText(start, end) |
891 | + { |
892 | + return textArea.getText(start, end); |
893 | + } |
894 | + |
895 | + /*! |
896 | + Removes the section of text that is between the start and end positions |
897 | + from the TextEditor. |
898 | + */ |
899 | + function remove(start, end) |
900 | + { |
901 | + return textArea.remove(start, end); |
902 | + } |
903 | + |
904 | + /*! |
905 | + Undoes the last operation if undo is \l{canUndo}{available}. Deselects |
906 | + any current selection, and updates the selection start to the current |
907 | + cursor position. |
908 | + */ |
909 | + function undo() |
910 | + { |
911 | + textArea.undo(); |
912 | + } |
913 | + |
914 | + clip: true |
915 | + style: Qt.createComponent("TextEditorStyle.qml", rootItem) |
916 | + |
917 | + LayoutMirroring.enabled: Qt.application.layoutDirection == Qt.RightToLeft |
918 | + LayoutMirroring.childrenInherit: true |
919 | + |
920 | + Rectangle { |
921 | + color: rootItem.__styleInstance.backgroundColor |
922 | + anchors.fill: parent |
923 | + |
924 | + Rectangle { |
925 | + visible: rootItem.showRightMargin && (rootItem.rightMarginAtColumn > 0) |
926 | + color: rootItem.__styleInstance.secondaryBackgroundColor |
927 | + |
928 | + anchors { |
929 | + fill: parent |
930 | + leftMargin: dummyFont.paintedWidth * rootItem.rightMarginAtColumn + lineColumn.width + flicker.margin - flicker.contentX |
931 | + } |
932 | + |
933 | + Rectangle { |
934 | + height: parent.height |
935 | + anchors.left: parent.left |
936 | + width: rootItem.__styleInstance.dividerWidth |
937 | + color: rootItem.__styleInstance.dividerColor |
938 | + } |
939 | + } |
940 | + |
941 | + Rectangle { |
942 | + width: parent.width |
943 | + height: textArea.cursorRectangle.height |
944 | + |
945 | + y: textArea.cursorRectangle.y + flicker.margin - flicker.contentY |
946 | + color: rootItem.__styleInstance.currentLineHighlightColor |
947 | + opacity: 0.3 |
948 | + |
949 | + visible: rootItem.highlightCurrentLine && textArea.cursorVisible |
950 | + } |
951 | + } |
952 | + |
953 | + Flickable { |
954 | + id: flicker |
955 | + anchors.fill: parent |
956 | + |
957 | + property int margin: rootItem.__styleInstance.frameSpacing |
958 | + |
959 | + contentWidth: textArea.paintedWidth + lineColumn.width |
960 | + contentHeight: textArea.paintedHeight + flicker.margin * 2 |
961 | + |
962 | + boundsBehavior: Flickable.StopAtBounds |
963 | + |
964 | + LineNumberColumn { |
965 | + id: lineColumn |
966 | + |
967 | + color: rootItem.__styleInstance.secondaryBackgroundColor |
968 | + dividerColor: rootItem.__styleInstance.dividerColor |
969 | + fontColor: rootItem.__styleInstance.selectedTextColor |
970 | + dividerWidth: rootItem.__styleInstance.dividerWidth |
971 | + |
972 | + visible: rootItem.displayLineNumbers |
973 | + model: documentHandler.lineBlocks |
974 | + font: textArea.font |
975 | + |
976 | + height: Math.max(flicker.contentHeight, flicker.height) |
977 | + topMargin: flicker.margin |
978 | + } |
979 | + |
980 | + TextEdit { |
981 | + id: textArea |
982 | + |
983 | + focus: true |
984 | + width: rootItem.width - lineColumn.width |
985 | + height: Math.max(textArea.contentHeight, textArea.contentHeight) |
986 | + anchors { |
987 | + left: lineColumn.right |
988 | + top: parent.top |
989 | + margins: flicker.margin |
990 | + } |
991 | + |
992 | + mouseSelectionMode: TextEdit.SelectWords |
993 | + selectByMouse: false |
994 | + activeFocusOnPress: true |
995 | + |
996 | + color: rootItem.__styleInstance.color |
997 | + selectedTextColor: rootItem.__styleInstance.selectedTextColor |
998 | + selectionColor: rootItem.__styleInstance.selectionColor |
999 | + |
1000 | + // Work as a code editor |
1001 | + textFormat: TextEdit.PlainText |
1002 | + font.family: "UbuntuMono" |
1003 | + font.pixelSize: FontUtils.sizeToPixels("medium") |
1004 | + |
1005 | + wrapMode: rootItem.textWrap ? TextEdit.Wrap |
1006 | + : TextEdit.NoWrap |
1007 | + } |
1008 | + } |
1009 | + |
1010 | + Label { |
1011 | + id: dummyFont |
1012 | + text: "a" |
1013 | + font: textArea.font |
1014 | + visible: false |
1015 | + } |
1016 | + |
1017 | + DocumentHandler { |
1018 | + id: documentHandler |
1019 | + textEditItem: textArea |
1020 | + } |
1021 | + |
1022 | + Scrollbar { |
1023 | + id: rightScrollbar |
1024 | + flickableItem: flicker |
1025 | + } |
1026 | + |
1027 | + Scrollbar { |
1028 | + id: bottomScrollbar |
1029 | + flickableItem: flicker |
1030 | + align: Qt.AlignBottom |
1031 | + } |
1032 | +} |
1033 | + |
1034 | |
1035 | === added file 'src/plugin/text-qml-plugin/TextEditorStyle.qml' |
1036 | --- src/plugin/text-qml-plugin/TextEditorStyle.qml 1970-01-01 00:00:00 +0000 |
1037 | +++ src/plugin/text-qml-plugin/TextEditorStyle.qml 2015-04-30 18:50:23 +0000 |
1038 | @@ -0,0 +1,35 @@ |
1039 | +/* |
1040 | + * Copyright (C) 2015 Canonical, Ltd. |
1041 | + * |
1042 | + * This program is free software; you can redistribute it and/or modify |
1043 | + * it under the terms of the GNU General Public License as published by |
1044 | + * the Free Software Foundation; version 3. |
1045 | + * |
1046 | + * This program is distributed in the hope that it will be useful, |
1047 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1048 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1049 | + * GNU General Public License for more details. |
1050 | + * |
1051 | + * You should have received a copy of the GNU General Public License |
1052 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1053 | + */ |
1054 | + |
1055 | +import QtQuick 2.3 |
1056 | +import Ubuntu.Components 1.1 |
1057 | + |
1058 | +Item { |
1059 | + id: visuals |
1060 | + |
1061 | + property color backgroundColor: "white" |
1062 | + property color secondaryBackgroundColor: "#f2f2f2" |
1063 | + property color dividerColor: "#ddd" |
1064 | + property color currentLineHighlightColor: UbuntuColors.blue |
1065 | + |
1066 | + property color color: styledItem.activeFocus ? Theme.palette.selected.fieldText : Theme.palette.normal.fieldText |
1067 | + property color selectedTextColor: Theme.palette.selected.foregroundText |
1068 | + property color selectionColor: Theme.palette.selected.foreground |
1069 | + |
1070 | + property real frameSpacing: units.gu(1) |
1071 | + property real dividerWidth: units.gu(0.1) |
1072 | +} |
1073 | + |
1074 | |
1075 | === added file 'src/plugin/text-qml-plugin/backend.cpp' |
1076 | --- src/plugin/text-qml-plugin/backend.cpp 1970-01-01 00:00:00 +0000 |
1077 | +++ src/plugin/text-qml-plugin/backend.cpp 2015-04-30 18:50:23 +0000 |
1078 | @@ -0,0 +1,37 @@ |
1079 | +/* |
1080 | + * Copyright (C) 2013-2015 Canonical, Ltd. |
1081 | + * |
1082 | + * This program is free software: you can redistribute it and/or modify it |
1083 | + * under the terms of the GNU General Public License version 3, as published |
1084 | + * by the Free Software Foundation. |
1085 | + * |
1086 | + * This program is distributed in the hope that it will be useful, but |
1087 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1088 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1089 | + * PURPOSE. See the GNU General Public License for more details. |
1090 | + * |
1091 | + * You should have received a copy of the GNU General Public License along |
1092 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1093 | + * |
1094 | + */ |
1095 | + |
1096 | +#include <QtQml> |
1097 | +#include <QtQml/QQmlContext> |
1098 | + |
1099 | +#include "backend.h" |
1100 | +#include "documenthandler.h" |
1101 | +#include "filereader.h" |
1102 | + |
1103 | +void BackendPlugin::registerTypes(const char *uri) |
1104 | +{ |
1105 | + Q_ASSERT(uri == QLatin1String("DocumentViewer.Text")); |
1106 | + |
1107 | + //@uri DocumentViewer.Text |
1108 | + qmlRegisterType<FileReader>(uri, 1, 0, "TextReader"); |
1109 | + qmlRegisterType<DocumentHandler>(uri, 1, 0, "DocumentHandler"); |
1110 | +} |
1111 | + |
1112 | +void BackendPlugin::initializeEngine(QQmlEngine *engine, const char *uri) |
1113 | +{ |
1114 | + QQmlExtensionPlugin::initializeEngine(engine, uri); |
1115 | +} |
1116 | |
1117 | === added file 'src/plugin/text-qml-plugin/backend.h' |
1118 | --- src/plugin/text-qml-plugin/backend.h 1970-01-01 00:00:00 +0000 |
1119 | +++ src/plugin/text-qml-plugin/backend.h 2015-04-30 18:50:23 +0000 |
1120 | @@ -0,0 +1,34 @@ |
1121 | +/* |
1122 | + * Copyright (C) 2013-2015 Canonical, Ltd. |
1123 | + * |
1124 | + * This program is free software: you can redistribute it and/or modify it |
1125 | + * under the terms of the GNU General Public License version 3, as published |
1126 | + * by the Free Software Foundation. |
1127 | + * |
1128 | + * This program is distributed in the hope that it will be useful, but |
1129 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1130 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1131 | + * PURPOSE. See the GNU General Public License for more details. |
1132 | + * |
1133 | + * You should have received a copy of the GNU General Public License along |
1134 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1135 | + * |
1136 | + */ |
1137 | + |
1138 | +#ifndef BACKEND_PLUGIN_H |
1139 | +#define BACKEND_PLUGIN_H |
1140 | + |
1141 | +#include <QtQml/QQmlEngine> |
1142 | +#include <QtQml/QQmlExtensionPlugin> |
1143 | + |
1144 | +class BackendPlugin : public QQmlExtensionPlugin |
1145 | +{ |
1146 | + Q_OBJECT |
1147 | + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") |
1148 | + |
1149 | +public: |
1150 | + void registerTypes(const char *uri); |
1151 | + void initializeEngine(QQmlEngine *engine, const char *uri); |
1152 | +}; |
1153 | +#endif // BACKEND_PLUGIN_H |
1154 | + |
1155 | |
1156 | === added file 'src/plugin/text-qml-plugin/documenthandler.cpp' |
1157 | --- src/plugin/text-qml-plugin/documenthandler.cpp 1970-01-01 00:00:00 +0000 |
1158 | +++ src/plugin/text-qml-plugin/documenthandler.cpp 2015-04-30 18:50:23 +0000 |
1159 | @@ -0,0 +1,108 @@ |
1160 | +/**************************************************************************** |
1161 | +** |
1162 | +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). |
1163 | +** Contact: http://www.qt-project.org/legal |
1164 | +** |
1165 | +** This file is part of the Qt Quick Controls module of the Qt Toolkit. |
1166 | +** |
1167 | +** $QT_BEGIN_LICENSE:BSD$ |
1168 | +** You may use this file under the terms of the BSD license as follows: |
1169 | +** |
1170 | +** "Redistribution and use in source and binary forms, with or without |
1171 | +** modification, are permitted provided that the following conditions are |
1172 | +** met: |
1173 | +** * Redistributions of source code must retain the above copyright |
1174 | +** notice, this list of conditions and the following disclaimer. |
1175 | +** * Redistributions in binary form must reproduce the above copyright |
1176 | +** notice, this list of conditions and the following disclaimer in |
1177 | +** the documentation and/or other materials provided with the |
1178 | +** distribution. |
1179 | +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names |
1180 | +** of its contributors may be used to endorse or promote products derived |
1181 | +** from this software without specific prior written permission. |
1182 | +** |
1183 | +** |
1184 | +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
1185 | +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
1186 | +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
1187 | +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
1188 | +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
1189 | +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
1190 | +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
1191 | +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
1192 | +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
1193 | +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
1194 | +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." |
1195 | +** |
1196 | +** $QT_END_LICENSE$ |
1197 | +** |
1198 | +****************************************************************************/ |
1199 | + |
1200 | +#include "documenthandler.h" |
1201 | + |
1202 | +#include <QtGui/QTextDocument> |
1203 | +#include <QtGui/QTextBlock> |
1204 | +#include <QtGui/QTextLayout> |
1205 | + |
1206 | +DocumentHandler::DocumentHandler() : |
1207 | + m_textEditItem(nullptr), |
1208 | + m_doc(nullptr) |
1209 | +{ |
1210 | + // |
1211 | +} |
1212 | + |
1213 | +void DocumentHandler::setTextEditItem(QQuickItem *textEditItem) |
1214 | +{ |
1215 | + if (textEditItem == m_textEditItem) |
1216 | + return; |
1217 | + |
1218 | + QString className(textEditItem->metaObject()->className()); |
1219 | + if (className != "QQuickTextEdit") { |
1220 | + qWarning() << "Item passed as argument is not a QQuickTextEdit. Aborting..."; |
1221 | + return; |
1222 | + } |
1223 | + |
1224 | + m_doc = nullptr; |
1225 | + m_textEditItem = textEditItem; |
1226 | + |
1227 | + QVariant doc = m_textEditItem->property("textDocument"); |
1228 | + if (doc.canConvert<QQuickTextDocument*>()) { |
1229 | + QQuickTextDocument *qqdoc = doc.value<QQuickTextDocument*>(); |
1230 | + |
1231 | + if (qqdoc) { |
1232 | + m_doc = qqdoc->textDocument(); |
1233 | + |
1234 | + // TODO: We can also use lengthChanged() from TextEdit? |
1235 | + connect(m_doc, SIGNAL(contentsChanged()), this, SLOT(updateLineBlocks())); |
1236 | + connect(m_textEditItem, SIGNAL(contentSizeChanged()), this, SLOT(updateLineBlocks())); |
1237 | + connect(m_textEditItem, SIGNAL(wrapModeChanged()), this, SLOT(updateLineBlocks())); |
1238 | + } |
1239 | + } |
1240 | + |
1241 | + Q_EMIT textEditItemChanged(); |
1242 | +} |
1243 | + |
1244 | +void DocumentHandler::updateLineBlocks() |
1245 | +{ |
1246 | + m_lineBlocks.clear(); |
1247 | + |
1248 | + QTextBlock block = m_doc->firstBlock(); |
1249 | + int blockNumber = block.blockNumber(); |
1250 | + qreal blockHeight; |
1251 | + |
1252 | + while (blockNumber < m_doc->blockCount()) { |
1253 | + blockHeight = block.layout()->boundingRect().height(); |
1254 | + |
1255 | + QVariantMap map; |
1256 | + map["lineNumber"] = blockNumber; |
1257 | + map["lineHeight"] = blockHeight; |
1258 | + |
1259 | + m_lineBlocks.append(map); |
1260 | + |
1261 | + block = block.next(); |
1262 | + blockNumber++; |
1263 | + } |
1264 | + |
1265 | + Q_EMIT lineBlocksChanged(); |
1266 | +} |
1267 | + |
1268 | |
1269 | === added file 'src/plugin/text-qml-plugin/documenthandler.h' |
1270 | --- src/plugin/text-qml-plugin/documenthandler.h 1970-01-01 00:00:00 +0000 |
1271 | +++ src/plugin/text-qml-plugin/documenthandler.h 2015-04-30 18:50:23 +0000 |
1272 | @@ -0,0 +1,85 @@ |
1273 | +/**************************************************************************** |
1274 | +** |
1275 | +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). |
1276 | +** Contact: http://www.qt-project.org/legal |
1277 | +** |
1278 | +** This file is part of the Qt Quick Controls module of the Qt Toolkit. |
1279 | +** |
1280 | +** $QT_BEGIN_LICENSE:BSD$ |
1281 | +** You may use this file under the terms of the BSD license as follows: |
1282 | +** |
1283 | +** "Redistribution and use in source and binary forms, with or without |
1284 | +** modification, are permitted provided that the following conditions are |
1285 | +** met: |
1286 | +** * Redistributions of source code must retain the above copyright |
1287 | +** notice, this list of conditions and the following disclaimer. |
1288 | +** * Redistributions in binary form must reproduce the above copyright |
1289 | +** notice, this list of conditions and the following disclaimer in |
1290 | +** the documentation and/or other materials provided with the |
1291 | +** distribution. |
1292 | +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names |
1293 | +** of its contributors may be used to endorse or promote products derived |
1294 | +** from this software without specific prior written permission. |
1295 | +** |
1296 | +** |
1297 | +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
1298 | +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
1299 | +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
1300 | +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
1301 | +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
1302 | +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
1303 | +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
1304 | +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
1305 | +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
1306 | +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
1307 | +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." |
1308 | +** |
1309 | +** $QT_END_LICENSE$ |
1310 | +** |
1311 | +****************************************************************************/ |
1312 | + |
1313 | +#ifndef DOCUMENTHANDLER_H |
1314 | +#define DOCUMENTHANDLER_H |
1315 | + |
1316 | +#include <QQuickTextDocument> |
1317 | + |
1318 | +#include <QtGui/QTextCharFormat> |
1319 | +#include <QtCore/QTextCodec> |
1320 | + |
1321 | +#include <qqmlfile.h> |
1322 | + |
1323 | +QT_BEGIN_NAMESPACE |
1324 | +class QTextDocument; |
1325 | +QT_END_NAMESPACE |
1326 | + |
1327 | +class DocumentHandler : public QObject |
1328 | +{ |
1329 | + Q_OBJECT |
1330 | + |
1331 | + Q_PROPERTY(QQuickItem *textEditItem READ textEditItem WRITE setTextEditItem NOTIFY textEditItemChanged) |
1332 | + Q_PROPERTY(QVariantList lineBlocks READ lineBlocks NOTIFY lineBlocksChanged) |
1333 | + |
1334 | +public: |
1335 | + DocumentHandler(); |
1336 | + |
1337 | + QQuickItem *textEditItem() { return m_textEditItem; } |
1338 | + void setTextEditItem(QQuickItem *textEditItem); |
1339 | + |
1340 | + QVariantList lineBlocks() { return m_lineBlocks; } |
1341 | + |
1342 | +Q_SIGNALS: |
1343 | + void textEditItemChanged(); |
1344 | + void lineBlocksChanged(); |
1345 | + void highlighterChanged(); |
1346 | + |
1347 | +private slots: |
1348 | + void updateLineBlocks(); |
1349 | + |
1350 | +private: |
1351 | + QQuickItem *m_textEditItem; |
1352 | + QTextDocument *m_doc; |
1353 | + |
1354 | + QVariantList m_lineBlocks; |
1355 | +}; |
1356 | + |
1357 | +#endif |
1358 | |
1359 | === added file 'src/plugin/text-qml-plugin/filereader.cpp' |
1360 | --- src/plugin/text-qml-plugin/filereader.cpp 1970-01-01 00:00:00 +0000 |
1361 | +++ src/plugin/text-qml-plugin/filereader.cpp 2015-04-30 18:50:23 +0000 |
1362 | @@ -0,0 +1,110 @@ |
1363 | +/* |
1364 | + * Copyright (C) 2013, 2015 Canonical, Ltd. |
1365 | + * |
1366 | + * This program is free software; you can redistribute it and/or modify |
1367 | + * it under the terms of the GNU General Public License as published by |
1368 | + * the Free Software Foundation; version 3. |
1369 | + * |
1370 | + * This program is distributed in the hope that it will be useful, |
1371 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1372 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1373 | + * GNU General Public License for more details. |
1374 | + * |
1375 | + * You should have received a copy of the GNU General Public License |
1376 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1377 | + */ |
1378 | + |
1379 | +#include <QFile> |
1380 | +#include <QObject> |
1381 | +#include <QDebug> |
1382 | +#include <QTextStream> |
1383 | + |
1384 | +#include "filereader.h" |
1385 | + |
1386 | +FileReader::FileReader(QObject *parent) : |
1387 | + QObject(parent), |
1388 | + m_path(""), |
1389 | + m_status(Status::Null) |
1390 | +{ |
1391 | + qRegisterMetaType<Status>("Status"); |
1392 | +} |
1393 | + |
1394 | +FileReader::~FileReader() { |
1395 | + |
1396 | +} |
1397 | + |
1398 | +void FileReader::setPath(QString path) { |
1399 | + |
1400 | + if (path == m_path && path.isEmpty()) |
1401 | + return; |
1402 | + |
1403 | + m_path = path; |
1404 | + Q_EMIT pathChanged(); |
1405 | + |
1406 | + ReaderThread *p = new ReaderThread(); |
1407 | + p->setFilePath(path); |
1408 | + |
1409 | + connect(p, SIGNAL(fileRead(QString)), this, SLOT(setFileString(QString))); |
1410 | + connect(p, SIGNAL(errorChanged(QString)), this, SLOT(setErrorString(QString))); |
1411 | + connect(p, SIGNAL(statusChanged(Status)), this, SLOT(setStatus(Status))); |
1412 | + connect(p, SIGNAL(finished()), p, SLOT(deleteLater())); |
1413 | + |
1414 | + p->start(); |
1415 | +} |
1416 | + |
1417 | +void FileReader::setFileString(QString string) |
1418 | +{ |
1419 | + if (m_fileString != string) { |
1420 | + m_fileString = string; |
1421 | + Q_EMIT fileStringChanged(); |
1422 | + } |
1423 | +} |
1424 | + |
1425 | +void FileReader::setStatus(Status status) |
1426 | +{ |
1427 | + if (m_status != status) { |
1428 | + m_status = status; |
1429 | + Q_EMIT statusChanged(); |
1430 | + } |
1431 | +} |
1432 | + |
1433 | +void FileReader::setErrorString(QString errorString) |
1434 | +{ |
1435 | + if (m_errorString != errorString) { |
1436 | + m_errorString = errorString; |
1437 | + Q_EMIT errorStringChanged(); |
1438 | + } |
1439 | +} |
1440 | + |
1441 | +void ReaderThread::run() { |
1442 | + if (!m_path.isEmpty()) { |
1443 | + Q_EMIT statusChanged(Status::Loading); |
1444 | + |
1445 | + QFile file(m_path); |
1446 | + |
1447 | + if (!file.open(QFile::ReadOnly | QFile::Text)) |
1448 | + { |
1449 | + qWarning() << "Could not open file for reading."; |
1450 | + |
1451 | + Q_EMIT statusChanged(Status::Error); |
1452 | + Q_EMIT errorChanged(tr("Could not open file for reading.")); |
1453 | + Q_EMIT fileRead(QString("")); |
1454 | + } |
1455 | + |
1456 | + QTextStream in(&file); |
1457 | + QString text = in.readAll(); |
1458 | + |
1459 | + file.flush(); |
1460 | + file.close(); |
1461 | + |
1462 | + Q_EMIT statusChanged(Status::Ready); |
1463 | + Q_EMIT errorChanged(QString("")); |
1464 | + Q_EMIT fileRead(text); |
1465 | + } else { |
1466 | + qWarning() << "No file specified."; |
1467 | + |
1468 | + Q_EMIT statusChanged(Status::Error); |
1469 | + Q_EMIT errorChanged(tr("No file specified.")); |
1470 | + Q_EMIT fileRead(QString("")); |
1471 | + } |
1472 | +} |
1473 | |
1474 | === added file 'src/plugin/text-qml-plugin/filereader.h' |
1475 | --- src/plugin/text-qml-plugin/filereader.h 1970-01-01 00:00:00 +0000 |
1476 | +++ src/plugin/text-qml-plugin/filereader.h 2015-04-30 18:50:23 +0000 |
1477 | @@ -0,0 +1,97 @@ |
1478 | +/* |
1479 | + * Copyright (C) 2013, 2015 Canonical, Ltd. |
1480 | + * |
1481 | + * This program is free software; you can redistribute it and/or modify |
1482 | + * it under the terms of the GNU General Public License as published by |
1483 | + * the Free Software Foundation; version 3. |
1484 | + * |
1485 | + * This program is distributed in the hope that it will be useful, |
1486 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1487 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1488 | + * GNU General Public License for more details. |
1489 | + * |
1490 | + * You should have received a copy of the GNU General Public License |
1491 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1492 | + */ |
1493 | + |
1494 | +#ifndef FILEREADER_H |
1495 | +#define FILEREADER_H |
1496 | + |
1497 | +#include <QObject> |
1498 | +#include <QThread> |
1499 | + |
1500 | +class FileReader: public QObject |
1501 | +{ |
1502 | + Q_OBJECT |
1503 | + Q_PROPERTY(QString path READ getPath WRITE setPath NOTIFY pathChanged) |
1504 | + Q_PROPERTY(QString fileString READ getfileString NOTIFY fileStringChanged) |
1505 | + Q_PROPERTY(Status status READ getStatus NOTIFY statusChanged) |
1506 | + Q_PROPERTY(QString errorString READ getErrorString NOTIFY errorStringChanged) |
1507 | + Q_ENUMS(Status) |
1508 | + |
1509 | +public: |
1510 | + explicit FileReader(QObject *parent = 0); |
1511 | + ~FileReader(); |
1512 | + |
1513 | + enum Status |
1514 | + { |
1515 | + Null, |
1516 | + Ready, |
1517 | + Loading, |
1518 | + Error |
1519 | + }; |
1520 | + |
1521 | + QString getPath() { return m_path; } |
1522 | + void setPath(QString path); |
1523 | + |
1524 | + QString getErrorString() { return m_errorString; } |
1525 | + |
1526 | + QString getfileString() { return m_fileString; } |
1527 | + |
1528 | + Status getStatus() { return m_status; } |
1529 | + |
1530 | +Q_SIGNALS: |
1531 | + void pathChanged(); |
1532 | + void fileStringChanged(); |
1533 | + void statusChanged(); |
1534 | + void errorStringChanged(); |
1535 | + |
1536 | +private slots: |
1537 | + void setFileString(QString string); |
1538 | + void setStatus(Status status); |
1539 | + void setErrorString(QString errorString); |
1540 | + |
1541 | +private: |
1542 | + QString m_path; |
1543 | + QString m_fileString; |
1544 | + Status m_status; |
1545 | + QString m_errorString; |
1546 | +}; |
1547 | + |
1548 | +class ReaderThread : public QThread |
1549 | +{ |
1550 | + Q_OBJECT |
1551 | + Q_ENUMS(Status) |
1552 | + |
1553 | +public: |
1554 | + enum Status |
1555 | + { |
1556 | + Null, |
1557 | + Ready, |
1558 | + Loading, |
1559 | + Error |
1560 | + }; |
1561 | + |
1562 | + void run(); |
1563 | + void setFilePath(QString path) { m_path = path; } |
1564 | + |
1565 | +Q_SIGNALS: |
1566 | + void errorChanged(QString error); |
1567 | + void fileRead(QString fileString); |
1568 | + void statusChanged(Status status); |
1569 | + |
1570 | +private: |
1571 | + QString m_path; |
1572 | +}; |
1573 | + |
1574 | +#endif // FILEREADER_H |
1575 | |
1576 | === added file 'src/plugin/text-qml-plugin/qmldir' |
1577 | --- src/plugin/text-qml-plugin/qmldir 1970-01-01 00:00:00 +0000 |
1578 | +++ src/plugin/text-qml-plugin/qmldir 2015-04-30 18:50:23 +0000 |
1579 | @@ -0,0 +1,7 @@ |
1580 | +module DocumentViewer.Text |
1581 | +plugin textqmlplugin |
1582 | + |
1583 | +TextEditor 1.0 TextEditor.qml |
1584 | +TextEditorStyle 1.0 TextEditorStyle.qml |
1585 | + |
1586 | +internal LineNumberColumn LineNumberColumn.qml |
1587 | |
1588 | === modified file 'tests/autopilot/ubuntu_docviewer_app/tests/test_docviewer.py' |
1589 | --- tests/autopilot/ubuntu_docviewer_app/tests/test_docviewer.py 2015-04-14 15:37:06 +0000 |
1590 | +++ tests/autopilot/ubuntu_docviewer_app/tests/test_docviewer.py 2015-04-30 18:50:23 +0000 |
1591 | @@ -29,7 +29,7 @@ |
1592 | self.launch_app() |
1593 | |
1594 | text_area = self.app.main_view.select_single( |
1595 | - "TextArea", objectName="textAreaMain") |
1596 | + "TextEditor", objectName="editor") |
1597 | |
1598 | self.assertThat( |
1599 | text_area.text, Eventually(Equals('TEST\n'))) |
FAILED: Continuous integration, rev:143 91.189. 93.70:8080/ job/ubuntu- docviewer- app-ci/ 206/ 91.189. 93.70:8080/ job/generic- mediumtests- utopic/ 2690 91.189. 93.70:8080/ job/generic- mediumtests- utopic/ 2690/artifact/ work/output/ *zip*/output. zip 91.189. 93.70:8080/ job/ubuntu- docviewer- app-utopic- amd64-ci/ 103 91.189. 93.70:8080/ job/ubuntu- docviewer- app-vivid- amd64-ci/ 109
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: 91.189. 93.70:8080/ job/ubuntu- docviewer- app-ci/ 206/rebuild
http://