[Libreoffice-commits] core.git: 40 commits - wizards/com

Javier Fernandez jfernandez at igalia.com
Mon Mar 25 06:23:56 PDT 2013


 wizards/com/sun/star/wizards/common/IRenderer.py             |   28 
 wizards/com/sun/star/wizards/common/SystemDialog.py          |    4 
 wizards/com/sun/star/wizards/common/UCB.py                   |  194 +++
 wizards/com/sun/star/wizards/common/XMLHelper.py             |   34 
 wizards/com/sun/star/wizards/common/XMLProvider.py           |   24 
 wizards/com/sun/star/wizards/ui/ImageList.py                 |   78 -
 wizards/com/sun/star/wizards/ui/event/ListModelBinder.py     |   27 
 wizards/com/sun/star/wizards/ui/event/Task.py                |  114 ++
 wizards/com/sun/star/wizards/ui/event/TaskEvent.py           |   42 
 wizards/com/sun/star/wizards/ui/event/TaskListener.py        |   39 
 wizards/com/sun/star/wizards/web/AbstractErrorHandler.py     |  181 +++
 wizards/com/sun/star/wizards/web/BackgroundsDialog.py        |   50 
 wizards/com/sun/star/wizards/web/CallWizard.py               |   51 
 wizards/com/sun/star/wizards/web/ErrorHandler.py             |   79 +
 wizards/com/sun/star/wizards/web/ExtensionVerifier.py        |   38 
 wizards/com/sun/star/wizards/web/FTPDialog.py                |  472 ++++++++
 wizards/com/sun/star/wizards/web/FTPDialogResources.py       |   79 +
 wizards/com/sun/star/wizards/web/IconsDialog.py              |   29 
 wizards/com/sun/star/wizards/web/ImageListDialog.py          |   17 
 wizards/com/sun/star/wizards/web/LogTaskListener.py          |   49 
 wizards/com/sun/star/wizards/web/Process.py                  |  594 +++++++++++
 wizards/com/sun/star/wizards/web/ProcessErrorHandler.py      |   61 +
 wizards/com/sun/star/wizards/web/ProcessErrors.py            |   32 
 wizards/com/sun/star/wizards/web/ProcessStatusRenderer.py    |   48 
 wizards/com/sun/star/wizards/web/StatusDialog.py             |  174 +++
 wizards/com/sun/star/wizards/web/StylePreview.py             |    7 
 wizards/com/sun/star/wizards/web/TOCPreview.py               |   65 +
 wizards/com/sun/star/wizards/web/TypeDetection.py            |   54 +
 wizards/com/sun/star/wizards/web/WWD_Events.py               |  476 ++++----
 wizards/com/sun/star/wizards/web/WWD_General.py              |   91 +
 wizards/com/sun/star/wizards/web/WWD_Startup.py              |  130 +-
 wizards/com/sun/star/wizards/web/WebWizard.py                |   42 
 wizards/com/sun/star/wizards/web/WebWizardDialog.py          |   25 
 wizards/com/sun/star/wizards/web/WebWizardDialogResources.py |   10 
 wizards/com/sun/star/wizards/web/data/CGArgument.py          |    2 
 wizards/com/sun/star/wizards/web/data/CGContent.py           |    7 
 wizards/com/sun/star/wizards/web/data/CGDesign.py            |    2 
 wizards/com/sun/star/wizards/web/data/CGDocument.py          |  104 +
 wizards/com/sun/star/wizards/web/data/CGExporter.py          |    8 
 wizards/com/sun/star/wizards/web/data/CGFilter.py            |    2 
 wizards/com/sun/star/wizards/web/data/CGGeneralInfo.py       |    3 
 wizards/com/sun/star/wizards/web/data/CGIconSet.py           |    2 
 wizards/com/sun/star/wizards/web/data/CGImage.py             |    2 
 wizards/com/sun/star/wizards/web/data/CGLayout.py            |    6 
 wizards/com/sun/star/wizards/web/data/CGPublish.py           |    8 
 wizards/com/sun/star/wizards/web/data/CGSession.py           |   30 
 wizards/com/sun/star/wizards/web/data/CGSessionName.py       |    2 
 wizards/com/sun/star/wizards/web/data/CGSettings.py          |   80 +
 wizards/com/sun/star/wizards/web/data/CGStyle.py             |    2 
 wizards/com/sun/star/wizards/web/export/AbstractExporter.py  |  106 +
 wizards/com/sun/star/wizards/web/export/CopyExporter.py      |   52 
 wizards/com/sun/star/wizards/web/export/Exporter.py          |   40 
 wizards/com/sun/star/wizards/web/export/__init__.py          |    1 
 53 files changed, 3375 insertions(+), 522 deletions(-)

New commits:
commit 7ccc1d024426260588fecce2fd5563b34c6514f5
Author: Javier Fernandez <jfernandez at igalia.com>
Date:   Tue Mar 19 18:04:02 2013 +0000

    Init: Added new file UCB.py
    
    Change-Id: I4f25ee62a1f090dd6f494108849f038656b5e9fa

diff --git a/wizards/com/sun/star/wizards/common/UCB.py b/wizards/com/sun/star/wizards/common/UCB.py
new file mode 100644
index 0000000..a7c3ff1
--- /dev/null
+++ b/wizards/com/sun/star/wizards/common/UCB.py
@@ -0,0 +1,194 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements. See the NOTICE file distributed
+#   with this work for additional information regarding copyright
+#   ownership. The ASF licenses this file to you under the Apache
+#   License, Version 2.0 (the "License"); you may not use this file
+#   except in compliance with the License. You may obtain a copy of
+#   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+
+import uno
+import traceback
+
+from abc import abstractmethod
+
+from ..common.FileAccess import FileAccess
+
+from com.sun.star.beans import Property
+
+from com.sun.star.ucb import Command
+from com.sun.star.ucb import GlobalTransferCommandArgument
+from com.sun.star.ucb.NameClash import OVERWRITE
+from com.sun.star.ucb import OpenCommandArgument2
+from com.sun.star.ucb.OpenMode import ALL
+from com.sun.star.ucb.TransferCommandOperation import COPY
+#from com.sun.star.ucb import XCommandProcessor
+#from com.sun.star.ucb import XContentAccess
+#from com.sun.star.ucb import XContentIdentifier
+from com.sun.star.ucb import XContentIdentifierFactory
+from com.sun.star.ucb import XContentProvider
+#from com.sun.star.ucb import XDynamicResultSet
+#from com.sun.star.uno import UnoRuntime
+
+
+# This class is used to copy the content of a folder to
+# another folder.
+# There is an incosistency with argument order.
+# It should be always: dir,filename.
+class UCB(object):
+
+    ucb = None
+    fa = None
+    xmsf = None
+
+    def __init__(self, xmsf):
+        self.ucb = xmsf.createInstanceWithArguments("com.sun.star.ucb.UniversalContentBroker", ())
+        self.fa = FileAccess(xmsf)
+        self.xmsf = xmsf
+
+    def deleteDirContent(self, folder):
+        if (not self.fa.exists(folder, True)):
+          return
+        l = self.listFiles(folder, None)
+        for i in range(len(l)):
+            self.delete(FileAccess.connectURLs(folder, l[i]))
+
+    def delete(self, filename):
+        # System.out.println("UCB.delete(" + filename)
+        self.executeCommand(self.getContent(filename),"delete", True)
+
+    def copy(self, sourceDir, targetDir):
+        self.copy1(sourceDir,targetDir, None)
+
+    def copy1(self, sourceDir, targetDir, verifier):
+        files = self.listFiles(sourceDir, verifier)
+        for i in range(len(files)):
+          self.copy2(sourceDir, files[i], targetDir)
+
+    def copy2(self, sourceDir, filename, targetDir, targetName):
+        #sourceDir = "file:///home/javi/intel-libreoffice/install/share/config/" + sourceDir[7:]
+        print ("WARNING !!! copy2 - sourcedir, filenName :", sourceDir, filename)
+        print ("WARNING !!! copy2 - targetDir, targetName :", targetDir, targetName)
+        if (not self.fa.exists(targetDir, True)):
+          self.fa.xInterface.createFolder(targetDir)
+        self.executeCommand(self.ucb, "globalTransfer", self.copyArg(sourceDir, filename, targetDir, targetName))
+
+    # @deprecated
+    # @param sourceDir
+    # @param filename
+    # @param targetDir
+    # @throws Exception
+    def copy3(self, sourceDir, filename, targetDir):
+        self.copy2(sourceDir, filename, targetDir, "")
+
+    # target name can be PropertyNames.EMPTY_STRING, in which case the name stays lige the source name
+    # @param sourceDir
+    # @param sourceFilename
+    # @param targetDir
+    # @param targetFilename
+    # @return
+    def copyArg(self, sourceDir, sourceFilename, targetDir, targetFilename):
+        aArg = GlobalTransferCommandArgument()
+        aArg.Operation = COPY
+        aArg.SourceURL = self.fa.getURL(sourceDir, sourceFilename)
+        aArg.TargetURL = targetDir
+        aArg.NewTitle = targetFilename
+        # fail, if object with same name exists in target folder
+        aArg.NameClash = OVERWRITE
+        return aArg
+
+    def executeCommand(self, xContent, aCommandName, aArgument):
+        aCommand  = Command()
+        aCommand.Name     = aCommandName
+        aCommand.Handle   = -1 # not available
+        aCommand.Argument = aArgument
+        return xContent.execute(aCommand, 0, None)
+
+    def listFiles(self, path, verifier):
+        xContent = self.getContent(path)
+
+        aArg = OpenCommandArgument2()
+        aArg.Mode = ALL
+        aArg.Priority = 32768
+
+        # Fill info for the properties wanted.
+        aArg.Properties = (Property(),)
+
+        aArg.Properties[0].Name = "Title"
+        aArg.Properties[0].Handle = -1
+
+        xSet = self.executeCommand(xContent, "open", aArg)
+
+        xResultSet = xSet.getStaticResultSet()
+
+        files = []
+
+        if (xResultSet.first()):
+            # obtain XContentAccess interface for child content access and XRow for properties
+            while (True):
+                # Obtain URL of child.
+                aId = xResultSet.queryContentIdentifierString()
+                # First column: Title (column numbers are 1-based!)
+                aTitle = xResultSet.getString(1)
+                if (len(aTitle) == 0 and xResultSet.wasNull()):
+                    # ignore
+                    pass
+                else:
+                    files.append(aTitle)
+                if (not xResultSet.next()):
+                    break
+                # next child
+        if (verifier is not None):
+            for i in range(len(files)):
+                if (not verifier.verify(files[i])):
+                    files.pop(i) # FIXME !!! dangerous
+        return files
+
+    def getContentProperty(self, content, propName, classType):
+        pv = []
+        pv[0] = Property()
+        pv[0].Name = propName
+        pv[0].Handle = -1
+
+        row = self.executeCommand(content, "getPropertyValues", pv)
+        if (isinstance(classType, str)):
+           return row.getString(1)
+        elif (isinstance(classType, bool)):
+            return True if (row.getBoolean(1)) else False
+        elif (isinstance(classType, int)):
+            return row.getInt(1)
+        elif (isinstance(classType, int)):
+            return row.getShort(1)
+        else:
+            return None
+
+    def getContent(self, path):
+        try:
+            print ("WARNING !!! getContent - path: ", path)
+            #if (path.startswith("/")):
+            #    s = "file://" + path
+            #elif (path.startswith("file://")):
+            #    s = path
+            #else:
+            #    s = "file:///home/javi/intel-libreoffice/install/share/config/" + path[7:]
+            #ident = self.ucb.createContentIdentifier(s)
+            ident = self.ucb.createContentIdentifier(path)
+            print ("WARNING !!! getContent - ident: ", ident.getContentIdentifier())
+            return self.ucb.queryContent(ident)
+        except Exception:
+            traceback.print_exc()
+            return None
+
+    class Verifier:
+        @abstractmethod
+        def verify(object):
+            pass
+
commit 49301ebc66f41108a35aaf3f0a028ec48caf5760
Author: Javier Fernandez <jfernandez at igalia.com>
Date:   Tue Mar 19 18:05:13 2013 +0000

    Init: Added new file XMLHelper.py
    
    Change-Id: I145965230232150e91233ed1cd9ba623c19955f0

