Merge lp:~mzanetti/reminders-app/html2enml into lp:reminders-app

Proposed by Michael Zanetti
Status: Merged
Approved by: David Planella
Approved revision: 13
Merged at revision: 11
Proposed branch: lp:~mzanetti/reminders-app/html2enml
Merge into: lp:reminders-app
Prerequisite: lp:~mzanetti/reminders-app/create-edit-delete-notes
Diff against target: 181 lines (+109/-8)
5 files modified
src/app/qml/ui/NotePage.qml (+1/-5)
src/plugin/Evernote/Evernote.pro (+5/-3)
src/plugin/Evernote/notesstore.cpp (+5/-0)
src/plugin/Evernote/utils/html2enmlconverter.cpp (+84/-0)
src/plugin/Evernote/utils/html2enmlconverter.h (+14/-0)
To merge this branch: bzr merge lp:~mzanetti/reminders-app/html2enml
Reviewer Review Type Date Requested Status
David Planella Approve
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve
Review via email: mp+196616@code.launchpad.net

Commit message

"properly" convert html back to enml. Loses images and tables but works quite well for all the rest.

Description of the change

Loses images and tables but works quite well for all the rest.

This is the Getting started note looks before editing on the phone:
http://i.imgur.com/ThrtJXe.png

This is how it looks afterwards:
http://i.imgur.com/aPrcs9x.png

I think this is pretty much the furthest we can get with a sane amount of efforts. Given that the TextArea isn't capable of displaying images and tables this stuff gets actually lost when converting the other way round.

To post a comment you must log in.
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
David Planella (dpm) wrote :

I agree that this is the way to go for now.

In the future though, we'll need to display images and tables, and I understand that the TextArea won't help us there. What do you think we should eventually use? A WebView instead of TextArea?

review: Approve
Revision history for this message
Randy Baumgarte (randy-fbn) wrote :

I haven't been to active here. Sorry but I haven't had the free time.

For NixNote I accomplished this by subclassing QWebView. Most of the
fancier stuff for editing and highlighting I accomplished with a bunch of
JavaScript hacks by using the JavaScript/Qt bridge and setting custom tag
elements.

The biggest problem I've encountered is Evernote doesn't allow some of the
things QWebView creates when using it as an editor, so saving it requires
some cleanup or you'll get rejected when uploading the note. WebView is
also nice because it can walk the DOM tree reasonably well since you need
to do all the en-media tag changes.

On Tue, Nov 26, 2013 at 7:55 AM, David Planella
<email address hidden>wrote:

