Esempio n. 1
0
class ReTagController(QtCore.QObject):
    """
    object for calling the re-tag view.
    ************************
    MANDATORY parameters: 
    ************************
    * application -> the parent qt-application object ()for installing the translator properly
    * store_path -> absolute path to the store of the item to be retagged (TIP: use the PathHelper object to resolve a relative path.)
    * item_name -> the name of the item to be renamed (exactly how it is defined in the tagfile)

    ************************
    TIP: use the PathHelper object to resolve a relative path AND to extract the item name out of it. 
    ************************
    
    ************************
    OPTIONAL parameters:
    ************************
    * standalone_application -> default = False; set this to true if there
    * verbose -> set this to true for detailed output
    (DEVEL * retag_mode -> this application could even be used for a normal tagging procedure as well.)
    
    ************************
    IMPORTANT!!!
    ************************
    the start() method must be called in order to begin with the tagging procedure
    """

    def __init__(self, application, store_path, item_name, retag_mode=True, verbose=False):
        QtCore.QObject.__init__(self)

        self.__log = None
        self.__main_config = None
        self.__store_config = None
        self.__tag_dialog = None
        self.__store = None

        self.__retag_mode = retag_mode

        self.__no_store_found = False

        self.__item_name = unicode(item_name)
        self.__store_path = store_path

        # the main application which has the translator installed
        self.__application = application

        self.LOG_LEVEL = logging.INFO
        if verbose:
            self.LOG_LEVEL = logging.DEBUG

        self.STORE_CONFIG_DIR = TsConstants.DEFAULT_STORE_CONFIG_DIR
        self.STORE_CONFIG_FILE_NAME = TsConstants.DEFAULT_STORE_CONFIG_FILENAME
        self.STORE_TAGS_FILE_NAME = TsConstants.DEFAULT_STORE_TAGS_FILENAME
        self.STORE_VOCABULARY_FILE_NAME = TsConstants.DEFAULT_STORE_VOCABULARY_FILENAME

        locale = unicode(QtCore.QLocale.system().name())[0:2]
        self.__translator = QtCore.QTranslator()
        if self.__translator.load("ts_" + locale + ".qm", "tsresources/"):
            self.__application.installTranslator(self.__translator)

        # get dir names for all available languages
        self.CURRENT_LANGUAGE = self.trUtf8("en")
        self.STORE_STORAGE_DIRS = []
        self.STORE_DESCRIBING_NAV_DIRS = []
        self.STORE_CATEGORIZING_NAV_DIRS = []
        self.STORE_EXPIRED_DIRS = []
        self.STORE_NAVIGATION_DIRS = []
        self.SUPPORTED_LANGUAGES = TsConstants.DEFAULT_SUPPORTED_LANGUAGES
        self.MAX_CLOUD_TAGS = TsConstants.DEFAULT_MAX_CLOUD_TAGS
        self.__store_dict = {}

        for lang in self.SUPPORTED_LANGUAGES:
            self.change_language(lang)
            self.STORE_NAVIGATION_DIRS.append(self.trUtf8("navigation"))
            self.STORE_STORAGE_DIRS.append(self.trUtf8("storage"))  # self.STORE_STORAGE_DIR_EN))
            self.STORE_DESCRIBING_NAV_DIRS.append(
                self.trUtf8("descriptions")
            )  # self.STORE_DESCRIBING_NAVIGATION_DIR_EN))
            self.STORE_CATEGORIZING_NAV_DIRS.append(
                self.trUtf8("categories")
            )  # self.STORE_CATEGORIZING_NAVIGATION_DIR_EN))
            self.STORE_EXPIRED_DIRS.append(self.trUtf8("expired_items"))  # STORE_EXPIRED_DIR_EN))
        ## reset language
        self.change_language(self.CURRENT_LANGUAGE)

        self.__log = LogHelper.get_app_logger(self.LOG_LEVEL)

    def start(self):
        """
        call this method to actually start the tagging procedure
        """
        self.__init_configuration()

    def __init_configuration(self):
        """
        initializes the configuration. This method is called every time the config file changes
        """
        self.__log.info("initialize configuration")

        self.__main_config = ConfigWrapper(TsConstants.CONFIG_PATH)

        if self.__main_config is None:
            self.__emit_not_retagable(self.trUtf8("No config file found for the given path"))
            return

        ## check if there has been found an appropriate store_path in the config
        if self.__store_path is None:
            self.__emit_not_retagable(self.trUtf8("No store found for the given path"))
            return
        else:
            self.__store_config = ConfigWrapper(self.__store_path)

        self.__prepare_store_params()

        self.CURRENT_LANGUAGE = self.__main_config.get_current_language()
        self.change_language(self.CURRENT_LANGUAGE)
        # self.__main_config.connect(self.__main_config, QtCore.SIGNAL("changed()"), self.__init_configuration)

        self.__store = Store(
            self.__store_config.get_store_id(),
            self.__store_path,
            self.STORE_CONFIG_DIR + "/" + self.STORE_CONFIG_FILE_NAME,
            self.STORE_CONFIG_DIR + "/" + self.STORE_TAGS_FILE_NAME,
            self.STORE_CONFIG_DIR + "/" + self.STORE_VOCABULARY_FILE_NAME,
            self.STORE_NAVIGATION_DIRS,
            self.STORE_STORAGE_DIRS,
            self.STORE_DESCRIBING_NAV_DIRS,
            self.STORE_CATEGORIZING_NAV_DIRS,
            self.STORE_EXPIRED_DIRS,
            self.__main_config.get_expiry_prefix(),
        )
        self.__store.init()

        if self.__tag_dialog is None:
            self.__tag_dialog = TagDialogController(
                self.__store.get_name(),
                self.__store.get_id(),
                self.__main_config.get_max_tags(),
                self.__main_config.get_tag_seperator(),
                self.__main_config.get_expiry_prefix(),
            )
            self.__tag_dialog.get_view().setModal(True)
            # self.__tag_dialog.set_parent(self.sender().get_view())
            self.__tag_dialog.connect(self.__tag_dialog, QtCore.SIGNAL("tag_item"), self.__tag_item_action)
            self.__tag_dialog.connect(self.__tag_dialog, QtCore.SIGNAL("handle_cancel()"), self.__handle_tag_cancel)

        ## configure the tag dialog with the according settings
        format_setting = self.__store.get_datestamp_format()
        datestamp_hidden = self.__store.get_datestamp_hidden()
        ## check if auto datestamp is enabled
        if format_setting != EDateStampFormat.DISABLED:
            self.__tag_dialog.show_datestamp(True)
            ## set the format
            format = None
            if format_setting == EDateStampFormat.DAY:
                format = TsConstants.DATESTAMP_FORMAT_DAY
            elif format_setting == EDateStampFormat.MONTH:
                format = TsConstants.DATESTAMP_FORMAT_MONTH

            self.__tag_dialog.set_datestamp_format(format, datestamp_hidden)

        self.__tag_dialog.show_category_line(self.__store.get_show_category_line())
        self.__tag_dialog.set_category_mandatory(self.__store.get_category_mandatory())

        ## check if the given item really exists in the store
        if not self.__store.item_exists(self.__item_name):
            self.__emit_not_retagable(self.trUtf8("%s: There is no such item recorded in the store" % self.__item_name))
            return

        self.__set_tag_information_to_dialog(self.__store)

        if self.__retag_mode:
            self.__handle_retag_mode()

        self.__tag_dialog.show_dialog()

    def __emit_not_retagable(self, err_msg):
        self.__log.error(err_msg)
        self.emit(QtCore.SIGNAL("retag_error"))

    def __handle_retag(self, store_name, file_name_list, new_describing_tags, new_categorizing_tags):

        for file_name in file_name_list:
            ## first of all remove the old references
            self.__store.remove_file(file_name)
            ## now create the new navigation structure
            try:
                self.__store.add_item_with_tags(file_name, new_describing_tags, new_categorizing_tags)
            except InodeShortageException, e:
                self.__tag_dialog.show_message(
                    self.trUtf8("The Number of free inodes is below the threshold of %s%" % e.get_threshold())
                )
                # raise
            except Exception, e:
                self.__tag_dialog.show_message(self.trUtf8("An error occurred while tagging"))
                raise
            else:
Esempio n. 2
0
class ReTagController(QtCore.QObject):
    """
    object for calling the re-tag view.
    ************************
    MANDATORY parameters: 
    ************************
    * application -> the parent qt-application object ()for installing the translator properly
    * store_path -> absolute path to the store of the item to be retagged (TIP: use the PathHelper object to resolve a relative path.)
    * item_name -> the name of the item to be renamed (exactly how it is defined in the tagfile)

    ************************
    TIP: use the PathHelper object to resolve a relative path AND to extract the item name out of it. 
    ************************
    
    ************************
    OPTIONAL parameters:
    ************************
    * standalone_application -> default = False; set this to true if there
    * verbose -> set this to true for detailed output
    (DEVEL * retag_mode -> this application could even be used for a normal tagging procedure as well.)
    
    ************************
    IMPORTANT!!!
    ************************
    the start() method must be called in order to begin with the tagging procedure
    """

    def __init__(self, application, store_path, item_name, retag_mode = True, verbose = False):
        QtCore.QObject.__init__(self)
        
        self.__log = None
        self.__main_config = None
        self.__store_config = None
        self.__tag_dialog = None
        self.__store = None
        
        self.__retag_mode = retag_mode
        
        self.__no_store_found = False

        self.__item_name = unicode(item_name)
        self.__store_path = store_path

        # the main application which has the translator installed
        self.__application = application

        self.LOG_LEVEL = logging.INFO
        if verbose:
            self.LOG_LEVEL = logging.DEBUG
            

        self.STORE_CONFIG_DIR = TsConstants.DEFAULT_STORE_CONFIG_DIR
        self.STORE_CONFIG_FILE_NAME = TsConstants.DEFAULT_STORE_CONFIG_FILENAME
        self.STORE_TAGS_FILE_NAME = TsConstants.DEFAULT_STORE_TAGS_FILENAME
        self.STORE_VOCABULARY_FILE_NAME = TsConstants.DEFAULT_STORE_VOCABULARY_FILENAME
        
        locale = unicode(QtCore.QLocale.system().name())[0:2]
        self.__translator = QtCore.QTranslator()
        if self.__translator.load("ts_" + locale + ".qm", "tsresources/"):
            self.__application.installTranslator(self.__translator)

        #get dir names for all available languages
        self.CURRENT_LANGUAGE = self.trUtf8("en")
        self.STORE_STORAGE_DIRS = []
        self.STORE_DESCRIBING_NAV_DIRS = []
        self.STORE_CATEGORIZING_NAV_DIRS = []
        self.STORE_EXPIRED_DIRS = []
        self.STORE_NAVIGATION_DIRS = []
        self.SUPPORTED_LANGUAGES = TsConstants.DEFAULT_SUPPORTED_LANGUAGES
        self.MAX_CLOUD_TAGS = TsConstants.DEFAULT_MAX_CLOUD_TAGS
        self.__store_dict = {}
        
        for lang in self.SUPPORTED_LANGUAGES: 
            self.change_language(lang)
            self.STORE_NAVIGATION_DIRS.append(self.trUtf8("navigation")) 
            self.STORE_STORAGE_DIRS.append(self.trUtf8("storage"))#self.STORE_STORAGE_DIR_EN))  
            self.STORE_DESCRIBING_NAV_DIRS.append(self.trUtf8("descriptions"))#self.STORE_DESCRIBING_NAVIGATION_DIR_EN))  
            self.STORE_CATEGORIZING_NAV_DIRS.append(self.trUtf8("categories"))#self.STORE_CATEGORIZING_NAVIGATION_DIR_EN)) 
            self.STORE_EXPIRED_DIRS.append(self.trUtf8("expired_items"))#STORE_EXPIRED_DIR_EN)) 
        ## reset language 
        self.change_language(self.CURRENT_LANGUAGE)
        
        self.__log = LogHelper.get_app_logger(self.LOG_LEVEL)
        
    def start(self):
        """
        call this method to actually start the tagging procedure
        """
        self.__init_configuration()
        
    
    def __init_configuration(self):
        """
        initializes the configuration. This method is called every time the config file changes
        """
        self.__log.info("initialize configuration")
        
        
        self.__main_config = ConfigWrapper(TsConstants.CONFIG_PATH)
        
        if self.__main_config is None:
            self.__emit_not_retagable(self.trUtf8("No config file found for the given path"))
            return
        
        ## check if there has been found an appropriate store_path in the config 
        if self.__store_path is None:
            self.__emit_not_retagable(self.trUtf8("No store found for the given path"))
            return
        else:
            self.__store_config = ConfigWrapper(self.__store_path)
        
        self.__prepare_store_params()
        
        self.CURRENT_LANGUAGE = self.__main_config.get_current_language();
        self.change_language(self.CURRENT_LANGUAGE)
        #self.__main_config.connect(self.__main_config, QtCore.SIGNAL("changed()"), self.__init_configuration)

        self.__store = Store(self.__store_config.get_store_id(), self.__store_path, 
              self.STORE_CONFIG_DIR + "/" + self.STORE_CONFIG_FILE_NAME,
              self.STORE_CONFIG_DIR + "/" + self.STORE_TAGS_FILE_NAME,
              self.STORE_CONFIG_DIR + "/" + self.STORE_VOCABULARY_FILE_NAME,
              self.STORE_NAVIGATION_DIRS,
              self.STORE_STORAGE_DIRS, 
              self.STORE_DESCRIBING_NAV_DIRS,
              self.STORE_CATEGORIZING_NAV_DIRS,
              self.STORE_EXPIRED_DIRS,
              self.__main_config.get_expiry_prefix())
        self.__store.init()
        
        if self.__tag_dialog is None:
            self.__tag_dialog = TagDialogController(self.__store.get_name(), self.__store.get_id(), self.__main_config.get_max_tags(), self.__main_config.get_tag_seperator(), self.__main_config.get_expiry_prefix())
            self.__tag_dialog.get_view().setModal(True)
            #self.__tag_dialog.set_parent(self.sender().get_view())
            self.__tag_dialog.connect(self.__tag_dialog, QtCore.SIGNAL("tag_item"), self.__tag_item_action)
            self.__tag_dialog.connect(self.__tag_dialog, QtCore.SIGNAL("handle_cancel()"), self.__handle_tag_cancel)


        ## configure the tag dialog with the according settings
        format_setting = self.__store.get_datestamp_format()
        datestamp_hidden = self.__store.get_datestamp_hidden()
        ## check if auto datestamp is enabled
        if format_setting != EDateStampFormat.DISABLED:
            self.__tag_dialog.show_datestamp(True)
            ## set the format
            format = None
            if format_setting == EDateStampFormat.DAY:
                format = TsConstants.DATESTAMP_FORMAT_DAY
            elif format_setting == EDateStampFormat.MONTH:
                format = TsConstants.DATESTAMP_FORMAT_MONTH
            
            self.__tag_dialog.set_datestamp_format(format, datestamp_hidden)
        
        self.__tag_dialog.show_category_line(self.__store.get_show_category_line())
        self.__tag_dialog.set_category_mandatory(self.__store.get_category_mandatory()) 
        
        ## check if the given item really exists in the store
        if not self.__store.item_exists(self.__item_name):
            self.__emit_not_retagable(self.trUtf8("%s: There is no such item recorded in the store" % self.__item_name))
            return 

        self.__set_tag_information_to_dialog(self.__store)
        
        if self.__retag_mode:
            self.__handle_retag_mode()
        
        self.__tag_dialog.show_dialog()
    
    def __emit_not_retagable(self, err_msg):
        self.__log.error(err_msg)
        self.emit(QtCore.SIGNAL("retag_error"))
    
    def __handle_retag(self, store_name, file_name_list, new_describing_tags, new_categorizing_tags):
        
        for file_name in file_name_list:
            ## first of all remove the old references
            self.__store.remove_file(file_name)
            ## now create the new navigation structure
            try:
                self.__store.add_item_with_tags(file_name, new_describing_tags, new_categorizing_tags)
            except InodeShortageException, e:
                self.__tag_dialog.show_message(self.trUtf8("The Number of free inodes is below the threshold of %s%" % e.get_threshold()))
                #raise
            except Exception, e:
                self.__tag_dialog.show_message(self.trUtf8("An error occurred while tagging"))
                raise
            else:
