Added a bookmarks importer for Apple Safari.

Mon, 19 Mar 2012 20:14:07 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Mon, 19 Mar 2012 20:14:07 +0100
changeset 1720
201622cf8a01
parent 1719
c65aefefa2ff
child 1721
1dc3370687a5

Added a bookmarks importer for Apple Safari.

APIs/Python3/eric5.api file | annotate | diff | comparison | revisions
APIs/Python3/eric5.bas file | annotate | diff | comparison | revisions
Documentation/Help/source.qch file | annotate | diff | comparison | revisions
Documentation/Help/source.qhp file | annotate | diff | comparison | revisions
Documentation/Source/eric5.Helpviewer.Bookmarks.BookmarksImporters.SafariImporter.html file | annotate | diff | comparison | revisions
Documentation/Source/eric5.Utilities.binplistlib.html file | annotate | diff | comparison | revisions
Documentation/Source/index-eric5.Helpviewer.Bookmarks.BookmarksImporters.html file | annotate | diff | comparison | revisions
Documentation/Source/index-eric5.Utilities.html file | annotate | diff | comparison | revisions
Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py file | annotate | diff | comparison | revisions
Helpviewer/Bookmarks/BookmarksImporters/__init__.py file | annotate | diff | comparison | revisions
Utilities/binplistlib.py file | annotate | diff | comparison | revisions
eric5.e4p file | annotate | diff | comparison | revisions
i18n/eric5_cs.ts file | annotate | diff | comparison | revisions
i18n/eric5_de.qm file | annotate | diff | comparison | revisions
i18n/eric5_de.ts file | annotate | diff | comparison | revisions
i18n/eric5_en.ts file | annotate | diff | comparison | revisions
i18n/eric5_es.ts file | annotate | diff | comparison | revisions
i18n/eric5_fr.ts file | annotate | diff | comparison | revisions
i18n/eric5_it.ts file | annotate | diff | comparison | revisions
i18n/eric5_ru.ts file | annotate | diff | comparison | revisions
i18n/eric5_tr.ts file | annotate | diff | comparison | revisions
i18n/eric5_zh_CN.GB2312.ts file | annotate | diff | comparison | revisions
--- a/APIs/Python3/eric5.api	Mon Mar 19 19:24:12 2012 +0100
+++ b/APIs/Python3/eric5.api	Mon Mar 19 20:14:07 2012 +0100
@@ -1820,6 +1820,11 @@
 eric5.Helpviewer.Bookmarks.BookmarksImporters.OperaImporter.OperaImporter.setPath?4(path)
 eric5.Helpviewer.Bookmarks.BookmarksImporters.OperaImporter.OperaImporter?1(id="", parent=None)
 eric5.Helpviewer.Bookmarks.BookmarksImporters.OperaImporter.getImporterInfo?4(id)
+eric5.Helpviewer.Bookmarks.BookmarksImporters.SafariImporter.SafariImporter.importedBookmarks?4()
+eric5.Helpviewer.Bookmarks.BookmarksImporters.SafariImporter.SafariImporter.open?4()
+eric5.Helpviewer.Bookmarks.BookmarksImporters.SafariImporter.SafariImporter.setPath?4(path)
+eric5.Helpviewer.Bookmarks.BookmarksImporters.SafariImporter.SafariImporter?1(id="", parent=None)
+eric5.Helpviewer.Bookmarks.BookmarksImporters.SafariImporter.getImporterInfo?4(id)
 eric5.Helpviewer.Bookmarks.BookmarksImporters.XbelImporter.XbelImporter.importedBookmarks?4()
 eric5.Helpviewer.Bookmarks.BookmarksImporters.XbelImporter.XbelImporter.open?4()
 eric5.Helpviewer.Bookmarks.BookmarksImporters.XbelImporter.XbelImporter.setPath?4(path)
@@ -7064,6 +7069,65 @@
 eric5.Utilities._escape_map?8
 eric5.Utilities._percentReplacementFunc?5(matchobj)
 eric5.Utilities._uescape?8
+eric5.Utilities.binplistlib.BoolWrapper?1(value)
+eric5.Utilities.binplistlib.HashableWrapper?1(value)
+eric5.Utilities.binplistlib.PlistByteCounts?7
+eric5.Utilities.binplistlib.PlistReader.contents?7
+eric5.Utilities.binplistlib.PlistReader.currentOffset?7
+eric5.Utilities.binplistlib.PlistReader.file?7
+eric5.Utilities.binplistlib.PlistReader.getSizedInteger?4(data, bytes)
+eric5.Utilities.binplistlib.PlistReader.offsets?7
+eric5.Utilities.binplistlib.PlistReader.parse?4()
+eric5.Utilities.binplistlib.PlistReader.proc_extra?4()
+eric5.Utilities.binplistlib.PlistReader.readArray?4(count)
+eric5.Utilities.binplistlib.PlistReader.readAsciiString?4(length)
+eric5.Utilities.binplistlib.PlistReader.readData?4(length)
+eric5.Utilities.binplistlib.PlistReader.readDate?4()
+eric5.Utilities.binplistlib.PlistReader.readDict?4(count)
+eric5.Utilities.binplistlib.PlistReader.readInteger?4(bytes)
+eric5.Utilities.binplistlib.PlistReader.readObject?4()
+eric5.Utilities.binplistlib.PlistReader.readReal?4(length)
+eric5.Utilities.binplistlib.PlistReader.readRefs?4(count)
+eric5.Utilities.binplistlib.PlistReader.readRoot?4()
+eric5.Utilities.binplistlib.PlistReader.readUid?4(length)
+eric5.Utilities.binplistlib.PlistReader.readUnicode?4(length)
+eric5.Utilities.binplistlib.PlistReader.reset?4()
+eric5.Utilities.binplistlib.PlistReader.setCurrentOffsetToObjectNumber?4(objectNumber)
+eric5.Utilities.binplistlib.PlistReader.trailer?7
+eric5.Utilities.binplistlib.PlistReader?1(fileOrStream)
+eric5.Utilities.binplistlib.PlistTrailer?7
+eric5.Utilities.binplistlib.PlistWriter.binaryInt?4(obj, bytes=None)
+eric5.Utilities.binplistlib.PlistWriter.binaryReal?4(obj)
+eric5.Utilities.binplistlib.PlistWriter.byteCounts?7
+eric5.Utilities.binplistlib.PlistWriter.check_key?4()
+eric5.Utilities.binplistlib.PlistWriter.computeOffsets?4(obj, asReference=False, isRoot=False)
+eric5.Utilities.binplistlib.PlistWriter.computedUniques?7
+eric5.Utilities.binplistlib.PlistWriter.file?7
+eric5.Utilities.binplistlib.PlistWriter.header?7
+eric5.Utilities.binplistlib.PlistWriter.incrementByteCount?4(field, incr=1)
+eric5.Utilities.binplistlib.PlistWriter.intSize?4(obj)
+eric5.Utilities.binplistlib.PlistWriter.positionOfObjectReference?4(obj)
+eric5.Utilities.binplistlib.PlistWriter.proc_size?4()
+eric5.Utilities.binplistlib.PlistWriter.proc_variable_length?4(length)
+eric5.Utilities.binplistlib.PlistWriter.realSize?4(obj)
+eric5.Utilities.binplistlib.PlistWriter.referencePositions?7
+eric5.Utilities.binplistlib.PlistWriter.reset?4()
+eric5.Utilities.binplistlib.PlistWriter.trailer?7
+eric5.Utilities.binplistlib.PlistWriter.wrapRoot?4(root)
+eric5.Utilities.binplistlib.PlistWriter.wrappedFalse?7
+eric5.Utilities.binplistlib.PlistWriter.wrappedTrue?7
+eric5.Utilities.binplistlib.PlistWriter.writeObject?4(obj, output, setReferencePosition=False)
+eric5.Utilities.binplistlib.PlistWriter.writeObjectReference?4(obj, output)
+eric5.Utilities.binplistlib.PlistWriter.writeOffsetTable?4(output)
+eric5.Utilities.binplistlib.PlistWriter.writeRoot?4(root)
+eric5.Utilities.binplistlib.PlistWriter.writtenReferences?7
+eric5.Utilities.binplistlib.PlistWriter?1(file)
+eric5.Utilities.binplistlib.apple_reference_date_offset?7
+eric5.Utilities.binplistlib.is_stream_binary_plist?4(stream)
+eric5.Utilities.binplistlib.readPlist?4(pathOrFile)
+eric5.Utilities.binplistlib.readPlistFromBytes?4(data)
+eric5.Utilities.binplistlib.writePlist?4(rootObject, pathOrFile, binary=True)
+eric5.Utilities.binplistlib.writePlistToBytes?4(rootObject, binary=True)
 eric5.Utilities.checkBlacklistedVersions?4()
 eric5.Utilities.checkPyside?4()
 eric5.Utilities.codingBytes_regexps?7
--- a/APIs/Python3/eric5.bas	Mon Mar 19 19:24:12 2012 +0100
+++ b/APIs/Python3/eric5.bas	Mon Mar 19 20:14:07 2012 +0100
@@ -58,7 +58,7 @@
 ChangeBookmarkCommand QUndoCommand
 ChatWidget QWidget Ui_ChatWidget
 ChromeImporter BookmarksImporter
-Class ClbrBaseClasses.Class VisibilityMixin
+Class ClbrBase
 ClassItem UMLItem
 ClassScope Scope
 ClbrBase _ClbrBase
@@ -95,6 +95,7 @@
 CorbaPage ConfigurationPageBase Ui_CorbaPage
 CreateDialogCodeDialog QDialog Ui_CreateDialogCodeDialog
 DCTestResult TestResult
+Data bytes
 DebugBase bdb.Bdb
 DebugClient AsyncIO DebugBase DebugClientBase.DebugClientBase
 DebugClientThreads AsyncIO DebugClientBase.DebugClientBase
@@ -326,6 +327,7 @@
 InsertBookmarksCommand RemoveBookmarksCommand
 Interface ClbrBaseClasses.Class VisibilityMixin
 InterfacePage ConfigurationPageBase Ui_InterfacePage
+InvalidPlistException Exception
 JavaScriptEricObject QObject
 JavaScriptExternalObject QObject
 LateFutureImport Message
@@ -388,6 +390,7 @@
 NetworkReply QNetworkReply
 NewDialogClassDialog QDialog Ui_NewDialogClassDialog
 NewPythonPackageDialog QDialog Ui_NewPythonPackageDialog
+NotBinaryPlistException Exception
 NumbersWidget QWidget Ui_NumbersWidget
 OfflineStorageConfigDialog QDialog Ui_OfflineStorageConfigDialog
 OpenSearchDialog QDialog Ui_OpenSearchDialog
@@ -499,6 +502,7 @@
 Redirector QObject
 RemoveBookmarksCommand QUndoCommand
 RevisionsValidator QValidator
+SafariImporter BookmarksImporter
 SchemeAccessHandler QObject
 Scope dict
 SearchReplaceWidget QWidget
@@ -622,6 +626,7 @@
 UMLGraphicsView E5GraphicsView
 UMLItem QGraphicsRectItem
 UMLSceneSizeDialog QDialog Ui_UMLSceneSizeDialog
+Uid int
 UnBinding Binding
 UndefinedExport Message
 UndefinedLocal Message
Binary file Documentation/Help/source.qch has changed
--- a/Documentation/Help/source.qhp	Mon Mar 19 19:24:12 2012 +0100
+++ b/Documentation/Help/source.qhp	Mon Mar 19 20:14:07 2012 +0100
@@ -207,6 +207,7 @@
                 <section title="eric5.Helpviewer.Bookmarks.BookmarksImporters.HtmlImporter" ref="eric5.Helpviewer.Bookmarks.BookmarksImporters.HtmlImporter.html" />
                 <section title="eric5.Helpviewer.Bookmarks.BookmarksImporters.IExplorerImporter" ref="eric5.Helpviewer.Bookmarks.BookmarksImporters.IExplorerImporter.html" />
                 <section title="eric5.Helpviewer.Bookmarks.BookmarksImporters.OperaImporter" ref="eric5.Helpviewer.Bookmarks.BookmarksImporters.OperaImporter.html" />
+                <section title="eric5.Helpviewer.Bookmarks.BookmarksImporters.SafariImporter" ref="eric5.Helpviewer.Bookmarks.BookmarksImporters.SafariImporter.html" />
                 <section title="eric5.Helpviewer.Bookmarks.BookmarksImporters.XbelImporter" ref="eric5.Helpviewer.Bookmarks.BookmarksImporters.XbelImporter.html" />
                 <section title="eric5.Helpviewer.Bookmarks.BookmarksImporters.__init__" ref="eric5.Helpviewer.Bookmarks.BookmarksImporters.__init__.html" />
               </section>
@@ -868,6 +869,7 @@
             <section title="eric5.Utilities.SingleApplication" ref="eric5.Utilities.SingleApplication.html" />
             <section title="eric5.Utilities.Startup" ref="eric5.Utilities.Startup.html" />
             <section title="eric5.Utilities.__init__" ref="eric5.Utilities.__init__.html" />
+            <section title="eric5.Utilities.binplistlib" ref="eric5.Utilities.binplistlib.html" />
             <section title="eric5.Utilities.uic" ref="eric5.Utilities.uic.html" />
           </section>
           <section title="eric5.UtilitiesPython2" ref="index-eric5.UtilitiesPython2.html">
@@ -1485,6 +1487,9 @@
       <keyword name="BookmarksToolBar.__rebuild" id="BookmarksToolBar.__rebuild" ref="eric5.Helpviewer.Bookmarks.BookmarksToolBar.html#BookmarksToolBar.__rebuild" />
       <keyword name="BookmarksToolBar.__removeBookmark" id="BookmarksToolBar.__removeBookmark" ref="eric5.Helpviewer.Bookmarks.BookmarksToolBar.html#BookmarksToolBar.__removeBookmark" />
       <keyword name="BookmarksToolBar._createMenu" id="BookmarksToolBar._createMenu" ref="eric5.Helpviewer.Bookmarks.BookmarksToolBar.html#BookmarksToolBar._createMenu" />
+      <keyword name="BoolWrapper" id="BoolWrapper" ref="eric5.Utilities.binplistlib.html#BoolWrapper" />
+      <keyword name="BoolWrapper (Constructor)" id="BoolWrapper (Constructor)" ref="eric5.Utilities.binplistlib.html#BoolWrapper.__init__" />
+      <keyword name="BoolWrapper.__repr__" id="BoolWrapper.__repr__" ref="eric5.Utilities.binplistlib.html#BoolWrapper.__repr__" />
       <keyword name="BreakPointModel" id="BreakPointModel" ref="eric5.Debugger.BreakPointModel.html#BreakPointModel" />
       <keyword name="BreakPointModel (Constructor)" id="BreakPointModel (Constructor)" ref="eric5.Debugger.BreakPointModel.html#BreakPointModel.__init__" />
       <keyword name="BreakPointModel (Module)" id="BreakPointModel (Module)" ref="eric5.Debugger.BreakPointModel.html" />
@@ -2332,6 +2337,7 @@
       <keyword name="DEBUGGER__.thnum" id="DEBUGGER__.thnum" ref="eric5.DebugClients.Ruby.Debuggee.html#DEBUGGER__.thnum" />
       <keyword name="DEBUGGER__.trace_func" id="DEBUGGER__.trace_func" ref="eric5.DebugClients.Ruby.Debuggee.html#DEBUGGER__.trace_func" />
       <keyword name="DEBUGGER__.waiting" id="DEBUGGER__.waiting" ref="eric5.DebugClients.Ruby.Debuggee.html#DEBUGGER__.waiting" />
