コード例 #1
0
def get_thumbnail(item, path_only=False):

    is_db_item = True

    if type(item) is int:  # item is db id
        connection = database.get_current_gallery("connection").cursor()
        connection.execute(("SELECT file_name, uuid " "FROM file " "WHERE file.pk_id=:id "), {"id": item})
        row = connection.fetchone()
        if row is None:
            raise ValueError("Item not found in database", item)

        path = os.path.join(database.get_current_gallery("directory"), "files", row[1])
    elif type(item) is unicode:  # item is fs path
        path = item
        is_db_item = False
    else:
        raise TypeError("Unknown item type", item)

    # FIXME mimetypes uses file extension, switch to libmagic
    if is_db_item:
        file_type, file_encoding = mimetypes.guess_type(row[0])
    else:
        file_type, file_encoding = mimetypes.guess_type(os.path.basename(item))

    if file_type not in _map:
        # no icon specified
        return DEFAULT_ICON

    handler = _map[file_type]

    if type(handler) is str:
        return handler
    elif isinstance(handler, types.FunctionType):

        if is_db_item:
            thumbnail_path = os.path.join(database.get_current_gallery("directory"), "thumbnails", row[1])
            if not os.path.isfile(thumbnail_path):
                try:
                    handler(path, thumbnail_path)
                except:
                    return DEFAULT_ICON
            if not path_only:
                return thumbnail_path
            else:
                return None
        else:
            # Generate unique name
            md5 = hashlib.md5()
            md5.update(item.encode("utf-8"))
            thumbnail_name = md5.hexdigest()

            thumbnail_path = os.path.join(
                database.get_current_gallery("directory"), "thumbnails", "temp", thumbnail_name
            )
            handler(path, thumbnail_path)
            return thumbnail_path
コード例 #2
0
ファイル: output.py プロジェクト: h0r57/OctoTagger
def change_expression(id, new_expression):
    connection = database.get_current_gallery("connection")
    c = connection.cursor()

    # get folder
    c.execute(
        (
            "SELECT location, name, use_softlink "
            "FROM folder "
            "WHERE pk_id = ?"
        ),
        (id,)
    )
    output = c.fetchone()
    if output is None:
        raise ValueError("Invalid folder id", id)

    # parse expression
    where = expression.parse(new_expression)

    # remake folder
    folder = os.path.join(output[0], output[1])
    if os.path.isdir(folder):
        shutil.rmtree(folder)
    os.makedirs(folder)

    # relink files
    c.execute(
        (
            "SELECT uuid, file_name "
            "FROM file "
            "WHERE {}"
        ).format(where)
    )
    files = c.fetchall()
    if files is not None:
        gallery = database.get_current_gallery("directory")
        for file in files:
            source = os.path.join(gallery, "files", file[0])
            target = os.path.join(folder, file[1])
            create_folders.symlink(source, target, output[2])

    # update db
    c.execute(
        (
            "UPDATE folder "
            "SET expression = ? "
            "WHERE pk_id = ?"
        ),
        (new_expression, id),
    )
    connection.commit()
コード例 #3
0
ファイル: output.py プロジェクト: h0r57/OctoTagger
def delete_gallery(id):
    connection = database.get_current_gallery("connection")
    c = connection.cursor()

    # get folder information
    c.execute(
        "SELECT location, name FROM gallery_folder WHERE pk_id = ?",
        (id,),
    )
    folder = c.fetchone()
    if folder is None:
        raise ValueError("Invalid gallery folder id", id)

    # delete folder
    folder = os.path.join(folder[0], folder[1])
    if os.path.isdir(folder):
        shutil.rmtree(folder)

    # remove from database
    c.execute(
        ("DELETE FROM gallery_folder_has_tag "
         "WHERE pk_fk_gallery_folder_id = ?"),
        (id,)
    )
    c.execute(
        "DELETE FROM gallery_folder WHERE pk_id = ?",
        (id,)
    )
    connection.commit()
コード例 #4
0
    def InitData(self):

        # Get and set values
        # Location, name, automatic, symlink
        gallery = database.get_current_gallery("connection")
        c = gallery.cursor()
        query_location = ("SELECT location, name, add_new_tag, use_softlink "
                          "FROM gallery_folder "
                          "WHERE pk_id = %d" % self.folder_id)
        c.execute(query_location)
        result = c.fetchone()
        self.name = result[1]
        self.location = result[0]

        self.tc_directory.SetValue(result[0])
        self.tc_name.SetValue(result[1])
        self.cb_automatic.SetValue(result[2] == 1)

        softlink = (result[3] == 1)
        self.rb_softlinks.SetValue(softlink)
        self.rb_hardlinks.SetValue(not softlink)

        # Tags
        query_tags = ("SELECT pk_fk_tag_id FROM gallery_folder_has_tag "
                      "WHERE pk_fk_gallery_folder_id = %d" % self.folder_id)
        c.execute(query_tags)
        tag_ids = c.fetchall()
        tag_names = []
        for tag_id in tag_ids:
            tag_names.append(tagging.tag_id_to_name(tag_id).replace("_", " "))

        self.lb.SetCheckedStrings(tag_names)
        self.checked_tags = tag_names
コード例 #5
0
ファイル: output.py プロジェクト: h0r57/OctoTagger
def create_gallery(id):
    connection = database.get_current_gallery("connection")
    c = connection.cursor()

    # get folder information
    c.execute(
        "SELECT location, name FROM gallery_folder WHERE pk_id = ?",
        (id,),
    )
    folder = c.fetchone()
    if folder is None:
        raise ValueError("Invalid gallery folder id", id)

    # create folder
    folder = os.path.join(folder[0], folder[1])
    if not os.path.isdir(folder):
        os.makedirs(folder)

    # get tags
    c.execute(
        ("SELECT pk_fk_tag_id FROM gallery_folder_has_tag "
         "WHERE pk_fk_gallery_folder_id = ?"),
        (id,)
    )
    tags = c.fetchall()

    for tag in tags:
        change_gallery(id, tag[0], True)
コード例 #6
0
ファイル: create_folders.py プロジェクト: h0r57/OctoTagger
def create_folders():

    # Get gallery connection
    gallery_conn = database.get_current_gallery("connection")
    cursor = gallery_conn.cursor()

    # Get output folders
    query_folders = ("SELECT name, location, "
                     "expression, use_softlink FROM folder")
    cursor.execute(query_folders)
    folders = cursor.fetchall()

    for folder in folders:
        name = folder[0]
        location = folder[1]
        folder_expression = folder[2]
        dest = os.path.join(location, name)

        if folder[3] == 1:
            use_softlink = True
        else:
            use_softlink = False

        if not os.path.exists(dest):
            os.makedirs(dest)

        # Get files
        query_files = ("SELECT file_name, uuid FROM file WHERE %s" %
                       (expression.parse(folder_expression)))

        cursor.execute(query_files)
        files = cursor.fetchall()
        for file in files:
            name = file[0]
            uuid = file[1]

            destination = os.path.join(dest, name)

            if not os.path.exists(destination):

                source = os.path.join(
                    os.path.join(database.get_current_gallery("directory"),
                                 "files"), uuid)

                symlink(source, destination, use_softlink)