diff --git a/wizards/com/sun/star/wizards/common/XMLHelper.py b/wizards/com/sun/star/wizards/common/XMLHelper.py
new file mode 100644
index 0000000..7ea3de3
--- /dev/null
+++ b/wizards/com/sun/star/wizards/common/XMLHelper.py
@@ -0,0 +1,34 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements. See the NOTICE file distributed
+#   with this work for additional information regarding copyright
+#   ownership. The ASF licenses this file to you under the Apache
+#   License, Version 2.0 (the "License"); you may not use this file
+#   except in compliance with the License. You may obtain a copy of
+#   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+class XMLHelper:
+
+    @classmethod
+    def addElement(self, parent, name, attNames, attValues):
+        doc = parent.ownerDocument
+        if (doc == None):
+            doc = parent
+        e = doc.createElement(name)
+        for i in range(len(attNames)):
+            if (not (attValues[i] is None or (attValues[i] == ""))):
+                e.setAttribute(attNames[i], attValues[i])
+        parent.appendChild(e)
+        return e
+
+    @classmethod
+    def addElement1(self, parent, name, attName, attValue):
+        return self.addElement(parent, name, [attName], [attValue])
commit e7eaba505520ff07a70de41def33b883723ab9c3
Author: Javier Fernandez <jfernandez at igalia.com>
Date:   Tue Mar 19 18:05:45 2013 +0000

    Init: Added new file XMLProvider.py
    
    Change-Id: Idfc71c05f80150d67bc3f27f01b4a95efe9a8b5a

diff --git a/wizards/com/sun/star/wizards/common/XMLProvider.py b/wizards/com/sun/star/wizards/common/XMLProvider.py
new file mode 100644
index 0000000..4627238
--- /dev/null
+++ b/wizards/com/sun/star/wizards/common/XMLProvider.py
@@ -0,0 +1,24 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements. See the NOTICE file distributed
+#   with this work for additional information regarding copyright
+#   ownership. The ASF licenses this file to you under the Apache
+#   License, Version 2.0 (the "License"); you may not use this file
+#   except in compliance with the License. You may obtain a copy of
+#   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+from abc import abstractmethod
+
+class XMLProvider:
+
+    @abstractmethod
+    def createDOM(parent):
+        pass
commit de2cfb15ec84b570dabb36b72cc90ded3811f584
Author: Javier Fernandez <jfernandez at igalia.com>
Date:   Tue Mar 19 18:06:29 2013 +0000

    Init: Added new file Task.py
    
    Change-Id: I968fdf4b906cf6aab0a274fe4d1292cbaf1be51e

diff --git a/wizards/com/sun/star/wizards/ui/event/Task.py b/wizards/com/sun/star/wizards/ui/event/Task.py
new file mode 100644
index 0000000..133f93b
--- /dev/null
+++ b/wizards/com/sun/star/wizards/ui/event/Task.py
@@ -0,0 +1,114 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements. See the NOTICE file distributed
+#   with this work for additional information regarding copyright
+#   ownership. The ASF licenses this file to you under the Apache
+#   License, Version 2.0 (the "License"); you may not use this file
+#   except in compliance with the License. You may obtain a copy of
+#   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+import traceback
+
+from .TaskEvent import TaskEvent
+
+class Task:
+    successfull = 0
+    failed = 0
+    maximum = 0
+    taskName = ""
+    listeners = []
+    subtaskName = ""
+
+    def __init__(self, taskName_, subtaskName_, max_):
+        self.taskName = taskName_
+        self.subtaskName = subtaskName_
+        self.maximum = max_
+
+    def start(self):
+        self.fireTaskStarted()
+
+    def fail(self):
+        self.fireTaskFailed()
+
+    def getMax(self):
+        return self.maximum
+
+    def setMax(self, max_):
+        self.maximum = max_
+        self.fireTaskStatusChanged()
+
+    def advance(self, success_):
+        if success_:
+            self.successfull += 1
+            print ("Success :", self.successfull)
+        else:
+            self.failed += 1
+            print ("Failed :", self.failed)
+        self.fireTaskStatusChanged()
+        if (self.failed + self.successfull == self.maximum):
+            self.fireTaskFinished()
+
+    def advance1(self, success_, nextSubtaskName):
+        self.advance(success_)
+        self.setSubtaskName(nextSubtaskName)
+
+    def getStatus(self):
+        return self.successfull + self.failed
+
+    def addTaskListener(self, tl):
+        self.listeners.append(tl)
+
+    def removeTaskListener(self, tl):
+        try:
+            index = self.listeners.index(tl)
+            self.listeners.pop(index)
+        except Exception:
+            traceback.print_exc()
+
+    def fireTaskStatusChanged(self):
+        te = TaskEvent(self, TaskEvent.TASK_STATUS_CHANGED)
+        for i in range(len(self.listeners)):
+            self.listeners[i].taskStatusChanged(te)
+
+    def fireTaskStarted(self):
+        te = TaskEvent(self, TaskEvent.TASK_STARTED)
+        for i in range(len(self.listeners)):
+            self.listeners[i].taskStarted(te)
+
+    def fireTaskFailed(self):
+        te = TaskEvent(self, TaskEvent.TASK_FAILED)
+        for i in range(len(self.listeners)):
+            self.listeners[i].taskFinished(te)
+
+    def fireTaskFinished(self):
+        te = TaskEvent(self, TaskEvent.TASK_FINISHED)
+        for i in range(len(self.listeners)):
+            self.listeners[i].taskFinished(te)
+
+    def fireSubtaskNameChanged(self):
+        te = TaskEvent(self, TaskEvent.SUBTASK_NAME_CHANGED)
+        for i in range(len(self.listeners)):
+            self.listeners[i].subtaskNameChanged(te)
+
+    def getSubtaskName(self):
+        return self.subtaskName
+
+    def getTaskName(self):
+        return self.taskName
+
+    def setSubtaskName(self, s):
+        self.subtaskName = s
+        self.fireSubtaskNameChanged()
+
+    def getFailed(self):
+        return self.failed
+
+    def getSuccessfull(self):
+        return self.successfull
commit c192de3a8c7ed6ee4ec78f9e938030321b9576ad
Author: Javier Fernandez <jfernandez at igalia.com>
Date:   Tue Mar 19 18:06:45 2013 +0000

    Init: Added new file TaskEvent.py
    
    Change-Id: Iadaa2e003186fc041e67270da39454cd28014a46

diff --git a/wizards/com/sun/star/wizards/ui/event/TaskEvent.py b/wizards/com/sun/star/wizards/ui/event/TaskEvent.py
new file mode 100644
index 0000000..291a1896
--- /dev/null
+++ b/wizards/com/sun/star/wizards/ui/event/TaskEvent.py
@@ -0,0 +1,42 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements. See the NOTICE file distributed
+#   with this work for additional information regarding copyright
+#   ownership. The ASF licenses this file to you under the Apache
+#   License, Version 2.0 (the "License"); you may not use this file
+#   except in compliance with the License. You may obtain a copy of
+#   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+from com.sun.star.document import EventObject
+
+#class TaskEvent(EventObject):
+class TaskEvent:
+
+    TASK_STARTED = 1
+    TASK_FINISHED = 2
+    TASK_STATUS_CHANGED = 3
+    SUBTASK_NAME_CHANGED = 4
+    TASK_FAILED = 5
+    taskType = 0
+    source = None
+
+    #general constructor-
+    # @param source
+    # @param type_
+    def __init__(self, source_, type_):
+        #super(TaskEvent, self).__init__(source)
+        self.taskType = type_
+        self.source = source_
+
+    def getTask(self):
+        return self.getSource()
+
+    def getSource(self):
+        return self.source
commit c0d9a71301225a74bc3acacb4fad65a0d712007f
Author: Javier Fernandez <jfernandez at igalia.com>
Date:   Tue Mar 19 18:07:09 2013 +0000

    Init: Added new file TaskListener.py
    
    Change-Id: I3b90d34dbe160410f63cd5cb6b40a1736a01c7cb

diff --git a/wizards/com/sun/star/wizards/ui/event/TaskListener.py b/wizards/com/sun/star/wizards/ui/event/TaskListener.py
new file mode 100644
index 0000000..9cd86e9
--- /dev/null
+++ b/wizards/com/sun/star/wizards/ui/event/TaskListener.py
@@ -0,0 +1,39 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements. See the NOTICE file distributed
+#   with this work for additional information regarding copyright
+#   ownership. The ASF licenses this file to you under the Apache
+#   License, Version 2.0 (the "License"); you may not use this file
+#   except in compliance with the License. You may obtain a copy of
+#   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+from abc import abstractmethod
+from com.sun.star.script import EventListener
+
+class TaskListener(EventListener):
+
+    @abstractmethod
+    def taskStarted(self, te):
+        pass
+
+    @abstractmethod
+    def taskFinished(self, te):
+        pass
+
+    # is called when the status of the task has advanced.
+    # @param te
+    @abstractmethod
+    def taskStatusChanged(self, te):
+        pass
+
+    @abstractmethod
+    def subtaskNameChanged(self, te):
+        pass
commit e4362e2434f6cf12eab721344753c7216e0e695e
Author: Javier Fernandez <jfernandez at igalia.com>
Date:   Tue Mar 19 18:07:34 2013 +0000

    Init: Added new file AbstractErrorHandler.py
    
    Change-Id: I8d5a304a51af734379c5597e9cdddf6ecfa6ba8a