Esempio n. 3
0
class Administration(QtCore.QObject):
    def __init__(self, application, verbose):
        QtCore.QObject.__init__(self)

        self.__log = None
        self.__main_config = None
        self.__admin_dialog = None
        self.__retag_dialog = None
        self.__verbose_mode = verbose
        # the main application which has the translator installed
        self.__application = application

        self.LOG_LEVEL = logging.INFO
        if verbose:
            self.LOG_LEVEL = logging.DEBUG

        self.STORE_CONFIG_DIR = TsConstants.DEFAULT_STORE_CONFIG_DIR
        self.STORE_CONFIG_FILE_NAME = TsConstants.DEFAULT_STORE_CONFIG_FILENAME
        self.STORE_TAGS_FILE_NAME = TsConstants.DEFAULT_STORE_TAGS_FILENAME
        self.STORE_VOCABULARY_FILE_NAME = TsConstants.DEFAULT_STORE_VOCABULARY_FILENAME

        self.__system_locale = unicode(QtCore.QLocale.system().name())[0:2]
        self.__translator = QtCore.QTranslator()
        if self.__translator.load("ts_" + self.__system_locale + ".qm",
                                  "tsresources/"):
            self.__application.installTranslator(self.__translator)
        # "en" is automatically translated to the current language e.g. en -> de
        self.CURRENT_LANGUAGE = self.__get_locale_language()
        #dir names for all available languages
        self.STORE_STORAGE_DIRS = []
        self.STORE_DESCRIBING_NAV_DIRS = []
        self.STORE_CATEGORIZING_NAV_DIRS = []
        self.STORE_EXPIRED_DIRS = []
        self.STORE_NAVIGATION_DIRS = []
        self.SUPPORTED_LANGUAGES = TsConstants.DEFAULT_SUPPORTED_LANGUAGES
        self.__store_dict = {}

        # catch all "possible" dir-names
        for lang in self.SUPPORTED_LANGUAGES:
            self.change_language(lang)
            self.STORE_STORAGE_DIRS.append(
                self.trUtf8("storage"))  #self.STORE_STORAGE_DIR_EN))
            self.STORE_DESCRIBING_NAV_DIRS.append(self.trUtf8(
                "descriptions"))  #self.STORE_DESCRIBING_NAVIGATION_DIR_EN))
            self.STORE_CATEGORIZING_NAV_DIRS.append(self.trUtf8(
                "categories"))  #self.STORE_CATEGORIZING_NAVIGATION_DIR_EN))
            self.STORE_EXPIRED_DIRS.append(
                self.trUtf8("expired_items"))  #STORE_EXPIRED_DIR_EN))
            self.STORE_NAVIGATION_DIRS.append(self.trUtf8("navigation"))

        self.__log = LogHelper.get_app_logger(self.LOG_LEVEL)
        self.__init_configuration()

    def __init_configuration(self):
        """
        initializes the configuration. This method is called every time the config file changes
        """
        self.__log.info("initialize configuration")
        if self.__main_config is None:
            self.__main_config = ConfigWrapper(TsConstants.CONFIG_PATH)
            #self.connect(self.__main_config, QtCore.SIGNAL("changed()"), self.__init_configuration)

        self.CURRENT_LANGUAGE = self.__main_config.get_current_language()

        if self.CURRENT_LANGUAGE is None or self.CURRENT_LANGUAGE == "":
            self.CURRENT_LANGUAGE = self.__get_locale_language()

        # switch back to the configured language
        self.change_language(self.CURRENT_LANGUAGE)

        ## connect to all the signals the admin gui is sending
        if self.__admin_dialog is None:
            self.__admin_dialog = StorePreferencesController()
            self.connect(self.__admin_dialog,
                         QtCore.SIGNAL("create_new_store"),
                         self.__handle_new_store)
            self.connect(self.__admin_dialog, QtCore.SIGNAL("rename_desc_tag"),
                         self.__handle_tag_rename)
            self.connect(self.__admin_dialog, QtCore.SIGNAL("rename_cat_tag"),
                         self.__handle_tag_rename)
            self.connect(self.__admin_dialog, QtCore.SIGNAL("retag"),
                         self.__handle_retagging)

            self.connect(self.__admin_dialog, QtCore.SIGNAL("rebuild_store"),
                         self.__handle_store_rebuild)
            self.connect(self.__admin_dialog, QtCore.SIGNAL("rename_store"),
                         self.__handle_store_rename)
            self.connect(self.__admin_dialog, QtCore.SIGNAL("delete_store"),
                         self.__handle_store_delete)

            self.connect(self.__admin_dialog, QtCore.SIGNAL("synchronize"),
                         self.__handle_synchronization)

        self.__admin_dialog.set_main_config(self.__main_config)

        self.__prepare_store_params()
        self.__create_stores()

        ## create a temporary store list
        ## add the desc and cat tags which are needed in the admin-dialog
        tmp_store_list = []
        for current_store_item in self.__main_config.get_stores():
            store_name = current_store_item["path"].split("/").pop()
            current_store_item["desc_tags"] = self.__store_dict[
                store_name].get_tags()
            current_store_item["cat_tags"] = self.__store_dict[
                store_name].get_categorizing_tags()
            tmp_store_list.append(current_store_item)

        self.__admin_dialog.set_store_list(tmp_store_list)
        if self.__main_config.get_first_start():
            self.__admin_dialog.set_first_start(True)

    def __handle_synchronization(self, store_name):
        """
        do all the necessary synchronization stuff here ...
        """
        store_to_sync = self.__store_dict[str(store_name)]
        print "####################"
        print "synchronize " + store_name
        print "####################"

        store_to_sync.add_item_list_with_tags(["item_one", "item_two"],
                                              ["be", "tough"])

    def __handle_store_delete(self, store_name):
        self.__admin_dialog.start_progressbar(
            self.trUtf8("Deleting store ..."))
        store = self.__store_dict[str(store_name)]
        self.__store_to_be_deleted = store_name
        self.connect(store, QtCore.SIGNAL("store_delete_end"),
                     self.__handle_store_deleted)
        ## remove the directories
        store.remove()
        self.disconnect(store, QtCore.SIGNAL("store_delete_end"), self.__dummy)
        ## remove the config entry
        self.__main_config.remove_store(store.get_id())

    def __dummy(self):
        return "dummy"

    def __handle_store_deleted(self, id):
        #second remove the item in the admin_dialog
        self.__admin_dialog.remove_store_item(self.__store_to_be_deleted)

    def __handle_store_rename(self, store_name, new_store_name):
        """
        the whole store directory gets moved to the new directory
        the store will be rebuilt then to make sure all links are updated
        """
        ## show a progress bar at the admin dialog
        self.__admin_dialog.start_progressbar(self.trUtf8("Moving store ..."))
        store = self.__store_dict.pop(str(store_name))

        self.__main_config.rename_store(store.get_id(), new_store_name)
        ## connect to the rebuild signal because after the moving there is a rebuild routine started
        self.connect(store, QtCore.SIGNAL("store_rebuild_end"),
                     self.__handle_store_rebuild)

        store.move(new_store_name)

        self.disconnect(store, QtCore.SIGNAL("store_rebuild_end"))

        self.__init_configuration()

    def __handle_store_rebuild(self, store_name):
        """
        the whole store structure will be rebuild according to the records in store.tgs file
        """
        ## show a progress bar at the admin dialog
        self.__admin_dialog.start_progressbar(
            self.trUtf8("Rebuilding store ..."))
        store = self.__store_dict[str(store_name)]
        self.connect(store, QtCore.SIGNAL("store_rebuild_end"),
                     self.__handle_store_rebuild)
        store.rebuild()
        self.disconnect(store, QtCore.SIGNAL("store_rebuild_end"),
                        self.__get_locale_language)

    def __hide_progress_dialog(self, store_name):
        self.__admin_dialog.stop_progressbar()

    def __get_locale_language(self):
        """
        returns the translation of "en" in the system language
        """
        return self.trUtf8("en")

    def __handle_tag_rename(self, old_tag, new_tag, store_name):
        store = self.__store_dict[store_name]

        old_ba = old_tag.toUtf8()
        old_str = str(old_ba)

        new_ba = new_tag.toUtf8()
        new_str = str(new_ba)
        store.rename_tag(unicode(old_str, "utf-8"), unicode(new_str, "utf-8"))

    def set_application(self, application):
        """
        if the manager is called from another qt application (e.g. tagstore.py)
        you must set the calling application here for proper i18n
        """
        self.__application = application

    def __handle_retagging(self, store_name, item_name):
        """
        creates and configures a tag-dialog with all store-params and tags
        """
        store = self.__store_dict[store_name]

        ## make a string object of the QListWidgetItem, so other methods can use it
        item_name = item_name.text()
        self.__log.info("retagging item %s at store %s..." %
                        (item_name, store_name))
        #if(self.__retag_dialog is None):

        ## create the object
        self.__retag_dialog = ReTagController(self.__application,
                                              store.get_store_path(),
                                              item_name, True,
                                              self.__verbose_mode)
        ## connect to the signal(s)
        self.connect(self.__retag_dialog, QtCore.SIGNAL("retag_error"),
                     self.__handle_retag_error)
        self.connect(self.__retag_dialog, QtCore.SIGNAL("retag_cancel"),
                     self.__handle_retag_cancel)
        self.connect(self.__retag_dialog, QtCore.SIGNAL("retag_success"),
                     self.__handle_retag_success)
        self.__retag_dialog.start()

    def __kill_tag_dialog(self):
        """
        hide the dialog and set it to None
        """
        self.__retag_dialog.hide_tag_dialog()
        self.__retag_dialog = None

    def __handle_retag_error(self):
        self.__kill_tag_dialog()
        self.__admin_dialog.show_tooltip(
            self.trUtf8("An error occurred while re-tagging"))

    def __handle_retag_success(self):
        self.__kill_tag_dialog()
        self.__admin_dialog.show_tooltip(self.trUtf8("Re-tagging successful!"))

    def __handle_retag_cancel(self):
        """
        the "postpone" button in the re-tag dialog has been clicked
        """
        self.__kill_tag_dialog()

    def __set_tag_information_to_dialog(self, store):
        """
        convenience method for setting the tag data at the gui-dialog
        """
        self.__retag_dialog.set_tag_list(store.get_tags())

        num_pop_tags = self.__main_config.get_num_popular_tags()

        tag_set = set(store.get_popular_tags(
            self.__main_config.get_max_tags()))
        tag_set = tag_set | set(store.get_recent_tags(num_pop_tags))

        cat_set = set(store.get_popular_categories(num_pop_tags))
        cat_set = cat_set | set(store.get_recent_categories(num_pop_tags))

        cat_list = list(cat_set)
        if store.is_controlled_vocabulary():
            allowed_set = set(store.get_controlled_vocabulary())
            self.__retag_dialog.set_category_list(list(allowed_set))

            ## just show allowed tags - so make the intersection of popular tags ant the allowed tags
            cat_list = list(cat_set.intersection(allowed_set))
        else:
            self.__retag_dialog.set_category_list(
                store.get_categorizing_tags())

        if len(cat_list) > num_pop_tags:
            cat_list = cat_list[:num_pop_tags]
        self.__retag_dialog.set_popular_categories(cat_list)

        ## make a list out of the set, to enable indexing, as not all tags cannot be used
        tag_list = list(tag_set)
        if len(tag_list) > num_pop_tags:
            tag_list = tag_list[:num_pop_tags]
        self.__retag_dialog.set_popular_tags(tag_list)

        self.__retag_dialog.set_store_name(store.get_name())

    def __retag_item_action(self, store_name, item_name, tag_list,
                            category_list):
        """
        the "tag!" button in the re-tag dialog has been clicked
        """
        store = self.__store_dict[store_name]
        try:
            ## 1. write the data to the store-file
            store.add_item_with_tags(item_name, tag_list, category_list)
            self.__log.debug("added item %s to store-file", item_name)
        except NameInConflictException, e:
            c_type = e.get_conflict_type()
            c_name = e.get_conflicted_name()
            if c_type == EConflictType.FILE:
                self.__retag_dialog.show_message(
                    self.trUtf8(
                        "The filename - %s - is in conflict with an already existing tag. Please rename!"
                        % c_name))
            elif c_type == EConflictType.TAG:
                self.__retag_dialog.show_message(
                    self.trUtf8(
                        "The tag - %s - is in conflict with an already existing file"
                        % c_name))
            else:
                self.trUtf8(
                    "A tag or item is in conflict with an already existing tag/item"
                )
            #raise
        except InodeShortageException, e:
            self.__retag_dialog.show_message(
                self.trUtf8(
                    "The Number of free inodes is below the threshold of %s%" %
                    e.get_threshold()))