コード例 #7
0
ファイル: output.py プロジェクト: h0r57/OctoTagger
def remove(item):
    connection = database.get_current_gallery("connection")
    c = connection.cursor()

    c.execute(
        "SELECT file_name FROM file WHERE pk_id=:file",
        {
            "file": item
        }
    )
    filename = c.fetchone()
    if filename is None:
        raise ValueError("No file with this id", item)

    c.execute(
        (
            "SELECT location, name FROM gallery_folder AS g "
            "LEFT JOIN gallery_folder_has_tag AS gt "
            "ON g.pk_id = gt.pk_fk_gallery_folder_id "
            "LEFT JOIN file_has_tag AS ft "
            "ON gt.pk_fk_tag_id = ft.pk_fk_tag_id "
            "WHERE ft.pk_fk_file_id=:file "
            "GROUP BY g.pk_id"
        ),
        {
            "file": item
        }
    )
    folders = c.fetchall()
    for folder in c.execute("SELECT location, name, expression FROM folder"):
        c.execute(
            (
                "SELECT pk_id FROM file "
                "WHERE :expression AND pk_id=:file"
            ),
            {
                "expression": expression.parse(folder[2]),
                "file": item
            }
        )
        if c.fetchone() is None:
            continue

        folders.append(folder[0:2])

    # Get tag name
    tags = tagging.get_tag_names(item)
    for folder in folders:
        for tag in tags:
            path = os.path.join(
                folder[0],
                folder[1],
                tag.replace("_", " "),
                filename[0]
            )
            if os.path.exists(path):
                os.remove(path)
コード例 #8
0
def output(id, advanced, tag=None, convert=False, path=None):
    connection = database.get_current_gallery("connection")
    c = connection.cursor()

    # get folder information
    if advanced:
        c.execute("SELECT location, name FROM folder WHERE pk_id=?", (id, ))
        folder = c.fetchone()
        if folder is None:
            raise ValueError("No advanced output folder with this id", id)
    else:
        if convert:
            raise ValueError("Gallery output folders cannot be converted")
        if tag is None:
            raise ValueError("Gallery folder exports require a tag")

        c.execute("SELECT name FROM tag WHERE pk_id=?", (tag, ))
        tag_name = c.fetchone()
        if tag_name is None:
            raise ValueError("Invalid tag id", tag)
        tag_name = tag_name[0]

        c.execute("SELECT location, name FROM gallery_folder WHERE pk_id=?",
                  (id, ))
        folder = c.fetchone()
        if folder is None:
            raise ValueError("No advanced output folder with this id", id)

    # set copy source and destination
    source = os.path.join(folder[0], folder[1])
    if not advanced:
        source = os.path.join(source, tag_name)

    if convert:
        dest = source
    elif not advanced:
        dest = os.path.join(path, tag_name)
    else:
        dest = os.path.join(path, folder[1])
    os.makedirs(dest)

    # copy files
    files = os.listdir(source)
    for file in files:
        shutil.copy(os.path.join(source, file), dest)

    if convert:
        # delete folder from db
        if advanced:
            query = "DELETE FROM folder WHERE pk_id=?"
        else:
            query = "DELETE FROM gallery_folder WHERE pk_id=?"

        c.execute(query, id)
        connection.commit()
コード例 #9
0
ファイル: import_files.py プロジェクト: h0r57/OctoTagger
def rename_file(id, new_name):

    # Update database
    gallery_conn = database.get_current_gallery("connection")
    cursor = gallery_conn.cursor()
    cursor.execute("SELECT uuid FROM file WHERE pk_id = %d" % (id))
    old_uuid = cursor.fetchone()[0]
    new_uuid = ".".join([old_uuid.split(".")[0], new_name.split(".")[-1]])

    cursor.execute((
        "UPDATE file SET uuid = \'%s\'"
        "WHERE pk_id = %d"
        ) % (new_uuid, id)
    )
    gallery_conn.commit()

    # Rename file
    file_path = os.path.join(
        database.get_current_gallery("directory"), "files")
    old_file = os.path.join(file_path, old_uuid)
    new_file = os.path.join(file_path, new_uuid)
    shutil.move(old_file, new_file)
コード例 #10
0
ファイル: tagging.py プロジェクト: h0r57/OctoTagger
def tag_name_to_id(tag_name):
    # Get gallery connection
    gallery = database.get_current_gallery("connection")
    cursor = gallery.cursor()

    query_get_tags = "SELECT pk_id FROM tag WHERE name = \'%s\'" % (tag_name)
    cursor.execute(query_get_tags)
    tags = cursor.fetchall()
    gallery.commit()
    if tags:
        for tag in tags:
            return tag[0]
    else:
        return "?"
コード例 #11
0
ファイル: output.py プロジェクト: h0r57/OctoTagger
def rename_tag(id, new_name):
    connection = database.get_current_gallery("connection")
    c = connection.cursor()

    # get old name
    c.execute("SELECT name FROM tag WHERE pk_id = ?", (id,))
    old_name = c.fetchone()
    if old_name is None:
        raise ValueError("Unknown tag id", id)
    old_name = old_name[0]

    if old_name == new_name:
        return

    # check if new names is taken
    c.execute("SELECT pk_id FROM tag WHERE name = ?", (new_name,))
    test = c.fetchone()
    if test is not None:
        raise ValueError("New tag name is already in use")

    # get all gallery folders with this tag
    c.execute(
        (
            "SELECT location, name "
            "FROM gallery_folder "
            "JOIN gallery_folder_has_tag "
            "WHERE pk_fk_tag_id = ?"
        ),
        (id,),
    )
    outputs = c.fetchall()

    # rename folders
    if outputs is not None:
        for output in outputs:
            folder = os.path.join(output[0], output[1])
            if os.path.isdir(os.path.join(folder, old_name.replace("_", " "))):
                shutil.move(
                    os.path.join(folder, old_name.replace("_", " ")),
                    os.path.join(folder, new_name.replace("_", " ")),
                )
            else:
                os.makedirs(os.path.join(folder, new_name.replace("_", " ")))

    # update db
    c.execute(
        "UPDATE tag SET name = ? WHERE pk_id = ?",
        (new_name, id),
    )
    connection.commit()
