예제 #1
0
    def show_insert_img_dialog(self, filter):

        """Show a file dialog filtered on the supported filetypes, get a
        filename, massage it, and return it to the widget to be inserted.
        There is more media file logic inside the database code too, as the
        user could also just type in the html tags as opposed to passing
        through the file selector here. The reason we don't do all the
        operations in the database code, is that we want to display a nice
        short relative path back in the edit field.

        """

        from mnemosyne.libmnemosyne.utils import copy_file_to_dir
        data_dir, media_dir = \
            self.config().data_dir, self.database().media_dir()
        path = expand_path(self.config()["import_img_dir"], data_dir)
        filter = _("Image files") + " " + filter
        filename = self.main_widget().get_filename_to_open(\
            path, filter, _("Insert image"))
        if not filename:
            return ""
        else:
            self.config()["import_img_dir"] = contract_path(\
                os.path.dirname(filename), data_dir)
            filename = copy_file_to_dir(filename, media_dir)
            return contract_path(filename, media_dir)
예제 #2
0
파일: pickle.py 프로젝트: umax/pomni
 def new(self, path):
     if self.is_loaded():
         self.unload()
     path = expand_path(path, self.config().basedir)
     self.load_failed = False
     self.save(contract_path(path, self.config().basedir))
     self.config()["path"] = contract_path(path, self.config().basedir)
     self.log().new_database()
예제 #3
0
파일: qtextedit2.py 프로젝트: wojas/pomni
 def insert_sound(self):
     path = expand_path(config()["import_sound_dir"])
     fname = unicode(QFileDialog.getOpenFileName(self, _("Insert sound"),
                     path, _("Sound files") + \
                     " (*.wav *.mp3 *.ogg *.WAV *.MP3 *.OGG)"))
     if fname:
         self.insertPlainText("<sound src=\""+contract_path(fname)+"\">")
         config()["import_sound_dir"] = \
                    contract_path(os.path.dirname(fname))
예제 #4
0
파일: qtextedit2.py 프로젝트: wojas/pomni
 def insert_img(self):
     path = expand_path(config()["import_img_dir"])
     fname = unicode(QFileDialog.getOpenFileName(self, _("Insert image"),
                     path, _("Image files") + \
                     " (*.png *.gif *.jpg *.bmp *.jpeg" + \
                     " *.PNG *.GIF *.jpg *.BMP *.JPEG)"))
     if fname:
         self.insertPlainText("<img src=\""+contract_path(fname)+"\">")
         config()["import_img_dir"] = \
                    contract_path(os.path.dirname(fname))
예제 #5
0
파일: pickle.py 프로젝트: wojas/pomni
 def load(self, path):
     path = expand_path(path, config().basedir)
     if self.is_loaded():
         unload_database()
     if not os.path.exists(path):
         self.load_failed = True
         raise LoadError
     try:
         infile = file(path, 'rb')
         db = cPickle.load(infile)
         self.start_date = db[0]
         self.categories = db[1]
         self.facts = db[2]
         self.fact_views = db[3]           
         self.cards = db[4]
         infile.close()
         self.load_failed = False
     except:
         self.load_failed = True
         raise InvalidFormatError(stack_trace=True)
     # Work around a sip bug: don't store card types, but their ids.
     for f in self.facts:
         f.card_type = card_type_by_id(f.card_type)
     # TODO: This was to remove database inconsistencies. Still needed?
     #for c in self.categories:
     #    self.remove_category_if_unused(c)
     config()["path"] = contract_path(path, config().basedir)
     log().loaded_database()
     for f in component_manager.get_all("function_hook", "after_load"):
         f.run()