diff --git a/wizards/com/sun/star/wizards/web/AbstractErrorHandler.py b/wizards/com/sun/star/wizards/web/AbstractErrorHandler.py
new file mode 100644
index 0000000..5f79384
--- /dev/null
+++ b/wizards/com/sun/star/wizards/web/AbstractErrorHandler.py
@@ -0,0 +1,181 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements. See the NOTICE file distributed
+#   with this work for additional information regarding copyright
+#   ownership. The ASF licenses this file to you under the Apache
+#   License, Version 2.0 (the "License"); you may not use this file
+#   except in compliance with the License. You may obtain a copy of
+#   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+from abc import abstractmethod
+
+from .ErrorHandler import ErrorHandler
+from ..common.SystemDialog import SystemDialog
+
+from com.sun.star.awt.VclWindowPeerAttribute import OK, DEF_OK, OK_CANCEL, DEF_CANCEL
+from com.sun.star.awt.VclWindowPeerAttribute import YES_NO, DEF_NO, DEF_YES
+
+#import com.sun.star.awt.VclWindowPeerAttribute
+
+
+# An abstract implementation of ErrorHandler, which
+# uses a renderer method geMessageFor(Exception, Object, int, int)
+# (in this class still abstract...)
+# to render the errors, and displays
+# error messeges.
+class AbstractErrorHandler(ErrorHandler):
+
+    xmsf = None
+    peer = None
+
+    def __init__(self, xmsf, peer_):
+        self.xmsf = xmsf
+        self.peer = peer_
+
+    # Implementation of ErrorHandler:
+    # shows a message box with the rendered error.
+    # @param arg identifies the error. This object is passed to the render method
+    # which returns the right error message.
+    # @return true/false for continue/abort.
+    def error(self, ex, arg, ix, errorType):
+        if (errorType == ErrorHandler.ERROR_FATAL):
+                return not self.showMessage(self.getMessageFor(ex, arg, ix, errorType), errorType)
+        elif (errorType == ErrorHandler.ERROR_PROCESS_FATAL):
+                return not self.showMessage(self.getMessageFor(ex, arg, ix, errorType), errorType)
+        elif (errorType == ErrorHandler.ERROR_NORMAL_ABORT):
+                return self.showMessage(self.getMessageFor(ex, arg, ix, errorType), errorType)
+        elif (errorType == ErrorHandler.ERROR_NORMAL_IGNORE):
+                return self.showMessage(self.getMessageFor(ex, arg, ix, errorType), errorType)
+        elif (errorType == ErrorHandler.ERROR_QUESTION_CANCEL):
+                return self.showMessage(self.getMessageFor(ex, arg, ix, errorType), errorType)
+        elif (errorType == ErrorHandler.ERROR_QUESTION_OK):
+                return self.showMessage(self.getMessageFor(ex, arg, ix, errorType), errorType)
+        elif (errorType == ErrorHandler.ERROR_QUESTION_NO):
+                return self.showMessage(self.getMessageFor(ex, arg, ix, errorType), errorType)
+        elif (errorType == ErrorHandler.ERROR_QUESTION_YES):
+                return self.showMessage(self.getMessageFor(ex, arg, ix, errorType), errorType)
+        elif (errorType == ErrorHandler.ERROR_WARNING):
+                return self.showMessage(self.getMessageFor(ex, arg, ix, errorType), errorType)
+        elif (errorType == ErrorHandler.ERROR_MESSAGE):
+                return self.showMessage(self.getMessageFor(ex, arg, ix, errorType), errorType)
+        raise IllegalArgumentException("unknown error type")
+
+    # @deprecated
+    # @param message
+    # @param errorType
+    # @return true if the ok/yes button is clicked, false otherwise.
+    def showMessage(self, message, errorType):
+        return self.showMessage1(self.xmsf, self.peer, message, errorType)
+
+    # display a message
+    # @deprecated
+    # @param xmsf
+    # @param message the message to display
+    # @param errorType an int constant from the ErrorHandler interface.
+    # @return
+    @classmethod
+    def showMessage1(self, xmsf, peer, message, errorType):
+        serviceName = self.getServiceNameFor(errorType)
+        attribute = self.getAttributeFor(errorType)
+        b = SystemDialog.showMessageBox(xmsf, serviceName, attribute, message, peer)
+        return b == self.getTrueFor(errorType)
+
+    @classmethod
+    def showMessage2(self, xmsf, peer, message, dialogType, buttons, defaultButton, returnTrueOn):
+        b = SystemDialog.showMessageBox(xmsf, dialogType, defaultButton + buttons, message, peer, )
+        return b == returnTrueOn
+
+
+    # normally ok(1) is the value for true.
+    # but a question dialog may use yes. so i use this method
+    # for each error type to get its type of "true" value.
+    # @param errorType
+    # @return
+    @classmethod
+    def getTrueFor(self, errorType):
+        if (errorType in (ErrorHandler.ERROR_FATAL, ErrorHandler.ERROR_PROCESS_FATAL,
+                          ErrorHandler.ERROR_NORMAL_ABORT, ErrorHandler.ERROR_NORMAL_IGNORE,
+                          ErrorHandler.ERROR_QUESTION_CANCEL, ErrorHandler.ERROR_QUESTION_OK)):
+                return 1
+        elif (errorType in (ErrorHandler.ERROR_QUESTION_NO, ErrorHandler.ERROR_QUESTION_YES)):
+                return 2
+        elif (errorType in (ErrorHandler.ERROR_WARNING, ErrorHandler.ERROR_MESSAGE)):
+                return 1
+        raise IllegalArgumentException("unkonown error type")
+
+
+    # @param errorType
+    # @return the Uno attributes for each error type.
+    @classmethod
+    def getAttributeFor(self, errorType):
+        if (errorType == ErrorHandler.ERROR_FATAL):
+                return OK
+        elif (errorType == ErrorHandler.ERROR_PROCESS_FATAL):
+                return OK
+        elif (errorType == ErrorHandler.ERROR_NORMAL_ABORT):
+                return OK_CANCEL + DEF_CANCEL
+        elif (errorType == ErrorHandler.ERROR_NORMAL_IGNORE):
+                return OK_CANCEL + DEF_OK
+        elif (errorType == ErrorHandler.ERROR_QUESTION_CANCEL):
+                return OK_CANCEL + DEF_CANCEL
+        elif (errorType == ErrorHandler.ERROR_QUESTION_OK):
+                return OK_CANCEL + DEF_OK
+        elif (errorType == ErrorHandler.ERROR_QUESTION_NO):
+                return YES_NO + DEF_NO
+        elif (errorType == ErrorHandler.ERROR_QUESTION_YES):
+                return YES_NO + DEF_YES
+        elif (errorType == ErrorHandler.ERROR_WARNING):
+                return OK
+        elif (errorType == ErrorHandler.ERROR_MESSAGE):
+                return OK
+        raise IllegalArgumentException("unkonown error type")
+
+    # @deprecated
+    # @param errorType
+    # @return the uno service name for each error type
+    @classmethod
+    def getServiceNameFor(self, errorType):
+        if (errorType == ErrorHandler.ERROR_FATAL):
+                return "errorbox"
+        elif (errorType == ErrorHandler.ERROR_PROCESS_FATAL):
+                return "errorbox"
+        elif (errorType == ErrorHandler.ERROR_NORMAL_ABORT):
+                return "errorbox"
+        elif (errorType == ErrorHandler.ERROR_NORMAL_IGNORE):
+                return "warningbox"
+        elif (errorType == ErrorHandler.ERROR_QUESTION_CANCEL):
+                return "querybox"
+        elif (errorType == ErrorHandler.ERROR_QUESTION_OK):
+                return "querybox"
+        elif (errorType == ErrorHandler.ERROR_QUESTION_NO):
+                return "querybox"
+        elif (errorType == ErrorHandler.ERROR_QUESTION_YES):
+                return "querybox"
+        elif (errorType == ErrorHandler.ERROR_WARNING):
+                return "warningbox"
+        elif (errorType == ErrorHandler.ERROR_MESSAGE):
+                return "infobox"
+        raise IllegalArgumentException("unkonown error type")
+
+    # renders the error
+    # @param ex the exception
+    # @param arg a free argument
+    # @param ix a free argument
+    # @param type the error type (from the int constants
+    # in ErrorHandler interface)
+    # @return a Strings which will be displayed in the message box,
+    # and which describes the error, and the needed action from the user.
+    @abstractmethod
+    def getMessageFor(self, ex, arg, ix, errorType):
+        pass
+
+
+
commit a2d36bc34bdc6ce5bf4f973a22b61fbc7d1d759c
Author: Javier Fernandez <jfernandez at igalia.com>
Date:   Tue Mar 19 18:07:59 2013 +0000

    Init: Added new file CallWizard.py
    
    Change-Id: Iba5ce15586bffd997c925522ee50fe71cdf59ea2

diff --git a/wizards/com/sun/star/wizards/web/CallWizard.py b/wizards/com/sun/star/wizards/web/CallWizard.py
new file mode 100644
index 0000000..1a98a31
--- /dev/null
+++ b/wizards/com/sun/star/wizards/web/CallWizard.py
@@ -0,0 +1,51 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements. See the NOTICE file distributed
+#   with this work for additional information regarding copyright
+#   ownership. The ASF licenses this file to you under the Apache
+#   License, Version 2.0 (the "License"); you may not use this file
+#   except in compliance with the License. You may obtain a copy of
+#   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+import unohelper
+import traceback
+
+from .WebWizard import WebWizard
+
+from com.sun.star.task import XJobExecutor
+
+# implement a UNO component by deriving from the standard unohelper.Base class
+# and from the interface(s) you want to implement.
+class CallWizard(unohelper.Base, XJobExecutor):
+    def __init__(self, ctx):
+        # store the component context for later use
+        self.ctx = ctx
+
+    def trigger(self, args):
+        try:
+            ww = WebWizard(self.ctx.ServiceManager)
+            ww.show()
+            ww.cleanup()
+        except Exception as e:
+            print ("Wizard failure exception " + str(type(e)) +
+                   " message " + str(e) + " args " + str(e.args) +
+                   traceback.format_exc())
+
+# pythonloader looks for a static g_ImplementationHelper variable
+g_ImplementationHelper = unohelper.ImplementationHelper()
+
+g_ImplementationHelper.addImplementation( \
+    CallWizard,                               # UNO object class
+    "com.sun.star.wizards.web.CallWizard",    # implemenation name
+    ("com.sun.star.task.Job",),)              # list of implemented services
+                                              # (the only service)
+
+# vim:set shiftwidth=4 softtabstop=4 expandtab:
commit c6d6410628db33c33627381d25563e9ddfaadfa8
Author: Javier Fernandez <jfernandez at igalia.com>
Date:   Tue Mar 19 18:08:15 2013 +0000

    Init: Added new file ErrorHandler.py
    
    Change-Id: Id4118c5f2e13e38d5c6803e8e07ef250cdcb2d7f

diff --git a/wizards/com/sun/star/wizards/web/ErrorHandler.py b/wizards/com/sun/star/wizards/web/ErrorHandler.py
new file mode 100644
index 0000000..093e498
--- /dev/null
+++ b/wizards/com/sun/star/wizards/web/ErrorHandler.py
@@ -0,0 +1,79 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements. See the NOTICE file distributed
+#   with this work for additional information regarding copyright
+#   ownership. The ASF licenses this file to you under the Apache
+#   License, Version 2.0 (the "License"); you may not use this file
+#   except in compliance with the License. You may obtain a copy of
+#   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+
+from com.sun.star.awt.VclWindowPeerAttribute import OK, DEF_OK, OK_CANCEL, DEF_CANCEL
+from com.sun.star.awt.VclWindowPeerAttribute import YES_NO, DEF_NO, DEF_YES
+
+class ErrorHandler:
+
+    MESSAGE_INFO = "infobox"
+    MESSAGE_QUESTION = "querybox"
+    MESSAGE_ERROR = "errorbox"
+    MESSAGE_WARNING = "warningbox"
+    BUTTONS_OK = OK
+    BUTTONS_OK_CANCEL = OK_CANCEL
+    BUTTONS_YES_NO = YES_NO
+    RESULT_CANCEL = 0
+    RESULT_OK = 1
+    RESULT_YES = 2
+    DEF_OK = DEF_OK
+    DEF_NO = DEF_NO
+    DEF_CANCEL = DEF_CANCEL
+
+    #Error type for fatal errors which should abort application
+    # execution. Should actually never be used :-)
+    ERROR_FATAL = 0
+    # An Error type for errors which should stop the current process.
+    ERROR_PROCESS_FATAL = 1
+    # An Error type for errors to which the user can choose, whether
+    # to continue or to abort the current process.
+    # default is abort.
+    ERROR_NORMAL_ABORT = 2
+    # An Error type for errors to which the user can choose, whether
+    # to continue or to abort the current process.
+    # default is continue.
+    ERROR_NORMAL_IGNORE = 3
+    # An error type for warnings which requires user interaction.
+    # (a question :-) )
+    # Default is abort (cancel).
+    ERROR_QUESTION_CANCEL = 4
+    # An error type for warnings which requires user interaction
+    # (a question :-) )
+    # Default is to continue (ok).
+    ERROR_QUESTION_OK = 5
+    # An error type for warnings which requires user interaction.
+    # (a question :-) )
+    # Default is abort (No).
+    ERROR_QUESTION_NO = 6
+    # An error type for warnings which requires user interaction
+    # (a question :-) )
+    # Default is to continue (Yes).
+    ERROR_QUESTION_YES = 7
+    # An error type which is just a warning...
+    ERROR_WARNING = 8
+    # An error type which just tells the user something
+    # ( like "you look tired! you should take a bath! and so on)
+    ERROR_MESSAGE = 9
+
+    # @param ex the exception that accured
+    # @param arg an object as help for recognizing the exception
+    # @param ix an integer which helps for detailed recognizing of the exception
+    # @param errorType one of the int constants defined by this Interface
+    # @return true if the execution should continue, false if it should stop.
+    def error(self, ex, arg, ix, errorType):
+        pass
+
commit 806e23dee4536915047e96365ebe5f6a2add5d2a
Author: Javier Fernandez <jfernandez at igalia.com>
Date:   Tue Mar 19 18:08:37 2013 +0000

    Init: Added new file ExtensionVerifier.py
    
    Change-Id: Ie6f413317d192643c0a30da760965fdb02125abd

diff --git a/wizards/com/sun/star/wizards/web/ExtensionVerifier.py b/wizards/com/sun/star/wizards/web/ExtensionVerifier.py
new file mode 100644
index 0000000..6f5fee0
--- /dev/null
+++ b/wizards/com/sun/star/wizards/web/ExtensionVerifier.py
@@ -0,0 +1,38 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements. See the NOTICE file distributed
+#   with this work for additional information regarding copyright
+#   ownership. The ASF licenses this file to you under the Apache
+#   License, Version 2.0 (the "License"); you may not use this file
+#   except in compliance with the License. You may obtain a copy of
+#   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+
+from ..common.UCB import UCB
+
+# Verifies all String that do not end with
+# the given extension.
+# This is used to exclude from a copy all the
+# xsl files, so I copy from a layout directory
+# all the files that do *not* end with xsl.
+class ExtensionVerifier(UCB.Verifier):
+
+    extension = ""
+
+    def __init__(self, extension_):
+        self.extension = "." + extension_
+
+    # @return true if the given object is
+    # a String which does not end with the
+    # given extension.
+    def verify(self, obj):
+        if (isinstance(obj, str())):
+            return not obj.endsWith(extension)
+        return False
commit 23c44b5745da8f0c63492e2246ffa41a439e3869
Author: Javier Fernandez <jfernandez at igalia.com>
Date:   Tue Mar 19 18:08:55 2013 +0000

    Init: Added new file FTPDialog.py
    
    Change-Id: Ia5ac3202e602fa5154510c7249847713cc76692e