コード例 #12
0
ファイル: tagging.py プロジェクト: h0r57/OctoTagger
def get_all_tags():
    # Get gallery connection
    gallery = database.get_current_gallery("connection")
    cursor = gallery.cursor()

    tag_names = []
    query_get_tags = "SELECT name FROM tag"
    cursor.execute(query_get_tags)
    tags = cursor.fetchall()
    for tag in tags:
        tag_names.append(tag[0])

    gallery.commit()
    return tag_names
コード例 #13
0
ファイル: tagging.py プロジェクト: h0r57/OctoTagger
def tag_id_to_name(tag_id):
    # Get gallery connection
    gallery = database.get_current_gallery("connection")
    cursor = gallery.cursor()

    query_get_tags = "SELECT name FROM tag WHERE pk_id = %d" % (tag_id)
    cursor.execute(query_get_tags)
    tags = cursor.fetchall()
    gallery.commit()
    if tags:
        for tag in tags:
            return tag[0]
    else:
        return "?"
コード例 #14
0
def file(ids, path, move=False):
    gallery = database.get_current_gallery("directory")
    connection = database.get_current_gallery("connection")
    c = connection.cursor()

    # Convert IDs to String
    str_ids = []
    for id in ids:
        str_ids.append(str(id))

    query = ("SELECT uuid, file_name, pk_id FROM file WHERE pk_id IN (" +
             ", ".join(str_ids) + ")")
    print query
    c.execute(query)
    files = c.fetchall()

    for file in files:
        intern = os.path.join(gallery, "files", file[0])
        extern = os.path.join(path, file[1])
        shutil.copy(intern, extern)
        if move:
            tagging.remove_file(int(file[2]))
            os.remove(intern)
コード例 #15
0
    def init_data(self):

        # Define variables
        name = expr = location = ""
        softlink = True

        # Get connection
        gallery_conn = database.get_current_gallery("connection")
        cursor = gallery_conn.cursor()

        # Get data
        query_folder = (
            "SELECT name, expression, location, use_softlink "
            "FROM folder WHERE pk_id = %d" % (self.folder_id)
        )
        cursor.execute(query_folder)
        result = cursor.fetchall()
        for properties in result:
            name = properties[0]
            expr = expression.map_tag_id(
                properties[1],
                tagging.tag_id_to_name
            )
            location = os.path.normpath(properties[2])
            if properties[3] == 1:
                softlink = True
            else:
                softlink = False

        # Set data in UI
        self.tc_name.SetValue(name)
        self.tc_expression.SetValue(expr)
        self.tc_directory.SetValue(location)

        if "?" in expr:
            wx.MessageBox(
                ("Your expression contains "
                 "tags that have been deleted, marked as question marks.\n"
                 "Please update it accordingly, "
                 "or the folder contents will not update."),
                "Warning",
            )

        if softlink:
            self.rb_softlinks.SetValue(True)
            self.rb_hardlinks.SetValue(False)
        else:
            self.rb_softlinks.SetValue(False)
            self.rb_hardlinks.SetValue(True)
コード例 #16
0
ファイル: tagging.py プロジェクト: h0r57/OctoTagger
def get_tags(file_id):
    # Get gallery connection
    gallery = database.get_current_gallery("connection")
    cursor = gallery.cursor()

    tags = []
    query_get_tags = "SELECT pk_fk_tag_id FROM file_has_tag WHERE pk_fk_file_id = %d" % (
        file_id)
    cursor.execute(query_get_tags)
    result = cursor.fetchall()
    for tag in result:
        tags.append(tag[0])

    gallery.commit()
    return tags
コード例 #17
0
ファイル: tagging.py プロジェクト: h0r57/OctoTagger
def delete_tag(id):
    gallery = database.get_current_gallery("connection")
    cursor = gallery.cursor()

    cursor.execute(
        "DELETE FROM gallery_folder_has_tag WHERE pk_fk_tag_id = ?",
        (id,),
    )
    cursor.execute(
        "DELETE FROM file_has_tag WHERE pk_fk_tag_id = ?",
        (id,),
    )
    cursor.execute("DELETE FROM tag WHERE pk_id = ?", (id,))

    gallery.commit()
コード例 #18
0
    def get_file(self, index):
        if self.file_buffer[index] is not None:
            return self.file_buffer[index]

        connection = database.get_current_gallery("connection")
        c = connection.cursor()
        c.execute(
            "SELECT uuid, file_name FROM file WHERE pk_id = ?",
            (self.files[index],),
        )

        result = c.fetchone()
        path = os.path.join(
            database.get_current_gallery("directory"),
            "files",
            result[0],
        )

        thumb_path = thumbnail.get_thumbnail(self.files[index], path_only=True)
        if thumb_path is not None:
            path = thumb_path

        self.file_buffer[index] = (result[1], path)
        return self.file_buffer[index]
コード例 #19
0
ファイル: tagging.py プロジェクト: h0r57/OctoTagger
def gallery_path_to_id(path):
    # Get gallery connection
    gallery = database.get_current_gallery("connection")
    cursor = gallery.cursor()

    location, name = os.path.split(path)

    query_get_folders = (
        "SELECT pk_id FROM gallery_folder "
        "WHERE location = \'%s\' AND name = \'%s\'" % (location, name))
    cursor.execute(query_get_folders)
    folder = cursor.fetchone()
    if folder:
        return folder[0]
    else:
        return False
コード例 #20
0
    def init_data(self):

        # Define variables
        name = expr = location = ""
        softlink = True

        # Get connection
        gallery_conn = database.get_current_gallery("connection")
        cursor = gallery_conn.cursor()

        # Get data
        query_folder = ("SELECT name, expression, location, use_softlink "
                        "FROM folder WHERE pk_id = %d" % (self.folder_id))
        cursor.execute(query_folder)
        result = cursor.fetchall()
        for properties in result:
            name = properties[0]
            expr = expression.map_tag_id(properties[1], tagging.tag_id_to_name)
            location = os.path.normpath(properties[2])
            if properties[3] == 1:
                softlink = True
            else:
                softlink = False

        # Set data in UI
        self.tc_name.SetValue(name)
        self.tc_expression.SetValue(expr)
        self.tc_directory.SetValue(location)

        if "?" in expr:
            wx.MessageBox(
                ("Your expression contains "
                 "tags that have been deleted, marked as question marks.\n"
                 "Please update it accordingly, "
                 "or the folder contents will not update."),
                "Warning",
            )

        if softlink:
            self.rb_softlinks.SetValue(True)
            self.rb_hardlinks.SetValue(False)
        else:
            self.rb_softlinks.SetValue(False)
            self.rb_hardlinks.SetValue(True)
