Calibre unexpected dark theme

It can be very annoying an undesired dark theme in Calibre (both viewer and editor): reading could become difficult, or almost impossible.
This happens (probably) if you have a flatpack release of Calibre: try to remove the flatpack one, and install a release of Calibre from their website.

Flatpack is convenient (automatic updates), but have some problems….

Espanso

A very useful feature of espanso (a text expander also for wayland) is the possibility to convert the clipboard content to lowercase (with ::low) or to uppercase (with ::up).

Webtrees problems

Webtrees is a fork of PhpGedView, an excellent genealogy program. It ha a big problem: uploading and setting multimedial files.
It’s often a terrible waste of time: a very complicated way to upload files.

workaround

  • You can try to upload images (if you work in localhost and you know what you are doing) in this way:
  • 1. symlink an image to /media folder in /data webtrees folder.
  • 2. add that image file in phpmyadmin (your webtrees db) “media” and “media_file” tables (you have to set a number, such as X110).
    3. add to “individuals” the id of that file, with a code like “1 OBJE @X110@” at the bottom of the field i_gedcom.
  • 4. Now, in webtrees grafical view you has now to (pretend to) modify (nothing modifying, in fact) and save this modification.
  • 5. You could have also to save the modification date (saving the proposed one).

caveat

  • a. The file symlinked must have rights permissions (owner rw, group and others only r).
  • b. no avif: only jpg or webp are allowed.

You should now see the expected image within the page of that individual

Table relations lost in phpmyadmin

If it happen that relations between tables don’t work anymore, you can try (very carefully, and after complete a backup), if you have a backup of them, to replace the files

ibdata1  e ib_logfile0

after stopping mariadb (or mysql). At your own risk: with no guarantee.

PhpMyAdmin: wildcards as default in search tab

The new PhpMyAdmin, the 5.2.3, unlike the previous, the 5.2.2, has “like” instead of “like %…%” as default search command.

If you prefer the previous default you can do it following these instructions .

I managed to bo back to the previous default modifying only the file
phpMyAdmin/libraries/classes/Types.php
at rows 99 -100

from