diff --git a/wizards/com/sun/star/wizards/web/FTPDialog.py b/wizards/com/sun/star/wizards/web/FTPDialog.py
new file mode 100644
index 0000000..6cd34ae
--- /dev/null
+++ b/wizards/com/sun/star/wizards/web/FTPDialog.py
@@ -0,0 +1,472 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements. See the NOTICE file distributed
+#   with this work for additional information regarding copyright
+#   ownership. The ASF licenses this file to you under the Apache
+#   License, Version 2.0 (the "License"); you may not use this file
+#   except in compliance with the License. You may obtain a copy of
+#   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+import traceback
+import uno
+
+from .WWHID import *
+from .FTPDialogResources import FTPDialogResources
+from ..ui.UnoDialog2 import UnoDialog2
+from ..ui.UIConsts import UIConsts
+from ..ui.event.DataAware import DataAware
+from ..ui.event.UnoDataAware import UnoDataAware
+from ..common.PropertyNames import PropertyNames
+from ..common.SystemDialog import SystemDialog
+from ..common.FileAccess import FileAccess
+from ..common.HelpIds import HelpIds
+from ..common.UCB import UCB
+from .data.CGPublish import CGPublish
+from .data.CGSettings import CGSettings
+
+#from com.sun.star.ucb import AuthenticationRequest
+#from com.sun.star.ucb import InteractiveAugmentedIOException
+#from com.sun.star.ucb import InteractiveNetworkConnectException
+#from com.sun.star.ucb import InteractiveNetworkResolveNameException
+#from com.sun.star.ucb import OpenCommandArgument2
+#from com.sun.star.ucb import OpenMode
+
+PushButtonType_OK_value = uno.getConstantByName( "com.sun.star.awt.PushButtonType.OK" )
+PushButtonType_CANCEL_value = uno.getConstantByName( "com.sun.star.awt.PushButtonType.CANCEL" )
+PushButtonType_HELP_value = uno.getConstantByName( "com.sun.star.awt.PushButtonType.HELP" )
+
+
+# This is the FTP Dialog. <br/>
+# The Dialog enables the user:
+# (*) entering FTP server and user information.
+# (*) testing the connection.
+# (*) choosing a directory on the server.
+# If a connection was established successfully, the user may
+# press OK, which will change
+# the CGPublish object propertiers according the user's input.
+# If no connection was established. the OK and Choose-Dir button are disabled.
+# See the method "disconnect()" which disables them.
+#
+# I use here the DataAware concept to automatically update
+# the members ip, username, and password (via the methods setXXX(...))
+# for details see the ui.events.DataAware classes. <br/>
+class FTPDialog(UnoDialog2, UIConsts):
+
+    # A Constant used for the setLabel(int) method to change the
+    # status-display. "unknown" is the status when the user first
+    # opens the dialog, or changes the servername/username/password.
+    STATUS_UNKONWN = 0
+    # A Constant used for the setLabel(int) method to change the
+    # status-display. (connection established)
+    STATUS_OK = 1
+    # A Constant used for the setLabel(int) method to change the
+    # status-display.
+    STATUS_USER_PWD_WRONG = 2
+    # A Constant used for the setLabel(int) method to change the
+    # status-display.
+    STATUS_SERVER_NOT_FOUND = 3
+    # A Constant used for the setLabel(int) method to change the
+    # status-display.
+    STATUS_NO_RIGHTS = 4
+    # A Constant used for the setLabel(int) method to change the
+    # status-display.
+    STATUS_HOST_UNREACHABLE = 5
+    # A Constant used for the setLabel(int) method to change the
+    # status-display.
+    STATUS_CONNECTING = 6
+    # The icon url for error
+    ICON_ERROR = "ftperror.gif"
+    # The icon url for ok (connection ok)
+    ICON_OK = "ftpconnected.gif"
+    # The icon url for unknown - this is the status when
+    # the user first opens the dialog
+    ICON_UNKNOWN = "ftpunknown.gif"
+    # The icon url for an icon representing the "connecting" state.
+    ICON_CONNECTING = "ftpconnecting.gif"    # GUI Components as Class members.
+    # Fixed Line
+    ln1 = None
+    lblFTPAddress = None
+    txtHost = None
+    lblUsername = None
+    txtUsername = None
+    lblPassword = None
+    txtPassword = None
+    # Fixed Line
+    ln2 = None
+    btnTestConnection = None
+    imgStatus = None
+    lblStatus = None
+    # Fixed Line
+    ln3 = None
+    txtDir = None
+    btnDir = None
+    btnOK = None
+    btnCancel = None
+    btnHelp = None
+    # Font Descriptors as Class members.
+
+    # Resources Object
+    resources = None
+    dataAware = []
+    username = ""
+    password = ""
+
+    #The ftp host name
+    host = ""
+    #The ftp directory.
+    folder = ""
+    #the ftp publish object which contains the
+    #data for this dialog.
+    publish = None
+    ucb = None
+    #used for the status images url.
+    imagesDirectory = ""
+
+    # constructor.
+    # constructs the UI.
+    # @param xmsf
+    # @param p the publishert object that contains the data
+    # for this dialog
+    # @throws Exception
+    def __init__(self, xmsf, p):
+        super(FTPDialog, self).__init__(xmsf)
+        self.publish = p
+
+        #templateDir = p.root.soTemplateDir
+        templateDir = ""
+        self.imagesDirectory = FileAccess.connectURLs(templateDir, "../wizard/bitmap/")
+
+        # Load Resources
+        self.resources = FTPDialogResources(xmsf)
+        self.ucb = UCB(xmsf)
+
+        # set dialog properties...
+        uno.invoke(self.xDialogModel, "setPropertyValues",
+                (("Closeable",
+                 PropertyNames.PROPERTY_HEIGHT,
+                 PropertyNames.PROPERTY_HELPURL, "Moveable",
+                 PropertyNames.PROPERTY_NAME,
+                 PropertyNames.PROPERTY_POSITION_X,
+                 PropertyNames.PROPERTY_POSITION_Y,
+                 "Title",
+                 PropertyNames.PROPERTY_WIDTH),
+                (True,
+                 160,
+                 HelpIds.getHelpIdString(HID_FTP),
+                 True,
+                 "FTPDialog",
+                 167,
+                 82,
+                 self.resources.resFTPDialog_title,
+                 222)))
+
+        # add controls to dialog
+        self.build()
+        #make the hostname, username and password textfield data-aware.
+        self.configure()
+        #make sure we display a disconnected status.
+        self.disconnect()
+
+
+    # Add controls to dialog.
+    def build(self):
+        PROPNAMES_LABEL = (PropertyNames.PROPERTY_HEIGHT, PropertyNames.PROPERTY_LABEL, PropertyNames.PROPERTY_NAME, PropertyNames.PROPERTY_POSITION_X, PropertyNames.PROPERTY_POSITION_Y, PropertyNames.PROPERTY_TABINDEX, PropertyNames.PROPERTY_WIDTH)
+        PROPNAMES_BUTTON = (PropertyNames.PROPERTY_HEIGHT, PropertyNames.PROPERTY_HELPURL, PropertyNames.PROPERTY_LABEL, PropertyNames.PROPERTY_NAME, PropertyNames.PROPERTY_POSITION_X, PropertyNames.PROPERTY_POSITION_Y, PropertyNames.PROPERTY_TABINDEX, PropertyNames.PROPERTY_WIDTH)
+        PROPNAMES_BUTTON2 = (PropertyNames.PROPERTY_HEIGHT, PropertyNames.PROPERTY_HELPURL, PropertyNames.PROPERTY_LABEL, PropertyNames.PROPERTY_NAME, PropertyNames.PROPERTY_POSITION_X, PropertyNames.PROPERTY_POSITION_Y, "PushButtonType", PropertyNames.PROPERTY_TABINDEX, PropertyNames.PROPERTY_WIDTH)
+
+        ln1 = self.insertFixedLine("ln1",
+                PROPNAMES_LABEL,
+                (8, self.resources.resln1_value, "ln1", 6, 6, 0, 210))
+        lblFTPAddress = self.insertLabel("lblFTPAddress",
+                PROPNAMES_LABEL,
+                (8, self.resources.reslblFTPAddress_value, "lblFTPAddress", 12, 20, 1, 95))
+        self.txtHost = self.insertTextField("txtHost", "disconnect",
+                (PropertyNames.PROPERTY_HEIGHT, PropertyNames.PROPERTY_HELPURL, PropertyNames.PROPERTY_NAME, PropertyNames.PROPERTY_POSITION_X, PropertyNames.PROPERTY_POSITION_Y, PropertyNames.PROPERTY_TABINDEX, PropertyNames.PROPERTY_WIDTH),
+                (12, HelpIds.getHelpIdString(HID_FTP_SERVER), "txtIP", 110, 18, 2, 106), self)
+        self.lblUsername = self.insertLabel("lblUsername",
+                PROPNAMES_LABEL,
+                (8, self.resources.reslblUsername_value, "lblUsername", 12, 36, 3, 85))
+        self.txtUsername = self.insertTextField("txtUsername", "disconnect",
+                (PropertyNames.PROPERTY_HEIGHT, PropertyNames.PROPERTY_HELPURL, PropertyNames.PROPERTY_NAME, PropertyNames.PROPERTY_POSITION_X, PropertyNames.PROPERTY_POSITION_Y, PropertyNames.PROPERTY_TABINDEX, PropertyNames.PROPERTY_WIDTH),
+                (12, HelpIds.getHelpIdString(HID_FTP_USERNAME), "txtUsername", 110, 34, 4, 106), self)
+        self.lblPassword = self.insertLabel("lblPassword",
+                PROPNAMES_LABEL,
+                (8, self.resources.reslblPassword_value, "lblPassword", 12, 52, 5, 85))
+        self.txtPassword = self.insertTextField("txtPassword", "disconnect",
+                ("EchoChar", PropertyNames.PROPERTY_HEIGHT, PropertyNames.PROPERTY_HELPURL, PropertyNames.PROPERTY_NAME, PropertyNames.PROPERTY_POSITION_X, PropertyNames.PROPERTY_POSITION_Y, PropertyNames.PROPERTY_TABINDEX, PropertyNames.PROPERTY_WIDTH),
+                (42, 12, HelpIds.getHelpIdString(HID_FTP_PASS), "txtPassword", 110, 50, 6, 106), self)
+        self.ln2 = self.insertFixedLine("ln2",
+                PROPNAMES_LABEL,
+                (8, self.resources.resln2_value, "ln2", 6, 68, 7, 210))
+        self.btnTestConnection = self.insertButton("btnConnect", "connect",
+                PROPNAMES_BUTTON,
+                (14, HelpIds.getHelpIdString(HID_FTP_TEST), self.resources.resbtnConnect_value, "btnConnect", 12, 80, 8, 50), self)
+        self.imgStatus = self.insertImage("imgStatus",
+                ("Border", PropertyNames.PROPERTY_HEIGHT, PropertyNames.PROPERTY_POSITION_X, PropertyNames.PROPERTY_POSITION_Y, "ScaleImage", "Tabstop", PropertyNames.PROPERTY_WIDTH),
+                (0, 14, 68, 80, False, False, 14))
+        self.lblStatus = self.insertLabel("lblStatus",
+                PROPNAMES_LABEL,
+                (8, self.resources.resFTPDisconnected, "lblStatus", 86, 82, 9, 99))
+        self.ln3 = self.insertFixedLine("ln3",
+                PROPNAMES_LABEL,
+                (8, self.resources.resln3_value, "ln3", 6, 100, 10, 210))
+        self.txtDir = self.insertTextField("txtDir", None,
+                (PropertyNames.PROPERTY_ENABLED, PropertyNames.PROPERTY_HEIGHT, PropertyNames.PROPERTY_HELPURL, PropertyNames.PROPERTY_NAME, PropertyNames.PROPERTY_POSITION_X, PropertyNames.PROPERTY_POSITION_Y, PropertyNames.PROPERTY_TABINDEX, "Text", PropertyNames.PROPERTY_WIDTH),
+                (False, 12, HelpIds.getHelpIdString(HID_FTP_TXT_PATH), "txtDir", 12, 113, 11, self.resources.restxtDir_value, 184), self)
+        self.btnDir = self.insertButton("btnDir", "chooseDirectory",
+                PROPNAMES_BUTTON,
+                (14, HelpIds.getHelpIdString(HID_FTP_BTN_PATH), self.resources.resbtnDir_value, "btnDir", 199, 112, 12, 16), self)
+        self.btnOK = self.insertButton("btnOK", None,
+                PROPNAMES_BUTTON2,
+                (14, HelpIds.getHelpIdString(HID_FTP_OK), self.resources.resbtnOK_value, "btnOK", 165, 142, PushButtonType_OK_value, 13, 50), self)
+        self.btnCancel = self.insertButton("btnCancel",
+                None, PROPNAMES_BUTTON2,
+                (14, HelpIds.getHelpIdString(HID_FTP_CANCEL), self.resources.resbtnCancel_value, "btnCancel", 113, 142, PushButtonType_CANCEL_value, 14, 50), self)
+        self.btnHelp = self.insertButton("btnHelp", None,
+                PROPNAMES_BUTTON2,
+                (14, "", self.resources.resbtnHelp_value, "btnHelp", 57, 142, PushButtonType_HELP_value, 15, 50), self)
+
+
+    # Make hostname, username and password text fields data aware.
+    def configure(self):
+        self.dataAware.append(UnoDataAware.attachEditControl(self, "host", self.txtHost, True))
+        self.dataAware.append(UnoDataAware.attachEditControl(self, "username", self.txtUsername, True))
+        self.dataAware.append(UnoDataAware.attachEditControl(self, "password", self.txtPassword, True))
+
+    # Shows the dialog.
+    # If the user clicks ok, changes the given CGPublish properties to the
+    # user input.
+    # @param parent a dialog to center this dialog to.
+    # @return 0 for cancel, 1 for ok.
+    # @throws Exception - well, if something goes wrong...
+    def execute(self, parent):
+        self.host = self.extractHost(self.publish.cp_URL)
+        self.username = "" if (self.publish.cp_Username == None) else self.publish.cp_Username
+        self.password = "" if (self.publish.password == None) else self.publish.password
+        self.folder = self.extractDir(self.publish.cp_URL)
+        self.setLabel(self.STATUS_UNKONWN)
+
+        self.enableTestButton()
+        self.updateUI()
+        result = self.executeDialogFromParent(parent)
+        # change the CGPublish properties
+        if (result == 1):
+            self.publish.cp_URL = "ftp://" + self.host() + self.getDir()
+            self.publish.cp_Username = self.username
+            self.publish.password = self.password
+
+        return result
+
+    # updates the hostname, username, password and
+    # directory text fields.
+    # is called uppon initialization.
+    def updateUI(self):
+        DataAware.updateUIs(self.dataAware)
+        self.setDir(self.folder)
+
+    # extract the hostname out of the url used by the
+    # publisher. This url does not include the username:password string.
+    # @param ftpUrl
+    # @return
+    def extractHost(self, ftpUrl):
+        if (ftpUrl is None or len(ftpUrl) < 6):
+            return ""
+        url = ftpUrl.substring(6)
+        i = url.indexOf("/")
+        if (i == -1):
+            return url
+        else:
+            return url.substring(0, i)
+
+    # used to get data from the CGPublish object.
+    # @param ftpUrl
+    # @return the directory portion of the ftp-url
+    def extractDir(self, ftpUrl):
+        if (ftpUrl is None or len(ftpUrl) < 6):
+            return "/"
+        url = ftpUrl.substring(6)
+        i = url.indexOf("/")
+        if (i == -1):
+            return "/"
+        else:
+            return url.substring(i)
+
+    # enables/disables the "test" button
+    # according to the status of the hostname, username, password text fields.
+    # If one of these fields is empty, the button is disabled.
+    def enableTestButton(self):
+        self.setEnabled(self.btnTestConnection, not self.isEmpty(self.host) or self.isEmpty(self.username) or self.isEmpty(self.password))
+
+    # @param s
+    # @return True if the string is None or "".
+    def isEmpty(self, s):
+        return (s is None) or (s == "")
+
+    # @return the ftp url with username and password,
+    # but without the directory portion.
+    def getAcountUrl(self):
+        return "ftp://" + self.username + ":" + self.password + "@" + self.host()
+
+    # return the host name without the "ftp://"
+    # @return
+    def host(self):
+        return self.host(self.host)
+
+    @classmethod
+    def host1(self, s):
+        return s.substring(6) if s.startswith("ftp://") else s
+
+    # @return the full ftp url including username, password and directory portion.
+    def getFullUrl(self):
+        return self.getAcountUrl() + self.folder
+
+    # First I try to connect to the full url, including directory.
+    # If an InteractiveAugmentedIOException accures, I try again,
+    # this time without the dir spec. If this works, I change the dir
+    # to "/", if not I say to the user its his problem...
+    def connect(self):
+        self.setEnabled(self.btnTestConnection, False)
+        self.setLabel(self.STATUS_CONNECTING)
+        success = False
+        try:
+            self.connect1(self.getFullUrl())
+            success = True
+        except InteractiveAugmentedIOException as iaioex:
+            try:
+                self.connect1(self.getAcountUrl())
+                self.setDir("/")
+                success = True
+            except Exception:
+                self.setLabel(self.STATUS_NO_RIGHTS)
+        except InteractiveNetworkResolveNameException as inrne:
+            self.setLabel(self.STATUS_SERVER_NOT_FOUND)
+        except AuthenticationRequest as ar:
+            self.setLabel(self.STATUS_USER_PWD_WRONG)
+        except InteractiveNetworkConnectException as incx:
+            self.setLabel(self.STATUS_HOST_UNREACHABLE)
+        except Exception:
+            self.setLabel(-1)
+            traceback.print_exc()
+
+        if (success):
+            self.setLabel(self.STATUS_OK)
+            self.setEnabled(self.btnDir, True)
+            self.setEnabled(self.btnOK, True)
+
+        self.setEnabled(self.btnTestConnection, True)
+
+
+    # To try the conenction I do some actions that
+    # seem logical to me: <br/>
+    # I get a ucb content.
+    # I list the files in this content.
+    # I call the ucb "open" command.
+    # I get the PropertyNames.PROPERTY_TITLE property of this content.
+    # @param acountUrl
+    # @throws Exception
+    def connect1(self, acountUrl):
+        content = self.ucb.getContent(self.acountUrl)
+
+        # list files in the content.
+        l = self.ucb.listFiles(self.acountUrl, None)
+
+        # open the content
+        aArg = OpenCommandArgument2()
+        aArg.Mode = OpenMode.FOLDERS # FOLDER, DOCUMENTS -> simple filter
+        aArg.Priority = 32768 # Ignored by most implementations
+
+        self.ucb.executeCommand(content, "open", aArg)
+
+        # get the title property of the content.
+        obj = self.ucb.getContentProperty(content, PropertyNames.PROPERTY_TITLE, str())
+
+    # changes the ftp subdirectory, in both
+    # the UI and the data.
+    # @param s the directory.
+    def setDir(self, s):
+        self.folder = s
+        self.txtDir.Model.Text = self.folder
+
+    # @return the ftp subdirecrtory.
+    def getDir(self):
+        return self.folder
+
+    # changes the status label to disconnected status, and
+    # disables the ok and choose-dir buttons.
+    # This method is called also when the hostname, username
+    # and passwordtext fields change.
+    def disconnect(self):
+        self.enableTestButton()
+        self.setEnabled(self.btnOK, False)
+        self.setEnabled(self.btnDir, False)
+        self.setLabel(self.STATUS_UNKONWN)
+
+    # changes the status label and icon, according to the
+    # given status
+    # @param status one opf the private status-constants.
+    # if this param is not one of them, an "unknown error" status is displayed.
+    def setLabel(self, status):
+        if status == self.STATUS_UNKONWN:
+            # not connected yet
+            self.setLabel1(self.resources.resFTPDisconnected, self.ICON_UNKNOWN)
+        elif status == self.STATUS_OK:
+            # connected!
+            self.setLabel1(self.resources.resFTPConnected, self.ICON_OK)
+        elif status == self.STATUS_USER_PWD_WRONG:
+            # wronf password
+            self.setLabel1(self.resources.resFTPUserPwdWrong, self.ICON_ERROR)
+        elif status == self.STATUS_SERVER_NOT_FOUND:
+            # problem resolving server name
+            self.setLabel1(self.resources.resFTPServerNotFound, self.ICON_ERROR)
+        elif status == self.STATUS_NO_RIGHTS:
+            # rights problem
+            self.setLabel1(self.resources.resFTPRights, self.ICON_ERROR)
+        elif status == self.STATUS_HOST_UNREACHABLE:
+            # host unreachable (firewall?)
+            self.setLabel1(self.resources.resFTPHostUnreachable, self.ICON_ERROR)
+        elif status ==  self.STATUS_CONNECTING:
+            self.setLabel1(self.resources.resConnecting, self.ICON_CONNECTING)
+        else:
+            self.setLabel1(self.resources.resFTPUnknownError, self.ICON_ERROR)
+
+    # changes the text of the status label and
+    # (TODO) the status image.
+    # @param label
+    # @param image
+    def setLabel1(self, label, image):
+        setattr(self.lblStatus.Model, PropertyNames.PROPERTY_LABEL, label)
+        setattr(self.imgStatus.Model, PropertyNames.PROPERTY_IMAGEURL, self.imageUrl(image))
+
+    def imageUrl(self, s):
+        return self.imagesDirectory + s
+
+    # called when the user clicks
+    # the choose-dir button. ("...")
+    # Opens the pickFolder dialog.
+    # checks if the returned folder is an ftp folder.
+    # sets the textbox and the data to the new selected dir.
+    def chooseDirectory(self):
+        sd = SystemDialog.createOfficeFolderDialog(self.xMSF)
+        newUrl = sd.callFolderDialog(self.resources.resFTPDirectory, "", self.getFullUrl())
+        if (newUrl is not None):
+            # if the user chose a local directory,
+            # sI do not accept it.
+            if (newUrl.startswith("ftp://")):
+                self.setDir(extractDir(newUrl))
+            else:
+                AbstractErrorHandler.showMessage(self.xMSF, self.xUnoDialog.getPeer(), self.resources.resIllegalFolder, ErrorHandler.ERROR_PROCESS_FATAL)
+
+    # practical to have such a method...
+    # @param p the publisher obejct that contains the ftp connection info.
+    # @return the full ftp url with username password and everything one needs.
+    @classmethod
+    def getFullURL1(self, p):
+        #return "ftp://" + p.Username + ":" + p.password + "@" + self.host(p.URL)
+        return "ftp://" + p.cp_Username + ":" + "" + "@" + self.host1(p.cp_URL)
commit a669ee3816eca4cd3c55a5a704eca2dde53ddf59
Author: Javier Fernandez <jfernandez at igalia.com>
Date:   Tue Mar 19 18:09:11 2013 +0000

    Init: Added new file FTPDialogResources.py
    
    Change-Id: Ibacf3645ecfd892b924fb2d2b202a1f5f2db3215