コード例 #21
0
ファイル: output.py プロジェクト: h0r57/OctoTagger
def delete_tag(id):
    connection = database.get_current_gallery("connection")
    c = connection.cursor()

    # get tag information
    c.execute("SELECT name FROM tag WHERE pk_id = ?", (id,))
    name = c.fetchone()
    if name is None:
        raise ValueError("Invalid tag id", id)
    name = name[0]

    # get galleries
    c.execute(
        (
            "SELECT pk_id, location, name "
            "FROM gallery_folder "
            "JOIN gallery_folder_has_tag ON pk_id = pk_fk_gallery_folder_id "
            "WHERE pk_fk_tag_id = ?"
        ),
        (id,),
    )
    galleries = c.fetchall()

    # untag galleries
    if galleries is not None:
        for gallery in galleries:
            change_gallery(gallery[0], id, False)

    # get files
    c.execute(
        (
            "SELECT pk_id "
            "FROM file "
            "JOIN file_has_tag ON pk_id = pk_fk_file_id "
            "WHERE pk_fk_tag_id = ?"
        ),
        (id,),
    )
    files = c.fetchall()

    # untag files
    if files is not None:
        for file in files:
            change(file[0], id, False)
コード例 #22
0
ファイル: tagging.py プロジェクト: h0r57/OctoTagger
def untag_file(file_id, tag_name):
    # Get gallery connection
    gallery = database.get_current_gallery("connection")
    cursor = gallery.cursor()

    # Get tag
    query_get_tags = "SELECT pk_id FROM tag WHERE name = \'%s\'" % (tag_name)
    cursor.execute(query_get_tags)
    tags = cursor.fetchall()

    for tag in tags:
        tag_id = tag[0]
        query_untag = (
            "DELETE FROM file_has_tag WHERE pk_fk_file_id = %d "
            "AND pk_fk_tag_id = %d" % (file_id, tag_id))
        cursor.execute(query_untag)

    # Write changes
    gallery.commit()
    output.change(file_id, tag_id, False)
コード例 #23
0
ファイル: tagging.py プロジェクト: h0r57/OctoTagger
def tag_file(file_id, tag_name, amount=-1):
    # Get gallery connection
    gallery = database.get_current_gallery("connection")
    cursor = gallery.cursor()

    # Get tag or create it
    if amount > -1:
        tag_id = create_tag(tag_name, True)
    elif amount == -1:
        tag_id = create_tag(tag_name)

    query_link = (
        "INSERT INTO file_has_tag(pk_fk_file_id, pk_fk_tag_id, amount) "
        "VALUES (%d, %d, %d)" %
        (file_id, tag_id, amount)
    )
    cursor.execute(query_link)

    # Write changes
    gallery.commit()
    output.change(file_id, tag_id, True)
コード例 #24
0
ファイル: tagging.py プロジェクト: h0r57/OctoTagger
def remove_file(file_id):
    gallery = database.get_current_gallery("connection")
    c = gallery.cursor()

    c.execute(
        (
            "SELECT pk_id FROM tag "
            "JOIN file_has_tag ON pk_id=pk_fk_tag_id "
            "WHERE pk_fk_file_id=:file"
        ),
        {
            "file": file_id
        }
    )
    tags = c.fetchall()
    for tag in tags:
        output.change(file_id, tag[0], False)

    c.execute("DELETE FROM file WHERE pk_id=%s" % str(file_id))
    c.execute("DELETE FROM file_has_tag WHERE pk_fk_file_id=%s" % str(file_id))
    gallery.commit()
コード例 #25
0
ファイル: output.py プロジェクト: h0r57/OctoTagger
def move(id, advanced, target):
    connection = database.get_current_gallery("connection")
    c = connection.cursor()

    # get folder information
    if advanced:
        query_select = "SELECT location, name FROM folder WHERE pk_id = ?"
    else:
        query_select = (
            "SELECT location, name FROM gallery_folder WHERE pk_id = ?"
        )
    c.execute(query_select, (id,))
    folder = c.fetchone()
    if folder is None:
        raise ValueError("No output folder with this id", id)
    (source, name) = folder

    # verify
    if source == target:
        # Source and target are the same
        return
    if os.path.exists(os.path.join(target, name)):
        # TODO: handle this better
        # Target path already exists
        return

    # move
    if os.path.isdir(os.path.join(source, name)):
        shutil.move(
            os.path.join(source, name),
            os.path.join(target, name),
        )

    # update db
    if advanced:
        query_update = "UPDATE folder SET location = ? WHERE pk_id = ?"
    else:
        query_update = "UPDATE gallery_folder SET location = ? WHERE pk_id = ?"
    c.execute(query_update, (target, id))
    connection.commit()
コード例 #26
0
    def InitData(self):

        # Get and set values
        # Location, name, automatic, symlink
        gallery = database.get_current_gallery("connection")
        c = gallery.cursor()
        query_location = (
            "SELECT location, name, add_new_tag, use_softlink "
            "FROM gallery_folder "
            "WHERE pk_id = %d" % self.folder_id
        )
        c.execute(query_location)
        result = c.fetchone()
        self.name = result[1]
        self.location = result[0]

        self.tc_directory.SetValue(result[0])
        self.tc_name.SetValue(result[1])
        self.cb_automatic.SetValue(result[2] == 1)

        softlink = (result[3] == 1)
        self.rb_softlinks.SetValue(softlink)
        self.rb_hardlinks.SetValue(not softlink)

        # Tags
        query_tags = (
            "SELECT pk_fk_tag_id FROM gallery_folder_has_tag "
            "WHERE pk_fk_gallery_folder_id = %d"
            % self.folder_id
        )
        c.execute(query_tags)
        tag_ids = c.fetchall()
        tag_names = []
        for tag_id in tag_ids:
            tag_names.append(tagging.tag_id_to_name(tag_id).replace("_", " "))

        self.lb.SetCheckedStrings(tag_names)
        self.checked_tags = tag_names
コード例 #27
0
ファイル: output.py プロジェクト: h0r57/OctoTagger
def rename(id, advanced, new):
    connection = database.get_current_gallery("connection")
    c = connection.cursor()

    # get folder information
    if advanced:
        query = "SELECT location, name FROM folder WHERE pk_id = ?"
    else:
        query = "SELECT location, name FROM gallery_folder WHERE pk_id = ?"
    c.execute(query, (id,))
    folder = c.fetchone()
    if folder is None:
        raise ValueError("No output folder with this id", id)
    (location, old) = folder

    # verify
    if old == new:
        # New name must be different
        return
    if os.path.exists(os.path.join(location, new)):
        # TODO: Handle this better
        # New name already exists
        return

    # move
    if os.path.isdir(os.path.join(location, old)):
        shutil.move(
            os.path.join(location, old),
            os.path.join(location, new),
        )

    # update db
    if advanced:
        query = "UPDATE folder SET name = ? WHERE pk_id = ?"
    else:
        query = "UPDATE gallery_folder SET name = ? WHERE pk_id = ?"
    c.execute(query, (new, id))
    connection.commit()