예제 #6
0
    def unused_media_files(self):
        """Returns a set of media files which are in the media directory but
        which are not referenced in the cards.

        """

        case_insensitive = is_filesystem_case_insensitive()
        # Files referenced in the database.
        files_in_db = set()
        for result in self.con.execute(\
            "select value from data_for_fact where value like '%src=%'"):
            for match in re_src.finditer(result[0]):
                filename = match.group(2)
                if case_insensitive:
                    filename = filename.lower()
                files_in_db.add(filename)
        # Files in the media dir.
        files_in_media_dir = set()
        for root, dirnames, filenames in os.walk(self.media_dir()):
            root = contract_path(root, self.media_dir())
            if root.startswith("_"):
                continue
            for filename in filenames:
                # Paths are stored using unix convention.
                if root:
                    filename = root + "/" + filename
                if case_insensitive:
                    filename = filename.lower()
                files_in_media_dir.add(filename)
        return files_in_media_dir - files_in_db
예제 #7
0
파일: SQLite.py 프로젝트: bartosh/pomni
 def new(self, path):
     if self.is_loaded():
         self.unload()
     self._path = expand_path(path, self.config().basedir)
     if os.path.exists(self._path):
         os.remove(self._path)
     self.load_failed = False
     # Create tables.
     self.con.executescript(SCHEMA)
     self.con.execute("insert into global_variables(key, value) values(?,?)",
         ("version", self.version))
     self.con.execute("""insert into partnerships(partner, _last_log_id)
         values(?,?)""", ("log.txt", 0))
     self.con.commit()
     self.config()["path"] = contract_path(self._path, self.config().basedir)
     # Create default criterion.
     from mnemosyne.libmnemosyne.activity_criteria.default_criterion import \
          DefaultCriterion
     self._current_criterion = DefaultCriterion(self.component_manager)
     self.add_activity_criterion(self._current_criterion)
     # Create media directory.
     mediadir = self.mediadir()
     if not os.path.exists(mediadir):
         os.mkdir(mediadir)
         os.mkdir(os.path.join(mediadir, "latex"))
예제 #8
0
    def unused_media_files(self):

        """Returns a set of media files which are in the media directory but
        which are not referenced in the cards.

        """

        case_insensitive = is_filesystem_case_insensitive()
        # Files referenced in the database.
        files_in_db = set()
        for result in self.con.execute("select value from data_for_fact where value like '%src=%'"):
            for match in re_src.finditer(result[0]):
                filename = match.group(2)
                if case_insensitive:
                    filename = filename.lower()
                files_in_db.add(filename)
        # Files in the media dir.
        files_in_media_dir = set()
        for root, dirnames, filenames in os.walk(self.media_dir()):
            root = contract_path(root, self.media_dir())
            if root.startswith("_"):
                continue
            for filename in filenames:
                # Paths are stored using unix convention.
                if root:
                    filename = root + "/" + filename
                if case_insensitive:
                    filename = filename.lower()
                files_in_media_dir.add(filename)
        return files_in_media_dir - files_in_db
예제 #9
0
 def accept(self):
     filename = self.filename_box.text().replace("\\", "/")
     if not filename:
         return QtWidgets.QDialog.accept(self)
     if os.path.isabs(filename):
         if not filename.startswith(\
             self.database().media_dir().replace("\\", "/")):
             self.main_widget().show_error(\
                 _("Please select a filename inside the media directory."))
             self.set_default_filename()
             return
         else:
             filename = contract_path(filename, self.database().media_dir())
     # By now, filename is relative to the media dir.
     # Save subdirectory for this card type.
     local_dir = os.path.dirname(filename)
     if local_dir:
         self.config()["tts_dir_for_card_type_id"]\
             [self.card_type.id] = local_dir
     full_local_dir = expand_path(local_dir, self.database().media_dir())
     if not os.path.exists(full_local_dir):
         os.makedirs(full_local_dir)
     shutil.copyfile(self.tmp_filename,
                     os.path.join(self.database().media_dir(), filename))
     self.text_to_insert = "<audio src=\"" + filename + "\">"
     QtWidgets.QDialog.accept(self)