diff --git a/wizards/com/sun/star/wizards/web/FTPDialogResources.py b/wizards/com/sun/star/wizards/web/FTPDialogResources.py
new file mode 100644
index 0000000..1190fe0
--- /dev/null
+++ b/wizards/com/sun/star/wizards/web/FTPDialogResources.py
@@ -0,0 +1,79 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements. See the NOTICE file distributed
+#   with this work for additional information regarding copyright
+#   ownership. The ASF licenses this file to you under the Apache
+#   License, Version 2.0 (the "License"); you may not use this file
+#   except in compliance with the License. You may obtain a copy of
+#   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+
+from ..common.Resource import Resource
+
+class FTPDialogResources(Resource):
+
+    UNIT_NAME = "dbwizres"
+    MODULE_NAME = "dbw"
+    RID_FTPDIALOG_START = 4200
+    RID_COMMON_START = 500
+    resFTPDialog_title = ""
+    reslblUsername_value = ""
+    reslblPassword_value = ""
+    resbtnConnect_value = ""
+    resbtnOK_value = ""
+    resbtnHelp_value = ""
+    resbtnCancel_value = ""
+    resln1_value = ""
+    reslblFTPAddress_value = ""
+    resln2_value = ""
+    resln3_value = ""
+    esln3_value = ""
+    restxtDir_value = ""
+    resbtnDir_value = ""
+    resFTPDisconnected = ""
+    resFTPConnected = ""
+    resFTPUserPwdWrong = ""
+    resFTPServerNotFound = ""
+    resFTPRights = ""
+    resFTPHostUnreachable = ""
+    resFTPUnknownError = ""
+    resFTPDirectory = ""
+    resIllegalFolder = ""
+    resConnecting = ""
+
+    def __init__(self, xmsf):
+        super(FTPDialogResources, self).__init__(xmsf, self.MODULE_NAME)
+
+        # Delete the String, uncomment the getResText method
+        resFTPDialog_title = self.getResText(self.RID_FTPDIALOG_START + 0)
+        reslblUsername_value = self.getResText(self.RID_FTPDIALOG_START + 1)
+        reslblPassword_value = self.getResText(self.RID_FTPDIALOG_START + 2)
+        resbtnConnect_value = self.getResText(self.RID_FTPDIALOG_START + 3)
+        resln1_value = self.getResText(self.RID_FTPDIALOG_START + 4)
+        reslblFTPAddress_value = self.getResText(self.RID_FTPDIALOG_START + 5)
+        resln2_value = self.getResText(self.RID_FTPDIALOG_START + 6)
+        resln3_value = self.getResText(self.RID_FTPDIALOG_START + 7)
+        resbtnDir_value = self.getResText(self.RID_FTPDIALOG_START + 8)
+        resFTPDisconnected = self.getResText(self.RID_FTPDIALOG_START + 9)
+        resFTPConnected = self.getResText(self.RID_FTPDIALOG_START + 10)
+        resFTPUserPwdWrong = self.getResText(self.RID_FTPDIALOG_START + 11)
+        resFTPServerNotFound = self.getResText(self.RID_FTPDIALOG_START + 12)
+        resFTPRights = self.getResText(self.RID_FTPDIALOG_START + 13)
+        resFTPHostUnreachable = self.getResText(self.RID_FTPDIALOG_START + 14)
+        resFTPUnknownError = self.getResText(self.RID_FTPDIALOG_START + 15)
+        resFTPDirectory = self.getResText(self.RID_FTPDIALOG_START + 16)
+        resIllegalFolder = self.getResText(self.RID_FTPDIALOG_START + 17)
+        resConnecting = self.getResText(self.RID_FTPDIALOG_START + 18)
+
+        resbtnCancel_value = self.getResText(self.RID_COMMON_START + 11)
+        resbtnOK_value = self.getResText(self.RID_COMMON_START + 18)
+        resbtnHelp_value = self.getResText(self.RID_COMMON_START + 15)
+
+        restxtDir_value = "/"
commit 3354a9c382a319c9e7352193e3352838836986d7
Author: Javier Fernandez <jfernandez at igalia.com>
Date:   Tue Mar 19 18:09:32 2013 +0000

    Init: Added new file LogTaskListener.py
    
    Change-Id: I3bed03d791c8ad5361b25e8374578a927aed9bf1

