class EditorPane(object):
    """
    The EditorPane is responsible for creating new idevice
    """
    def __init__(self, webServer, parent):
        """
        Initialize
        JR: anado parente para poder acceder a algunos atributos de editorpag, en concreto a showHide
        """
        self.ideviceStore = webServer.application.ideviceStore
        self.webDir = webServer.application.config.webDir
        self.styles = webServer.application.config.styleStore.getStyles()
        self.elements = []
        self.idevice = GenericIdevice("", "", "", "", "")
        self.idevice.id = self.ideviceStore.getNewIdeviceId()
        self.originalIdevice = GenericIdevice("", "", "", "", "")
        self.purpose = ""
        self.tip = ""
        self.message = ""
        self.parent = parent
        self._nameInstruc     = \
           x_(u"Your new iDevice will appear in the iDevice "
              u"pane with this title. This is a compulsory field "
              u"and you will be prompted to enter a label if you try "
              u"to submit your iDevice without one.")
        self._authorInstruc = x_(u"This is an optional field.")
        self._purposeInstruc = x_(
            u"The purpose dialogue allows you to describe"
            u" your intended purpose of the iDevice to other"
            u" potential users.")
        self._emphasisInstruc = x_(
            u"Use this pulldown to select whether or not "
            u" the iDevice should have any formatting "
            u" applied to it to distinguish "
            u"it; ie. a border and an icon.")
        self._tipInstruc = x_(u"Use this field to describe "
                              u"your intended use and the pedagogy behind "
                              u"the device's development. This can be useful "
                              u"if your iDevice is to be exported for others "
                              u"to use.")
        self._lineInstruc = x_(u"Add a single text line to an iDevice. "
                               u"Useful if you want the ability to place a "
                               u"label within the iDevice.")
        self._textBoxInstruc = x_(
            u"Add a text entry box to an iDevice. "
            u"Used for entering larger amounts of textual "
            u"content.")
        self._feedbackInstruc = x_(
            u"Add an interactive feedback field to your iDevice.")
        self._flashInstruc = x_(u"Add a flash video to your iDevice.")
        self._mp3Instruc = x_(u"Add an mp3 file to your iDevice.")
        self._attachInstruc = x_(u"Add an attachment file to your iDevice.")

        self.style = self.styles[0]

    # Properties

    nameInstruc = lateTranslate('nameInstruc')
    authorInstruc = lateTranslate('authorInstruc')
    purposeInstruc = lateTranslate('purposeInstruc')
    emphasisInstruc = lateTranslate('emphasisInstruc')
    tipInstruc = lateTranslate('tipInstruc')
    lineInstruc = lateTranslate('lineInstruc')
    textBoxInstruc = lateTranslate('textBoxInstruc')
    feedbackInstruc = lateTranslate('feedbackInstruc')
    flashInstruc = lateTranslate('flashInstruc')
    mp3Instruc = lateTranslate('mp3Instruc')
    attachInstruc = lateTranslate('attachInstruc')

    def setIdevice(self, idevice):
        """
        Sets the iDevice to edit
        """
        self.idevice = idevice.clone()
        self.idevice.id = idevice.id
        self.originalIdevice = idevice

    def process(self, request, status):
        """
        Process
        """

        log.debug("process " + repr(request.args))
        self.message = ""

        if status == "old":
            for element in self.elements:
                element.process(request)

            if "title" in request.args:
                self.idevice.title = unicode(request.args["title"][0], 'utf8')

            if "tip" in request.args:
                self.idevice.tip = unicode(request.args["tip"][0], 'utf8')

            if "emphasis" in request.args:
                self.idevice.emphasis = int(request.args["emphasis"][0])
                if self.idevice.emphasis == 0:
                    self.idevice.icon = ""

        if "addText" in request.args:
            field = TextField(_(u"Enter the label here"),
                              _(u"Enter instructions for completion here"))
            field.setIDevice(self.idevice)
            self.idevice.addField(field)
            self.idevice.edit = True

        if "addTextArea" in request.args:
            field = TextAreaField(
                _(u"Enter the label here"),
                _(u"Enter the instructions for completion here"))
            field.setIDevice(self.idevice)
            self.idevice.addField(field)
            self.idevice.edit = True

        if "addFeedback" in request.args:
            field = FeedbackField(
                _(u"Enter the label here"),
                _(u"""Feedback button will not appear if no 
data is entered into this field."""))
            field.setIDevice(self.idevice)
            self.idevice.addField(field)
            self.idevice.edit = True

        #if "addFlash" in request.args:
        #print "add a flash"
        #field = FlashField(_(u"Enter the label here"),
        #_(u"Enter the instructions for completion here"))
        #field.setIDevice(self.idevice)
        #self.idevice.addField(field)

        if "addMP3" in request.args:

            field = MultimediaField(
                _(u"Enter the label here"),
                _(u"Enter the instructions for completion here"))
            field.setIDevice(self.idevice)
            self.idevice.addField(field)
            if not 'xspf_player.swf' in self.idevice.systemResources:
                self.idevice.systemResources += ['xspf_player.swf']
            self.idevice.edit = True

        if "addAttachment" in request.args:

            field = AttachmentField(
                _(u"Enter the label here"),
                _(u"Enter the instructions for completion here"))
            field.setIDevice(self.idevice)
            self.idevice.addField(field)
            self.idevice.edit = True

        if ("action" in request.args
                and request.args["action"][0] == "selectIcon"):
            self.idevice.icon = request.args["object"][0]

        if "preview" in request.args:
            if self.idevice.title == "":
                self.message = _("Please enter<br />an idevice name.")
            else:
                self.idevice.edit = False

        if "edit" in request.args:
            self.idevice.edit = True

        if "cancel" in request.args:
            ideviceId = self.idevice.id
            self.idevice = self.originalIdevice.clone()
            self.idevice.id = ideviceId
            self.parent.showHide = False

        if ("action" in request.args
                and request.args["action"][0] == "changeStyle"):
            self.style = self.styles[int(request.args["object"][0])]

        self.__buildElements()

    def __buildElements(self):
        """
        Building up element array
        """
        self.elements = []
        elementTypeMap = {
            TextField: TextEditorElement,
            TextAreaField: TextAreaEditorElement,
            ImageField: ImageEditorElement,
            FeedbackField: FeedbackEditorElement,
            MultimediaField: MultimediaEditorElement,
            FlashField: FlashEditorElement,
            AttachmentField: AttachmentEditorElement
        }

        for field in self.idevice.fields:
            elementType = elementTypeMap.get(field.__class__)

            if elementType:
                # Create an instance of the appropriate element class
                log.debug(u"createElement " + elementType.__class__.__name__ +
                          u" for " + field.__class__.__name__)
                self.elements.append(elementType(field))
            else:
                log.error(u"No element type registered for " +
                          field.__class__.__name__)

    def renderButtons(self, request):
        """
        Render the idevice being edited
        """
        html = "<font color=\"red\"><b>" + self.message + "</b></font>"

        html += "<fieldset><legend><b>" + _("Add Field") + "</b></legend>"
        html += common.submitButton("addText", _("Text Line"))
        html += common.elementInstruc(self.lineInstruc) + "<br/>"
        html += common.submitButton("addTextArea", _("Text Box"))
        html += common.elementInstruc(self.textBoxInstruc) + "<br/>"
        html += common.submitButton("addFeedback", _("Feedback"))
        html += common.elementInstruc(self.feedbackInstruc) + "<br/>"
        #  Attachments are now embeddable:
        #html += common.submitButton("addAttachment", _("Attachment"))
        #html += common.elementInstruc(self.attachInstruc) + "<br/>"
        #  MP3 fields are now embeddable:
        #html += common.submitButton("addMP3", _("MP3"))
        #html += common.elementInstruc(self.mp3Instruc) + "<br/>"
        html += "</fieldset>\n"

        html += "<fieldset><legend><b>" + _("Actions") + "</b></legend>"

        if self.idevice.edit:
            html += common.submitButton("preview", _("Preview"),
                                        not self.parent.isGeneric)
        else:
            html += common.submitButton("edit", _("Edit"))

        html += "<br/>"
        html += common.submitButton("cancel", _("Cancel"))
        #html += "</fieldset>"

        return html

    def renderIdevice(self, request):
        """
        Returns an XHTML string for rendering the new idevice
        """
        html = "<div id=\"editorWorkspace\">\n"
        html += "<script type=\"text/javascript\">\n"
        html += "<!--\n"
        html += """
            function submitLink(action, object, changed) 
            {
                var form = document.getElementById("contentForm")
            
                form.action.value = action;
                form.object.value = object;
                form.isChanged.value = changed;
                form.submit();
            }\n"""
        html += """
            function submitIdevice() 
            {
                var form = document.getElementById("contentForm")
                if (form.ideviceSelect.value == "newIdevice")
                    form.action.value = "newIdevice"
                else
                    form.action.value = "changeIdevice"
                form.object.value = form.ideviceSelect.value;
                form.isChanged.value = 1;
                form.submit();
            }\n"""
        html += """
            function submitStyle()
            {
                var form = document.getElementById("contentForm")
                form.action.value = "changeStyle";
                form.object.value = form.styleSelect.value;
                form.isChanged.value = 0;
                form.submit();
            }\n"""
        html += "//-->\n"
        html += "</script>\n"

        self.purpose = self.idevice.purpose.replace("\r", "")
        self.purpose = self.purpose.replace("\n", "\\n")

        self.tip = self.idevice.tip.replace("\r", "")
        self.tip = self.tip.replace("\n", "\\n")

        if self.idevice.edit:
            html += "<b>" + _("Name") + ": </b>\n"
            html += common.elementInstruc(self.nameInstruc) + "<br/>"
            html += '<input type="text" name= "title" id="title" value="%s"/>' % self.idevice.title

            this_package = None
            html += common.formField('richTextArea', this_package,
                                     _(u"Pedagogical Tip"), 'tip', '',
                                     self.tipInstruc, self.tip)

            html += "<b>" + _("Emphasis") + ":</b> "
            html += "<select onchange=\"submit();\" name=\"emphasis\">\n"

            emphasisValues = {
                Idevice.NoEmphasis: _(u"No emphasis"),
                Idevice.SomeEmphasis: _(u"Some emphasis")
            }
            for value, description in emphasisValues.items():
                html += "<option value=\"" + unicode(value) + "\" "
                if self.idevice.emphasis == value:
                    html += "selected "
                html += ">" + description + "</option>\n"

            html += "</select> \n"
            html += common.elementInstruc(self.emphasisInstruc)
            html += "<br/><br/>\n"

            if self.idevice.emphasis > 0:
                html += self.__renderStyles() + " "
                html += u'<a href="#" '
                html += u'onmousedown="Javascript:updateCoords(event);"\n'
                html += u'onclick="Javascript:showMe(\'iconpanel\', 350, 100);">'
                html += u'Select an icon:</a> \n'
                icon = self.idevice.icon
                if icon != "":
                    html += '<img align="middle" '
                    html += 'src="/style/%s/icon_%s' % (
                        self.style.get_dirname(), icon)
                    html += '.gif"/><br/>'
                html += u'<div id="iconpanel" style="display:none; z-index:99;">'
                html += u'<div style="float:right;" >\n'
                html += u'<img alt="%s" ' % _("Close")
                html += u'src="/images/stock-stop.png" title="%s"\n' % _(
                    "Close")
                html += u'onmousedown="Javascript:hideMe();"/></div><br/> \n'
                html += u'<div align="center"><b>%s:</b></div><br/>' % _(
                    "Icons")
                html += self.__renderIcons()
                html += u'</div><br/>\n'
            for element in self.elements:
                html += element.renderEdit()
        else:
            html += "<b>" + self.idevice.title + "</b><br/><br/>"
            for element in self.elements:
                html += element.renderPreview()
            if self.idevice.purpose != "" or self.idevice.tip != "":
                html += "<a title=\"" + _("Pedagogical Help") + "\" "
                html += "onmousedown=\"Javascript:updateCoords(event);\" \n"
                html += "onclick=\"Javascript:showMe('phelp', 380, 240);\" \n"
                html += "href=\"Javascript:void(0)\" style=\"cursor:help;\">\n "
                html += '<img alt="%s" src="/images/info.png" border="0" \n' % _(
                    'Info')
                html += "align=\"middle\" /></a>\n"
                html += "<div id=\"phelp\" style=\"display:none;\">\n"
                html += "<div style=\"float:right;\" "
                html += '<img alt="%s" src="/images/stock-stop.png" \n' % _(
                    'Close')
                html += " title='" + _(
                    "Close") + "' border='0' align='middle' \n"
                html += "onmousedown=\"Javascript:hideMe();\"/></div>\n"
                if self.idevice.purpose != "":
                    html += "<b>Purpose:</b><br/>%s<br/>" % self.purpose

                if self.idevice.tip != "":
                    html += "<b>Tip:</b><br/>%s<br/>" % self.idevice.tip

                html += "</div>\n"
        html += "</div>\n"
        self.message = ""

        return html

    def __renderStyles(self):
        """
        Return xhtml string for rendering styles select
        """
        html = '<select onchange="submitStyle();" name="styleSelect">\n'
        idx = 0
        for style in self.styles:
            html += "<option value='%d' " % idx
            if self.style.get_name() == style.get_name():
                html += "selected "
            html += ">" + style.get_name() + "</option>\n"
            idx = idx + 1
        html += "</select> \n"

        return html

    def __renderIcons(self):
        """
        Return xhtml string for dispay all icons
        """
        iconpath = self.style.get_style_dir()
        iconfiles = iconpath.files("icon_*")
        html = ""
        for iconfile in iconfiles:
            iconname = iconfile.namebase
            icon = iconname.split("_", 1)[1]
            filename = "/style/%s/%s.gif" % (self.style.get_dirname(),
                                             iconname)
            html += u'<div style="float:left; text-align:center; width:80px;\n'
            html += u'margin-right:10px; margin-bottom:10px" > '
            html += u'<img src="%s" \n' % filename
            html += u' alt="%s" ' % _("Submit")
            html += u"onclick=\"submitLink('selectIcon','%s',1)\">\n" % icon
            html += u'<br/>%s.gif</div>\n' % icon
        return html
class AppletIdevice(Idevice):
    """
    Java Applet Idevice. Enables you to embed java applet in the browser
    """
    persistenceVersion = 1

    def __init__(self, parentNode=None):
        """
        Sets up the idevice title and instructions etc
        """
        Idevice.__init__(self, 
                         x_(u"Java Applet"), 
                         x_(u"University of Auckland"), 
                         u"",
                         u"",
                         u"",
                             parentNode)
        self.emphasis          = Idevice.NoEmphasis
        self.appletCode        = u""
        self.type              = u"other"
        self._fileInstruc      = x_(u"""Add all the files provided for the applet
except the .txt file one at a time using the add files and upload buttons. The 
files, once loaded will be displayed beneath the Applet code field.""")
        self._codeInstruc      = x_(u""""Find the .txt file (in the applet file) 
and open it. Copy the contents of this file <ctrl A, ctrl C> into the applet 
code field.""")
        self._typeInstruc     = x_(u""" <p>If the applet you're adding was generated 
by one of the programs in this drop down, please select it, 
then add the data/applet file generated by your program. </p>
<p>eg. For Geogebra applets, select geogebra, then add the .ggb file that 
you created in Geogebra.</p>""")
        self.message          = ""
        
    # Properties    
    fileInstruc = lateTranslate('fileInstruc')
    codeInstruc = lateTranslate('codeInstruc')
    typeInstruc = lateTranslate('typeInstruc')

    def getResourcesField(self, this_resource):
        """
        implement the specific resource finding mechanism for this iDevice:
        """
        # if this_resource is listed within the iDevice's userResources, 
        # then we can assume that this_resource is indeed a valid resource, 
        # even though that has no direct field.
        # As such, merely return the resource itself, to indicate that
        # it DOES belong to this iDevice, but is not a FieldWithResources:
        if this_resource in self.userResources:
            return this_resource

        return None
       
    def getRichTextFields(self):
        """
        Like getResourcesField(), a general helper to allow nodes to search 
        through all of their fields without having to know the specifics of each
        iDevice type.  
        """
        # Applet iDevice has no rich-text fields:
        return []
        
    def burstHTML(self, i):
        """
        takes a BeautifulSoup fragment (i) and bursts its contents to 
        import this idevice from a CommonCartridge export
        """
        # Java Applet Idevice:
        #title = i.find(name='span', attrs={'class' : 'iDeviceTitle' })
        #idevice.title = title.renderContents().decode('utf-8')
        # no title for this idevice.

        # =====> WARNING: not yet loading any of the files!
        #
        # BEWARE also of the appletCode line breaks loading as <br/>,
        # may want change this back to \n or \r\n?

        # AND: also need to load the applet type: Geogebra or Other.
        inner = i.find(name='div', attrs={'class' : 'iDevice emphasis0' })
        self.appletCode= inner.renderContents().decode('utf-8')

    def uploadFile(self, filePath):
        """
        Store the upload files in the package
        Needs to be in a package to work.
        """ 
        log.debug(u"uploadFile "+unicode(filePath))
        resourceFile = Path(filePath)
        assert(self.parentNode, _('file %s has no parentNode') % self.id)
        assert(self.parentNode.package, _('iDevice %s has no package') % self.parentNode.id)
        
        if resourceFile.isfile():
            self.message = ""
            Resource(self, resourceFile)
            if self.type == "geogebra":
                self.appletCode = self.getAppletcode(resourceFile.basename())
        else:
            log.error('File %s is not a file' % resourceFile)
    
    
    def deleteFile(self, fileName):
        """
        Delete a selected file
        """
        for resource in self.userResources:
            if resource.storageName == fileName:
                resource.delete()
                break
            
    def getAppletcode(self, filename):
        """
        xhtml string for GeoGebraApplet
        """
        
        html = """
        <applet code="geogebra.GeoGebraApplet.class" archive="geogebra.jar" width="750" height="450">
            <param name="filename" value="%s">
            <param name="framePossible" value="false">
            Please <a href="http://java.sun.com/getjava"> install Java 1.4</a> (or later) to use this page.
        </applet> """ % filename
        
        return html
    
    def copyFiles(self):
        """
        if geogebra, then copy all jar files, otherwise delete all jar files.
        """
        
        for resource in reversed(self.userResources):
            resource.delete()
            
        self.appletCode = ""
        self.message = ""
        if self.type == "geogebra":
            #from exe.application import application
            from exe import globals
            ideviceDir = globals.application.config.webDir/'templates'            
            for file in GEOGEBRA_FILE_NAMES:
                filename = ideviceDir/file
                self.uploadFile(filename)
            self.appletCode = self.getAppletcode("")
            
    def upgradeToVersion1(self):
        """
        Called to upgrade to 0.23 release
        """
        self.message       = ""
        self.type          = u"other"
        self._typeInstruc  = x_(u""" <p>If the applet you're adding was generated 
by one of the programs in this drop down, please select it, 
then add the data/applet file generated by your program. </p>
<p>eg. For Geogebra applets, select geogebra, then add the .ggb file that 
you created in Geogebra.</p>""")
예제 #3
0
class CitasparapensarfpdIdevice(Idevice):
    """
    El iDevice Citas para pensar permite al alumnado reflexionar sobre algunas citas propuestas
    """
    persistenceVersion = 7

    def __init__(self, activity="", answer=""):
        """
        Initialize 
        """
        Idevice.__init__(
            self, x_(u"FPD - Citas Para Pensar"),
            x_(u"Jose Ramon Jimenez Reyes"),
            x_(u"""Citas para pensar es un iDevice que permite al alumnado reflexionar sobre algunas citas propuestas."""
               ), u"", u"citasparapensarfpd")
        #        self.emphasis = Idevice.SomeEmphasis
        self.emphasis = "_citasparapensarfpd"
        self._activityInstruc = x_(
            u"""Introduce el texto que aparecer&aacute; en este iDevice""")
        #        self.systemResources += ["common.js"]

        self.activityTextArea = TextAreaField(x_(u'Texto Citas para pensar:'),
                                              self._activityInstruc, activity)
        self.activityTextArea.idevice = self

    # Properties
    activityInstruc = lateTranslate('activityInstruc')

    def getResourcesField(self, this_resource):
        """
        implement the specific resource finding mechanism for this iDevice:
        """
        # be warned that before upgrading, this iDevice field could not exist:
        if hasattr(self, 'activityTextArea')\
        and hasattr(self.activityTextArea, 'images'):
            for this_image in self.activityTextArea.images:
                if hasattr(this_image, '_imageResource') \
                    and this_resource == this_image._imageResource:
                    return self.activityTextArea

        return None

    def getRichTextFields(self):
        fields_list = []
        if hasattr(self, 'activityTextArea'):
            fields_list.append(self.activityTextArea)

        return fields_list

    def burstHTML(self, i):
        # Citasparapensarfpd Idevice:
        title = i.find(name='span', attrs={'class': 'iDeviceTitle'})
        self.title = title.renderContents().decode('utf-8')

        reflections = i.findAll(name='div', attrs={'id': re.compile('^ta')})
        # should be exactly two of these:
        # 1st = field[0] == Activity
        if len(reflections) >= 1:
            self.activityTextArea.content_wo_resourcePaths = \
                    reflections[0].renderContents().decode('utf-8')
            # and add the LOCAL resource paths back in:
            self.activityTextArea.content_w_resourcePaths = \
                    self.activityTextArea.MassageResourceDirsIntoContent( \
                        self.activityTextArea.content_wo_resourcePaths)
            self.activityTextArea.content = \
                    self.activityTextArea.content_w_resourcePaths

    def upgradeToVersion1(self):
        """
        Upgrades the node from version 0 to 1.
        """
        log.debug(u"Upgrading iDevice")
        self.icon = u"citasparapensarfpd"

    def upgradeToVersion2(self):
        """
        Upgrades the node from 1 (v0.5) to 2 (v0.6).
        Old packages will loose their icons, but they will load.
        """
        log.debug(u"Upgrading iDevice")
        #        self.emphasis = Idevice.SomeEmphasis
        self.emphasis = "_citasparapensarfpd"

    def upgradeToVersion3(self):
        """
        Upgrades v0.6 to v0.7.
        """
        self.lastIdevice = False

    def upgradeToVersion4(self):
        """
        Upgrades to exe v0.10
        """
        self._upgradeIdeviceToVersion1()
        self._activityInstruc = self.__dict__['activityInstruc']

    def upgradeToVersion5(self):
        """
        Upgrades to exe v0.10
        """
        self._upgradeIdeviceToVersion1()

    def upgradeToVersion6(self):
        """
        Upgrades to v0.12
        """
        self._upgradeIdeviceToVersion2()
        self.systemResources += ["common.js"]

    def upgradeToVersion7(self):
        """ 
        Upgrades to somewhere before version 0.25 (post-v0.24) 
        Taking the old unicode string fields, and converting them 
        into image-enabled TextAreaFields:
        """
        self.activityTextArea = TextAreaField(x_(u'Texto para pensar:'),
                                              self._activityInstruc,
                                              self.activity)
        self.activityTextArea.idevice = self