コード例 #28
0
ファイル: tagging.py プロジェクト: h0r57/OctoTagger
def create_tag(tag_name, is_numeric=False):
    # Get gallery connection
    gallery = database.get_current_gallery("connection")
    cursor = gallery.cursor()

    # Try to find existing tag
    query_get_tags = "SELECT pk_id FROM tag WHERE name = \'%s\'" % (tag_name)
    cursor.execute(query_get_tags)
    tag = cursor.fetchone()
    if tag:
        return tag[0]

    else:
        # Tag needs to be created
        query_insert_tag = "INSERT INTO tag(name, is_numeric) VALUES (\'%s\', %d)" % (
            tag_name, is_numeric)
        cursor.execute(query_insert_tag)
        gallery.commit()

    # Get ID of the tag
    query_get_tags = "SELECT pk_id FROM tag WHERE name = \'%s\'" % (tag_name)
    cursor.execute(query_get_tags)
    tag_id = cursor.fetchone()

    cursor.execute("SELECT pk_id, add_new_tag FROM gallery_folder")
    gallery_folders = cursor.fetchall()
    for gallery_folder in gallery_folders:
        print gallery_folder
        if gallery_folder[1] == 1:
            cursor.execute(
                "INSERT INTO gallery_folder_has_tag "
                "VALUES(%d, %d)"
                % (gallery_folder[0], tag_id[0])
            )
    gallery.commit()

    return tag_id[0]
コード例 #29
0
def get_suggestions(selected_files):

    tag_ids = tagging.get_all_tag_ids()
    print("suggestion start")
    recomm_ids = []
    recomms = []
    file_ids = []
    tag_quantities = []
    i = 0
    query_items = "SELECT pk_id FROM file"
    final_ids = []

    cursor = database.get_current_gallery("connection").cursor()
    cursor.execute(query_items)
    result = cursor.fetchall()

    for item in result:
        file_ids.append(item[0])

    for tag_id in tag_ids:
        tag_quantities.append([0, tag_id])

    for tempFile in file_ids:
        counter = 0
        for tag_id in tag_ids:
            if tagging.file_has_tag_id(tempFile, tag_id):
                tag_quantities[counter][0] += 1
            counter += 1

    if len(tag_ids) > 7:
        while i < 7:
            if not tag_quantities:
                break

            length = len(selected_files)
            tagcount = 0
            for selected_file in selected_files:
                if tagging.file_has_tag_id(selected_file,
                                           max(tag_quantities)[1]):
                    tagcount += 1

            if tagcount is length:
                tag_quantities.remove(max(tag_quantities))
                i += 1

            else:
                recomm_ids.append(max(tag_quantities)[1])
                tag_quantities.remove(max(tag_quantities))
                i += 1
        i = 0
    else:
        while i < len(tag_ids):
            if not tag_quantities:
                break

            length = len(selected_files)
            tagcount = 0
            for selected_file in selected_files:
                if tagging.file_has_tag_id(selected_file,
                                           max(tag_quantities)[1]):
                    tagcount += 1

            if tagcount is length:
                tag_quantities.remove(max(tag_quantities))
                i += 1

            else:
                recomm_ids.append(max(tag_quantities)[1])
                tag_quantities.remove(max(tag_quantities))
                i += 1
        i = 0

    tag_corr = []
    corr_recomm_ids = []

    for tag_id in tag_ids:
        tag_corr.append([0, tag_id])

    for tempFile in selected_files:
        counter = 0
        for tag_id in tag_ids:
            if tagging.file_has_tag_id(tempFile, tag_id):
                tag_corr[counter][0] += 1
            counter += 1

    if len(tag_ids) > 7:
        while i < 7:
            if not tag_corr:
                break

            if max(tag_corr)[0] < len(selected_files):
                corr_recomm_ids.append(max(tag_corr)[1])
                tag_corr.remove(max(tag_corr))
                i += 1

            else:
                tag_corr.remove(max(tag_corr))
                i += 1

        i = 0
    else:
        while i < len(tag_ids):
            if not tag_corr:
                break

            if max(tag_corr)[0] < len(selected_files):
                corr_recomm_ids.append(max(tag_corr)[1])
                tag_corr.remove(max(tag_corr))
                i += 1

            else:
                tag_corr.remove(max(tag_corr))
                i += 1

        i = 0

    if not selected_files:
        corr_recomm_ids.append(1)
        recomm_ids.append(1)

    corr = True
    recomm = True

    while True:
        if not recomm_ids and not corr_recomm_ids:
            break

        if len(selected_files) > 1:
            if corr_recomm_ids[i] not in final_ids and corr is True:
                final_ids.append(corr_recomm_ids[i])
                if corr_recomm_ids[i] is corr_recomm_ids[len(corr_recomm_ids) -
                                                         1]:
                    corr = False

        if recomm_ids[i] not in final_ids and recomm is True:
            final_ids.append(recomm_ids[i])
            if corr_recomm_ids[i] is corr_recomm_ids[len(corr_recomm_ids) - 1]:
                recomm = False

        if recomm_ids[i] is recomm_ids[
                len(recomm_ids) - 1] and corr_recomm_ids[i] is corr_recomm_ids[
                    len(corr_recomm_ids) - 1]:
            break

        i += 1
    i = 0

    for tag in final_ids:
        recomms.append(tagging.tag_id_to_name(tag))

    return recomms