diff --git a/wizards/com/sun/star/wizards/web/LogTaskListener.py b/wizards/com/sun/star/wizards/web/LogTaskListener.py
new file mode 100644
index 0000000..13b7e59
--- /dev/null
+++ b/wizards/com/sun/star/wizards/web/LogTaskListener.py
@@ -0,0 +1,49 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements. See the NOTICE file distributed
+#   with this work for additional information regarding copyright
+#   ownership. The ASF licenses this file to you under the Apache
+#   License, Version 2.0 (the "License"); you may not use this file
+#   except in compliance with the License. You may obtain a copy of
+#   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+
+# used for debugging.
+class LogTaskListener(TaskListener, ErrorHandler):
+
+    out
+
+    def __init__(os):
+        out = os
+
+    def __init__():
+        self.__init__(System.out)
+
+    # @see com.sun.star.wizards.web.status.TaskListener#taskStarted(com.sun.star.wizards.web.status.TaskEvent)
+    def taskStarted(te):
+        out.println("TASK " + te.getTask().getTaskName() + " STARTED.")
+
+    #@see com.sun.star.wizards.web.status.TaskListener#taskFinished(com.sun.star.wizards.web.status.TaskEvent)
+    def taskFinished(te):
+        out.println("TASK " + te.getTask().getTaskName() + " FINISHED: " + te.getTask().getSuccessfull() + "/" + te.getTask().getMax() + "Succeeded.")
+
+    #@see com.sun.star.wizards.web.status.TaskListener#taskStatusChanged(com.sun.star.wizards.web.status.TaskEvent)
+    def taskStatusChanged(te)
+        out.println("TASK " + te.getTask().getTaskName() + " status : " + te.getTask().getSuccessfull() + "(+" + te.getTask().getFailed() + ")/" + te.getTask().getMax())
+
+    #@see com.sun.star.wizards.web.status.TaskListener#subtaskNameChanged(com.sun.star.wizards.web.status.TaskEvent)
+    def subtaskNameChanged(te):
+        out.println("SUBTASK Name:" + te.getTask().getSubtaskName())
+
+    # @see com.sun.star.wizards.web.status.ErrorReporter#error(java.lang.Exception, java.lang.Object, java.lang.String)
+    def error(ex, arg, ix, i):
+        print (PropertyNames.EMPTY_STRING + arg + "//" + ix + "//Exception: " + ex.getLocalizedMessage())
+        ex.printStackTrace()
+        return True;
commit 3718f8aba3f79f194eff6103137d11ad0e1e1280
Author: Javier Fernandez <jfernandez at igalia.com>
Date:   Wed Mar 20 21:30:44 2013 +0000

    Init: Added new file Process.py
    
    Change-Id: I09a49ec08b89f6fbae27a60d5f9208bea7ba8cf8