예제 #4
0
class MultimediaIdevice(Idevice):
    """
    A Multimedia Idevice is one built up from an Multimedia file and free text.
    """

    persistenceVersion = 2

    def __init__(self, defaultMedia=None):
        Idevice.__init__(
            self, x_(u"MP3"), x_(u"Auckland University of Technology"),
            x_(u"The MP3 iDevice allows you to attach an MP3 "
               "media file to your content along with relevant textual"
               "learning instructions."), u"", u"")
        self.emphasis = Idevice.NoEmphasis
        self.media = MultimediaField(
            x_(u"Choose an MP3 file"),
            x_(u""
               "<ol>"
               "  <li>Click &lt;Select an MP3&gt; and browse to the MP3 "
               "      file you wish to insert</li>"
               " <li>Click on the dropdown menu to select the position "
               "       that you want the file displayed on screen.</li>"
               "  <li>Enter an optional caption for your file.</li>"
               " <li>Associate any relevant text to the MP3 file.</li>"
               " <li>Choose the type of style you would like the iDevice to"
               "       display e.g. 'Some emphasis' "
               "applies a border and icon to the iDevice content displayed.</li>"
               "</ol>"))
        self.media.idevice = self
        self.text = TextAreaField(
            x_(u"Text"),
            x_("""Enter the text you wish to 
associate with the file."""))
        self.text.idevice = self
        self.float = u"left"
        self.caption = u""
        self.icon = u"multimedia"
        self._captionInstruc = x_(u"""Provide a caption for the 
MP3 file. This will appear in the players title bar as well.""")

        self._alignInstruc = x_(u"""Alignment allows you to 
choose where on the screen the media player will be positioned.""")
        self.systemResources += ['xspf_player.swf']

    # Properties
    captionInstruc = lateTranslate('captionInstruc')
    alignInstruc = lateTranslate('alignInstruc')

    def getResourcesField(self, this_resource):
        """
        implement the specific resource finding mechanism for this iDevice:
        """
        # be warned that before upgrading, this iDevice field could not exist:
        if hasattr(self, 'media') and hasattr(self.media, 'mediaResource'):
            if this_resource == self.media.mediaResource:
                return self.media

        # be warned that before upgrading, this iDevice field could not exist:
        if hasattr(self, 'text') and hasattr(self.text, 'images'):
            for this_image in self.text.images:
                if hasattr(this_image, '_imageResource') \
                and this_resource == this_image._imageResource:
                    return self.text

        return None

    def getRichTextFields(self):
        """
        Like getResourcesField(), a general helper to allow nodes to search 
        through all of their fields without having to know the specifics of each
        iDevice type.  
        """
        fields_list = []
        if hasattr(self, 'text'):
            fields_list.append(self.text)
        return fields_list

    def upgradeToVersion2(self):
        """
        (We skipped version 1 by accident)
        Upgrades to 0.22
        """
        self.systemResources += ['xspf_player.swf']
예제 #5
0
class ImageWithTextIdevice(Idevice):
    """
    A ImageWithText Idevice is one built up from an image and free text.
    """
    persistenceVersion = 9

    def __init__(self, defaultImage = None):
        Idevice.__init__(self, 
                         x_(u"Image with Text"), 
                         x_(u"University of Auckland"), 
                         x_(u"""<p>
The image with text iDevice can be used in a number of ways to support both
the emotional (affective) and learning task (cognitive) dimensions of eXe
content. 
</p><p>
<b>Integrating visuals with verbal summaries</b>
</p><p>
Cognitive psychologists indicate that presenting learners with a
representative image and corresponding verbal summary (that is presented
simultaneously) can reduce cognitive load and enhance learning retention.
This iDevice can be used to present an image (photograph, diagram or
graphic) with a brief verbal summary covering the main points relating to
the image. For example, if you were teaching the functions of a four-stroke
combustion engine, you could have a visual for each of the four positions of
the piston with a brief textual summary of the key aspects of each visual.
</p>"""), u"", u"")
        self.emphasis           = Idevice.NoEmphasis
        self.group              = Idevice.Media
        self.image              = ImageField(x_(u"Image"), u"")
        self.image.idevice      = self
        self.image.defaultImage = defaultImage
        self.text               = TextAreaField(x_(u"Text"),
                                                x_("""Enter the text you wish to 
                                                associate with the image."""))
        self.text.idevice       = self
        self.float              = u"left"
        self.caption            = u""
        self._captionInstruc    = x_(u"""Provide a caption for the image 
you have just inserted.""")

    # Properties
    captionInstruc = lateTranslate('captionInstruc')
    
    def upgradeToVersion1(self):
        """
        Called to upgrade from 0.5 release
        """
        self.float = u"left"
       

    def upgradeToVersion2(self):
        """
        Called to upgrade from 0.6 release
        """
        self.caption  = u""
        self.emphasis = Idevice.NoEmphasis
        

    def upgradeToVersion3(self):
        """
        Upgrades v0.6 to v0.7.
        """
        self.lastIdevice = False

        
    def upgradeToVersion4(self):
        """
        Upgrades to exe v0.10
        """
        self._upgradeIdeviceToVersion1()


    def upgradeToVersion5(self):
        """
        Upgrades to v0.12
        """
        log.debug("upgrade to version 5")
        self._upgradeIdeviceToVersion2()        
        self.image._upgradeFieldToVersion2()
        
    def upgradeToVersion6(self):
        """
        Called to upgrade from 0.13 release
        """
        self._captionInstruc  = x_(u"""Provide a caption for the image 
you have just inserted.""")

    def upgradeToVersion7(self):
        """
        Called to upgrade to version 0.24
        """
        self.image.isFeedback = False

    def upgradeToVersion8(self):
        """
        Converting ImageWithTextIdevice -> FreeTextIdevice,
        now that FreeText can hold embeddded images.

        BUT - due to the inconsistent loading of the objects via unpickling,
        since the resources aren't necessarily properly loaded and upgraded,
        NOR is the package necessarily, as it might not even have a list of
        resources yet, all of this conversion code must be done in an
        afterUpgradeHandler
        """ 
        G.application.afterUpgradeHandlers.append(self.convertToFreeText)


    def upgradeToVersion9(self):
        """
        Adds group to idevice
        """
        self.group = Idevice.Media
 

    def convertToFreeText(self):
        """
        Actually do the Converting of 
              ImageWithTextIdevice -> FreeTextIdevice,
        now that FreeText can hold embeddded images.
        """
        new_content = ""

        # ensure that an image resource still exists on this ImageWithText,
        # before trying to add it into the FreeText idevice.
        # Why?  corrupt packages have been seen missing resources...
        # (usually in with extra package objects as well, probably
        # from old code doing faulty Extracts, or somesuch nonesense)
        imageResource_exists = False
        if self.image.imageResource:
            # also ensure that it has the correct md5 checksum, since there was 
            # a period in which resource checksums were being created before
            # the resource zip file was fully closed, and not flushed out:
            self.image.imageResource.checksumCheck()

            if os.path.exists(self.image.imageResource.path) and \
            os.path.isfile(self.image.imageResource.path): 
                imageResource_exists = True
            else:
                log.warn("Couldn't find ImageWithText image when upgrading "\
                        + self.image.imageResource.storageName)

        if imageResource_exists:
            new_content += "<img src=\"resources/" \
                    + self.image.imageResource.storageName + "\" " 
            if self.image.height:
                new_content += "height=\"" + self.image.height + "\" " 
            if self.image.width:
                new_content += "width=\"" + self.image.width + "\" " 
            new_content += "/> \n"
        elif self.image.imageResource:
            new_content += "<BR>\n[WARNING: missing image: " \
                    + self.image.imageResource.storageName + "]\n"


        if self.caption != "": 
            new_content += "<BR>\n[" + self.caption + "]\n"

        if self.text.content != "": 
            new_content += "<P>\n" + self.text.content + "\n"
        # note: this is given a text field which itself did NOT yet have
        # any embedded media! easier, eh?

        replacementIdev = FreeTextIdevice(new_content)


        ###########
        # now, copy that content field's content into its _w_resourcePaths,
        # and properly remove the resource directory via Massage....
        # for its _wo_resourcePaths:
        # note that replacementIdev's content field's content 
        # is automatically set at its constructor (above),
        # as is the default content_w_resourcePaths (a copy of content)
        # AND the default content_wo_resourcePaths (a copy of content),
        # so only need to update the content_wo_resourcePaths:
        replacementIdev.content.content_wo_resourcePaths = \
                replacementIdev.content.MassageContentForRenderView( \
                    replacementIdev.content.content_w_resourcePaths)
        # Design note: ahhhhh, the above is a good looking reason to possibly
        # have the MassageContentForRenderView() method
        # just assume its content_w_resourcePaths as the input
        # and write the output to its content_wo_resourcePaths.....
        #######
        
        # next step, add the new IDevice into the same node as this one
        self.parentNode.addIdevice(replacementIdev)
        
        # in passing GalleryImage into the FieldWithResources, 
        # that content field needs to be sure to have an updated 
        # parentNode, courtesy of its idevice: 
        replacementIdev.content.setParentNode()

        # and semi-manually add/create the current image
        # resource into the FreeTextIdevice's TextAreaField, content.
        # the content text will have already been taken care of above,
        # including the ideal <img src=...> including resources path,
        # but still need the actual image resource:
        
        if imageResource_exists:
            # Not sure why this can't be imported up top, but it gives 
            # ImportError: cannot import name GalleryImages, 
            # so here it be: 
            from exe.engine.galleryidevice  import GalleryImage 
            
            full_image_path = self.image.imageResource.path
            new_GalleryImage = GalleryImage(replacementIdev.content, \
                    self.caption,  full_image_path, mkThumbnail=False)

        # and move it up to the position following this node!
        while ( self.parentNode.idevices.index(replacementIdev) \
                > ( (self.parentNode.idevices.index(self) + 1))):
            replacementIdev.movePrev()

        # finally: delete THIS idevice itself, deleting it from the node
        self.delete()

   
    def getResourcesField(self, this_resource):
        """
        implement the specific resource finding mechanism for this iDevice:
        """
        # be warned that before upgrading, this iDevice field could not exist:
        if hasattr(self, 'image') and hasattr(self.image, 'imageResource'):
            if this_resource == self.image.imageResource:
                return self.image

        # be warned that before upgrading, this iDevice field could not exist:
        if hasattr(self, 'text') and hasattr(self.text, 'images'):
            for this_image in self.text.images:
                if hasattr(this_image, '_imageResource') \
                and this_resource == this_image._imageResource:
                    return self.text

        return None
       

    def getRichTextFields(self):
        """
        Like getResourcesField(), a general helper to allow nodes to search 
        through all of their fields without having to know the specifics of each
        iDevice type.  
        """
        fields_list = []
        if hasattr(self, 'text'):
            fields_list.append(self.text)

        return fields_list
예제 #6
0
class ImageMagnifierIdevice(Idevice):
    """
    A ImageMagnifier Idevice is one built up from an image and free text.
    """

    persistenceVersion = 3

    def __init__(self, defaultImage=None):
        Idevice.__init__(
            self, x_(u"Image Magnifier"), x_(u"University of Auckland"),
            x_(u"""The image magnifier is a magnifying tool enabling
 learners to magnify the view of the image they have been given. Moving the 
magnifying glass over the image allows larger detail to be studied."""), u"",
            u"")
        self.emphasis = Idevice.NoEmphasis
        self.group = Idevice.Media
        self.imageMagnifier = MagnifierField(
            x_(u"Choose an Image"),
            x_(u"""Click 
on the picture below or the "Add Image" button to select an image file to be 
magnified."""))
        self.imageMagnifier.idevice = self
        self.imageMagnifier.defaultImage = defaultImage
        self.text = TextAreaField(
            x_(u"Text"),
            x_("""Enter the text you wish to 
associate with the file."""))
        self.text.idevice = self
        self.float = u"left"
        self.caption = u""
        self._captionInstruc = x_(u"""Provide a caption for the 
image to be magnified.""")
        self._dimensionInstruc = x_(u"""Choose the size you want 
your image to display at. The measurements are in pixels. Generally, 100 
pixels equals approximately 3cm. Leave both fields blank if you want the 
image to display at its original size.""")
        self._alignInstruc = x_(u"""Alignment allows you to 
choose where on the screen the image will be positioned.""")
        self._initialZoomInstruc = x_(u"""Set the initial level of zoom 
when the IDevice loads, as a percentage of the original image size""")
        self._maxZoomInstruc = x_(u"""Set the maximum level of zoom, 
as a percentage of the original image size""")
        self._glassSizeInstruc = x_(
            u"""Select the size of the magnifying glass""")
        self.systemResources += ['magnifier.swf']

    # Properties
    captionInstruc = lateTranslate('captionInstruc')
    dimensionInstruc = lateTranslate('dimensionInstruc')
    alignInstruc = lateTranslate('alignInstruc')
    initialZoomInstruc = lateTranslate('initialZoomInstruc')
    maxZoomInstruc = lateTranslate('maxZoomInstruc')
    glassSizeInstruc = lateTranslate('glassSizeInstruc')

    def getResourcesField(self, this_resource):
        """
        implement the specific resource finding mechanism for this iDevice:
        """
        # be warned that before upgrading, this iDevice field could not exist:
        if hasattr(self, 'imageMagnifier')\
        and hasattr(self.imageMagnifier, 'imageResource'):
            if this_resource == self.imageMagnifier.imageResource:
                return self.imageMagnifier

        # be warned that before upgrading, this iDevice field could not exist:
        if hasattr(self, 'text') and hasattr(self.text, 'images'):
            for this_image in self.text.images:
                if hasattr(this_image, '_imageResource') \
                and this_resource == this_image._imageResource:
                    return self.text

        return None

    def getRichTextFields(self):
        """
        Like getResourcesField(), a general helper to allow nodes to search 
        through all of their fields without having to know the specifics of each
        iDevice type.  
        """
        fields_list = []
        if hasattr(self, 'text'):
            fields_list.append(self.text)

        return fields_list

    def burstHTML(self, i):
        """
        takes a BeautifulSoup fragment (i) and bursts its contents to 
        import this idevice from a CommonCartridge export
        """
        # ImageMagnifier Idevice:
        #======> WARNING - NOT YET BURSTING!!!!!!!!

        #title = i.find(name='span', attrs={'class' : 'iDeviceTitle' })
        #idevice.title = title.renderContents().decode('utf-8')
        # no title for this idevice
        # WARNING: not yet loading the image or its parameters:
        # Could be in the following tag:
        # <param name="FlashVars" \
        #   value="glassSize=2&height=189&width=267 \
        #   &initialZoomSize=100&file=sunflowers.jpg \
        #   &maxZoomSize=150&targetColor=#FF0000&borderWidth=12

        #inner = i.find(name='div', attrs={'class' : 'iDevice_inner' })
        #idevice.fields[0].content = inner.renderContents().decode('utf-8')
        #idevice.fields[0].content_w_resourcePaths = inner.renderContents().decode('utf-8')
        #idevice.fields[0].content_wo_resourcePaths = inner.renderContents().decode('utf-8')

    def upgradeToVersion1(self):
        """
        Upgrades to v0.14
        """
        self._alignInstruc = x_(u"""Alignment allows you to 
choose where on the screen the image will be positioned.""")
        self._initialZoomInstruc = x_(u"""Set the initial level of zoom 
when the IDevice loads, as a percentage of the original image size""")
        self._maxZoomInstruc = x_(u"""Set the maximum level of zoom, 
as a percentage of the original image size""")
        self._glassSizeInstruc = x_(u"""This chooses the initial size 
of the magnifying glass""")

    def upgradeToVersion2(self):
        """
        Upgrades to v0.24
        """
        self.imageMagnifier.isDefaultImage = False

    def upgradeToVersion3(self):
        """
        Adds group to idevice
        """
        self.group = Idevice.Media