예제 #10
0
    def initialise(self, data_dir=None, config_dir=None,
                   filename=None, automatic_upgrades=True, debug_file=None, 
                   server_only=False):

        """The automatic upgrades of the database can be turned off by setting
        'automatic_upgrade' to False. This is mainly useful for the testsuite.

        """

        if debug_file:
            self.component_manager.debug_file = open(debug_file, "w", 0)
        self.register_components()
        # Upgrade from 1.x if needed.
        if automatic_upgrades:
            from mnemosyne.libmnemosyne.upgrades.upgrade1 import Upgrade1
            Upgrade1(self.component_manager).backup_old_dir()
        if data_dir:
            self.config().data_dir = data_dir
            self.config().config_dir = data_dir
        if config_dir:
            self.config().config_dir = config_dir
        # Upgrade config if needed.
        if automatic_upgrades:
            from mnemosyne.libmnemosyne.upgrades.upgrade3 import Upgrade3
            Upgrade3(self.component_manager).run() 
        self.activate_components()
        register_component_manager(self.component_manager,
            self.config()["user_id"])
        self.execute_user_plugin_dir()
        self.activate_saved_plugins()
        # If we are only running a sync or a review server, do not yet load
        # the database to prevent threading access issues.
        if server_only:
            if filename:
                self.config()["last_database"] = \
                    contract_path(filename, self.config().data_dir)
            return
        # Loading the database should come after all user plugins have been
        # loaded, since these could be needed e.g. for a card type in the
        # database.
        if filename and not filename.endswith(".db"):
            from mnemosyne.libmnemosyne.translator import _
            self.main_widget().show_error(\
                _("Command line argument is not a *.db file."))
            sys.exit()
        self.load_database(filename)
        # Only now that the database is loaded, we can start writing log
        # events to it. This is why we log started_scheduler and
        # loaded_database manually.
        try:
            self.log().started_program()
        except Exception, e:
            if "lock" in str(e):
                from mnemosyne.libmnemosyne.translator import _
                self.main_widget().show_error(\
                 _("Another copy of Mnemosyne is still running.") + "\n" + \
                 _("Continuing is impossible and will lead to data loss!"))
                sys.exit()
            else:
                raise e
예제 #11
0
파일: pickle.py 프로젝트: umax/pomni
 def save(self, path=None):
     # Don't erase a database which failed to load.
     if self.load_failed == True:
         return -1
     if not path:
         path = self.config()["path"]
     path = expand_path(path, self.config().basedir)
     # Update version.
     self.global_variables["version"] = self.version
     # Work around a sip bug: don't store card types, but their ids.
     for f in self.facts:
         f.card_type = f.card_type.id
     try:
         # Write to a backup file first, as shutting down Windows can
         # interrupt the dump command and corrupt the database.
         outfile = file(path + "~", 'wb')
         db = [self.tags, self.facts, self.cards,
               self.global_variables]
         cPickle.dump(db, outfile)
         outfile.close()
         shutil.move(path + "~", path) # Should be atomic.
     except:
         raise RuntimeError, _("Unable to save file.") \
               + "\n" + traceback_string()
     self.config()["path"] = contract_path(path, self.config().basedir)
     # Work around sip bug again.
     for f in self.facts:
         f.card_type = self.card_type_by_id(f.card_type)
예제 #12
0
파일: pickle.py 프로젝트: wojas/pomni
 def new(self, path):
     if self.is_loaded():
         self.unload()
     self.load_failed = False
     self.start_date = StartDate()
     config()["path"] = path
     log().new_database()
     self.save(contract_path(path, config().basedir))
