OSDN Git Service

Remove all .class files from repos
[neighbornote/NeighborNote.git] / src / cx / fbn / nevernote / dialog / OnlineNoteHistory.java
1 /*\r
2  * This file is part of NeverNote \r
3  * Copyright 2009 Randy Baumgarte\r
4  * \r
5  * This file may be licensed under the terms of of the\r
6  * GNU General Public License Version 2 (the ``GPL'').\r
7  *\r
8  * Software distributed under the License is distributed\r
9  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either\r
10  * express or implied. See the GPL for the specific language\r
11  * governing rights and limitations.\r
12  *\r
13  * You should have received a copy of the GPL along with this\r
14  * program. If not, go to http://www.gnu.org/licenses/gpl.html\r
15  * or write to the Free Software Foundation, Inc.,\r
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
17  *\r
18 */\r
19 \r
20 package cx.fbn.nevernote.dialog;\r
21 \r
22 import java.io.File;\r
23 import java.text.SimpleDateFormat;\r
24 import java.util.List;\r
25 \r
26 import com.evernote.edam.notestore.NoteVersionId;\r
27 import com.evernote.edam.type.Note;\r
28 import com.evernote.edam.type.Resource;\r
29 import com.trolltech.qt.core.QByteArray;\r
30 import com.trolltech.qt.core.QFile;\r
31 import com.trolltech.qt.core.QIODevice;\r
32 import com.trolltech.qt.core.Qt.ContextMenuPolicy;\r
33 import com.trolltech.qt.gui.QComboBox;\r
34 import com.trolltech.qt.gui.QDialog;\r
35 import com.trolltech.qt.gui.QHBoxLayout;\r
36 import com.trolltech.qt.gui.QLabel;\r
37 import com.trolltech.qt.gui.QPushButton;\r
38 import com.trolltech.qt.gui.QVBoxLayout;\r
39 import com.trolltech.qt.xml.QDomAttr;\r
40 import com.trolltech.qt.xml.QDomDocument;\r
41 import com.trolltech.qt.xml.QDomElement;\r
42 import com.trolltech.qt.xml.QDomNodeList;\r
43 \r
44 import cx.fbn.nevernote.Global;\r
45 import cx.fbn.nevernote.gui.BrowserWindow;\r
46 import cx.fbn.nevernote.sql.DatabaseConnection;\r
47 \r
48 public class OnlineNoteHistory extends QDialog {\r
49         public final QPushButton        restoreAsNew;\r
50         public final QPushButton        restore;\r
51         private DatabaseConnection  conn;\r
52         public final QComboBox          historyCombo;    \r
53         private final BrowserWindow     browser;\r
54         \r
55         // Constructor\r
56         public OnlineNoteHistory(DatabaseConnection c) {\r
57                 setWindowTitle("Online Note History");\r
58                 QVBoxLayout main = new QVBoxLayout();\r
59                 setLayout(main);\r
60                 historyCombo = new QComboBox(this);\r
61                 \r
62                 QHBoxLayout comboLayout = new QHBoxLayout();\r
63                 comboLayout.addWidget(new QLabel("History Date:"));\r
64                 comboLayout.addWidget(historyCombo);\r
65                 comboLayout.addStretch(100);\r
66                 \r
67                 main.addLayout(comboLayout);\r
68                                 \r
69                 browser = new BrowserWindow(conn);\r
70                 main.addWidget(browser);\r
71                 browser.titleLabel.setVisible(false);\r
72                 browser.notebookBox.setVisible(false);\r
73                 browser.hideButtons();\r
74                 browser.tagEdit.setVisible(false);\r
75                 browser.tagLabel.setVisible(false);\r
76                 \r
77                 QHBoxLayout buttonLayout = new QHBoxLayout();\r
78                 buttonLayout.addStretch(100);\r
79                 restore = new QPushButton("Restore Note");\r
80                 restore.clicked.connect(this, "restorePushed()");\r
81                 \r
82                 restoreAsNew = new QPushButton("Restore As New Note");\r
83                 restoreAsNew.clicked.connect(this, "restoreAsNewPushed()");\r
84                 QPushButton cancel = new QPushButton("Cancel");\r
85                 cancel.clicked.connect(this, "cancelPressed()");\r
86                 \r
87                 buttonLayout.addWidget(restore);\r
88                 buttonLayout.addWidget(restoreAsNew);\r
89                 buttonLayout.addWidget(cancel);\r
90                 main.addLayout(buttonLayout);\r
91                 \r
92                 browser.getBrowser().setContextMenuPolicy(ContextMenuPolicy.NoContextMenu);\r
93 \r
94         }\r
95         \r
96         @SuppressWarnings("unused")\r
97         private void restoreAsNewPushed() {\r
98                 this.close();\r
99         }\r
100         @SuppressWarnings("unused")\r
101         private void restorePushed() {\r
102                 this.close();\r
103         }\r
104         @SuppressWarnings("unused")\r
105         private void cancelPressed() {\r
106                 this.close();\r
107         }\r
108         \r
109         public void setCurrent(boolean isDirty) {\r
110                 if (isDirty) \r
111                         historyCombo.addItem(new String("Current (Non Synchronized)"));\r
112                 else\r
113                         historyCombo.addItem(new String("Current (Synchronized)"));\r
114                                 \r
115         }\r
116         \r
117         public void load(List<NoteVersionId> versions) {\r
118                 String fmt = Global.getDateFormat() + " " + Global.getTimeFormat();\r
119                 String dateTimeFormat = new String(fmt);\r
120                 SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat);\r
121                 \r
122                 for (int i=0; i<versions.size(); i++) {\r
123                         StringBuilder versionDate = new StringBuilder(simple.format(versions.get(i).getServiceUpdated()));\r
124                         historyCombo.addItem(versionDate.toString());\r
125                 }\r
126         }\r
127         \r
128         public void setContent(Note currentNote) {\r
129                 StringBuffer b = rebuildNoteHTML(currentNote);\r
130                 StringBuffer js = new StringBuffer();\r
131 \r
132                 // We need to prepend the note with <HEAD></HEAD> or encoded characters are ugly \r
133                 js.append("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">");       \r
134                 js.append("<style type=\"text/css\">en-crypt-temp { border-style:solid; border-color:blue; padding:1mm 1mm 1mm 1mm; }</style>");\r
135                 js.append("</head>");\r
136                 js.append(b.toString());\r
137                 js.append("</HTML>");\r
138 //              js.replace("<!DOCTYPE en-note SYSTEM 'http://xml.evernote.com/pub/enml2.dtd'>", "");\r
139 //              js.replace("<?xml version='1.0' encoding='UTF-8'?>", "");\r
140                 \r
141                 browser.setNote(currentNote);\r
142                 browser.getBrowser().page().mainFrame().setHtml(js.toString());\r
143         }\r
144  \r
145         //*************************************************\r
146         //* XML Modifying Methods\r
147         //*************************************************\r
148         private StringBuffer rebuildNoteHTML(Note note) {\r
149                 QDomDocument doc = new QDomDocument();\r
150                 QDomDocument.Result result = doc.setContent(note.getContent());\r
151                 if (!result.success) {\r
152                         return new StringBuffer(note.getContent());\r
153                 }\r
154                 \r
155                 doc = modifyTags(note, doc);\r
156                 QDomElement docElem = doc.documentElement();\r
157                 docElem.setTagName("Body");\r
158                 \r
159                 // Fix the stupid problem where inserting an <img> tag after an <a> tag (which is done\r
160                 // to get the <en-media> application tag to work properly) causes spaces to be inserted\r
161                 // between the <a> & <img>.  This messes things up later.  This is an ugly hack.\r
162                 String docString = doc.toString();\r
163                 StringBuffer html = new StringBuffer(docString.substring(docString.toLowerCase().indexOf("<body>")));\r
164                 \r
165                 for (int i=html.indexOf("<a en-tag=\"en-media\" ", 0); i>-1; i=html.indexOf("<a en-tag=\"en-media\" ", i)) {\r
166                         i=html.indexOf(">\n",i+1);\r
167                         int z = html.indexOf("<img",i);\r
168                         for (int j=z-1; j>i; j--) \r
169                                 html.deleteCharAt(j);\r
170                         i=html.indexOf("/>", z+1);\r
171                         z = html.indexOf("</a>",i);\r
172                         for (int j=z-1; j>i+1; j--) \r
173                                 html.deleteCharAt(j);\r
174                 } \r
175                 return html;\r
176         }       \r
177 \r
178         \r
179         \r
180         private QDomDocument modifyTags(Note note, QDomDocument doc) {\r
181                 QDomElement docElem = doc.documentElement();\r
182                 \r
183                 // Modify en-media tags\r
184                 QDomNodeList anchors = docElem.elementsByTagName("en-media");\r
185                 int enMediaCount = anchors.length();\r
186                 for (int i=enMediaCount-1; i>=0; i--) {\r
187                         QDomElement enmedia = anchors.at(i).toElement();\r
188                         if (enmedia.hasAttribute("type")) {\r
189                                 QDomAttr attr = enmedia.attributeNode("type");\r
190                                 QDomAttr hash = enmedia.attributeNode("hash");\r
191                                 String[] type = attr.nodeValue().split("/");\r
192                                 String appl = type[1];\r
193                                 \r
194                                 if (type[0] != null) {\r
195                                         if (type[0].equals("image")) {\r
196                                                 modifyImageTags(note, docElem, enmedia, hash);\r
197                                         }\r
198                                         if (!type[0].equals("image")) {\r
199                                                 modifyApplicationTags(note, doc, docElem, enmedia, hash, appl);\r
200                                         }\r
201 //                                      if (type[0].equals("audio")) {\r
202 //                                              modifyApplicationTags(doc, docElem, enmedia, hash, appl);\r
203 //                                      }\r
204                                 }\r
205                         }\r
206                 }\r
207                 \r
208                 // Modify todo tags\r
209                 anchors = docElem.elementsByTagName("en-todo");\r
210                 int enTodoCount = anchors.length();\r
211                 for (int i=enTodoCount-1; i>=0; i--) {\r
212                         QDomElement enmedia = anchors.at(i).toElement();\r
213                         modifyTodoTags(enmedia);\r
214                 }\r
215                 \r
216                 // Modify en-crypt tags\r
217                 anchors = docElem.elementsByTagName("en-crypt");\r
218                 int enCryptLen = anchors.length();\r
219                 for (int i=enCryptLen-1; i>=0; i--) {\r
220                         QDomElement enmedia = anchors.at(i).toElement();\r
221                         //enmedia.setAttribute("style","display:none");\r
222                         enmedia.setAttribute("contentEditable","false");\r
223                         enmedia.setAttribute("src", Global.getDirectoryPath()+"images/encrypt.png");\r
224                         enmedia.setAttribute("en-tag","en-crypt");\r
225                         enmedia.setAttribute("alt", enmedia.text());\r
226                         Global.cryptCounter++;\r
227                         enmedia.setAttribute("id", "crypt"+Global.cryptCounter.toString());\r
228                         String encryptedText = enmedia.text();\r
229                         \r
230                         // If the encryption string contains crlf at the end, remove them because they mess up the javascript.\r
231                         if (encryptedText.endsWith("\n"))\r
232                                 encryptedText = encryptedText.substring(0,encryptedText.length()-1);\r
233                         if (encryptedText.endsWith("\r"))\r
234                                 encryptedText = encryptedText.substring(0,encryptedText.length()-1);\r
235                         \r
236                         // Add the commands\r
237                         enmedia.setAttribute("onClick", "window.jambi.decryptText('crypt"+Global.cryptCounter.toString()+"', '"+encryptedText+"', '"+enmedia.attribute("hint")+"');");\r
238                         enmedia.setAttribute("onMouseOver", "style.cursor='hand'");\r
239                         enmedia.setTagName("img");\r
240                         enmedia.removeChild(enmedia.firstChild());   // Remove the actual encrypted text\r
241                 }\r
242 \r
243                 return doc;\r
244         }\r
245         \r
246         \r
247         \r
248         \r
249            private void modifyApplicationTags(Note n, QDomDocument doc, QDomElement docElem, QDomElement enmedia, QDomAttr hash, String appl) {\r
250                   \r
251                    Resource r = null;\r
252                    for (int i=0; i<n.getResourcesSize(); i++) {\r
253                            String hashValue = hash.value();\r
254                            byte res[] = n.getResources().get(i).getData().getBodyHash();\r
255                            String resourceHashValue = new String(Global.byteArrayToHexString(res));\r
256                            if (resourceHashValue.equalsIgnoreCase(hashValue)) {\r
257                                    r = n.getResources().get(i);\r
258                                    i=n.getResourcesSize();\r
259                            }\r
260                    }\r
261                    \r
262                    if (r!= null) {\r
263                                 if (r.getData()!=null) {\r
264                                         // Did we get a generic applicaiton?  Then look at the file name to \r
265                                         // try and find a good application type for the icon\r
266                                         if (appl.equalsIgnoreCase("octet-stream")) {\r
267                                                 if (r.getAttributes() != null && r.getAttributes().getFileName() != null) {\r
268                                                         String fn = r.getAttributes().getFileName();\r
269                                                         int pos = fn.indexOf(".");\r
270                                                         if (pos > -1) {\r
271                                                                 appl = fn.substring(pos+1);\r
272                                                         }\r
273                                                 }\r
274                                         }\r
275                                         \r
276                                         String fileDetails = null;\r
277                                         if (r.getAttributes() != null && r.getAttributes().getFileName() != null && !r.getAttributes().getFileName().equals(""))\r
278                                                 fileDetails = r.getAttributes().getFileName();\r
279                                         if (fileDetails != null && !fileDetails.equals("")) \r
280                                                 enmedia.setAttribute("href", "nnres://" +r.getGuid()+n.getUpdateSequenceNum() +Global.attachmentNameDelimeter +fileDetails);\r
281                                         else\r
282                                                 enmedia.setAttribute("href", "nnres://" +r.getGuid()+n.getUpdateSequenceNum() +Global.attachmentNameDelimeter +appl);\r
283                                         if (fileDetails == null || fileDetails.equals(""))\r
284                                                 fileDetails = "";\r
285                                         enmedia.setAttribute("en-tag", "en-media");\r
286                                         enmedia.setAttribute("guid", r.getGuid());\r
287                                         enmedia.setTagName("a");\r
288                                         QDomElement newText = doc.createElement("img");\r
289                                         String icon = findIcon(appl);\r
290                                         if (icon.equals("attachment.png"))\r
291                                                 icon = findIcon(fileDetails.substring(fileDetails.indexOf(".")+1));\r
292                                         newText.setAttribute("src", Global.getDirectoryPath()+"images"+File.separator +icon);   \r
293                                         newText.setAttribute("title", fileDetails);\r
294                                         enmedia.removeChild(enmedia.firstChild());\r
295                                         enmedia.appendChild(newText);\r
296                                 }\r
297                         }\r
298             }\r
299             // find the appropriate icon for an attachment\r
300             private String findIcon(String appl) {\r
301                 appl = appl.toLowerCase();\r
302                 File f = new File(Global.getDirectoryPath()+"images"+File.separator +appl +".png");\r
303                 if (f.exists())\r
304                         return appl+".png";\r
305                 return "attachment.png";\r
306             }\r
307             \r
308         \r
309         \r
310         \r
311         \r
312         \r
313         \r
314     private void modifyTodoTags(QDomElement todo) {\r
315                 todo.setAttribute("type", "checkbox");\r
316                 String checked = todo.attribute("checked");\r
317                 todo.removeAttribute("checked");\r
318                 if (checked.equalsIgnoreCase("true"))\r
319                         todo.setAttribute("checked", "");\r
320                 else\r
321                         todo.setAttribute("unchecked","");\r
322                 todo.setAttribute("value", checked);\r
323                 todo.setAttribute("onClick", "value=checked;window.jambi.contentChanged(); ");\r
324                 todo.setTagName("input");\r
325     }\r
326     \r
327     \r
328     private void modifyImageTags(Note note, QDomElement docElem, QDomElement enmedia, QDomAttr hash) {\r
329         String type = enmedia.attribute("type");\r
330         if (type.startsWith("image/"))\r
331                 type = "."+type.substring(6);\r
332         else\r
333                 type="";\r
334         \r
335         Resource r = null;\r
336                 for (int i=0; i<note.getResourcesSize(); i++) {\r
337                         String hashValue = hash.value();\r
338                         byte res[] = note.getResources().get(i).getData().getBodyHash();\r
339                         String resourceHashValue = new String(Global.byteArrayToHexString(res));\r
340                    if (hashValue.equalsIgnoreCase(resourceHashValue)) {\r
341                            r = note.getResources().get(i);\r
342                            i=note.getResourcesSize();\r
343                    }\r
344                 }\r
345         \r
346                 if (r==null)\r
347                         return;\r
348                 \r
349         QFile tfile = new QFile(Global.getDirectoryPath()+"res"+File.separator +r.getGuid()+note.getUpdateSequenceNum()+type);\r
350         if (!tfile.exists()) {\r
351                         if (r!= null && r.getData() != null && r.getData().getBody().length > 0) {\r
352                                 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));\r
353                                 QByteArray binData = new QByteArray(r.getData().getBody());\r
354                                 tfile.write(binData);\r
355                                 tfile.close();\r
356                                 enmedia.setAttribute("src", tfile.fileName());\r
357                                 enmedia.setAttribute("en-tag", "en-media");\r
358                                 enmedia.setNodeValue("");\r
359                         enmedia.setAttribute("guid", r.getGuid());\r
360                         enmedia.setTagName("img");\r
361                 }\r
362         }\r
363                 enmedia.setAttribute("src", tfile.fileName());\r
364                 enmedia.setAttribute("en-tag", "en-media");\r
365                 enmedia.setNodeValue("");\r
366                 enmedia.setAttribute("guid", r.getGuid());\r
367                 enmedia.setTagName("img");\r
368     }\r
369 }\r