예제 #7
0
class ExternalUrlIdevice(Idevice):
    """
    ExternalUrlIdevice: just has a field for the url
    """
    persistenceVersion = 3

    def __init__(self, content=""):
        Idevice.__init__(
            self, x_(u"External Web Site"), x_(u"University of Auckland"),
            x_(u"""The external website iDevice loads an external website 
into an inline frame in your eXe content rather then opening it in a popup box. 
This means learners are not having to juggle windows. 
This iDevice should only be used if your content 
will be viewed by learners online."""), "", "")
        self.emphasis = Idevice.NoEmphasis
        self.url = ""
        self.height = "300"

        self._urlInstruc = x_(u"""Enter the URL you wish to display
and select the size of the area to display it in.""")

        #Properties

    urlInstruc = lateTranslate('urlInstruc')

    def getResourcesField(self, this_resource):
        """
        implement the specific resource finding mechanism for this iDevice:
        """
        # NOTE that the ExternalURL iDevice has NO additional resources:
        return None

    def getRichTextFields(self):
        """
        Like getResourcesField(), a general helper to allow nodes to search 
        through all of its fields without having to know the specifics of each 
        iDevice type.  
        """
        # ExternalURL has no rich-text fields:
        return []

    def burstHTML(self, i):
        """
        takes a BeautifulSoup fragment (i) and bursts its contents to 
        import this idevice from a CommonCartridge export
        """
        # External Web Site Idevice:
        #title = i.find(name='span', attrs={'class' : 'iDeviceTitle' })
        #idevice.title = title.renderContents().decode('utf-8')
        # no title for this iDevice.

        inner = i.find(name='iframe').__str__()
        # 1. the url: <iframe src="HERE" ... ></iframe>
        url_start_pos = inner.find('src=\"')
        if url_start_pos >= 0:
            url_start_pos += len('src=\"')
            url_end_pos = inner.find('\"', url_start_pos)
            if url_end_pos >= url_start_pos:
                self.url = inner[url_start_pos:url_end_pos].decode('utf-8')

        # 2. the height: <iframe height="###px" ... ></iframe>
        height_start_pos = inner.find('height=\"')
        if height_start_pos >= 0:
            height_start_pos += len('height=\"')
            height_end_pos = inner.find('px\"', height_start_pos)
            if height_end_pos >= height_start_pos:
                self.height = \
                    inner[height_start_pos : height_end_pos].decode('utf-8')

    def upgradeToVersion1(self):
        """
        Upgrades exe to v0.10
        """
        self._upgradeIdeviceToVersion1()

    def upgradeToVersion2(self):
        """
        Upgrades to v0.12
        """
        self._upgradeIdeviceToVersion2()

    def upgradeToVersion3(self):
        """
        add _urlInstruc
        """
        self._urlInstruc = x_(u"""Enter the URL you wish to display
and select the size of the area to display it in.""")
예제 #8
0
class ReflectionfpdIdevice(Idevice):
    """
    A Reflection Idevice presents question/s for the student to think about
    before they look at the answer/s
    """
    persistenceVersion = 7

    def __init__(self, activity="", answer=""):
        """
        Initialize 
        """
        Idevice.__init__(
            self, x_(u"FPD - Reflexiona (con Retroalimentacion)"),
            x_(u"University of Auckland"),
            x_(u"""Reflection is a teaching method often used to 
connect theory to practice. Reflection tasks often provide learners with an 
opportunity to observe and reflect on their observations before presenting 
these as a piece of academic work. Journals, diaries, profiles and portfolios 
are useful tools for collecting observation data. Rubrics and guides can be 
effective feedback tools."""), u"", u"reflexionfpd")
        #        self.emphasis         = Idevice.SomeEmphasis
        self.emphasis = "_reflexionfpd"
        self._activityInstruc = x_(u"""Enter a question for learners 
to reflect upon.""")
        self._answerInstruc = x_(u"""Describe how learners will assess how 
they have done in the exercise. (Rubrics are useful devices for providing 
reflective feedback.)""")
        self.systemResources += ["common.js"]

        self.activityTextArea = TextAreaField(x_(u'Reflective question:'),
                                              self._activityInstruc, activity)
        self.activityTextArea.idevice = self

        self.answerTextArea = TextAreaField(x_(u'Feedback:'),
                                            self._answerInstruc, answer)
        self.answerTextArea.idevice = self

    # Properties
    activityInstruc = lateTranslate('activityInstruc')
    answerInstruc = lateTranslate('answerInstruc')

    def getResourcesField(self, this_resource):
        """
        implement the specific resource finding mechanism for this iDevice:
        """
        # be warned that before upgrading, this iDevice field could not exist:
        if hasattr(self, 'activityTextArea')\
        and hasattr(self.activityTextArea, 'images'):
            for this_image in self.activityTextArea.images:
                if hasattr(this_image, '_imageResource') \
                    and this_resource == this_image._imageResource:
                    return self.activityTextArea

        # be warned that before upgrading, this iDevice field could not exist:
        if hasattr(self, 'answerTextArea')\
        and hasattr(self.answerTextArea, 'images'):
            for this_image in self.answerTextArea.images:
                if hasattr(this_image, '_imageResource') \
                    and this_resource == this_image._imageResource:
                    return self.answerTextArea

        return None

    def getRichTextFields(self):
        """
        Like getResourcesField(), a general helper to allow nodes to search 
        through all of their fields without having to know the specifics of each
        iDevice type.  
        """
        fields_list = []
        if hasattr(self, 'activityTextArea'):
            fields_list.append(self.activityTextArea)
        if hasattr(self, 'answerTextArea'):
            fields_list.append(self.answerTextArea)

        return fields_list

    def burstHTML(self, i):
        """
        takes a BeautifulSoup fragment (i) and bursts its contents to 
        import this idevice from a CommonCartridge export
        """
        # Reflection Idevice:
        title = i.find(name='span', attrs={'class': 'iDeviceTitle'})
        self.title = title.renderContents().decode('utf-8')

        reflections = i.findAll(name='div', attrs={'id': re.compile('^ta')})
        # should be exactly two of these:
        # 1st = field[0] == Activity
        if len(reflections) >= 1:
            self.activityTextArea.content_wo_resourcePaths = \
                    reflections[0].renderContents().decode('utf-8')
            # and add the LOCAL resource paths back in:
            self.activityTextArea.content_w_resourcePaths = \
                    self.activityTextArea.MassageResourceDirsIntoContent( \
                        self.activityTextArea.content_wo_resourcePaths)
            self.activityTextArea.content = \
                    self.activityTextArea.content_w_resourcePaths
        # 2nd = field[1] == Answer
        if len(reflections) >= 2:
            self.answerTextArea.content_wo_resourcePaths = \
                    reflections[1].renderContents().decode('utf-8')
            # and add the LOCAL resource paths back in:
            self.answerTextArea.content_w_resourcePaths = \
                    self.answerTextArea.MassageResourceDirsIntoContent( \
                        self.answerTextArea.content_wo_resourcePaths)
            self.answerTextArea.content = \
                    self.answerTextArea.content_w_resourcePaths

    def upgradeToVersion1(self):
        """
        Upgrades the node from version 0 to 1.
        """
        log.debug(u"Upgrading iDevice")
        self.icon = u"reflexionfpd"

    def upgradeToVersion2(self):
        """
        Upgrades the node from 1 (v0.5) to 2 (v0.6).
        Old packages will loose their icons, but they will load.
        """
        log.debug(u"Upgrading iDevice")
        #        self.emphasis         = Idevice.SomeEmphasis
        self.emphasis = "_reflexionfpd"

    def upgradeToVersion3(self):
        """
        Upgrades v0.6 to v0.7.
        """
        self.lastIdevice = False

    def upgradeToVersion4(self):
        """
        Upgrades to exe v0.10
        """
        self._upgradeIdeviceToVersion1()
        self._activityInstruc = self.__dict__['activityInstruc']
        self._answerInstruc = self.__dict__['answerInstruc']

    def upgradeToVersion5(self):
        """
        Upgrades to exe v0.10
        """
        self._upgradeIdeviceToVersion1()

    def upgradeToVersion6(self):
        """
        Upgrades to v0.12
        """
        self._upgradeIdeviceToVersion2()
        self.systemResources += ["common.js"]

    def upgradeToVersion7(self):
        """ 
        Upgrades to somewhere before version 0.25 (post-v0.24) 
        Taking the old unicode string fields, and converting them 
        into image-enabled TextAreaFields:
        """
        self.activityTextArea = TextAreaField(x_(u'Reflective question:'),
                                              self._activityInstruc,
                                              self.activity)
        self.activityTextArea.idevice = self
        self.answerTextArea = TextAreaField(x_(u'Feedback:'),
                                            self._answerInstruc, self.answer)
        self.answerTextArea.idevice = self
예제 #9
0
class MultichoiceIdevice(Idevice):
    """
    A multichoice Idevice is one built up from question and options
    """
    persistenceVersion = 7

    def __init__(self, question=""):
        """
        Initialize 
        """
        Idevice.__init__(self,
                         x_(u"Multi-choice"),
                         x_(u"University of Auckland"),
                         x_(u"""Although more often used in formal testing 
situations MCQs can be used as a testing tool to stimulate thought and  
discussion on topics students may feel a little reticent in responding to. 

When designing a MCQ test consider the following:
<ul>
<li> What learning outcomes are the questions testing</li>
<li>    What intellectual skills are being tested</li>
<li> What are the language skills of the audience</li>
<li> Gender and cultural issues</li>
<li> Avoid grammar language and question structures that might provide 
     clues</li>
</ul>
 """), x_(u"""When building an MCQ consider the following: <ul>
<li> Use phrases that learners are familiar with and have 
encountered in their study </li>
<li> Keep responses concise </li>
<li> There should be some consistency between the stem and the responses </li>
<li> Provide enough options to challenge learners to think about their response
</li>
<li> Try to make sure that correct responses are not more detailed than the 
distractors </li>
<li> Distractors should be incorrect but plausible </li>
</ul>
"""), u"question")
        self.emphasis         = Idevice.SomeEmphasis
        self.questions        = []
        self.options          = []


        # question and hint appear to be left over, and no longer applicable,
        # since they are now on a per-question basis, and part of the child
        # QuizQuestionField, but here their old attributes remain:
        self.question         = ""
        self.hint             = ""
        # eventually: somebody should confirm this and remove them, will you?

        self._hintInstruc     = x_(u"""Enter a hint here. If you
do not want to provide a hint, leave this field blank.""")
        self._questionInstruc      = x_(u"""Enter the question stem. 
The quest should be clear and unambiguous. Avoid negative premises 
as these can tend to be ambiguous.""")
        self._keyInstruc      = x_(u"""Select the correct option by clicking 
on the radio button.""")
        self._answerInstruc   = x_(u"""Enter the available choices here. 
You can add options by clicking the "Add Another Option" button. Delete options 
by clicking the red "X" next to the Option.""")
        self._feedbackInstruc = x_(u"""Type in the feedback that you want the 
student to see when selecting the particular option. If you don't complete this 
box, eXe will automatically provide default feedback as follows: "Correct 
answer" as indicated by the selection for the correct answer; or "Wrong answer"
for the other options.""")
        self.systemResources += ["common.js", "libot_drag.js",
                                 "panel-amusements.png", "stock-stop.png"]
        self.message          = ""

        self.addQuestion()

    # Properties
    hintInstruc     = lateTranslate('hintInstruc')
    questionInstruc = lateTranslate('questionInstruc')
    keyInstruc      = lateTranslate('keyInstruc')
    answerInstruc   = lateTranslate('answerInstruc')
    feedbackInstruc = lateTranslate('feedbackInstruc')

        
    def addQuestion(self):
        """
        Add a new question to this iDevice. 
        """
        question = QuizQuestionField(self, x_(u'Question'))
        question.addOption()
        self.questions.append(question)


    def getResourcesField(self, this_resource):
        """
        implement the specific resource finding mechanism for this iDevice:
        """
        for this_question in self.questions:
            this_field = this_question.getResourcesField(this_resource)
            if this_field is not None:
                return this_field

        return None

    def getRichTextFields(self):
        """
        Like getResourcesField(), a general helper to allow nodes to search 
        through all of their fields without having to know the specifics of each
        iDevice type.  
        """
        fields_list = []

        for this_question in self.questions:
            fields_list.extend(this_question.getRichTextFields())

        return fields_list

    def burstHTML(self, i):
        """
        takes a BeautifulSoup fragment (i) and bursts its contents to 
        import this idevice from a CommonCartridge export
        """
        # Multi-choice Idevice:
        title = i.find(name='h2', attrs={'class' : 'iDeviceTitle' })
        self.title = title.renderContents().decode('utf-8')

        inner = i.find(name='div', attrs={'class' : 'iDevice_inner' })
        # copied and modified from CaseStudy:

        mc_questions = inner.findAll(name='div', attrs={'class' : 'question'})
        if len(mc_questions) < 1:
            # need to remove the default 1st question
            del self.questions[0]

        for question_num in range(len(mc_questions)):
            if question_num > 0:
                # only created with the first question, add others:
                self.addQuestion()

            question = mc_questions[question_num]

            questions = question.findAll(name='div', 
                    attrs={'class' : 'block' , 
                    'id' : re.compile('^taquestion') })
            if len(questions) == 1:
                # ELSE: should warn of unexpected result!
                inner_question = questions[0]
                self.questions[question_num].questionTextArea.content_wo_resourcePaths \
                        = inner_question.renderContents().decode('utf-8')
                # and add the LOCAL resource paths back in:
                self.questions[question_num].questionTextArea.content_w_resourcePaths \
                        = self.questions[question_num].questionTextArea.MassageResourceDirsIntoContent( \
                            self.questions[question_num].questionTextArea.content_wo_resourcePaths)
                self.questions[question_num].questionTextArea.content = \
                        self.questions[question_num].questionTextArea.content_w_resourcePaths


            hints = question.findAll(name='div', 
                    attrs={'class' : 'block' , 'id' : re.compile('^tahint') })
            if len(hints) == 1:
                # no warning otherwise, since hint is optional
                inner_hint = hints[0]
                self.questions[question_num].hintTextArea.content_wo_resourcePaths \
                        = inner_hint.renderContents().decode('utf-8')
                # and add the LOCAL resource paths back in:
                self.questions[question_num].hintTextArea.content_w_resourcePaths \
                        = self.questions[question_num].hintTextArea.MassageResourceDirsIntoContent( \
                            self.questions[question_num].hintTextArea.content_wo_resourcePaths)
                self.questions[question_num].hintTextArea.content = \
                        self.questions[question_num].hintTextArea.content_w_resourcePaths
            else:
                self.questions[question_num].hintTextArea.content = ""
                self.questions[question_num].hintTextArea.content_w_resourcePaths \
                        = ""
                self.questions[question_num].hintTextArea.content_wo_resourcePaths \
                        = ""
            options = question.findAll(name='div', 
                    attrs={'class' : 'block' , 'id' : re.compile('^taans') })
            feedbacks = question.findAll(name='div', 
                    attrs={'id' : re.compile('^sa') })
            # the feedbacks now have the correctness
            # of the option embedded as well, in the even_steven :-)
            #####
            # NOTE also that feedbacks will just have Correct or Wrong
            # (perhaps translated? but no divs, that's the important part!)
            # but if one was defined, it will appear in a div such as:
            # <div id="taf18_5" class="block" style="display:block">FB</div> 
            if len(options) < 1:
                # need to remove the default 1st option
                del self.questions[question_num].options[0]

            for option_loop in range(0, len(options)):
                if option_loop >= 1:
                    # more options than created by default:
                    self.questions[question_num].addOption()

                self.questions[question_num].options[option_loop].answerTextArea.content_wo_resourcePaths \
                        = options[option_loop].renderContents().decode('utf-8')
                # and add the LOCAL resource paths back in:
                self.questions[question_num].options[option_loop].answerTextArea.content_w_resourcePaths \
                        = self.questions[question_num].options[option_loop].answerTextArea.MassageResourceDirsIntoContent( \
                            self.questions[question_num].options[option_loop].answerTextArea.content_wo_resourcePaths)
                self.questions[question_num].options[option_loop].answerTextArea.content \
                        = self.questions[question_num].options[option_loop].answerTextArea.content_w_resourcePaths

                inner_feedback = feedbacks[option_loop].find(name='div', 
                        id=re.compile('^taf')) 
                if inner_feedback:
                    self.questions[question_num].options[option_loop].feedbackTextArea.content_wo_resourcePaths \
                            = inner_feedback.renderContents().decode('utf-8')
                    # and add the LOCAL resource paths back in:
                    self.questions[question_num].options[option_loop].feedbackTextArea.content_w_resourcePaths \
                            = self.questions[question_num].options[option_loop].feedbackTextArea.MassageResourceDirsIntoContent( \
                                self.questions[question_num].options[option_loop].feedbackTextArea.content_wo_resourcePaths)
                    self.questions[question_num].options[option_loop].feedbackTextArea.content \
                            = self.questions[question_num].options[option_loop].feedbackTextArea.content_w_resourcePaths
                else:
                    # no user-defined feedback, just using the default:
                    self.questions[question_num].options[option_loop].feedbackTextArea.content \
                            = ""
                    self.questions[question_num].options[option_loop].feedbackTextArea.content_w_resourcePaths \
                            = ""
                    self.questions[question_num].options[option_loop].feedbackTextArea.content_wo_resourcePaths \
                            = ""

                # and finally, see if this is a correct answer:
                even_score = int(feedbacks[option_loop].attrMap['even_steven'])
                if not (even_score % 2):
                    # i.e., if it IS even, then this is correct:
                    self.questions[question_num].options[option_loop].isCorrect \
                            = True

                            


    def upgradeToVersion1(self):
        """
        Called to upgrade from 0.4 release
        """
        self.hint  = ""
        self.icon  = "multichoice"
        self.__dict__['hintInstruc'] = \
                     x_(u"Enter a hint here. If you do not want to provide a "
                        u"hint, leave this field blank.")


    def upgradeToVersion2(self):
        """
        Upgrades the node from 1 (v0.5) to 2 (v0.6).
        Old packages will loose their icons, but they will load.
        """
        log.debug(u"Upgrading iDevice")
        self.emphasis = Idevice.SomeEmphasis

    
    def upgradeToVersion3(self):
        """
        Upgrades the node from 1 (v0.6) to 2 (v0.7).
        Change icon from 'multichoice' to 'question'
        """
        log.debug(u"Upgrading iDevice icon")
        self.icon = "question"

        
    def upgradeToVersion4(self):
        """
        Upgrades v0.6 to v0.7.
        """
        self.lastIdevice = False


    def upgradeToVersion5(self):
        """
        Upgrades to exe v0.10
        """
        self._upgradeIdeviceToVersion1()
        self._hintInstruc     = self.__dict__['hintInstruc']
        self._questionInstruc = self.__dict__['questionInstruc']
        self._keyInstruc      = self.__dict__['keyInstruc']
        self._answerInstruc   = self.__dict__['answerInstruc']
        self._feedbackInstruc = self.__dict__['feedbackInstruc']


    def upgradeToVersion6(self):
        """
        Upgrades to v0.12
        """
        self._upgradeIdeviceToVersion2()
        self.systemResources += ["common.js", "libot_drag.js",
                                 "panel-amusements.png", "stock-stop.png"]
        
    def upgradeToVersion7(self):
        """
        Upgrades to v0.19
        """
        self.questions = []
        length = len(self.options)
        if length >0:
            self.addQuestion()
            self.questions[0].hint = self.hint
            self.questions[0].question = self.question
            
            for i in range(1, length):
                self.questions[0].addOption()
                i += 1
            for i in range(0, length):
                self.questions[0].options[i].answer    = self.options[i].answer
                self.questions[0].options[i].feedback  = self.options[i].feedback
                self.questions[0].options[i].isCorrect = self.options[i].isCorrect
                self.questions[0].options[i].question  = self.questions[0]
                self.questions[0].options[i].idevice   = self
                i += 1
 
            self.question = ""
            self.options  = []
            self.hint     = ""

    def upgradeTo8SafetyCheck(self):
        """
        Handles the post-upgrade issues which require all of its child objects
        to have already been upgraded, not just this multichoiceidevice itself.
        But this is essentially a missing upgradeToVersion8 (as described in,
        and called by, its TwistedRePersist, to follow)
        """
        if not hasattr(self, 'questions'):
            # not sure why it wouldn't even have this, but define it:
            self.questions        = []
        if len(self.questions) == 0:
            # no question defined yet, nothing to upgrade there:
            return
        if not hasattr(self.questions[0], 'question'):
            # does NOT have a self.questions[0].question anymore 
            # -> already new enough. 
            return

        if (self.questions[0].question != 
                self.questions[0].questionTextArea.content):
            # .question is the original pre-upgrade string,
            # and .questionTextArea has been created to hold its content,
            # but is now created as the latest persistenceVersion,==1.
            # Therefore the actual data was not yet properly migrated
            # from .question to .questionTextArea, and this is caused by
            # forcing the upgrade call that we know to be needed:
            self.questions[0].upgradeToVersion1()

            # next up, ensure that each options has been properly upgraded:
            length = len(self.questions[0].options)
            if length >0:
                for i in range(0, length):
                    # note that even though it is an older multichoice,
                    # newer options could have been added, which might
                    # not have the .answer or .feedback:
                    if hasattr(self.questions[0].options[i], 'answer'):
                        # from the original self.options[i].answer
                        if (self.questions[0].options[i].answer != 
                            self.questions[0].options[i].answerTextArea): 
                            # As with .question -> .questionTextArea, .answer 
                            # was not yet properly migrated to .answerTextArea,
                            # and this is caused by forcing the upgrade call 
                            # that we know to be needed:
                            self.questions[0].options[i].upgradeToVersion1() 
                        # finally, delete the old answer: 
                        del self.questions[0].options[i].answer
                    if hasattr(self.questions[0].options[i], 'feedback'): 
                        # and finally, delete the old feedback: 
                        del self.questions[0].options[i].feedback

        # finally, delete the old question and hint:
        if hasattr(self.questions[0], 'question'):
            del self.questions[0].question
        if hasattr(self.questions[0], 'hint'):
            del self.questions[0].hint

    def TwistedRePersist(self):
        """
        Handles any post-upgrade issues 
        (such as typically re-persisting non-persistent data)
        In this case, this is to handle a MultiChoiceIdevice Upgrade case
        that slipped between the cracks....
        """
        # A missing upgrade path should have been implemented as 
        #    upgradeToVersion8
        # but it's now too late to put in a version8,
        # primarily because we have frozen our persistence versions:
        # as of v1.00, so that all >= v1.00 elps are compatible.

        # But rather than doing the missing upgrade right here, 
        # after multichoiceidevice itself has gone through its other upgrades,
        # we need to ensure that all of its related objects have also gone
        # through their upgrades.
        # So, put this as an afterUpgradeHandler:
        G.application.afterUpgradeHandlers.append(self.upgradeTo8SafetyCheck)