> Review: Approve
>
> I agree that this is the way to go for now.
>
> In the future though, we'll need to display images and tables, and I
> understand that the TextArea won't help us there. What do you think we
> should eventually use? A WebView instead of TextArea?
> --
> https://code.launchpad.net/~mzanetti/reminders-app/html2enml/+merge/196616
> Your team Ubuntu Reminders app developers is subscribed to branch
> lp:reminders-app.
>

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/app/qml/ui/NotePage.qml'
2--- src/app/qml/ui/NotePage.qml 2013-11-25 19:10:47 +0000
3+++ src/app/qml/ui/NotePage.qml 2013-11-25 19:10:47 +0000
4@@ -13,11 +13,7 @@
5 width: parent.width
6 text: "save"
7 onClicked: {
8- print("timer triggered")
9- var content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml2.dtd\"><en-note><div><br clear=\"none\"/>"
10- content = content + noteTextArea.getText(0, noteTextArea.length)
11- content = content + "<br clear=\"none\"/></div><div><br clear=\"none\"/></div></en-note>"
12- note.content = content
13+ note.content = noteTextArea.text
14 note.save();
15 }
16 }
17
18=== modified file 'src/plugin/Evernote/Evernote.pro'
19--- src/plugin/Evernote/Evernote.pro 2013-11-25 19:10:47 +0000
20+++ src/plugin/Evernote/Evernote.pro 2013-11-25 19:10:47 +0000
21@@ -1,7 +1,7 @@
22 TARGET=evernoteplugin
23 TEMPLATE=lib
24 CONFIG = qt plugin
25-QT += qml gui
26+QT += qml gui xml
27 QMAKE_CXXFLAGS += -std=c++0x -fPIC
28
29 INCLUDEPATH += ../../../3rdParty/evernote-sdk-cpp/src/ ../../../3rdParty/libthrift
30@@ -22,7 +22,8 @@
31 jobs/createnotejob.cpp \
32 jobs/evernotejob.cpp \
33 jobs/savenotejob.cpp \
34- jobs/deletenotejob.cpp
35+ jobs/deletenotejob.cpp \
36+ utils/html2enmlconverter.cpp
37
38 HEADERS += evernoteplugin.h \
39 notesstore.h \
40@@ -37,7 +38,8 @@
41 jobs/createnotejob.h \
42 jobs/evernotejob.h \
43 jobs/savenotejob.h \
44- jobs/deletenotejob.h
45+ jobs/deletenotejob.h \
46+ utils/html2enmlconverter.h
47
48 message(building in $$OUT_PWD)
49 LIBS += -L$$OUT_PWD/../../../3rdParty/evernote-sdk-cpp/ -L$$OUT_PWD/../../../3rdParty/libthrift/ -levernote-sdk-cpp -llibthrift
50
51=== modified file 'src/plugin/Evernote/notesstore.cpp'
52--- src/plugin/Evernote/notesstore.cpp 2013-11-25 19:10:47 +0000
53+++ src/plugin/Evernote/notesstore.cpp 2013-11-25 19:10:47 +0000
54@@ -2,6 +2,7 @@
55 #include "notebooks.h"
56 #include "notebook.h"
57 #include "note.h"
58+#include "utils/html2enmlconverter.h"
59
60 #include "jobs/fetchnotesjob.h"
61 #include "jobs/fetchnotebooksjob.h"
62@@ -133,6 +134,10 @@
63 void NotesStore::saveNote(const QString &guid)
64 {
65 Note *note = m_notes.value(guid);
66+
67+ QString enml = Html2EnmlConverter::html2enml(note->content());
68+ note->setContent(enml);
69+
70 SaveNoteJob *job = new SaveNoteJob(note, this);
71 connect(job, &SaveNoteJob::resultReady, this, &NotesStore::saveNoteJobDone);
72 m_jobQueue.append(job);
73
74=== added directory 'src/plugin/Evernote/utils'
75=== added file 'src/plugin/Evernote/utils/html2enmlconverter.cpp'
76--- src/plugin/Evernote/utils/html2enmlconverter.cpp 1970-01-01 00:00:00 +0000
77+++ src/plugin/Evernote/utils/html2enmlconverter.cpp 2013-11-25 19:10:47 +0000
78@@ -0,0 +1,84 @@
79+#include "html2enmlconverter.h"
80+
81+#include <QXmlStreamReader>
82+#include <QXmlStreamWriter>
83+#include <QStringList>
84+
85+// Taken from http://xml.evernote.com/pub/enml2.dtd
86+QStringList supportedTags = QStringList() << "a" << "abbr" << "acronym" << "address" << "area" << "b" << "bdo" << "big" <<
87+ "blockquote" << "br" << "caption" << "center" << "cite" << "code" << "col" <<
88+ "colgroup" << "dd" << "del" << "dfn" << "div" << "dl" << "dt" << "em" <<
89+ "en-crypt" << "en-media" << "en-todo" << "font" << "h1" << "h2" << "h3" <<
90+ "h4" << "h5" << "h6" << "hr" << "i" << "img" << "ins" << "kbd" << "li" <<
91+ "map" << "ol" << "p" << "pre" << "q" << "s" << "samp" << "small" << "span" <<
92+ "strike" << "strong" << "sub" << "sup" << "table" << "tbody" << "td" <<
93+ "tfoot" << "th" << "thead" << "tr" << "tt" << "u" << "ul" << "var";
94+
95+
96+Html2EnmlConverter::Html2EnmlConverter()
97+{
98+}
99+
100+QString Html2EnmlConverter::html2enml(const QString &html)
101+{
102+ // output
103+ QString evml;
104+ QXmlStreamWriter writer(&evml);
105+ writer.writeStartDocument();
106+ writer.writeDTD("<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml2.dtd\">");
107+
108+ // input
109+ QXmlStreamReader reader(html);
110+
111+ // state
112+ bool isBody = false;
113+
114+ while (!reader.atEnd() && !reader.hasError()) {
115+ QXmlStreamReader::TokenType token = reader.readNext();
116+ if(token == QXmlStreamReader::StartDocument) {
117+ continue;
118+ }
119+
120+ // Handle start elements
121+ if(token == QXmlStreamReader::StartElement) {
122+ // skip everything if body hasn't started yet
123+ if (!isBody) {
124+ if (reader.name() == "body") {
125+ writer.writeStartElement("en-note");
126+ isBody = true;
127+ }
128+ continue;
129+ }
130+ // Write supported start elements to output (including attributes)
131+ if (supportedTags.contains(reader.name().toString())) {
132+ writer.writeStartElement(reader.name().toString());
133+ writer.writeAttributes(reader.attributes());
134+ }
135+ }
136+
137+ // Write *all* normal text inside <body> </body> to output
138+ if (isBody && token == QXmlStreamReader::Characters) {
139+ writer.writeCharacters(reader.text().toString());
140+ }
141+
142+ // handle end elements
143+ if (token == QXmlStreamReader::EndElement) {
144+
145+ // skip everything after body
146+ if (reader.name() == "body") {
147+ writer.writeEndElement();
148+ isBody = false;
149+ break;
150+ }
151+
152+ // Write closing tags for supported elements
153+ if (supportedTags.contains(reader.name().toString())) {
154+ writer.writeEndElement();
155+ }
156+ }
157+ }
158+
159+ writer.writeEndDocument();
160+
161+ return evml;
162+}
163
164=== added file 'src/plugin/Evernote/utils/html2enmlconverter.h'
165--- src/plugin/Evernote/utils/html2enmlconverter.h 1970-01-01 00:00:00 +0000
166+++ src/plugin/Evernote/utils/html2enmlconverter.h 2013-11-25 19:10:47 +0000
167@@ -0,0 +1,14 @@
168+#ifndef HTML2ENMLCONVERTER_H
169+#define HTML2ENMLCONVERTER_H
170+
171+#include <QString>
172+
173+class Html2EnmlConverter
174+{
175+public:
176+ Html2EnmlConverter();
177+
178+ static QString html2enml(const QString &html);
179+};
180+
181+#endif // HTML2ENMLCONVERTER_H

Subscribers

People subscribed via source and target branches