diff --git a/wizards/com/sun/star/wizards/web/Process.py b/wizards/com/sun/star/wizards/web/Process.py
new file mode 100644
index 0000000..1516cad
--- /dev/null
+++ b/wizards/com/sun/star/wizards/web/Process.py
@@ -0,0 +1,594 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements. See the NOTICE file distributed
+#   with this work for additional information regarding copyright
+#   ownership. The ASF licenses this file to you under the Apache
+#   License, Version 2.0 (the "License"); you may not use this file
+#   except in compliance with the License. You may obtain a copy of
+#   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+import traceback
+import importlib
+
+from .WebWizardConst import *
+from ..common.UCB import UCB
+from ..common.FileAccess import FileAccess
+from ..ui.event.Task import Task
+from .ProcessErrors import ProcessErrors
+from .ExtensionVerifier import ExtensionVerifier
+from .ErrorHandler import ErrorHandler
+from .data.CGContent import CGContent
+from .data.CGDocument import CGDocument
+from .data.CGExporter import CGExporter
+from .data.CGLayout import CGLayout
+from .data.CGPublish import CGPublish
+from .data.CGSettings import CGSettings
+#from .export.Exporter import Exporter
+#from .export.AbstractExporter import AbstractExporter
+#from .export.CopyExporter import CopyExporter
+
+from com.sun.star.io import IOException
+from com.sun.star.uno import SecurityException
+
+# This class is used to process a CGSession object
+# and generate a site. </br>
+# it does the following: <br/>
+# 1. create a temporary directory.<br/>
+# 2. export documents to the temporary directory.<br/>
+# 3. generate the TOC page, includes copying images from the
+# web wizard work directory and other layout files.<br/>
+# 4. publish, or copy, from the temporary directory to
+# different destinations.<br/>
+# 5. delete the temporary directory.<br/>
+# <br/>
+# to follow up the status/errors it uses a TaskListener object,
+# and an ErrorHandler. <br/>
+# in practice, the TaskListener is the status dialog,
+# and the Errorhandler does the interaction with the user,
+# if something goes wrong.<br/>
+# Note that this class takes it in count that
+# the given session object is prepared for it -
+# all preparations are done in WWD_Events.finishWizard methods.
+# <br/>
+# <br/>
+#
+# note on error handling: <br/>
+# on "catch" clauses I tries to decide whether the
+# exception is fatal or not. For fatal exception an error message
+# is displayed (or rather: the errorHandler is being called...)
+# and a false is returned.
+# In less-fatal errors, the errorHandler "should decide" which means,
+# the user is given the option to "OK" or to "Cancel" and depending
+# on that interaction I cary on.
+class Process(ProcessErrors):
+
+    TASKS_PER_DOC = 5
+    TASKS_PER_XSL = 2
+    TASKS_PER_PUBLISH = 2
+    TASKS_IN_PREPARE = 1
+    TASKS_IN_EXPORT = 2
+    TASKS_IN_GENERATE = 2
+    TASKS_IN_PUBLISH = 2
+    TASKS_IN_FINISHUP = 1
+    settings = None
+    xmsf = None
+    errorHandler = None
+    tempDir = None
+    fileAccess = None
+    ucb = None
+    myTask = None
+    #This is a cache for exporters, so I do not need to
+    #instanciate the same exporter more than once.
+    exporters = {}
+    result = None
+
+    def __init__(self, settings, xmsf, er):
+        self.xmsf = xmsf
+        self.settings = settings
+        self.fileAccess = FileAccess(xmsf)
+        self.errorHandler = er
+
+        self.ucb = UCB(xmsf)
+
+        self.taskSteps = self.getTaskSteps()
+        self.myTask = Task(TASK, TASK_PREPARE, self.taskSteps)
+
+    # @return to how many destinations should the
+    # generated site be published.
+    def countPublish(self):
+        count = 0
+        publishers = self.settings.cp_DefaultSession.cp_Publishing
+        for e in publishers.childrenList:
+            if e.cp_Publish:
+                count += 1
+        return count
+
+    # @return the number of task steps that this
+    # session should have
+    def getTaskSteps(self):
+        docs = self.settings.cp_DefaultSession.cp_Content.cp_Documents.getSize()
+        xsl = 0
+        try:
+            layout = self.settings.cp_DefaultSession.getLayout()
+            xsl = len(layout.getTemplates(self.xmsf))
+        except Exception:
+            traceback.print_exc()
+
+        publish = self.countPublish()
+        return \
+                self.TASKS_IN_PREPARE + \
+                self.TASKS_IN_EXPORT + docs * self.TASKS_PER_DOC + \
+                self.TASKS_IN_GENERATE + xsl * self.TASKS_PER_XSL + \
+                self.TASKS_IN_PUBLISH + publish * self.TASKS_PER_PUBLISH + \
+                self.TASKS_IN_FINISHUP
+
+    # does the job
+    def runProcess(self):
+        self.myTask.start()
+        try:
+            try:
+                # I use here '&&' so if one of the
+                # methods returns false, the next
+                # will not be called.
+                self.result = self.createTempDir(self.myTask) and self.export(self.myTask) and self.generate(self.tempDir, self.myTask) and self.publish(self.tempDir, self.myTask)
+                print ("runProcess -- result: ", self.result)
+            finally:
+                # cleanup must be called.
+                self.result = self.result and self.cleanup(self.myTask)
+                print ("runProcess (cleanup) -- result: ", self.result)
+        except Exception:
+            traceback.print_exc()
+            self.result = False
+            print ("runProcess (Exception) -- result: ", self.result)
+
+        if not self.result:
+            # this is a bug protection.
+            self.myTask.fail()
+
+        while (self.myTask.getStatus() < self.myTask.getMax()):
+            self.myTask.advance(True)
+
+    # creates a temporary directory.
+    # @param task
+    # @return true should continue
+    def createTempDir(self, task):
+        try:
+            self.tempDir = self.fileAccess.createNewDir(self.getSOTempDir(self.xmsf), "/wwiztemp")
+        except Exception:
+            traceback.print_exc()
+        if self.tempDir is None:
+            print ("WARNING !!! createTempDir -- error")
+            #self.error(None, None, ProcessErrors.ERROR_MKDIR, ErrorHandler.ERROR_PROCESS_FATAL)
+            return False
+        else:
+            task.advance(True)
+            return True
+
+    # @param xmsf
+    # @return the staroffice /openoffice temporary directory
+    def getSOTempDir(self, xmsf):
+        try:
+            return FileAccess.getOfficePath(self.xmsf, "Temp", "")
+        except Exception:
+            traceback.print_exc()
+        return None
+
+    # CLEANUP
+
+    # delete the temporary directory
+    # @return true should continue
+    def cleanup(self, task):
+        print ("WARNING !!! cleanup")
+        task.setSubtaskName(TASK_FINISH)
+        b = self.fileAccess.delete(self.tempDir)
+        if not b:
+            print ("WARNING !!! cleanup -- error")
+            self.error(None, None, ProcessErrors.ERROR_CLEANUP, ErrorHandler.ERROR_WARNING)
+        task.advance(b)
+        return b
+
+    # This method is used to copy style files to a target
+    # Directory: css and background.
+    # Note that this method is static since it is
+    # also used when displaying a "preview"
+    def copyMedia(self, copy, settings, targetDir, task):
+        # 1. .css
+        sourceDir = FileAccess.connectURLs(settings.workPath, "styles")
+        filename = settings.cp_DefaultSession.getStyle().cp_CssHref
+        print ("WARNING !!! copyMedia (css) - source, filenamem, target, targetName: ", sourceDir, filename, targetDir, "style.css")
+        copy.copy2(sourceDir, filename, targetDir, "style.css")
+
+        task.advance(True)
+
+        # 2. background image
+        background = settings.cp_DefaultSession.cp_Design.cp_BackgroundImage
+        if (background is not None and background is not ""):
+            sourceDir = FileAccess.getParentDir(background)
+            filename = background[len(sourceDir):]
+            print ("WARNING !!! copyMedia (background) - source, filenamem, target, targetName: ", sourceDir, filename, targetDir + "/images", "background.gif")
+            copy.copy2(sourceDir, filename, targetDir + "/images", "background.gif")
+
+        task.advance(True)
+
+    # Copy "static" files (which are always the same,
+    # thus not user-input-dependant) to a target directory.
+    # Note that this method is static since it is
+    # also used when displaying a "preview"
+    # @param copy
+    # @param settings
+    # @param targetDir
+    # @throws Exception
+    @classmethod
+    def copyStaticImages(self, copy, settings, targetDir):
+        source = FileAccess.connectURLs(settings.workPath, "images")
+        target = targetDir + "/images"
+        print ("WARNING !!! copyStaticImages - source, target: ", source, target)
+        copy.copy(source, target)
+
+    # publish the given directory.
+    # @param dir the source directory to publish from
+    # @param task task tracking.
+    # @return true if should continue
+    def publish(self, folder, task):
+        task.setSubtaskName(TASK_PUBLISH_PREPARE)
+        configSet = self.settings.cp_DefaultSession.cp_Publishing
+        try:
+            self.copyMedia(self.ucb, self.settings, folder, task)
+            self.copyStaticImages(self.ucb, self.settings, folder)
+            task.advance(True)
+        except Exception as ex:
+            # error in copying media
+            traceback.print_exc()
+            print ("WARNING !!! publish -- error")
+            self.error(ex, "", ProcessErrors.ERROR_PUBLISH_MEDIA, ErrorHandler.ERROR_PROCESS_FATAL)
+            return False
+        for p in configSet.childrenList:
+            if p.cp_Publish:
+                key = configSet.getKey(p)
+                task.setSubtaskName(key)
+                if key is ZIP_PUBLISHER:
+                    self.fileAccess.delete(p.cp_URL)
+                if (not self.publish1(folder, p, self.ucb, task)):
+                    return False
+        return True
+
+    # publish the given directory to the
+    # given target CGPublish.
+    # @param dir the dir to copy from
+    # @param publish the object that specifies the target
+    # @param copy ucb encapsulation
+    # @param task task tracking
+    # @return true if should continue
+    def publish1(self, folder, publish, copy, task):
+        try:
+            task.advance(True)
+            url = publish.url
+            print ("WARNING !!! publish1 - source, target: ", folder, url)
+            copy.copy(folder, url)
+            task.advance(True)
+            return True
+        except Exception as e:
+            task.advance(False)
+            traceback.print_exc()
+            print ("WARNING !!! publish1 -- error")
+            return self.error(e, publish, ProcessErrors.ERROR_PUBLISH, ErrorHandler.ERROR_NORMAL_IGNORE)
+
+    # Generates the TOC pages for the current session.
+    # @param targetDir generating to this directory.
+    def generate(self, targetDir, task):
+        result = False
+        task.setSubtaskName(TASK_GENERATE_PREPARE)
+
+
+        layout = self.settings.cp_DefaultSession.getLayout()
+
+        try:
+            # here I create the DOM of the TOC to pass to the XSL
+            doc = self.settings.cp_DefaultSession.createDOM1()
+            self.generate1(self.xmsf, layout, doc, self.fileAccess, targetDir, task)
+        except Exception as ex:
+            print ("WARNING !!! generate (calling generate1  -- error")
+            traceback.print_exc()
+            print ("WARNING !!! publish1 -- error")
+            self.error(ex, "", ProcessErrors.ERROR_GENERATE_XSLT, ErrorHandler.ERROR_PROCESS_FATAL)
+            return False
+
+        # copy files which are not xsl from layout directory to
+        # website root.
+        try:
+            task.setSubtaskName(TASK_GENERATE_COPY)
+
+            self.copyLayoutFiles(self.ucb, self.fileAccess, self.settings, layout, targetDir)
+
+            task.advance(True)
+
+            result = True
+        except Exception as ex:
+            task.advance(False)
+            print ("WARNING !!! generate (copying layouts) -- error")
+            traceback.print_exc()
+            return self.error(ex, None, ProcessErrors.ERROR_GENERATE_COPY, ErrorHandler.ERROR_NORMAL_ABORT)
+        return result
+
+    # copies layout files which are not .xsl files
+    # to the target directory.
+    # @param ucb UCB encapsulatzion object
+    # @param fileAccess filaAccess encapsulation object
+    # @param settings web wizard settings
+    # @param layout the layout object
+    # @param targetDir the target directory to copy to
+    # @throws Exception
+    @classmethod
+    def copyLayoutFiles(self, ucb, fileAccess, settings, layout, targetDir):
+        filesPath = fileAccess.getURL(FileAccess.connectURLs(settings.workPath, "layouts/"), layout.cp_FSName)
+        print ("WARNING !!! copyLayoutFiles - source, target: ", filesPath, targetDir)
+        ucb.copy1(filesPath, targetDir, ExtensionVerifier("xsl"))
+
+    # generates the TOC page for the given layout.
+    # This method might generate more than one file, depending
+    # on how many .xsl files are in the
+    # directory specifies by the given layout object.
+    # @param xmsf
+    # @param layout specifies the layout to use.
+    # @param doc the DOM representation of the web wizard session
+    # @param fileAccess encapsulation of FileAccess
+    # @param targetPath target directory
+    # @param task
+    # @throws Exception
+    @classmethod
+    def generate1(self, xmsf, layout, doc, fileAccess, targetPath, task):
+        # a map that contains xsl templates. the keys are the xsl file names.
+        #templates = layout.getTemplates(xmsf)
+        templates = {}
+
+        task.advance1(True, TASK_GENERATE_XSL)
+
+        # each template generates a page.
+        for key,temp in templates:
+            transformer = temp.newTransformer()
+
+            doc.normalize()
+            task.advance(True)
+
+            # The target file name is like the xsl template filename
+            # without the .xsl extension.
+            #fn = fileAccess.getPath(targetPath, key[:key.length() - 4])
+            #f = File(fn)
+            #oStream = FileOutputStream(f)
+            # Due to a problem occuring when using Xalan-Java 2.6.0 and
+            # Java 1.5.0, wrap f in a FileOutputStream here (otherwise, the
+            # StreamResult's getSystemId would return a "file:/..." URL while
+            # the Xalan code expects a "file:///..." URL):
+            #transformer.transform(DOMSource(doc), StreamResult(oStream))
+            #oStream.close()
+            task.advance(True)
+
+    # I broke the export method to two methods
+    # in a time where a tree with more than one contents was planned.
+    # I left it that way, because it may be used in the future.
+    # @param task
+    # @return
+    def export(self, task):
+        return self.export1(self.settings.cp_DefaultSession.cp_Content, self.tempDir, task)
+
+    # This method could actually, with light modification, use recursion.
+    # In the present situation, where we only use a "flat" list of
+    # documents, instead of the original plan to use a tree,
+    # the recursion is not implemented.
+    # @param content the content ( directory-like, contains documents) 
+    # @param dir (target directory for exporting this content.
+    # @param task
+    # @return true if should continue
+    def export1(self, content, folder, task):
+        toPerform = 1
+        contentDir = None
+
+        try:
+            task.setSubtaskName(TASK_EXPORT_PREPARE)
+
+            # 1. create a content directory.
+            # each content (at the moment there is only one :-( )
+            # is created in its own directory.
+            # faileure here is fatal.
+            print ("export1 - folder and cp_Name: ", folder, content.cp_Name)
+            contentDir = self.fileAccess.createNewDir(folder, content.cp_Name);
+            if (contentDir is None or contentDir is ""):
+                raise IOException("Directory " + folder + " could not be created.")
+
+            content.dirName = FileAccess.getFilename(contentDir)
+
+            task.advance1(True, TASK_EXPORT_DOCUMENTS)
+            toPerform -= 1
+
+            # 2. export all documents and sub contents.
+            # (at the moment, only documents, no subcontents)
+            for item in content.cp_Documents.childrenList:
+                try:
+                    #
+                    # In present this is always the case.
+                    # may be in the future, when
+                    # a tree is used, it will be abit different.
+                    if (isinstance (item, CGDocument)):
+                        if (not self.export2(item, contentDir, task)):
+                            return False
+                    elif (not self.export2(item, contentDir, task)):
+                    # we never get here since we
+                    # did not implement sub-contents.
+                        return False
+                except SecurityException as sx:
+                    # nonfatal
+                    traceback.print_exc()
+                    print ("WARNING !!! export1 (SecurityException -- error")
+                    if (not self.error(sx, item, ProcessErrors.ERROR_EXPORT_SECURITY, ErrorHandler.ERROR_NORMAL_IGNORE)):
+                        return False
+                    self.result = False
+        except IOException as iox:
+            # nonfatal
+            traceback.print_exc()
+            print ("WARNING !!! export1 (IOException -- error")
+            return self.error(iox, content, ProcessErrors.ERROR_EXPORT_IO, ErrorHandler.ERROR_NORMAL_IGNORE)
+        except SecurityException as se:
+            # nonfatal
+            traceback.print_exc()
+            print ("WARNING !!! export1 (SecurityException -- error")
+            return self.error(se, content, ProcessErrors.ERROR_EXPORT_SECURITY, ErrorHandler.ERROR_NORMAL_IGNORE)
+
+        self.failTask(task, toPerform)
+        return True
+
+    # exports a single document
+    # @param doc the document to export
+    # @param dir the target directory
+    # @param task task tracking
+    # @return true if should continue
+    def export2(self, doc, folder, task):
+        # first I check if the document was already validated...
+        if (not doc.valid):
+            try:
+                print ("WARNING !!! export2 -- new validation: ")
+                doc.validate(self.xmsf, task)
+            except Exception as ex:
+                # fatal
+                traceback.print_exc()
+                print ("WARNING !!! export2 (validation) -- error")
+                self.error(ex, doc, ProcessErrors.ERROR_DOC_VALIDATE, ErrorHandler.ERROR_PROCESS_FATAL)
+                return False
+        # get the exporter specified for this document
+        exp = doc.cp_Exporter
+        print ("WARNING !!! export2 -- exporter: ", exp)
+        exporter = self.settings.cp_Exporters.getElement(exp)
+
+        try:
+             # here I calculate the destination filename.
+             # I take the original filename (docFilename), substract the extension, (docExt) -> (fn)
+             # and find an available filename which starts with
+             # this filename, but with the new extension. (destExt)
+            print ("WARNING !!! export2 - doc.cp_URL: ", doc.cp_URL)
+            print ("WARNING !!! export2 - doc.localFilename: ", doc.localFilename)
+            docFilename = FileAccess.getFilename(doc.cp_URL)
+            print ("WARNING !!! export2 - docFilename: ", docFilename)
+
+            docExt = FileAccess.getExtension(docFilename)
+            print ("WARNING !!! export2 - docExt: ", docExt)
+            # filename without extension
+            #fn = doc.localFilename.substring(0, doc.localFilename.length() - docExt.length() - 1)
+            fn = doc.localFilename[:len(doc.localFilename) - len(docExt) - 1]
+            print ("WARNING !!! export2 - fn: ", fn)
+
+            # the copyExporter does not change
+            # the extension of the target...
+            destExt = FileAccess.getExtension(docFilename) \
+                if (exporter.cp_Extension is "") \
+                else exporter.cp_Extension
+            print ("WARNING !!! export2 - destExt: ", destExt)
+
+            # if this filter needs to export to its own directory...
+            # this is the case in, for example, impress html export
+            if (exporter.cp_OwnDirectory):
+                # +++
+                folder = self.fileAccess.createNewDir(folder, fn)
+                doc.dirName = FileAccess.getFilename(folder)
+
+            # if two files with the same name
+            # need to be exported ? So here
+            # i get a new filename, so I do not
+            # overwrite files...
+            f = self.fileAccess.getNewFile(folder, fn, destExt)
+            print ("WARNING !!! export2 - f: ", f)
+
+
+            # set filename with extension.
+            # this will be used by the exporter,
+            # and to generate the TOC.
+            doc.urlFilename = FileAccess.getFilename(f)
+            print ("WARNING !!! export2 - : doc.urlFilename", doc.urlFilename)
+
+            task.advance(True)
+
+            try:
+                # export
+                self.getExporter(exporter).export(doc, f, self.xmsf, task)
+                task.advance(True)
+             # getExporter(..) throws
+             # IllegalAccessException, InstantiationException, ClassNotFoundException
+             # export() throws Exception
+            except Exception as ex:
+                # nonfatal
+                traceback.print_exc()
+                print ("WARNING !!! export2 (getting exporters) -- error")
+                if (not self.error(ex, doc, ProcessErrors.ERROR_EXPORT, ErrorHandler.ERROR_NORMAL_IGNORE)):
+                    return False
+        except Exception as ex:
+            # nonfatal
+            traceback.print_exc()
+            print ("WARNING !!! export2 (general) -- error")
+            if (not self.error(ex, doc, ProcessErrors.ERROR_EXPORT_MKDIR, ErrorHandler.ERROR_NORMAL_ABORT)):
+                return False
+
+        return True
+
+    # submit an error.
+    # @param ex the exception
+    # @param arg1 error argument
+    # @param arg2 error argument 2
+    # @param errType error type
+    # @return the interaction result
+    def error(self, ex, arg1, arg2, errType):
+        self.result = False
+        print ("error -- result: ", self.result)
+        return self.errorHandler.error(ex, arg1, arg2, errType)
+
+
+    # advances the given task in the given count of steps,
+    # marked as failed.
+    # @param task the task to advance
+    # @param count the number of steps to advance
+    def failTask(self, task, count):
+        while (count > 0):
+            task.advance(False)
+            count -= 1
+
+    # creates an instance of the exporter class
+    # as specified by the
+    # exporter object.
+    # @param export specifies the exporter to be created
+    # @return the Exporter instance
+    # @throws ClassNotFoundException
+    # @throws IllegalAccessException
+    # @throws InstantiationException
+    def createExporter(self, export):
+        print ("WANRING !!!! Creating exporter -- class: ", export.cp_ExporterClass)
+        pkgname = ".".join(export.cp_ExporterClass.split(".")[3:])
+        className = export.cp_ExporterClass.split(".")[-1]
+        mod = importlib.import_module(pkgname)
+        return getattr(mod, className)(export)
+
+    # searches the an exporter for the given CGExporter object
+    # in the cache.
+    # If its not there, creates it, stores it in the cache and
+    # returns it.
+    # @param export specifies the needed exporter.
+    # @return an Exporter instance
+    # @throws ClassNotFoundException thrown when using Class.forName(string)
+    # @throws IllegalAccessException thrown when using Class.forName(string)
+    # @throws InstantiationException thrown when using Class.forName(string)
+    def getExporter(self, export):
+        exp = self.exporters.get(export.cp_Name)
+        if (exp is None):
+            exp = self.createExporter(export)
+            self.exporters[export.cp_Name] = exp
+        return exp
+
+    # @return tru if everything went smooth, false
+    # if error(s) accured.
+    def getResult(self):
+        print ("Process -- getFailed: ", self.myTask.getFailed())
+        print ("Process -- result: ", self.result)
+        return (self.myTask.getFailed() == 0) and self.result
commit a13ad6b0a90ec6d67685db00f3b92c78af016e59
Author: Javier Fernandez <jfernandez at igalia.com>
Date:   Tue Mar 19 18:10:03 2013 +0000

    Init: Added new file ProcessErrorHandler.py
    
    Change-Id: I0444f27eddc4367c963a4c5e81a7f4b8011d5626