Esempio n. 4
0
class Tagstore(QtCore.QObject):

    def __init__(self, application, parent=None, verbose=False, dryrun=False):
        """ 
        initializes the configuration. This method is called every time the config file changes
        """
        
        QtCore.QObject.__init__(self)
        
        self.__application = application
        
        self.__admin_widget = None
        
        self.DRY_RUN = dryrun        
        ## initialize localization
        self.__system_locale = unicode(QtCore.QLocale.system().name())[0:2]
        self.__translator = QtCore.QTranslator()
        if self.__translator.load("ts_" + self.__system_locale + ".qm", "tsresources/"):
            self.__application.installTranslator(self.__translator)
        # "en" is automatically translated to the current language e.g. en -> de
        self.CURRENT_LANGUAGE = self.trUtf8("en")
        self.SUPPORTED_LANGUAGES = TsConstants.DEFAULT_SUPPORTED_LANGUAGES
        
        ## global settings/defaults (only used if reading config file failed or invalid!)
        self.STORE_CONFIG_DIR = TsConstants.DEFAULT_STORE_CONFIG_DIR
        self.STORE_CONFIG_FILE_NAME = TsConstants.DEFAULT_STORE_CONFIG_FILENAME
        self.STORE_TAGS_FILE_NAME = TsConstants.DEFAULT_STORE_TAGS_FILENAME
        self.STORE_VOCABULARY_FILE_NAME = TsConstants.DEFAULT_STORE_VOCABULARY_FILENAME

        #get dir names for all available languages
        store_current_language = self.CURRENT_LANGUAGE 
        self.STORE_STORAGE_DIRS = []
        self.STORE_DESCRIBING_NAV_DIRS = []
        self.STORE_CATEGORIZING_NAV_DIRS = []
        self.STORE_EXPIRED_DIRS = []
        self.STORE_NAVIGATION_DIRS = []

        for lang in self.SUPPORTED_LANGUAGES: 
            self.change_language(lang)
            self.STORE_NAVIGATION_DIRS.append(self.trUtf8("navigation")) 
            self.STORE_STORAGE_DIRS.append(self.trUtf8("storage"))#self.STORE_STORAGE_DIR_EN))  
            self.STORE_DESCRIBING_NAV_DIRS.append(self.trUtf8("descriptions"))#self.STORE_DESCRIBING_NAVIGATION_DIR_EN))  
            self.STORE_CATEGORIZING_NAV_DIRS.append(self.trUtf8("categories"))#self.STORE_CATEGORIZING_NAVIGATION_DIR_EN)) 
            self.STORE_EXPIRED_DIRS.append(self.trUtf8("expired_items"))#STORE_EXPIRED_DIR_EN)) 
        ## reset language 
        self.change_language(store_current_language) 
     
        self.EXPIRY_PREFIX = TsConstants.DEFAULT_EXPIRY_PREFIX
        self.TAG_SEPERATOR = TsConstants.DEFAULT_TAG_SEPARATOR
        self.NUM_RECENT_TAGS = TsConstants.DEFAULT_RECENT_TAGS
        self.NUM_POPULAR_TAGS = TsConstants.DEFAULT_POPULAR_TAGS
        self.MAX_TAGS = TsConstants.DEFAULT_MAX_TAGS
        self.MAX_CLOUD_TAGS = TsConstants.DEFAULT_MAX_CLOUD_TAGS
        self.STORES = []
        ## dict for dialogs identified by their store id
        self.DIALOGS = {}
        
        ## init configurations
        self.__app_config_wrapper = None
        self.__log = None
        
        self.LOG_LEVEL = logging.INFO
        if verbose:
            self.LOG_LEVEL = logging.DEBUG
            
        self.__log = LogHelper.get_app_logger(self.LOG_LEVEL)
        self.__log.info("starting tagstore watcher")
        
        self.__init_configurations()
        
    def __init_configurations(self):
        """
        initializes the configuration. This method is called every time the config file changes
        """
        self.__log.info("initialize configuration")
        ## reload config file - overwrite default settings
        self.__app_config_wrapper = ConfigWrapper(TsConstants.CONFIG_PATH)
        self.__app_config_wrapper.connect(self.__app_config_wrapper, QtCore.SIGNAL("changed()"), self.__init_configurations)
        self.__app_config_wrapper.print_app_config_to_log()
        tag_seperator = self.__app_config_wrapper.get_tag_seperator()
        if tag_seperator.strip() != "":
            self.TAG_SEPERATOR = tag_seperator
        expiry_prefix = self.__app_config_wrapper.get_expiry_prefix()
        if expiry_prefix.strip() != "":
            self.EXPIRY_PREFIX = expiry_prefix
        
        self.NUM_RECENT_TAGS = self.__app_config_wrapper.get_num_popular_tags()
        self.NUM_POPULAR_TAGS = self.__app_config_wrapper.get_num_popular_tags()
        self.MAX_TAGS = self.__app_config_wrapper.get_max_tags()
        
        self.CURRENT_LANGUAGE = self.__app_config_wrapper.get_current_language();
        if self.CURRENT_LANGUAGE is None or self.CURRENT_LANGUAGE == "":
            self.CURRENT_LANGUAGE = self.trUtf8("en")
        self.change_language(self.CURRENT_LANGUAGE)
        
        config_dir = self.__app_config_wrapper.get_store_config_directory()
        if config_dir != "":
            self.STORE_CONFIG_DIR = config_dir
        config_file_name = self.__app_config_wrapper.get_store_configfile_name()
        if config_file_name != "":
            self.STORE_CONFIG_FILE_NAME = config_file_name
        tags_file_name = self.__app_config_wrapper.get_store_tagsfile_name()
        if tags_file_name != "":
            self.STORE_TAGS_FILE_NAME = tags_file_name
        vocabulary_file_name = self.__app_config_wrapper.get_store_vocabularyfile_name()
        if vocabulary_file_name != "":
            self.STORE_VOCABULARY_FILE_NAME = vocabulary_file_name
        
       