예제 #13
0
 def default_filename(self, card_type, foreign_text):
     if foreign_text.count(" ") <= 1:
         filename = foreign_text.replace("?", "").replace("/", "")\
             .replace("\\", "") + ".mp3"
     else:
         filename = datetime.datetime.today().strftime("%Y%m%d.mp3")
     local_dir = self.config()["tts_dir_for_card_type_id"]\
         .get(card_type.id, "")
     filename = os.path.join(local_dir, filename)
     full_path = expand_path(filename, self.database().media_dir())
     full_path = make_filename_unique(full_path)
     filename = contract_path(full_path, self.database().media_dir())
     return filename
예제 #14
0
    def insert_video(self, filter):
        from mnemosyne.libmnemosyne.utils import copy_file_to_dir

        basedir, mediadir = self.config().basedir, self.database().mediadir()
        path = expand_path(self.config()["import_video_dir"], basedir)
        filter = _("Video files") + " " + filter
        filename = self.main_widget().open_file_dialog(path, filter, _("Insert video"))
        if not filename:
            return ""
        else:
            self.config()["import_video_dir"] = contract_path(os.path.dirname(filename), basedir)
            filename = copy_file_to_dir(filename, mediadir)
            return filename
예제 #15
0
    def insert_img(self, filter):

        """Show a file dialog filtered on the supported filetypes, get a
        filename, massage it, and return it to the widget to be inserted.
        There is more media file logic inside the database code too, as the
        user could also just type in the html tags as opposed to passing
        through the fileselector here.

        """

        from mnemosyne.libmnemosyne.utils import copy_file_to_dir

        basedir, mediadir = self.config().basedir, self.database().mediadir()
        path = expand_path(self.config()["import_img_dir"], basedir)
        filter = _("Image files") + " " + filter
        filename = self.main_widget().open_file_dialog(path, filter, _("Insert image"))
        if not filename:
            return ""
        else:
            self.config()["import_img_dir"] = contract_path(os.path.dirname(filename), basedir)
            filename = copy_file_to_dir(filename, mediadir)
            return contract_path(filename, mediadir)
예제 #16
0
 def show_insert_flash_dialog(self, filter):
     from mnemosyne.libmnemosyne.utils import copy_file_to_dir
     data_dir, media_dir = self.config().data_dir, self.database().media_dir()
     path = expand_path(self.config()["import_flash_dir"], data_dir)
     filter = _("Flash files") + " " + filter
     filename = self.main_widget().get_filename_to_open(\
         path, filter, _("Insert Flash"))
     if not filename:
         return ""
     else:
         self.config()["import_flash_dir"] = contract_path(\
             os.path.dirname(filename), data_dir)
         filename = copy_file_to_dir(filename, media_dir)
         return filename
예제 #17
0
파일: SQLite.py 프로젝트: bartosh/pomni
 def save(self, path=None):
     # Don't erase a database which failed to load.
     if self.load_failed == True:
         return -1
     # Update format.
     self.con.execute("update global_variables set value=? where key=?",
                      (self.version, "version" ))
     # Save database and copy it to different location if needed.
     self.con.commit()
     if not path:
         return
     dest_path = expand_path(path, self.config().basedir)
     if dest_path != self._path:
         shutil.copy(self._path, dest_path)
         self._path = dest_path
     self.config()["path"] = contract_path(path, self.config().basedir)