diff --git a/wizards/com/sun/star/wizards/web/ProcessErrorHandler.py b/wizards/com/sun/star/wizards/web/ProcessErrorHandler.py
new file mode 100644
index 0000000..6b6c8bb
--- /dev/null
+++ b/wizards/com/sun/star/wizards/web/ProcessErrorHandler.py
@@ -0,0 +1,61 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements. See the NOTICE file distributed
+#   with this work for additional information regarding copyright
+#   ownership. The ASF licenses this file to you under the Apache
+#   License, Version 2.0 (the "License"); you may not use this file
+#   except in compliance with the License. You may obtain a copy of
+#   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+
+from .ProcessErrors import ProcessErrors
+from .AbstractErrorHandler import AbstractErrorHandler
+from .WebWizardConst import *
+
+# used to interact error accuring when generating the
+# web-site to the user.
+# This class renders the different errors,
+# replaceing some strings from the resources with
+# content of the given arguments, depending on the error
+# that accured.
+class ProcessErrorHandler(AbstractErrorHandler, ProcessErrors):
+
+    FILENAME = "%FILENAME"
+    URL = "%URL"
+    ERROR = "%ERROR"
+    resources = None
+
+    def __init__(self, xmsf, peer, res):
+        super(ProcessErrorHandler, self).__init__(xmsf, peer)
+        self.resources = res
+
+    def getMessageFor(self, ex, obj, ix, errType):
+        if ix == ProcessErrors.ERROR_MKDIR:
+            return self.resources.resErrDocExport.replace(obj.localFilename, self.FILENAME)
+        elif ix == ProcessErrors.ERROR_EXPORT_MKDIR:
+            return self.resources.resErrMkDir.replace(obj.localFilename, self.FILENAME)
+        elif ix == ProcessErrors.ERROR_DOC_VALIDATE:
+            return self.resources.resErrDocInfo.replace(obj.localFilename, self.FILENAME)
+        elif ix == ProcessErrors.ERROR_EXPORT_IO:
+            return self.resources.resErrExportIO.replace(obj.localFilename, self.FILENAME)
+        elif ix == ProcessErrors.ERROR_EXPORT_SECURITY:
+            return self.resources.resErrSecurity.replace(obj.localFilename, self.FILENAME)
+        elif ix == ProcessErrors.ERROR_GENERATE_XSLT:
+            return self.resources.resErrTOC
+        elif ix == ProcessErrors.ERROR_GENERATE_COPY:
+            return self.resources.resErrTOCMedia
+        elif ix == ProcessErrors.ERROR_PUBLISH:
+            return self.resources.resErrPublish.replace(self.URL, obj.URL)
+        elif (ix == ProcessErrors.ERROR_EXPORT or ix == ProcessErrors.ERROR_PUBLISH_MEDIA):
+            return self.resources.resErrPublishMedia
+        elif ix == ProcessErrors.ERROR_CLEANUP:
+            return self.resources.resErrUnexpected
+        else:
+            return self.resources.resErrUnknown.replace("%ERROR", "{0}/{1}/{2!s}".format(ex.__class__.__name__, obj.__class__.__name__, ix))
commit 8262f4855d2cbb7b2435ebf29323c4588ed22488
Author: Javier Fernandez <jfernandez at igalia.com>
Date:   Tue Mar 19 18:10:33 2013 +0000

    Init: Added new file ProcessErrors.py
    
    Change-Id: I02484002b23db77313247fb3c6de12dc82c08da7

diff --git a/wizards/com/sun/star/wizards/web/ProcessErrors.py b/wizards/com/sun/star/wizards/web/ProcessErrors.py
new file mode 100644
index 0000000..40fda77
--- /dev/null
+++ b/wizards/com/sun/star/wizards/web/ProcessErrors.py
@@ -0,0 +1,32 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements. See the NOTICE file distributed
+#   with this work for additional information regarding copyright
+#   ownership. The ASF licenses this file to you under the Apache
+#   License, Version 2.0 (the "License"); you may not use this file
+#   except in compliance with the License. You may obtain a copy of
+#   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+
+# Error IDs for errors that can accure
+# in the interaction with the Process class.
+class ProcessErrors:
+
+    ERROR_MKDIR = 0
+    ERROR_EXPORT = 1
+    ERROR_EXPORT_MKDIR = 2
+    ERROR_DOC_VALIDATE = 3
+    ERROR_EXPORT_IO = 4
+    ERROR_EXPORT_SECURITY = 5
+    ERROR_GENERATE_XSLT = 6
+    ERROR_GENERATE_COPY = 7
+    ERROR_PUBLISH = 8
+    ERROR_PUBLISH_MEDIA = 9
+    ERROR_CLEANUP = 10
commit 49ecc6ea1db0bcca7be5812ebd8bf6ab9140eadc
Author: Javier Fernandez <jfernandez at igalia.com>
Date:   Tue Mar 19 18:10:55 2013 +0000

    Init: Added new file ProcessStatusRenderer.py
    
    Change-Id: Ifacbff7c1423580f14ff3c92a8202015f1afad6b

diff --git a/wizards/com/sun/star/wizards/web/ProcessStatusRenderer.py b/wizards/com/sun/star/wizards/web/ProcessStatusRenderer.py
new file mode 100644
index 0000000..f123785
--- /dev/null
+++ b/wizards/com/sun/star/wizards/web/ProcessStatusRenderer.py
@@ -0,0 +1,48 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements. See the NOTICE file distributed
+#   with this work for additional information regarding copyright
+#   ownership. The ASF licenses this file to you under the Apache
+#   License, Version 2.0 (the "License"); you may not use this file
+#   except in compliance with the License. You may obtain a copy of
+#   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+
+
+from .WebWizardConst import *
+from ..common.IRenderer import IRenderer
+
+
+# recieves status calls from the status dialog which
+# apears when the user clicks "create".
+# allocates strings from the resources to
+# display the current task status.
+# (renders the state to resource strings)
+class ProcessStatusRenderer(IRenderer):
+
+    strings = {}
+
+    def __init__(self, res):
+        self.strings[TASK_EXPORT_DOCUMENTS] = res.resTaskExportDocs
+        self.strings[TASK_EXPORT_PREPARE] = res.resTaskExportPrepare
+        self.strings[TASK_GENERATE_COPY] = res.resTaskGenerateCopy
+        self.strings[TASK_GENERATE_PREPARE] = res.resTaskGeneratePrepare
+        self.strings[TASK_GENERATE_XSL] = res.resTaskGenerateXsl
+        self.strings[TASK_PREPARE] = res.resTaskPrepare
+        self.strings[LOCAL_PUBLISHER] = res.resTaskPublishLocal
+        self.strings[ZIP_PUBLISHER] = res.resTaskPublishZip
+        self.strings[FTP_PUBLISHER] = res.resTaskPublishFTP
+
+        self.strings[TASK_PUBLISH_PREPARE] = res.resTaskPublishPrepare
+        self.strings[TASK_FINISH] = res.resTaskFinish
+
+    def render(self, object):
+        return self.strings[object]
+
commit c6d5bffcc8cba3642aeb10e1d508dd4f15253491
Author: Javier Fernandez <jfernandez at igalia.com>
Date:   Tue Mar 19 18:11:09 2013 +0000

    Init: Added new file StatusDialog.py
    
    Change-Id: I679e60042d2d46fdeaf5b56063108bb0332393a0

diff --git a/wizards/com/sun/star/wizards/web/StatusDialog.py b/wizards/com/sun/star/wizards/web/StatusDialog.py
new file mode 100644
index 0000000..5b353cc
--- /dev/null
+++ b/wizards/com/sun/star/wizards/web/StatusDialog.py
@@ -0,0 +1,174 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements. See the NOTICE file distributed
+#   with this work for additional information regarding copyright
+#   ownership. The ASF licenses this file to you under the Apache
+#   License, Version 2.0 (the "License"); you may not use this file
+#   except in compliance with the License. You may obtain a copy of
+#   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+import uno
+import traceback
+
+from ..ui.UnoDialog2 import UnoDialog2
+from ..ui.UnoDialog import UnoDialog
+from ..ui.event.TaskListener import TaskListener
+from ..common.PropertyNames import PropertyNames
+
+# Note on the argument resource:
+# This should be a String array containing the followin strings, in the
+# following order:
+# dialog title, cancel, close, counter prefix, counter midfix, counter postfix
+class StatusDialog(UnoDialog2):
+
+    STANDARD_WIDTH = 240
+    lblTaskName = None
+    lblCounter = None
+    progressBar = None
+    btnCancel = None
+    finished = False
+    enableBreak = False
+    closeOnFinish = True
+    renderer = None
+    finishedMethod = None
+
+    def __init__(self, xmsf, width, taskName, displayCount, resources, hid):
+        super(StatusDialog, self).__init__(xmsf)
+
+        self.res = resources
+        if not (len(self.res) == 6):
+            # display a close button?

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list