#        self.SUPPORTED_LANGUAGES = self.__app_config_wrapper.get_supported_languages()
#        current_language = self.CURRENT_LANGUAGE
#        self.STORE_STORAGE_DIRS = []
#        self.STORE_NAVIGATION_DIRS = [] 
#        for lang in self.SUPPORTED_LANGUAGES:
#            self.change_language(lang)
#            self.STORE_STORAGE_DIRS.append(self.trUtf8("storage")) 
#            self.STORE_NAVIGATION_DIRS.append(self.trUtf8("navigation")) 
#        ## reset language
#        self.change_language(current_language)

        ## get stores from config file         
        config_store_items = self.__app_config_wrapper.get_stores()
        config_store_ids = self.__app_config_wrapper.get_store_ids()

        deleted_stores = []
        for store in self.STORES:
            id = store.get_id()
            if id in config_store_ids:
            ## update changed stores
                store.set_path(self.__app_config_wrapper.get_store_path(id), 
                               self.STORE_CONFIG_DIR + "/" + self.STORE_CONFIG_FILE_NAME,
                               self.STORE_CONFIG_DIR + "/" + self.STORE_TAGS_FILE_NAME,
                               self.STORE_CONFIG_DIR + "/" + self.STORE_VOCABULARY_FILE_NAME)
                store.change_expiry_prefix(self.EXPIRY_PREFIX)               
                config_store_ids.remove(id)             ## remove already updated items
            else:
            ## remove deleted stores
                deleted_stores.append(store)

        ## update deleted stores from global list after iterating through it
        for store in deleted_stores:
            self.STORES.remove(store)
            self.__log.debug("removed store: %s", store.get_name())
        
        ## add new stores
        for store_item in config_store_items:
            if store_item["id"] in config_store_ids:    ## new
                store = Store(store_item["id"], store_item["path"], 
                              self.STORE_CONFIG_DIR + "/" + self.STORE_CONFIG_FILE_NAME,
                              self.STORE_CONFIG_DIR + "/" + self.STORE_TAGS_FILE_NAME,
                              self.STORE_CONFIG_DIR + "/" + self.STORE_VOCABULARY_FILE_NAME,
                              self.STORE_NAVIGATION_DIRS,
                              self.STORE_STORAGE_DIRS, 
                              self.STORE_DESCRIBING_NAV_DIRS,
                              self.STORE_CATEGORIZING_NAV_DIRS,
                              self.STORE_EXPIRED_DIRS,
							  self.EXPIRY_PREFIX)

                store.connect(store, QtCore.SIGNAL("removed(PyQt_PyObject)"), self.store_removed)
                store.connect(store, QtCore.SIGNAL("renamed(PyQt_PyObject, QString)"), self.store_renamed)
                store.connect(store, QtCore.SIGNAL("file_renamed(PyQt_PyObject, QString, QString)"), self.file_renamed)
                store.connect(store, QtCore.SIGNAL("file_removed(PyQt_PyObject, QString)"), self.file_removed)
                store.connect(store, QtCore.SIGNAL("pending_operations_changed(PyQt_PyObject)"), self.pending_file_operations)
                store.connect(store, QtCore.SIGNAL("vocabulary_changed"), self.__handle_vocabulary_changed)
                store.connect(store, QtCore.SIGNAL("store_config_changed"), self.__handle_store_config_changed)

                extensions = self.__app_config_wrapper.get_additional_ignored_extension()
                ##if there comes a value from the config -> set it
                if len(extensions) > 0 and extensions[0] != "":
                    store.add_ignored_extensions(extensions)

                self.STORES.append(store)

                self.__log.debug("init store: %s", store.get_name())
                
                ## create a dialogcontroller for each store ...
                tmp_dialog = TagDialogController(store.get_name(), store.get_id(), self.MAX_TAGS, self.TAG_SEPERATOR, self.EXPIRY_PREFIX)
                
                tmp_dialog.connect(tmp_dialog, QtCore.SIGNAL("tag_item"), self.tag_item_action)
                tmp_dialog.connect(tmp_dialog, QtCore.SIGNAL("handle_cancel()"), self.handle_cancel)
                tmp_dialog.connect(tmp_dialog, QtCore.SIGNAL("open_store_admin_dialog()"), self.show_admin_dialog)
                
                self.DIALOGS[store.get_id()] = tmp_dialog
                ## call init to initialize new store instance (after adding the event handler)
                ## necessary if store was renamed during tagstore was not running (to write config)
                store.init()
                self.connect(tmp_dialog, QtCore.SIGNAL("item_selected"), self.__set_tag_information_to_dialog_wrapper)
                self.__configure_tag_dialog(store, tmp_dialog)
                

    
    def __configure_tag_dialog(self, store, tmp_dialog):
        """
        given a store and a tag dialog - promote all settings to the dialog 
        """
        
        format_setting = store.get_datestamp_format()
        is_hidden = store.get_datestamp_hidden()

        ##check if auto datestamp is enabled
        if format_setting != EDateStampFormat.DISABLED:
            tmp_dialog.show_datestamp(True)
            ## set the format
            format = None
            if format_setting == EDateStampFormat.DAY:
                format = TsConstants.DATESTAMP_FORMAT_DAY
            elif format_setting == EDateStampFormat.MONTH:
                format = TsConstants.DATESTAMP_FORMAT_MONTH
            tmp_dialog.set_datestamp_format(format, is_hidden)
                
        tmp_dialog.show_category_line(store.get_show_category_line())
        tmp_dialog.set_category_mandatory(store.get_category_mandatory())

    def __handle_vocabulary_changed(self, store):
        self.__set_tag_information_to_dialog(store)
    
    def __handle_store_config_changed(self, store):
        ## at first get the store-corresponding dialog controller
        dialog_controller = self.DIALOGS[store.get_id()]
        self.__configure_tag_dialog(store, dialog_controller)
    
    def show_admin_dialog(self):
        self.__admin_widget = Administration(self.__application, verbose=verbose_mode)
        self.__admin_widget.set_modal(True)
        self.__admin_widget.set_parent(self.sender().get_view())
        #admin_widget.set_parent(self.__tag_dialog)
        self.__admin_widget.show_admin_dialog(True)
    
    def store_removed(self, store):
        """
        event handler of the stores remove event
        """
        self.__app_config_wrapper.remove_store(store.get_id())
        ## __init_configuration is called due to config file changes
        
    def store_renamed(self, store, new_path):
        """
        event handler of the stores rename event
        """
        self.__app_config_wrapper.rename_store(store.get_id(), new_path)
        ## __init_configuration is called due to config file changes
        
    def file_renamed(self, store, old_file_name, new_file_name):
        """
        event handler for: file renamed
        """
        self.__log.debug("..........file renamed %s, %s" % (old_file_name, new_file_name))
        store.rename_file(old_file_name, new_file_name)
        
    def file_removed(self, store, file_name):
        """
        event handler for: file renamed
        """
        self.__log.debug("...........file removed %s" % file_name)
        store.remove_file(file_name)
        
    def pending_file_operations(self, store):
        """
        event handler: handles all operations with user interaction
        """        
        self.__log.info("new pending file operation added")

        dialog_controller = self.DIALOGS[store.get_id()]
        
        #dialog_controller.clear_store_children(store.get_name())
#        dialog_controller.clear_all_items()
        dialog_controller.clear_tagdialog()
        
        added_list = set(store.get_pending_changes().get_items_by_event(EFileEvent.ADDED))
        added_renamed_list = set(store.get_pending_changes().get_items_by_event(EFileEvent.ADDED_OR_RENAMED))
        
        whole_list = added_list | added_renamed_list
        
        if whole_list is None or len(whole_list) == 0:
            dialog_controller.hide_dialog()
            return
        self.__log.debug("store: %s, item: %s " % (store.get_id(), store.get_pending_changes().to_string()))
        
        for item in whole_list:
            dialog_controller.add_pending_item(item)

        self.__set_tag_information_to_dialog(store)

        
        dialog_controller.show_dialog()
     
    def handle_cancel(self):
        dialog_controller = self.sender()
        if dialog_controller is None or not isinstance(dialog_controller, TagDialogController):
            return
        dialog_controller.hide_dialog()
        
    def __set_tag_information_to_dialog_wrapper(self, store_id):
        for store in self.STORES:
            if store.get_id() == store_id:
                self.__set_tag_information_to_dialog(store)

    def __set_tag_information_to_dialog(self, store):
        """
        convenience method for refreshing the tag data at the gui-dialog
        """
        self.__log.debug("refresh tag information on dialog")
        dialog_controller = self.DIALOGS[store.get_id()]
        dialog_controller.set_tag_list(store.get_tags())
        
        item_list = dialog_controller.get_selected_item_list_public()

        if item_list is not None:
            if len(item_list) > 0 and item_list[0] is not None:
    
                if store.get_tagline_config() == 1 or store.get_tagline_config() == 2 or store.get_tagline_config() == 3:
                    tmp_cat_list = store.get_cat_recommendation(self.NUM_POPULAR_TAGS, str(item_list[0].text()))
                    cat_list = []
                    if store.is_controlled_vocabulary():
                        allowed_set = set(store.get_controlled_vocabulary())
                        dialog_controller.set_category_list(list(allowed_set))
            
                        ## just show allowed tags - so make the intersection of popular tags ant the allowed tags
                        for cat in tmp_cat_list:
                            if cat in list(allowed_set):
                                cat_list.append(cat)
                        #for cat in list(allowed_set):
                        #    if cat not in cat_list:
                        #        cat_list.append(cat)
                        #cat_list = list(cat_set.intersection(allowed_set)) 
                    else:
                        dialog_controller.set_category_list(store.get_categorizing_tags())
                        cat_list = tmp_cat_list
                    #print cat_list
                    #if len(cat_list) > self.NUM_POPULAR_TAGS:
                    #    cat_list = cat_list[:self.NUM_POPULAR_TAGS]
                    #dialog_controller.set_popular_categories(cat_list)
                    dict = store.get_cat_cloud(str(item_list[0].text())) 
                    dialog_controller.set_cat_cloud(dict, cat_list, self.MAX_CLOUD_TAGS)
                    
                ## make a list out of the set, to enable indexing, as not all tags cannot be used
                #tag_list = list(tag_set)
                if store.get_tagline_config() == 1 or store.get_tagline_config() == 2 or store.get_tagline_config() == 0:
                    tag_list = store.get_tag_recommendation(self.NUM_POPULAR_TAGS, str(item_list[0].text()))
                    #if len(tag_list) > self.NUM_POPULAR_TAGS:
                    #    tag_list = tag_list[:self.NUM_POPULAR_TAGS]
                    #dialog_controller.set_popular_tags(tag_list)
                    dict = store.get_tag_cloud(str(item_list[0].text()))
                    dialog_controller.set_tag_cloud(dict, tag_list, self.MAX_CLOUD_TAGS)
    
                
        
                #if len(self.DIALOGS) > 1:
                dialog_controller.set_store_name(store.get_name())
    
    def tag_item_action(self, store_name, item_name_list, tag_list, category_list):
        """
        write the tags for the given item to the store
        """
        
        store = None
        ## find the store where the item should be saved    
        for loop_store in self.STORES:
            if store_name == loop_store.get_name():
                store = loop_store
                break
            
        if store is not None:
            dialog_controller = self.DIALOGS[store.get_id()]
            try:
                ## 1. write the data to the store-file
                store.add_item_list_with_tags(item_name_list, tag_list, category_list)
                self.__log.debug("added items %s to store-file", item_name_list)
            except NameInConflictException, e:
                c_type = e.get_conflict_type()
                c_name = e.get_conflicted_name()
                if c_type == EConflictType.FILE:
                    dialog_controller.show_message(self.trUtf8("The filename - %s - is in conflict with an already existing tag. Please rename!" % c_name))
                elif c_type == EConflictType.TAG:
                    dialog_controller.show_message(self.trUtf8("The tag - %s - is in conflict with an already existing file" % c_name))
                else:
                    self.trUtf8("A tag or item is in conflict with an already existing tag/item")
                #raise
            except InodeShortageException, e:
                dialog_controller.show_message(self.trUtf8("The Number of free inodes is below the threshold of %s%" % e.get_threshold()))
                #raise
            except Exception, e:
                dialog_controller.show_message(self.trUtf8("An error occurred while tagging"))
                raise