コード例 #30
0
def get_suggestions(selected_files):

    tag_ids = tagging.get_all_tag_ids()
    print("suggestion start")
    recomm_ids = []
    recomms = []
    file_ids = []
    tag_quantities = []
    i = 0
    query_items = "SELECT pk_id FROM file"
    final_ids = []

    cursor = database.get_current_gallery("connection").cursor()
    cursor.execute(query_items)
    result = cursor.fetchall()

    for item in result:
        file_ids.append(item[0])

    for tag_id in tag_ids:
        tag_quantities.append([0, tag_id])

    for tempFile in file_ids:
        counter = 0
        for tag_id in tag_ids:
            if tagging.file_has_tag_id(tempFile, tag_id):
                tag_quantities[counter][0] += 1
            counter += 1

    if len(tag_ids) > 7:
        while i < 7:
            if not tag_quantities:
                break

            length = len(selected_files)
            tagcount = 0
            for selected_file in selected_files:
                if tagging.file_has_tag_id(selected_file, max(tag_quantities)[1]):
                    tagcount += 1

            if tagcount is length:
                tag_quantities.remove(max(tag_quantities))
                i += 1

            else:
                recomm_ids.append(max(tag_quantities)[1])
                tag_quantities.remove(max(tag_quantities))
                i += 1
        i = 0
    else:
        while i < len(tag_ids):
            if not tag_quantities:
                break

            length = len(selected_files)
            tagcount = 0
            for selected_file in selected_files:
                if tagging.file_has_tag_id(selected_file, max(tag_quantities)[1]):
                    tagcount += 1

            if tagcount is length:
                tag_quantities.remove(max(tag_quantities))
                i += 1

            else:
                recomm_ids.append(max(tag_quantities)[1])
                tag_quantities.remove(max(tag_quantities))
                i += 1
        i = 0

    tag_corr = []
    corr_recomm_ids = []

    for tag_id in tag_ids:
        tag_corr.append([0, tag_id])

    for tempFile in selected_files:
        counter = 0
        for tag_id in tag_ids:
            if tagging.file_has_tag_id(tempFile, tag_id):
                tag_corr[counter][0] += 1
            counter += 1

    if len(tag_ids) > 7:
        while i < 7:
            if not tag_corr:
                break

            if max(tag_corr)[0] < len(selected_files):
                corr_recomm_ids.append(max(tag_corr)[1])
                tag_corr.remove(max(tag_corr))
                i += 1

            else:
                tag_corr.remove(max(tag_corr))
                i += 1

        i = 0
    else:
        while i < len(tag_ids):
            if not tag_corr:
                break

            if max(tag_corr)[0] < len(selected_files):
                corr_recomm_ids.append(max(tag_corr)[1])
                tag_corr.remove(max(tag_corr))
                i += 1

            else:
                tag_corr.remove(max(tag_corr))
                i += 1

        i = 0

    if not selected_files:
        corr_recomm_ids.append(1)
        recomm_ids.append(1)

    corr = True
    recomm = True

    while True:
        if not recomm_ids and not corr_recomm_ids:
            break

        if len(selected_files) > 1:
            if corr_recomm_ids[i] not in final_ids and corr is True:
                final_ids.append(corr_recomm_ids[i])
                if corr_recomm_ids[i] is corr_recomm_ids[len(corr_recomm_ids)-1]:
                    corr = False

        if recomm_ids[i] not in final_ids and recomm is True:
            final_ids.append(recomm_ids[i])
            if corr_recomm_ids[i] is corr_recomm_ids[len(corr_recomm_ids)-1]:
                recomm = False

        if recomm_ids[i] is recomm_ids[len(recomm_ids)-1] and corr_recomm_ids[i] is corr_recomm_ids[len(corr_recomm_ids)-1]:
            break

        i += 1
    i = 0

    for tag in final_ids:
        recomms.append(tagging.tag_id_to_name(tag))

    return recomms
コード例 #31
0
ファイル: import_files.py プロジェクト: h0r57/OctoTagger
def import_files(files):

    # Get gallery connection
    gallery_conn = database.get_current_gallery("connection")
    cursor = gallery_conn.cursor()
    dest_dir = os.path.join(database.get_current_gallery("directory"), "files")

    # Retrieve import setting
    sys_cursor = database.get_sys_db().cursor()
    sys_cursor.execute(
        "SELECT import_copy FROM settings"
    )
    import_copy = (sys_cursor.fetchone()[0] == 1)

    # Keep track of files with the same name
    same_name_files = []

    # Progress Window
    current_file = 1
    message = "Importing file " + str(current_file) + " of " + str(len(files))
    dlg_progress = wx.ProgressDialog(
        "Importing",
        message,
        maximum=len(files)
    )

    if type(files) is list:

        for file in files:
            file = os.path.normpath(file)

            # Update progress info
            dlg_progress.Update(
                current_file,
                "Importing file " + str(current_file) + " of " + str(len(files)) + "."
            )
            current_file += 1

            # Defensive programming
            if os.path.isfile(file) and os.path.isdir(dest_dir):

                original_name = os.path.basename(file)  # for the database
                new_name = (
                    str(uuid.uuid4()) + "." + original_name.split(".")[-1]
                )

                while os.path.exists(os.path.join(dest_dir, new_name)):
                    new_name = (
                        str(uuid.uuid4()) + "." + original_name.split(".")[-1]
                    )
                dest = os.path.join(dest_dir, new_name)
                if import_copy:
                    shutil.copy(file, dest)
                else:
                    shutil.move(file, dest)

                # Check if name already exists
                cursor.execute(
                    "SELECT file_name FROM file WHERE file_name = ?",
                    (original_name,)
                )
                name = cursor.fetchone()
                if name:
                    same_name_files.append(name[0])

                # Save to database
                cursor.execute(
                    ("INSERT INTO file (file_name, uuid) "
                     "VALUES (\'%s\', \'%s\')") %
                    (original_name, new_name)
                )
                gallery_conn.commit()

            else:
                wx.MessageBox(
                    'An error has occured while importing.',
                    'Error',
                    wx.OK | wx.ICON_EXCLAMATION
                )

    elif type(files) is dict:
        for file, tags in files.iteritems():
            print file
            # Update progress info
            dlg_progress.Update(
                current_file,
                "Importing file " + str(current_file) + 
                " of " + str(len(files)) + "."
            )
            current_file += 1

            file = os.path.normpath(file)

            # Defensive programming
            if not os.path.isfile(file):
                continue

            if not os.path.isdir(dest_dir):
                print "Not a dir:", file, dest_dir

            if os.path.isfile(file) and os.path.isdir(dest_dir):
                original_name = os.path.basename(file)
                new_name = (
                    str(uuid.uuid4()) + "." + original_name.split(".")[-1]
                )

                while os.path.exists(os.path.join(dest_dir, new_name)):
                    new_name = (
                        str(uuid.uuid4()) + "." + original_name.split(".")[-1]
                    )

                dest = os.path.join(dest_dir, new_name)
                if import_copy:
                    shutil.copy(file, dest)
                else:
                    shutil.move(file, dest)

                # Check if name already exists
                cursor.execute(
                    "SELECT file_name FROM file WHERE file_name = ?",
                    (original_name,)
                )
                name = cursor.fetchone()
                if name:
                    same_name_files.append(name[0])

                # Save to database
                query_insert_file = (
                    ("INSERT INTO file (file_name, uuid) "
                     "VALUES (\'%s\', \'%s\')")
                    % (original_name, new_name)
                )

                cursor.execute(query_insert_file)
                gallery_conn.commit()

                # Get ID
                query_file_id = (
                    "SELECT pk_id FROM file WHERE uuid = \'%s\'"
                    % (new_name)
                )
                cursor.execute(query_file_id)
                file_id = cursor.fetchone()[0]

                # Connect with tags
                tag_names = []
                for tag in tags:
                    tag_names.append(tagging.tag_id_to_name(tag))

                for tag_name in tag_names:
                    tagging.tag_file(file_id, tag_name)

            else:
                wx.MessageBox(
                    'An error has occured while importing.',
                    'Error',
                    wx.OK | wx.ICON_EXCLAMATION
                )

    dlg_progress.Destroy()

    # Warn user about same name files
    if len(same_name_files) == 0:
        return

    else:
        wx.MessageBox(
            ("Some of your imported files share the "
             "same name with each other, or with files "
             "that are already imported. \n\n"
             "This can lead to some unexpected behaviour "
             "or inconsistencies. "
             "It is recommended to give each file a unique name. "
             "You can rename a file in OctoTagger "
             "by selecting it and pressing 'F2'.\n\n"
             "Below is the list of file names the occur multiple times:\n\n" +
             "\n".join(same_name_files)),
            "Warning"
        )