예제 #10
0
class EditorPane(object):
    """
    The EditorPane is responsible for creating new idevice
    """
    def __init__(self, webServer, parent):
        """
        Initialize
        JR: anado parente para poder acceder a algunos atributos de editorpag, en concreto a showHide
        """
        self.ideviceStore = webServer.application.ideviceStore
        self.webDir = webServer.application.config.webDir
        self.styles = webServer.application.config.styleStore.getStyles()
        self.elements = []
        self.idevice = GenericIdevice("", "", "", "", "")
        self.idevice.id = self.ideviceStore.getNewIdeviceId()
        self.originalIdevice = GenericIdevice("", "", "", "", "")
        self.purpose = ""
        self.tip = ""
        self.message = ""
        self.parent = parent
        self._nameInstruc     = \
           x_(u"Your new iDevice will appear in the iDevice "
              u"pane with this title. This is a compulsory field "
              u"and you will be prompted to enter a label if you try "
              u"to submit your iDevice without one.")
        self._authorInstruc = x_(u"This is an optional field.")
        self._purposeInstruc = x_(
            u"The purpose dialogue allows you to describe"
            u" your intended purpose of the iDevice to other"
            u" potential users.")
        self._emphasisInstruc = x_(
            u"Use this pulldown to select whether or not "
            u" the iDevice should have any formatting "
            u" applied to it to distinguish "
            u"it; ie. a border and an icon.")
        self._tipInstruc = x_(u"Use this field to describe "
                              u"your intended use and the pedagogy behind "
                              u"the device's development. This can be useful "
                              u"if your iDevice is to be exported for others "
                              u"to use.")
        self._lineInstruc = x_(u"Add a single text line to an iDevice. "
                               u"Useful if you want the ability to place a "
                               u"label within the iDevice.")
        self._textBoxInstruc = x_(
            u"Add a text entry box to an iDevice. "
            u"Used for entering larger amounts of textual "
            u"content.")
        self._feedbackInstruc = x_(
            u"Add an interactive feedback field to your iDevice.")
        self._flashInstruc = x_(u"Add a flash video to your iDevice.")
        self._mp3Instruc = x_(u"Add an mp3 file to your iDevice.")
        self._attachInstruc = x_(u"Add an attachment file to your iDevice.")

        self.style = self.styles[0]

    # Properties

    nameInstruc = lateTranslate('nameInstruc')
    authorInstruc = lateTranslate('authorInstruc')
    purposeInstruc = lateTranslate('purposeInstruc')
    emphasisInstruc = lateTranslate('emphasisInstruc')
    tipInstruc = lateTranslate('tipInstruc')
    lineInstruc = lateTranslate('lineInstruc')
    textBoxInstruc = lateTranslate('textBoxInstruc')
    feedbackInstruc = lateTranslate('feedbackInstruc')
    flashInstruc = lateTranslate('flashInstruc')
    mp3Instruc = lateTranslate('mp3Instruc')
    attachInstruc = lateTranslate('attachInstruc')

    def setIdevice(self, idevice):
        """
        Sets the iDevice to edit
        """
        self.idevice = idevice.clone()
        self.idevice.id = idevice.id
        self.originalIdevice = idevice

    def process(self, request, status):
        """
        Process
        """

        log.debug("process " + repr(request.args))
        self.message = ""

        if status == "old":
            for element in self.elements:
                element.process(request)

            if "title" in request.args:
                self.idevice.title = unicode(request.args["title"][0], 'utf8')

            if "tip" in request.args:
                self.idevice.tip = unicode(request.args["tip"][0], 'utf8')

            if "emphasis" in request.args:
                self.idevice.emphasis = int(request.args["emphasis"][0])
                if self.idevice.emphasis == 0:
                    self.idevice.icon = ""

        if "addText" in request.args:
            field = TextField(_(u"Enter the label here"),
                              _(u"Enter instructions for completion here"))
            field.setIDevice(self.idevice)
            self.idevice.addField(field)
            self.idevice.edit = True

        if "addTextArea" in request.args:
            field = TextAreaField(
                _(u"Enter the label here"),
                _(u"Enter the instructions for completion here"))
            field.setIDevice(self.idevice)
            self.idevice.addField(field)
            self.idevice.edit = True

        if "addFeedback" in request.args:
            field = FeedbackField(
                _(u"Enter the label here"),
                _(u"""Feedback button will not appear if no 
data is entered into this field."""))
            field.setIDevice(self.idevice)
            self.idevice.addField(field)
            self.idevice.edit = True

        #if "addFlash" in request.args:
        #print "add a flash"
        #field = FlashField(_(u"Enter the label here"),
        #_(u"Enter the instructions for completion here"))
        #field.setIDevice(self.idevice)
        #self.idevice.addField(field)

        if "addMP3" in request.args:

            field = MultimediaField(
                _(u"Enter the label here"),
                _(u"Enter the instructions for completion here"))
            field.setIDevice(self.idevice)
            self.idevice.addField(field)
            if not 'xspf_player.swf' in self.idevice.systemResources:
                self.idevice.systemResources += ['xspf_player.swf']
            self.idevice.edit = True

        if "addAttachment" in request.args:

            field = AttachmentField(
                _(u"Enter the label here"),
                _(u"Enter the instructions for completion here"))
            field.setIDevice(self.idevice)
            self.idevice.addField(field)
            self.idevice.edit = True

        if ("action" in request.args
                and request.args["action"][0] == "selectIcon"):
            self.idevice.icon = request.args["object"][0]

        if "preview" in request.args:
            if self.idevice.title == "":
                self.message = _("Please enter<br />an idevice name.")
            else:
                self.idevice.edit = False

        if "edit" in request.args:
            self.idevice.edit = True

        if "cancel" in request.args:
            ideviceId = self.idevice.id
            self.idevice = self.originalIdevice.clone()
            self.idevice.id = ideviceId
            self.parent.showHide = False

        if ("action" in request.args
                and request.args["action"][0] == "changeStyle"):
            self.style = self.styles[int(request.args["object"][0])]

        self.__buildElements()

    def __buildElements(self):
        """
        Building up element array
        """
        self.elements = []
        elementTypeMap = {
            TextField: TextEditorElement,
            TextAreaField: TextAreaEditorElement,
            ImageField: ImageEditorElement,
            FeedbackField: FeedbackEditorElement,
            MultimediaField: MultimediaEditorElement,
            FlashField: FlashEditorElement,
            AttachmentField: AttachmentEditorElement
        }

        for field in self.idevice.fields:
            elementType = elementTypeMap.get(field.__class__)

            if elementType:
                # Create an instance of the appropriate element class
                log.debug(u"createElement " + elementType.__class__.__name__ +
                          u" for " + field.__class__.__name__)
                self.elements.append(elementType(field))
            else:
                log.error(u"No element type registered for " +
                          field.__class__.__name__)

    def renderButtons(self, request):
        """
        Render the idevice being edited
        """
        html = "<font color=\"red\"><b>" + self.message + "</b></font>"

        html += "<fieldset><legend><b>" + _("Add Field") + "</b></legend>"
        html += common.submitButton("addText", _("Text Line"))
        html += common.elementInstruc(self.lineInstruc) + "<br/>"
        html += common.submitButton("addTextArea", _("Text Box"))
        html += common.elementInstruc(self.textBoxInstruc) + "<br/>"
        html += common.submitButton("addFeedback", _("Feedback"))
        html += common.elementInstruc(self.feedbackInstruc) + "<br/>"
        #  Attachments are now embeddable:
        #html += common.submitButton("addAttachment", _("Attachment"))
        #html += common.elementInstruc(self.attachInstruc) + "<br/>"
        #  MP3 fields are now embeddable:
        #html += common.submitButton("addMP3", _("MP3"))
        #html += common.elementInstruc(self.mp3Instruc) + "<br/>"
        html += "</fieldset>\n"

        html += "<fieldset><legend><b>" + _("Actions") + "</b></legend>"

        if self.idevice.edit:
            html += common.submitButton("preview", _("Preview"),
                                        not self.parent.isGeneric)
        else:
            html += common.submitButton("edit", _("Edit"))

        html += "<br/>"
        html += common.submitButton("cancel", _("Cancel"))
        #html += "</fieldset>"

        return html

    def renderIdevice(self, request):
        """
        Returns an XHTML string for rendering the new idevice
        """
        html = "<div id=\"editorWorkspace\">\n"
        html += "<script type=\"text/javascript\">\n"
        html += "<!--\n"
        html += """
            function selectStyleIcon(icon,e) {
                var div = document.getElementById("styleIcons");
                var imgs = div.getElementsByTagName("IMG");
                for (var i=0;i<imgs.length;i++) {
                    imgs[i].style.border = "1px solid #E8E8E8";
                }
                e.style.border = "1px solid #333333";            
                submitLink("selectIcon",icon,1);
            }        
            function submitLink(action, object, changed) 
            {
                var form = document.getElementById("contentForm")
                form.action.value = action;
                form.object.value = object;
                form.isChanged.value = changed;
                form.submit();
            }\n"""
        html += """
            function submitIdevice() 
            {
                var form = document.getElementById("contentForm")
                if (form.ideviceSelect.value == "newIdevice")
                    form.action.value = "newIdevice"
                else
                    form.action.value = "changeIdevice"
                form.object.value = form.ideviceSelect.value;
                form.isChanged.value = 1;
                form.submit();
            }\n"""
        html += """
            function submitStyle()
            {
                var form = document.getElementById("contentForm")
                form.action.value = "changeStyle";
                form.object.value = form.styleSelect.value;
                form.isChanged.value = 0;
                form.submit();
            }\n"""
        html += "//-->\n"
        html += "</script>\n"

        self.purpose = self.idevice.purpose.replace("\r", "")
        self.purpose = self.purpose.replace("\n", "\\n")

        self.tip = self.idevice.tip.replace("\r", "")
        self.tip = self.tip.replace("\n", "\\n")

        if self.idevice.edit:
            html += "<b>" + _("Name") + ": </b>\n"
            html += common.elementInstruc(self.nameInstruc) + "<br/>"
            html += '<input type="text" name= "title" id="title" value="%s"/>' % self.idevice.title

            this_package = None
            html += common.formField('richTextArea', this_package,
                                     _(u"Pedagogical Tip"), 'tip', '',
                                     self.tipInstruc, self.tip)

            html += "<b>" + _("Emphasis") + ":</b> "
            html += "<select onchange=\"submit();\" name=\"emphasis\">\n"

            emphasisValues = {
                Idevice.NoEmphasis: _(u"No emphasis"),
                Idevice.SomeEmphasis: _(u"Some emphasis")
            }
            for value, description in emphasisValues.items():
                html += "<option value=\"" + unicode(value) + "\" "
                if self.idevice.emphasis == value:
                    html += "selected "
                html += ">" + description + "</option>\n"

            html += "</select> \n"
            html += common.elementInstruc(self.emphasisInstruc)
            html += "<br/><br/>\n"

            if self.idevice.emphasis > 0:
                html += self.__renderStyles() + " "
                html += u'<a style="margin-right:.5em" href="javascript:void(0)" '
                html += u'onclick="showMessageBox(\'iconpanel\');">'
                html += u'%s</a>' % _('Select an icon')
                icon = self.idevice.icon
                if icon != "":

                    iconExists = False
                    myIcon = Path(G.application.config.stylesDir /
                                  self.style.get_dirname() / "icon_" +
                                  self.idevice.icon + ".gif")
                    if myIcon.exists():
                        iconExists = True
                    else:
                        myIcon = Path(G.application.config.stylesDir /
                                      self.style.get_dirname() / "icon_" +
                                      self.idevice.icon + ".png")
                        if myIcon.exists():
                            iconExists = True
                    if iconExists:
                        html += '<img style="vertical-align:middle;max-width:60px;height:auto" '
                        html += 'src="/style/%s/icon_%s' % (
                            self.style.get_dirname(), icon)
                        html += '%s"/><br />' % myIcon.ext

                html += u'<div style="display:none;z-index:99;">'
                html += u'<div id="iconpaneltitle">' + _("Icons") + '</div>'
                html += u'<div id="iconpanelcontent">'
                html += self.__renderIcons()
                html += u'</div>'
                html += u'</div>\n'
                html += u'<br style="clear:both;margin-bottom:10px" />'
            for element in self.elements:
                html += element.renderEdit()
        else:
            html += "<b>" + self.idevice.title + "</b><br/><br/>"
            for element in self.elements:
                html += element.renderPreview()
            if self.idevice.purpose != "" or self.idevice.tip != "":
                html += "<a title=\"" + _("Pedagogical Help") + "\" "
                html += "onclick=\"showMessageBox('phelp');\" "
                html += "href=\"javascript:void(0)\" style=\"cursor:help;\">\n "
                html += '<img alt="%s" src="/images/info.png" border="0" ' % _(
                    'Info')
                html += "align=\"middle\" /></a>\n"
                html += "<div style='display:none;'>"
                if self.idevice.purpose != "":
                    html += "<div id='phelptitle'>" + _('Purpose') + "</div>"
                    html += "<div id='phelpcontent'>" + self.purpose + "</div>"
                if self.idevice.tip != "":
                    html += "<div id='phelptitle'>" + _('Tip:') + "</div>"
                    html += "<div id='phelpcontent'>" + self.idevice.tip + "</div>"
                html += "</div>"
                html += "</div>\n"
        html += "</div>\n"
        self.message = ""

        return html

    def __renderStyles(self):
        """
        Return xhtml string for rendering styles select
        """
        html = '<select onchange="submitStyle();" style="display:none" name="styleSelect" id="styleSelect">\n'
        idx = 0
        isSelected = False
        for style in self.styles:
            html += "<option value='%d' " % idx
            if self.style.get_name() == style.get_name():
                html += "selected "
                isSelected = True
            html += ">" + style.get_name() + "~" + style.get_dirname(
            ) + "</option>\n"
            idx = idx + 1
        html += "</select> \n"
        # Auto-select the current style
        # This should be done with Python, not JavaScript
        # It's just a provisional solution so the user does not have to choose the right Style
        html += "<script type='text/javascript'>\
            function autoSelectStyle(){\
                var autoSelectStyle = document.getElementById('styleSelect');\
                if (autoSelectStyle.options[autoSelectStyle.value].innerHTML.split('~')[1]==top.exe_style_dirname) return false;\
                var currentStyleFolder;\
                for (var i=0; i<autoSelectStyle.options.length; i++) {\
                    currentStyleFolder = autoSelectStyle.options[i].innerHTML.split('~')[1];\
                    if (top.exe_style_dirname==currentStyleFolder) {\
                        autoSelectStyle.value=i;\
                        submitStyle();\
                    }\
                }\
            }\
            if (typeof(top.exe_style_dirname)!='undefined') {\
                autoSelectStyle();\
            }\
            \
        </script>"

        return html

    def __renderIcons(self):
        """
        Return xhtml string for dispay all icons
        """
        iconpath = self.style.get_style_dir()
        iconfiles = iconpath.files("icon_*")
        html = '<div id="styleIcons"><div style="height:300px;overflow:auto">'

        for iconfile in iconfiles:
            iconname = iconfile.namebase
            icon = iconname.split("_", 1)[1]

            iconExists = False
            iconExtension = "gif"
            myIcon = Path(G.application.config.stylesDir /
                          self.style.get_dirname() / iconname + ".gif")
            if myIcon.exists():
                iconExists = True
            else:
                myIcon = Path(G.application.config.stylesDir /
                              self.style.get_dirname() / iconname + ".png")
                if myIcon.exists():
                    iconExists = True
                    iconExtension = "png"

            if iconExists:
                filename = "/style/%s/%s.%s" % (self.style.get_dirname(),
                                                iconname, iconExtension)
                html += u'<div style="float:left; text-align:center; width:105px;\n'
                html += u'margin-right:10px; margin-bottom:15px" > '
                html += u'<img src="%s" \n' % filename
                # html += u' alt="%s" ' % _("Submit")
                # window[1] because we use Ext.MessageBox instead of libot_drag.js
                html += u"style=\"border:1px solid #E8E8E8;padding:5px;cursor:pointer;max-width:60px;height:auto\" onclick=\"window[1].selectStyleIcon('%s',this)\" title=\"%s.%s\">\n" % (
                    icon, icon, iconExtension)
                # html += u"style=\"cursor:pointer\" onclick=\"window[1].submitLink('selectIcon','%s',1)\">\n" % icon
                html += u'<br /><span style="display:inline-block;width:100px;overflow:hidden;text-overflow:ellipsis">%s.%s</span></div>\n' % (
                    icon, iconExtension)

        html += '</div></div>'

        return html
class WikipediaIdevice(Idevice):
    """
    A Wikipedia Idevice is one built from a Wikipedia article.
    """
    persistenceVersion = 8

    def __init__(self, defaultSite):
        Idevice.__init__(self, x_(u"Wiki Article"), 
                         x_(u"University of Auckland"), 
                         x_(u"""<p>The Wikipedia iDevice allows you to locate 
existing content from within Wikipedia and download this content into your eXe 
resource. The Wikipedia Article iDevice takes a snapshot copy of the article 
content. Changes in Wikipedia will not automatically update individual snapshot 
copies in eXe, a fresh copy of the article will need to be taken. Likewise, 
changes made in eXe will not be updated in Wikipedia. </p> <p>Wikipedia content 
is covered by the GNU free documentation license.</p>"""), 
                         u"", u"")
        self.emphasis         = Idevice.NoEmphasis
        self.articleName      = u""
        self.article          = TextAreaField(x_(u"Article"))
        self.article.idevice  = self
        self.images           = {}
        self.site             = defaultSite
        self.icon             = u"inter"
        self.systemResources += ["fdl.html"]
        self._langInstruc      = x_(u"""Select the appropriate language version 
of Wikipedia to search and enter search term.""")
        self._searchInstruc    = x_("""Enter a phrase or term you wish to search 
within Wikipedia.""")
        self.ownUrl               = ""

        
    # Properties
    langInstruc      = lateTranslate('langInstruc')
    searchInstruc    = lateTranslate('searchInstruc')
   
    def loadArticle(self, name):
        """
        Load the article from Wikipedia
        """
        self.articleName = name
        url = ""
        name = urllib.quote(name.replace(" ", "_").encode('utf-8'))
        try:
            url  = (self.site or self.ownUrl)
            if not url.endswith('/') and name <> '': url += '/'
            if '://' not in url: url = 'http://' + url
            url += name
            net  = urllib.urlopen(url)
            page = net.read()
            net.close()
        except IOError, error:
            log.warning(unicode(error))
            self.article.content = _(u"Unable to download from %s <br/>Please check the spelling and connection and try again.") % url
            self.article.content_w_resourcePaths = self.article.content
            self.article.content_wo_resourcePaths = self.article.content
            return

        page = unicode(page, "utf8")
        # FIXME avoid problems with numeric entities in attributes
        page = page.replace(u'&#160;', u'&nbsp;')

        # avoidParserProblems is set to False because BeautifulSoup's
        # cleanup was causing a "concatenating Null+Str" error,
        # and Wikipedia's HTML doesn't need cleaning up.
        # BeautifulSoup is faster this way too.
        soup = BeautifulSoup(page, False)
        content = soup.first('div', {'id': "content"})

        # remove the wiktionary, wikimedia commons, and categories boxes
        #  and the protected icon and the needs citations box
        if content:
            infoboxes = content.findAll('div',
                    {'class' : 'infobox sisterproject'})
            [infobox.extract() for infobox in infoboxes]
            catboxes = content.findAll('div', {'id' : 'catlinks'})
            [catbox.extract() for catbox in catboxes]
            amboxes = content.findAll('table',
                    {'class' : re.compile(r'.*\bambox\b.*')})
            [ambox.extract() for ambox in amboxes]
            protecteds = content.findAll('div', {'id' : 'protected-icon'})
            [protected.extract() for protected in protecteds]
        else:
            content = soup.first('body')

        if not content:
            log.error("no content")
            self.article.content = _(u"Unable to download from %s <br/>Please check the spelling and connection and try again.") % url
            # set the other elements as well
            self.article.content_w_resourcePaths = self.article.content
            self.article.content_wo_resourcePaths = self.article.content
            return

        # clear out any old images
        while self.userResources:
            self.userResources[0].delete()
        self.images        = {}

        # Download the images
        bits = url.split('/')
        netloc = '%s//%s' % (bits[0], bits[2])
        path = '/'.join(bits[3:-1])
        tmpDir = TempDirPath()
        for imageTag in content.fetch('img'):
            imageSrc  = unicode(imageTag['src'])
            imageName = imageSrc.split('/')[-1]
            # Search if we've already got this image
            if imageName not in self.images:
                if not imageSrc.startswith("http://"):
                    if imageSrc.startswith("/"):
                        imageSrc = netloc + imageSrc
                    else:
                        imageSrc = '%s/%s/%s' % (netloc, path, imageSrc)
                urllib.urlretrieve(imageSrc, tmpDir/imageName)
                new_resource = Resource(self, tmpDir/imageName)
                if new_resource._storageName != imageName:
                    # looks like it was changed due to a possible conflict,
                    # so reset the imageName accordingly for the content:
                    imageName = new_resource._storageName
                self.images[imageName] = True
            # We have to use absolute URLs if we want the images to
            # show up in edit mode inside FCKEditor
            imageTag['src'] = (u"/" + self.parentNode.package.name + u"/resources/" + imageName)
        self.article.content = self.reformatArticle(netloc, unicode(content))
        # now that these are supporting images, any direct manipulation
        # of the content field must also store this updated information
        # into the other corresponding fields of TextAreaField:
        # (perhaps eventually a property should be made for TextAreaField 
        #  such that these extra set's are not necessary, but for now, here:)
        self.article.content_w_resourcePaths = self.article.content
        self.article.content_wo_resourcePaths = self.article.content
