예제 #1
0
    def _process_media(self, fact):

        """Copy the media files to the media directory and edit the media
        table. We don't keep track of which facts use which media and delete
        a media file if it's no longer in use. The reason for this is that some
        people use the media directory as their only location to store their
        media files, and also use these files for other purposes.

        Note that not all 'added_media_file' events originated here, they are
        also generated by the latex subsystem, or by checking for files which
        were modified outside of Mnemosyne.

        """

        for match in re_src.finditer("".join(fact.data.values())):
            filename = match.group(2)
            if filename.startswith("http:"):
                continue
            if len(filename) > 200:
                self.main_widget().show_information(
                    _("Media filename rather long. This could cause problems using this file on a different OS.")
                )
            if "#" in filename:
                self.main_widget().show_information(
                    _("Filename contains '#', which could cause problems on some operating systems.")
                )
            if not path_exists(filename) and not path_exists(expand_path(filename, self.media_dir())):
                self.main_widget().show_error(_("Missing media file!") + "\n\n" + filename)
                for fact_key, value in fact.data.iteritems():
                    fact.data[fact_key] = fact.data[fact_key].replace(
                        match.group(), 'src_missing="%s"' % match.group(2)
                    )
                continue
            # If needed, copy file to the media dir. Normally this happens when
            # the user clicks 'Add image' e.g., but he could have typed in the
            # full path directly.
            if os.path.isabs(filename):
                filename = copy_file_to_dir(filename, self.media_dir())
            else:  # We always store Unix paths internally.
                filename = filename.replace("\\", "/")
            for fact_key, value in fact.data.iteritems():
                fact.data[fact_key] = value.replace(match.group(2), filename)
                self.con.execute(
                    """update data_for_fact set value=? where
                    _fact_id=? and key=?""",
                    (fact.data[fact_key], fact._id, fact_key),
                )
            if self.con.execute("select count() from media where filename=?", (filename,)).fetchone()[0] == 0:
                self.con.execute(
                    """insert into media(filename, _hash)
                    values(?,?)""",
                    (filename, self._media_hash(filename)),
                )
                # When we are applying log entries during sync or import, the
                # side effects of e.g. ADDED_FACT events should not generate
                # additional ADDED_MEDIA_FILE events at the remote partner, so
                # we disable the logging of these side effects in that case.
                if not self.syncing and not self.importing:
                    self.log().added_media_file(filename)
예제 #2
0
    def _process_media(self, fact):
        """Copy the media files to the media directory and edit the media
        table. We don't keep track of which facts use which media and delete
        a media file if it's no longer in use. The reason for this is that some
        people use the media directory as their only location to store their
        media files, and also use these files for other purposes.

        Note that not all 'added_media_file' events originated here, they are
        also generated by the latex subsystem, or by checking for files which
        were modified outside of Mnemosyne.

        """

        for match in re_src.finditer("".join(fact.data.values())):
            filename = match.group(2)
            if filename.startswith("http:"):
                continue
            if len(filename) > 200:
                self.main_widget().show_information(\
_("Media filename rather long. This could cause problems using this file on a different OS."))
            if "#" in filename:
                self.main_widget().show_information(\
_("Filename contains '#', which could cause problems on some operating systems."))
            if not path_exists(filename) and \
                not path_exists(expand_path(filename, self.media_dir())):
                self.main_widget().show_error(
                    _("Missing media file!") + "\n\n" + filename)
                for fact_key, value in fact.data.iteritems():
                    fact.data[fact_key] = \
                        fact.data[fact_key].replace(match.group(),
                        "src_missing=\"%s\"" % match.group(2))
                continue
            # If needed, copy file to the media dir. Normally this happens when
            # the user clicks 'Add image' e.g., but he could have typed in the
            # full path directly.
            if os.path.isabs(filename):
                filename = copy_file_to_dir(filename, self.media_dir())
            else:  # We always store Unix paths internally.
                filename = filename.replace("\\", "/")
            for fact_key, value in fact.data.iteritems():
                fact.data[fact_key] = value.replace(match.group(2), filename)
                self.con.execute(
                    """update data_for_fact set value=? where
                    _fact_id=? and key=?""",
                    (fact.data[fact_key], fact._id, fact_key))
            if self.con.execute("select count() from media where filename=?",
                                (filename, )).fetchone()[0] == 0:
                self.con.execute(
                    """insert into media(filename, _hash)
                    values(?,?)""", (filename, self._media_hash(filename)))
                # When we are applying log entries during sync or import, the
                # side effects of e.g. ADDED_FACT events should not generate
                # additional ADDED_MEDIA_FILE events at the remote partner, so
                # we disable the logging of these side effects in that case.
                if not self.syncing and not self.importing:
                    self.log().added_media_file(filename)