コード例 #32
0
    def SaveSettings(self):
        # FIXME: Change name not working (under windows)?

        # Register folders
        # Get gallery connection
        gallery_conn = database.get_current_gallery("connection")
        cursor = gallery_conn.cursor()

        location = self.tc_directory.GetValue()
        name = self.tc_name.GetValue()
        if self.cb_automatic.GetValue():
            add_new_tag = 1
        else:
            add_new_tag = 0

        if self.rb_softlinks.GetValue():
            use_softlink = True
        else:
            use_softlink = False

        if not os.path.isdir(location):
            wx.MessageBox("Location does not exist!", "Error")
            return

        if name == "":
            wx.MessageBox("Must define a name.", "Error")
            return

        output.change_link_type(self.folder_id, False, use_softlink)

        new_checked_tags = self.lb.GetCheckedStrings()
        for tag in new_checked_tags:
            if tag not in self.checked_tags:
                tag_id = tagging.tag_name_to_id(tag.replace(" ", "_"))
                output.change_gallery(self.folder_id, tag_id, True)

        for tag in self.checked_tags:
            if tag not in new_checked_tags:
                tag_id = tagging.tag_name_to_id(tag.replace(" ", "_"))
                output.change_gallery(self.folder_id, tag_id, False)

        if name != self.name or location != self.location:
            if os.path.isdir(os.path.join(location, name)):
                print "koko made NI"
                wx.MessageBox(
                    ("Location or target folder already exists, "
                     "remove it first."),
                    "Error",
                )
                return

        if name != self.name:
            output.rename(self.folder_id, False, name)

        if location != self.location:
            output.move(self.folder_id, False, location)

        query_save = ("UPDATE gallery_folder SET "
                      "add_new_tag = %d "
                      "WHERE pk_id = %d" % (add_new_tag, self.folder_id))
        cursor.execute(query_save)
        gallery_conn.commit()

        self.Close()
コード例 #33
0
    def SaveSettings(self):
        # FIXME: Change name not working (under windows)?

        # Register folders
        # Get gallery connection
        gallery_conn = database.get_current_gallery("connection")
        cursor = gallery_conn.cursor()

        location = self.tc_directory.GetValue()
        name = self.tc_name.GetValue()
        if self.cb_automatic.GetValue():
            add_new_tag = 1
        else:
            add_new_tag = 0

        if self.rb_softlinks.GetValue():
            use_softlink = True
        else:
            use_softlink = False

        if not os.path.isdir(location):
            wx.MessageBox("Location does not exist!", "Error")
            return

        if name == "":
            wx.MessageBox("Must define a name.", "Error")
            return

        output.change_link_type(self.folder_id, False, use_softlink)

        new_checked_tags = self.lb.GetCheckedStrings()
        for tag in new_checked_tags:
            if tag not in self.checked_tags:
                tag_id = tagging.tag_name_to_id(tag.replace(" ", "_"))
                output.change_gallery(self.folder_id, tag_id, True)

        for tag in self.checked_tags:
            if tag not in new_checked_tags:
                tag_id = tagging.tag_name_to_id(tag.replace(" ", "_"))
                output.change_gallery(self.folder_id, tag_id, False)

        if name != self.name or location != self.location:
            if os.path.isdir(os.path.join(location, name)):
                print "koko made NI"
                wx.MessageBox(
                    ("Location or target folder already exists, "
                     "remove it first."),
                    "Error",
                )
                return

        if name != self.name:
            output.rename(self.folder_id, False, name)

        if location != self.location:
            output.move(self.folder_id, False, location)

        query_save = (
            "UPDATE gallery_folder SET "
            "add_new_tag = %d "
            "WHERE pk_id = %d" %
            (add_new_tag, self.folder_id)
        )
        cursor.execute(query_save)
        gallery_conn.commit()

        self.Close()
コード例 #34
0
ファイル: itemview.py プロジェクト: TeamOctoTagger/OctoTagger
    def SetItems(self, items):
        self.Freeze()
        '''
        Sets which items are to be displayed. Pass ids from database as int or
        paths from filesystem as str.
        '''
        connection = database.get_current_gallery('connection').cursor()

        ids = map(unicode, filter(lambda x: type(x) == int, items))
        paths = filter(lambda x: type(x) == unicode, items)
        files = filter(os.path.isfile, paths)
        folders = filter(os.path.isdir, paths)
        gf = filter(
            lambda x: os.path.isdir("|".join(x.split("|")[0:-1])),
            paths,
        )

        connection.execute(
            "SELECT pk_id FROM file WHERE pk_id IN ({}) ORDER BY file_name"
            .format(','.join(ids))
        )
        ids = map(lambda x: x[0], connection.fetchall())

        files.sort(key=os.path.basename)
        folders.sort(key=os.path.basename)
        gf.sort(key=os.path.basename)

        items = gf
        items.extend(folders)
        items.extend(files)
        items.extend(ids)

        def parse_items(items):
            result = []
            for item in items:
                if type(item) is int:  # item is db id
                    connection.execute(
                        (
                            'SELECT file_name '
                            'FROM file '
                            'WHERE file.pk_id=:id '
                        ),
                        {
                            'id': item,
                        }
                    )
                    row = connection.fetchone()
                    if row is None:
                        raise ValueError('Item not found in database', item)

                    result.append({
                        'name': row[0],
                        'path': item,
                    })
                elif type(item) is unicode:  # item is fs path
                    splitted_item = item.split("|")
                    if splitted_item.pop() == "GALLERYFOLDER":
                        is_gf = True
                        item = "|".join(splitted_item)
                    else:
                        is_gf = False

                    name = os.path.basename(item)
                    if os.path.isdir(item):
                        result.append({
                            'name': name,
                            'path': item,
                            'thumb': thumbnail.GENERIC['folder'],
                            'is_gf': is_gf,
                        })
                    elif os.path.isfile(item):
                        result.append({
                            'name': name,
                            'path': item,
                        })
                    else:
                        print ('Encountered unsupported path', item)

                else:
                    raise TypeError('Encountered unsupported item', item)
            return result

        self.items = parse_items(items)
        self.update_items()
        self.Thaw()