예제 #12
0
class FlashMovieIdevice(Idevice):
    """
    A FlashMovie Idevice is one built up from a flash file and free text.
    """
    persistenceVersion = 5

    def __init__(self):
        Idevice.__init__(
            self, x_(u"Flash Movie"), x_(u"University of Auckland"),
            x_(u"""\
This iDevice only supports the Flash Video File (.FLV) format, and will not
accept other video formats. You can however convert other movie formats
(e.g. mov, wmf etc) into the .FLV format using third party encoders. These
are not supplied with eXe. Users will also need to download the Flash 8
player from http://www.macromedia.com/ to play the video."""), u"", u"")
        self.emphasis = Idevice.NoEmphasis
        self.group = Idevice.Media
        self.flash = FlashMovieField(x_(u"Flash Movie"))
        self.flash.idevice = self
        self.text = TextAreaField(
            x_(u"Description"),
            x_("""Enter 
the text you wish to associate with the file."""))
        self.text.idevice = self
        self.float = u"left"
        self.caption = ""
        self._captionInstruc = x_(u"""Provide a caption for the flash movie 
you have just inserted.""")
        self.systemResources += ['flowPlayer.swf']

    # Properties
    captionInstruc = lateTranslate('captionInstruc')

    def getResourcesField(self, this_resource):
        """
        implement the specific resource finding mechanism for this iDevice:
        """
        # be warned that before upgrading, this iDevice field could not exist:
        if hasattr(self, 'flash') and hasattr(self.flash, 'flashResource'):
            if this_resource == self.flash.flashResource:
                return self.flash

        # be warned that before upgrading, this iDevice field could not exist:
        if hasattr(self, 'text') and hasattr(self.text, 'images'):
            for this_image in self.text.images:
                if hasattr(this_image, '_imageResource') \
                and this_resource == this_image._imageResource:
                    return self.text

        return None

    def getRichTextFields(self):
        """
        Like getResourcesField(), a general helper to allow nodes to search 
        through all of their fields without having to know the specifics of each
        iDevice type.  
        """
        fields_list = []
        if hasattr(self, 'text'):
            fields_list.append(self.text)

        return fields_list

    def upgradeToVersion2(self):
        """
        Upgrades to v0.12
        """
        self._upgradeIdeviceToVersion2()
        self.flash._upgradeFieldToVersion2()
        self.systemResources += ['videoContainer.swf']

    def upgradeToVersion3(self):
        """
        Upgrades to v0.14
        """
        self._captionInstruc = x_(u"""Provide a caption for the flash movie 
you have just inserted.""")
        self.flash._upgradeFieldToVersion3()

    def upgradeToVersion4(self):
        """
        Upgrades to v0.23
        """
        self.systemResources.remove('videoContainer.swf')
        self.systemResources += ['flowPlayer.swf']

    def upgradeToVersion5(self):
        """
        Adds group to idevice
        """
        self.group = Idevice.Media
class FlashWithTextIdevice(Idevice):
    """
    A FlashWithText Idevice is one built up from a flash file and free text.
    """

    persistenceVersion = 4

    def __init__(self):
        Idevice.__init__(
            self, x_(u"Flash with Text"), x_(u"University of Auckland"),
            x_(u"""The flash with text idevice allows you to 
associate additional textual information to a flash file. This may be useful 
where you wish to provide educational instruction regarding the flash file 
the learners will view."""), u"", u"")
        self.emphasis = Idevice.NoEmphasis
        self.flash = FlashField(x_(u"Flash with Text"), u"")
        self.flash.idevice = self
        self.text = TextAreaField(
            x_(u"Description"),
            x_("""Enter the text you wish to 
                                 associate with the image."""))
        self.text.idevice = self
        self.float = u"left"
        self.caption = u""
        self._captionInstruc = x_(u"""Provide a caption for the flash you 
                                  have just inserted.""")
        self._dimensionInstruc = x_(u"""Enter the flash display 
dimensions (in pixels) and determine the alignment of the image on screen. 
The width and height dimensions will alter proportionally.""")

    # Properties
    captionInstruc = lateTranslate('captionInstruc')
    dimensionInstruc = lateTranslate('dimensionInstruc')

    def getResourcesField(self, this_resource):
        """
        implement the specific resource finding mechanism for this iDevice:
        """
        # be warned that before upgrading, this iDevice field could not exist:
        if hasattr(self, 'flash') and hasattr(self.flash, 'flashResource'):
            if this_resource == self.flash.flashResource:
                return self.flash

        # be warned that before upgrading, this iDevice field could not exist:
        if hasattr(self, 'text') and hasattr(self.text, 'images'):
            for this_image in self.text.images:
                if hasattr(this_image, '_imageResource') \
                and this_resource == this_image._imageResource:
                    return self.text

        return None

    def getRichTextFields(self):
        """
        Like getResourcesField(), a general helper to allow nodes to search 
        through all of their fields without having to know the specifics of each
        iDevice type.  
        """
        fields_list = []
        if hasattr(self, 'text'):
            fields_list.append(self.text)

        return fields_list

    def upgradeToVersion1(self):
        """
        Upgrades exe to v0.10
        """
        self._upgradeIdeviceToVersion1()

    def upgradeToVersion2(self):
        """
        Upgrades to v0.12
        """
        self._upgradeIdeviceToVersion2()
        self.flash._upgradeFieldToVersion2()

    def upgradeToVersion3(self):
        """
        Upgrades to v0.13
        """
        self._captionInstruc = x_(u"""Provide a caption for the flash you 
                                  have just inserted.""")
        self._dimensionInstruc = x_(u"""Enter the flash display 
dimensions (in pixels) and determine the alignment of the image on screen. 
The width and height dimensions will alter proportionally.""")
        self.flash._upgradeFieldToVersion3()

    def NoLonger_upgradeToVersion4(self):
        """
        NOTE: upgradeToVersion4 (from r3051) no longer enabled, because:
        FlashWithTextIdevice is now deprecated, leaving its functionality
        fully in place, but hidden from standard usage.  Before doing the
        deprecation, however, there had previously been a very brief period
        of converting FlashWithTextIdevice -> FreeTextIdevice,
        since FreeText can hold embeddded .swf Flash Object media. It was
        decided, though, that the behaviour was just different enough that
        FlashWithTextIdevice should still be available, if needed.
        Leaving the persistence version to 4, for those few intermediate elps.
        """
        G.application.afterUpgradeHandlers.append(self.convertToFreeText)
예제 #14
0
class WikipediaIdevice(Idevice):
    """
    A Wikipedia Idevice is one built from a Wikipedia article.
    """
    persistenceVersion = 9

    def __init__(self, defaultSite):
        Idevice.__init__(
            self, x_(u"Wiki Article"), x_(u"University of Auckland"),
            x_(u"""<p>The Wikipedia iDevice allows you to locate 
existing content from within Wikipedia and download this content into your eXe 
resource. The Wikipedia Article iDevice takes a snapshot copy of the article 
content. Changes in Wikipedia will not automatically update individual snapshot 
copies in eXe, a fresh copy of the article will need to be taken. Likewise, 
changes made in eXe will not be updated in Wikipedia. </p> <p>Wikipedia content 
is covered by the GNU Free Documentation 1.2 License, and since 2009 additionally
by the Creative Commons Attribution-ShareAlike 3.0 Unported License.</p>"""),
            u"", u"")
        self.emphasis = Idevice.NoEmphasis
        self.articleName = u""
        self.article = TextAreaField(x_(u"Article"))
        self.article.idevice = self
        self.images = {}
        self.site = defaultSite
        self.icon = u"inter"
        self._langInstruc = x_(u"""Select the appropriate language version 
of Wikipedia to search and enter search term.""")
        self._searchInstruc = x_("""Enter a phrase or term you wish to search 
within Wikipedia.""")
        self.ownUrl = ""
        self.systemResources += ['exe_wikipedia.css']

    # Properties
    langInstruc = lateTranslate('langInstruc')
    searchInstruc = lateTranslate('searchInstruc')

    def loadArticle(self, name):
        """
        Load the article from Wikipedia
        """
        self.articleName = name
        url = ''
        name = urllib.quote(name.replace(" ", "_").encode('utf-8'))

        # Get the full URL of the site
        url = self.site or self.ownUrl
        if not url.endswith('/') and name != '':
            url += '/'
        if '://' not in url:
            url = 'http://' + url
        url += name

        # Get the site content
        try:
            net = urllib.urlopen(url)
            page = net.read()
            net.close()
        except IOError, error:
            log.warning(unicode(error))
            self.article.content = _(
                u"Unable to download from %s <br/>Please check the spelling and connection and try again."
            ) % url
            self.article.content_w_resourcePaths = self.article.content
            self.article.content_wo_resourcePaths = self.article.content
            return

        page = unicode(page, "utf8")
        # FIXME avoid problems with numeric entities in attributes
        page = page.replace(u'&#160;', u'&nbsp;')
        # avoidParserProblems is set to False because BeautifulSoup's
        # cleanup was causing a "concatenating Null+Str" error,
        # and Wikipedia's HTML doesn't need cleaning up.
        # BeautifulSoup is faster this way too.
        soup = BeautifulSoup(page, False)
        content = soup.first('div', {'id': "content"})
        # Fix bug #1359: El estilo ITE no respeta ancho de página al exportar
        # a páginas web si se usa iDevice wikipedia
        content['id'] = "wikipedia-content"

        # remove the wiktionary, wikimedia commons, and categories boxes
        # and the protected icon and the needs citations box
        if content:
            infoboxes = content.findAll('div',
                                        {'class': 'infobox sisterproject'})
            [infobox.extract() for infobox in infoboxes]
            catboxes = content.findAll('div', {'id': 'catlinks'})
            [catbox.extract() for catbox in catboxes]
            amboxes = content.findAll('table',
                                      {'class': re.compile(r'.*\bambox\b.*')})
            [ambox.extract() for ambox in amboxes]
            protecteds = content.findAll('div', {'id': 'protected-icon'})
            [protected.extract() for protected in protecteds]
            # Extract HTML comments
            comments = content.findAll(
                text=lambda text: isinstance(text, Comment))
            [comment.extract() for comment in comments]
        else:
            content = soup.first('body')

        # If we still don't have content it means there is a problem with the article
        if not content:
            log.error(u"No content on Wikipedia article: %s" % url)
            self.article.content = _(
                u"Unable to download from %s <br/>Please check the spelling and connection and try again."
            ) % url
            # Set the other elements as well
            self.article.content_w_resourcePaths = self.article.content
            self.article.content_wo_resourcePaths = self.article.content
            return

        # Clear out any old images
        while self.userResources:
            self.userResources[0].delete()
        self.images = {}

        # Download the images
        bits = url.split('/')
        netloc = '%s//%s' % (bits[0], bits[2])
        path = '/'.join(bits[3:-1])
        tmpDir = TempDirPath()

        # Fetch all images from content
        for imageTag in content.fetch('img'):
            # Get src and image filename
            imageSrc = unicode(imageTag['src'])
            imageName = imageSrc.split('/')[-1]
            imageName = imageName.replace('&gt;', '>')
            imageName = imageName.replace('&lt;', '<')
            imageName = imageName.replace('&quot;', '"')
            imageName = imageName.replace('&nbsp;', '')
            imageName = imageName.replace('%2C', ',')
            imageName = imageName.replace('%22', '"')
            imageName = imageName.replace('%28', '(')
            imageName = imageName.replace('%29', ')')
            imageName = imageName.replace('%C3%A5', 'å')
            # Decode image name
            imageName = urllib.unquote(imageName)
            # Search if we've already got this image
            if imageName not in self.images:
                if not re.match("^http(s)?:\/\/", imageSrc):
                    if imageSrc.startswith("/"):
                        imageSrc = bits[0] + imageSrc
                    else:
                        imageSrc = '%s/%s/%s' % (netloc, path, imageSrc)
                try:
                    # download with its original name... in ASCII:
                    ## er... just because some repositories do not undestand no ascii names of files:
                    imageName = imageName.encode('ascii', 'ignore')

                    # If the image file doesn't have an extension try to guess it
                    if not re.match('^.*\.(.){1,}', imageName):
                        # Open a conecction with the image and get the headers
                        online_resource = urllib.urlopen(imageSrc)
                        image_info = online_resource.info()
                        online_resource.close()

                        # Try to guess extension from mimetype
                        extension = mimetypes.guess_extension(
                            image_info['content-type'])
                        # Wikimedia uses mainly SVG images so we can safely say that
                        # this image is in svg (if it wasn't if wouldn't be shown anyway)
                        extension = extenion or '.svg'
                        imageName = imageName + extension

                    # Download image
                    urllib.urlretrieve(imageSrc, tmpDir / imageName)
                    # Add the new resource
                    new_resource = Resource(self, tmpDir / imageName)
                except:
                    log.error(u'Unable to download file: %s' % imageSrc)
                    # If there is an exception try to get the next one
                    continue
                if new_resource._storageName != imageName:
                    # looks like it was changed due to a possible conflict,
                    # so reset the imageName accordingly for the content:
                    imageName = new_resource._storageName
                self.images[imageName] = True
            imageTag['src'] = u"resources/" + imageName
        self.article.content = self.reformatArticle(netloc, unicode(content))
        # now that these are supporting images, any direct manipulation
        # of the content field must also store this updated information
        # into the other corresponding fields of TextAreaField:
        # (perhaps eventually a property should be made for TextAreaField
        #  such that these extra set's are not necessary, but for now, here:)
        self.article.content_w_resourcePaths = self.article.content
        self.article.content_wo_resourcePaths = self.article.content
class ScormClozeField(FieldWithResources):
    """
    This field handles a passage with words that the student must fill in
    And can now support multiple images (and any other resources) via tinyMCE
    """

    regex = re.compile('(%u)((\d|[A-F]){4})', re.UNICODE)
    persistenceVersion = 3

    # these will be recreated in FieldWithResources' TwistedRePersist:
    nonpersistant = ['content', 'content_wo_resourcePaths']

    def __init__(self, name, instruc):
        """
        Initialise
        """
        FieldWithResources.__init__(self, name, instruc)
        self.parts = []
        self._encodedContent = ''
        self.rawContent = ''
        self._setVersion2Attributes()

    def _setVersion2Attributes(self):
        """
        Sets the attributes that were added in persistenceVersion 2
        """
        self.strictMarking = False
        self._strictMarkingInstruc = \
            x_(u"<p>If left unchecked a small number of spelling and "
                "capitalization errors will be accepted. If checked only "
                "an exact match in spelling and capitalization will be accepted."
                "</p>"
                "<p><strong>For example:</strong> If the correct answer is "
                "<code>Elephant</code> then both <code>elephant</code> and "
                "<code>Eliphant</code> will be judged "
                "<em>\"close enough\"</em> by the algorithm as it only has "
                "one letter wrong, even if \"Check Capitilization\" is on."
                "</p>"
                "<p>If capitalization checking is off in the above example, "
                "the lowercase <code>e</code> will not be considered a "
                "mistake and <code>eliphant</code> will also be accepted."
                "</p>"
                "<p>If both \"Strict Marking\" and \"Check Capitalization\" "
                "are set, the only correct answer is \"Elephant\". If only "
                "\"Strict Marking\" is checked and \"Check Capitalization\" "
                "is not, \"elephant\" will also be accepted."
                "</p>")
        self.checkCaps = False
        self._checkCapsInstruc = \
            x_(u"<p>If this option is checked, submitted answers with "
                "different capitalization will be marked as incorrect."
                "</p>")
        self.instantMarking = False
        self._instantMarkingInstruc = \
            x_(u"""<p>If this option is set, each word will be marked as the
learner types it rather than all the words being marked the end of the
exercise.</p>""")

    # Property handlers
    def set_encodedContent(self, value):
        """
        Cleans out the encoded content as it is passed in. Makes clean XHTML.
        """
        for key, val in name2codepoint.items():
            value = value.replace('&%s;' % key, unichr(val))
        # workaround for Microsoft Word which incorrectly quotes font names
        value = re.sub(r'font-family:\s*"([^"]+)"', r'font-family: \1', value)
        parser = ScormClozeHTMLParser()
        parser.feed(value)
        parser.close()
        self.parts = parser.result
        encodedContent = ''
        for shown, hidden in parser.result:
            encodedContent += shown
            if hidden:
                encodedContent += ' <u>'
                encodedContent += hidden
                encodedContent += '</u> '
        self._encodedContent = encodedContent

    # Properties
    encodedContent = property(lambda self: self._encodedContent,
                              set_encodedContent)
    strictMarkingInstruc = lateTranslate('strictMarkingInstruc')
    checkCapsInstruc = lateTranslate('checkCapsInstruc')
    instantMarkingInstruc = lateTranslate('instantMarkingInstruc')

    def upgradeToVersion1(self):
        """
        Upgrades to exe v0.11
        """
        self.autoCompletion = True
        self.autoCompletionInstruc = _(u"""Allow auto completion when
                                       user filling the gaps.""")

    def upgradeToVersion2(self):
        """
        Upgrades to exe v0.12
        """
        Field.upgradeToVersion2(self)
        strictMarking = not self.autoCompletion
        del self.autoCompletion
        del self.autoCompletionInstruc
        self._setVersion2Attributes()
        self.strictMarking = strictMarking

    def upgradeToVersion3(self):
        """
        Upgrades to somewhere before version 0.25 (post-v0.24)
        to reflect that ClozeField now inherits from FieldWithResources,
        and will need its corresponding fields populated from content.
        """
        self.content = self.encodedContent
        self.content_w_resourcePaths = self.encodedContent
        self.content_wo_resourcePaths = self.encodedContent
예제 #16
0
class ParasabermasfpdIdevice(Idevice):
    """
    El iDevice Para saber permite al alumnado ampliar conocimientos voluntarios para su aprendizaje
    """
    persistenceVersion = 9

    def __init__(self, activity="", answer=""):
        """
        Initialize 
        """
        Idevice.__init__(
            self, x_(u"FPD - A Step Ahead"), x_(u"Jose Ramon Jimenez Reyes"),
            x_(u"""A Step Ahead is an iDevice that permits students widen their knowledge with further contents."""
               ), u"", u"parasabermasfpd")
        #        self.emphasis         = Idevice.SomeEmphasis
        self.emphasis = "_parasabermasfpd"
        self._activityInstruc = x_(
            u"""Enter the text that will appear on this iDevice""")
        #        self.systemResources += ["common.js"]

        self.activityTextArea = TextAreaField(x_(u'A Step Ahead Text'),
                                              self._activityInstruc, activity)
        self.activityTextArea.idevice = self

    # Properties
    activityInstruc = lateTranslate('activityInstruc')

    def getResourcesField(self, this_resource):
        """
        implement the specific resource finding mechanism for this iDevice:
        """
        # be warned that before upgrading, this iDevice field could not exist:
        if hasattr(self, 'activityTextArea')\
        and hasattr(self.activityTextArea, 'images'):
            for this_image in self.activityTextArea.images:
                if hasattr(this_image, '_imageResource') \
                    and this_resource == this_image._imageResource:
                    return self.activityTextArea

        return None

    def getRichTextFields(self):
        fields_list = []
        if hasattr(self, 'activityTextArea'):
            fields_list.append(self.activityTextArea)

        return fields_list

    def burstHTML(self, i):
        # Parasabermasfpd Idevice:
        title = i.find(name='span', attrs={'class': 'iDeviceTitle'})
        self.title = title.renderContents().decode('utf-8')

        reflections = i.findAll(name='div', attrs={'id': re.compile('^ta')})
        # should be exactly two of these:
        # 1st = field[0] == Activity
        if len(reflections) >= 1:
            self.activityTextArea.content_wo_resourcePaths = \
                    reflections[0].renderContents().decode('utf-8')
            # and add the LOCAL resource paths back in:
            self.activityTextArea.content_w_resourcePaths = \
                    self.activityTextArea.MassageResourceDirsIntoContent( \
                        self.activityTextArea.content_wo_resourcePaths)
            self.activityTextArea.content = \
                    self.activityTextArea.content_w_resourcePaths

    def upgradeToVersion1(self):
        """
        Upgrades the node from version 0 to 1.
        """
        log.debug(u"Upgrading iDevice")
        self.icon = u"activity"

    def upgradeToVersion2(self):
        """
        Upgrades the node from 1 (v0.5) to 2 (v0.6).
        Old packages will loose their icons, but they will load.
        """
        log.debug(u"Upgrading iDevice")
        #        self.emphasis         = Idevice.SomeEmphasis
        self.emphasis = "_parasabermasfpd"

    def upgradeToVersion3(self):
        """
        Upgrades v0.6 to v0.7.
        """
        self.lastIdevice = False

    def upgradeToVersion4(self):
        """
        Upgrades to exe v0.10
        """
        self._upgradeIdeviceToVersion1()
        self._activityInstruc = self.__dict__['activityInstruc']

    def upgradeToVersion5(self):
        """
        Upgrades to exe v0.10
        """
        self._upgradeIdeviceToVersion1()

    def upgradeToVersion6(self):
        """
        Upgrades to v0.12
        """
        self._upgradeIdeviceToVersion2()
