OSDN Git Service

Added LaTex image insert & edit
[neighbornote/NeighborNote.git] / src / cx / fbn / nevernote / xml / NoteFormatter.java
1 package cx.fbn.nevernote.xml;\r
2 \r
3 import java.io.File;\r
4 import java.util.ArrayList;\r
5 import java.util.List;\r
6 \r
7 import com.evernote.edam.type.Note;\r
8 import com.evernote.edam.type.Resource;\r
9 import com.trolltech.qt.core.QByteArray;\r
10 import com.trolltech.qt.core.QDataStream;\r
11 import com.trolltech.qt.core.QFile;\r
12 import com.trolltech.qt.core.QIODevice;\r
13 import com.trolltech.qt.core.QIODevice.OpenModeFlag;\r
14 import com.trolltech.qt.core.QTemporaryFile;\r
15 import com.trolltech.qt.core.QUrl;\r
16 import com.trolltech.qt.core.Qt.BGMode;\r
17 import com.trolltech.qt.gui.QColor;\r
18 import com.trolltech.qt.gui.QPainter;\r
19 import com.trolltech.qt.gui.QPainter.RenderHint;\r
20 import com.trolltech.qt.gui.QPixmap;\r
21 import com.trolltech.qt.xml.QDomAttr;\r
22 import com.trolltech.qt.xml.QDomDocument;\r
23 import com.trolltech.qt.xml.QDomElement;\r
24 import com.trolltech.qt.xml.QDomNodeList;\r
25 \r
26 import cx.fbn.nevernote.Global;\r
27 import cx.fbn.nevernote.config.FileManager;\r
28 import cx.fbn.nevernote.filters.EnSearch;\r
29 import cx.fbn.nevernote.gui.PDFPreview;\r
30 import cx.fbn.nevernote.sql.DatabaseConnection;\r
31 import cx.fbn.nevernote.utilities.ApplicationLogger;\r
32 \r
33 public class NoteFormatter {\r
34 \r
35         private final ApplicationLogger logger;\r
36         private final DatabaseConnection conn;\r
37         public boolean resourceError = false;\r
38         public boolean readOnly = false; \r
39         public boolean inkNote = false;\r
40         public boolean addHighlight = true;\r
41         private Note currentNote;\r
42         private String currentNoteGuid;\r
43         private boolean pdfPreview;\r
44         ArrayList<QTemporaryFile> tempFiles;\r
45         private EnSearch enSearch;\r
46         private boolean noteHistory;\r
47         \r
48         public NoteFormatter(ApplicationLogger logger, DatabaseConnection conn, List<QTemporaryFile> tempFiles2) {\r
49                 this.logger = logger;\r
50                 this.conn = conn;\r
51                 noteHistory = false;\r
52         }\r
53         \r
54         \r
55         public void setNote(Note note, boolean pdfPreview) {\r
56                 currentNote = note;\r
57                 this.pdfPreview = pdfPreview;\r
58                 readOnly = false;\r
59                 currentNoteGuid = null;\r
60                 if (note != null) {\r
61                         currentNoteGuid = note.getGuid();\r
62                         readOnly = conn.getNotebookTable().isReadOnly(note.getNotebookGuid());\r
63                 } \r
64                 resourceError = false;\r
65         }\r
66         \r
67         public void setHighlight(EnSearch search) {\r
68                 if (search==null || search.hilightWords == null ||search.hilightWords.size() == 0) {\r
69                         enSearch = null;\r
70                         addHighlight = false;\r
71                 } else {\r
72                         enSearch = search;\r
73                         addHighlight = true;\r
74                 }\r
75         }\r
76         \r
77         // Set if we are coming here through note histary.  It triggers longer file names to avoid conflicts\r
78         public void setNoteHistory(boolean value) {\r
79                 noteHistory = value;\r
80         }\r
81         \r
82         // Rebuild the note HTML to something usable\r
83         public String rebuildNoteHTML() {\r
84                 if (currentNote == null)\r
85                         return null;\r
86                 logger.log(logger.HIGH, "Entering NeverNote.rebuildNoteHTML");\r
87                 logger.log(logger.EXTREME, "Note guid: " +currentNoteGuid);\r
88                 logger.log(logger.EXTREME, "Note Text:" +currentNote);\r
89                 QDomDocument doc = new QDomDocument();\r
90                 QDomDocument.Result result = doc.setContent(currentNote.getContent());\r
91                 if (!result.success) {\r
92                         logger.log(logger.MEDIUM, "Parse error when rebuilding HTML");\r
93                         logger.log(logger.MEDIUM, "Note guid: " +currentNoteGuid);\r
94                         logger.log(logger.EXTREME, "Start of unmodified note HTML");\r
95                         logger.log(logger.EXTREME, currentNote.getContent());\r
96                         logger.log(logger.EXTREME, "End of unmodified note HTML");\r
97                         return currentNote.getContent();\r
98                 }\r
99 \r
100                 if (tempFiles == null)\r
101                         tempFiles = new ArrayList<QTemporaryFile>();\r
102                 tempFiles.clear();\r
103                 \r
104                 doc = modifyTags(doc);\r
105                 if (addHighlight)\r
106                         doc = addHilight(doc);\r
107                 QDomElement docElem = doc.documentElement();\r
108                 docElem.setTagName("Body");\r
109 //              docElem.setAttribute("bgcolor", "green");\r
110                 logger.log(logger.EXTREME, "Rebuilt HTML:");\r
111                 logger.log(logger.EXTREME, doc.toString());     \r
112                 logger.log(logger.HIGH, "Leaving NeverNote.rebuildNoteHTML");\r
113                 // Fix the stupid problem where inserting an <img> tag after an <a> tag (which is done\r
114                 // to get the <en-media> application tag to work properly) causes spaces to be inserted\r
115                 // between the <a> & <img>.  This messes things up later.  This is an ugly hack.\r
116                 StringBuffer html = new StringBuffer(doc.toString());\r
117                 for (int i=html.indexOf("<a en-tag=\"en-media\" ", 0); i>-1; i=html.indexOf("<a en-tag=\"en-media\" ", i)) {\r
118                         i=html.indexOf(">\n",i+1);\r
119                         int z = html.indexOf("<img",i);\r
120                         for (int j=z-1; j>i; j--) \r
121                                 html.deleteCharAt(j);\r
122                         i=html.indexOf("/>", z+1);\r
123                         z = html.indexOf("</a>",i);\r
124                         for (int j=z-1; j>i+1; j--) \r
125                                 html.deleteCharAt(j);\r
126                 } \r
127                 return html.toString();\r
128         }       \r
129 \r
130         private void addImageHilight(String resGuid, QFile f) {\r
131                 if (enSearch == null || enSearch.hilightWords == null || enSearch.hilightWords.size() == 0)\r
132                         return;\r
133                 \r
134                 // Get the recognition XML that tells where to hilight on the image\r
135                 Resource recoResource = conn.getNoteTable().noteResourceTable.getNoteResourceRecognition(resGuid);\r
136                 if (recoResource.getRecognition().getBody() == null || recoResource.getRecognition().getBody().length == 0)\r
137                         return;\r
138                 QByteArray recoData = new QByteArray(recoResource.getRecognition().getBody());\r
139                 String xml = recoData.toString();\r
140                 \r
141                 // Get a painter for the image.  This is the background (the initial image).\r
142         QPixmap pix = new QPixmap(f.fileName());\r
143         QPixmap hilightedPix = new QPixmap(pix.size());\r
144         QPainter p = new QPainter(hilightedPix);\r
145         p.drawPixmap(0,0, pix);\r
146 \r
147         // Create a transparent pixmap.  The only non-transparent\r
148         // piece is the hilight that will be overlayed to hilight text no the background\r
149         QPixmap overlayPix = new QPixmap(pix.size());\r
150         overlayPix.fill(QColor.transparent);\r
151         QPainter p2 = new QPainter(overlayPix);\r
152         p2.setBackgroundMode(BGMode.TransparentMode);\r
153         p2.setRenderHint(RenderHint.Antialiasing, true);\r
154                 QColor yellow = QColor.yellow;\r
155 //              yellow.setAlphaF(0.4);\r
156         p2.setBrush(yellow);\r
157         \r
158                 // Get the recognition data from the note\r
159         QDomDocument doc = new QDomDocument();\r
160         doc.setContent(xml);\r
161         \r
162         // Go through all "item" nodes\r
163                 QDomNodeList anchors = doc.elementsByTagName("item");\r
164                 for (int i=0; i<anchors.length(); i++) {\r
165                         QDomElement element = anchors.at(i).toElement();\r
166                         int x = new Integer(element.attribute("x"));   // x coordinate\r
167                         int y = new Integer(element.attribute("y"));   // y coordinate\r
168                         int w = new Integer(element.attribute("w"));   // width\r
169                         int h = new Integer(element.attribute("h"));   // height\r
170                         QDomNodeList children = element.childNodes();  // all children ("t" nodes).\r
171                         \r
172                         // Go through the children ("t" nodes)\r
173                         for (int j=0; j<children.length(); j++) {\r
174                         QDomElement child = children.at(j).toElement();\r
175                         if (child.nodeName().equalsIgnoreCase("t")) {\r
176                                 String text = child.text();   // recognition text\r
177                                 int weight = new Integer(child.attribute("w"));  // recognition weight\r
178                                 if (weight >= Global.getRecognitionWeight()) {   // Are we above the maximum?\r
179                                         \r
180                                         // Check to see if this word matches something we were searching for.\r
181                                         for (int k=0; k<enSearch.hilightWords.size(); k++) {\r
182                                                 String searchWord = enSearch.hilightWords.get(k).toLowerCase();\r
183                                                 if (searchWord.startsWith("*"))\r
184                                                         searchWord = searchWord.substring(1);\r
185                                                 if (searchWord.endsWith("*"))\r
186                                                         searchWord = searchWord.substring(0,searchWord.length()-1);\r
187                                                 if (text.toLowerCase().contains(searchWord)) {\r
188                                                         p2.drawRect(x,y,w,h);                   \r
189                                                 }\r
190                                         }\r
191                                 }\r
192                         }\r
193                         }\r
194                 }\r
195         p2.end();\r
196         \r
197         // Paint the hilight onto the background.\r
198         p.setOpacity(0.4);\r
199         p.drawPixmap(0,0, overlayPix);\r
200         p.end();\r
201         \r
202         // Save over the initial pixmap.\r
203         hilightedPix.save(f.fileName());\r
204         }\r
205         \r
206     // Modify the en-media tag into an image tag so it can be displayed.\r
207     private void modifyImageTags(QDomDocument doc, QDomElement docElem, QDomElement enmedia, QDomAttr hash) {\r
208         logger.log(logger.HIGH, "Entering NeverNote.modifyImageTags");\r
209         String type = enmedia.attribute("type");\r
210         if (type.startsWith("image/"))\r
211                 type = "."+type.substring(6);\r
212         else\r
213                 type="";\r
214         \r
215         String resGuid = conn.getNoteTable().noteResourceTable.getNoteResourceGuidByHashHex(currentNoteGuid, hash.value());\r
216         QFile tfile = new QFile(Global.getFileManager().getResDirPath(resGuid + type));\r
217 //      if (!tfile.exists()) {\r
218                 Resource r = null;\r
219                 if (resGuid != null)\r
220                                 r = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid,true);\r
221                         if (r==null || r.getData() == null || r.getData().getBody().length == 0) {\r
222                                 resourceError = true;\r
223                                 readOnly = true;\r
224                         }\r
225                         if (r!= null && r.getData() != null && r.getData().getBody().length > 0) {\r
226                                 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));\r
227                                 QByteArray binData = new QByteArray(r.getData().getBody());\r
228                                 tfile.write(binData);\r
229                                 tfile.close();\r
230                                 \r
231                                 // If we have recognition text, outline it\r
232                                 addImageHilight(r.getGuid(), tfile);\r
233                                 \r
234                                 enmedia.setAttribute("src", QUrl.fromLocalFile(tfile.fileName()).toString());\r
235                                 enmedia.setAttribute("en-tag", "en-media");\r
236                                 enmedia.setNodeValue("");\r
237                         enmedia.setAttribute("guid", r.getGuid());\r
238                         enmedia.setTagName("img");\r
239                 }\r
240 //      }\r
241         // Technically, we should do a file:// to have a proper url, but for some reason QWebPage hates\r
242         // them and won't generate a thumbnail image properly if we use them.\r
243 //              enmedia.setAttribute("src", QUrl.fromLocalFile(tfile.fileName()).toString());\r
244                 enmedia.setAttribute("src", tfile.fileName().toString());\r
245                 enmedia.setAttribute("en-tag", "en-media");\r
246                 enmedia.setTagName("img");\r
247                 if (r.getAttributes().getSourceURL() == null || !r.getAttributes().getSourceURL().toLowerCase().startsWith("http://latex.codecogs.com/gif.latex?"))\r
248                         enmedia.setAttribute("onContextMenu", "window.jambi.imageContextMenu('" +tfile.fileName()  +"');");\r
249                 else {\r
250                         QDomElement newText = doc.createElement("a");\r
251                         enmedia.setAttribute("src", tfile.fileName().toString());\r
252                         enmedia.setAttribute("en-tag", "en-latex");\r
253                         newText.setAttribute("onMouseOver", "style.cursor='hand'");\r
254                         newText.setAttribute("title", r.getAttributes().getSourceURL());\r
255                         newText.setAttribute("href", "latex://"+tfile.fileName().toString());\r
256                         enmedia.parentNode().replaceChild(newText, enmedia);\r
257                         newText.appendChild(enmedia);\r
258 \r
259                 }\r
260                 enmedia.setNodeValue("");\r
261                 enmedia.setAttribute("guid", resGuid);\r
262 \r
263 \r
264                 logger.log(logger.HIGH, "Leaving NeverNote.modifyImageTags");\r
265     }\r
266     \r
267     \r
268         // Modify tags from Evernote specific things to XHTML tags.\r
269         private QDomDocument modifyTags(QDomDocument doc) {\r
270                 logger.log(logger.HIGH, "Entering NeverNote.modifyTags");\r
271                 if (tempFiles == null)\r
272                         tempFiles = new ArrayList<QTemporaryFile>();\r
273                 tempFiles.clear();\r
274                 QDomElement docElem = doc.documentElement();\r
275                 \r
276                 // Modify en-media tags\r
277                 QDomNodeList anchors = docElem.elementsByTagName("en-media");\r
278                 int enMediaCount = anchors.length();\r
279                 for (int i=enMediaCount-1; i>=0; i--) {\r
280                         QDomElement enmedia = anchors.at(i).toElement();\r
281                         if (enmedia.hasAttribute("type")) {\r
282                                 QDomAttr attr = enmedia.attributeNode("type");\r
283                                 QDomAttr hash = enmedia.attributeNode("hash");\r
284                                 String[] type = attr.nodeValue().split("/");\r
285                                 String appl = type[1];\r
286                                 \r
287                                 if (type[0] != null) {\r
288                                         if (type[0].equals("image")) {\r
289                                                 modifyImageTags(doc, docElem, enmedia, hash);\r
290                                         }\r
291                                         if (!type[0].equals("image")) {\r
292                                                 modifyApplicationTags(doc, docElem, enmedia, hash, appl);\r
293                                         }\r
294                                 }\r
295                         }\r
296                 }\r
297                 \r
298                 // Modify todo tags\r
299                 anchors = docElem.elementsByTagName("en-todo");\r
300                 int enTodoCount = anchors.length();\r
301                 for (int i=enTodoCount-1; i>=0; i--) {\r
302                         QDomElement enmedia = anchors.at(i).toElement();\r
303                         modifyTodoTags(enmedia);\r
304                 }\r
305                 \r
306                 // Modify en-crypt tags\r
307                 anchors = docElem.elementsByTagName("en-crypt");\r
308                 int enCryptLen = anchors.length();\r
309                 for (int i=enCryptLen-1; i>=0; i--) {\r
310                         QDomElement enmedia = anchors.at(i).toElement();\r
311                         enmedia.setAttribute("contentEditable","false");\r
312                         enmedia.setAttribute("src", Global.getFileManager().getImageDirPath("encrypt.png"));\r
313                         enmedia.setAttribute("en-tag","en-crypt");\r
314                         enmedia.setAttribute("alt", enmedia.text());\r
315                         Global.cryptCounter++;\r
316                         enmedia.setAttribute("id", "crypt"+Global.cryptCounter.toString());\r
317                         String encryptedText = enmedia.text();\r
318                         \r
319                         // If the encryption string contains crlf at the end, remove them because they mess up the javascript.\r
320                         if (encryptedText.endsWith("\n"))\r
321                                 encryptedText = encryptedText.substring(0,encryptedText.length()-1);\r
322                         if (encryptedText.endsWith("\r"))\r
323                                 encryptedText = encryptedText.substring(0,encryptedText.length()-1);\r
324                         \r
325                         // Add the commands\r
326                         String hint = enmedia.attribute("hint");\r
327                         hint = hint.replace("'","&apos;");\r
328                         enmedia.setAttribute("onClick", "window.jambi.decryptText('crypt"+Global.cryptCounter.toString()+"', '"+encryptedText+"', '"+hint+"');");\r
329                         enmedia.setAttribute("onMouseOver", "style.cursor='hand'");\r
330                         enmedia.setTagName("img");\r
331                         enmedia.removeChild(enmedia.firstChild());   // Remove the actual encrypted text\r
332                 }\r
333 \r
334                 \r
335                 // Modify link tags\r
336                 anchors = docElem.elementsByTagName("a");\r
337                 enCryptLen = anchors.length();\r
338                 for (int i=0; i<anchors.length(); i++) {\r
339                         QDomElement element = anchors.at(i).toElement();\r
340                         if (!element.attribute("href").toLowerCase().startsWith("latex://"))\r
341                                 element.setAttribute("title", element.attribute("href"));\r
342                         else {\r
343                                 element.setAttribute("title", element.attribute("title").toLowerCase().replace("http://latex.codecogs.com/gif.latex?",""));\r
344                         }\r
345                 }\r
346 \r
347                 logger.log(logger.HIGH, "Leaving NeverNote.modifyTags");\r
348                 return doc;\r
349         }\r
350         \r
351 \r
352         // Get an ink note image.  If an image doesn't exist then we fall back \r
353         // to the old ugly icon\r
354     private boolean buildInkNote(QDomDocument doc, QDomElement docElem, QDomElement enmedia, QDomAttr hash, String appl) {\r
355         String resGuid = conn.getNoteTable().noteResourceTable.getNoteResourceGuidByHashHex(currentNote.getGuid(), hash.value());\r
356         Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid, false);\r
357  \r
358         // If we can't find the resource, then fall back to the old method.  We'll return & show\r
359         // an error later\r
360         if (r == null || r.getData() == null) \r
361                 return false;\r
362         \r
363         // If there isn't some type of error, continue on.\r
364                 if (!resourceError) {\r
365                         \r
366                         // Get a list of images in the database.  We'll use these to bulid the page.\r
367                         List<QByteArray> data = conn.getInkImagesTable().getImage(r.getGuid());\r
368                         \r
369                         // If no pictures are found, go back to & just show the icon\r
370                         if (data.size() == 0)\r
371                                 return false;\r
372                         \r
373                         // We have pictures, so append them to the page.  This really isn't proper since\r
374                         // we leave the en-media tag in place, but since we can't edit the page it doesn't\r
375                         // hurt anything.\r
376                         for (int i=0; i<data.size(); i++) {\r
377                         QFile f = new QFile(Global.getFileManager().getResDirPath(resGuid + new Integer(i).toString()+".png"));\r
378                                 f.open(OpenModeFlag.WriteOnly);\r
379                                 f.write(data.get(i));\r
380                                 f.close();\r
381                                 QDomElement newImage = doc.createElement("img");\r
382                                 newImage.setAttribute("src", QUrl.fromLocalFile(f.fileName()).toString());\r
383                                 enmedia.appendChild(newImage);\r
384                         }\r
385                         return true;\r
386                 }\r
387         return false;\r
388     }\r
389         \r
390         \r
391     // Modify the en-media tag into an attachment\r
392     private void modifyApplicationTags(QDomDocument doc, QDomElement docElem, QDomElement enmedia, QDomAttr hash, String appl) {\r
393         logger.log(logger.HIGH, "Entering NeverNote.modifyApplicationTags");\r
394         if (appl.equalsIgnoreCase("vnd.evernote.ink")) {\r
395                 inkNote = true;\r
396             if (buildInkNote(doc, docElem, enmedia, hash, appl))\r
397                 return;\r
398         }\r
399         String resGuid = conn.getNoteTable().noteResourceTable.getNoteResourceGuidByHashHex(currentNote.getGuid(), hash.value());\r
400         Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid, false);\r
401         if (r == null || r.getData() == null) \r
402                 resourceError = true;\r
403                 if (r!= null) {\r
404                         if (r.getData()!=null) {\r
405                                 // Did we get a generic applicaiton?  Then look at the file name to \r
406                                 // try and find a good application type for the icon\r
407                                 if (appl.equalsIgnoreCase("octet-stream")) {\r
408                                         if (r.getAttributes() != null && r.getAttributes().getFileName() != null) {\r
409                                                 String fn = r.getAttributes().getFileName();\r
410                                                 int pos = fn.lastIndexOf(".");\r
411                                                 if (pos > -1) {\r
412                                                         appl = fn.substring(pos+1);\r
413                                                 }\r
414                                         }\r
415                                 }\r
416                                 \r
417                                 String fileDetails = null;\r
418                                 if (r.getAttributes() != null && r.getAttributes().getFileName() != null && !r.getAttributes().getFileName().equals(""))\r
419                                         fileDetails = r.getAttributes().getFileName();\r
420                                 String contextFileName;\r
421                                 FileManager fileManager = Global.getFileManager();\r
422                 if (fileDetails != null && !fileDetails.equals("")) {\r
423                         if (!noteHistory) {\r
424                                 enmedia.setAttribute("href", "nnres://" +r.getGuid() \r
425                                                 +Global.attachmentNameDelimeter +fileDetails);\r
426                                 contextFileName = fileManager.getResDirPath(r.getGuid() \r
427                                                 +Global.attachmentNameDelimeter + fileDetails);\r
428                         } else {\r
429                                 enmedia.setAttribute("href", "nnres://" +r.getGuid() + currentNote.getUpdateSequenceNum() \r
430                                                 +Global.attachmentNameDelimeter +fileDetails);\r
431                                 contextFileName = fileManager.getResDirPath(r.getGuid() + currentNote.getUpdateSequenceNum() \r
432                                                 +Global.attachmentNameDelimeter + fileDetails);\r
433                         }\r
434                                 } else { \r
435                                         if (!noteHistory) {\r
436                                                 enmedia.setAttribute("href", "nnres://" +r.getGuid() +currentNote.getUpdateSequenceNum()\r
437                                                                 +Global.attachmentNameDelimeter +appl);\r
438                                                 contextFileName = fileManager.getResDirPath(r.getGuid() +currentNote.getUpdateSequenceNum() \r
439                                                                 +Global.attachmentNameDelimeter + appl);\r
440                                         } else {\r
441                                                 enmedia.setAttribute("href", "nnres://" +r.getGuid() \r
442                                                                 +Global.attachmentNameDelimeter +appl);\r
443                                                 contextFileName = fileManager.getResDirPath(r.getGuid() \r
444                                                                 +Global.attachmentNameDelimeter + appl);\r
445                                         }\r
446                                 }\r
447                                 contextFileName = contextFileName.replace("\\", "/");\r
448                                 enmedia.setAttribute("onContextMenu", "window.jambi.resourceContextMenu('" +contextFileName +"');");\r
449                                 if (fileDetails == null || fileDetails.equals(""))\r
450                                         fileDetails = "";\r
451                                 enmedia.setAttribute("en-tag", "en-media");\r
452                                 enmedia.setAttribute("guid", r.getGuid());\r
453                                 enmedia.setTagName("a");\r
454                                 QDomElement newText = doc.createElement("img");\r
455                                 boolean goodPreview = false;\r
456                                 String filePath = "";\r
457                                 if (appl.equalsIgnoreCase("pdf") && pdfPreview) {\r
458                                         String fileName;\r
459                                         Resource res = conn.getNoteTable().noteResourceTable.getNoteResource(r.getGuid(), true);\r
460                                         if (res.getAttributes() != null && \r
461                                                         res.getAttributes().getFileName() != null && \r
462                                                         !res.getAttributes().getFileName().trim().equals(""))\r
463                                                 fileName = res.getGuid()+Global.attachmentNameDelimeter+res.getAttributes().getFileName();\r
464                                         else\r
465                                                 fileName = res.getGuid()+".pdf";\r
466                                         QFile file = new QFile(fileManager.getResDirPath(fileName));\r
467                                 QFile.OpenMode mode = new QFile.OpenMode();\r
468                                 mode.set(QFile.OpenModeFlag.WriteOnly);\r
469                                 file.open(mode);\r
470                                 QDataStream out = new QDataStream(file);\r
471                                 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(res.getGuid(), true);\r
472                                         QByteArray binData = new QByteArray(resBinary.getData().getBody());\r
473                                         resBinary = null;\r
474                                 out.writeBytes(binData.toByteArray());\r
475                                 file.close();\r
476                                 PDFPreview pdfPreview = new PDFPreview();\r
477                                         goodPreview = pdfPreview.setupPreview(file.fileName(), appl,0);\r
478                                         if (goodPreview) {\r
479                                                 QDomElement span = doc.createElement("span");\r
480                                                 QDomElement table = doc.createElement("table");\r
481                                                 span.setAttribute("pdfNavigationTable", "true");\r
482                                                 QDomElement tr = doc.createElement("tr");\r
483                                                 QDomElement td = doc.createElement("td");\r
484                                                 QDomElement left = doc.createElement("img");\r
485                                                 left.setAttribute("onMouseDown", "window.jambi.nextPage('" +file.fileName() +"')");\r
486                                                 left.setAttribute("onMouseDown", "window.jambi.nextPage('" +file.fileName() +"')");\r
487                                                 left.setAttribute("onMouseOver", "style.cursor='hand'");\r
488                                                 QDomElement right = doc.createElement("img");\r
489                                                 right.setAttribute("onMouseDown", "window.jambi.nextPage('" +file.fileName() +"')");\r
490                                                 left.setAttribute("onMouseDown", "window.jambi.previousPage('" +file.fileName() +"')");\r
491                                                 // NFC TODO: should these be file:// URLs?\r
492                                                 left.setAttribute("src", Global.getFileManager().getImageDirPath("small_left.png"));\r
493                                                 right.setAttribute("src", Global.getFileManager().getImageDirPath("small_right.png"));\r
494                                                 right.setAttribute("onMouseOver", "style.cursor='hand'");\r
495                                                 \r
496                                                 table.appendChild(tr);\r
497                                                 tr.appendChild(td);\r
498                                                 td.appendChild(left);\r
499                                                 td.appendChild(right);\r
500                                                 span.appendChild(table);\r
501                                                 enmedia.parentNode().insertBefore(span, enmedia);\r
502                                         } \r
503                                         filePath = fileName+".png";\r
504                                 }\r
505                                 String icon = findIcon(appl);\r
506                                 if (icon.equals("attachment.png"))\r
507                                         icon = findIcon(fileDetails.substring(fileDetails.indexOf(".")+1));\r
508                                 // NFC TODO: should this be a 'file://' URL?\r
509                                 newText.setAttribute("src", Global.getFileManager().getImageDirPath(icon));\r
510                                 if (goodPreview) {\r
511                                 // NFC TODO: should this be a 'file://' URL?\r
512                                         newText.setAttribute("src", fileManager.getResDirPath(filePath));\r
513                                         newText.setAttribute("style", "border-style:solid; border-color:green; padding:0.5mm 0.5mm 0.5mm 0.5mm;");\r
514                                 }\r
515                                 newText.setAttribute("title", fileDetails);\r
516                                 enmedia.removeChild(enmedia.firstChild());\r
517                                 \r
518                                 enmedia.appendChild(newText);\r
519                         }\r
520                 }\r
521                 logger.log(logger.HIGH, "Leaving NeverNote.modifyApplicationTags");\r
522     }\r
523     // Modify the en-to tag into an input field\r
524     private void modifyTodoTags(QDomElement todo) {\r
525         logger.log(logger.HIGH, "Entering NeverNote.modifyTodoTags");\r
526                 todo.setAttribute("type", "checkbox");\r
527                 String checked = todo.attribute("checked");\r
528                 todo.removeAttribute("checked");\r
529                 if (checked.equalsIgnoreCase("true"))\r
530                         todo.setAttribute("checked", "");\r
531                 else\r
532                         todo.setAttribute("unchecked","");\r
533                 todo.setAttribute("value", checked);\r
534                 todo.setAttribute("onClick", "value=checked;window.jambi.contentChanged(); ");\r
535                 todo.setAttribute("onMouseOver", "style.cursor='hand'");\r
536                 todo.setTagName("input");\r
537                 logger.log(logger.HIGH, "Leaving NeverNote.modifyTodoTags");\r
538     }\r
539     \r
540     \r
541     \r
542     // Modify any cached todo tags that may have changed\r
543     public String modifyCachedTodoTags(String note) {\r
544         logger.log(logger.HIGH, "Entering NeverNote.modifyCachedTodoTags");\r
545         StringBuffer html = new StringBuffer(note);\r
546                 for (int i=html.indexOf("<input", 0); i>-1; i=html.indexOf("<input", i)) {\r
547                         int endPos =html.indexOf(">",i+1);\r
548                         String input = html.substring(i,endPos);\r
549                         if (input.indexOf("value=\"true\"") > 0) \r
550                                 input = input.replace(" unchecked=\"\"", " checked=\"\"");\r
551                         else\r
552                                 input = input.replace(" checked=\"\"", " unchecked=\"\"");\r
553                         html.replace(i, endPos, input);\r
554                         i++;\r
555                 }\r
556                 logger.log(logger.HIGH, "Leaving NeverNote.modifyCachedTodoTags");\r
557                 return html.toString();\r
558     }\r
559     \r
560     \r
561 \r
562 \r
563         // Scan and do hilighting of words\r
564         public QDomDocument addHilight(QDomDocument doc) {\r
565 //              EnSearch e = listManager.getEnSearch();\r
566                 if (enSearch.hilightWords == null || enSearch.hilightWords.size() == 0)\r
567                         return doc;\r
568                 XMLInsertHilight hilight = new XMLInsertHilight(doc, enSearch.hilightWords);\r
569                 return hilight.getDoc();\r
570         }\r
571         \r
572         \r
573     // find the appropriate icon for an attachment\r
574     private String findIcon(String appl) {\r
575         logger.log(logger.HIGH, "Entering NeverNote.findIcon");\r
576         appl = appl.toLowerCase();\r
577         String relativePath = appl + ".png";\r
578         File f = Global.getFileManager().getImageDirFile(relativePath);\r
579         if (f.exists()) {\r
580             return relativePath;\r
581         }\r
582         if (f.exists())\r
583                 return appl+".png";\r
584         logger.log(logger.HIGH, "Leaving NeverNote.findIcon");\r
585         return "attachment.png";\r
586     }\r
587 \r
588 }\r