+      <keyword name="Data" id="Data" ref="eric5.Utilities.binplistlib.html#Data" />
       <keyword name="DataViews (Package)" id="DataViews (Package)" ref="index-eric5.DataViews.html" />
       <keyword name="DebugBase" id="DebugBase" ref="eric5.DebugClients.Python.DebugBase.html#DebugBase" />
       <keyword name="DebugBase" id="DebugBase" ref="eric5.DebugClients.Python3.DebugBase.html#DebugBase" />
@@ -4391,6 +4397,9 @@
       <keyword name="HTMLGenerator" id="HTMLGenerator" ref="eric5.QScintilla.Exporters.ExporterHTML.html#HTMLGenerator" />
       <keyword name="HTMLGenerator (Constructor)" id="HTMLGenerator (Constructor)" ref="eric5.QScintilla.Exporters.ExporterHTML.html#HTMLGenerator.__init__" />
       <keyword name="HTMLGenerator.generate" id="HTMLGenerator.generate" ref="eric5.QScintilla.Exporters.ExporterHTML.html#HTMLGenerator.generate" />
+      <keyword name="HashableWrapper" id="HashableWrapper" ref="eric5.Utilities.binplistlib.html#HashableWrapper" />
+      <keyword name="HashableWrapper (Constructor)" id="HashableWrapper (Constructor)" ref="eric5.Utilities.binplistlib.html#HashableWrapper.__init__" />
+      <keyword name="HashableWrapper.__repr__" id="HashableWrapper.__repr__" ref="eric5.Utilities.binplistlib.html#HashableWrapper.__repr__" />
       <keyword name="HelpAppearancePage" id="HelpAppearancePage" ref="eric5.Preferences.ConfigurationPages.HelpAppearancePage.html#HelpAppearancePage" />
       <keyword name="HelpAppearancePage (Constructor)" id="HelpAppearancePage (Constructor)" ref="eric5.Preferences.ConfigurationPages.HelpAppearancePage.html#HelpAppearancePage.__init__" />
       <keyword name="HelpAppearancePage (Module)" id="HelpAppearancePage (Module)" ref="eric5.Preferences.ConfigurationPages.HelpAppearancePage.html" />
@@ -5952,6 +5961,7 @@
       <keyword name="InterfacePage.on_stderrTextColourButton_clicked" id="InterfacePage.on_stderrTextColourButton_clicked" ref="eric5.Preferences.ConfigurationPages.InterfacePage.html#InterfacePage.on_stderrTextColourButton_clicked" />
       <keyword name="InterfacePage.on_styleSheetButton_clicked" id="InterfacePage.on_styleSheetButton_clicked" ref="eric5.Preferences.ConfigurationPages.InterfacePage.html#InterfacePage.on_styleSheetButton_clicked" />
       <keyword name="InterfacePage.save" id="InterfacePage.save" ref="eric5.Preferences.ConfigurationPages.InterfacePage.html#InterfacePage.save" />
+      <keyword name="InvalidPlistException" id="InvalidPlistException" ref="eric5.Utilities.binplistlib.html#InvalidPlistException" />
       <keyword name="JavaScriptEricObject" id="JavaScriptEricObject" ref="eric5.Helpviewer.HelpBrowserWV.html#JavaScriptEricObject" />
       <keyword name="JavaScriptEricObject (Constructor)" id="JavaScriptEricObject (Constructor)" ref="eric5.Helpviewer.HelpBrowserWV.html#JavaScriptEricObject.__init__" />
       <keyword name="JavaScriptEricObject.providerString" id="JavaScriptEricObject.providerString" ref="eric5.Helpviewer.HelpBrowserWV.html#JavaScriptEricObject.providerString" />
@@ -6633,6 +6643,7 @@
       <keyword name="NoneSplashScreen.clearMessage" id="NoneSplashScreen.clearMessage" ref="eric5.UI.SplashScreen.html#NoneSplashScreen.clearMessage" />
       <keyword name="NoneSplashScreen.finish" id="NoneSplashScreen.finish" ref="eric5.UI.SplashScreen.html#NoneSplashScreen.finish" />
       <keyword name="NoneSplashScreen.showMessage" id="NoneSplashScreen.showMessage" ref="eric5.UI.SplashScreen.html#NoneSplashScreen.showMessage" />
+      <keyword name="NotBinaryPlistException" id="NotBinaryPlistException" ref="eric5.Utilities.binplistlib.html#NotBinaryPlistException" />
       <keyword name="NumbersWidget" id="NumbersWidget" ref="eric5.UI.NumbersWidget.html#NumbersWidget" />
       <keyword name="NumbersWidget (Constructor)" id="NumbersWidget (Constructor)" ref="eric5.UI.NumbersWidget.html#NumbersWidget.__init__" />
       <keyword name="NumbersWidget (Module)" id="NumbersWidget (Module)" ref="eric5.UI.NumbersWidget.html" />
@@ -7008,6 +7019,43 @@
       <keyword name="PixmapDiagram.getDiagramName" id="PixmapDiagram.getDiagramName" ref="eric5.Graphics.PixmapDiagram.html#PixmapDiagram.getDiagramName" />
       <keyword name="PixmapDiagram.getStatus" id="PixmapDiagram.getStatus" ref="eric5.Graphics.PixmapDiagram.html#PixmapDiagram.getStatus" />
       <keyword name="PixmapDiagram.wheelEvent" id="PixmapDiagram.wheelEvent" ref="eric5.Graphics.PixmapDiagram.html#PixmapDiagram.wheelEvent" />
+      <keyword name="PlistReader" id="PlistReader" ref="eric5.Utilities.binplistlib.html#PlistReader" />
+      <keyword name="PlistReader (Constructor)" id="PlistReader (Constructor)" ref="eric5.Utilities.binplistlib.html#PlistReader.__init__" />
+      <keyword name="PlistReader.getSizedInteger" id="PlistReader.getSizedInteger" ref="eric5.Utilities.binplistlib.html#PlistReader.getSizedInteger" />
+      <keyword name="PlistReader.parse" id="PlistReader.parse" ref="eric5.Utilities.binplistlib.html#PlistReader.parse" />
+      <keyword name="PlistReader.proc_extra" id="PlistReader.proc_extra" ref="eric5.Utilities.binplistlib.html#PlistReader.proc_extra" />
+      <keyword name="PlistReader.readArray" id="PlistReader.readArray" ref="eric5.Utilities.binplistlib.html#PlistReader.readArray" />
+      <keyword name="PlistReader.readAsciiString" id="PlistReader.readAsciiString" ref="eric5.Utilities.binplistlib.html#PlistReader.readAsciiString" />
+      <keyword name="PlistReader.readData" id="PlistReader.readData" ref="eric5.Utilities.binplistlib.html#PlistReader.readData" />
+      <keyword name="PlistReader.readDate" id="PlistReader.readDate" ref="eric5.Utilities.binplistlib.html#PlistReader.readDate" />
+      <keyword name="PlistReader.readDict" id="PlistReader.readDict" ref="eric5.Utilities.binplistlib.html#PlistReader.readDict" />
+      <keyword name="PlistReader.readInteger" id="PlistReader.readInteger" ref="eric5.Utilities.binplistlib.html#PlistReader.readInteger" />
+      <keyword name="PlistReader.readObject" id="PlistReader.readObject" ref="eric5.Utilities.binplistlib.html#PlistReader.readObject" />
+      <keyword name="PlistReader.readReal" id="PlistReader.readReal" ref="eric5.Utilities.binplistlib.html#PlistReader.readReal" />
+      <keyword name="PlistReader.readRefs" id="PlistReader.readRefs" ref="eric5.Utilities.binplistlib.html#PlistReader.readRefs" />
+      <keyword name="PlistReader.readRoot" id="PlistReader.readRoot" ref="eric5.Utilities.binplistlib.html#PlistReader.readRoot" />
+      <keyword name="PlistReader.readUid" id="PlistReader.readUid" ref="eric5.Utilities.binplistlib.html#PlistReader.readUid" />
+      <keyword name="PlistReader.readUnicode" id="PlistReader.readUnicode" ref="eric5.Utilities.binplistlib.html#PlistReader.readUnicode" />
+      <keyword name="PlistReader.reset" id="PlistReader.reset" ref="eric5.Utilities.binplistlib.html#PlistReader.reset" />
+      <keyword name="PlistReader.setCurrentOffsetToObjectNumber" id="PlistReader.setCurrentOffsetToObjectNumber" ref="eric5.Utilities.binplistlib.html#PlistReader.setCurrentOffsetToObjectNumber" />
+      <keyword name="PlistWriter" id="PlistWriter" ref="eric5.Utilities.binplistlib.html#PlistWriter" />
+      <keyword name="PlistWriter (Constructor)" id="PlistWriter (Constructor)" ref="eric5.Utilities.binplistlib.html#PlistWriter.__init__" />
+      <keyword name="PlistWriter.binaryInt" id="PlistWriter.binaryInt" ref="eric5.Utilities.binplistlib.html#PlistWriter.binaryInt" />
+      <keyword name="PlistWriter.binaryReal" id="PlistWriter.binaryReal" ref="eric5.Utilities.binplistlib.html#PlistWriter.binaryReal" />
+      <keyword name="PlistWriter.check_key" id="PlistWriter.check_key" ref="eric5.Utilities.binplistlib.html#PlistWriter.check_key" />
+      <keyword name="PlistWriter.computeOffsets" id="PlistWriter.computeOffsets" ref="eric5.Utilities.binplistlib.html#PlistWriter.computeOffsets" />
+      <keyword name="PlistWriter.incrementByteCount" id="PlistWriter.incrementByteCount" ref="eric5.Utilities.binplistlib.html#PlistWriter.incrementByteCount" />
+      <keyword name="PlistWriter.intSize" id="PlistWriter.intSize" ref="eric5.Utilities.binplistlib.html#PlistWriter.intSize" />
+      <keyword name="PlistWriter.positionOfObjectReference" id="PlistWriter.positionOfObjectReference" ref="eric5.Utilities.binplistlib.html#PlistWriter.positionOfObjectReference" />
+      <keyword name="PlistWriter.proc_size" id="PlistWriter.proc_size" ref="eric5.Utilities.binplistlib.html#PlistWriter.proc_size" />
+      <keyword name="PlistWriter.proc_variable_length" id="PlistWriter.proc_variable_length" ref="eric5.Utilities.binplistlib.html#PlistWriter.proc_variable_length" />
+      <keyword name="PlistWriter.realSize" id="PlistWriter.realSize" ref="eric5.Utilities.binplistlib.html#PlistWriter.realSize" />
+      <keyword name="PlistWriter.reset" id="PlistWriter.reset" ref="eric5.Utilities.binplistlib.html#PlistWriter.reset" />
+      <keyword name="PlistWriter.wrapRoot" id="PlistWriter.wrapRoot" ref="eric5.Utilities.binplistlib.html#PlistWriter.wrapRoot" />
+      <keyword name="PlistWriter.writeObject" id="PlistWriter.writeObject" ref="eric5.Utilities.binplistlib.html#PlistWriter.writeObject" />
+      <keyword name="PlistWriter.writeObjectReference" id="PlistWriter.writeObjectReference" ref="eric5.Utilities.binplistlib.html#PlistWriter.writeObjectReference" />
+      <keyword name="PlistWriter.writeOffsetTable" id="PlistWriter.writeOffsetTable" ref="eric5.Utilities.binplistlib.html#PlistWriter.writeOffsetTable" />
+      <keyword name="PlistWriter.writeRoot" id="PlistWriter.writeRoot" ref="eric5.Utilities.binplistlib.html#PlistWriter.writeRoot" />
       <keyword name="PluginAbout (Module)" id="PluginAbout (Module)" ref="eric5.Plugins.PluginAbout.html" />
       <keyword name="PluginActivationError" id="PluginActivationError" ref="eric5.PluginManager.PluginExceptions.html#PluginActivationError" />
       <keyword name="PluginActivationError (Constructor)" id="PluginActivationError (Constructor)" ref="eric5.PluginManager.PluginExceptions.html#PluginActivationError.__init__" />
@@ -8141,6 +8189,13 @@
       <keyword name="RevisionsValidator (Constructor)" id="RevisionsValidator (Constructor)" ref="eric5.Plugins.VcsPlugins.vcsMercurial.TransplantExtension.TransplantDialog.html#RevisionsValidator.__init__" />
       <keyword name="RevisionsValidator.validate" id="RevisionsValidator.validate" ref="eric5.Plugins.VcsPlugins.vcsMercurial.TransplantExtension.TransplantDialog.html#RevisionsValidator.validate" />
       <keyword name="Ruby (Package)" id="Ruby (Package)" ref="index-eric5.DebugClients.Ruby.html" />
+      <keyword name="SafariImporter" id="SafariImporter" ref="eric5.Helpviewer.Bookmarks.BookmarksImporters.SafariImporter.html#SafariImporter" />
+      <keyword name="SafariImporter (Constructor)" id="SafariImporter (Constructor)" ref="eric5.Helpviewer.Bookmarks.BookmarksImporters.SafariImporter.html#SafariImporter.__init__" />
+      <keyword name="SafariImporter (Module)" id="SafariImporter (Module)" ref="eric5.Helpviewer.Bookmarks.BookmarksImporters.SafariImporter.html" />
+      <keyword name="SafariImporter.__processChildren" id="SafariImporter.__processChildren" ref="eric5.Helpviewer.Bookmarks.BookmarksImporters.SafariImporter.html#SafariImporter.__processChildren" />
+      <keyword name="SafariImporter.importedBookmarks" id="SafariImporter.importedBookmarks" ref="eric5.Helpviewer.Bookmarks.BookmarksImporters.SafariImporter.html#SafariImporter.importedBookmarks" />
+      <keyword name="SafariImporter.open" id="SafariImporter.open" ref="eric5.Helpviewer.Bookmarks.BookmarksImporters.SafariImporter.html#SafariImporter.open" />
+      <keyword name="SafariImporter.setPath" id="SafariImporter.setPath" ref="eric5.Helpviewer.Bookmarks.BookmarksImporters.SafariImporter.html#SafariImporter.setPath" />
       <keyword name="SchemeAccessHandler" id="SchemeAccessHandler" ref="eric5.Helpviewer.Network.SchemeAccessHandler.html#SchemeAccessHandler" />
       <keyword name="SchemeAccessHandler (Constructor)" id="SchemeAccessHandler (Constructor)" ref="eric5.Helpviewer.Network.SchemeAccessHandler.html#SchemeAccessHandler.__init__" />
       <keyword name="SchemeAccessHandler (Module)" id="SchemeAccessHandler (Module)" ref="eric5.Helpviewer.Network.SchemeAccessHandler.html" />
@@ -10101,6 +10156,8 @@
       <keyword name="UMLSceneSizeDialog (Constructor)" id="UMLSceneSizeDialog (Constructor)" ref="eric5.Graphics.UMLSceneSizeDialog.html#UMLSceneSizeDialog.__init__" />
       <keyword name="UMLSceneSizeDialog (Module)" id="UMLSceneSizeDialog (Module)" ref="eric5.Graphics.UMLSceneSizeDialog.html" />
       <keyword name="UMLSceneSizeDialog.getData" id="UMLSceneSizeDialog.getData" ref="eric5.Graphics.UMLSceneSizeDialog.html#UMLSceneSizeDialog.getData" />