#        self.systemResources += ["common.js"]

    def upgradeToVersion7(self):
        """ 
        Upgrades to somewhere before version 0.25 (post-v0.24) 
        Taking the old unicode string fields, and converting them 
        into image-enabled TextAreaFields:
        """
        self.activityTextArea = TextAreaField(x_(u'A Step Ahead Text'),
                                              self._activityInstruc,
                                              self.activity)
        self.activityTextArea.idevice = self

    def upgradeToVersion8(self):
        """
        Delete icon from system resources
        """
        self._upgradeIdeviceToVersion3()

    def upgradeToVersion9(self):
        if self._title == u"FPD - Para Saber Mas":
            self._title = u"FPD - A Step Ahead"
        if self._purpose == u"""Para saber m&aacute;s es un iDevice que permite al alumnado ampliar conocimientos, siendo estos voluntarios para su aprendizaje.""":
            self._purpose = u"""A Step Ahead is an iDevice that permits students widen their knowledge with further contents."""
        if self._activityInstruc == u"""Introduce el texto que aparecer&aacute; en este iDevice""":
            self._activityInstruc = u"""Enter the text that will appear on this iDevice"""
        if self.activityTextArea._name == u'Texto Para saber m&aacute;s':
            self.activityTextArea._name = u'A Step Ahead Text'
예제 #17
0
class CasestudyIdevice(Idevice):
    """
    A multichoice Idevice is one built up from question and options
    """
    persistenceVersion = 9

    def __init__(self, story="", defaultImage=None):
        """
        Initialize 
        """
        Idevice.__init__(
            self, x_(u"Case Study"), x_(u"University of Auckland"),
            x_(u"""A case study is a device that provides learners 
with a simulation that has an educational basis. It takes a situation, generally 
based in reality, and asks learners to demonstrate or describe what action they 
would take to complete a task or resolve a situation. The case study allows 
learners apply their own knowledge and experience to completing the tasks 
assigned. when designing a case study consider the following:<ul> 
<li>    What educational points are conveyed in the story</li>
<li>    What preparation will the learners need to do prior to working on the 
case study</li>
<li>    Where the case study fits into the rest of the course</li>
<li>    How the learners will interact with the materials and each other e.g.
if run in a classroom situation can teams be setup to work on different aspects
of the case and if so how are ideas feed back to the class</li></ul>"""), "",
            u"casestudy")
        self.emphasis = Idevice.SomeEmphasis

        self._storyInstruc = x_(u"""Create the case story. A good case is one 
that describes a controversy or sets the scene by describing the characters 
involved and the situation. It should also allow for some action to be taken 
in order to gain resolution of the situation.""")
        self.storyTextArea = TextAreaField(x_(u'Story:'), self._storyInstruc,
                                           story)
        self.storyTextArea.idevice = self

        self.questions = []
        self._questionInstruc = x_(u"""Describe the activity tasks relevant 
to the case story provided. These could be in the form of questions or 
instructions for activity which may lead the learner to resolving a dilemma 
presented. """)
        self._feedbackInstruc = x_(u"""Provide relevant feedback on the 
situation.""")
        if defaultImage is None:
            defaultImage = G.application.config.webDir / 'images' / DEFAULT_IMAGE
        self.defaultImage = toUnicode(defaultImage)
        self.addQuestion()

    # Properties
    storyInstruc = lateTranslate('storyInstruc')
    questionInstruc = lateTranslate('questionInstruc')
    feedbackInstruc = lateTranslate('feedbackInstruc')
    storyInstruc = lateTranslate('storyInstruc')
    questionInstruc = lateTranslate('questionInstruc')
    feedbackInstruc = lateTranslate('feedbackInstruc')

    def addQuestion(self):
        """
        Add a new question to this iDevice. 
        """
        self.questions.append(Question(self))

    def getResourcesField(self, this_resource):
        """
        implement the specific resource finding mechanism for this iDevice:
        """
        # be warned that before upgrading, this iDevice field could not exist:
        if hasattr(self, 'storyTextArea')\
        and hasattr(self.storyTextArea, 'images'):
            for this_image in self.storyTextArea.images:
                if hasattr(this_image, '_imageResource') \
                and this_resource == this_image._imageResource:
                    return self.storyTextArea

        for this_question in self.questions:
            this_field = this_question.getResourcesField(this_resource)
            if this_field is not None:
                return this_field

        return None

    def getRichTextFields(self):
        """
        Like getResourcesField(), a general helper to allow nodes to search 
        through all of their fields without having to know the specifics of each
        iDevice type.  
        """
        fields_list = []
        if hasattr(self, 'storyTextArea'):
            fields_list.append(self.storyTextArea)

        for this_question in self.questions:
            fields_list.extend(this_question.getRichTextFields())

        return fields_list

    def burstHTML(self, i):
        """
        takes a BeautifulSoup fragment (i) and bursts its contents to 
        import this idevice from a CommonCartridge export
        """
        # CaseStudy Idevice:
        title = i.find(name='h2', attrs={'class': 'iDeviceTitle'})
        self.title = title.renderContents().decode('utf-8')

        inner = i.find(name='div', attrs={'class': 'iDevice_inner'})

        story = inner.find(name='div',
                           attrs={
                               'class': 'block',
                               'id': re.compile('^ta')
                           })
        self.storyTextArea.content_wo_resourcePaths = \
                story.renderContents().decode('utf-8')
        # and add the LOCAL resource paths back in:
        self.storyTextArea.content_w_resourcePaths = \
                self.storyTextArea.MassageResourceDirsIntoContent( \
                    self.storyTextArea.content_wo_resourcePaths)
        self.storyTextArea.content = self.storyTextArea.content_w_resourcePaths

        case_questions = inner.findAll(name='div', attrs={'class': 'question'})
        for question_num in range(len(case_questions)):
            if question_num > 0:
                # only created with the first question, add others:
                self.addQuestion()

            question = case_questions[question_num]

            case_stories = question.findAll(name='div',
                                            attrs={
                                                'class': 'block',
                                                'id':
                                                re.compile('^taquesQuestion')
                                            })
            if len(case_stories) == 1:
                # ELSE: should warn of unexpected result!
                inner_question = case_stories[0]
                self.questions[question_num].questionTextArea.content = \
                        inner_question.renderContents().decode('utf-8')
                self.questions[question_num].questionTextArea.content_w_resourcePaths \
                        = inner_question.renderContents().decode('utf-8')
                self.questions[question_num].questionTextArea.content_wo_resourcePaths \
                        = inner_question.renderContents().decode('utf-8')
                # and add the LOCAL resource paths back in:
                self.questions[question_num].questionTextArea.content_w_resourcePaths \
                        = self.questions[question_num].questionTextArea.MassageResourceDirsIntoContent( \
                            self.questions[question_num].questionTextArea.content_wo_resourcePaths)
                self.questions[question_num].questionTextArea.content = \
                        self.questions[question_num].questionTextArea.content_w_resourcePaths

            case_feedbacks = question.findAll(name='div',
                                              attrs={
                                                  'class': 'feedback',
                                                  'id': re.compile('^sq')
                                              })
            if len(case_feedbacks) == 1:
                # no warning otherwise, since feedback is optional
                inner_feedback = case_feedbacks[0]
                self.questions[question_num].feedbackTextArea.content_wo_resourcePaths \
                        = inner_feedback.renderContents().decode('utf-8')
                # and add the LOCAL resource paths back in:
                self.questions[question_num].feedbackTextArea.content_w_resourcePaths \
                        = self.questions[question_num].feedbackTextArea.MassageResourceDirsIntoContent( \
                            self.questions[question_num].feedbackTextArea.content_wo_resourcePaths)
                self.questions[question_num].feedbackTextArea.content = \
                        self.questions[question_num].feedbackTextArea.content_w_resourcePaths
                _btfeedBack = inner.find(
                    name='input',
                    attrs={'name': re.compile('^toggle-feedback-')})
            else:
                self.questions[question_num].feedbackTextArea.content = ""
                self.questions[question_num].feedbackTextArea.content_w_resourcePaths \
                        = ""
                self.questions[question_num].feedbackTextArea.content_wo_resourcePaths \
                        = ""
                _btfeedBack = inner.find(
                    name='input',
                    attrs={'name': re.compile('^toggle-feedback-')})

    def upgradeToVersion1(self):
        """
        Upgrades the node from version 0 to 1.
        Old packages will loose their icons, but they will load.
        """
        log.debug(u"Upgrading iDevice")
        self.icon = "casestudy"

    def upgradeToVersion2(self):
        """
        Upgrades the node from 1 (v0.5) to 2 (v0.6).
        Old packages will loose their icons, but they will load.
        """
        log.debug(u"Upgrading iDevice")
        self.emphasis = Idevice.SomeEmphasis

    def upgradeToVersion3(self):
        """
        Upgrades v0.6 to v0.7.
        """
        self.lastIdevice = False

    def upgradeToVersion4(self):
        """
        Upgrades to exe v0.10
        """
        self._upgradeIdeviceToVersion1()
        self._storyInstruc = self.__dict__['storyInstruc']
        self._questionInstruc = self.__dict__['questionInstruc']
        self._feedbackInstruc = self.__dict__['feedbackInstruc']

    def upgradeToVersion5(self):
        """
        Upgrades to v0.12
        """
        self._upgradeIdeviceToVersion2()

    def upgradeToVersion6(self):
        """
        Upgrades for v0.18
        """
        self.defaultImage = toUnicode(G.application.config.webDir / 'images' /
                                      DEFAULT_IMAGE)
        for question in self.questions:
            question.setupImage(self)

    def upgradeToVersion7(self):
        """
        Upgrades to somewhere before version 0.25 (post-v0.24)
        Taking the old unicode string fields, 
        and converting them into a image-enabled TextAreaFields:
        """
        self.storyTextArea = TextAreaField(x_(u'Story:'), self._storyInstruc,
                                           self.story)
        self.storyTextArea.idevice = self
        for question in self.questions:
            question.questionTextArea = TextAreaField(u'', u'',
                                                      question.question)
            question.questionTextArea.idevice = self
            question.feedbackTextArea = TextAreaField(u'', u'',
                                                      question.feedback)
            question.feedbackTextArea.idevice = self

    def upgradeToVersion8(self):
        """
        Converting CaseStudyIdevice's image -> embedded image in its feedback
        field, a TextField than can now hold embedded images.

        BUT - due to the inconsistent loading of the objects via unpickling,
        since the resources aren't necessarily properly loaded and upgraded,
        NOR is the package necessarily, as it might not even have a list of
        resources yet, all of this conversion code must be done in an
        afterUpgradeHandler  
        (as perhaps should have been done for the previous upgradeToVersion7)
        """
        G.application.afterUpgradeHandlers.append(self.embedImagesInFeedback)

    def upgradeToVersion9(self):
        """
        Delete icon from system resources
        """
        self._upgradeIdeviceToVersion3()

    def embedImagesInFeedback(self):
        """
        Loop through each question, to call their conversion:
        CaseStudyIdevice's image -> embedded in its feedback field,
        now that its TextField can hold embeddded images.
        """
        for question in self.questions:
            question.embedImageInFeedback()
예제 #18
0
class TrueFalseIdevice(Idevice):
    """
    A TrueFalse Idevice is one built up from question and options
    """
    persistenceVersion = 11

    def __init__(self):
        """
        Initialize 
        """
        Idevice.__init__(
            self, x_(u"True-False Question"), x_(u"University of Auckland"),
            x_(u"""True/false questions present a statement where 
the learner must decide if the statement is true. This type of question works 
well for factual information and information that lends itself to either/or 
responses."""), u"", u"question")
        self.emphasis = Idevice.SomeEmphasis
        self._hintInstruc = x_(u"""A hint may be provided to assist the 
learner in answering the question.""")
        self.questions = []
        self._questionInstruc = x_(u"""Type the question stem. The question 
should be clear and unambiguous. Avoid negative premises as these can tend to 
be ambiguous.""")
        self._keyInstruc = ""
        self._feedbackInstruc = x_(u"""Enter any feedback you wish to provide 
to the learner. This field may be left blank. if this field is left blank 
default feedback will be provided.""")
        self.questions.append(TrueFalseQuestion(self))
        self.systemResources += [
            "common.js", "panel-amusements.png", "stock-stop.png"
        ]
        self.instructionsForLearners = TextAreaField(
            x_(u'Instructions'),
            x_(u"""Provide instruction on how the True/False Question should be 
completed."""), u'')

        self.instructionsForLearners.idevice = self

    # Properties
    hintInstruc = lateTranslate('hintInstruc')
    questionInstruc = lateTranslate('questionInstruc')
    keyInstruc = lateTranslate('keyInstruc')
    feedbackInstruc = lateTranslate('feedbackInstruc')

    def addQuestion(self):
        """
        Add a new question to this iDevice. 
        """
        self.questions.append(TrueFalseQuestion(self))

    def getResourcesField(self, this_resource):
        """
        implement the specific resource finding mechanism for this iDevice:
        """
        # be warned that before upgrading, this iDevice field could not exist:
        if hasattr(self, 'instructionsForLearners')\
        and hasattr(self.instructionsForLearners, 'images'):
            for this_image in self.instructionsForLearners.images:
                if hasattr(this_image, '_imageResource') \
                    and this_resource == this_image._imageResource:
                    return self.instructionsForLearners

        for this_question in self.questions:
            this_field = this_question.getResourcesField(this_resource)
            if this_field is not None:
                return this_field

        return None

    def getRichTextFields(self):
        """
        Like getResourcesField(), a general helper to allow nodes to search 
        through all of their fields without having to know the specifics of each
        iDevice type.  
        """
        fields_list = []
        if hasattr(self, 'instructionsForLearners'):
            fields_list.append(self.instructionsForLearners)

        for this_question in self.questions:
            fields_list.extend(this_question.getRichTextFields())

        return fields_list

    def burstHTML(self, i):
        """
        takes a BeautifulSoup fragment (i) and bursts its contents to 
        import this idevice from a CommonCartridge export
        """
        # True-False Idevice:
        title = i.find(name='h2', attrs={'class': 'iDeviceTitle'})
        self.title = title.renderContents().decode('utf-8')

        inner = i.find(name='div', attrs={'class': 'iDevice_inner'})

        instruct = inner.find(name='div',
                              attrs={
                                  'class': 'block',
                                  'style': 'display:block'
                              })
        self.instructionsForLearners.content_wo_resourcePaths = \
                instruct.renderContents().decode('utf-8')
        # and add the LOCAL resource paths back in:
        self.instructionsForLearners.content_w_resourcePaths = \
                self.instructionsForLearners.MassageResourceDirsIntoContent( \
                    self.instructionsForLearners.content_wo_resourcePaths)
        self.instructionsForLearners.content = \
                self.instructionsForLearners.content_w_resourcePaths

        # copied and modified from Multi-Select, and others :-) :

        tf_questions = inner.findAll(name='div', attrs={'class': 'question'})
        if len(tf_questions) < 1:
            # need to remove the default 1st question
            del self.questions[0]

        for question_num in range(len(tf_questions)):
            if question_num > 0:
                # only created with the first question, add others:
                self.addQuestion()

            question = tf_questions[question_num]

            questions = question.findAll(name='div',
                                         attrs={
                                             'class': 'block',
                                             'id': re.compile('^taquestion')
                                         })
            if len(questions) == 1:
                # ELSE: should warn of unexpected result!
                inner_question = questions[0]
                self.questions[question_num].questionTextArea.content_wo_resourcePaths \
                        = inner_question.renderContents().decode('utf-8')
                # and add the LOCAL resource paths back in:
                self.questions[question_num].questionTextArea.content_w_resourcePaths \
                        = self.questions[question_num].questionTextArea.MassageResourceDirsIntoContent( \
                            self.questions[question_num].questionTextArea.content_wo_resourcePaths)
                self.questions[question_num].questionTextArea.content = \
                        self.questions[question_num].questionTextArea.content_w_resourcePaths

            answer_true = question.find(name='div',
                                        attrs={'id': re.compile('^s0b')})
            answer_false = question.find(name='div',
                                         attrs={'id': re.compile('^s1b')})
            # true-false only has 1 feedback per question:
            feedbacks = question.findAll(name='div',
                                         attrs={'id': re.compile('^sfb')})
            # true-false only has 1 hint per question:
            hints = question.findAll(name='div',
                                     attrs={'id': re.compile('^tahint')})

            # and finally, see if this is a correct answer:
            even_score = int(answer_true.attrMap['even_steven'])
            if not (even_score % 2):
                # i.e., if it IS even, then this is correct:
                self.questions[question_num].isCorrect = True

            if len(hints) >= 1:
                inner_hint = hints[0]
                self.questions[question_num].hintTextArea.content_wo_resourcePaths \
                        = inner_hint.renderContents().decode('utf-8')
                # and add the LOCAL resource paths back in:
                self.questions[question_num].hintTextArea.content_w_resourcePaths \
                        = self.questions[question_num].hintTextArea.MassageResourceDirsIntoContent( \
                            self.questions[question_num].hintTextArea.content_wo_resourcePaths)
                self.questions[question_num].hintTextArea.content = \
                        self.questions[question_num].hintTextArea.content_w_resourcePaths
            else:
                # no user-defined feedback, just using the default:
                self.questions[question_num].hintTextArea.content = ""
                self.questions[question_num].hintTextArea.content_w_resourcePaths \
                        = ""
                self.questions[question_num].hintTextArea.content_wo_resourcePaths \
                        = ""

            if len(feedbacks) >= 1:
                inner_feedback = feedbacks[0]
                self.questions[question_num].feedbackTextArea.content_wo_resourcePaths \
                        = inner_feedback.renderContents().decode('utf-8')
                # and add the LOCAL resource paths back in:
                self.questions[question_num].feedbackTextArea.content_w_resourcePaths \
                        = self.questions[question_num].feedbackTextArea.MassageResourceDirsIntoContent( \
                            self.questions[question_num].feedbackTextArea.content_wo_resourcePaths)
                self.questions[question_num].feedbackTextArea.content = \
                        self.questions[question_num].feedbackTextArea.content_w_resourcePaths
            else:
                # no user-defined feedback, just using the default:
                self.questions[question_num].feedbackTextArea.content = ""
                self.questions[question_num].feedbackTextArea.content_w_resourcePaths \
                        = ""
                self.questions[question_num].feedbackTextArea.content_wo_resourcePaths \
                        = ""

    def upgradeToVersion1(self):
        """
        Upgrades the node from version 0 to 1.
        Old packages will loose their icons, but they will load.
        """
        log.debug(u"Upgrading iDevice")
        self.icon = u"multichoice"

    def upgradeToVersion2(self):
        """
        Upgrades the node from 1 (v0.5) to 2 (v0.6).
        Old packages will loose their icons, but they will load.
        """
        log.debug(u"Upgrading iDevice")
        self.emphasis = Idevice.SomeEmphasis

    def upgradeToVersion3(self):
        """
        Upgrades the node from 1 (v0.6) to 2 (v0.7).
        Change icon from 'multichoice' to 'question'
        """
        log.debug(u"Upgrading iDevice icon")
        self.icon = "question"

    def upgradeToVersion4(self):
        """
        Upgrades v0.6 to v0.7.
        """
        self.lastIdevice = False

    def upgradeToVersion5(self):
        """
        Upgrades exe to v0.10
        """
        self._upgradeIdeviceToVersion1()
        self._hintInstruc = self.__dict__['hintInstruc']
        self._questionInstruc = self.__dict__['questionInstruc']
        self._keyInstruc = self.__dict__['keyInstruc']

    def upgradeToVersion6(self):
        """
        Upgrades exe to v0.11
        """
        self._feedbackInstruc = x_(u"""Type in the feedback that you want the 
student to see when selecting the particular question. If you don't complete
this box, eXe will automatically provide default feedback as follows: 
"Correct answer" as indicated by the selection for the correct answer; or 
"Wrong answer" for the other alternatives.""")

    def upgradeToVersion7(self):
        """
        Upgrades to v0.12
        """
        self._upgradeIdeviceToVersion2()
        self.systemResources += [
            "common.js", "libot_drag.js", "panel-amusements.png",
            "stock-stop.png"
        ]

    def upgradeToVersion8(self):
        """
        Upgrades to v0.15
        """
        self.instructionsForLearners = TextAreaField(
            x_(u'Instructions'),
            x_(u"""Provide instruction on how the True/False Question should be 
completed."""),
            x_(u'Read the paragraph below and '
               'fill in the missing words.'))
        self.instructionsForLearners.idevice = self

    def upgradeToVersion9(self):
        """ 
        Upgrades to somewhere before version 0.25 (post-v0.24) 
        Taking the TrueFalseQuestions' old unicode string fields, 
        and converting them into a image-enabled TextAreaFields:
        """
        for question in self.questions:
            question.upgrade_setIdevice(self)

    def upgradeToVersion10(self):
        if "libot_drag.js" in self.systemResources:
            self.systemResources.remove("libot_drag.js")

    def upgradeToVersion11(self):
        """
        Delete icon from system resources
        """
        self._upgradeIdeviceToVersion3()