Esempio n. 5
0
class Administration(QtCore.QObject):

    def __init__(self, application, verbose):
        QtCore.QObject.__init__(self)
        
        self.__log = None
        self.__main_config = None
        self.__admin_dialog = None
        self.__retag_dialog = None
        self.__verbose_mode = verbose
        # the main application which has the translator installed
        self.__application = application

        self.LOG_LEVEL = logging.INFO
        if verbose:
            self.LOG_LEVEL = logging.DEBUG
            

        self.STORE_CONFIG_DIR = TsConstants.DEFAULT_STORE_CONFIG_DIR
        self.STORE_CONFIG_FILE_NAME = TsConstants.DEFAULT_STORE_CONFIG_FILENAME
        self.STORE_TAGS_FILE_NAME = TsConstants.DEFAULT_STORE_TAGS_FILENAME
        self.STORE_VOCABULARY_FILE_NAME = TsConstants.DEFAULT_STORE_VOCABULARY_FILENAME
        
        self.__system_locale = unicode(QtCore.QLocale.system().name())[0:2]
        self.__translator = QtCore.QTranslator()
        if self.__translator.load("ts_" + self.__system_locale + ".qm", "tsresources/"):
            self.__application.installTranslator(self.__translator)
        # "en" is automatically translated to the current language e.g. en -> de
        self.CURRENT_LANGUAGE = self.__get_locale_language()
        #dir names for all available languages
        self.STORE_STORAGE_DIRS = []
        self.STORE_DESCRIBING_NAV_DIRS = []
        self.STORE_CATEGORIZING_NAV_DIRS = []
        self.STORE_EXPIRED_DIRS = []
        self.STORE_NAVIGATION_DIRS = []
        self.SUPPORTED_LANGUAGES = TsConstants.DEFAULT_SUPPORTED_LANGUAGES
        self.__store_dict = {}
        
        # catch all "possible" dir-names
        for lang in self.SUPPORTED_LANGUAGES: 
            self.change_language(lang) 
            self.STORE_STORAGE_DIRS.append(self.trUtf8("storage"))#self.STORE_STORAGE_DIR_EN))  
            self.STORE_DESCRIBING_NAV_DIRS.append(self.trUtf8("descriptions"))#self.STORE_DESCRIBING_NAVIGATION_DIR_EN))  
            self.STORE_CATEGORIZING_NAV_DIRS.append(self.trUtf8("categories"))#self.STORE_CATEGORIZING_NAVIGATION_DIR_EN)) 
            self.STORE_EXPIRED_DIRS.append(self.trUtf8("expired_items"))#STORE_EXPIRED_DIR_EN))
            self.STORE_NAVIGATION_DIRS.append(self.trUtf8("navigation")) 
        
        self.__log = LogHelper.get_app_logger(self.LOG_LEVEL)
        self.__init_configuration()
        
    def __init_configuration(self):
        """
        initializes the configuration. This method is called every time the config file changes
        """
        self.__log.info("initialize configuration")
        if self.__main_config is None:
            self.__main_config = ConfigWrapper(TsConstants.CONFIG_PATH)
            #self.connect(self.__main_config, QtCore.SIGNAL("changed()"), self.__init_configuration)
        
        self.CURRENT_LANGUAGE = self.__main_config.get_current_language();
        
        if self.CURRENT_LANGUAGE is None or self.CURRENT_LANGUAGE == "":
            self.CURRENT_LANGUAGE = self.__get_locale_language()
        
        # switch back to the configured language
        self.change_language(self.CURRENT_LANGUAGE)

        ## connect to all the signals the admin gui is sending 
        if self.__admin_dialog is None:
            self.__admin_dialog = StorePreferencesController()
            self.connect(self.__admin_dialog, QtCore.SIGNAL("create_new_store"), self.__handle_new_store)
            self.connect(self.__admin_dialog, QtCore.SIGNAL("rename_desc_tag"), self.__handle_tag_rename)
            self.connect(self.__admin_dialog, QtCore.SIGNAL("rename_cat_tag"), self.__handle_tag_rename)
            self.connect(self.__admin_dialog, QtCore.SIGNAL("retag"), self.__handle_retagging)
            
            self.connect(self.__admin_dialog, QtCore.SIGNAL("rebuild_store"), self.__handle_store_rebuild)
            self.connect(self.__admin_dialog, QtCore.SIGNAL("rename_store"), self.__handle_store_rename)
            self.connect(self.__admin_dialog, QtCore.SIGNAL("delete_store"), self.__handle_store_delete)

            self.connect(self.__admin_dialog, QtCore.SIGNAL("synchronize"), self.__handle_synchronization)
            
        self.__admin_dialog.set_main_config(self.__main_config)
        
        
        self.__prepare_store_params()
        self.__create_stores()
        
        ## create a temporary store list
        ## add the desc and cat tags which are needed in the admin-dialog
        tmp_store_list = []
        for current_store_item in self.__main_config.get_stores():
            store_name = current_store_item["path"].split("/").pop()
            current_store_item["desc_tags"] = self.__store_dict[store_name].get_tags()
            current_store_item["cat_tags"] = self.__store_dict[store_name].get_categorizing_tags()
            tmp_store_list.append(current_store_item)
        
        self.__admin_dialog.set_store_list(tmp_store_list)
        if self.__main_config.get_first_start():
            self.__admin_dialog.set_first_start(True)
    
    def __handle_synchronization(self, store_name):
        """
        do all the necessary synchronization stuff here ...
        """
        store_to_sync = self.__store_dict[str(store_name)]
        print "####################"
        print "synchronize " + store_name
        print "####################"
        
        store_to_sync.add_item_list_with_tags(["item_one", "item_two"], ["be", "tough"])
            
    def __handle_store_delete(self, store_name):
        self.__admin_dialog.start_progressbar(self.trUtf8("Deleting store ..."))
        store = self.__store_dict[str(store_name)]
        self.__store_to_be_deleted = store_name
        self.connect(store, QtCore.SIGNAL("store_delete_end"), self.__handle_store_deleted)
        ## remove the directories 
        store.remove()
        self.disconnect(store, QtCore.SIGNAL("store_delete_end"), self.__dummy)
        ## remove the config entry 
        self.__main_config.remove_store(store.get_id())
    
    def __dummy(self):
        return "dummy"
    
    def __handle_store_deleted(self, id):
        #second remove the item in the admin_dialog 
        self.__admin_dialog.remove_store_item(self.__store_to_be_deleted)
        
    def __handle_store_rename(self, store_name, new_store_name):
        """
        the whole store directory gets moved to the new directory
        the store will be rebuilt then to make sure all links are updated
        """
        ## show a progress bar at the admin dialog
        self.__admin_dialog.start_progressbar(self.trUtf8("Moving store ..."))
        store = self.__store_dict.pop(str(store_name))        

        self.__main_config.rename_store(store.get_id(), new_store_name)
        ## connect to the rebuild signal because after the moving there is a rebuild routine started
        self.connect(store, QtCore.SIGNAL("store_rebuild_end"), self.__handle_store_rebuild)

        store.move(new_store_name)
        
        self.disconnect(store, QtCore.SIGNAL("store_rebuild_end"))
        
        self.__init_configuration()
        
        
    def __handle_store_rebuild(self, store_name):
        """
        the whole store structure will be rebuild according to the records in store.tgs file
        """
        ## show a progress bar at the admin dialog
        self.__admin_dialog.start_progressbar(self.trUtf8("Rebuilding store ..."))
        store = self.__store_dict[str(store_name)]
        self.connect(store, QtCore.SIGNAL("store_rebuild_end"), self.__handle_store_rebuild)
        store.rebuild()
        self.disconnect(store, QtCore.SIGNAL("store_rebuild_end"), self.__get_locale_language)
    
    def __hide_progress_dialog(self, store_name):
        self.__admin_dialog.stop_progressbar()
        
    
    def __get_locale_language(self):
        """
        returns the translation of "en" in the system language
        """
        return self.trUtf8("en")
    
    def __handle_tag_rename(self, old_tag, new_tag, store_name):
        store = self.__store_dict[store_name]

        old_ba = old_tag.toUtf8()
        old_str = str(old_ba)
        
        new_ba = new_tag.toUtf8()
        new_str = str(new_ba)
        store.rename_tag(unicode(old_str, "utf-8"), unicode(new_str, "utf-8"))
    
    def set_application(self, application):
        """
        if the manager is called from another qt application (e.g. tagstore.py)
        you must set the calling application here for proper i18n
        """
        self.__application = application
    
    def __handle_retagging(self, store_name, item_name):
        """
        creates and configures a tag-dialog with all store-params and tags
        """
        store = self.__store_dict[store_name]
        
        ## make a string object of the QListWidgetItem, so other methods can use it
        item_name = item_name.text()                
        self.__log.info("retagging item %s at store %s..." % (item_name, store_name))
        #if(self.__retag_dialog is None):
            
        ## create the object
        self.__retag_dialog = ReTagController(self.__application, store.get_store_path(), item_name, True, self.__verbose_mode)
        ## connect to the signal(s)
        self.connect(self.__retag_dialog, QtCore.SIGNAL("retag_error"), self.__handle_retag_error)
        self.connect(self.__retag_dialog, QtCore.SIGNAL("retag_cancel"), self.__handle_retag_cancel)
        self.connect(self.__retag_dialog, QtCore.SIGNAL("retag_success"), self.__handle_retag_success)
        self.__retag_dialog.start()

    def __kill_tag_dialog(self):
        """
        hide the dialog and set it to None
        """
        self.__retag_dialog.hide_tag_dialog()
        self.__retag_dialog = None
    
    def __handle_retag_error(self):
        self.__kill_tag_dialog()
        self.__admin_dialog.show_tooltip(self.trUtf8("An error occurred while re-tagging"))
    
    def __handle_retag_success(self):
        self.__kill_tag_dialog()
        self.__admin_dialog.show_tooltip(self.trUtf8("Re-tagging successful!"))
    
    def __handle_retag_cancel(self):
        """
        the "postpone" button in the re-tag dialog has been clicked
        """
        self.__kill_tag_dialog()
    
    def __set_tag_information_to_dialog(self, store):
        """
        convenience method for setting the tag data at the gui-dialog
        """
        self.__retag_dialog.set_tag_list(store.get_tags())
        
        num_pop_tags = self.__main_config.get_num_popular_tags()
        
        tag_set = set(store.get_popular_tags(self.__main_config.get_max_tags()))
        tag_set = tag_set | set(store.get_recent_tags(num_pop_tags))

        cat_set = set(store.get_popular_categories(num_pop_tags))
        cat_set = cat_set | set(store.get_recent_categories(num_pop_tags))

        cat_list = list(cat_set)
        if store.is_controlled_vocabulary():
            allowed_set = set(store.get_controlled_vocabulary())
            self.__retag_dialog.set_category_list(list(allowed_set))

            ## just show allowed tags - so make the intersection of popular tags ant the allowed tags
            cat_list = list(cat_set.intersection(allowed_set)) 
        else:
            self.__retag_dialog.set_category_list(store.get_categorizing_tags())
            
        if len(cat_list) > num_pop_tags:
            cat_list = cat_list[:num_pop_tags]
        self.__retag_dialog.set_popular_categories(cat_list)
        
        ## make a list out of the set, to enable indexing, as not all tags cannot be used
        tag_list = list(tag_set)
        if len(tag_list) > num_pop_tags:
            tag_list = tag_list[:num_pop_tags]
        self.__retag_dialog.set_popular_tags(tag_list)


        self.__retag_dialog.set_store_name(store.get_name())
    
    def __retag_item_action(self, store_name, item_name, tag_list, category_list):
        """
        the "tag!" button in the re-tag dialog has been clicked
        """
        store = self.__store_dict[store_name]
        try:
            ## 1. write the data to the store-file
            store.add_item_with_tags(item_name, tag_list, category_list)
            self.__log.debug("added item %s to store-file", item_name)
        except NameInConflictException, e:
            c_type = e.get_conflict_type()
            c_name = e.get_conflicted_name()
            if c_type == EConflictType.FILE:
                self.__retag_dialog.show_message(self.trUtf8("The filename - %s - is in conflict with an already existing tag. Please rename!" % c_name))
            elif c_type == EConflictType.TAG:
                self.__retag_dialog.show_message(self.trUtf8("The tag - %s - is in conflict with an already existing file" % c_name))
            else:
                self.trUtf8("A tag or item is in conflict with an already existing tag/item")
            #raise
        except InodeShortageException, e:
            self.__retag_dialog.show_message(self.trUtf8("The Number of free inodes is below the threshold of %s%" % e.get_threshold()))