コード例 #35
0
    def SaveSettings(self):

        # Register folders
        # Get gallery connection
        gallery_conn = database.get_current_gallery("connection")
        cursor = gallery_conn.cursor()

        location = self.tc_directory.GetValue()
        name = self.tc_name.GetValue()
        if self.cb_automatic.GetValue():
            add_new_tag = 1
        else:
            add_new_tag = 0

        if self.rb_softlinks.GetValue():
            use_softlink = 1
        else:
            use_softlink = 0

        if not os.path.isdir(location):
            wx.MessageBox("Location does not exist!", "Error")
            return

        if name == "":
            wx.MessageBox("Must define a name.", "Error")
            return

        if os.path.isdir(os.path.join(location, name)):
            wx.MessageBox(
                ("Target folder already exists, "
                 "remove it first."),
                "Error",
            )
            return

        checked_tags = self.lb.GetCheckedStrings()
        tags = []
        for tag in checked_tags:
            tags.append(tagging.tag_name_to_id(tag.replace(" ", "_")))

        cursor.execute(
            (
                "INSERT INTO gallery_folder "
                "(name, location, add_new_tag, use_softlink) "
                "VALUES (:name, :location, :add_new_tag, :use_softlink)"
            ),
            {
                "name": name,
                "location": location,
                "add_new_tag": add_new_tag,
                "use_softlink": use_softlink
            }
        )
        gallery_conn.commit()

        cursor.execute(
            (
                "SELECT pk_id FROM gallery_folder "
                "WHERE name = :name "
                "AND location = :location "
            ),
            {
                "name": name,
                "location": location,
            }
        )
        folder_id = cursor.fetchone()[0]

        output.create_gallery(folder_id)
        for tag in tags:
            output.change_gallery(folder_id, tag, True)
コード例 #36
0
    def on_ok(self, e):

        # Check for valid input

        location = self.tc_directory.GetValue()
        dir = os.path.normpath(location)
        name = self.tc_name.GetValue()
        expr = expression.map_tag_name(self.tc_expression.GetValue(), tagging.tag_name_to_id)

        if "?" in expr:
            wx.MessageBox(
                (
                    "One or more of the tags in the specified expression "
                    "does not exist. Please create them first, "
                    "or change the expression."
                ),
                "Error",
            )
            return

        if self.rb_softlinks.GetValue():
            softlink = 1
        else:
            softlink = 0

        if name == "":
            wx.MessageBox("Please enter a name!", "Error", wx.OK | wx.ICON_EXCLAMATION)

            return

        if expr == "":
            wx.MessageBox("Please enter an expression!", "Error", wx.OK | wx.ICON_EXCLAMATION)

            return

        if location == "":
            wx.MessageBox("Please enter a location!", "Error", wx.OK | wx.ICON_EXCLAMATION)

            return

        if not os.path.exists(dir) or not os.path.isdir(dir):
            wx.MessageBox("Invalid location!", "Error", wx.OK | wx.ICON_EXCLAMATION)

            return

        # Create database entry

        gallery_conn = database.get_current_gallery("connection")
        cursor = gallery_conn.cursor()

        query_insert_folder = (
            "INSERT INTO folder"
            "(name, location, expression, use_softlink) "
            "VALUES ('%s', '%s', '%s', %d)" % (name, dir, expr, softlink)
        )

        cursor.execute(query_insert_folder)
        gallery_conn.commit()

        # Create folders
        create_folders.create_folders()
        self.EndModal(0)
コード例 #37
0
ファイル: output.py プロジェクト: h0r57/OctoTagger
def change(item, tag, create):
    connection = database.get_current_gallery("connection")
    c = connection.cursor()

    c.execute(
        (
            "SELECT uuid, file_name "
            "FROM file "
            "WHERE pk_id=:id"
        ),
        {
            "id": item
        }
    )
    # TODO better var name
    g_file = c.fetchone()
    if g_file is None:
        raise ValueError("No file with this id", item)
    target = os.path.join(
        database.get_current_gallery("directory"),
        "files",
        g_file[0]
    )

    # gallery output folders

    c.execute(
        "SELECT pk_id, location, name, use_softlink "
        "FROM gallery_folder"
    )
    folders = c.fetchall()
    for folder in folders:
        c.execute(
            (
                "SELECT name "
                "FROM gallery_folder_has_tag "
                "JOIN tag ON pk_fk_tag_id=pk_id "
                "WHERE pk_fk_gallery_folder_id=:folder AND pk_id=:tag"
            ),
            {
                "folder": folder[0],
                "tag": tag
            }
        )
        tag_name = c.fetchone()
        if tag_name is None:
            # gallery output does not use this tag
            continue
        else:
            tag_name = tag_name[0]

        path = os.path.join(folder[1], folder[2], tag_name.replace("_", " "))
        if not os.path.isdir(path):
            os.makedirs(path)

        link_path = os.path.join(path, g_file[1])

        if create:
            # create
            if os.path.exists(link_path):
                os.remove(link_path)
            create_folders.symlink(target, link_path, folder[3])
        else:
            # delete
            if os.path.lexists(link_path):
                os.remove(link_path)

    # advanced output folders

    c.execute(
        "SELECT location, name, expression, use_softlink "
        "FROM folder"
    )
    folders = c.fetchall()
    for folder in folders:
        path = os.path.join(folder[0], folder[1])
        link = os.path.join(path, g_file[1])
        query_file = (
                "SELECT pk_id "
                "FROM file "
                "WHERE %s AND pk_id = %d"
                % (expression.parse(folder[2]), item)
        )
        c.execute(query_file)
        matches = c.fetchone()
        if matches is None and os.path.exists(link):
            os.remove(link)
        elif matches is not None:
            if os.path.exists(link):
                os.remove(link)
            if not os.path.isdir(path):
                os.makedirs(path)
            create_folders.symlink(target, link, folder[3])