예제 #3
0
    def _media_hash(self, filename):
        """A hash function that will be used to determine whether or not a
        media file has been modified outside of Mnemosyne.

        'filename' is a relative path inside the media dir.

        In principle, you could have different hash implementations on
        different systems, as the hash is considered something internal and is
        not sent across during sync e.g..

        """

        filename = os.path.join(self.media_dir(), os.path.normcase(filename))
        if not path_exists(filename):
            return "0"
        try:
            media_file = file(filename, "rb")
        except UnicodeEncodeError:  # Android specific issue.
            media_file = file(filename.encode("utf-8"), "rb")
        hasher = md5()
        while True:
            buffer = media_file.read(8096)
            if not buffer:
                break
            hasher.update(buffer)
        return hasher.hexdigest()
예제 #4
0
    def _media_hash(self, filename):

        """A hash function that will be used to determine whether or not a
        media file has been modified outside of Mnemosyne.

        'filename' is a relative path inside the media dir.

        In principle, you could have different hash implementations on
        different systems, as the hash is considered something internal and is
        not sent across during sync e.g..

        """

        filename = os.path.join(self.media_dir(), os.path.normcase(filename))
        if not path_exists(filename):
            return "0"
        try:
            media_file = file(filename, "rb")
        except UnicodeEncodeError:  # Android specific issue.
            media_file = file(filename.encode("utf-8"), "rb")
        hasher = md5()
        while True:
            buffer = media_file.read(8096)
            if not buffer:
                break
            hasher.update(buffer)
        return hasher.hexdigest()
예제 #5
0
    def create_media_dir_if_needed(self):
        media_dir = self.media_dir()
        if not path_exists(media_dir):
            try:
                os.makedirs(media_dir)
            except WindowsError:
                self.main_widget().show_error(_("Could not create" ) + " " + \
media_dir + ".\n" + _("Check your file permissions and make sure the directory is not open in a file browser."))
예제 #6
0
 def check_for_edited_media_files(self):
     # Regular media files.
     new_hashes = {}
     for sql_res in self.con.execute("select filename, _hash from media"):
         filename, hash = sql_res[0], sql_res[1]
         if not path_exists(expand_path(filename, self.media_dir())):
             continue
         new_hash = self._media_hash(filename)
         if hash != new_hash:
             new_hashes[filename] = new_hash
     for filename, new_hash in new_hashes.iteritems():
         self.con.execute("update media set _hash=? where filename=?", (new_hash, filename))
         self.log().edited_media_file(filename)
예제 #7
0
 def create_media_dir_if_needed(self):
     media_dir = self.media_dir()
     if not path_exists(media_dir):
         try:
             os.makedirs(media_dir)
         except WindowsError:
             self.main_widget().show_error(
                 _("Could not create")
                 + " "
                 + media_dir
                 + ".\n"
                 + _("Check your file permissions and make sure the directory is not open in a file browser.")
             )
예제 #8
0
 def check_for_edited_media_files(self):
     # Regular media files.
     new_hashes = {}
     for sql_res in self.con.execute("select filename, _hash from media"):
         filename, hash = sql_res[0], sql_res[1]
         if not path_exists(expand_path(filename, self.media_dir())):
             continue
         new_hash = self._media_hash(filename)
         if hash != new_hash:
             new_hashes[filename] = new_hash
     for filename, new_hash in new_hashes.iteritems():
         self.con.execute("update media set _hash=? where filename=?",
                          (new_hash, filename))
         self.log().edited_media_file(filename)
예제 #9
0
    def media_filenames_to_sync_for(self, partner):

        """Determine which media files need to be sent across during the sync.
        Obviously, this only includes existing media files, not deleted ones.

        """

        _id = self.last_log_index_synced_for(partner)
        filenames = set()
        for filename in [cursor[0] for cursor in self.con.execute(\
            """select object_id from log where _id>? and (event_type=? or
            event_type=?)""", (_id, EventTypes.ADDED_MEDIA_FILE,
            EventTypes.EDITED_MEDIA_FILE))]:
            if path_exists(expand_path(filename, self.media_dir())):
                filenames.add(filename)                
        return filenames
예제 #10
0
    def add_media_file(self, log_entry):

        """ADDED_MEDIA_FILE events get created in several places:
        database._process_media, database.check_for_edited_media_files,
        latex, ... . In order to make sure that all of these are treated
        in the same way, we generate an ADDED_MEDIA_FILE event here, and
        prevent _process_media from generating this event through
        self.syncing = True.

        """

        filename = log_entry["fname"]
        full_path = expand_path(filename, self.media_dir())
        if path_exists(full_path):
            self.con.execute("""insert or replace into media(filename, _hash)
                values(?,?)""", (filename, self._media_hash(filename)))
        self.log().added_media_file(filename)