예제 #19
0
class RssIdevice(Idevice):
    """
    An RSS Idevice is one built from a RSS feed.
    """
    def __init__(self):
        Idevice.__init__(
            self, x_(u"RSS"), x_(u"Auckland University of Technology"),
            x_(u"""The RSS iDevice is used 
to provide new content to an individual users machine. Using this
iDevice you can provide links from a feed you select for learners to view."""),
            u"", u"")
        self.emphasis = Idevice.NoEmphasis
        self.rss = TextAreaField(x_(u"RSS"))
        self.rss.idevice = self
        self.icon = u"inter"
        self._urlInstruc = x_(u"""Enter an RSS URL for the RSS feed you 
want to attach to your content. Feeds are often identified by a small graphic
 icon (often like this <img src="/images/feed-icon.png" />) or the text "RSS". Clicking on the 
 icon or text label will display an RSS feed right in your browser. You can copy and paste the
URL into this field. Alternately, right clicking on the link or graphic will open a menu box;
click on COPY LINK LOCATION or Copy Shortcut. Back in eXe open the RSS bookmark iDevice and Paste the URL 
into the RSS URL field and click the LOAD button. This will extract the titles from your feed and
display them as links in your content. From here you can edit the bookmarks and add
 instructions or additional learning information.""")
        self.url = ""

    # Properties
    urlInstruc = lateTranslate('urlInstruc')

    def getResourcesField(self, this_resource):
        """
        implement the specific resource finding mechanism for this iDevice:
        """
        # be warned that before upgrading, this iDevice field could not exist:
        if hasattr(self, 'rss') and hasattr(self.rss, 'images'):
            for this_image in self.rss.images:
                if hasattr(this_image, '_imageResource') \
                    and this_resource == this_image._imageResource:
                    return self.rss

        return None

    def getRichTextFields(self):
        """
        Like getResourcesField(), a general helper to allow nodes to search 
        through all of their fields without having to know the specifics of each
        iDevice type.  
        """
        fields_list = []
        if hasattr(self, 'rss'):
            fields_list.append(self.rss)

        return fields_list

    def loadRss(self, url):
        """
        Load the rss
        """
        content = ""
        try:
            rssDic = feedparser.parse(url)
            length = len(rssDic['entries'])
            if length > 0:
                for i in range(0, length):
                    content += '<p><A href="%s">%s</A></P>' % (
                        rssDic['entries'][i].link, rssDic['entries'][i].title)
        except IOError, error:
            log.warning(unicode(error))
            content += _(
                u"Unable to load RSS feed from %s <br/>Please check the spelling and connection and try again."
            ) % url

        if content == "":
            content += _(
                u"Unable to load RSS feed from %s <br/>Please check the spelling and connection and try again."
            ) % url
        self.rss.content = unicode(content)
        # now that these are supporting images, any direct manipulation
        # of the content field must also store this updated information
        # into the other corresponding fields of TextAreaField:
        # (perhaps eventually a property should be made for TextAreaField
        #  such that these extra set's are not necessary, but for now, here:)
        self.rss.content_w_resourcePaths = self.rss.content
        self.rss.content_wo_resourcePaths = self.rss.content
예제 #20
0
class AttachmentIdevice(Idevice):
    """
    An Attachment Idevice allows a file to be attached to a package.
    """
    persistenceVersion = 4

    # 2013-11-04, JRF: added .odp examples to the .ppt references
    def __init__(self):
        Idevice.__init__(
            self, x_(u"Attachment"), x_(u"University of Auckland"),
            x_(u"The attachment iDevice is used to attach "
               "existing files to your .elp content. For example, "
               "you might have a PDF file or a PPT or .ODP presentation "
               "file that you wish the learners to have access "
               "to, these can be attached and labeled to indicate "
               "what the attachment is and how large the file is. "
               "Learners can click on the attachment link and can "
               "download the attachment."), u"", u"")

        self.emphasis = Idevice.NoEmphasis
        self.label = u''

        self._descriptionInstruc = x_(u"Enter the text you wish to associate "
                                      u"with the downloaded file. You might "
                                      u"want to provide instructions on what "
                                      u"you require the learner to do once "
                                      u"the file is downloaded or how the "
                                      u"material should be used.")

        self.descriptionTextArea = TextAreaField(x_(u'Description:'),
                                                 self._descriptionInstruc, u'')
        self.descriptionTextArea.idevice = self

        self._filenameInstruc = x_(u'Click <strong>Select a file</strong>, '
                                   'browse to the file you want '
                                   'to attach and select it.')
        self._labelInstruc = x_(u"<p>"
                                "Assign a label for the attachment. It "
                                "is useful to include the type of file. "
                                "Eg. pdf, ppt, .odp, etc."
                                "</p>"
                                "<p>"
                                "Including the size is also recommended so "
                                "that after your package is exported "
                                "to a web site, people will have an idea "
                                "how long it would take to download this "
                                "attachment."
                                "</p>"
                                "<p>"
                                "For example: "
                                "<code>Sales Forecast.doc (500kb)</code>"
                                "</p>")

    # Properties
    filenameInstruc = lateTranslate('filenameInstruc')
    labelInstruc = lateTranslate('labelInstruc')
    descriptionInstruc = lateTranslate('descriptionInstruc')

    def setAttachment(self, attachmentPath):
        """
        Store the attachment in the package
        Needs to be in a package to work.
        """
        log.debug(u"setAttachment " + unicode(attachmentPath))
        resourceFile = Path(attachmentPath)

        assert self.parentNode, \
               _('Attachment %s has no parentNode') % self.id
        assert self.parentNode.package, \
               _('iDevice %s has no package') % self.parentNode.id

        if resourceFile.isfile():
            if self.userResources:
                # Clear out old attachment/s
                while self.userResources:
                    self.userResources[0].delete()
            # Create the new resource
            Resource(self, resourceFile)
        else:
            log.error('File %s is not a file' % resourceFile)

    def getResourcesField(self, this_resource):
        """
        implement the specific resource finding mechanism for this iDevice:
        """
        # be warned that before upgrading, this iDevice field could not exist:
        if hasattr(self, 'descriptionTextArea')\
        and hasattr(self.descriptionTextArea, 'images'):
            for this_image in self.descriptionTextArea.images:
                if hasattr(this_image, '_imageResource') \
                and this_resource == this_image._imageResource:
                    return self.descriptionTextArea

        # if this_resource wasn't found in the above TextArea, but is still
        # listed within the iDevice's userResources, then we can assume
        # that this_resource is the attached resource, even though that
        # has no direct field.
        # As such, merely return the resource itself, to indicate that
        # it DOES belong to this iDevice, but is not a FieldWithResources:
        if this_resource in self.userResources:
            return this_resource

        return None

    def getRichTextFields(self):
        """
        Like getResourcesField(), a general helper to allow nodes to search 
        through all of their fields without having to know the specifics of each
        iDevice type.  
        """
        fields_list = []
        if hasattr(self, 'descriptionTextArea'):
            fields_list.append(self.descriptionTextArea)
        return fields_list

    def upgradeToVersion1(self):
        """
        Upgrades v0.6 to v0.7.
        """
        self.lastIdevice = False

    def upgradeToVersion2(self):
        """
        Upgrades to v0.10
        """
        self._upgradeIdeviceToVersion1()
        self._filenameInstruc = self.__dict__.get('filenameInstruc', '')
        self._labelInstruc = self.__dict__.get('labelInstruc', '')
        self._descriptionInstruc = self.__dict__.get('descriptionInstruc', '')

    def upgradeToVersion3(self):
        """
        Upgrades to v0.12
        """
        self._upgradeIdeviceToVersion2()
        if self.filename and self.parentNode:
            Resource(self, Path(self.filename))
        del self.filename

    def upgradeToVersion4(self):
        """
        Upgrades to somewhere before version 0.25 (post-v0.24)
        Taking the old .description unicode string field, 
        and converting it into an image-enabled TextAreaField:
        """
        self.descriptionTextArea = TextAreaField(x_(u'Description:'),
                                                 self._descriptionInstruc,
                                                 self.description)
        self.descriptionTextArea.idevice = self
예제 #21
0
class ListaField(FieldWithResources):
    """
    This field handles a passage with words that the student must choose in
    And can now support multiple images (and any other resources) via tinyMCE
    """

    regex = re.compile('(%u)((\d|[A-F]){4})', re.UNICODE)
    persistenceVersion = 3

    # these will be recreated in FieldWithResources' TwistedRePersist:
    nonpersistant = ['content', 'content_wo_resourcePaths']

    def __init__(self, name, instruc):
        """
        Initialise
        """
        FieldWithResources.__init__(self, name, instruc)
        self.parts = []
        self._encodedContent = ''
        self.rawContent = ''
        self._setVersion2Attributes()
        self.otras = ''
        self.otrasInstruc = \
            x_(u"<p>Optional: Write other words to complete the Dropdown activity.<br/> Use | (the vertical bar) to separate words.<br/> This field can be left blank. </p>")

    def _setVersion2Attributes(self):
        """
        Sets the attributes that were added in persistenceVersion 2
        """

        #self.showScore = False
        #self._showScoreInstruc = \
        #x_(u"""<p>Si esta opci&oacute;n esta marcada se muestra la puntuaci&oacute;n obtenida.</p>""")

    # Property handlers
    def set_encodedContent(self, value):
        """
        Cleans out the encoded content as it is passed in. Makes clean XHTML.
        """
        for key, val in name2codepoint.items():
            value = value.replace('&%s;' % key, unichr(val))
        # workaround for Microsoft Word which incorrectly quotes font names
        value = re.sub(r'font-family:\s*"([^"]+)"', r'font-family: \1', value)
        parser = ListaHTMLParser()
        parser.feed(value)
        parser.close()
        self.parts = parser.result
        encodedContent = ''
        for shown, hidden in parser.result:
            encodedContent += shown
            if hidden:
                encodedContent += ' <u>'
                encodedContent += hidden
                encodedContent += '</u> '
        self._encodedContent = encodedContent

    # Properties
    encodedContent = property(lambda self: self._encodedContent,
                              set_encodedContent)
    #showScoreInstruc      = lateTranslate('showScoreInstruc')
    otrasInstruc = lateTranslate('otrasInstruc')

    def upgradeToVersion1(self):
        """
        Upgrades to exe v0.11
        """
        self.autoCompletion = True
        self.autoCompletionInstruc = _(u"""Allow auto completion when 
                                       user filling the gaps.""")

    def upgradeToVersion2(self):
        """
        Upgrades to exe v0.12
        """
        Field.upgradeToVersion2(self)
        strictMarking = not self.autoCompletion
        del self.autoCompletion
        del self.autoCompletionInstruc
        self._setVersion2Attributes()
        self.strictMarking = strictMarking

    def upgradeToVersion3(self):
        """
        Upgrades to somewhere before version 0.25 (post-v0.24) 
        to reflect that ClozeField now inherits from FieldWithResources,
        and will need its corresponding fields populated from content.
        """
        self.content = self.encodedContent
        self.content_w_resourcePaths = self.encodedContent
        self.content_wo_resourcePaths = self.encodedContent
예제 #22
0
class TestQuestion(Persistable):
    """
    A TestQuestion is built up of question and AnswerOptions.
    """

    persistenceVersion = 3

    def __init__(self, idevice, question=""):
        """
        Initialize 
        """
        self.idevice = idevice

        self.options = []
        self.correctAns = -2
        self.userAns = -1
        self._questionInstruc = x_(u"""Enter the question stem. 
The quest should be clear and unambiguous. Avoid negative premises 
as these can tend to be ambiguous.""")
        self._optionInstruc = x_(u"""Enter an answer option. Provide 
a range of plausible distractors (usually 3-4) as well as the correct answer. 
Click on the &lt;Add another option&gt; button to add another answer.""")
        self._correctAnswerInstruc = x_(u"""To indicate the correct answer, 
click the radio button next to the correct option.""")

        self.questionTextArea = TextAreaField(x_(u'Question:'),
                                              self._questionInstruc, u'')
        self.questionTextArea.idevice = self.idevice

        self.addOption()

    # Properties
    questionInstruc = lateTranslate('questionInstruc')
    optionInstruc = lateTranslate('optionInstruc')
    correctAnswerInstruc = lateTranslate('correctAnswerInstruc')

    def addOption(self):
        """
        Add a new option to this question. 
        """
        self.options.append(AnswerOption(self, self.idevice))

    def getResourcesField(self, this_resource):
        """
        implement the specific resource finding mechanism for this iDevice:
        """
        # be warned that before upgrading, this iDevice field could not exist:
        if hasattr(self, 'questionTextArea')\
        and hasattr(self.questionTextArea, 'images'):
            for this_image in self.questionTextArea.images:
                if hasattr(this_image, '_imageResource') \
                and this_resource == this_image._imageResource:
                    return self.questionTextArea

        for this_option in self.options:
            this_field = this_option.getResourcesField(this_resource)
            if this_field is not None:
                return this_field

        return None

    def getRichTextFields(self):
        """
        Like getResourcesField(), a general helper to allow nodes to search 
        through all of their fields without having to know the specifics of each
        iDevice type.  
        """
        fields_list = []
        if hasattr(self, 'questionTextArea'):
            fields_list.append(self.questionTextArea)

        for this_option in self.options:
            fields_list.extend(this_option.getRichTextFields())

        return fields_list

    def upgradeToVersion1(self):
        """
        Upgrades to v 0.13
        """
        self._optionInstruc = x_(u"""Enter an answer option. Provide 
a range of plausible distractors (usually 3-4) as well as the correct answer. 
Click on the &lt;Add another option&gt; button to add another answer.""")

    def upgradeToVersion2(self):
        """
        Upgrades to v 0.13
        """
        self._questionInstruc = x_(u"""Enter the question stem. 
The quest should be clear and unambiguous. Avoid negative premises 
as these can tend to be ambiguous.""")

    def upgradeToVersion3(self):
        """
        Upgrades to v 0.13
        """
        self._correctAnswerInstruc = x_(u"""To indicate the correct answer, 
click the radio button next to the correct option.""")

    def upgrade_setIdevice(self, idevice):
        """
        While some of this might typically be done in an automatic upgrade
        method called from in increased persistence version, the problem
        with that approach is that the idevice was not previously stored,
        and cannot easily be gotten at that stage of operation. 

        Rather than making such an upgrade method more messy than necessary,
        this method allows the parent TestQuestionIdevice to merely set
        itself on each of its TestQuestions during its own upgrade.

        Helps upgrade to somewhere before version 0.25 (post-v0.24),
        taking the old unicode string fields, 
        and converting them into a image-enabled TextAreaFields:
        """
        self.idevice = idevice
        self.questionTextArea = TextAreaField(x_(u'Question:'),
                                              self._questionInstruc,
                                              self.question)
        self.questionTextArea.idevice = self.idevice

        # and then, need to propagate the same upgrades
        # down through each of the options:
        for option in self.options:
            option.upgrade_setIdevice(self.idevice, self)