+      <keyword name="Uid" id="Uid" ref="eric5.Utilities.binplistlib.html#Uid" />
+      <keyword name="Uid.__repr__" id="Uid.__repr__" ref="eric5.Utilities.binplistlib.html#Uid.__repr__" />
       <keyword name="UnBinding" id="UnBinding" ref="eric5.Utilities.py3flakes.checker.html#UnBinding" />
       <keyword name="UnBinding" id="UnBinding" ref="eric5.UtilitiesPython2.py2flakes.checker.html#UnBinding" />
       <keyword name="UndefinedExport" id="UndefinedExport" ref="eric5.Utilities.py3flakes.messages.html#UndefinedExport" />
@@ -11099,6 +11156,7 @@
       <keyword name="addSearchPath" id="addSearchPath" ref="eric5.UI.PixmapCache.html#addSearchPath" />
       <keyword name="analyze" id="analyze" ref="eric5.DataViews.CodeMetrics.html#analyze" />
       <keyword name="append_PKCS7_padding" id="append_PKCS7_padding" ref="eric5.Utilities.crypto.py3AES.html#append_PKCS7_padding" />
+      <keyword name="binplistlib (Module)" id="binplistlib (Module)" ref="eric5.Utilities.binplistlib.html" />
       <keyword name="blank_lines" id="blank_lines" ref="eric5.Plugins.CheckerPlugins.Pep8.pep8.html#blank_lines" />
       <keyword name="blank_lines" id="blank_lines" ref="eric5.UtilitiesPython2.pep8.html#blank_lines" />
       <keyword name="bookmarks (Module)" id="bookmarks (Module)" ref="eric5.Plugins.VcsPlugins.vcsMercurial.BookmarksExtension.bookmarks.html" />
@@ -11339,6 +11397,7 @@
       <keyword name="getImporterInfo" id="getImporterInfo" ref="eric5.Helpviewer.Bookmarks.BookmarksImporters.HtmlImporter.html#getImporterInfo" />
       <keyword name="getImporterInfo" id="getImporterInfo" ref="eric5.Helpviewer.Bookmarks.BookmarksImporters.IExplorerImporter.html#getImporterInfo" />
       <keyword name="getImporterInfo" id="getImporterInfo" ref="eric5.Helpviewer.Bookmarks.BookmarksImporters.OperaImporter.html#getImporterInfo" />
+      <keyword name="getImporterInfo" id="getImporterInfo" ref="eric5.Helpviewer.Bookmarks.BookmarksImporters.SafariImporter.html#getImporterInfo" />
       <keyword name="getImporterInfo" id="getImporterInfo" ref="eric5.Helpviewer.Bookmarks.BookmarksImporters.XbelImporter.html#getImporterInfo" />
       <keyword name="getImporterInfo" id="getImporterInfo" ref="eric5.Helpviewer.Bookmarks.BookmarksImporters.__init__.html#getImporterInfo" />
       <keyword name="getImporters" id="getImporters" ref="eric5.Helpviewer.Bookmarks.BookmarksImporters.__init__.html#getImporters" />
@@ -11460,6 +11519,7 @@
       <keyword name="isLinuxPlatform" id="isLinuxPlatform" ref="eric5.Globals.__init__.html#isLinuxPlatform" />
       <keyword name="isMacPlatform" id="isMacPlatform" ref="eric5.Globals.__init__.html#isMacPlatform" />
       <keyword name="isWindowsPlatform" id="isWindowsPlatform" ref="eric5.Globals.__init__.html#isWindowsPlatform" />
+      <keyword name="is_stream_binary_plist" id="is_stream_binary_plist" ref="eric5.Utilities.binplistlib.html#is_stream_binary_plist" />
       <keyword name="isatty" id="isatty" ref="eric5.DebugClients.Ruby.AsyncFile.html#isatty" />
       <keyword name="isinpath" id="isinpath" ref="eric5.Utilities.__init__.html#isinpath" />
       <keyword name="iter_child_nodes" id="iter_child_nodes" ref="eric5.UtilitiesPython2.py2flakes.checker.html#iter_child_nodes" />
@@ -11573,6 +11633,8 @@
       <keyword name="readEncodedFile" id="readEncodedFile" ref="eric5.UtilitiesPython2.Tools.html#readEncodedFile" />
       <keyword name="readEncodedFileWithHash" id="readEncodedFileWithHash" ref="eric5.Utilities.__init__.html#readEncodedFileWithHash" />
       <keyword name="readModule" id="readModule" ref="eric5.Utilities.ModuleParser.html#readModule" />
+      <keyword name="readPlist" id="readPlist" ref="eric5.Utilities.binplistlib.html#readPlist" />
+      <keyword name="readPlistFromBytes" id="readPlistFromBytes" ref="eric5.Utilities.binplistlib.html#readPlistFromBytes" />
       <keyword name="readShortcuts" id="readShortcuts" ref="eric5.Preferences.Shortcuts.html#readShortcuts" />
       <keyword name="readToolGroups" id="readToolGroups" ref="eric5.Preferences.__init__.html#readToolGroups" />
       <keyword name="readline" id="readline" ref="eric5.DebugClients.Ruby.AsyncFile.html#readline" />
@@ -11727,6 +11789,8 @@
       <keyword name="wrapperName" id="wrapperName" ref="eric5.uninstall.html#wrapperName" />
       <keyword name="write" id="write" ref="eric5.DebugClients.Ruby.AsyncFile.html#write" />
       <keyword name="writeEncodedFile" id="writeEncodedFile" ref="eric5.Utilities.__init__.html#writeEncodedFile" />
+      <keyword name="writePlist" id="writePlist" ref="eric5.Utilities.binplistlib.html#writePlist" />
+      <keyword name="writePlistToBytes" id="writePlistToBytes" ref="eric5.Utilities.binplistlib.html#writePlistToBytes" />
       <keyword name="writelines" id="writelines" ref="eric5.DebugClients.Ruby.AsyncFile.html#writelines" />
       <keyword name="yesNo" id="yesNo" ref="eric5.E5Gui.E5MessageBox.html#yesNo" />
     </keywords>
@@ -11896,6 +11960,7 @@
       <file>eric5.Helpviewer.Bookmarks.BookmarksImporters.HtmlImporter.html</file>
       <file>eric5.Helpviewer.Bookmarks.BookmarksImporters.IExplorerImporter.html</file>
       <file>eric5.Helpviewer.Bookmarks.BookmarksImporters.OperaImporter.html</file>
+      <file>eric5.Helpviewer.Bookmarks.BookmarksImporters.SafariImporter.html</file>
       <file>eric5.Helpviewer.Bookmarks.BookmarksImporters.XbelImporter.html</file>
       <file>eric5.Helpviewer.Bookmarks.BookmarksImporters.__init__.html</file>
       <file>eric5.Helpviewer.Bookmarks.BookmarksManager.html</file>
@@ -12403,6 +12468,7 @@
       <file>eric5.Utilities.SingleApplication.html</file>
       <file>eric5.Utilities.Startup.html</file>
       <file>eric5.Utilities.__init__.html</file>