Esempio n. 6
0
class Store(QtCore.QObject):

    __pyqtSignals__ = ("removed(PyQt_PyObject)",
                       "renamed(PyQt_PyObject, QString)",
                       "file_renamed(PyQt_PyObject, QString, QString)",
                       "file_removed(PyQt_PyObject, QString)",
                       "pending_operations_changed(PyQt_PyObject)")

    def __init__(self, id, path, config_file_name, tags_file, vocabulary_file, navigation_dir_list, storage_dir_list, describing_nav_dir_list, categorising_nav_dir_list, expiry_dir_list, expiry_prefix):
        """
        constructor
        """
        QtCore.QObject.__init__(self)

        #self.__log = logging.getLogger("TagStoreLogger")#None##FIXXME
        self.__log = None

        self.__file_system = FileSystemWrapper(self.__log)
        self.__watcher = QtCore.QFileSystemWatcher(self)
        self.__watcher.connect(self.__watcher,QtCore.SIGNAL("directoryChanged(QString)"), self.__directory_changed)
        self.__tag_wrapper = None
        self.__sync_tag_wrapper = None
        self.__store_config_wrapper = None
        self.__pending_changes = PendingChanges()
        
        self.__sync_tags_file_name = TsConstants.DEFAULT_STORE_SYNC_TAGS_FILENAME
        
        self.__tagline_config = None
        self.__paths_to_maintain = []
        
        self.__id = unicode(id)
        self.__path = unicode(path)
        self.__config_file_name = unicode(config_file_name)
        self.__tags_file_name = unicode(tags_file)
        self.__vocabulary_file_name = unicode(vocabulary_file)
        
        self.__storage_dir_list = storage_dir_list
        self.__describing_nav_dir_list = describing_nav_dir_list
        self.__categorising_nav_dir_list = categorising_nav_dir_list
        self.__expiry_dir_list = expiry_dir_list
        self.__expiry_prefix = unicode(expiry_prefix)
        
        self.__storage_dir_name = self.trUtf8("storage")
        self.__navigation_dir_name = self.trUtf8("navigation")
        self.__describing_nav_dir_name = self.trUtf8("descriptions")
        self.__categorising_nav_dir_name = self.trUtf8("categories")
        self.__expiry_dir_name = self.trUtf8("expired_items")
        #self.__parent_path = None
        #self.__name = None
        #self.__config_path = None
        #self.__watcher_path = None
        #self.__describing_nav_path = None
        #self.__config_path = self.__path + "/" + self.__config_file_name
        #self.__watcher_path = self.__path + "/" + self.__storage_dir_name
        #self.__describing_nav_path = self.__path + "/" + self.__describing_nav_dir_name

        self.__create_wrappers()
        
        if self.__path.find(":/") == -1:
            self.__path = self.__path.replace(":", ":/")
        self.__name = unicode(self.__path.split("/")[-1])
        self.__parent_path = unicode(self.__path[:len(self.__path)-len(self.__name)-1])
        
        self.__tagcloud = TagCloud()
        self.__recommender = Recommender(self.get_store_path())
        
    def __create_wrappers(self):
        if self.__file_system.path_exists(self.__path + "/" + self.__tags_file_name):
            self.__tag_wrapper = TagWrapper(self.__path + "/" + self.__tags_file_name)
        if self.__file_system.path_exists(self.__path + "/" + self.__config_file_name):
            self.__store_config_wrapper = ConfigWrapper(self.__path + "/" + self.__config_file_name)

    def init(self):
        """
        init is called after event listeners were added to the store instance
        """
        ## throw exception if store directory does not exist
        if not self.__file_system.path_exists(self.__path):
            ## look for renamed or removed store folder
            self.__handle_renamed_removed_store()
        if not self.__file_system.path_exists(self.__path):
            #print self.__path
            raise StoreInitError, self.trUtf8("The specified store directory does not exist! %s" % self.__path)
            return
        
        
        ## look for store/describing_nav/categorising_nav/expire directories names (all languages) if they do not exist
        if not self.__file_system.path_exists(self.__path + "/" + self.__storage_dir_name):
            for dir in self.__storage_dir_list:
                if self.__file_system.path_exists(self.__path + "/" + dir):
                    self.__storage_dir_name = unicode(dir)
        if not self.__file_system.path_exists(self.__path + "/" + self.__describing_nav_dir_name):
            for dir in self.__describing_nav_dir_list:
                if self.__file_system.path_exists(self.__path + "/" + dir):
                    self.__describing_nav_dir_name = unicode(dir)
        if not self.__file_system.path_exists(self.__path + "/" + self.__categorising_nav_dir_name):
            for dir in self.__categorising_nav_dir_list:
                if self.__file_system.path_exists(self.__path + "/" + dir):
                    self.__categorising_nav_dir_name = unicode(dir)
        if not self.__file_system.path_exists(self.__path + "/" + self.__expiry_dir_name):
            for dir in self.__expiry_dir_list:
                if self.__file_system.path_exists(self.__path + "/" + dir):
                    self.__expiry_dir_name = unicode(dir)
        if not self.__file_system.path_exists(self.__path + "/" + self.__navigation_dir_name):
            for dir in self.__expiry_dir_list:
                if self.__file_system.path_exists(self.__path + "/" + dir):
                    self.__navigation_dir_name = unicode(dir)
        
        
        
        ## built stores directories and config file if they currently not exist (new store)
        self.__file_system.create_dir(self.__path + "/" + self.__storage_dir_name)
        self.__file_system.create_dir(self.__path + "/" + self.__expiry_dir_name)
        self.__file_system.create_dir(self.__path + "/" + self.__config_file_name.split("/")[0])
        self.__file_system.create_dir(self.__path + "/" + self.__navigation_dir_name)
        ## create config/vocabulary files if they don't exist
        if not self.__file_system.path_exists(self.__path + "/" + self.__config_file_name):
            ConfigWrapper.create_store_config_file(self.__path + "/" + self.__config_file_name)
            ## now create a new config_wrapper instance
            self.__store_config_wrapper = ConfigWrapper(self.__path + "/" + self.__config_file_name)
        if not self.__file_system.path_exists(self.__path + "/" + self.__tags_file_name):
            TagWrapper.create_tags_file(self.__path + "/" + self.__tags_file_name)
            ## now create a new tag_wrapper instance
            self.__tag_wrapper = TagWrapper(self.__path + "/" + self.__tags_file_name)
        if not self.__file_system.path_exists(self.__path + "/" + self.__vocabulary_file_name):
            self.__vocabulary_wrapper = VocabularyWrapper.create_vocabulary_file(self.__path + "/" + self.__vocabulary_file_name)


        ## 0 ... show just the describing tagline -> create the NAVIGATION dir 
        ## 3 ... show just the categorizing tagline - only restricted vocabulary is allowed -> create the CATEGORIES dir
        ## ELSE: two taglines with dirs: CATEGORIES/DESCRIPTIONS
        self.__tagline_config = self.__store_config_wrapper.get_show_category_line()
        
        # clear the old list (if there is already one)
        self.__paths_to_maintain = []
        
        if self.__tagline_config == 0:
            #self.__file_system.create_dir(self.__path + "/" + self.__navigation_dir_name)
            self.__paths_to_maintain.append(self.__path + "/" + self.__navigation_dir_name)
        elif self.__tagline_config == 3:
            #self.__file_system.create_dir(self.__path + "/" + self.__categorising_nav_dir_name)
            self.__paths_to_maintain.append(self.__path + "/" + self.__categorising_nav_dir_name)
        else:
            #self.__file_system.create_dir(self.__path + "/" + self.__categorising_nav_dir_name)
            self.__paths_to_maintain.append(self.__path + "/" + self.__categorising_nav_dir_name)
            #self.__file_system.create_dir(self.__path + "/" + self.__describing_nav_dir_name)
            self.__paths_to_maintain.append(self.__path + "/" + self.__describing_nav_dir_name)

        for path in self.__paths_to_maintain:
            self.__file_system.create_dir(path)

        self.__init_store()

    def init_sync_log(self, target_store_name):
        """
        initializes the sync log
        """
        # construct sync tags file path
        target_store_name = target_store_name.replace(":", "")
        
        self.__sync_tags_file_path = self.__path + "/" + TsConstants.DEFAULT_STORE_CONFIG_DIR + "/" + target_store_name + self.__sync_tags_file_name
        
        self.__log.info("init sync log path:%s" % self.__sync_tags_file_path)
        if not self.__file_system.path_exists(self.__sync_tags_file_path):
            # create default sync tags file
            TagWrapper.create_tags_file(self.__sync_tags_file_path)
            
        ## now create a new sync tag_wrapper instance
        self.__sync_tag_wrapper = TagWrapper(self.__sync_tags_file_path)

    def sync_item_exists(self, item_name):
        """
        checks an item exists in the sync log
        """
        return self.__sync_tag_wrapper.file_exists(item_name)

    def get_sync_items(self):
        """
        returns a list of all item names in the sync log 
        """
        return self.__sync_tag_wrapper.get_files()

    def get_sync_file_timestamp(self, file_name):
        """
        returns the timestamp value in the sync log
        """
        return self.__sync_tag_wrapper.get_file_timestamp(file_name)
        
    def get_describing_sync_tags_for_item(self, item_name):
        """
        returns all describing tags associated with the given item in the sync log
        """
        return self.__sync_tag_wrapper.get_file_tags(item_name)
        
    def get_categorizing_sync_tags_for_item(self, item_name):
        """
        returns all categorizing tags associated with the given item in the sync log
        """
        return self.__sync_tag_wrapper.get_file_categories(item_name)

        
    def __init_store(self):
        """
        initializes the store paths, config reader, file system watcher without instantiation of a new object
        """
        self.__name = self.__path.split("/")[-1]
        self.__parent_path = self.__path[:len(self.__path)-len(self.__name)]
        self.__tags_file_path = self.__path + "/" + self.__tags_file_name
        self.__sync_tags_file_path = self.__path + "/" + TsConstants.DEFAULT_STORE_CONFIG_DIR + "/" + self.__sync_tags_file_name
        self.__config_path = self.__path + "/" + self.__config_file_name
        self.__vocabulary_path = self.__path + "/" + self.__vocabulary_file_name #TsConstants.STORE_CONFIG_DIR + "/" + TsConstants.STORE_VOCABULARY_FILENAME
        self.__watcher_path = self.__path + "/" + self.__storage_dir_name
        self.__navigation_path = self.__path + "/" + self.__navigation_dir_name
        self.__describing_nav_path = self.__path + "/" + self.__describing_nav_dir_name
        self.__categorising_nav_path = self.__path + "/" + self.__categorising_nav_dir_name
        config_file_name = unicode(self.__config_path.split("/")[-1])
        self.__temp_progress_path = unicode(self.__config_path[:len(self.__config_path)-len(config_file_name)-1])
        
        self.__tag_wrapper = TagWrapper(self.__tags_file_path)
        self.__sync_tag_wrapper = TagWrapper(self.__sync_tags_file_path)
        
        ## update store id to avoid inconsistency
        config_wrapper = ConfigWrapper(self.__path + "/" + self.__config_file_name)#self.__tags_file_name)
        config_wrapper.set_store_id(self.__id)
        self.__vocabulary_wrapper = VocabularyWrapper(self.__vocabulary_path)
        self.connect(self.__vocabulary_wrapper, QtCore.SIGNAL("changed"), self.__handle_vocabulary_changed)
        self.__store_config_wrapper = ConfigWrapper(self.__config_path)
        self.connect(self.__store_config_wrapper, QtCore.SIGNAL("changed()"), self.__handle_store_config_changed)
        
        if len(self.__name) == 0:
            self.__name = self.__path[:self.__path.rfind("/")]
        
        if not self.__is_android_store():
            # no activity is required on android tag stores
            self.__watcher.addPath(self.__parent_path)
            self.__watcher.addPath(self.__watcher_path)
        
        ## all necessary files and dirs should have been created now - so init the logger
        self.__log = LogHelper.get_store_logger(self.__path, logging.INFO) 
        self.__log.info("parent_path: '%s'" % self.__name)

        ## handle offline changes
        self.__handle_unfinished_operation()
        self.__handle_file_expiry()
        self.__handle_file_changes(self.__watcher_path)
        
    
    def __handle_store_config_changed(self):
        self.emit(QtCore.SIGNAL("store_config_changed"), self)

    def __handle_vocabulary_changed(self):
        self.emit(QtCore.SIGNAL("vocabulary_changed"), self)
        