return [
'LIKE',
'LIKE %...%',

to
return [
'LIKE %...%',
'LIKE',


Librewriter for a pdf book

1. number pages

You can add number pages at the footer of your pages

  • in format -> page style -> footer -> Footer on
  • and then, in footer area (by clicking at the bottom) insert -> page number (select mirror to get different alignment for even and odd pages

2. titles in header

You can also create header, with, i.g., the book title (on the even pages) and the chapter title (on the odd ones):

  • in format -> page style -> header -> Header on (deselect same content for left and right pages)
  • and, as above for the footer, going in header area, insert, i.g. in a left page the field title, in a right page, insert -> fields -> Document -> (type: heading, format: heading content). Don’t forget to set the “up to level” (typically : 2, if you want tha names of headings of 2° level, as h2 in html), changing it from 1.

3. bibliografy

You can also add bibliography enter (i.g. in footnotes) and get an automatic bibliografi index at the the end of your file (book/article). These are the steps:

  • Set a “bibliografy entry” (or “citation”): insert -> table of content or index – > bibliografy entry (or “citation”) -> source: document content – new
  • there you have to set, if it is a book, at least the author, the title and the year, and a short name (in Italian, a sigla) to recall it afterwards quicky. (if Journal Article → Author, Title, Year, Journal).
  • Then you can create, typically at the end of your document, the bibliography index: insert -> table of content or index – > table of content or index or bibliography -> type: bibliography, and there you can edit the structure of the items (and their formatting)

Split columns in a pdf

It can happen that you have a pdf with two columns in a page

such as in this image pdf 2 colonne

and you want to split them (i.g. because the ocr is not correct, and you have a text as if was an only column).
A website very useful and easy to make this is online2pdf.

esport and show FF bookmarks in a webpage

With the help of IA I managed to get Firefox bookmarks

import os
import json
import sqlite3
import shutil
import tempfile

profile_name = "your-profile"  # <-- cambia con il tuo
profile_path = os.path.expanduser(f"~/.mozilla/firefox/{profile_name}")
db_path = os.path.join(profile_path, "places.sqlite")

if not os.path.isfile(db_path):
    print(f"Il file places.sqlite non esiste: {db_path}")
    exit(1)

# Copia temporanea per evitare blocchi
tmp_dir = tempfile.gettempdir()
temp_db_path = os.path.join(tmp_dir, "places_copy.sqlite")
shutil.copy2(db_path, temp_db_path)

conn = sqlite3.connect(temp_db_path)
conn.row_factory = sqlite3.Row
cursor = conn.cursor()

# Preleva tutte le informazioni rilevanti
query = """
SELECT
    b.id,
    b.title,
    b.parent,
    b.type,
    b.fk,
    b.dateAdded,
    p.url,
    ia.content AS description
FROM moz_bookmarks b
LEFT JOIN moz_places p ON b.fk = p.id
LEFT JOIN moz_items_annos ia ON b.id = ia.item_id
LEFT JOIN moz_anno_attributes a_attr ON ia.anno_attribute_id = a_attr.id
WHERE (b.type = 1 OR b.type = 2)
  AND (a_attr.name IS NULL OR a_attr.name = 'bookmarkProperties/description')
ORDER BY b.parent, b.position
"""

cursor.execute(query)
rows = cursor.fetchall()

# Costruisci dizionario gerarchico
items = {row["id"]: {
    "id": row["id"],
    "title": row["title"] if row["title"] else "(senza titolo)",
    "type": "folder" if row["type"] == 2 else "bookmark",
    "url": row["url"] if row["type"] == 1 else None,
    "description": row["description"],
    "children": []
} for row in rows}

# Organizza gerarchia
root = []
for row in rows:
    item = items[row["id"]]
    parent_id = row["parent"]
    if parent_id in items:
        items[parent_id]["children"].append(item)
    else:
        root.append(item)

# Salva in JSON
with open("bookmarks_full.json", "w", encoding="utf-8") as f:
    json.dump(root, f, ensure_ascii=False, indent=2)

print(f"Esportazione completata: {len(root)} cartelle o elementi di primo livello.")
conn.close()
os.remove(temp_db_path)

also selecting a specific bookmark folder

import os
import sqlite3
import shutil
import tempfile
import sys

profile_name = "your-FF-profile"
folder_name_to_export = "[the folder name]"  # Nome della cartella da esportare
output_path = "bookmarks-FF-[a name].php"

# Percorso del profilo
profile_path = os.path.expanduser(f"~/.mozilla/firefox/{profile_name}")
db_path = os.path.join(profile_path, "places.sqlite")

if not os.path.isfile(db_path):
    print(f"Il file places.sqlite non esiste: {db_path}")
    sys.exit(1)

# Copia temporanea del DB
tmp_dir = tempfile.gettempdir()
temp_db_path = os.path.join(tmp_dir, "places_copy.sqlite")
shutil.copy2(db_path, temp_db_path)

conn = sqlite3.connect(temp_db_path)
conn.row_factory = sqlite3.Row
cursor = conn.cursor()

# 1. Query per cartelle e segnalibri (senza tag)
query = """
SELECT
  b.id,
  b.title,
  b.parent,
  b.type,
  b.fk,
  p.url
FROM moz_bookmarks b
LEFT JOIN moz_places p ON b.fk = p.id
WHERE b.type IN (1, 2)
ORDER BY b.parent, b.position
"""

cursor.execute(query)
rows = cursor.fetchall()

# Costruzione struttura
items = {row["id"]: {
    "id": row["id"],
    "title": row["title"] or "(senza titolo)",
    "type": "folder" if row["type"] == 2 else "bookmark",
    "url": row["url"] if row["type"] == 1 else None,
    "description": None,
    "children": []
} for row in rows}

# Costruzione gerarchia
for row in rows:
    item = items[row["id"]]
    parent_id = row["parent"]
    if parent_id in items:
        items[parent_id]["children"].append(item)

# 2. Query per associare tag reali ai segnalibri
tag_query = """
SELECT
  b.id AS bookmark_id,
  GROUP_CONCAT(tg.title, ', ') AS tags
FROM moz_bookmarks b
LEFT JOIN moz_bookmarks bt ON bt.fk = b.fk
LEFT JOIN moz_bookmarks tg ON tg.id = bt.parent AND tg.parent = -3
WHERE b.type = 1
GROUP BY b.id
"""

cursor.execute(tag_query)
tag_rows = cursor.fetchall()

# Assegna i tag ai segnalibri nella struttura
for row in tag_rows:
    bookmark_id = row["bookmark_id"]
    tags = row["tags"]
    if bookmark_id in items:
        items[bookmark_id]["description"] = tags if tags else "(senza tag)"

# Cerca la cartella da esportare
matching_folders = [item for item in items.values()
                    if item["type"] == "folder" and item["title"] == folder_name_to_export]

if not matching_folders:
    print(f"Nessuna cartella trovata con nome '{folder_name_to_export}'.")
    conn.close()
    os.remove(temp_db_path)
    sys.exit(1)

# Funzione per scrivere array PHP
def to_php_array(item, indent=2):
    space = ' ' * indent
    lines = [f"{space}["]
    lines.append(f"{space}  'title' => '{item['title'].replace('\'', '\\\'')}',")
    if item.get("url"):
        lines.append(f"{space}  'url' => '{item['url'].replace('\'', '\\\'')}',")
    if item.get("description"):
        lines.append(f"{space}  'description' => '{item['description'].replace('\'', '\\\'')}',")
    if item.get("children"):
        lines.append(f"{space}  'children' => [")
        for child in item["children"]:
            lines.append(to_php_array(child, indent + 4) + ",")
        lines.append(f"{space}  ],")
    lines.append(f"{space}]")
    return "\n".join(lines)

# Scrittura file PHP
with open(output_path, "w", encoding="utf-8") as f:
    f.write("<?php\nreturn [\n")
    for folder in matching_folders:
        f.write(to_php_array(folder, indent=2))
        f.write(",\n")
    f.write("];\n")

print(f"Esportazione completata in {output_path}")

conn.close()
os.remove(temp_db_path)

and output them in a php webpage

<?php
$segnalibri = include 'bookmarks-FF-[a name].php';

function stampaSegnalibri($items) {
    foreach ($items as $item) {
        echo "<div style='margin-bottom:8px'>";

        if (isset($item['url'])) {
            // titolo come link
            $title_html = htmlspecialchars($item['title'], ENT_QUOTES);
            $url_html = htmlspecialchars($item['url'], ENT_QUOTES);
            echo "<a href=\"$url_html\" target=\"_blank\">$title_html</a>";
        } else {
            // solo titolo testo normale
            echo "<strong>" . htmlspecialchars($item['title'], ENT_QUOTES) . "</strong>";
        }

        // descrizione (se presente)
        if (!empty($item['description'])) {
            $desc_html = htmlspecialchars($item['description'], ENT_QUOTES);
            echo "<br><small style='color: #555;'>$desc_html</small>";
        }

        // figli (ricorsivo)
        if (isset($item['children']) && count($item['children']) > 0) {
            echo "<div style='margin-left:20px; margin-top:4px;'>";
            stampaSegnalibri($item['children']);
            echo "</div>";
        }

        echo "</div>";
    }
}

stampaSegnalibri($segnalibri);
?>

The problem is that FF doesn’t have a description field, and I didn’t manage tgo get it from another filed, such as ‘tags’ one.