예제 #23
0
class AppletIdevice(Idevice):
    """
    Java Applet Idevice. Enables you to embed java applet in the browser
    """
    persistenceVersion = 1

    def __init__(self, parentNode=None):
        """
        Sets up the idevice title and instructions etc.
        """
        Idevice.__init__(self, x_(u"Java Applet"),
                         x_(u"University of Auckland"), u"", u"", u"",
                         parentNode)
        self.emphasis = Idevice.NoEmphasis
        self.appletCode = u""
        self.type = u"other"
        self._fileInstruc = x_(u"""Add all the files provided for the applet
except the .txt file one at a time using the add files and upload buttons. The 
files, once loaded will be displayed beneath the Applet code field.""")
        self._codeInstruc = x_(u""""Find the .txt file (in the applet file) 
and open it. Copy the contents of this file <ctrl A, ctrl C> into the applet 
code field.""")
        self._typeInstruc = x_(
            u""" <p>If the applet you're adding was generated 
by one of the programs in this drop down, please select it, 
then add the data/applet file generated by your program. </p>
<p>eg. For Geogebra applets, select geogebra, then add the .ggb file that 
you created in Geogebra.</p>""")
        self.message = ""

    # Properties
    fileInstruc = lateTranslate('fileInstruc')
    codeInstruc = lateTranslate('codeInstruc')
    typeInstruc = lateTranslate('typeInstruc')

    global DESC_PLUGIN
    DESC_PLUGIN = 0

    def getResourcesField(self, this_resource):
        """
        implement the specific resource finding mechanism for this iDevice:
        """
        # if this_resource is listed within the iDevice's userResources,
        # then we can assume that this_resource is indeed a valid resource,
        # even though that has no direct field.
        # As such, merely return the resource itself, to indicate that
        # it DOES belong to this iDevice, but is not a FieldWithResources:
        if this_resource in self.userResources:
            return this_resource

        return None

    def getRichTextFields(self):
        """
        Like getResourcesField(), a general helper to allow nodes to search 
        through all of their fields without having to know the specifics of each
        iDevice type.  
        """
        # Applet iDevice has no rich-text fields:
        return []

    def burstHTML(self, i):
        """
        takes a BeautifulSoup fragment (i) and bursts its contents to 
        import this idevice from a CommonCartridge export
        """
        # Java Applet Idevice:
        #title = i.find(name='span', attrs={'class' : 'iDeviceTitle' })
        #idevice.title = title.renderContents().decode('utf-8')
        # no title for this idevice.
        # =====> WARNING: not yet loading any of the files!
        # BEWARE also of the appletCode line breaks loading as <br/>,
        # may want change this back to \n or \r\n?
        # AND: also need to load the applet type: Geogebra or Other.
        inner = i.find(name='div', attrs={'class': 'iDevice emphasis0'})
        self.appletCode = inner.renderContents().decode('utf-8')

    def verifyConn(self, site):
        """
        verify if the URL indicated by the user is reachable
        """
        import httplib
        import socket
        import re
        timeout = 30
        socket.setdefaulttimeout(timeout)
        try:
            patron = '(?:http.*://)?(?P<host>[^:/ ]+).?(?P<port>[0-9]*).*'
            portandhost = re.search(patron, site)
            port = portandhost.group('port')
            host = portandhost.group('host')
            if not portandhost.group('port'):
                port = '80'
            conn = httplib.HTTPConnection(host, port)
            # now the real connection test:
            conn.connect()
        except (httplib.HTTPResponse, socket.error):
            return False
        try:
            # nothing more needed:
            conn.close()
        except:
            pass
        return True

    def uploadFile(self, filePath):
        """
        Store the upload files in the package
        Needs to be in a package to work.
        """
        if self.type == "descartes" and not filePath.endswith(".jar"):
            if filePath.find(",") == -1:
                global SCENE_NUM
                SCENE_NUM = 1
            else:
                SCENE_NUM = int(filePath[:filePath.find(",")])
        if self.type == "descartes" and (filePath.endswith(".htm")
                                         or filePath.endswith(".html")):
            global url
            url = filePath
            self.appletCode = self.getAppletcodeDescartes(filePath)
            # none scene was found:
            if self.appletCode == '':
                return None
        else:
            log.debug(u"uploadFile " + unicode(filePath))
            resourceFile = Path(filePath)
            assert self.parentNode, _('file %s has no parentNode') % self.id
            assert self.parentNode.package, \
                    _('iDevice %s has no package') % self.parentNode.id
            if resourceFile.isfile():
                self.message = ""
                Resource(self, resourceFile)
                if self.type == "geogebra":
                    self.appletCode = self.getAppletcodeGeogebra(
                        resourceFile.basename().replace(' ', '_').replace(
                            ')', '').replace('(', ''))
                if self.type == "jclic":
                    self.appletCode = self.getAppletcodeJClic(
                        resourceFile.basename().replace(' ', '_').replace(
                            ')', '').replace('(', ''))
                if self.type == "scratch":
                    self.appletCode = self.getAppletcodeScratch(
                        resourceFile.basename().replace(' ', '_').replace(
                            ')', '').replace('(', ''))
                if self.type == "descartes":
                    self.appletCode = self.getAppletcodeDescartes(
                        resourceFile.basename())
                ## next code should be used to load in the editor the HTML code of the html file:
                # if self.type == "other":
                #     if filePath.endswith(".html") or filePath.endswith(".htm"):
                #         content = open(filePath, 'r')
                #         str = content.read()
                #         self.appletCode = str
                #         content.close()
                #    else:
                #        log.error('File %s is not a HTML file' % resourceFile)
            else:
                log.error('File %s is not a file' % resourceFile)

    def deleteFile(self, fileName):
        """
        Delete a selected file
        """
        for resource in self.userResources:
            if resource.storageName == fileName:
                resource.delete()
                break

    def getAppletcodeGeogebra(self, filename):
        """
        xhtml string for GeoGebraApplet
        """

        html = """
        <applet code="geogebra.GeoGebraApplet.class" archive="geogebra.jar" width="750" height="450">
            <param name="filename" value="%s">
            <param name="framePossible" value="true">
            <param name="java_arguments" value="-Xmx1024m"/>
            <param name="showResetIcon" value="true"/>
            <param name="showAnimationButton" value="true"/>
            <param name="errorDialogsActive" value="true"/>
            <param name="enableRightClick" value="true"/>
            <param name="enableLabelDrags" value="false"/>
            <param name="showMenuBar" value="false"/>
            <param name="showToolBar" value="true"/>
            <param name="showToolBarHelp" value="true"/>
            <param name="enableShiftDragZoom" value="true"/><param name="showAlgebraInput" value="false"/>
            <param name="useBrowserForJS" value="false" />
            <param name="cache_archive" value="geogebra.jar,geogebra_main.jar, geogebra_gui.jar, geogebra_cas.jar,geogebra_algos.jar, geogebra_export.jar, geogebra_javascript.jar,jlatexmath.jar, jlm_greek.jar, jlm_cyrillic.jar,geogebra_properties.jar" />
            Please <a href="http://java.sun.com/getjava"> install Java 1.4</a> (or later) to use this page.
        </applet> """ % filename

        return html

    def getAppletcodeJClic(self, filename):
        """
        xhtml string for JClicApplet
        """
        html = """
            <applet code="JClicApplet" archive="jclic.jar" width="800" height="600">
            <param name="name" value="JClicApplet">
            <param name="activitypack" value="%s">
            <param name="framePossible" value="false">
            Please <a href="http://java.sun.com/getjava"> install Java 1.4</a> (or later) to use this page.
        </applet> """ % filename

        return html

    def getAppletcodeScratch(self, project):
        """
        xhtml string for ScratchApplet
        """
        html = """
            <applet id="ProjectApplet" style="display:block" code="ScratchApplet" archive="ScratchApplet.jar" width="482" height="387">
            <param name="project" value="%s">
            <param name="useBrowserForJS" value="false" />
            Please <a href="http://java.sun.com/getjava"> install Java 1.4</a> (or later) to use this page.
        </applet> """ % project

        return html

    def downloadFiles(self, stringapplet):
        """
        only for DescartesApplet initially; three jobs:
        1 look for image and macros files in the URL indicated by the user,
        2 modify applet code for a correct exe detection of them after this,
        3 download and store them into the exe project (absolute urls are required).
        Return the code modified.
        """
        from BeautifulSoup import BeautifulSoup, BeautifulStoneSoup
        import re
        import urllib
        import urllib2
        import string
        import os
        # import urllib.request
        stringappletmod = stringapplet
        soup = BeautifulSoup(stringapplet)

        # ONE: image files:
        key_image = [
            'archivo=', 'imagem_de_fundo=', 'imagem=', 'imagen=', 'file=',
            'fitxer=', 'artxibo=', 'image=', 'bg_image=', 'imatge=',
            'immagine=', 'irudia=', 'irundia=', 'fichier=', 'imaxe=',
            'arquivo=', 'immagine_fondo='
        ]
        # paths to the images indicated in the applet code:
        imageslist = []
        for x in key_image:
            if string.find(stringapplet, x) != -1:
                expression = r"%s'([\w\./]+)'" % x
                patron = re.compile(expression)
                for tag in soup.findAll('param'):
                    result = patron.search(tag['value'])
                    if result:
                        if result.group(1) not in imageslist:
                            imageslist.append(result.group(1))
        # modify applet code:
        urlimageslist = []
        for im in imageslist:
            # put as locals the images' path inside exe editor...
            stringappletmod = stringappletmod.replace(im,
                                                      im[im.rfind("/") + 1:])
            # from imageslist, it's neccesary to create the list of absolute paths to the image
            # files because we want to download this images and load them in the project:
            # first quit scene number
            urlnoesc = url[url.find(",") + 1:]
            # cut the right side of the last /:
            urlcut = urlnoesc[:urlnoesc.rfind("/")]
            # and extend with the image from the applet code:
            urlimageslist.append(urlcut + "/" + im)
        # repeated no thanks:
        urlimageslist = list(set(urlimageslist))
        # do not forget that it could be image_down and image_over versions
        # of the file in the same place, so... a new extended list:
        urlimgslistextended = []
        for pathimg in urlimageslist:
            # we trick to urlimageslist adding files that haven't been detected really
            if pathimg not in urlimgslistextended:
                urlimgslistextended.append(pathimg)
                if string.find(pathimg, '.png') != -1:
                    urlimgslistextended.append(
                        pathimg.replace('.png', '_down.png'))
                    urlimgslistextended.append(
                        pathimg.replace('.png', '_over.png'))
                if string.find(pathimg, '.jpg') != -1:
                    urlimgslistextended.append(
                        pathimg.replace('.jpg', '_down.jpg'))
                    urlimgslistextended.append(
                        pathimg.replace('.jpg', '_over.jpg'))
                if string.find(pathimg, '.gif') != -1:
                    urlimgslistextended.append(
                        pathimg.replace('.gif', '_down.gif'))
                    urlimgslistextended.append(
                        pathimg.replace('.gif', '_over.gif'))
        urlimgslistextended = list(set(urlimgslistextended))
        # now we can: download all you can find:
        for pathimgext in urlimgslistextended:
            # the clean name of the image file
            img = pathimgext[pathimgext.rfind("/") + 1:]
            # firstly to test the existence of the file:
            try:
                resp = urllib2.urlopen(pathimgext)
            except urllib2.URLError, e:
                if not hasattr(e, "code"):
                    raise
                resp = e
            try:
                # download whith its original name:
                img_down = urllib.urlretrieve(pathimgext, img)
            except:
                print 'Unable to download file'
            # be sure the file was found:
            if img_down[1].maintype == 'image':
                self.uploadFile(img_down[0])
            os.remove(img_down[0])
        # change the path in the soup, now the file will be local:
        for x in imageslist:
            if x in soup:
                x = x[x.rfind("/") + 1:]

        # TWO: local macros (sometimes a macro that is called may reside inside the jar file)
        # paths to the macros indicated in the applet code:
        macroslist = []
        key_typo = ['tipo=', 'tipus=', 'type=', 'mota=']
        for x in key_typo:
            if string.find(stringapplet, x) != -1:
                expression = r"%s'ma[ck]ro'" % x
                patron = re.compile(expression)
                for tag in soup.findAll('param'):
                    result = patron.search(tag['value'])
                    if result:
                        # tipo = macro or makro finded, now we need expresion parameter inside value tag
                        key_macro = [
                            'expresión=', 'expresion=', 'adierazpen=',
                            'espressione=', 'expresi&oacute;n=',
                            'expresi&oacute;=', 'expresi&amp;oacute;n=',
                            'express&atilde;o='
                        ]
                        for y in key_macro:
                            if string.find(tag, y) != -1:
                                # consider sometimes macro file has txt format but sometimes has not format...
                                # and sometimes they are locals and sometimes they are inside the jar file
                                wexpression = ur"%s'(?P<bla>[\w./]+)'" % y  # notice unicode conversion
                                wpatron = re.compile(wexpression)
                                # convert tag to unicode string also:
                                utag = unicode(tag)
                                wresult = wpatron.search(utag)
                                if wresult:
                                    macroslist.append(wresult.group('bla'))
        # repeated no thanks:
        macroslist = list(set(macroslist))
        # from macroslist, it's neccesary to create the list of absolute
        # paths to the macros because we want to download them:
        urlmacroslist = []
        for mac in macroslist:
            urlnoesc = url[url.find(",") + 1:]
            urlcut = urlnoesc[:urlnoesc.rfind("/")]
            urlmacroslist.append(urlcut + "/" + mac)
            urlmacroslist = list(set(urlmacroslist))
        # we try to download them but really we do not know if they will be
        # physically, as locals -out of the jar file- so our code must look for them,
        # and if they seem not to be we we will asume they are in the jar file
        for pathmacro in urlmacroslist:
            macro = pathmacro[pathmacro.rfind("/") + 1:]
            try:
                resp = urllib2.urlopen(pathmacro)
            except urllib2.URLError, e:
                if not hasattr(e, "code"):
                    raise
                resp = e
            if resp.code == 200:
                macro_down = urllib.urlretrieve(pathmacro, macro)
                self.uploadFile(macro_down[0])
                os.remove(macro_down[0])

                # and modify the applet code inside eXe, now the file will be local:
                for x in macroslist:
                    if x.endswith('.txt'):
                        if string.find(x, macro) != -1:
                            stringappletmod = stringappletmod.replace(x, macro)
예제 #24
0
class Idevice(Persistable):
    """
    The base class for all iDevices
    iDevices are mini templates which the user uses to create content in the 
    package
    """

    # Class attributes
    # see derieved classes for persistenceVersion
    nextId = 1
    NoEmphasis, SomeEmphasis, StrongEmphasis = range(3)

    def __init__(self, title, author, purpose, tip, icon, parentNode=None):
        """Initialize a new iDevice, setting a unique id"""
        log.debug("Creating iDevice")
        self.edit = True
        self.lastIdevice = True
        self.emphasis = Idevice.NoEmphasis
        self.version = 0
        self.id = unicode(Idevice.nextId)
        Idevice.nextId += 1
        self.parentNode = parentNode
        self._title = title
        self._author = author
        self._purpose = purpose
        self._tip = tip
        self.icon = icon
        # userResources are copied into and stored in the package
        self.userResources = []
        # systemResources are resources from whatever style dir we are using at render time
        self.systemResources = []
        self.originalicon = icon

    # Properties
    def get_title(self):
        """
        Gives a nicely encoded and translated title that can be put inside
        xul labels (eg. <label value="my &quot;idevice&quot;">)
        """
        if not hasattr(self, '_title'):
            self._title = 'NO TITLE'
        if self._title:
            title = c_(self._title)
            title = title.replace('&', '&amp;')
            title = title.replace('"', '&quot;')
            return title
        else:
            return u''

    def set_title(self, value):
        """
        Sets self._title
        """
        if c_(self._title) != value:
            self._title = value

    title = property(get_title, set_title)
    rawTitle = lateTranslate('title')
    author = lateTranslate('author')
    purpose = lateTranslate('purpose')
    tip = lateTranslate('tip')

    def get_klass(self):
        if hasattr(self, 'class_'):
            if self.class_ == '':
                # return u'customIdevice'
                # We add 3 classes to the custom iDevice
                # 1. customIdevice (common)
                customIdeviceClass = 'customIdevice '
                # 2. Title (with no spaces, etc.)
                if self._title == '':
                    customIdeviceClass += 'untitledIdevice'
                else:
                    customIdeviceClass += 'Idevice' + re.sub(
                        '\W+', '', self._title)
                # 3. Icon
                if self.icon:
                    customIdeviceClass += ' icon' + self.icon
                else:
                    customIdeviceClass += ' noIcon'
                return customIdeviceClass
            else:
                return self.class_ + u'Idevice'
        else:
            klass = str(self.__class__).split('.')[-1]
            return klass[:-2]

    klass = property(get_klass)

    def __cmp__(self, other):
        """
        Compare this iDevice with other
        """
        return cmp(self.id, other.id)

    def __deepcopy__(self, others):
        """
        Override deepcopy because normal one seems to skip things when called from resource.__deepcopy__
        """
        # Create a new me
        miniMe = self.__class__.__new__(self.__class__)
        others[id(self)] = miniMe
        # Copy our resources first
        miniMe.userResources = []
        for resource in self.userResources:
            miniMe.userResources.append(deepcopy(resource, others))
        # Copy the rest of our attributes
        for key, val in self.__dict__.items():
            if key != 'userResources':
                setattr(miniMe, key, deepcopy(val, others))
        miniMe.id = unicode(Idevice.nextId)
        Idevice.nextId += 1
        return miniMe

    # Public Methods

    def clone(self):
        """
        Clone an iDevice just like this one
        """
        log.debug("Cloning iDevice")
        newIdevice = copy.deepcopy(self)
        return newIdevice

    def delete(self):
        """
        delete an iDevice from it's parentNode
        """
        # Clear out old user resources
        # use reverse for loop to delete old user resources
        length = len(self.userResources)
        for i in range(length - 1, -1, -1):
            # possible bug fix, due to inconsistent order of loading:
            # ensure that this idevice IS attached to the resource:
            if self.userResources[i]._idevice is None:
                self.userResources[i]._idevice = self
            # and NOW we can finally properly delete it!
            self.userResources[i].delete()

        if self.parentNode:
            # first remove any internal anchors' links:
            self.ChangedParentNode(self.parentNode, None)

            self.parentNode.idevices.remove(self)
            self.parentNode = None

    def isFirst(self):
        """
        Return true if this is the first iDevice in this node
        """
        index = self.parentNode.idevices.index(self)
        return index == 0

    def isLast(self):
        """
        Return true if this is the last iDevice in this node
        """
        index = self.parentNode.idevices.index(self)
        return index == len(self.parentNode.idevices) - 1

    def movePrev(self):
        """
        Move to the previous position
        """
        parentNode = self.parentNode
        index = parentNode.idevices.index(self)
        if index > 0:
            temp = parentNode.idevices[index - 1]
            parentNode.idevices[index - 1] = self
            parentNode.idevices[index] = temp

    def moveNext(self):
        """
        Move to the next position
        """
        parentNode = self.parentNode
        index = parentNode.idevices.index(self)
        if index < len(parentNode.idevices) - 1:
            temp = parentNode.idevices[index + 1]
            parentNode.idevices[index + 1] = self
            parentNode.idevices[index] = temp

    def setParentNode(self, parentNode):
        """
        Change parentNode
        Now includes support for renaming any internal anchors and their links.
        """
        old_node = None
        if self.parentNode:
            old_node = self.parentNode
            self.parentNode.idevices.remove(self)
        old_id = self.id
        parentNode.addIdevice(self)
        self.id = old_id
        # and update any internal anchors and their links:
        self.ChangedParentNode(old_node, parentNode)

    def ChangedParentNode(self, old_node, new_node):
        """
        To update all fo the anchors (if any) that are defined within
        any of this iDevice's various fields, and any 
        internal links corresponding to those anchors.
        This is essentially a variation of Node:RenamedNode()
        It also removes any internal links from the data structures as well, 
        if this iDevice is being deleted
        """
        my_fields = self.getRichTextFields()
        num_fields = len(my_fields)
        for field_loop in range(num_fields - 1, -1, -1):
            this_field = my_fields[field_loop]
            if hasattr(this_field, 'anchor_names') \
            and len(this_field.anchor_names) > 0:
                # okay, this is an applicable field with some anchors:
                this_field.ReplaceAllInternalAnchorsLinks(oldNode=old_node,
                                                          newNode=new_node)

                if new_node:
                    # add this particular anchor field into the new node's list:
                    if not hasattr(new_node, 'anchor_fields'):
                        new_node.anchor_fields = []
                    if this_field not in new_node.anchor_fields:
                        new_node.anchor_fields.append(this_field)
                    if new_package:
                        if not hasattr(new_package, 'anchor_nodes'):
                            new_package.anchor_nodes = []
                        if new_node not in new_package.anchor_nodes:
                            new_package.anchor_nodes.append(new_node)

            # now, regardless of whether or not that field has any anchors,
            # if this idevice is being deleted (new_node is None), then
            # go ahead and remove any of its internal links
            # from the corresponding data structures:
            if not new_node \
            and hasattr(this_field, 'intlinks_to_anchors') \
            and len(this_field.intlinks_to_anchors) > 0:
                this_field.RemoveAllInternalLinks()

        return

    def getResourcesField(self, this_resource):
        """
        Allow resources to easily find their specific corresponding field,
        to help out with loading and especially merging scenarios for resources
        with names already in use, for example.
        This method is expected to be overridden within each specific iDevice.
        """
        # in the parent iDevice class, merely return a None,
        # and let each specific iDevice class implement its own version:
        log.warn("getResourcesField called on iDevice; no specific " +
                 "implementation available for this particular iDevice " +
                 "class: " + repr(self))
        return None

    def getRichTextFields(self):
        """
        Like getResourcesField(), a general helper to allow nodes to search 
        through all of their fields without having to know the specifics of each
        iDevice type.  
        Currently used by Extract to find all fields which have internal links.
        """
        # in the parent iDevice class, merely return an empty list,
        # and let each specific iDevice class implement its own version:
        log.warn("getRichTextFields called on iDevice; no specific " +
                 "implementation available for this particular iDevice " +
                 "class: " + repr(self))
        return []

    # Protected Methods

    def _upgradeIdeviceToVersion1(self):
        """
        Upgrades the Idevice class members from version 0 to version 1.
        Should be called in derived classes.
        """
        log.debug("upgrading to version 1")
        self._title = self.__dict__.get('title', self.title)
        self._author = self.__dict__.get('author', self.title)
        self._purpose = self.__dict__.get('purpose', self.title)
        self._tip = self.__dict__.get('tip', self.title)

    def _upgradeIdeviceToVersion2(self):
        """
        Upgrades the Idevice class members from version 1 to version 2.
        Should be called in derived classes.
        """
        log.debug("upgrading to version 2, for 0.12")
        self.userResources = []
        if self.icon:
            self.systemResources = ["icon_" + self.icon + ".gif"]
        else:
            self.systemResources = []

    def _upgradeIdeviceToVersion3(self):
        if self.icon:
            icon = "icon_" + self.icon + ".gif"
            if icon in self.systemResources:
                self.systemResources.remove(icon)

    def _upgradeIdeviceToVersion4(self):
        pass
예제 #25
0
class NotaIdevice(Idevice):
    """
    Note Idevice is for comments
    """
    persistenceVersion = 7

    def __init__(self, activity="", answer=""):
        """
        Initialize 
        """
        Idevice.__init__(self, x_(u"Note"), x_(u"exelearning.net"), u"",
                         u"Note", "")
        self.emphasis = Idevice.SomeEmphasis
        self._commentInstruc = u""
        self.systemResources += ["common.js"]

        self.commentTextArea = TextAreaField(x_(u'Comment:'),
                                             self._commentInstruc, answer)
        self.commentTextArea.idevice = self

    # Properties
    commentInstruc = lateTranslate('commentInstruc')

    def getResourcesField(self, this_resource):
        """
        implement the specific resource finding mechanism for this iDevice:
        """
        # be warned that before upgrading, this iDevice field could not exist:

        # be warned that before upgrading, this iDevice field could not exist:
        if hasattr(self, 'commentTextArea')\
        and hasattr(self.commentTextArea, 'images'):
            for this_image in self.commentTextArea.images:
                if hasattr(this_image, '_imageResource') \
                    and this_resource == this_image._imageResource:
                    return self.commentTextArea

        return None

    def getRichTextFields(self):
        """
        Like getResourcesField(), a general helper to allow nodes to search 
        through all of their fields without having to know the specifics of each
        iDevice type.  
        """
        fields_list = []

        if hasattr(self, 'commentTextArea'):
            fields_list.append(self.commentTextArea)

        return fields_list

    def upgradeToVersion1(self):
        """
        Upgrades the node from version 0 to 1.
        """
        log.debug(u"Upgrading iDevice")

    def upgradeToVersion2(self):
        """
        Upgrades the node from 1 (v0.5) to 2 (v0.6).
        Old packages will loose their icons, but they will load.
        """
        log.debug(u"Upgrading iDevice")
        self.emphasis = Idevice.SomeEmphasis

    def upgradeToVersion3(self):
        """
        Upgrades v0.6 to v0.7.
        """
        self.lastIdevice = False

    def upgradeToVersion4(self):
        """
        Upgrades to exe v0.10
        """
        self._upgradeIdeviceToVersion1()
        self._commentInstruc = self.__dict__['commentInstruc']

    def upgradeToVersion5(self):
        """
        Upgrades to exe v0.10
        """
        self._upgradeIdeviceToVersion1()

    def upgradeToVersion6(self):
        """
        Upgrades to v0.12
        """
        self._upgradeIdeviceToVersion2()
        self.systemResources += ["common.js"]

    def upgradeToVersion7(self):
        """ 
        Upgrades to somewhere before version 0.25 (post-v0.24) 
        Taking the old unicode string fields, and converting them 
        into image-enabled TextAreaFields:
        """
        self.commentTextArea = TextAreaField(x_(u'Feedback:'),
                                             self._commentInstruc, self.answer)
        self.commentTextArea.idevice = self

    def upgradeToVersion8(self):
        self.icon = ""