Add the full school maturita reading list of 82 books.

Keep full quizzes for 1984 and Spalovač mrtvol; other titles get catalog metadata stubs across Swift, GTK, and content.json.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
pepaskopec-blip 2026-09-22 11:01:32 +02:00
commit f813595bba
10 changed files with 949 additions and 45 deletions

543
data/cetba-catalog.json Normal file
View file

@ -0,0 +1,543 @@
[
{
"id": "1984",
"author": "George Orwell",
"title": "1984",
"translator": "Šimečková",
"genre": "Próza",
"full": true,
"page": "cetba1984"
},
{
"id": "fahrenheit451",
"author": "Ray Bradbury",
"title": "451 stupňů Fahrenheita",
"translator": "Nezval",
"genre": "Próza"
},
{
"id": "audience",
"author": "Václav Havel",
"title": "Audience",
"genre": "Drama"
},
{
"id": "bajecna-leta",
"author": "Michal Viewegh",
"title": "Báječná léta pod psa",
"genre": "Próza"
},
{
"id": "bidnici",
"author": "Victor Hugo",
"title": "Bídníci",
"translator": "Pavlousková",
"genre": "Próza"
},
{
"id": "bila-nemoc",
"author": "Karel Čapek",
"title": "Bílá nemoc",
"genre": "Drama"
},
{
"id": "bylo-nas-pet",
"author": "Karel Poláček",
"title": "Bylo nás pět",
"genre": "Próza"
},
{
"id": "cekani-na-godota",
"author": "Samuel Beckett",
"title": "Čekání na Godota",
"translator": "Ouředník",
"genre": "Drama"
},
{
"id": "ceske-nebe",
"author": "Zdeněk Svěrák, Ladislav Smoljak",
"title": "České nebe",
"genre": "Drama"
},
{
"id": "dekameron",
"author": "Giovanni Boccaccio",
"title": "Dekameron",
"translator": "Krátký",
"genre": "Próza"
},
{
"id": "den-trifidu",
"author": "John Wyndham",
"title": "Den trifidů",
"translator": "Kořán",
"genre": "Próza"
},
{
"id": "denik-anny-frankove",
"author": "Anne Franková",
"title": "Deník Anne Frankové",
"genre": "Próza"
},
{
"id": "jekyll-hyde",
"author": "Robert Louis Stevenson",
"title": "Dr. Jekyll a Mr. Hyde",
"translator": "Kořán",
"genre": "Próza"
},
{
"id": "edison",
"author": "Vítězslav Nezval",
"title": "Edison",
"genre": "Poezie"
},
{
"id": "farma-zvirat",
"author": "George Orwell",
"title": "Farma zvířat",
"translator": "Gössell",
"genre": "Próza"
},
{
"id": "gulliverovy-cesty",
"author": "Jonathan Swift",
"title": "Gulliverovy cesty",
"translator": "Skoumal",
"genre": "Próza"
},
{
"id": "hamlet",
"author": "William Shakespeare",
"title": "Hamlet",
"translator": "Nevrla",
"genre": "Drama"
},
{
"id": "havran",
"author": "Edgar Allan Poe",
"title": "Havran",
"genre": "Poezie"
},
{
"id": "hladove-hry",
"author": "Suzanne Collins",
"title": "Hladové hry – I. Aréna smrti",
"translator": "Dušek",
"genre": "Próza"
},
{
"id": "hlava-xxii",
"author": "Joseph Heller",
"title": "Hlava XXII",
"translator": "Jindra",
"genre": "Próza"
},
{
"id": "chram-matky-bozi",
"author": "Victor Hugo",
"title": "Chrám Matky Boží",
"translator": "Tomášková",
"genre": "Próza"
},
{
"id": "jak-jsem-vyhral-valku",
"author": "Patrick Ryan",
"title": "Jak jsem vyhrál válku",
"translator": "Vrba",
"genre": "Próza"
},
{
"id": "jana-eyrova",
"author": "Charlotte Brontëová",
"title": "Jana Eyrová",
"translator": "Polák",
"genre": "Próza"
},
{
"id": "ivan-denisovic",
"author": "Alexandr Solženicyn",
"title": "Jeden den Ivana Denisoviče",
"translator": "Machonin, Nováková",
"genre": "Próza"
},
{
"id": "jmeno-ruze",
"author": "Umberto Eco",
"title": "Jméno růže",
"translator": "Frýbort",
"genre": "Próza"
},
{
"id": "kalibuv-zlocin",
"author": "Karel Václav Rais",
"title": "Kalibův zločin",
"genre": "Próza"
},
{
"id": "kniska-karla-kryla",
"author": "Karel Kryl",
"title": "Kníška Karla Kryla",
"genre": "Poezie"
},
{
"id": "komu-zvoni-hrana",
"author": "Ernest Hemingway",
"title": "Komu zvoní hrana",
"translator": "Valja, Kobík",
"genre": "Próza"
},
{
"id": "kral-oidipus",
"author": "Sofoklés",
"title": "Král Oidipus",
"translator": "Stiebitz",
"genre": "Drama"
},
{
"id": "krysar",
"author": "Viktor Dyk",
"title": "Krysař",
"genre": "Próza"
},
{
"id": "kulicka",
"author": "Guy de Maupassant",
"title": "Kulička",
"translator": "Guth",
"genre": "Próza"
},
{
"id": "kvety-zla",
"author": "Charles Baudelaire",
"title": "Květy zla",
"translator": "Nezval",
"genre": "Poezie"
},
{
"id": "kytice",
"author": "Karel Jaromír Erben",
"title": "Kytice",
"genre": "Poezie"
},
{
"id": "lakomec",
"author": "Molière",
"title": "Lakomec",
"translator": "Mikeš",
"genre": "Drama"
},
{
"id": "lolita",
"author": "Vladimir Nabokov",
"title": "Lolita",
"translator": "Kořínek",
"genre": "Próza"
},
{
"id": "maj",
"author": "Karel Hynek Mácha",
"title": "Máj",
"genre": "Poezie"
},
{
"id": "maly-princ",
"author": "Antoine de Saint-Exupéry",
"title": "Malý princ",
"translator": "Stavinohová",
"genre": "Próza"
},
{
"id": "marysa",
"author": "Alois Mrštík, Vilém Mrštík",
"title": "Maryša",
"genre": "Drama"
},
{
"id": "modlitba-pro-katerinu",
"author": "Arnošt Lustig",
"title": "Modlitba pro Kateřinu Horovitzovou",
"genre": "Próza"
},
{
"id": "most-kwai",
"author": "Pierre Boulle",
"title": "Most přes řeku Kwai",
"translator": "Šup",
"genre": "Próza"
},
{
"id": "stanice-zoo",
"author": "Christiane F.",
"title": "My děti ze stanice ZOO",
"translator": "Soukupová",
"genre": "Próza"
},
{
"id": "na-ceste",
"author": "Jack Kerouac",
"title": "Na cestě",
"translator": "Popel",
"genre": "Próza"
},
{
"id": "na-zapadni-fronte",
"author": "Erich Maria Remarque",
"title": "Na západní frontě klid",
"translator": "Gel",
"genre": "Próza"
},
{
"id": "navsteva-stare-damy",
"author": "Friedrich Dürrenmatt",
"title": "Návštěva staré dámy",
"genre": "Drama"
},
{
"id": "nebe-nezna-vyvolenych",
"author": "Erich Maria Remarque",
"title": "Nebe nezná vyvolených",
"translator": "V. a K. Holubovi",
"genre": "Próza"
},
{
"id": "o-mysich-a-lidech",
"author": "John Steinbeck",
"title": "O myších a lidech",
"translator": "Vendyš",
"genre": "Próza"
},
{
"id": "obraz-doriana-graye",
"author": "Oscar Wilde",
"title": "Obraz Doriana Graye",
"translator": "Novák",
"genre": "Próza"
},
{
"id": "obsluhoval-jsem",
"author": "Bohumil Hrabal",
"title": "Obsluhoval jsem anglického krále",
"genre": "Próza"
},
{
"id": "oliver-twist",
"author": "Charles Dickens",
"title": "Oliver Twist",
"translator": "E. a E. Tilschovi",
"genre": "Próza"
},
{
"id": "ostre-sledovane-vlaky",
"author": "Bohumil Hrabal",
"title": "Ostře sledované vlaky",
"genre": "Próza"
},
{
"id": "svejk",
"author": "Jaroslav Hašek",
"title": "Osudy dobrého vojáka Švejka za světové války",
"genre": "Próza"
},
{
"id": "pan-much",
"author": "William Golding",
"title": "Pán much",
"translator": "Kovályová",
"genre": "Próza"
},
{
"id": "pan-prstenu",
"author": "J. R. R. Tolkien",
"title": "Pán prstenů – Společenstvo prstenu",
"translator": "Pošustová",
"genre": "Próza"
},
{
"id": "petr-a-lucie",
"author": "Romain Rolland",
"title": "Petr a Lucie",
"translator": "Zaorálek",
"genre": "Próza"
},
{
"id": "poe-povidky",
"author": "Edgar Allan Poe",
"title": "Povídky",
"genre": "Próza"
},
{
"id": "povidky-z-kapes",
"author": "Karel Čapek",
"title": "Povídky z jedné a druhé kapsy",
"genre": "Próza"
},
{
"id": "promena",
"author": "Franz Kafka",
"title": "Proměna",
"genre": "Próza"
},
{
"id": "pycha-a-predsudek",
"author": "Jane Austenová",
"title": "Pýcha a předsudek",
"translator": "Poláčková",
"genre": "Próza"
},
{
"id": "rur",
"author": "Karel Čapek",
"title": "R. U. R.",
"genre": "Drama"
},
{
"id": "revizor",
"author": "Nikolaj Vasiljevič Gogol",
"title": "Revizor",
"translator": "Mahler, Suchařípa, Morávková",
"genre": "Drama"
},
{
"id": "romeo-a-julie",
"author": "William Shakespeare",
"title": "Romeo a Julie",
"translator": "Hilský",
"genre": "Drama"
},
{
"id": "romeo-julie-a-tma",
"author": "Jan Otčenášek",
"title": "Romeo, Julie a tma",
"genre": "Próza"
},
{
"id": "rozmarne-leto",
"author": "Vladislav Vančura",
"title": "Rozmarné léto",
"genre": "Próza"
},
{
"id": "ruze-pro-algernon",
"author": "Daniel Keyes",
"title": "Růže pro Algernon",
"translator": "Podaný",
"genre": "Próza"
},
{
"id": "saturnin",
"author": "Zdeněk Jirotka",
"title": "Saturnin",
"genre": "Próza"
},
{
"id": "sluha-dvou-panu",
"author": "Carlo Goldoni",
"title": "Sluha dvou pánů",
"translator": "Bezděková",
"genre": "Drama"
},
{
"id": "smrt-krasnych-srncu",
"author": "Ota Pavel",
"title": "Smrt krásných srnců",
"genre": "Próza"
},
{
"id": "sofiina-volba",
"author": "William Styron",
"title": "Sofiina volba",
"translator": "Nenadál",
"genre": "Próza"
},
{
"id": "fuks",
"author": "Ladislav Fuks",
"title": "Spalovač mrtvol",
"genre": "Próza",
"full": true,
"page": "cetbaFuks"
},
{
"id": "stare-recke-baje",
"author": "Eduard Petiška",
"title": "Staré řecké báje a pověsti",
"genre": "Próza"
},
{
"id": "starec-a-more",
"author": "Ernest Hemingway",
"title": "Stařec a moře",
"translator": "Vrba",
"genre": "Próza"
},
{
"id": "svaty-xaverius",
"author": "Jakub Arbes",
"title": "Svatý Xaverius",
"genre": "Próza"
},
{
"id": "tereza-raquinova",
"author": "Émile Zola",
"title": "Tereza Raquinová",
"genre": "Próza"
},
{
"id": "tezka-hodina",
"author": "Jiří Wolker",
"title": "Těžká hodina",
"genre": "Poezie"
},
{
"id": "tyrolske-elegie",
"author": "Karel Havlíček Borovský",
"title": "Tyrolské elegie",
"genre": "Poezie"
},
{
"id": "valka-s-mloky",
"author": "Karel Čapek",
"title": "Válka s mloky",
"genre": "Próza"
},
{
"id": "velky-cirkus",
"author": "Pierre Clostermann",
"title": "Velký cirkus",
"translator": "Jedlička",
"genre": "Próza"
},
{
"id": "velky-gatsby",
"author": "F. Scott Fitzgerald",
"title": "Velký Gatsby",
"translator": "Dorůžka",
"genre": "Próza"
},
{
"id": "tridni-kniha",
"author": "Ladislav Smoljak, Zdeněk Svěrák",
"title": "Vyšetřování ztráty třídní knihy",
"genre": "Drama"
},
{
"id": "zabijak",
"author": "Émile Zola",
"title": "Zabiják",
"translator": "Kárl",
"genre": "Próza"
},
{
"id": "zbabelci",
"author": "Josef Škvorecký",
"title": "Zbabělci",
"genre": "Próza"
},
{
"id": "zert",
"author": "Milan Kundera",
"title": "Žert",
"genre": "Próza"
}
]