예제 #18
0
파일: SQLite.py 프로젝트: axelson/pomni
 def load(self, path):
     if self.is_loaded():
         self.unload()
     self._path = expand_path(path, self.config().basedir)
     # Check database version.
     try:
         sql_res = self.con.execute("""select value from global_variables
             where key=?""", ("version", )).fetchone()
         self.load_failed = False
     except sqlite3.OperationalError:
         self.main_widget().error_box(
             _("Another copy of Mnemosyne is still running.") + "\n" +
             _("Continuing is impossible and will lead to data loss!"))
         sys.exit()
     except:
         self.load_failed = True
         raise RuntimeError, _("Unable to load file.")
     
     if sql_res["value"] != self.version:
         self.load_failed = True
         raise RuntimeError, \
             _("Unable to load file: database version mismatch.")
     # Instantiate card types stored in this database.
     for cursor in self.con.execute("select id from card_types"):
         id = cursor[0]
         card_type = self.get_card_type(id, id_is_internal=-1)
         self.component_manager.register(card_type)
     # Identify missing plugins for card types and their parents.       
     plugin_needed = set()
     active_ids = set(card_type.id for card_type in self.card_types())
     for cursor in self.con.execute("""select distinct card_type_id
         from facts"""):
         id = cursor[0]
         while "::" in id: # Move up one level of the hierarchy.
             id, child_name = id.rsplit("::", 1)
             if id not in active_ids:
                 plugin_needed.add(id)
         if id not in active_ids:
             plugin_needed.add(id)
     for card_type_id in plugin_needed:
         self._find_plugin_for_card_type(card_type_id)        
    
     self.config()["path"] = contract_path(path, self.config().basedir)
     for f in self.component_manager.get_all("hook", "after_load"):
         f.run()
예제 #19
0
파일: SQLite.py 프로젝트: axelson/pomni
 def new(self, path):
     if self.is_loaded():
         self.unload()
     self._path = expand_path(path, self.config().basedir)
     if os.path.exists(self._path):
         os.remove(self._path)
     self.load_failed = False
     # Create tables.
     self.con.executescript(SCHEMA)
     self.con.execute("insert into global_variables(key, value) values(?,?)",
                     ("version", self.version))
     self.con.execute("""insert into partnerships(partner, _last_log_id)
                      values(?,?)""", ("log.txt", 0))
     self.con.commit()
     self.config()["path"] = contract_path(self._path, self.config().basedir)
     # Create media directory.
     mediadir = self.config().mediadir()
     if not os.path.exists(mediadir):
         os.mkdir(mediadir)
예제 #20
0
    def add_media_file(self, filename):
        """
        Adds a new media file to the media directory.
        """

        from mnemosyne.libmnemosyne.utils import copy_file_to_dir, contract_path
        media_dir = self.mnemo.database().media_dir()

        # Make sure the path is proper absolute filesystem path
        filename_expanded = os.path.expanduser(filename)
        if os.path.isabs(filename_expanded):
            filename_abs = filename_expanded
        else:
            filename_abs = os.path.join(
                os.path.dirname(utils.get_absolute_filepath()),
                filename_expanded)

        copy_file_to_dir(filename_abs, media_dir)
        return contract_path(filename_abs, media_dir)
예제 #21
0
    def delete_unused_media_files(self, unused_files):

        """Delete media files which are no longer in use. 'unused_files'
        should be a subset of 'self.unused_media_files', because here we no
        longer check if these media files are used or not.

        """
        for filename in unused_files:
            os.remove(expand_path(filename, self.media_dir()))
            self.log().deleted_media_file(filename)
        # Purge empty dirs.
        for root, dirnames, filenames in os.walk(self.media_dir(), topdown=False):
            contracted_root = contract_path(root, self.media_dir())
            if not contracted_root or contracted_root.startswith("_"):
                continue
            if len(filenames) == 0 and len(dirnames) == 0:
                os.rmdir(root)
        # Other media files, e.g. latex.
        for f in self.component_manager.all("hook", "delete_unused_media_files"):
            f.run()
        remove_empty_dirs_in(self.media_dir())
예제 #22
0
    def delete_unused_media_files(self, unused_files):
        """Delete media files which are no longer in use. 'unused_files'
        should be a subset of 'self.unused_media_files', because here we no
        longer check if these media files are used or not.

        """
        for filename in unused_files:
            os.remove(expand_path(filename, self.media_dir()))
            self.log().deleted_media_file(filename)
        # Purge empty dirs.
        for root, dirnames, filenames in \
            os.walk(self.media_dir(), topdown=False):
            contracted_root = contract_path(root, self.media_dir())
            if not contracted_root or contracted_root.startswith("_"):
                continue
            if len(filenames) == 0 and len(dirnames) == 0:
                os.rmdir(root)
        # Other media files, e.g. latex.
        for f in self.component_manager.all("hook",
                                            "delete_unused_media_files"):
            f.run()
        remove_empty_dirs_in(self.media_dir())