#    def handle_offline_changes(self):
#        """
#        called after store and event-handler are created to handle (offline) modifications
#        """
#        self.__handle_file_changes(self.__watcher_path)

    def add_ignored_extensions(self, ignored_list):
        self.__file_system.add_ignored_extensions(ignored_list)

    def set_path(self, path, config_file=None, tags_file=None, vocabulary_file=None):
        """
        resets the stores path and config path (called if application config changes)
        """
        if self.__path == unicode(path) and (config_file is None or self.__config_file_name == unicode(config_file)):
            exit
        ## update changes
        self.__watcher.removePaths([self.__parent_path, self.__watcher_path])
        self.__path = unicode(path)
        if config_file is not None:
            self.__config_file_name = unicode(config_file)
        if tags_file is not None:
            self.__tags_file_name = unicode(tags_file)
        if vocabulary_file is not None:
            self.__vocabulary_file_name = unicode(vocabulary_file)
        self.__init_store()
        
    def __handle_renamed_removed_store(self):
        """
        searches the parents directory for renamed or removed stores
        """
        #print self.__parent_path
        #print self.__config_file_name
        #print ".."
        config_paths = self.__file_system.find_files(self.__parent_path, self.__config_file_name)
        #print "config paths: " + ",".join(config_paths)
        new_name = ""
        for path in config_paths:
            reader = ConfigWrapper(path)
            #print "found: " + path
            #print self.__id + ", " + reader.get_store_id()
            
            if self.__id == reader.get_store_id():
                new_name = path.split("/")[-3]
                #print "new name: " + new_name

        if new_name == "":      ## removed
            ## delete describing_nav directors
            #self.remove()
            self.emit(QtCore.SIGNAL("removed(PyQt_PyObject)"), self)
        else:                   ## renamed
            self.__path = self.__parent_path + "/" + new_name
            self.__navigation_path = self.__path + "/" + self.__navigation_dir_name
            self.__describing_nav_path = self.__path + "/" + self.__describing_nav_dir_name
            self.__categorising_nav_path = self.__path + "/" + self.__categorising_nav_dir_name
            ## update all links in windows: absolute links only
            #if self.__file_system.get_os() == EOS.Windows:
                #print "rebuild"
                #self.rebuild()
            #print "emit: " + self.__parent_path + "/" + new_name
            self.emit(QtCore.SIGNAL("renamed(PyQt_PyObject, QString)"), self, self.__parent_path + "/" + new_name)
    
    def __directory_changed(self, path):
        """
        handles directory changes of the stores directory and its parent directory 
        and finds out if the store itself was renamed/removed
        """
        if path == self.__parent_path:
            if not self.__file_system.path_exists(self.__path):
                ## store itself was changed: renamed, moved or deleted
                self.__watcher.removePath(self.__parent_path)
                self.__handle_renamed_removed_store()
        else:
            ## files or directories in the store directory have been changed
            self.__handle_file_changes(self.__watcher_path)

    def __handle_unfinished_operation(self):
        """
        looks for a opInProgress.tmp file to find out if the last operation was finished correctly
        this file is created before an operation starts and deleted afterwards
        """
        if self.__file_system.path_exists(self.__temp_progress_path + "/" + "opInProgress.tmp"):
            self.rebuild()
            
    def __create_inprogress_file(self):
        """
        creates a temporary file during an operation in progress to handle operation interruption
        """
        self.__file_system.create_file(self.__temp_progress_path + "/" + "opInProgress.tmp")

    def __remove_inprogress_file(self):
        """
        removes the temporary file after the operation succeeded
        """
        self.__file_system.remove_file(self.__temp_progress_path + "/" + "opInProgress.tmp")
        
    def __handle_file_expiry(self):
        """
        looks for expired items and moves & renames them to filename including tags in the expiry_directory
        """
        expiry_date_files = self.__tag_wrapper.get_files_with_expiry_tags(self.__expiry_prefix)
        now = datetime.datetime.now()
        for file in expiry_date_files:
            file_extension = "." + file["filename"].split(".")[-1]
            file_name = file["filename"]
            file_name = file_name[:len(file_name)-len(file_extension)]
            if int(file["exp_year"]) < now.year or (int(file["exp_year"]) == now.year and int(file["exp_month"]) < now.month):
                new_filename = file_name + " - " + "; ".join(file["category"]) + " - " + "; ".join(file["tags"]) + file_extension
                self.__file_system.rename_file(self.__watcher_path + "/" + file["filename"], self.__path + "/" + self.__expiry_dir_name + "/" + new_filename)
    
    def __get_lockfile_path(self):
        return self.__path + "/" + self.__storage_dir_name + "/" + TsConstants.DEFAULT_SYNCHRONIZATION_LOCKFILE_NAME
    
                    
    def __is_sync_active(self):
        """
        returns true when the sync is active
        """
  
        # get lock path
        path = self.__get_lockfile_path();
  
        # check if path exists        
        result = self.__file_system.path_exists(path)
        if result == False:
            return result
        
        
        # read pid from file
        old_pid = None 
        pid_file = open(path, "r")
        
        for line in pid_file.readlines():
            old_pid = line

        # close pid file
        pid_file.close()
        
        if old_pid is None or old_pid == "":
            # empty file remove
            self.__file_system.remove_file(path)
            return False
        
        # check if the pid still exists
        return PidHelper.pid_exists(old_pid)

    def __handle_file_changes(self, path):
        """
        handles the stores file and dir changes to find out if a file/directory was added, renamed, removed
        """
        if(path == self.__get_lockfile_path()):
            return
        
        ## if there is a synchronize procedure running - just do nothing
        #if(self.__is_synchronize_in_progress()):
        #    print "recognized a new file - but this must be from the sync-process"
        #    return
        
        if self.__is_sync_active():
            self.__log.info("__handle_file_changes: sync is active")
            return

        if self.__is_android_store():
            # no notifications on android stores
            self.__log.info("__handle_file_changes: no notifications on android stores")
            return
        
        # sync any changes if the´sync was active
        self.__tag_wrapper.sync_settings()
        
        ## this method does not handle the renaming or deletion of the store directory itself (only childs)
        existing_files = set(self.__file_system.get_files(path))
        existing_dirs = set(self.__file_system.get_directories(path))
        config_files = set(self.__tag_wrapper.get_files())
        captured_added_files = set(self.__pending_changes.get_added_names())
        captured_removed_files = set(self.__pending_changes.get_removed_names())

        data_files = (config_files | captured_added_files) - captured_removed_files 
        added = list((existing_files | existing_dirs) - data_files)
        removed = list(data_files - (existing_files | existing_dirs))
    
        #names = self.__pending_changes.get_added_names()
        #for name in names:
        #    self.__log.info(name)
    
        if len(added) == 1 and len(removed) == 1:
            self.__pending_changes.register(removed[0], self.__get_type(removed[0]), EFileEvent.REMOVED_OR_RENAMED)
            self.__pending_changes.register(added[0], self.__get_type(added[0]), EFileEvent.ADDED_OR_RENAMED)
            self.emit(QtCore.SIGNAL("file_renamed(PyQt_PyObject, QString, QString)"), self, removed[0], added[0])
        else:
            if len(removed) > 0:
                if len(added) == 0:
                    for item in removed:
                        self.__pending_changes.register(item, self.__get_type(item), EFileEvent.REMOVED)
                        self.emit(QtCore.SIGNAL("file_removed(PyQt_PyObject, QString)"), self, item)
                else:
                    for item in removed:
                        self.__pending_changes.register(item, self.__get_type(item), EFileEvent.REMOVED_OR_RENAMED)
                        self.emit(QtCore.SIGNAL("pending_operations_changed(PyQt_PyObject)"), self)
            if len(added) > 0:
                if len(removed) == 0:
                    for item in added:
                        self.__pending_changes.register(item, self.__get_type(item), EFileEvent.ADDED)
                        self.emit(QtCore.SIGNAL("pending_operations_changed(PyQt_PyObject)"), self)
                else:
                    for item in added:
                        self.__pending_changes.register(item, self.__get_type(item), EFileEvent.ADDED_OR_RENAMED)
                        self.emit(QtCore.SIGNAL("pending_operations_changed(PyQt_PyObject)"), self)                
        
    def __get_type(self, item):
        """
        returns the items type to be stored in pending_changes
        """
        if self.__file_system.is_directory(self.__watcher_path + "/" + unicode(item)):
            return EFileType.DIRECTORY
        return EFileType.FILE
    
    def get_name(self):
        """
        returns the stores name
        """
        return self.__name
    
    def get_id(self):
        """
        returns the stores id
        """
        return unicode(self.__id)
    def get_max_tags(self):
        return self.__store_config_wrapper.get_max_tags()
    def get_tag_separator(self):
        return self.__store_config_wrapper.get_tag_seperator()

    def get_store_path(self):
        """
        returns the root of the tagstore
        """
        return self.__path
    
    def get_pending_changes(self):
        """
        returns the stores unhandled changes 
        """
        return self.__pending_changes
    
    def move(self, new_path):
        """
        moves the whole path to the specified place 
        """
        ## first of all move the physical data to the new location 
        self.__file_system.move(self.__path, new_path)
        ## re-set the path variable
        self.__path = new_path
        ## initialize to update all necessary membervariables
        self.init()
        ## rebuild the whole store structure to make sure all links are updated
        self.rebuild()

    def remove(self):
        """
        removes all directories and links in the stores describing_nav path
        """
        for path in self.__paths_to_maintain:
            self.__file_system.delete_dir_content(path)
        
        self.emit(QtCore.SIGNAL("store_delete_end"), self.__id)
    
    def rebuild(self):
        """
        removes and rebuilds all links in the describing_nav path
        """
        self.__create_inprogress_file()
        self.__log.info("START rebuild progress")
        self.remove()
        for file in self.__tag_wrapper.get_files():
            describing_tag_list = self.__tag_wrapper.get_file_tags(file)
            categorising_tag_list = self.__tag_wrapper.get_file_categories(file)
            self.add_item_with_tags(file, describing_tag_list, categorising_tag_list)
        self.__remove_inprogress_file()
        self.emit(QtCore.SIGNAL("store_rebuild_end"), self.__name)
        self.__log.info("rebuild progress END")
    
    def rename_file(self, old_file_name, new_file_name):
        """
        renames an existing file: links and config settings 
        """
        self.__log.info("renaming: %s to %s" % (old_file_name, new_file_name))
        self.__create_inprogress_file()
        if self.__tag_wrapper.file_exists(old_file_name):
            describing_tag_list = self.__tag_wrapper.get_file_tags(old_file_name)
            categorising_tag_list = self.__tag_wrapper.get_file_categories(old_file_name)
            self.remove_file(old_file_name)
            self.add_item_with_tags(new_file_name, describing_tag_list, categorising_tag_list)

            self.__pending_changes.remove(old_file_name)
            self.__pending_changes.remove(new_file_name)
        else:
            self.__pending_changes.edit(old_file_name, new_file_name)
            self.emit(QtCore.SIGNAL("pending_operations_changed(PyQt_PyObject)"), self)
        self.__remove_inprogress_file()
        
    def remove_file(self, file_name):
        """
        removes a file: links and config settings 
        """
        self.__log.info("remove file: %s" % file_name)
        self.__create_inprogress_file()
        self.__pending_changes.remove(file_name)
        if self.__tag_wrapper.file_exists(file_name):
            describing_tag_list = self.__tag_wrapper.get_file_tags(file_name)
            categorising_tag_list = self.__tag_wrapper.get_file_categories(file_name)
            for path in self.__paths_to_maintain:
                if path == self.__describing_nav_path:
                    self.__delete_links(file_name, describing_tag_list, self.__describing_nav_path)
                if path == self.__categorising_nav_path:
                    self.__delete_links(file_name, categorising_tag_list, self.__categorising_nav_path)
                if path == self.__navigation_path:
                    #changed fron cat -> do desc tags because there are just descrbing tags when
                    #there is just the "navigation" folder
                    #self.__delete_links(file_name, categorising_tag_list, self.__navigation_path)
                    self.__delete_links(file_name, describing_tag_list, self.__navigation_path)
            self.__tag_wrapper.remove_file(file_name)
        else:
            self.emit(QtCore.SIGNAL("pending_operations_changed(PyQt_PyObject)"), self)
        self.__remove_inprogress_file()
        
    def __delete_links(self, file_name, tag_list, current_path):
        """
        deletes all links to the given file
        """
        self.__create_inprogress_file()
        for tag in tag_list:
            recursive_list = [] + tag_list
            recursive_list.remove(tag)
            self.__delete_links(file_name, recursive_list, current_path + "/" + tag)
            self.__file_system.remove_link(current_path + "/" + tag + "/" + file_name)
        self.__remove_inprogress_file()
    
    def change_expiry_prefix(self, new_prefix):
        """
        changes the expiry prefix and all existing expiry tags
        """
        ## handle changes only
        if self.__expiry_prefix == new_prefix:  
            return

        self.__log.info("changing the expiry prefix from %s to %s" % (self.__expiry_prefix, new_prefix))
        
        self.__create_inprogress_file()
        expiry_date_files = self.__tag_wrapper.get_files_with_expiry_tags(self.__expiry_prefix)
        
        for file in expiry_date_files:
            for tag in file["tags"]:
                match = re.match("^(" + self.__expiry_prefix + ")([0-9]{4})(-)([0-9]{2})", tag)
                if match:
                    self.rename_tag(tag, tag.replace(self.__expiry_prefix, new_prefix))
            
            for tag in file["category"]:
                match = re.match("^(" + self.__expiry_prefix + ")([0-9]{4})(-)([0-9]{2})", tag)
                if match:
                    self.rename_tag(tag, tag.replace(self.__expiry_prefix, new_prefix))

        ## set new prefix
        self.__expiry_prefix = new_prefix
        self.__remove_inprogress_file()
    
    def get_items(self):
        """
        returns a list of all item names in the store 
        """
        return self.__tag_wrapper.get_files()
    
    def get_tags(self):
        """
        returns a list of all describing  tags
        """
        return self.__tag_wrapper.get_all_tags()

    def get_categorizing_tags(self):
        """
        returns a list of categorizing all tags
        """
        return self.__tag_wrapper.get_all_categorizing_tags()

    def get_recent_tags(self, number):
        """
        returns a given number of recently entered tags
        """
        return self.__tag_wrapper.get_recent_tags(number)
    
    def get_popular_tags(self, number):
        """
        returns a given number of the most popular tags
        """
        return self.__tag_wrapper.get_popular_tags(number)

    def get_popular_categories(self, number):
        """
        returns a given number of the most popular tags
        """
        return self.__tag_wrapper.get_popular_categories(number)

    def get_recent_categories(self, number):
        """
        returns a given number of recently entered tags
        """
        return self.__tag_wrapper.get_recent_categories(number)

    def get_describing_tags_for_item(self, item_name):
        """
        returns all describing tags associated with the given item
        """
        return self.__tag_wrapper.get_file_tags(item_name)
        
    def get_categorizing_tags_for_item(self, item_name):
        """
        returns all categorizing tags associated with the given item
        """
        return self.__tag_wrapper.get_file_categories(item_name)
        

    def get_show_category_line(self):
        return self.__store_config_wrapper.get_show_category_line()

    def is_controlled_vocabulary(self):
        """
        return True if there is just controlled vocabulary allowed in the second tagline 
        """
        setting = self.__store_config_wrapper.get_show_category_line()
        if setting == ECategorySetting.ENABLED_ONLY_PERSONAL or setting == ECategorySetting.ENABLED_SINGLE_CONTROLLED_TAGLINE:
            return True
        return False
    
    def get_datestamp_format(self):
        return self.__store_config_wrapper.get_datestamp_format()

    def get_datestamp_hidden(self):
        return self.__store_config_wrapper.get_datestamp_hidden()
    
    def get_category_mandatory(self):
        return self.__store_config_wrapper.get_category_mandatory()

    def __name_in_conflict(self, file_name, describing_tag_list, categorising_tag_list):
        """
        checks for conflicts and returns the result as boolean
        """
        
        ## both lists could be none if there is just one tagline
        if(categorising_tag_list is None):
            categorising_tag_list = []
        if(describing_tag_list is None):
            describing_tag_list = []
        
        #TODO: extend functionality: have a look at #18 (Wiki)
        existing_files = self.__tag_wrapper.get_files()
        existing_tags = self.__tag_wrapper.get_all_tags()
        tag_list = list(set(describing_tag_list) | set(categorising_tag_list))

        file_name = unicode(file_name)        

        if file_name in existing_tags:
            return [file_name, EConflictType.FILE]
        for tag in tag_list:
            if tag in existing_files:
                return [tag, EConflictType.TAG]
        return ["", None]
    
    def add_item_list_with_tags(self, file_name_list, describing_tag_list, categorising_tag_list=None, silent=False):
        for item in file_name_list:
            self.add_item_with_tags(item, describing_tag_list, categorising_tag_list, silent)
        
    def add_item_with_tags(self, file_name, describing_tag_list, categorising_tag_list=None, silent=False):
        """
        adds tags to the given file, resets existing tags
        """
        #TODO: if file_name already in config, delete missing tags and recreate whole link structure
        #existing tags will not be recreated in windows-> linux, osx???
         
        #self.__log.info("add item with tags to navigation: itemname: %s" % file_name)
        #self.__log.info("describing tags: %s" % describing_tag_list)
        #self.__log.info("categorizing tags: %s" % categorising_tag_list)
        ## throw error if inodes run short
        if self.__file_system.inode_shortage(self.__config_path):
            self.__log.error("inode threshold has exceeded")
            raise InodeShortageException(TsRestrictions.INODE_THRESHOLD)
        ## throw error if item-names and tag-names (new and existing) are in conflict
        conflict = self.__name_in_conflict(file_name, describing_tag_list, categorising_tag_list)
        if conflict[0] != "":
            self.__log.error("name_in_conflict_error: %s, %s" % (conflict[0], conflict[1]))
            raise NameInConflictException(conflict[0], conflict[1])
        ## ignore multiple tags
        describing_tags = list(set(describing_tag_list))
        categorising_tags = []
        if categorising_tag_list is not None:
            categorising_tags = list(set(categorising_tag_list))


        #try:
        self.__create_inprogress_file()
        
        #print "-----"
        #print self.__describing_nav_path
        #print self.__categorising_nav_path
        #print self.__navigation_path
        # is it not an android store

        start = time()#time.clock() ## performance measure
        self.__log.info("starting to create TagTrees for item: %s" % file_name) ## FIXXME: remove this line if time measurement works

        if not self.__is_android_store():
            for path in self.__paths_to_maintain:
                if path == self.__describing_nav_path:
                    self.__build_store_navigation(file_name, describing_tags, self.__describing_nav_path)
                elif path == self.__categorising_nav_path:
                    self.__build_store_navigation(file_name, categorising_tags, self.__categorising_nav_path)
                elif path == self.__navigation_path:
                    self.__build_store_navigation(file_name, describing_tags, self.__navigation_path)
        #except:
        #    raise Exception, self.trUtf8("An error occurred during building the navigation path(s) and links!")
        #try:
        
        self.__tag_wrapper.set_file(file_name, describing_tags, categorising_tags)

        self.__pending_changes.remove(file_name)
        self.__remove_inprogress_file()
        #except:
        #    raise Exception, self.trUtf8("An error occurred during saving file and tags to configuration file!")
        ## scalability test
        ## print "number of tags: " + str(len(tags)) + ", time: " + str(time.clock()-start)
        self.__log.info("tagged item " + file_name + \
                            ", # descr tags: " + str(len(describing_tags)) + \
                            ", # categ tags: " + str(len(categorising_tags)) + \
                            "; %f" % (time()-start) )  ## performance measure
        ## CAUTION: time.clock() measures something weird, but not actual time
        
    def __build_store_navigation(self, link_name, tag_list, current_path):
        """
        builds the whole directory and link-structure (describing & categorising nav path) inside a stores filesystem
        """
        link_source = self.__watcher_path + "/" + link_name

        for tag in tag_list:
            self.__file_system.create_dir(current_path + "/" + tag)
            self.__file_system.create_link(link_source, current_path + "/" + tag + "/" + link_name)
            recursive_list = [] + tag_list
            recursive_list.remove(tag)
            self.__build_store_navigation(link_name, recursive_list, current_path + "/" + tag)
    
    def rename_tag(self, old_tag_name, new_tag_name):
        """
        renames a tag inside the store 
        """
        self.__create_inprogress_file()
        ##get all affected files per tag
        files = self.__tag_wrapper.get_files_with_tag(old_tag_name)
        self.delete_tags([old_tag_name])
        for file in files:
            if old_tag_name in file["tags"]:
                file["tags"].append(new_tag_name)
                file["tags"].remove(old_tag_name)
            if old_tag_name in file["category"]:
                file["category"].append(new_tag_name)
                file["category"].remove(old_tag_name)
            self.add_item_with_tags(file["filename"], file["tags"], file["category"]) 
        self.__remove_inprogress_file()
    
    def item_exists(self, item_name):
        """
        returns True or False if the item is entered in the store.tgs
        """
        return self.__tag_wrapper.file_exists(item_name)
    
    def delete_tags(self, tag_list):
        """
        delete tags inside the store
        """
        self.__create_inprogress_file()
        for tag_name in tag_list:
            ##get all affected files per tag
            files = self.__tag_wrapper.get_files_with_tag(tag_name)
            for file in files:
                for path in self.__paths_to_maintain:
                    if path == self.__describing_nav_path:
                        self.__delete_tag_folders(tag_name, file["tags"], self.__describing_nav_path)
                    if path == self.__categorising_nav_path:
                        self.__delete_tag_folders(tag_name, file["category"], self.__categorising_nav_path)
                    if path == self.__navigation_path:
                        self.__delete_tag_folders(tag_name, file["tags"], self.__navigation_path)
            ##remove tag from config file
            self.__tag_wrapper.remove_tag(tag_name)
        self.__remove_inprogress_file()
        
    def __delete_tag_folders(self, affected_tag, tag_list, current_path):
        """
        recursive function to delete the tag directories within the describing_nav structure
        """
        if affected_tag not in tag_list:
            return
        self.__file_system.delete_dir(current_path + "/" + affected_tag)
        diff_list = [] + tag_list
        diff_list.remove(affected_tag)
        for tag in diff_list:
            recursive_list = [] + tag_list
            recursive_list.remove(tag)
            self.__delete_tag_folders(affected_tag, recursive_list, current_path + "/" + tag)
        
    def get_controlled_vocabulary(self):
        """
        returns a predefined list of allowed strings (controlled vocabulary) to be used for categorizing
        """
        return self.__vocabulary_wrapper.get_vocabulary()
    
    def set_controlled_vocabulary(self, vocabulary_set):
        self.__vocabulary_wrapper.set_vocabulary(vocabulary_set)

    def get_storage_directory(self):
        """
        returns the path of the storage directory where the items are stored
        """        
        return self.__watcher_path
    
    def get_android_root_directory(self):
        """
        returns the root directory of the android removable storage drive
        """
        res = self.__path[:self.__path.find("/tagstore")] ###FIXME hardcoded constant
        return res
    
    def __is_android_store(self):
        """
        returns True if the store is an android store
        """
        
        # get 'android_store' store setting
        result = self.__store_config_wrapper.get_android_store()
        
        # is this setting active
        if result is None or result =="":
            return False
        
        if int(result) == 0:
            return False
        else:
            return True
        
    def is_android_store(self):
        return self.__is_android_store()
        
    def set_sync_tags(self, file_name, describing_tags, categorising_tags):
        """
        updates the sync tags
        """
        
        # is the and sync tag wrapper initialized
        if self.__sync_tag_wrapper != None:
            self.__sync_tag_wrapper.set_file(file_name, describing_tags, categorising_tags)

    
    def is_sync_active(self):
        """
        returns True when the sync is active
        """
        return self.__is_sync_active()
    
    def create_sync_lock_file(self):
        """
        creates the sync lock file
        """
        
        if self.__is_sync_active():
            # sync is already active
            return False
        
        # get sync lock file
        path = self.__get_lockfile_path()
        
        # get current pid
        pid = PidHelper.get_current_pid()
        
        # write new pid file
        pid_file = open(path, "w")
        pid_file.write(str(pid))
        pid_file.close()
        
        # done
        return True
    
    def remove_sync_lock_file(self):
        """
        removes the sync lock file
        """
        
        # sync lockfile
        path = self.__get_lockfile_path()
        
        # remove lock file
        self.__file_system.remove_file(path)

    def finish_sync(self):
        """
        writes all changes to the config file / sync file
        """
        
        if self.__tag_wrapper != None:
            self.__tag_wrapper.sync_settings()
        
        if self.__sync_tag_wrapper != None:
            self.__sync_tag_wrapper.sync_settings()


    def get_tag_recommendation(self, number, file_name):
        """
        Changes from Georg
        returns the recommendation
        """
        dictionary = self.__recommender.get_tag_recommendation(
                              self.__tag_wrapper,
                              file_name,
                              number,
                              self.__storage_dir_name)
        
        
        list_with_high_prio = []
        
        threshold = 0.9
        if len(dictionary) <= number:
            threshold = 0.5
        
        for tag_name, rating in dictionary.iteritems():
            if rating > threshold:
                list_with_high_prio.append(tag_name)
    
        
        
        list1 = sorted(dictionary.iteritems(), key=lambda (k,v): (v,k), reverse=True)
        return_list = []
        #for item in list[:number]:
        for item in list1[:15]:
            if item[0] in list_with_high_prio:
                return_list.append(item[0])  
        return return_list

        #list = sorted(dictionary.iteritems(), key=lambda (k,v): (v,k), reverse=True)
        #return_list = []
        #print list
        #for item in list[:number]:
        #for item in list:
        #    return_list.append(item[0])
        #print return_list
        #return return_list

        
    def get_cat_recommendation(self, number, file_name):
        """
        Changes from Georg
        returns the recommendation
        """
        allowed_dict = {}
        if self.is_controlled_vocabulary():
                allowed_dict = self.get_controlled_vocabulary()
        
        dictionary = self.__recommender.get_cat_recommendation(
                              self.__tag_wrapper,
                              file_name,
                              number,
                              self.__storage_dir_name,
                              allowed_dict)
        

        list_with_high_prio = []
        
        threshold = 0.9
        if len(dictionary) <= number:
            threshold = 0.5
        
        for tag_name, rating in dictionary.iteritems():
            if rating > threshold:
                list_with_high_prio.append(tag_name)
    
        
        
        list1 = sorted(dictionary.iteritems(), key=lambda (k,v): (v,k), reverse=True)
        return_list = []
        #for item in list[:number]:
        for item in list1[:15]:
            if item[0] in list_with_high_prio:
                return_list.append(item[0])  
        
        return return_list
        '''
        if len(dictionary) > number/2:
            for item in list:
                if dictionary[item] < 0.6:
                    return_list.append(item[0])
            print "if"
            print return_list
            
        else:
            for item in list:
                return_list.append(item[0])
            print return_list
        return return_list
        '''
        
        
    def get_tag_cloud(self, name):
        dict = self.__tag_wrapper.get_tag_dict(self.__tag_wrapper.KEY_TAGS)
        if len(dict) < 10:
            extension = self.__recommender.get_file_extension(name)
            self.__recommender.recommend_new_tags(dict, extension)
        return self.__tagcloud.create_tag_cloud(dict)
    
    def get_cat_cloud(self, name):
        tmp_dict = self.__tag_wrapper.get_tag_dict(self.__tag_wrapper.KEY_CATEGORIES)
        
        if len(tmp_dict) < 10:
            extension = self.__recommender.get_file_extension(name)
            self.__recommender.recommend_new_tags(tmp_dict, extension)
        
        
        dict = {}
        if self.is_controlled_vocabulary():
            allowed_list = self.get_controlled_vocabulary()
            for cat, size in tmp_dict.iteritems():
                if cat in allowed_list:
                    dict.setdefault(cat, size)
            for cat in allowed_list:
                if cat not in dict:
                    dict.setdefault(cat, 0)
            return self.__tagcloud.create_tag_cloud(dict)
        else:
            return self.__tagcloud.create_tag_cloud(tmp_dict)
    
    def get_tagline_config(self):
        return self.__tagline_config