+      <file>eric5.Utilities.binplistlib.html</file>
       <file>eric5.Utilities.crypto.__init__.html</file>
       <file>eric5.Utilities.crypto.py3AES.html</file>
       <file>eric5.Utilities.crypto.py3PBKDF2.html</file>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Documentation/Source/eric5.Helpviewer.Bookmarks.BookmarksImporters.SafariImporter.html	Mon Mar 19 20:14:07 2012 +0100
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN'
+'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html><head>
+<title>eric5.Helpviewer.Bookmarks.BookmarksImporters.SafariImporter</title>
+<style>
+body {
+    background: #EDECE6;
+    margin: 0em 1em 10em 1em;
+    color: black;
+}
+
+h1 { color: white; background: #85774A; }
+h2 { color: white; background: #85774A; }
+h3 { color: white; background: #9D936E; }
+h4 { color: white; background: #9D936E; }
+    
+a { color: #BA6D36; }
+
+</style>
+</head>
+<body><a NAME="top" ID="top"></a>
+<h1>eric5.Helpviewer.Bookmarks.BookmarksImporters.SafariImporter</h1>
+<p>
+Module implementing an importer for Apple Safari bookmarks.
+</p>
+<h3>Global Attributes</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+<table>
+<tr>
+<td><a href="#SafariImporter">SafariImporter</a></td>
+<td>Class implementing the Apple Safari bookmarks importer.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+<table>
+<tr>
+<td><a href="#getImporterInfo">getImporterInfo</a></td>
+<td>Module function to get information for the given source id.</td>
+</tr>
+</table>
+<hr /><hr />
+<a NAME="SafariImporter" ID="SafariImporter"></a>
+<h2>SafariImporter</h2>
+<p>
+    Class implementing the Apple Safari bookmarks importer.
+</p>
+<h3>Derived from</h3>
+BookmarksImporter
+<h3>Class Attributes</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+<table>
+<tr>
+<td><a href="#SafariImporter.__init__">SafariImporter</a></td>
+<td>Constructor</td>
+</tr><tr>
+<td><a href="#SafariImporter.__processChildren">__processChildren</a></td>
+<td>Private method to process the list of children.</td>
+</tr><tr>
+<td><a href="#SafariImporter.importedBookmarks">importedBookmarks</a></td>
+<td>Public method to get the imported bookmarks.</td>
+</tr><tr>
+<td><a href="#SafariImporter.open">open</a></td>
+<td>Public method to open the bookmarks file.</td>
+</tr><tr>
+<td><a href="#SafariImporter.setPath">setPath</a></td>
+<td>Public method to set the path of the bookmarks file or directory.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<a NAME="SafariImporter.__init__" ID="SafariImporter.__init__"></a>
+<h4>SafariImporter (Constructor)</h4>
+<b>SafariImporter</b>(<i>id="", parent=None</i>)
+<p>
+        Constructor
+</p><dl>
+<dt><i>id</i></dt>
+<dd>
+source ID (string)
+</dd><dt><i>parent</i></dt>
+<dd>
+reference to the parent object (QObject)
+</dd>
+</dl><a NAME="SafariImporter.__processChildren" ID="SafariImporter.__processChildren"></a>
+<h4>SafariImporter.__processChildren</h4>
+<b>__processChildren</b>(<i>children, rootNode</i>)
+<p>
+        Private method to process the list of children.
+</p><dl>
+<dt><i>children</i></dt>
+<dd>
+list of child nodes to be processed (list of dict)
+</dd><dt><i>rootNode</i></dt>
+<dd>
+node to add the bookmarks to (BookmarkNode)
+</dd>
+</dl><a NAME="SafariImporter.importedBookmarks" ID="SafariImporter.importedBookmarks"></a>
+<h4>SafariImporter.importedBookmarks</h4>
+<b>importedBookmarks</b>(<i></i>)
+<p>
+        Public method to get the imported bookmarks.
+</p><dl>
+<dt>Returns:</dt>
+<dd>
+imported bookmarks (BookmarkNode)
+</dd>
+</dl><a NAME="SafariImporter.open" ID="SafariImporter.open"></a>
+<h4>SafariImporter.open</h4>
+<b>open</b>(<i></i>)
+<p>
+        Public method to open the bookmarks file.
+</p><dl>
+<dt>Returns:</dt>
+<dd>
+flag indicating success (boolean)
+</dd>
+</dl><a NAME="SafariImporter.setPath" ID="SafariImporter.setPath"></a>
+<h4>SafariImporter.setPath</h4>
+<b>setPath</b>(<i>path</i>)
+<p>
+        Public method to set the path of the bookmarks file or directory.
+</p><dl>
+<dt><i>path</i></dt>
+<dd>
+bookmarks file or directory (string)
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="getImporterInfo" ID="getImporterInfo"></a>
+<h2>getImporterInfo</h2>
+<b>getImporterInfo</b>(<i>id</i>)
+<p>
+    Module function to get information for the given source id.
+</p><dl>
+<dt>Returns:</dt>
+<dd>
+tuple with an icon (QPixmap), readable name (string), name of
+        the default bookmarks file (string), an info text (string),
+        a prompt (string) and the default directory of the bookmarks file (string)
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+</body></html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Documentation/Source/eric5.Utilities.binplistlib.html	Mon Mar 19 20:14:07 2012 +0100
@@ -0,0 +1,997 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN'
+'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+<html><head>
+<title>eric5.Utilities.binplistlib</title>
+<style>
+body {
+    background: #EDECE6;
+    margin: 0em 1em 10em 1em;
+    color: black;
+}
+
+h1 { color: white; background: #85774A; }
+h2 { color: white; background: #85774A; }
+h3 { color: white; background: #9D936E; }
+h4 { color: white; background: #9D936E; }
+    
+a { color: #BA6D36; }
+
+</style>
+</head>
+<body><a NAME="top" ID="top"></a>
+<h1>eric5.Utilities.binplistlib</h1>
+<p>
+Module implementing a library for reading and writing binary property list files.
+</p><p>
+Binary Property List (plist) files provide a faster and smaller serialization
+format for property lists on OS X. This is a library for generating binary
+plists which can be read by OS X, iOS, or other clients.
+</p><p>
+The API models the plistlib API, and will call through to plistlib when
+XML serialization or deserialization is required.
+</p><p>
+To generate plists with UID values, wrap the values with the Uid object. The
+value must be an int.
+</p><p>
+To generate plists with NSData/CFData values, wrap the values with the
+Data object. The value must be a bytes object.
+</p><p>
+Date values can only be datetime.datetime objects.
+</p><p>
+The exceptions InvalidPlistException and NotBinaryPlistException may be 
+thrown to indicate that the data cannot be serialized or deserialized as
+a binary plist.
+</p><p>
+Plist generation example:
+<pre>
+    from binplistlib import *
+    from datetime import datetime
+    plist = {'aKey':'aValue',
+             '0':1.322,
+             'now':datetime.now(),
+             'list':[1,2,3],
+             'tuple':('a','b','c')
+             }
+    try:
+        writePlist(plist, "example.plist")
+    except (InvalidPlistException, NotBinaryPlistException) as e:
+        print("Something bad happened:", e)
+</pre>
+Plist parsing example:
+<pre>
+    from binplistlib import *
+    try:
+        plist = readPlist("example.plist")
+        print(plist)
+    except (InvalidPlistException, NotBinaryPlistException) as e:
+        print("Not a plist:", e)
+</pre>
+</p>
+<h3>Global Attributes</h3>
+<table>
+<tr><td>PlistByteCounts</td></tr><tr><td>PlistTrailer</td></tr><tr><td>__all__</td></tr><tr><td>apple_reference_date_offset</td></tr>
+</table>
+<h3>Classes</h3>
+<table>
+<tr>
+<td><a href="#BoolWrapper">BoolWrapper</a></td>
+<td>Class wrapping a boolean value.</td>
+</tr><tr>
+<td><a href="#Data">Data</a></td>
+<td>Class implementing a wrapper around bytes types for representing Data values.</td>
+</tr><tr>
+<td><a href="#HashableWrapper">HashableWrapper</a></td>
+<td>Class wrapping a hashable value.</td>
+</tr><tr>
+<td><a href="#InvalidPlistException">InvalidPlistException</a></td>
+<td>Exception raised when the plist is incorrectly formatted.</td>
+</tr><tr>
+<td><a href="#NotBinaryPlistException">NotBinaryPlistException</a></td>
+<td>Exception raised when a binary plist was expected but not encountered.</td>
+</tr><tr>
+<td><a href="#PlistReader">PlistReader</a></td>
+<td>Class implementing the plist reader.</td>
+</tr><tr>
+<td><a href="#PlistWriter">PlistWriter</a></td>
+<td>Class implementing the plist writer.</td>
+</tr><tr>
+<td><a href="#Uid">Uid</a></td>
+<td>Class implementing a wrapper around integers for representing UID values.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+<table>
+<tr>
+<td><a href="#is_stream_binary_plist">is_stream_binary_plist</a></td>
+<td>Module function to check, if the stream is a binary plist.</td>
+</tr><tr>
+<td><a href="#readPlist">readPlist</a></td>
+<td>Module function to read a plist file.</td>
+</tr><tr>
+<td><a href="#readPlistFromBytes">readPlistFromBytes</a></td>
+<td>Module function to read from a plist bytes object.</td>
+</tr><tr>
+<td><a href="#writePlist">writePlist</a></td>
+<td>Module function to write a plist file.</td>
+</tr><tr>
+<td><a href="#writePlistToBytes">writePlistToBytes</a></td>
+<td>Module function to write a plist bytes object.</td>
+</tr>
+</table>
+<hr /><hr />
+<a NAME="BoolWrapper" ID="BoolWrapper"></a>
+<h2>BoolWrapper</h2>
+<p>
+    Class wrapping a boolean value.
+</p>
+<h3>Derived from</h3>
+object
+<h3>Class Attributes</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+<table>
+<tr>
+<td><a href="#BoolWrapper.__init__">BoolWrapper</a></td>
+<td></td>
+</tr><tr>
+<td><a href="#BoolWrapper.__repr__">__repr__</a></td>
+<td></td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<a NAME="BoolWrapper.__init__" ID="BoolWrapper.__init__"></a>
+<h4>BoolWrapper (Constructor)</h4>
+<b>BoolWrapper</b>(<i>value</i>)
+<a NAME="BoolWrapper.__repr__" ID="BoolWrapper.__repr__"></a>
+<h4>BoolWrapper.__repr__</h4>
+<b>__repr__</b>(<i></i>)
+
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="Data" ID="Data"></a>
+<h2>Data</h2>
+<p>
+    Class implementing a wrapper around bytes types for representing Data values.
+</p>
+<h3>Derived from</h3>
+bytes
+<h3>Class Attributes</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Static Methods</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="HashableWrapper" ID="HashableWrapper"></a>
+<h2>HashableWrapper</h2>
+<p>
+    Class wrapping a hashable value.
+</p>
+<h3>Derived from</h3>
+object
+<h3>Class Attributes</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+<table>
+<tr>
+<td><a href="#HashableWrapper.__init__">HashableWrapper</a></td>
+<td></td>
+</tr><tr>
+<td><a href="#HashableWrapper.__repr__">__repr__</a></td>
+<td></td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<a NAME="HashableWrapper.__init__" ID="HashableWrapper.__init__"></a>
+<h4>HashableWrapper (Constructor)</h4>
+<b>HashableWrapper</b>(<i>value</i>)
+<a NAME="HashableWrapper.__repr__" ID="HashableWrapper.__repr__"></a>
+<h4>HashableWrapper.__repr__</h4>
+<b>__repr__</b>(<i></i>)
+
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="InvalidPlistException" ID="InvalidPlistException"></a>
+<h2>InvalidPlistException</h2>
+<p>
+    Exception raised when the plist is incorrectly formatted.
+</p>
+<h3>Derived from</h3>
+Exception
+<h3>Class Attributes</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Static Methods</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="NotBinaryPlistException" ID="NotBinaryPlistException"></a>
+<h2>NotBinaryPlistException</h2>
+<p>
+    Exception raised when a binary plist was expected but not encountered.
+</p>
+<h3>Derived from</h3>
+Exception
+<h3>Class Attributes</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Static Methods</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="PlistReader" ID="PlistReader"></a>
+<h2>PlistReader</h2>
+<p>
+    Class implementing the plist reader.
+</p>
+<h3>Derived from</h3>
+object
+<h3>Class Attributes</h3>
+<table>
+<tr><td>contents</td></tr><tr><td>currentOffset</td></tr><tr><td>file</td></tr><tr><td>offsets</td></tr><tr><td>trailer</td></tr>
+</table>
+<h3>Class Methods</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+<table>
+<tr>
+<td><a href="#PlistReader.__init__">PlistReader</a></td>
+<td>Constructor</td>
+</tr><tr>
+<td><a href="#PlistReader.getSizedInteger">getSizedInteger</a></td>
+<td>Private method to read an integer of a specific size.</td>
+</tr><tr>
+<td><a href="#PlistReader.parse">parse</a></td>
+<td>Public method to parse the plist data.</td>
+</tr><tr>
+<td><a href="#PlistReader.proc_extra">proc_extra</a></td>
+<td></td>
+</tr><tr>
+<td><a href="#PlistReader.readArray">readArray</a></td>
+<td>Private method to read an Array object.</td>
+</tr><tr>
+<td><a href="#PlistReader.readAsciiString">readAsciiString</a></td>
+<td>Private method to read an ASCII encoded string.</td>
+</tr><tr>
+<td><a href="#PlistReader.readData">readData</a></td>
+<td>Private method to read some bytes.</td>
+</tr><tr>
+<td><a href="#PlistReader.readDate">readDate</a></td>
+<td>Private method to read a date.</td>
+</tr><tr>
+<td><a href="#PlistReader.readDict">readDict</a></td>
+<td>Private method to read a Dictionary object.</td>
+</tr><tr>
+<td><a href="#PlistReader.readInteger">readInteger</a></td>
+<td>Private method to read an Integer object.</td>
+</tr><tr>
+<td><a href="#PlistReader.readObject">readObject</a></td>
+<td>Private method to read the object data.</td>
+</tr><tr>
+<td><a href="#PlistReader.readReal">readReal</a></td>
+<td>Private method to read a Real object.</td>
+</tr><tr>
+<td><a href="#PlistReader.readRefs">readRefs</a></td>
+<td>Private method to read References.</td>
+</tr><tr>
+<td><a href="#PlistReader.readRoot">readRoot</a></td>
+<td>Private method to read the root object.</td>
+</tr><tr>
+<td><a href="#PlistReader.readUid">readUid</a></td>
+<td>Private method to read a UID.</td>
+</tr><tr>
+<td><a href="#PlistReader.readUnicode">readUnicode</a></td>
+<td>Private method to read an Unicode encoded string.</td>
+</tr><tr>
+<td><a href="#PlistReader.reset">reset</a></td>
+<td>Private method to reset the instance object.</td>
+</tr><tr>
+<td><a href="#PlistReader.setCurrentOffsetToObjectNumber">setCurrentOffsetToObjectNumber</a></td>
+<td>Private method to set the current offset.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<a NAME="PlistReader.__init__" ID="PlistReader.__init__"></a>
+<h4>PlistReader (Constructor)</h4>
+<b>PlistReader</b>(<i>fileOrStream</i>)
+<p>
+        Constructor
+</p><dl>
+<dt><i>fileOrStream</i></dt>
+<dd>
+open file containing the plist data (file object)
+</dd>
+</dl><a NAME="PlistReader.getSizedInteger" ID="PlistReader.getSizedInteger"></a>
+<h4>PlistReader.getSizedInteger</h4>
+<b>getSizedInteger</b>(<i>data, bytes</i>)
+<p>
+        Private method to read an integer of a specific size.
+</p><dl>
+<dt><i>data</i></dt>
+<dd>
+data to extract the integer from (bytes)
+</dd><dt><i>bytes</i></dt>
+<dd>
+length of the integer (integer)
+</dd>
+</dl><a NAME="PlistReader.parse" ID="PlistReader.parse"></a>
+<h4>PlistReader.parse</h4>
+<b>parse</b>(<i></i>)
+<p>
+        Public method to parse the plist data.
+</p><dl>
+<dt>Returns:</dt>
+<dd>
+unpickled object
+</dd>
+</dl><a NAME="PlistReader.proc_extra" ID="PlistReader.proc_extra"></a>
+<h4>PlistReader.proc_extra</h4>
+<b>proc_extra</b>(<i></i>)
+<a NAME="PlistReader.readArray" ID="PlistReader.readArray"></a>
+<h4>PlistReader.readArray</h4>
+<b>readArray</b>(<i>count</i>)
+<p>
+        Private method to read an Array object.
+</p><dl>
+<dt><i>count</i></dt>
+<dd>
+number of array elements (integer)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+list of unpickled objects
+</dd>
+</dl><a NAME="PlistReader.readAsciiString" ID="PlistReader.readAsciiString"></a>
+<h4>PlistReader.readAsciiString</h4>
+<b>readAsciiString</b>(<i>length</i>)
+<p>
+        Private method to read an ASCII encoded string.
+</p><dl>
+<dt><i>length</i></dt>
+<dd>
+length of the string (integer)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+ASCII encoded string
+</dd>
+</dl><a NAME="PlistReader.readData" ID="PlistReader.readData"></a>
+<h4>PlistReader.readData</h4>
+<b>readData</b>(<i>length</i>)
+<p>
+        Private method to read some bytes.
+</p><dl>
+<dt><i>length</i></dt>
+<dd>
+number of bytes to read (integer)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+Data object
+</dd>
+</dl><a NAME="PlistReader.readDate" ID="PlistReader.readDate"></a>
+<h4>PlistReader.readDate</h4>
+<b>readDate</b>(<i></i>)
+<p>
+        Private method to read a date.
+</p><dl>
+<dt>Returns:</dt>
+<dd>
+date object (datetime.datetime)
+</dd>
+</dl><a NAME="PlistReader.readDict" ID="PlistReader.readDict"></a>
+<h4>PlistReader.readDict</h4>
+<b>readDict</b>(<i>count</i>)
+<p>
+        Private method to read a Dictionary object.
+</p><dl>
+<dt><i>count</i></dt>
+<dd>
+number of dictionary elements (integer)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+dictionary of unpickled objects
+</dd>
+</dl><a NAME="PlistReader.readInteger" ID="PlistReader.readInteger"></a>
+<h4>PlistReader.readInteger</h4>
+<b>readInteger</b>(<i>bytes</i>)
+<p>
+        Private method to read an Integer object.
+</p><dl>
+<dt><i>bytes</i></dt>
+<dd>
+length of the object (integer)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+integer object
+</dd>
+</dl><a NAME="PlistReader.readObject" ID="PlistReader.readObject"></a>
+<h4>PlistReader.readObject</h4>
+<b>readObject</b>(<i></i>)
+<p>
+        Private method to read the object data.
+</p><dl>
+<dt>Returns:</dt>
+<dd>
+unpickled object
+</dd>
+</dl><a NAME="PlistReader.readReal" ID="PlistReader.readReal"></a>
+<h4>PlistReader.readReal</h4>
+<b>readReal</b>(<i>length</i>)
+<p>
+        Private method to read a Real object.
+</p><dl>
+<dt><i>length</i></dt>
+<dd>
+length of the object (integer)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+float object
+</dd>
+</dl><a NAME="PlistReader.readRefs" ID="PlistReader.readRefs"></a>
+<h4>PlistReader.readRefs</h4>
+<b>readRefs</b>(<i>count</i>)
+<p>
+        Private method to read References.
+</p><dl>
+<dt><i>count</i></dt>
+<dd>
+amount of the references (integer)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+list of references (list of integers)
+</dd>
+</dl><a NAME="PlistReader.readRoot" ID="PlistReader.readRoot"></a>
+<h4>PlistReader.readRoot</h4>
+<b>readRoot</b>(<i></i>)
+<p>
+        Private method to read the root object.
+</p><dl>
+<dt>Returns:</dt>
+<dd>
+unpickled object
+</dd>
+</dl><a NAME="PlistReader.readUid" ID="PlistReader.readUid"></a>
+<h4>PlistReader.readUid</h4>
+<b>readUid</b>(<i>length</i>)
+<p>
+        Private method to read a UID.
+</p><dl>
+<dt><i>length</i></dt>
+<dd>
+length of the UID (integer)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+Uid object
+</dd>
+</dl><a NAME="PlistReader.readUnicode" ID="PlistReader.readUnicode"></a>
+<h4>PlistReader.readUnicode</h4>
+<b>readUnicode</b>(<i>length</i>)
+<p>
+        Private method to read an Unicode encoded string.
+</p><dl>
+<dt><i>length</i></dt>
+<dd>
+length of the string (integer)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+unicode encoded string
+</dd>
+</dl><a NAME="PlistReader.reset" ID="PlistReader.reset"></a>
+<h4>PlistReader.reset</h4>
+<b>reset</b>(<i></i>)
+<p>
+        Private method to reset the instance object.
+</p><a NAME="PlistReader.setCurrentOffsetToObjectNumber" ID="PlistReader.setCurrentOffsetToObjectNumber"></a>
+<h4>PlistReader.setCurrentOffsetToObjectNumber</h4>
+<b>setCurrentOffsetToObjectNumber</b>(<i>objectNumber</i>)
+<p>
+        Private method to set the current offset.
+</p><dl>
+<dt><i>objectNumber</i></dt>
+<dd>
+number of the object (integer)
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="PlistWriter" ID="PlistWriter"></a>
+<h2>PlistWriter</h2>
+<p>
+    Class implementing the plist writer.
+</p>
+<h3>Derived from</h3>
+object
+<h3>Class Attributes</h3>
+<table>
+<tr><td>byteCounts</td></tr><tr><td>computedUniques</td></tr><tr><td>file</td></tr><tr><td>header</td></tr><tr><td>referencePositions</td></tr><tr><td>trailer</td></tr><tr><td>wrappedFalse</td></tr><tr><td>wrappedTrue</td></tr><tr><td>writtenReferences</td></tr>
+</table>
+<h3>Class Methods</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+<table>
+<tr>
+<td><a href="#PlistWriter.__init__">PlistWriter</a></td>
+<td>Constructor</td>
+</tr><tr>
+<td><a href="#PlistWriter.binaryInt">binaryInt</a></td>
+<td>Private method to pack an integer object.</td>
+</tr><tr>
+<td><a href="#PlistWriter.binaryReal">binaryReal</a></td>
+<td>Private method to pack a real object.</td>
+</tr><tr>
+<td><a href="#PlistWriter.check_key">check_key</a></td>
+<td></td>
+</tr><tr>
+<td><a href="#PlistWriter.computeOffsets">computeOffsets</a></td>
+<td></td>
+</tr><tr>
+<td><a href="#PlistWriter.incrementByteCount">incrementByteCount</a></td>
+<td></td>
+</tr><tr>
+<td><a href="#PlistWriter.intSize">intSize</a></td>
+<td>Private method to determine the number of bytes necessary to store the given integer.</td>
+</tr><tr>
+<td><a href="#PlistWriter.positionOfObjectReference">positionOfObjectReference</a></td>
+<td>Private method to get the position of an object.</td>
+</tr><tr>
+<td><a href="#PlistWriter.proc_size">proc_size</a></td>
+<td></td>
+</tr><tr>
+<td><a href="#PlistWriter.proc_variable_length">proc_variable_length</a></td>
+<td></td>
+</tr><tr>
+<td><a href="#PlistWriter.realSize">realSize</a></td>
+<td>Private method to determine the number of bytes necessary to store the given real.</td>
+</tr><tr>
+<td><a href="#PlistWriter.reset">reset</a></td>
+<td>Private method to reset the instance object.</td>
+</tr><tr>
+<td><a href="#PlistWriter.wrapRoot">wrapRoot</a></td>
+<td>Private method to generate object wrappers.</td>
+</tr><tr>
+<td><a href="#PlistWriter.writeObject">writeObject</a></td>
+<td>Private method to serialize the given object to the output.</td>
+</tr><tr>
+<td><a href="#PlistWriter.writeObjectReference">writeObjectReference</a></td>
+<td>Private method to write an object reference.</td>
+</tr><tr>
+<td><a href="#PlistWriter.writeOffsetTable">writeOffsetTable</a></td>
+<td>Private method to write all of the object reference offsets.</td>
+</tr><tr>
+<td><a href="#PlistWriter.writeRoot">writeRoot</a></td>
+<td>Public method to write an object to a plist file.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<a NAME="PlistWriter.__init__" ID="PlistWriter.__init__"></a>
+<h4>PlistWriter (Constructor)</h4>
+<b>PlistWriter</b>(<i>file</i>)
+<p>
+        Constructor
+</p><dl>
+<dt><i>file</i></dt>
+<dd>
+file to write the plist data to (file object)
+</dd>
+</dl><a NAME="PlistWriter.binaryInt" ID="PlistWriter.binaryInt"></a>
+<h4>PlistWriter.binaryInt</h4>
+<b>binaryInt</b>(<i>obj, bytes=None</i>)
+<p>
+        Private method to pack an integer object.
+</p><dl>
+<dt><i>obj</i></dt>
+<dd>
+integer to be packed
+</dd><dt><i>bytes</i></dt>
+<dd>
+length the integer should be packed into (integer)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+serialized object (bytes)
+</dd>
+</dl><a NAME="PlistWriter.binaryReal" ID="PlistWriter.binaryReal"></a>
+<h4>PlistWriter.binaryReal</h4>
+<b>binaryReal</b>(<i>obj</i>)
+<p>
+        Private method to pack a real object.
+</p><dl>
+<dt><i>obj</i></dt>
+<dd>
+real to be packed
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+serialized object (bytes)
+</dd>
+</dl><a NAME="PlistWriter.check_key" ID="PlistWriter.check_key"></a>
+<h4>PlistWriter.check_key</h4>
+<b>check_key</b>(<i></i>)
+<a NAME="PlistWriter.computeOffsets" ID="PlistWriter.computeOffsets"></a>
+<h4>PlistWriter.computeOffsets</h4>
+<b>computeOffsets</b>(<i>obj, asReference=False, isRoot=False</i>)
+<a NAME="PlistWriter.incrementByteCount" ID="PlistWriter.incrementByteCount"></a>
+<h4>PlistWriter.incrementByteCount</h4>
+<b>incrementByteCount</b>(<i>field, incr=1</i>)
+<a NAME="PlistWriter.intSize" ID="PlistWriter.intSize"></a>
+<h4>PlistWriter.intSize</h4>
+<b>intSize</b>(<i>obj</i>)
+<p>
+        Private method to determine the number of bytes necessary to store the
+        given integer.
+</p><dl>
+<dt><i>obj</i></dt>
+<dd>
+integer object
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+number of bytes required (integer)
+</dd>
+</dl><a NAME="PlistWriter.positionOfObjectReference" ID="PlistWriter.positionOfObjectReference"></a>
+<h4>PlistWriter.positionOfObjectReference</h4>
+<b>positionOfObjectReference</b>(<i>obj</i>)
+<p>
+        Private method to get the position of an object.
+</p><p>
+        If the given object has been written already, return its
+        position in the offset table. Otherwise, return None.
+</p><dl>
+<dt>Returns:</dt>
+<dd>
+position of the object (integer)
+</dd>
+</dl><a NAME="PlistWriter.proc_size" ID="PlistWriter.proc_size"></a>
+<h4>PlistWriter.proc_size</h4>
+<b>proc_size</b>(<i></i>)
+<a NAME="PlistWriter.proc_variable_length" ID="PlistWriter.proc_variable_length"></a>
+<h4>PlistWriter.proc_variable_length</h4>
+<b>proc_variable_length</b>(<i>length</i>)
+<a NAME="PlistWriter.realSize" ID="PlistWriter.realSize"></a>
+<h4>PlistWriter.realSize</h4>
+<b>realSize</b>(<i>obj</i>)
+<p>
+        Private method to determine the number of bytes necessary to store the
+        given real.
+</p><dl>
+<dt><i>obj</i></dt>
+<dd>
+real object
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+number of bytes required (integer)
+</dd>
+</dl><a NAME="PlistWriter.reset" ID="PlistWriter.reset"></a>
+<h4>PlistWriter.reset</h4>
+<b>reset</b>(<i></i>)
+<p>
+        Private method to reset the instance object.
+</p><a NAME="PlistWriter.wrapRoot" ID="PlistWriter.wrapRoot"></a>
+<h4>PlistWriter.wrapRoot</h4>
+<b>wrapRoot</b>(<i>root</i>)
+<p>
+        Private method to generate object wrappers.
+</p><dl>
+<dt><i>root</i></dt>
+<dd>
+object to be wrapped
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+wrapped object
+</dd>
+</dl><a NAME="PlistWriter.writeObject" ID="PlistWriter.writeObject"></a>
+<h4>PlistWriter.writeObject</h4>
+<b>writeObject</b>(<i>obj, output, setReferencePosition=False</i>)
+<p>
+        Private method to serialize the given object to the output.
+</p><dl>
+<dt><i>obj</i></dt>
+<dd>
+object to be serialized
+</dd><dt><i>output</i></dt>
+<dd>
+output to be serialized to (bytes)
+</dd><dt><i>setReferencePosition</i></dt>
+<dd>
+flag indicating, that the reference
+            position the object was written to shall be recorded (boolean)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+new output
+</dd>
+</dl><a NAME="PlistWriter.writeObjectReference" ID="PlistWriter.writeObjectReference"></a>
+<h4>PlistWriter.writeObjectReference</h4>
+<b>writeObjectReference</b>(<i>obj, output</i>)
+<p>
+        Private method to write an object reference.
+</p><p>
+        Tries to write an object reference, adding it to the references
+        table. Does not write the actual object bytes or set the reference
+        position. Returns a tuple of whether the object was a new reference
+        (True if it was, False if it already was in the reference table)
+        and the new output.
+</p><dl>
+<dt><i>obj</i></dt>
+<dd>
+object to be written
+</dd><dt><i>output</i></dt>
+<dd>
+output stream to append the object to
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+flag indicating a new reference and the new output
+</dd>
+</dl><a NAME="PlistWriter.writeOffsetTable" ID="PlistWriter.writeOffsetTable"></a>
+<h4>PlistWriter.writeOffsetTable</h4>
+<b>writeOffsetTable</b>(<i>output</i>)
+<p>
+        Private method to write all of the object reference offsets.
+</p><dl>
+<dt><i>output</i></dt>
+<dd>
+current output (bytes)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+new output (bytes)
+</dd>
+</dl><a NAME="PlistWriter.writeRoot" ID="PlistWriter.writeRoot"></a>
+<h4>PlistWriter.writeRoot</h4>
+<b>writeRoot</b>(<i>root</i>)
+<p>
+        Public method to write an object to a plist file.
+</p><p>
+        Strategy is:
+        <ul>
+        <li>write header</li>
+        <li>wrap root object so everything is hashable</li>
+        <li>compute size of objects which will be written
+          <ul>
+          <li>need to do this in order to know how large the object refs
+            will be in the list/dict/set reference lists</li>
+        </ul></li>
+        <li>write objects
+          <ul>
+          <li>keep objects in writtenReferences</li>
+          <li>keep positions of object references in referencePositions</li>
+          <li>write object references with the length computed previously</li>
+        </ul></li>
+        <li>computer object reference length</li>
+        <li>write object reference positions</li>
+        <li>write trailer</li>
+        </ul>
+</p><dl>
+<dt><i>root</i></dt>
+<dd>
+reference to the object to be written
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="Uid" ID="Uid"></a>
+<h2>Uid</h2>
+<p>
+    Class implementing a wrapper around integers for representing UID values.
+</p><p>
+    This is used in keyed archiving.
+</p>
+<h3>Derived from</h3>
+int
+<h3>Class Attributes</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+<table>
+<tr>
+<td><a href="#Uid.__repr__">__repr__</a></td>
+<td></td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+<table>
+<tr><td>None</td></tr>
+</table>
+<a NAME="Uid.__repr__" ID="Uid.__repr__"></a>
+<h4>Uid.__repr__</h4>
+<b>__repr__</b>(<i></i>)
+
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="is_stream_binary_plist" ID="is_stream_binary_plist"></a>
+<h2>is_stream_binary_plist</h2>
+<b>is_stream_binary_plist</b>(<i>stream</i>)
+<p>
+    Module function to check, if the stream is a binary plist.
+</p><dl>
+<dt><i>stream</i></dt>
+<dd>
+plist stream (file object)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+flag indicating a binary plist (boolean)
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="readPlist" ID="readPlist"></a>
+<h2>readPlist</h2>
+<b>readPlist</b>(<i>pathOrFile</i>)
+<p>
+    Module function to read a plist file.
+</p><dl>
+<dt><i>pathOrFile</i></dt>
+<dd>
+name of the plist file (string) or an open file (file object)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+reference to the read object
+</dd>
+</dl><dl>
+<dt>Raises <b>InvalidPlistException</b>:</dt>
+<dd>
+raised to signal an invalid plist file
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="readPlistFromBytes" ID="readPlistFromBytes"></a>
+<h2>readPlistFromBytes</h2>
+<b>readPlistFromBytes</b>(<i>data</i>)
+<p>
+    Module function to read from a plist bytes object.
+</p><dl>
+<dt><i>data</i></dt>
+<dd>
+plist data (bytes)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+reference to the read object
+</dd>
+</dl><dl>
+<dt>Raises <b>InvalidPlistException</b>:</dt>
+<dd>
+raised to signal an invalid plist file
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="writePlist" ID="writePlist"></a>
+<h2>writePlist</h2>
+<b>writePlist</b>(<i>rootObject, pathOrFile, binary=True</i>)
+<p>
+    Module function to write a plist file.
+</p><dl>
+<dt><i>rootObject</i></dt>
+<dd>
+reference to the object to be written
+</dd><dt><i>pathOrFile</i></dt>
+<dd>
+name of the plist file (string) or an open file (file object)
+</dd><dt><i>binary</i></dt>
+<dd>
+flag indicating the generation of a binary plist file (boolean)
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr /><hr />
+<a NAME="writePlistToBytes" ID="writePlistToBytes"></a>
+<h2>writePlistToBytes</h2>
+<b>writePlistToBytes</b>(<i>rootObject, binary=True</i>)
+<p>
+    Module function to write a plist bytes object.
+</p><dl>
+<dt><i>rootObject</i></dt>
+<dd>
+reference to the object to be written
+</dd><dt><i>binary</i></dt>
+<dd>
+flag indicating the generation of a binary plist bytes object (boolean)
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+</body></html>
\ No newline at end of file
--- a/Documentation/Source/index-eric5.Helpviewer.Bookmarks.BookmarksImporters.html	Mon Mar 19 19:24:12 2012 +0100
+++ b/Documentation/Source/index-eric5.Helpviewer.Bookmarks.BookmarksImporters.html	Mon Mar 19 20:14:07 2012 +0100
@@ -47,6 +47,9 @@
 <td><a href="eric5.Helpviewer.Bookmarks.BookmarksImporters.OperaImporter.html">OperaImporter</a></td>
 <td>Module implementing an importer for Opera bookmarks.</td>
 </tr><tr>
+<td><a href="eric5.Helpviewer.Bookmarks.BookmarksImporters.SafariImporter.html">SafariImporter</a></td>
+<td>Module implementing an importer for Apple Safari bookmarks.</td>
+</tr><tr>
 <td><a href="eric5.Helpviewer.Bookmarks.BookmarksImporters.XbelImporter.html">XbelImporter</a></td>
 <td>Module implementing an importer for XBEL files.</td>
 </tr><tr>
--- a/Documentation/Source/index-eric5.Utilities.html	Mon Mar 19 19:24:12 2012 +0100
+++ b/Documentation/Source/index-eric5.Utilities.html	Mon Mar 19 20:14:07 2012 +0100
@@ -60,6 +60,9 @@
 <td><a href="eric5.Utilities.__init__.html">Utilities</a></td>
 <td>Package implementing various functions/classes needed everywhere within eric5.</td>
 </tr><tr>
+<td><a href="eric5.Utilities.binplistlib.html">binplistlib</a></td>
+<td>Module implementing a library for reading and writing binary property list files.</td>
+</tr><tr>
 <td><a href="eric5.Utilities.uic.html">uic</a></td>
 <td>Module implementing a function to compile all user interface files of a directory or directory tree.</td>
 </tr>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py	Mon Mar 19 20:14:07 2012 +0100
@@ -0,0 +1,137 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2012 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing an importer for Apple Safari bookmarks.
+"""
+
+import os
+
+from PyQt4.QtCore import QCoreApplication, QDate, Qt
+
+from ..BookmarkNode import BookmarkNode
+
+from .BookmarksImporter import BookmarksImporter
+
+import UI.PixmapCache
+import Globals
+
+from Utilities import binplistlib
+
+
+def getImporterInfo(id):
+    """
+    Module function to get information for the given source id.
+    
+    @return tuple with an icon (QPixmap), readable name (string), name of
+        the default bookmarks file (string), an info text (string),
+        a prompt (string) and the default directory of the bookmarks file (string)
+    """
+    if id == "safari":
+        if Globals.isWindowsPlatform():
+            standardDir = os.path.expandvars(
+                "%APPDATA%\\Apple Computer\\Safari")
+        else:
+            # TODO: changes this on the Mac
+##            standardDir = os.path.expanduser("~/.config/google-chrome/Default")
+            standardDir = ""
+        return (
+            UI.PixmapCache.getPixmap("safari.png"),
+            "Apple Safari",
+            "Bookmarks.plist",
+            QCoreApplication.translate("SafariImporter",
+                """Apple Safari stores its bookmarks in the <b>Bookmarks.plist</b> """
+                """file. This file is usually located in"""),
+            QCoreApplication.translate("SafariImporter",
+                """Please choose the file to begin importing bookmarks."""),
+            standardDir,
+        )
+    else:
+        raise ValueError("Unsupported browser ID given ({0}).".format(id))
+
+
+class SafariImporter(BookmarksImporter):
+    """
+    Class implementing the Apple Safari bookmarks importer.
+    """
+    def __init__(self, id="", parent=None):
+        """
+        Constructor
+        
+        @param id source ID (string)
+        @param parent reference to the parent object (QObject)
+        """
+        super().__init__(id, parent)
+        
+        self.__fileName = ""
+    
+    def setPath(self, path):
+        """
+        Public method to set the path of the bookmarks file or directory.
+        
+        @param path bookmarks file or directory (string)
+        """
+        self.__fileName = path
+    
+    def open(self):
+        """
+        Public method to open the bookmarks file.
+        
+        @return flag indicating success (boolean)
+        """
+        if not os.path.exists(self.__fileName):
+            self._error = True
+            self._errorString = self.trUtf8("File '{0}' does not exist.")\
+                .format(self.__fileName)
+            return False
+        return True
+    
+    def importedBookmarks(self):
+        """
+        Public method to get the imported bookmarks.
+        
+        @return imported bookmarks (BookmarkNode)
+        """
+        try:
+            bookmarksDict = binplistlib.readPlist(self.__fileName)
+        except binplistlib.InvalidPlistException as err:
+            self._error = True
+            self._errorString = self.trUtf8(
+                "Bookmarks file cannot be read.\nReason: {0}".format(str(err)))
+            return None
+        
+        importRootNode = BookmarkNode(BookmarkNode.Folder)
+        if bookmarksDict["WebBookmarkFileVersion"] == 1 and \
+           bookmarksDict["WebBookmarkType"] == "WebBookmarkTypeList":
+            self.__processChildren(bookmarksDict["Children"], importRootNode)
+        
+        if self._id == "safari":
+            importRootNode.title = self.trUtf8("Apple Safari Import")
+        else:
+            importRootNode.title = self.trUtf8("Imported {0}")\
+                .format(QDate.currentDate().toString(Qt.SystemLocaleShortDate))
+        return importRootNode
+    
+    def __processChildren(self, children, rootNode):
+        """
+        Private method to process the list of children.
+        
+        @param children list of child nodes to be processed (list of dict)
+        @param rootNode node to add the bookmarks to (BookmarkNode)
+        """
+        for child in children:
+            if child["WebBookmarkType"] == "WebBookmarkTypeList":
+                folder = BookmarkNode(BookmarkNode.Folder, rootNode)
+                folder.title = child["Title"].replace("&", "&&")
+                if "Children" in child:
+                    self.__processChildren(child["Children"], folder)
+            elif child["WebBookmarkType"] == "WebBookmarkTypeLeaf":
+                url = child["URLString"]
+                if url.startswith(("place:", "about:")):
+                    continue
+                
+                bookmark = BookmarkNode(BookmarkNode.Bookmark, rootNode)
+                bookmark.url = url
+                bookmark.title = child["URIDictionary"]["title"].replace("&", "&&")
--- a/Helpviewer/Bookmarks/BookmarksImporters/__init__.py	Mon Mar 19 19:24:12 2012 +0100
+++ b/Helpviewer/Bookmarks/BookmarksImporters/__init__.py	Mon Mar 19 20:14:07 2012 +0100
@@ -32,6 +32,8 @@
             (UI.PixmapCache.getIcon("chromium.png"), "Chromium", "chromium"))
     importers.append(
         (UI.PixmapCache.getIcon("opera.png"), "Opera", "opera"))
+    importers.append(
+        (UI.PixmapCache.getIcon("safari.png"), "Apple Safari", "safari"))
     if Globals.isWindowsPlatform():
         importers.append(
             (UI.PixmapCache.getIcon("internet_explorer.png"), "Internet Explorer", "ie"))
@@ -74,6 +76,9 @@
     elif id == "ie":
         from . import IExplorerImporter
         return IExplorerImporter.getImporterInfo(id)
+    elif id == "safari":
+        from . import SafariImporter
+        return SafariImporter.getImporterInfo(id)
     else:
         raise ValueError("Invalid importer ID given ({0}).".format(id))
 
@@ -103,5 +108,8 @@
     elif id == "ie":
         from . import IExplorerImporter
         return IExplorerImporter.IExplorerImporter(id, parent)
+    elif id == "safari":
+        from . import SafariImporter
+        return SafariImporter.SafariImporter(id, parent)
     else:
         raise ValueError("No importer for ID {0}.".format(id))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/binplistlib.py	Mon Mar 19 20:14:07 2012 +0100
@@ -0,0 +1,967 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2012 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a library for reading and writing binary property list files.
+
+Binary Property List (plist) files provide a faster and smaller serialization
+format for property lists on OS X. This is a library for generating binary
+plists which can be read by OS X, iOS, or other clients.
+
+The API models the plistlib API, and will call through to plistlib when
+XML serialization or deserialization is required.
+
+To generate plists with UID values, wrap the values with the Uid object. The
+value must be an int.
+
+To generate plists with NSData/CFData values, wrap the values with the
+Data object. The value must be a bytes object.
+
+Date values can only be datetime.datetime objects.
+
+The exceptions InvalidPlistException and NotBinaryPlistException may be 
+thrown to indicate that the data cannot be serialized or deserialized as
+a binary plist.
+
+Plist generation example:
+<pre>
+    from binplistlib import *
+    from datetime import datetime
+    plist = {'aKey':'aValue',
+             '0':1.322,
+             'now':datetime.now(),
+             'list':[1,2,3],
+             'tuple':('a','b','c')
+             }
+    try:
+        writePlist(plist, "example.plist")
+    except (InvalidPlistException, NotBinaryPlistException) as e:
+        print("Something bad happened:", e)
+</pre>
+Plist parsing example:
+<pre>
+    from binplistlib import *
+    try:
+        plist = readPlist("example.plist")
+        print(plist)
+    except (InvalidPlistException, NotBinaryPlistException) as e:
+        print("Not a plist:", e)
+</pre>
+"""
+
+#
+# Ported from the Python 2 biplist.py script.
+#
+# Original License:
+#
+# Copyright (c) 2010, Andrew Wooster
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+#    * Redistributions of source code must retain the above copyright notice,
+#      this list of conditions and the following disclaimer.
+#    * Redistributions in binary form must reproduce the above copyright
+#      notice, this list of conditions and the following disclaimer in the
+#      documentation and/or other materials provided with the distribution.
+#    * Neither the name of biplist nor the names of its contributors may be
+#      used to endorse or promote products derived from this software without 
+#      specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+from collections import namedtuple
+from io import BytesIO
+import calendar
+import datetime
+import math
+import plistlib
+from struct import pack, unpack
+
+__all__ = [
+    'Uid', 'Data', 'readPlist', 'writePlist', 'readPlistFromBytes',
+    'writePlistToBytes', 'InvalidPlistException', 'NotBinaryPlistException'
+]
+
+apple_reference_date_offset = 978307200
+
+
+class Uid(int):
+    """
+    Class implementing a wrapper around integers for representing UID values.
+    
+    This is used in keyed archiving.
+    """
+    def __repr__(self):
+        return "Uid(%d)" % self
+
+
+class Data(bytes):
+    """
+    Class implementing a wrapper around bytes types for representing Data values.
+    """
+    pass
+
+
+class InvalidPlistException(Exception):
+    """
+    Exception raised when the plist is incorrectly formatted.
+    """
+    pass
+
+
+class NotBinaryPlistException(Exception):
+    """
+    Exception raised when a binary plist was expected but not encountered.
+    """
+    pass
+
+
+def readPlist(pathOrFile):
+    """
+    Module function to read a plist file.
+    
+    @param pathOrFile name of the plist file (string) or an open file (file object)
+    @return reference to the read object
+    @exception InvalidPlistException raised to signal an invalid plist file
+    """
+    didOpen = False
+    result = None
+    if isinstance(pathOrFile, str):
+        pathOrFile = open(pathOrFile, 'rb')
+        didOpen = True
+    try:
+        reader = PlistReader(pathOrFile)
+        result = reader.parse()
+    except NotBinaryPlistException as e:
+        try:
+            pathOrFile.seek(0)
+            result = plistlib.readPlist(pathOrFile)
+        except Exception as e:
+            raise InvalidPlistException(e)
+    if didOpen:
+        pathOrFile.close()
+    return result
+
+def writePlist(rootObject, pathOrFile, binary=True):
+    """
+    Module function to write a plist file.
+    
+    @param rootObject reference to the object to be written
+    @param pathOrFile name of the plist file (string) or an open file (file object)
+    @param binary flag indicating the generation of a binary plist file (boolean)
+    """
+    if not binary:
+        plistlib.writePlist(rootObject, pathOrFile)
+        return
+    else:
+        didOpen = False
+        if isinstance(pathOrFile, str):
+            pathOrFile = open(pathOrFile, 'wb')
+            didOpen = True
+        writer = PlistWriter(pathOrFile)
+        writer.writeRoot(rootObject)
+        if didOpen:
+            pathOrFile.close()
+        return
+
+def readPlistFromBytes(data):
+    """
+    Module function to read from a plist bytes object.
+    
+    @param data plist data (bytes)
+    @return reference to the read object
+    @exception InvalidPlistException raised to signal an invalid plist file
+    """
+    return readPlist(BytesIO(data))
+
+def writePlistToBytes(rootObject, binary=True):
+    """
+    Module function to write a plist bytes object.
+    
+    @param rootObject reference to the object to be written
+    @param binary flag indicating the generation of a binary plist bytes object (boolean)
+    """
+    if not binary:
+        return plistlib.writePlistToBytes(rootObject)
+    else:
+        io = BytesIO()
+        writer = PlistWriter(io)
+        writer.writeRoot(rootObject)
+        return io.getvalue()
+
+def is_stream_binary_plist(stream):
+    """
+    Module function to check, if the stream is a binary plist.
+    
+    @param stream plist stream (file object)
+    @return flag indicating a binary plist (boolean)
+    """
+    stream.seek(0)
+    header = stream.read(7)
+    if header == b'bplist0':
+        return True
+    else:
+        return False
+
+PlistTrailer = namedtuple('PlistTrailer',
+    'offsetSize, objectRefSize, offsetCount, topLevelObjectNumber, offsetTableOffset')
+PlistByteCounts = namedtuple('PlistByteCounts',
+    'nullBytes, boolBytes, intBytes, realBytes, dateBytes, dataBytes, stringBytes, '
+    'uidBytes, arrayBytes, setBytes, dictBytes')
+
+class PlistReader(object):
+    """
+    Class implementing the plist reader.
+    """
+    file = None
+    contents = b''
+    offsets = None
+    trailer = None
+    currentOffset = 0
+    
+    def __init__(self, fileOrStream):
+        """
+        Constructor
+        
+        @param fileOrStream open file containing the plist data (file object)
+        """
+        self.reset()
+        self.file = fileOrStream
+    
+    def parse(self):
+        """
+        Public method to parse the plist data.
+        
+        @return unpickled object
+        """
+        return self.readRoot()
+    
+    def reset(self):
+        """
+        Private method to reset the instance object.
+        """
+        self.trailer = None
+        self.contents = b''
+        self.offsets = []
+        self.currentOffset = 0
+    
+    def readRoot(self):
+        """
+        Private method to read the root object.
+        
+        @return unpickled object
+        """
+        result = None
+        self.reset()
+        # Get the header, make sure it's a valid file.
+        if not is_stream_binary_plist(self.file):
+            raise NotBinaryPlistException()
+        self.file.seek(0)
+        self.contents = self.file.read()
+        if len(self.contents) < 32:
+            raise InvalidPlistException("File is too short.")
+        trailerContents = self.contents[-32:]
+        try:
+            self.trailer = PlistTrailer._make(unpack("!xxxxxxBBQQQ", trailerContents))
+            offset_size = self.trailer.offsetSize * self.trailer.offsetCount
+            offset = self.trailer.offsetTableOffset
+            offset_contents = self.contents[offset:offset+offset_size]
+            offset_i = 0
+            while offset_i < self.trailer.offsetCount:
+                begin = self.trailer.offsetSize*offset_i
+                tmp_contents = offset_contents[begin:begin+self.trailer.offsetSize]
+                tmp_sized = self.getSizedInteger(tmp_contents, self.trailer.offsetSize)
+                self.offsets.append(tmp_sized)
+                offset_i += 1
+            self.setCurrentOffsetToObjectNumber(self.trailer.topLevelObjectNumber)
+            result = self.readObject()
+        except TypeError as e:
+            raise InvalidPlistException(e)
+        return result
+    
+    def setCurrentOffsetToObjectNumber(self, objectNumber):
+        """
+        Private method to set the current offset.
+        
+        @param objectNumber number of the object (integer)
+        """
+        self.currentOffset = self.offsets[objectNumber]
+    
+    def readObject(self):
+        """
+        Private method to read the object data.
+        
+        @return unpickled object
+        """
+        result = None
+        tmp_byte = self.contents[self.currentOffset:self.currentOffset+1]
+        marker_byte = unpack("!B", tmp_byte)[0]
+        format = (marker_byte >> 4) & 0x0f
+        extra = marker_byte & 0x0f
+        self.currentOffset += 1
+        
+        def proc_extra(extra):
+            if extra == 0b1111:
+                #self.currentOffset += 1
+                extra = self.readObject()
+            return extra
+        
+        # bool, null, or fill byte
+        if format == 0b0000:
+            if extra == 0b0000:
+                result = None
+            elif extra == 0b1000:
+                result = False
+            elif extra == 0b1001:
+                result = True
+            elif extra == 0b1111:
+                pass # fill byte
+            else:
+                raise InvalidPlistException(
+                    "Invalid object found at offset: {0}".format(self.currentOffset - 1))
+        # int
+        elif format == 0b0001:
+            extra = proc_extra(extra)
+            result = self.readInteger(pow(2, extra))
+        # real
+        elif format == 0b0010:
+            extra = proc_extra(extra)
+            result = self.readReal(extra)
+        # date
+        elif format == 0b0011 and extra == 0b0011:
+            result = self.readDate()
+        # data
+        elif format == 0b0100:
+            extra = proc_extra(extra)
+            result = self.readData(extra)
+        # ascii string
+        elif format == 0b0101:
+            extra = proc_extra(extra)
+            result = self.readAsciiString(extra)
+        # Unicode string
+        elif format == 0b0110:
+            extra = proc_extra(extra)
+            result = self.readUnicode(extra)
+        # uid
+        elif format == 0b1000:
+            result = self.readUid(extra)
+        # array
+        elif format == 0b1010:
+            extra = proc_extra(extra)
+            result = self.readArray(extra)
+        # set
+        elif format == 0b1100:
+            extra = proc_extra(extra)
+            result = set(self.readArray(extra))
+        # dict
+        elif format == 0b1101:
+            extra = proc_extra(extra)
+            result = self.readDict(extra)
+        else:    
+            raise InvalidPlistException(
+                "Invalid object found: {{format: {0}, extra: {1}}}".format(
+                    bin(format), bin(extra)))
+        return result
+    
+    def readInteger(self, bytes):
+        """
+        Private method to read an Integer object.
+        
+        @param bytes length of the object (integer)
+        @return integer object
+        """
+        result = 0
+        original_offset = self.currentOffset
+        data = self.contents[self.currentOffset:self.currentOffset+bytes]
+        result = self.getSizedInteger(data, bytes)
+        self.currentOffset = original_offset + bytes
+        return result
+    
+    def readReal(self, length):
+        """
+        Private method to read a Real object.
+        
+        @param length length of the object (integer)
+        @return float object
+        """
+        result = 0.0
+        to_read = pow(2, length)
+        data = self.contents[self.currentOffset:self.currentOffset+to_read]
+        if length == 2: # 4 bytes
+            result = unpack('>f', data)[0]
+        elif length == 3: # 8 bytes
+            result = unpack('>d', data)[0]
+        else:
+            raise InvalidPlistException(
+                "Unknown real of length {0} bytes".format(to_read))
+        return result
+    
+    def readRefs(self, count):    
+        """
+        Private method to read References.
+        
+        @param count amount of the references (integer)
+        @return list of references (list of integers)
+        """
+        refs = []
+        i = 0
+        while i < count:
+            fragment = self.contents[
+                self.currentOffset:self.currentOffset+self.trailer.objectRefSize]
+            ref = self.getSizedInteger(fragment, len(fragment))
+            refs.append(ref)
+            self.currentOffset += self.trailer.objectRefSize
+            i += 1
+        return refs
+    
+    def readArray(self, count):
+        """
+        Private method to read an Array object.
+        
+        @param count number of array elements (integer)
+        @return list of unpickled objects
+        """
+        result = []
+        values = self.readRefs(count)
+        i = 0
+        while i < len(values):
+            self.setCurrentOffsetToObjectNumber(values[i])
+            value = self.readObject()
+            result.append(value)
+            i += 1
+        return result
+    
+    def readDict(self, count):
+        """
+        Private method to read a Dictionary object.
+        
+        @param count number of dictionary elements (integer)
+        @return dictionary of unpickled objects
+        """
+        result = {}
+        keys = self.readRefs(count)
+        values = self.readRefs(count)
+        i = 0
+        while i < len(keys):
+            self.setCurrentOffsetToObjectNumber(keys[i])
+            key = self.readObject()
+            self.setCurrentOffsetToObjectNumber(values[i])
+            value = self.readObject()
+            result[key] = value
+            i += 1
+        return result
+    
+    def readAsciiString(self, length):
+        """
+        Private method to read an ASCII encoded string.
+        
+        @param length length of the string (integer)
+        @return ASCII encoded string
+        """
+        result = str(unpack("!{0}s".format(length),
+            self.contents[self.currentOffset:self.currentOffset+length])[0],
+            encoding="ascii")
+        self.currentOffset += length
+        return result
+    
+    def readUnicode(self, length):
+        """
+        Private method to read an Unicode encoded string.
+        
+        @param length length of the string (integer)
+        @return unicode encoded string
+        """
+        actual_length = length*2
+        data = self.contents[self.currentOffset:self.currentOffset+actual_length]
+        # unpack not needed?!! data = unpack(">%ds" % (actual_length), data)[0]
+        self.currentOffset += actual_length
+        return data.decode('utf_16_be')
+    
+    def readDate(self):
+        """
+        Private method to read a date.
+        
+        @return date object (datetime.datetime)
+        """
+        global apple_reference_date_offset
+        result = unpack(">d", self.contents[self.currentOffset:self.currentOffset+8])[0]
+        result = datetime.datetime.utcfromtimestamp(result + apple_reference_date_offset)
+        self.currentOffset += 8
+        return result
+    
+    def readData(self, length):
+        """
+        Private method to read some bytes.
+        
+        @param length number of bytes to read (integer)
+        @return Data object
+        """
+        result = self.contents[self.currentOffset:self.currentOffset+length]
+        self.currentOffset += length
+        return Data(result)
+    
+    def readUid(self, length):
+        """
+        Private method to read a UID.
+        
+        @param length length of the UID (integer)
+        @return Uid object
+        """
+        return Uid(self.readInteger(length+1))
+    
+    def getSizedInteger(self, data, bytes):
+        """
+        Private method to read an integer of a specific size.
+        
+        @param data data to extract the integer from (bytes)
+        @param bytes length of the integer (integer)
+        """
+        result = 0
+        # 1, 2, and 4 byte integers are unsigned
+        if bytes == 1:
+            result = unpack('>B', data)[0]
+        elif bytes == 2:
+            result = unpack('>H', data)[0]
+        elif bytes == 4:
+            result = unpack('>L', data)[0]
+        elif bytes == 8:
+            result = unpack('>q', data)[0]
+        else:
+            raise InvalidPlistException("Encountered integer longer than 8 bytes.")
+        return result
+
+class HashableWrapper(object):
+    """
+    Class wrapping a hashable value.
+    """
+    def __init__(self, value):
+        self.value = value
+    def __repr__(self):
+        return "<HashableWrapper: %s>" % [self.value]
+
+class BoolWrapper(object):
+    """
+    Class wrapping a boolean value.
+    """
+    def __init__(self, value):
+        self.value = value
+    def __repr__(self):
+        return "<BoolWrapper: %s>" % self.value
+
+class PlistWriter(object):
+    """
+    Class implementing the plist writer.
+    """
+    header = b'bplist00bybiplist1.0'
+    file = None
+    byteCounts = None
+    trailer = None
+    computedUniques = None
+    writtenReferences = None
+    referencePositions = None
+    wrappedTrue = None
+    wrappedFalse = None
+    
+    def __init__(self, file):
+        """
+        Constructor
+        
+        @param file file to write the plist data to (file object)
+        """
+        self.reset()
+        self.file = file
+        self.wrappedTrue = BoolWrapper(True)
+        self.wrappedFalse = BoolWrapper(False)
+
+    def reset(self):
+        """
+        Private method to reset the instance object.
+        """
+        self.byteCounts = PlistByteCounts(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+        self.trailer = PlistTrailer(0, 0, 0, 0, 0)
+        
+        # A set of all the uniques which have been computed.
+        self.computedUniques = set()
+        # A list of all the uniques which have been written.
+        self.writtenReferences = {}
+        # A dict of the positions of the written uniques.
+        self.referencePositions = {}
+        
+    def positionOfObjectReference(self, obj):
+        """
+        Private method to get the position of an object.
+        
+        If the given object has been written already, return its
+        position in the offset table. Otherwise, return None.
+        
+        @return position of the object (integer)
+        """
+        return self.writtenReferences.get(obj)
+        
+    def writeRoot(self, root):
+        """
+        Public method to write an object to a plist file.
+        
+        Strategy is:
+        <ul>
+        <li>write header</li>
+        <li>wrap root object so everything is hashable</li>
+        <li>compute size of objects which will be written
+          <ul>
+          <li>need to do this in order to know how large the object refs
+            will be in the list/dict/set reference lists</li>
+        </ul></li>
+        <li>write objects
+          <ul>
+          <li>keep objects in writtenReferences</li>
+          <li>keep positions of object references in referencePositions</li>
+          <li>write object references with the length computed previously</li>
+        </ul></li>
+        <li>computer object reference length</li>
+        <li>write object reference positions</li>
+        <li>write trailer</li>
+        </ul>
+        
+        @param root reference to the object to be written
+        """
+        output = self.header
+        wrapped_root = self.wrapRoot(root)
+        should_reference_root = True#not isinstance(wrapped_root, HashableWrapper)
+        self.computeOffsets(wrapped_root, asReference=should_reference_root, isRoot=True)
+        self.trailer = self.trailer._replace(
+            **{'objectRefSize':self.intSize(len(self.computedUniques))})
+        (_, output) = self.writeObjectReference(wrapped_root, output)
+        output = self.writeObject(wrapped_root, output, setReferencePosition=True)
+        
+        # output size at this point is an upper bound on how big the
+        # object reference offsets need to be.
+        self.trailer = self.trailer._replace(**{
+            'offsetSize':self.intSize(len(output)),
+            'offsetCount':len(self.computedUniques),
+            'offsetTableOffset':len(output),
+            'topLevelObjectNumber':0
+            })
+        
+        output = self.writeOffsetTable(output)
+        output += pack('!xxxxxxBBQQQ', *self.trailer)
+        self.file.write(output)
+    
+    def wrapRoot(self, root):
+        """
+        Private method to generate object wrappers.
+        
+        @param root object to be wrapped
+        @return wrapped object
+        """
+        if isinstance(root, bool):
+            if root is True:
+                return self.wrappedTrue
+            else:
+                return self.wrappedFalse
+        elif isinstance(root, set):
+            n = set()
+            for value in root:
+                n.add(self.wrapRoot(value))
+            return HashableWrapper(n)
+        elif isinstance(root, dict):
+            n = {}
+            for key, value in root.items():
+                n[self.wrapRoot(key)] = self.wrapRoot(value)
+            return HashableWrapper(n)
+        elif isinstance(root, list):
+            n = []
+            for value in root:
+                n.append(self.wrapRoot(value))
+            return HashableWrapper(n)
+        elif isinstance(root, tuple):
+            n = tuple([self.wrapRoot(value) for value in root])
+            return HashableWrapper(n)
+        else:
+            return root
+
+    def incrementByteCount(self, field, incr=1):
+        self.byteCounts = self.byteCounts._replace(
+            **{field:self.byteCounts.__getattribute__(field) + incr})
+
+    def computeOffsets(self, obj, asReference=False, isRoot=False):
+        def check_key(key):
+            if key is None:
+                raise InvalidPlistException('Dictionary keys cannot be null in plists.')
+            elif isinstance(key, Data):
+                raise InvalidPlistException('Data cannot be dictionary keys in plists.')
+            elif not isinstance(key, str):
+                raise InvalidPlistException('Keys must be strings.')
+        
+        def proc_size(size):
+            if size > 0b1110:
+                size += self.intSize(size)
+            return size
+        # If this should be a reference, then we keep a record of it in the
+        # uniques table.
+        if asReference:
+            if obj in self.computedUniques:
+                return
+            else:
+                self.computedUniques.add(obj)
+        
+        if obj is None:
+            self.incrementByteCount('nullBytes')
+        elif isinstance(obj, BoolWrapper):
+            self.incrementByteCount('boolBytes')
+        elif isinstance(obj, Uid):
+            size = self.intSize(obj)
+            self.incrementByteCount('uidBytes', incr=1+size)
+        elif isinstance(obj, int):
+            size = self.intSize(obj)
+            self.incrementByteCount('intBytes', incr=1+size)
+        elif isinstance(obj, (float)):
+            size = self.realSize(obj)
+            self.incrementByteCount('realBytes', incr=1+size)
+        elif isinstance(obj, datetime.datetime):    
+            self.incrementByteCount('dateBytes', incr=2)
+        elif isinstance(obj, Data):
+            size = proc_size(len(obj))
+            self.incrementByteCount('dataBytes', incr=1+size)
+        elif isinstance(obj, str):
+            size = proc_size(len(obj))
+            self.incrementByteCount('stringBytes', incr=1+size)
+        elif isinstance(obj, HashableWrapper):
+            obj = obj.value
+            if isinstance(obj, set):
+                size = proc_size(len(obj))
+                self.incrementByteCount('setBytes', incr=1+size)
+                for value in obj:
+                    self.computeOffsets(value, asReference=True)
+            elif isinstance(obj, (list, tuple)):
+                size = proc_size(len(obj))
+                self.incrementByteCount('arrayBytes', incr=1+size)
+                for value in obj:
+                    self.computeOffsets(value, asReference=True)
+            elif isinstance(obj, dict):
+                size = proc_size(len(obj))
+                self.incrementByteCount('dictBytes', incr=1+size)
+                for key, value in obj.items():
+                    check_key(key)
+                    self.computeOffsets(key, asReference=True)
+                    self.computeOffsets(value, asReference=True)
+        else:
+            raise InvalidPlistException("Unknown object type.")
+
+    def writeObjectReference(self, obj, output):
+        """
+        Private method to write an object reference.
+        
+        Tries to write an object reference, adding it to the references
+        table. Does not write the actual object bytes or set the reference
+        position. Returns a tuple of whether the object was a new reference
+        (True if it was, False if it already was in the reference table)
+        and the new output.
+        
+        @param obj object to be written
+        @param output output stream to append the object to
+        @return flag indicating a new reference and the new output
+        """
+        position = self.positionOfObjectReference(obj)
+        if position is None:
+            self.writtenReferences[obj] = len(self.writtenReferences)
+            output += self.binaryInt(len(self.writtenReferences) - 1,
+                                      bytes=self.trailer.objectRefSize)
+            return (True, output)
+        else:
+            output += self.binaryInt(position, bytes=self.trailer.objectRefSize)
+            return (False, output)
+
+    def writeObject(self, obj, output, setReferencePosition=False):
+        """
+        Private method to serialize the given object to the output.
+        
+        @param obj object to be serialized
+        @param output output to be serialized to (bytes)
+        @param setReferencePosition flag indicating, that the reference
+            position the object was written to shall be recorded (boolean)
+        @return new output
+        """
+        def proc_variable_length(format, length):
+            result = ''
+            if length > 0b1110:
+                result += pack('!B', (format << 4) | 0b1111)
+                result = self.writeObject(length, result)
+            else:
+                result += pack('!B', (format << 4) | length)
+            return result
+        
+        if setReferencePosition:
+            self.referencePositions[obj] = len(output)
+        
+        if obj is None:
+            output += pack('!B', 0b00000000)
+        elif isinstance(obj, BoolWrapper):
+            if obj.value is False:
+                output += pack('!B', 0b00001000)
+            else:
+                output += pack('!B', 0b00001001)
+        elif isinstance(obj, Uid):
+            size = self.intSize(obj)
+            output += pack('!B', (0b1000 << 4) | size - 1)
+            output += self.binaryInt(obj)
+        elif isinstance(obj, int):
+            bytes = self.intSize(obj)
+            root = math.log(bytes, 2)
+            output += pack('!B', (0b0001 << 4) | int(root))
+            output += self.binaryInt(obj)
+        elif isinstance(obj, float):
+            # just use doubles
+            output += pack('!B', (0b0010 << 4) | 3)
+            output += self.binaryReal(obj)
+        elif isinstance(obj, datetime.datetime):
+            timestamp = calendar.timegm(obj.utctimetuple())
+            timestamp -= apple_reference_date_offset
+            output += pack('!B', 0b00110011)
+            output += pack('!d', float(timestamp))
+        elif isinstance(obj, Data):
+            output += proc_variable_length(0b0100, len(obj))
+            output += obj
+        elif isinstance(obj, str):
+            # Python 3 uses unicode strings only
+            bytes = obj.encode('utf_16_be')
+            output += proc_variable_length(0b0110, len(bytes)/2)
+            output += bytes
+        elif isinstance(obj, HashableWrapper):
+            obj = obj.value
+            if isinstance(obj, (set, list, tuple)):
+                if isinstance(obj, set):
+                    output += proc_variable_length(0b1100, len(obj))
+                else:
+                    output += proc_variable_length(0b1010, len(obj))
+            
+                objectsToWrite = []
+                for objRef in obj:
+                    (isNew, output) = self.writeObjectReference(objRef, output)
+                    if isNew:
+                        objectsToWrite.append(objRef)
+                for objRef in objectsToWrite:
+                    output = self.writeObject(objRef, output, setReferencePosition=True)
+            elif isinstance(obj, dict):
+                output += proc_variable_length(0b1101, len(obj))
+                keys = []
+                values = []
+                objectsToWrite = []
+                for key, value in obj.items():
+                    keys.append(key)
+                    values.append(value)
+                for key in keys:
+                    (isNew, output) = self.writeObjectReference(key, output)
+                    if isNew:
+                        objectsToWrite.append(key)
+                for value in values:
+                    (isNew, output) = self.writeObjectReference(value, output)
+                    if isNew:
+                        objectsToWrite.append(value)
+                for objRef in objectsToWrite:
+                    output = self.writeObject(objRef, output, setReferencePosition=True)
+        return output
+    
+    def writeOffsetTable(self, output):
+        """
+        Private method to write all of the object reference offsets.
+        
+        @param output current output (bytes)
+        @return new output (bytes)
+        """
+        all_positions = []
+        writtenReferences = list(self.writtenReferences.items())
+        writtenReferences.sort(key=lambda x: x[1])
+        for obj,order in writtenReferences:
+            position = self.referencePositions.get(obj)
+            if position is None:
+                raise InvalidPlistException(
+                    "Error while writing offsets table. Object not found. {0}"
+                    .format(obj))
+            output += self.binaryInt(position, self.trailer.offsetSize)
+            all_positions.append(position)
+        return output
+    
+    def binaryReal(self, obj):
+        """
+        Private method to pack a real object.
+        
+        @param obj real to be packed
+        @return serialized object (bytes)
+        """
+        # just use doubles
+        result = pack('>d', obj)
+        return result
+    
+    def binaryInt(self, obj, bytes=None):
+        """
+        Private method to pack an integer object.
+        
+        @param obj integer to be packed
+        @param bytes length the integer should be packed into (integer)
+        @return serialized object (bytes)
+        """
+        result = ''
+        if bytes is None:
+            bytes = self.intSize(obj)
+        if bytes == 1:
+            result += pack('>B', obj)
+        elif bytes == 2:
+            result += pack('>H', obj)
+        elif bytes == 4:
+            result += pack('>L', obj)
+        elif bytes == 8:
+            result += pack('>q', obj)
+        else:
+            raise InvalidPlistException(
+                "Core Foundation can't handle integers with size greater than 8 bytes.")
+        return result
+    
+    def intSize(self, obj):
+        """
+        Private method to determine the number of bytes necessary to store the
+        given integer.
+        
+        @param obj integer object
+        @return number of bytes required (integer)
+        """
+        # SIGNED
+        if obj < 0: # Signed integer, always 8 bytes
+            return 8
+        # UNSIGNED
+        elif obj <= 0xFF: # 1 byte
+            return 1
+        elif obj <= 0xFFFF: # 2 bytes
+            return 2
+        elif obj <= 0xFFFFFFFF: # 4 bytes
+            return 4
+        # SIGNED
+        # 0x7FFFFFFFFFFFFFFF is the max.
+        elif obj <= 0x7FFFFFFFFFFFFFFF: # 8 bytes
+            return 8
+        else:
+            raise InvalidPlistException(
+                "Core Foundation can't handle integers with size greater than 8 bytes.")
+    
+    def realSize(self, obj):
+        """
+        Private method to determine the number of bytes necessary to store the
+        given real.
+        
+        @param obj real object
+        @return number of bytes required (integer)
+        """
+        return 8
--- a/eric5.e4p	Mon Mar 19 19:24:12 2012 +0100
+++ b/eric5.e4p	Mon Mar 19 20:14:07 2012 +0100
@@ -995,6 +995,8 @@
     <Source>Helpviewer/Bookmarks/BookmarksImporters/OperaImporter.py</Source>
     <Source>Helpviewer/Bookmarks/BookmarksImporters/FirefoxImporter.py</Source>
     <Source>Helpviewer/Bookmarks/BookmarksImporters/IExplorerImporter.py</Source>
+    <Source>Utilities/binplistlib.py</Source>
+    <Source>Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py</Source>
   </Sources>
   <Forms>
     <Form>PyUnit/UnittestDialog.ui</Form>
--- a/i18n/eric5_cs.ts	Mon Mar 19 19:24:12 2012 +0100
+++ b/i18n/eric5_cs.ts	Mon Mar 19 20:14:07 2012 +0100
@@ -1597,12 +1597,12 @@
 <context>
     <name>BookmarksImporters</name>
     <message>
-        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="38"/>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="40"/>
         <source>XBEL File</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="42"/>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="44"/>
         <source>HTML File</source>
         <translation type="unfinished"></translation>
     </message>
@@ -35428,6 +35428,40 @@
     </message>
 </context>
 <context>
+    <name>SafariImporter</name>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="40"/>
+        <source>Apple Safari stores its bookmarks in the &lt;b&gt;Bookmarks.plist&lt;/b&gt; file. This file is usually located in</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="40"/>
+        <source>Please choose the file to begin importing bookmarks.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="86"/>
+        <source>File &apos;{0}&apos; does not exist.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="101"/>
+        <source>Bookmarks file cannot be read.
+Reason: {0}</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="111"/>
+        <source>Apple Safari Import</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="113"/>
+        <source>Imported {0}</source>
+        <translation type="unfinished">Importováno {0}</translation>
+    </message>
+</context>
+<context>
     <name>SearchReplaceWidget</name>
     <message>
         <location filename="QScintilla/SearchReplaceWidget.py" line="511"/>
Binary file i18n/eric5_de.qm has changed
--- a/i18n/eric5_de.ts	Mon Mar 19 19:24:12 2012 +0100
+++ b/i18n/eric5_de.ts	Mon Mar 19 20:14:07 2012 +0100
@@ -1586,12 +1586,12 @@
 <context>
     <name>BookmarksImporters</name>
     <message>
-        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="38"/>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="40"/>
         <source>XBEL File</source>
         <translation>XBEL Datei</translation>
     </message>
     <message>
-        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="42"/>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="44"/>
         <source>HTML File</source>
         <translation>HTML Datei</translation>
     </message>
@@ -34478,6 +34478,41 @@
     </message>
 </context>
 <context>
+    <name>SafariImporter</name>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="40"/>
+        <source>Apple Safari stores its bookmarks in the &lt;b&gt;Bookmarks.plist&lt;/b&gt; file. This file is usually located in</source>
+        <translation>Apple Safari speichert die Lesezeichen in der Datei &lt;b&gt;Bookmarks.plist&lt;/b&gt;. Diese Datei befindet sich gewöhnlich in</translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="40"/>
+        <source>Please choose the file to begin importing bookmarks.</source>
+        <translation>Bitte wähle die Datei, um den Import von Lesezeichen zu starten.</translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="86"/>
+        <source>File &apos;{0}&apos; does not exist.</source>
+        <translation>Datei &apos;{0}&apos; existiert nicht.</translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="101"/>
+        <source>Bookmarks file cannot be read.
+Reason: {0}</source>
+        <translation>Lesezeichendatei &apos;{0}&apos; kann nicht gelesen werden.
+Ursache: {1}</translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="111"/>
+        <source>Apple Safari Import</source>
+        <translation>Apple Safari Import</translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="113"/>
+        <source>Imported {0}</source>
+        <translation>Importiert {0}</translation>
+    </message>
+</context>
+<context>
     <name>SearchReplaceWidget</name>
     <message>
         <location filename="QScintilla/SearchReplaceWidget.py" line="511"/>
--- a/i18n/eric5_en.ts	Mon Mar 19 19:24:12 2012 +0100
+++ b/i18n/eric5_en.ts	Mon Mar 19 20:14:07 2012 +0100
@@ -1559,12 +1559,12 @@
 <context>
     <name>BookmarksImporters</name>
     <message>
-        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="38"/>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="40"/>
         <source>XBEL File</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="42"/>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="44"/>
         <source>HTML File</source>
         <translation type="unfinished"></translation>
     </message>
@@ -34196,6 +34196,40 @@
     </message>
 </context>
 <context>
+    <name>SafariImporter</name>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="40"/>
+        <source>Apple Safari stores its bookmarks in the &lt;b&gt;Bookmarks.plist&lt;/b&gt; file. This file is usually located in</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="40"/>
+        <source>Please choose the file to begin importing bookmarks.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="86"/>
+        <source>File &apos;{0}&apos; does not exist.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="101"/>
+        <source>Bookmarks file cannot be read.
+Reason: {0}</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="111"/>
+        <source>Apple Safari Import</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="113"/>
+        <source>Imported {0}</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
     <name>SearchReplaceWidget</name>
     <message>
         <location filename="QScintilla/SearchReplaceWidget.py" line="125"/>
--- a/i18n/eric5_es.ts	Mon Mar 19 19:24:12 2012 +0100
+++ b/i18n/eric5_es.ts	Mon Mar 19 20:14:07 2012 +0100
@@ -1595,12 +1595,12 @@
 <context>
     <name>BookmarksImporters</name>
     <message>
-        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="38"/>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="40"/>
         <source>XBEL File</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="42"/>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="44"/>
         <source>HTML File</source>
         <translation type="unfinished"></translation>
     </message>
@@ -35047,6 +35047,40 @@
     </message>
 </context>
 <context>
+    <name>SafariImporter</name>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="40"/>
+        <source>Apple Safari stores its bookmarks in the &lt;b&gt;Bookmarks.plist&lt;/b&gt; file. This file is usually located in</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="40"/>
+        <source>Please choose the file to begin importing bookmarks.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="86"/>
+        <source>File &apos;{0}&apos; does not exist.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="101"/>
+        <source>Bookmarks file cannot be read.
+Reason: {0}</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="111"/>
+        <source>Apple Safari Import</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="113"/>
+        <source>Imported {0}</source>
+        <translation type="unfinished">Importado {0}</translation>
+    </message>
+</context>
+<context>
     <name>SearchReplaceWidget</name>
     <message>
         <location filename="QScintilla/SearchReplaceWidget.py" line="511"/>
--- a/i18n/eric5_fr.ts	Mon Mar 19 19:24:12 2012 +0100
+++ b/i18n/eric5_fr.ts	Mon Mar 19 20:14:07 2012 +0100
@@ -1778,12 +1778,12 @@
 <context>
     <name>BookmarksImporters</name>
     <message>
-        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="38"/>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="40"/>
         <source>XBEL File</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="42"/>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="44"/>
         <source>HTML File</source>
         <translation type="unfinished"></translation>
     </message>
@@ -37730,6 +37730,40 @@
     </message>
 </context>
 <context>
+    <name>SafariImporter</name>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="40"/>
+        <source>Apple Safari stores its bookmarks in the &lt;b&gt;Bookmarks.plist&lt;/b&gt; file. This file is usually located in</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="40"/>
+        <source>Please choose the file to begin importing bookmarks.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="86"/>
+        <source>File &apos;{0}&apos; does not exist.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="101"/>
+        <source>Bookmarks file cannot be read.
+Reason: {0}</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="111"/>
+        <source>Apple Safari Import</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="113"/>
+        <source>Imported {0}</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
     <name>SearchDialog</name>
     <message>
         <location filename="Helpviewer/SearchDialog.py" line="89"/>
--- a/i18n/eric5_it.ts	Mon Mar 19 19:24:12 2012 +0100
+++ b/i18n/eric5_it.ts	Mon Mar 19 20:14:07 2012 +0100
@@ -1597,12 +1597,12 @@
 <context>
     <name>BookmarksImporters</name>
     <message>
-        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="38"/>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="40"/>
         <source>XBEL File</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="42"/>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="44"/>
         <source>HTML File</source>
         <translation type="unfinished"></translation>
     </message>
@@ -34938,6 +34938,40 @@
     </message>
 </context>
 <context>
+    <name>SafariImporter</name>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="40"/>
+        <source>Apple Safari stores its bookmarks in the &lt;b&gt;Bookmarks.plist&lt;/b&gt; file. This file is usually located in</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="40"/>
+        <source>Please choose the file to begin importing bookmarks.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="86"/>
+        <source>File &apos;{0}&apos; does not exist.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="101"/>
+        <source>Bookmarks file cannot be read.
+Reason: {0}</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="111"/>
+        <source>Apple Safari Import</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="113"/>
+        <source>Imported {0}</source>
+        <translation type="unfinished">Importato {0}</translation>
+    </message>
+</context>
+<context>
     <name>SearchReplaceWidget</name>
     <message>
         <location filename="QScintilla/SearchReplaceWidget.py" line="511"/>
--- a/i18n/eric5_ru.ts	Mon Mar 19 19:24:12 2012 +0100
+++ b/i18n/eric5_ru.ts	Mon Mar 19 20:14:07 2012 +0100
@@ -1594,12 +1594,12 @@
 <context>
     <name>BookmarksImporters</name>
     <message>
-        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="38"/>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="40"/>
         <source>XBEL File</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="42"/>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="44"/>
         <source>HTML File</source>
         <translation type="unfinished"></translation>
     </message>
@@ -35080,6 +35080,40 @@
     </message>
 </context>
 <context>
+    <name>SafariImporter</name>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="40"/>
+        <source>Apple Safari stores its bookmarks in the &lt;b&gt;Bookmarks.plist&lt;/b&gt; file. This file is usually located in</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="40"/>
+        <source>Please choose the file to begin importing bookmarks.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="86"/>
+        <source>File &apos;{0}&apos; does not exist.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="101"/>
+        <source>Bookmarks file cannot be read.
+Reason: {0}</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="111"/>
+        <source>Apple Safari Import</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="113"/>
+        <source>Imported {0}</source>
+        <translation type="unfinished">Импортировано {0}</translation>
+    </message>
+</context>
+<context>
     <name>SearchReplaceWidget</name>
     <message>
         <location filename="QScintilla/SearchReplaceWidget.py" line="511"/>
--- a/i18n/eric5_tr.ts	Mon Mar 19 19:24:12 2012 +0100
+++ b/i18n/eric5_tr.ts	Mon Mar 19 20:14:07 2012 +0100
@@ -1595,12 +1595,12 @@
 <context>
     <name>BookmarksImporters</name>
     <message>
-        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="38"/>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="40"/>
         <source>XBEL File</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="42"/>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="44"/>
         <source>HTML File</source>
         <translation type="unfinished"></translation>
     </message>
@@ -35237,6 +35237,40 @@
     </message>
 </context>
 <context>
+    <name>SafariImporter</name>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="40"/>
+        <source>Apple Safari stores its bookmarks in the &lt;b&gt;Bookmarks.plist&lt;/b&gt; file. This file is usually located in</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="40"/>
+        <source>Please choose the file to begin importing bookmarks.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="86"/>
+        <source>File &apos;{0}&apos; does not exist.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="101"/>
+        <source>Bookmarks file cannot be read.
+Reason: {0}</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="111"/>
+        <source>Apple Safari Import</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="113"/>
+        <source>Imported {0}</source>
+        <translation type="unfinished">İçe Aktarılmış {0}</translation>
+    </message>
+</context>
+<context>
     <name>SearchReplaceWidget</name>
     <message>
         <location filename="QScintilla/SearchReplaceWidget.py" line="125"/>
--- a/i18n/eric5_zh_CN.GB2312.ts	Mon Mar 19 19:24:12 2012 +0100
+++ b/i18n/eric5_zh_CN.GB2312.ts	Mon Mar 19 20:14:07 2012 +0100
@@ -1771,12 +1771,12 @@
 <context>
     <name>BookmarksImporters</name>
     <message>
-        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="38"/>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="40"/>
         <source>XBEL File</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="42"/>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/__init__.py" line="44"/>
         <source>HTML File</source>
         <translation type="unfinished"></translation>
     </message>
@@ -37698,6 +37698,40 @@
     </message>
 </context>
 <context>
+    <name>SafariImporter</name>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="40"/>
+        <source>Apple Safari stores its bookmarks in the &lt;b&gt;Bookmarks.plist&lt;/b&gt; file. This file is usually located in</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="40"/>
+        <source>Please choose the file to begin importing bookmarks.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="86"/>
+        <source>File &apos;{0}&apos; does not exist.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="101"/>
+        <source>Bookmarks file cannot be read.
+Reason: {0}</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="111"/>
+        <source>Apple Safari Import</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="Helpviewer/Bookmarks/BookmarksImporters/SafariImporter.py" line="113"/>
+        <source>Imported {0}</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
     <name>SearchDialog</name>
     <message>
         <location filename="QScintilla/Ui_SearchDialog.py" line="123"/>

eric ide

mercurial