예제 #23
0
파일: pickle.py 프로젝트: wojas/pomni
 def save(self, path):
     path = expand_path(path, config().basedir)
     # Work around a sip bug: don't store card types, but their ids.
     for f in self.facts:
         f.card_type = f.card_type.id
     # Don't erase a database which failed to load.
     if self.load_failed == True:
         return
     try:
         # Write to a backup file first, as shutting down Windows can
         # interrupt the dump command and corrupt the database.
         outfile = file(path + "~", 'wb')
         db = [self.start_date, self.categories, self.facts, self.fact_views,
               self.cards]
         cPickle.dump(db, outfile)
         outfile.close()
         shutil.move(path + "~", path) # Should be atomic.
     except:
         print traceback_string()
         raise SaveError()
     config()["path"] = contract_path(path, config().basedir)
     # Work around sip bug again.
     for f in self.facts:
         f.card_type = card_type_by_id(f.card_type)
예제 #24
0
파일: pickle.py 프로젝트: umax/pomni
    def load(self, path):
        if self.is_loaded():
            self.unload()
        path = expand_path(path, self.config().basedir)
        if not os.path.exists(path):
            self.load_failed = True
            raise RuntimeError, _("File does not exist.")
        try:
            infile = file(path, 'rb')
            db = cPickle.load(infile)
            self.tags = db[0]
            self.facts = db[1]
            self.cards = db[2]
            self.global_variables = db[3]
            infile.close()
            self.load_failed = False
        except:
            self.load_failed = True
            raise RuntimeError, _("Invalid file format.") \
                  + "\n" + traceback_string()

        # Check database version.
        if self.global_variables["version"] != self.version:
            self.load_failed = True
            raise RuntimeError, _("Unable to load file: database version mismatch.")
        
        # Deal with clones and plugins, also plugins for parent classes.
        # Because of the sip bugs, card types here are actually still card
        # type ids.
        plugin_needed = set()
        clone_needed = []
        active_id = set(card_type.id for card_type in self.card_types())
        for id in set(card.fact.card_type for card in self.cards):
            while "." in id: # Move up one level of the hierarchy.
                id, child_name = id.rsplit(".", 1)          
                if id.endswith("_CLONED"):
                    id = id.replace("_CLONED", "")
                    clone_needed.append((id, child_name))
                if id not in active_id:
                    plugin_needed.add(id)
            if id not in active_id:
                plugin_needed.add(id)

        # Activate necessary plugins.
        for card_type_id in plugin_needed:
            found = False
            for plugin in self.plugins():
                for component in plugin.components:
                    if component.component_type == "card_type" and \
                           component.id == card_type_id:
                        found = True
                        try:
                            plugin.activate()
                        except:
                            self.load_failed = True
                            raise RuntimeError, \
                                  _("Error when running plugin:") \
                                  + "\n" + traceback_string()
            if not found:
                self.load_failed = True
                raise RuntimeError, \
                      _("Missing plugin for card type with id:") \
                      + " " + card_type_id
            
        # Create necessary clones.
        for parent_type_id, clone_name in clone_needed:
            parent_instance = self.card_type_by_id(parent_type_id)
            try:
                parent_instance.clone(clone_name)
            except NameError:
                # In this case the clone was already created by loading the
                # database earlier.
                pass
            
        # Work around a sip bug: don't store card types, but their ids.
        for f in self.facts:
            f.card_type = self.card_type_by_id(f.card_type)    
        self.config()["path"] = contract_path(path, self.config().basedir)
        for f in self.component_manager.get_all("hook", "after_load"):
            f.run()