View file

@ -50,7 +50,10 @@ enum Route: Hashable {
case .mluvnice: return "mluvnice"
case .mluvEx(let n): return "mluve\(n)"
case .readingList: return "readinglist"
case .book(let id): return id == "1984" ? "cetba1984" : "cetbaFuks"
case .book(let id):
if id == "1984" { return "cetba1984" }
if id == "fuks" { return "cetbaFuks" }
return "cetba_" + id.replacingOccurrences(of: "-", with: "_")
case .bookQuiz(let id): return id == "1984" ? "cetba1984quiz" : "cetbaFuksQuiz"
case .bookPlot(let id): return id == "1984" ? "cetba1984dej" : "cetbaFuksDej"
}
@ -120,6 +123,10 @@ func routeFromPage(_ page: String) -> Route? {
case "cetbaFuksQuiz": return .bookQuiz("fuks")
case "cetbaFuksDej": return .bookPlot("fuks")
default:
if page.hasPrefix("cetba_") {
let slug = String(page.dropFirst(6)).replacingOccurrences(of: "_", with: "-")
return .book(slug)
}
if let m = page.wholeMatch(of: /unit(\d+)/), let n = Int(m.1) {
return .unitMap(n - 1)
}

View file

@ -887,7 +887,10 @@ struct BookListScreen: View {
Label {
VStack(alignment: .leading) {
Text(b.str("title"))
Text(vm.tr(b.str("subKey"))).font(.caption).foregroundStyle(.secondary)
let genre = b.str("genre")
Text(genre.isEmpty ? vm.tr(b.str("subKey")) : genre)
.font(.caption)
.foregroundStyle(.secondary)
}
} icon: {
Image(systemName: "book.fill")
@ -907,7 +910,10 @@ struct BookScreen: View {
var body: some View {
if let b = vm.content.book(id) {
let hasQuiz = !b.arr("quiz").isEmpty
let hasPlot = !b.arr("plot").isEmpty
List {
if hasQuiz {
NavigationLink(value: Route.bookQuiz(id)) {
Label {
VStack(alignment: .leading) {
@ -918,6 +924,8 @@ struct BookScreen: View {
Image(systemName: "questionmark.circle")
}
}
}
if hasPlot {
NavigationLink(value: Route.bookPlot(id)) {
Label {
VStack(alignment: .leading) {
@ -928,6 +936,7 @@ struct BookScreen: View {
Image(systemName: "list.number")
}
}
}
ForEach(Array(b.arr("notes").enumerated()), id: \.offset) { _, note in
Section(note.str("title")) {
ForEach(note.strs("lines"), id: \.self) { line in

View file

@ -1165,10 +1165,11 @@ def main() -> int:
def note_lines(fn, name):
return str_list(A(f"{fn}.{name}"))
books = [
{
"id": "1984",
"title": "George Orwell – 1984",
catalog_path = ROOT / "data" / "cetba-catalog.json"
catalog = json.loads(catalog_path.read_text(encoding="utf-8"))
full_books = {
"1984": {
"subKey": "cetba1984_sub",
"page": "cetba1984",
"quizTitle": "lit_quiz_title",
@ -1189,9 +1190,7 @@ def main() -> int:
"plot": assembly_items(A("lit_plot_items")),
"plotMeaning": str_list(A("lit_plot_meaning")),
},
{
"id": "fuks",
"title": "Ladislav Fuks – Spalovač mrtvol",
"fuks": {
"subKey": "cetbaFuks_sub",
"page": "cetbaFuks",
"quizTitle": "lit_fuks_quiz_title",
@ -1212,7 +1211,78 @@ def main() -> int:
"plot": assembly_items(A("fuks_plot_items")),
"plotMeaning": str_list(A("fuks_plot_meaning")),
},
}
books = []
for entry in catalog:
bid = entry["id"]
display = f"{entry['author']} – {entry['title']}"
page = entry.get("page") or f"cetba_{bid.replace('-', '_')}"
if bid in full_books:
book = {"id": bid, "title": display, **full_books[bid]}
book["genre"] = entry.get("genre", "")
books.append(book)
continue
about = [f"Autor: {entry['author']}", f"Žánr: {entry['genre']}"]
if entry.get("translator"):
about.append(f"Překlad: {entry['translator']}")
about.append("Ze školního seznamu maturitní četby.")
books.append({
"id": bid,
"title": display,
"subKey": "cetba_entry_sub",
"page": page,
"genre": entry["genre"],
"quizTitle": "",
"quizSub": "",
"plotTitle": "",
"plotSub": "",
"notes": [
{"title": "O knize", "icon": "book", "lines": about},
],
"quiz": [],
"plot": [],
"plotMeaning": [],
})
# GTK catalog include for the reading-list path map
inc_lines = [
"/* Generated from data/cetba-catalog.json – do not edit by hand. */",
f"#define BOOK_NODES {len(catalog)}",
"",
"typedef struct {",
" const char *title;",
" const char *target;",
" const char *author;",
" const char *work;",
" const char *genre;",
" const char *translator;",
" int full;",
"} BookDef;",
"",
"static const BookDef book_defs[BOOK_NODES] = {",
]
for entry in catalog:
bid = entry["id"]
display = f"{entry['author']} – {entry['title']}"
page = entry.get("page") or f"cetba_{bid.replace('-', '_')}"
if entry.get("full"):
target = entry.get("page") or page
full = 1
else:
target = "cetbastub"
full = 0
transl = entry.get("translator") or ""
def c_str(s: str) -> str:
return '"' + s.replace("\\", "\\\\").replace('"', '\\"') + '"'
transl_c = "NULL" if not transl else c_str(transl)
inc_lines.append(
f" {{{c_str(display)}, {c_str(target)}, {c_str(entry['author'])}, "
f"{c_str(entry['title'])}, {c_str(entry['genre'])}, {transl_c}, {full}}},"
)
inc_lines.append("};")
inc_lines.append("")
(SRC / "cetba_catalog.inc").write_text("\n".join(inc_lines) + "\n", encoding="utf-8")
subjects = [
{"key": "Deutsch", "open": True, "target": "roadmap", "icon": "de"},

View file

@ -1211,17 +1211,11 @@ static void lit_note_card(GtkWidget *parent, const char *title,
/* Reading roadmap (Maturitní četba) */
/* ------------------------------------------------------------------ */
#define BOOK_NODES 2
#include "cetba_catalog.inc"
typedef struct {
const char *title;
const char *target;
} BookDef;
static const BookDef book_defs[BOOK_NODES] = {
{"George Orwell – 1984", "cetba1984"},
{"Ladislav Fuks – Spalovač mrtvol", "cetbaFuks"},
};
static int stub_book_idx = -1;
static GtkWidget *stub_title_lbl;
static GtkWidget *stub_about_box;
static GtkWidget *book_rail;
static GtkWidget *book_nodes[BOOK_NODES];
@ -1340,6 +1334,58 @@ void book_rail_theme_reset(void) {
gtk_widget_queue_draw(book_rail);
}
static void rebuild_stub_about(int idx) {
GtkWidget *child;
static char author_buf[192];
static char genre_buf[96];
static char transl_buf[192];
const char *lines[4];
int n = 0;
if (!stub_about_box || idx < 0 || idx >= BOOK_NODES)
return;
while ((child = gtk_widget_get_first_child(stub_about_box)))
gtk_box_remove(GTK_BOX(stub_about_box), child);
g_snprintf(author_buf, sizeof author_buf, "Autor: %s",
book_defs[idx].author);
g_snprintf(genre_buf, sizeof genre_buf, "Žánr: %s",
book_defs[idx].genre);
lines[n++] = author_buf;
lines[n++] = genre_buf;
if (book_defs[idx].translator) {
g_snprintf(transl_buf, sizeof transl_buf, "Překlad: %s",
book_defs[idx].translator);
lines[n++] = transl_buf;
}
lines[n++] = tr("cetba_stub_soon");
for (int i = 0; i < n; i++) {
GtkWidget *l = gtk_label_new(lines[i]);
gtk_widget_set_halign(l, GTK_ALIGN_START);
gtk_label_set_wrap(GTK_LABEL(l), TRUE);
gtk_label_set_xalign(GTK_LABEL(l), 0.0);
gtk_widget_add_css_class(l, "notes-body");
gtk_box_append(GTK_BOX(stub_about_box), l);
}
}
static void on_book_node_clicked(GtkButton *button, gpointer user_data) {
int idx = GPOINTER_TO_INT(user_data);
const char *target = book_defs[idx].target;
(void)button;
if (!book_defs[idx].full) {
stub_book_idx = idx;
if (stub_title_lbl)
gtk_label_set_text(GTK_LABEL(stub_title_lbl), book_defs[idx].title);
rebuild_stub_about(idx);
}
if (main_stack && target)
gtk_stack_set_visible_child_name(main_stack, target);
}
static GtkWidget *book_make_node(int i) {
GtkWidget *btn = gtk_button_new();
GtkWidget *icon = icon_area_new(draw_book_badge_icon, 0, 0, 0, 48);
@ -1351,9 +1397,8 @@ static GtkWidget *book_make_node(int i) {
gtk_button_set_child(GTK_BUTTON(btn), icon);
g_object_set_data_full(G_OBJECT(btn), "target",
g_strdup(book_defs[i].target), g_free);
g_signal_connect(btn, "clicked", G_CALLBACK(on_nav_clicked), NULL);
g_signal_connect(btn, "clicked", G_CALLBACK(on_book_node_clicked),
GINT_TO_POINTER(i));
return btn;
}
@ -1593,3 +1638,113 @@ GtkWidget *build_cetba_fuks_page(void) {
return page;
}
GtkWidget *build_cetba_stub_page(void) {
GtkWidget *page;
GtkWidget *top;
GtkWidget *center;
GtkWidget *scroll;
GtkWidget *box;
GtkWidget *card;
GtkWidget *head;
GtkWidget *ic;
GtkWidget *t;
GtkWidget *sub;
page = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_set_margin_start(page, 32);
gtk_widget_set_margin_end(page, 32);
gtk_widget_set_margin_top(page, 24);
gtk_widget_set_margin_bottom(page, 24);
top = gtk_center_box_new();
gtk_widget_add_css_class(top, "page-top");
gtk_widget_set_margin_top(top, 8);
gtk_widget_set_margin_bottom(top, 18);
gtk_center_box_set_start_widget(GTK_CENTER_BOX(top),
make_back_button("readinglist"));
center = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
gtk_widget_set_valign(center, GTK_ALIGN_CENTER);
gtk_center_box_set_center_widget(GTK_CENTER_BOX(top), center);
stub_title_lbl = gtk_label_new("…");
gtk_widget_set_halign(stub_title_lbl, GTK_ALIGN_CENTER);
gtk_label_set_wrap(GTK_LABEL(stub_title_lbl), TRUE);
gtk_widget_add_css_class(stub_title_lbl, "roadmap-title");
gtk_box_append(GTK_BOX(center), stub_title_lbl);
sub = gtk_label_new(NULL);
i18n_bind(sub, "cetba_entry_sub", 0);
gtk_widget_set_halign(sub, GTK_ALIGN_CENTER);
gtk_widget_add_css_class(sub, "roadmap-sub");
gtk_label_set_wrap(GTK_LABEL(sub), TRUE);
gtk_box_append(GTK_BOX(center), sub);
gtk_box_append(GTK_BOX(page), top);
scroll = gtk_scrolled_window_new();
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
gtk_widget_set_vexpand(scroll, TRUE);
gtk_widget_set_margin_top(scroll, 14);
gtk_widget_set_margin_bottom(scroll, 14);
gtk_box_append(GTK_BOX(page), scroll);
box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(scroll), box);
card = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
gtk_widget_add_css_class(card, "notes-card");
gtk_widget_set_margin_bottom(card, 14);
gtk_box_append(GTK_BOX(box), card);
head = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10);
gtk_box_append(GTK_BOX(card), head);
ic = icon_area_new(draw_book_icon, 0, 0, 0, 26);
gtk_widget_set_valign(ic, GTK_ALIGN_CENTER);
gtk_box_append(GTK_BOX(head), ic);
t = gtk_label_new("O knize");
gtk_widget_set_halign(t, GTK_ALIGN_START);
gtk_widget_set_valign(t, GTK_ALIGN_CENTER);
gtk_widget_add_css_class(t, "notes-title");
gtk_box_append(GTK_BOX(head), t);
stub_about_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
gtk_box_append(GTK_BOX(card), stub_about_box);
return page;
}
void cetba_open_stub(int idx) {
if (idx < 0 || idx >= BOOK_NODES || book_defs[idx].full)
return;
stub_book_idx = idx;
if (stub_title_lbl)
gtk_label_set_text(GTK_LABEL(stub_title_lbl), book_defs[idx].title);
rebuild_stub_about(idx);
if (main_stack)
gtk_stack_set_visible_child_name(main_stack, "cetbastub");
}
void cetba_register_search(void) {
char target[32];
for (int i = 0; i < BOOK_NODES; i++) {
if (book_defs[i].full) {
search_catalog_add(book_defs[i].title, tr("search_book"),
book_defs[i].target, FALSE, 2, book_defs[i].author);
if (g_strcmp0(book_defs[i].target, "cetba1984") == 0)
search_catalog_add(tr("lit_quiz_title"), tr("search_exercise"),
"cetba1984quiz", FALSE, 3, "orwell kviz");
else if (g_strcmp0(book_defs[i].target, "cetbaFuks") == 0)
search_catalog_add(tr("lit_fuks_quiz_title"),
tr("search_exercise"), "cetbaFuksQuiz",
FALSE, 3, "fuks kviz");
} else {
g_snprintf(target, sizeof target, "cetbastub:%d", i);
search_catalog_add(book_defs[i].title, tr("search_book"),
target, FALSE, 2, book_defs[i].author);
}
}
}

98
src/cetba_catalog.inc Normal file
View file

@ -0,0 +1,98 @@
/* Generated from data/cetba-catalog.json – do not edit by hand. */
#define BOOK_NODES 82
typedef struct {
const char *title;
const char *target;
const char *author;
const char *work;
const char *genre;
const char *translator;
int full;
} BookDef;
static const BookDef book_defs[BOOK_NODES] = {
{"George Orwell – 1984", "cetba1984", "George Orwell", "1984", "Próza", "Šimečková", 1},
{"Ray Bradbury – 451 stupňů Fahrenheita", "cetbastub", "Ray Bradbury", "451 stupňů Fahrenheita", "Próza", "Nezval", 0},
{"Václav Havel – Audience", "cetbastub", "Václav Havel", "Audience", "Drama", NULL, 0},
{"Michal Viewegh – Báječná léta pod psa", "cetbastub", "Michal Viewegh", "Báječná léta pod psa", "Próza", NULL, 0},
{"Victor Hugo – Bídníci", "cetbastub", "Victor Hugo", "Bídníci", "Próza", "Pavlousková", 0},
{"Karel Čapek – Bílá nemoc", "cetbastub", "Karel Čapek", "Bílá nemoc", "Drama", NULL, 0},
{"Karel Poláček – Bylo nás pět", "cetbastub", "Karel Poláček", "Bylo nás pět", "Próza", NULL, 0},
{"Samuel Beckett – Čekání na Godota", "cetbastub", "Samuel Beckett", "Čekání na Godota", "Drama", "Ouředník", 0},
{"Zdeněk Svěrák, Ladislav Smoljak – České nebe", "cetbastub", "Zdeněk Svěrák, Ladislav Smoljak", "České nebe", "Drama", NULL, 0},
{"Giovanni Boccaccio – Dekameron", "cetbastub", "Giovanni Boccaccio", "Dekameron", "Próza", "Krátký", 0},
{"John Wyndham – Den trifidů", "cetbastub", "John Wyndham", "Den trifidů", "Próza", "Kořán", 0},
{"Anne Franková – Deník Anne Frankové", "cetbastub", "Anne Franková", "Deník Anne Frankové", "Próza", NULL, 0},
{"Robert Louis Stevenson – Dr. Jekyll a Mr. Hyde", "cetbastub", "Robert Louis Stevenson", "Dr. Jekyll a Mr. Hyde", "Próza", "Kořán", 0},
{"Vítězslav Nezval – Edison", "cetbastub", "Vítězslav Nezval", "Edison", "Poezie", NULL, 0},
{"George Orwell – Farma zvířat", "cetbastub", "George Orwell", "Farma zvířat", "Próza", "Gössell", 0},
{"Jonathan Swift – Gulliverovy cesty", "cetbastub", "Jonathan Swift", "Gulliverovy cesty", "Próza", "Skoumal", 0},
{"William Shakespeare – Hamlet", "cetbastub", "William Shakespeare", "Hamlet", "Drama", "Nevrla", 0},
{"Edgar Allan Poe – Havran", "cetbastub", "Edgar Allan Poe", "Havran", "Poezie", NULL, 0},
{"Suzanne Collins – Hladové hry – I. Aréna smrti", "cetbastub", "Suzanne Collins", "Hladové hry – I. Aréna smrti", "Próza", "Dušek", 0},
{"Joseph Heller – Hlava XXII", "cetbastub", "Joseph Heller", "Hlava XXII", "Próza", "Jindra", 0},
{"Victor Hugo – Chrám Matky Boží", "cetbastub", "Victor Hugo", "Chrám Matky Boží", "Próza", "Tomášková", 0},
{"Patrick Ryan – Jak jsem vyhrál válku", "cetbastub", "Patrick Ryan", "Jak jsem vyhrál válku", "Próza", "Vrba", 0},
{"Charlotte Brontëová – Jana Eyrová", "cetbastub", "Charlotte Brontëová", "Jana Eyrová", "Próza", "Polák", 0},
{"Alexandr Solženicyn – Jeden den Ivana Denisoviče", "cetbastub", "Alexandr Solženicyn", "Jeden den Ivana Denisoviče", "Próza", "Machonin, Nováková", 0},
{"Umberto Eco – Jméno růže", "cetbastub", "Umberto Eco", "Jméno růže", "Próza", "Frýbort", 0},
{"Karel Václav Rais – Kalibův zločin", "cetbastub", "Karel Václav Rais", "Kalibův zločin", "Próza", NULL, 0},
{"Karel Kryl – Kníška Karla Kryla", "cetbastub", "Karel Kryl", "Kníška Karla Kryla", "Poezie", NULL, 0},
{"Ernest Hemingway – Komu zvoní hrana", "cetbastub", "Ernest Hemingway", "Komu zvoní hrana", "Próza", "Valja, Kobík", 0},
{"Sofoklés – Král Oidipus", "cetbastub", "Sofoklés", "Král Oidipus", "Drama", "Stiebitz", 0},
{"Viktor Dyk – Krysař", "cetbastub", "Viktor Dyk", "Krysař", "Próza", NULL, 0},
{"Guy de Maupassant – Kulička", "cetbastub", "Guy de Maupassant", "Kulička", "Próza", "Guth", 0},
{"Charles Baudelaire – Květy zla", "cetbastub", "Charles Baudelaire", "Květy zla", "Poezie", "Nezval", 0},
{"Karel Jaromír Erben – Kytice", "cetbastub", "Karel Jaromír Erben", "Kytice", "Poezie", NULL, 0},
{"Molière – Lakomec", "cetbastub", "Molière", "Lakomec", "Drama", "Mikeš", 0},
{"Vladimir Nabokov – Lolita", "cetbastub", "Vladimir Nabokov", "Lolita", "Próza", "Kořínek", 0},
{"Karel Hynek Mácha – Máj", "cetbastub", "Karel Hynek Mácha", "Máj", "Poezie", NULL, 0},
{"Antoine de Saint-Exupéry – Malý princ", "cetbastub", "Antoine de Saint-Exupéry", "Malý princ", "Próza", "Stavinohová", 0},
{"Alois Mrštík, Vilém Mrštík – Maryša", "cetbastub", "Alois Mrštík, Vilém Mrštík", "Maryša", "Drama", NULL, 0},
{"Arnošt Lustig – Modlitba pro Kateřinu Horovitzovou", "cetbastub", "Arnošt Lustig", "Modlitba pro Kateřinu Horovitzovou", "Próza", NULL, 0},
{"Pierre Boulle – Most přes řeku Kwai", "cetbastub", "Pierre Boulle", "Most přes řeku Kwai", "Próza", "Šup", 0},
{"Christiane F. – My děti ze stanice ZOO", "cetbastub", "Christiane F.", "My děti ze stanice ZOO", "Próza", "Soukupová", 0},
{"Jack Kerouac – Na cestě", "cetbastub", "Jack Kerouac", "Na cestě", "Próza", "Popel", 0},
{"Erich Maria Remarque – Na západní frontě klid", "cetbastub", "Erich Maria Remarque", "Na západní frontě klid", "Próza", "Gel", 0},
{"Friedrich Dürrenmatt – Návštěva staré dámy", "cetbastub", "Friedrich Dürrenmatt", "Návštěva staré dámy", "Drama", NULL, 0},
{"Erich Maria Remarque – Nebe nezná vyvolených", "cetbastub", "Erich Maria Remarque", "Nebe nezná vyvolených", "Próza", "V. a K. Holubovi", 0},
{"John Steinbeck – O myších a lidech", "cetbastub", "John Steinbeck", "O myších a lidech", "Próza", "Vendyš", 0},
{"Oscar Wilde – Obraz Doriana Graye", "cetbastub", "Oscar Wilde", "Obraz Doriana Graye", "Próza", "Novák", 0},
{"Bohumil Hrabal – Obsluhoval jsem anglického krále", "cetbastub", "Bohumil Hrabal", "Obsluhoval jsem anglického krále", "Próza", NULL, 0},
{"Charles Dickens – Oliver Twist", "cetbastub", "Charles Dickens", "Oliver Twist", "Próza", "E. a E. Tilschovi", 0},
{"Bohumil Hrabal – Ostře sledované vlaky", "cetbastub", "Bohumil Hrabal", "Ostře sledované vlaky", "Próza", NULL, 0},
{"Jaroslav Hašek – Osudy dobrého vojáka Švejka za světové války", "cetbastub", "Jaroslav Hašek", "Osudy dobrého vojáka Švejka za světové války", "Próza", NULL, 0},
{"William Golding – Pán much", "cetbastub", "William Golding", "Pán much", "Próza", "Kovályová", 0},
{"J. R. R. Tolkien – Pán prstenů – Společenstvo prstenu", "cetbastub", "J. R. R. Tolkien", "Pán prstenů – Společenstvo prstenu", "Próza", "Pošustová", 0},
{"Romain Rolland – Petr a Lucie", "cetbastub", "Romain Rolland", "Petr a Lucie", "Próza", "Zaorálek", 0},
{"Edgar Allan Poe – Povídky", "cetbastub", "Edgar Allan Poe", "Povídky", "Próza", NULL, 0},
{"Karel Čapek – Povídky z jedné a druhé kapsy", "cetbastub", "Karel Čapek", "Povídky z jedné a druhé kapsy", "Próza", NULL, 0},
{"Franz Kafka – Proměna", "cetbastub", "Franz Kafka", "Proměna", "Próza", NULL, 0},
{"Jane Austenová – Pýcha a předsudek", "cetbastub", "Jane Austenová", "Pýcha a předsudek", "Próza", "Poláčková", 0},
{"Karel Čapek – R. U. R.", "cetbastub", "Karel Čapek", "R. U. R.", "Drama", NULL, 0},
{"Nikolaj Vasiljevič Gogol – Revizor", "cetbastub", "Nikolaj Vasiljevič Gogol", "Revizor", "Drama", "Mahler, Suchařípa, Morávková", 0},
{"William Shakespeare – Romeo a Julie", "cetbastub", "William Shakespeare", "Romeo a Julie", "Drama", "Hilský", 0},
{"Jan Otčenášek – Romeo, Julie a tma", "cetbastub", "Jan Otčenášek", "Romeo, Julie a tma", "Próza", NULL, 0},
{"Vladislav Vančura – Rozmarné léto", "cetbastub", "Vladislav Vančura", "Rozmarné léto", "Próza", NULL, 0},
{"Daniel Keyes – Růže pro Algernon", "cetbastub", "Daniel Keyes", "Růže pro Algernon", "Próza", "Podaný", 0},
{"Zdeněk Jirotka – Saturnin", "cetbastub", "Zdeněk Jirotka", "Saturnin", "Próza", NULL, 0},
{"Carlo Goldoni – Sluha dvou pánů", "cetbastub", "Carlo Goldoni", "Sluha dvou pánů", "Drama", "Bezděková", 0},
{"Ota Pavel – Smrt krásných srnců", "cetbastub", "Ota Pavel", "Smrt krásných srnců", "Próza", NULL, 0},
{"William Styron – Sofiina volba", "cetbastub", "William Styron", "Sofiina volba", "Próza", "Nenadál", 0},
{"Ladislav Fuks – Spalovač mrtvol", "cetbaFuks", "Ladislav Fuks", "Spalovač mrtvol", "Próza", NULL, 1},
{"Eduard Petiška – Staré řecké báje a pověsti", "cetbastub", "Eduard Petiška", "Staré řecké báje a pověsti", "Próza", NULL, 0},
{"Ernest Hemingway – Stařec a moře", "cetbastub", "Ernest Hemingway", "Stařec a moře", "Próza", "Vrba", 0},
{"Jakub Arbes – Svatý Xaverius", "cetbastub", "Jakub Arbes", "Svatý Xaverius", "Próza", NULL, 0},
{"Émile Zola – Tereza Raquinová", "cetbastub", "Émile Zola", "Tereza Raquinová", "Próza", NULL, 0},
{"Jiří Wolker – Těžká hodina", "cetbastub", "Jiří Wolker", "Těžká hodina", "Poezie", NULL, 0},
{"Karel Havlíček Borovský – Tyrolské elegie", "cetbastub", "Karel Havlíček Borovský", "Tyrolské elegie", "Poezie", NULL, 0},
{"Karel Čapek – Válka s mloky", "cetbastub", "Karel Čapek", "Válka s mloky", "Próza", NULL, 0},
{"Pierre Clostermann – Velký cirkus", "cetbastub", "Pierre Clostermann", "Velký cirkus", "Próza", "Jedlička", 0},
{"F. Scott Fitzgerald – Velký Gatsby", "cetbastub", "F. Scott Fitzgerald", "Velký Gatsby", "Próza", "Dorůžka", 0},
{"Ladislav Smoljak, Zdeněk Svěrák – Vyšetřování ztráty třídní knihy", "cetbastub", "Ladislav Smoljak, Zdeněk Svěrák", "Vyšetřování ztráty třídní knihy", "Drama", NULL, 0},
{"Émile Zola – Zabiják", "cetbastub", "Émile Zola", "Zabiják", "Próza", "Kárl", 0},
{"Josef Škvorecký – Zbabělci", "cetbastub", "Josef Škvorecký", "Zbabělci", "Próza", NULL, 0},
{"Milan Kundera – Žert", "cetbastub", "Milan Kundera", "Žert", "Próza", NULL, 0},
};

View file

@ -552,6 +552,10 @@ const TrEntry tr_ui[] = {
{"book_1984_sub", "Antiutopický román • 1949", "Dystopian novel • 1949"},
{"cetba1984_sub", "Přehled knihy, klíčové pojmy a cvičení.",
"Book overview, key terms and exercises."},
{"cetba_entry_sub", "Údaje ze školního seznamu maturitní četby.",
"Details from the school maturita reading list."},
{"cetba_stub_soon", "Podrobný přehled a cvičení zatím nejsou k dispozici.",
"A detailed overview and exercises are not available yet."},
{"lit_quiz_title", "Kvíz: George Orwell – 1984",
"Quiz: George Orwell – 1984"},
{"lit_quiz_sub", "U každé otázky vyberte jednu správnou odpověď.",

View file

@ -519,6 +519,7 @@ void activate(GtkApplication *app, gpointer user_data) {
"cetbaFuksQuiz");
gtk_stack_add_named(main_stack, build_cetba_fuks_plot_page(),
"cetbaFuksDej");
gtk_stack_add_named(main_stack, build_cetba_stub_page(), "cetbastub");
gtk_stack_add_named(main_stack, build_hw_unit1_page(), "hwunit1");
gtk_stack_add_named(main_stack, build_hw_unit1_exercise_page(), "hwex1");
gtk_stack_add_named(main_stack, build_hw_unit2_page(), "hwunit2");

View file

@ -851,6 +851,12 @@ GtkWidget *build_cetba1984_plot_page(void);
GtkWidget *build_cetba_fuks_page(void);
GtkWidget *build_cetba_fuks_quiz_page(void);
GtkWidget *build_cetba_fuks_plot_page(void);
GtkWidget *build_cetba_stub_page(void);
void cetba_register_search(void);
void cetba_open_stub(int idx);
void search_catalog_add(const char *title, const char *subtitle,
const char *target, gboolean locked, int rank,
const char *extra);
void book_rail_theme_reset(void);
GtkWidget *build_hw_unit1_page(void);
GtkWidget *build_hw_unit1_exercise_page(void);

View file

@ -1,5 +1,6 @@
#include "maturita.h"
#include <stdlib.h>
#include <string.h>
#define SEARCH_MAX 24
@ -90,12 +91,23 @@ static void item_free(gpointer p) {
g_free(it);
}
static void catalog_add(const char *title, const char *subtitle,
const char *target, gboolean locked, int rank,
const char *extra);
void search_catalog_add(const char *title, const char *subtitle,
const char *target, gboolean locked, int rank,
const char *extra) {
catalog_add(title, subtitle, target, locked, rank, extra);
}
static void catalog_add(const char *title, const char *subtitle,
const char *target, gboolean locked, int rank,
const char *extra) {
if (!title || !target)
return;
if (main_stack && !gtk_stack_get_child_by_name(main_stack, target))
if (main_stack && !gtk_stack_get_child_by_name(main_stack, target)
&& strncmp(target, "cetbastub:", 10) != 0)
return;
g_ptr_array_add(search_items,
item_new(title, subtitle, target, locked, rank, extra));
@ -190,14 +202,7 @@ static void catalog_rebuild(void) {
"gramatika grammar");
catalog_add_key("Maturitní četba", "search_book", "readinglist", FALSE, 1,
"knihy books");
catalog_add("George Orwell – 1984", tr("search_book"), "cetba1984",
FALSE, 2, "orwell dystopie");
catalog_add(tr("lit_quiz_title"), tr("search_exercise"), "cetba1984quiz",
FALSE, 3, "orwell kviz");
catalog_add("Ladislav Fuks – Spalovač mrtvol", tr("search_book"),
"cetbaFuks", FALSE, 2, "fuks cremator");
catalog_add(tr("lit_fuks_quiz_title"), tr("search_exercise"),
"cetbaFuksQuiz", FALSE, 3, "fuks kviz");
cetba_register_search();
{
static const char *mluv_names[] = {
@ -247,6 +252,12 @@ static int cmp_item(gconstpointer a, gconstpointer b) {
static void search_go(const char *target) {
if (!target || !main_stack)
return;
if (strncmp(target, "cetbastub:", 10) == 0) {
int idx = atoi(target + 10);
search_close();
cetba_open_stub(idx);
return;
}
if (!gtk_stack_get_child_by_name(main_stack, target))
return;
search_close();