mirror of
https://github.com/pepaskopec-blip/Graduately.git
synced 2026-10-27 15:14:35 +00:00
Wire quiz and plot practice for every reading-list stub book.
GTK stubs now open shared kvíz/děj pages from generated packs; Mac book screens keep practice above notes with stable titles. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
cf136ca936
commit
a9ce04bb3b
8 changed files with 29889 additions and 27 deletions
|
|
@ -1074,20 +1074,6 @@ struct BookScreen: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !notes.isEmpty {
|
|
||||||
VStack(alignment: .leading, spacing: 14) {
|
|
||||||
Text(vm.tr("book_notes"))
|
|
||||||
#if os(macOS)
|
|
||||||
.font(.title.weight(.semibold))
|
|
||||||
#else
|
|
||||||
.font(.title2.weight(.semibold))
|
|
||||||
#endif
|
|
||||||
ForEach(Array(notes.enumerated()), id: \.offset) { _, note in
|
|
||||||
BookNoteCard(note: note)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if hasQuiz || hasPlot {
|
if hasQuiz || hasPlot {
|
||||||
VStack(alignment: .leading, spacing: 14) {
|
VStack(alignment: .leading, spacing: 14) {
|
||||||
Text(vm.tr("book_practice"))
|
Text(vm.tr("book_practice"))
|
||||||
|
|
@ -1099,8 +1085,8 @@ struct BookScreen: View {
|
||||||
if hasQuiz {
|
if hasQuiz {
|
||||||
NavigationLink(value: Route.bookQuiz(id)) {
|
NavigationLink(value: Route.bookQuiz(id)) {
|
||||||
BookActionCard(
|
BookActionCard(
|
||||||
title: vm.tr(b.str("quizTitle")),
|
title: vm.tr("book_quiz_heading"),
|
||||||
subtitle: vm.tr(b.str("quizSub")),
|
subtitle: vm.tr("lit_quiz_sub"),
|
||||||
systemImage: "questionmark.circle.fill",
|
systemImage: "questionmark.circle.fill",
|
||||||
done: quizDone,
|
done: quizDone,
|
||||||
doneLabel: vm.tr("book_done")
|
doneLabel: vm.tr("book_done")
|
||||||
|
|
@ -1111,8 +1097,8 @@ struct BookScreen: View {
|
||||||
if hasPlot {
|
if hasPlot {
|
||||||
NavigationLink(value: Route.bookPlot(id)) {
|
NavigationLink(value: Route.bookPlot(id)) {
|
||||||
BookActionCard(
|
BookActionCard(
|
||||||
title: vm.tr(b.str("plotTitle")),
|
title: vm.tr("lit_plot_title"),
|
||||||
subtitle: vm.tr(b.str("plotSub")),
|
subtitle: vm.tr("lit_plot_sub"),
|
||||||
systemImage: "list.number",
|
systemImage: "list.number",
|
||||||
done: plotDone,
|
done: plotDone,
|
||||||
doneLabel: vm.tr("book_done")
|
doneLabel: vm.tr("book_done")
|
||||||
|
|
@ -1122,6 +1108,20 @@ struct BookScreen: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !notes.isEmpty {
|
||||||
|
VStack(alignment: .leading, spacing: 14) {
|
||||||
|
Text(vm.tr("book_notes"))
|
||||||
|
#if os(macOS)
|
||||||
|
.font(.title.weight(.semibold))
|
||||||
|
#else
|
||||||
|
.font(.title2.weight(.semibold))
|
||||||
|
#endif
|
||||||
|
ForEach(Array(notes.enumerated()), id: \.offset) { _, note in
|
||||||
|
BookNoteCard(note: note)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
.padding(28)
|
.padding(28)
|
||||||
|
|
|
||||||
|
|
@ -1241,7 +1241,7 @@ def main() -> int:
|
||||||
"subKey": "cetba1984_sub" if quiz else "cetba_entry_sub",
|
"subKey": "cetba1984_sub" if quiz else "cetba_entry_sub",
|
||||||
"page": page if not entry.get("full") else (entry.get("page") or page),
|
"page": page if not entry.get("full") else (entry.get("page") or page),
|
||||||
"genre": entry.get("genre", ""),
|
"genre": entry.get("genre", ""),
|
||||||
"quizTitle": f"Kvíz: {display}" if quiz else "",
|
"quizTitle": "book_quiz_heading" if quiz else "",
|
||||||
"quizSub": "lit_quiz_sub" if quiz else "",
|
"quizSub": "lit_quiz_sub" if quiz else "",
|
||||||
"plotTitle": "lit_plot_title" if plot else "",
|
"plotTitle": "lit_plot_title" if plot else "",
|
||||||
"plotSub": "lit_plot_sub" if plot else "",
|
"plotSub": "lit_plot_sub" if plot else "",
|
||||||
|
|
@ -1336,7 +1336,7 @@ def main() -> int:
|
||||||
return s.replace("\\", "\\\\").replace('"', '\\"')
|
return s.replace("\\", "\\\\").replace('"', '\\"')
|
||||||
|
|
||||||
notes_lines = [
|
notes_lines = [
|
||||||
"/* Generated from data/cetba/*.json – do not edit by hand. */",
|
"/* Generated from data/cetba JSON packs – do not edit by hand. */",
|
||||||
"",
|
"",
|
||||||
"typedef struct {",
|
"typedef struct {",
|
||||||
" const char *title;",
|
" const char *title;",
|
||||||
|
|
@ -1386,6 +1386,96 @@ def main() -> int:
|
||||||
notes_lines.append("")
|
notes_lines.append("")
|
||||||
(SRC / "cetba_book_notes.inc").write_text("\n".join(notes_lines) + "\n", encoding="utf-8")
|
(SRC / "cetba_book_notes.inc").write_text("\n".join(notes_lines) + "\n", encoding="utf-8")
|
||||||
|
|
||||||
|
# Quiz + plot packs for the GTK stub pages (shared by every catalog book).
|
||||||
|
ex_lines = [
|
||||||
|
"/* Generated from data/cetba JSON packs – do not edit by hand. */",
|
||||||
|
"/* Requires LitQ (cetba.c) and AssemblyItem (maturita.h). */",
|
||||||
|
"",
|
||||||
|
"typedef struct {",
|
||||||
|
" const LitQ *qs;",
|
||||||
|
" int nq;",
|
||||||
|
" const AssemblyItem *plot;",
|
||||||
|
" const char **plot_meaning;",
|
||||||
|
" int nplot;",
|
||||||
|
"} BookExPack;",
|
||||||
|
"",
|
||||||
|
]
|
||||||
|
ex_pack_entries = []
|
||||||
|
for entry in catalog:
|
||||||
|
bid = entry["id"]
|
||||||
|
safe = re.sub(r"[^a-zA-Z0-9_]", "_", bid)
|
||||||
|
content_path = cetba_dir / f"{bid}.json"
|
||||||
|
disk = {}
|
||||||
|
if content_path.exists():
|
||||||
|
disk = json.loads(content_path.read_text(encoding="utf-8"))
|
||||||
|
quiz = disk.get("quiz") or []
|
||||||
|
plot = disk.get("plot") or []
|
||||||
|
plot_meaning = disk.get("plotMeaning") or []
|
||||||
|
|
||||||
|
qs_name = f"book_{safe}_qs"
|
||||||
|
if quiz:
|
||||||
|
ex_lines.append(f"static const LitQ {qs_name}[] = {{")
|
||||||
|
for q in quiz[:32]:
|
||||||
|
opts = (q.get("options") or []) + ["", "", "", ""]
|
||||||
|
ex_lines.append(" {")
|
||||||
|
ex_lines.append(f' "{c_escape(q.get("prompt") or "")}",')
|
||||||
|
ex_lines.append(" {")
|
||||||
|
for o in opts[:4]:
|
||||||
|
ex_lines.append(f' "{c_escape(o)}",')
|
||||||
|
ex_lines.append(" },")
|
||||||
|
ex_lines.append(f' {int(q.get("correct") or 0)},')
|
||||||
|
ex_lines.append(f' "{c_escape(q.get("expl") or "")}",')
|
||||||
|
ex_lines.append(" },")
|
||||||
|
ex_lines.append("};")
|
||||||
|
ex_lines.append("")
|
||||||
|
nq = min(len(quiz), 32)
|
||||||
|
qs_ref = qs_name
|
||||||
|
else:
|
||||||
|
nq = 0
|
||||||
|
qs_ref = "NULL"
|
||||||
|
|
||||||
|
plot_name = f"book_{safe}_plot"
|
||||||
|
mean_name = f"book_{safe}_plot_meaning"
|
||||||
|
if plot and isinstance(plot[0], dict):
|
||||||
|
words = (plot[0].get("words") or [])[:6]
|
||||||
|
while len(words) < 6:
|
||||||
|
words.append("")
|
||||||
|
prompt = plot[0].get("prompt") or "Přetáhněte části příběhu do správného pořadí:"
|
||||||
|
nwords = sum(1 for w in words if w)
|
||||||
|
ex_lines.append(f"static const AssemblyItem {plot_name}[] = {{")
|
||||||
|
ex_lines.append(" {")
|
||||||
|
ex_lines.append(f' "{c_escape(prompt)}",')
|
||||||
|
ex_lines.append(" {")
|
||||||
|
for w in words:
|
||||||
|
ex_lines.append(f' "{c_escape(w)}",')
|
||||||
|
ex_lines.append(" },")
|
||||||
|
ex_lines.append(f" {nwords},")
|
||||||
|
ex_lines.append(" },")
|
||||||
|
ex_lines.append("};")
|
||||||
|
ex_lines.append("")
|
||||||
|
meaning = plot_meaning[0] if plot_meaning else ""
|
||||||
|
ex_lines.append(f"static const char *{mean_name}[] = {{")
|
||||||
|
ex_lines.append(f' "{c_escape(meaning)}",')
|
||||||
|
ex_lines.append("};")
|
||||||
|
ex_lines.append("")
|
||||||
|
plot_ref = plot_name
|
||||||
|
mean_ref = mean_name
|
||||||
|
nplot = 1
|
||||||
|
else:
|
||||||
|
plot_ref = "NULL"
|
||||||
|
mean_ref = "NULL"
|
||||||
|
nplot = 0
|
||||||
|
|
||||||
|
ex_pack_entries.append(
|
||||||
|
f" {{{qs_ref}, {nq}, {plot_ref}, {mean_ref}, {nplot}}}"
|
||||||
|
)
|
||||||
|
|
||||||
|
ex_lines.append("static const BookExPack book_ex_packs[BOOK_NODES] = {")
|
||||||
|
ex_lines.append(",\n".join(ex_pack_entries))
|
||||||
|
ex_lines.append("};")
|
||||||
|
ex_lines.append("")
|
||||||
|
(SRC / "cetba_book_exercises.inc").write_text("\n".join(ex_lines) + "\n", encoding="utf-8")
|
||||||
|
|
||||||
subjects = [
|
subjects = [
|
||||||
{"key": "Deutsch", "open": True, "target": "roadmap", "icon": "de"},
|
{"key": "Deutsch", "open": True, "target": "roadmap", "icon": "de"},
|
||||||
{"key": "Správa počítačových sítí", "open": True, "target": "netyears", "icon": "wifi"},
|
{"key": "Správa počítačových sítí", "open": True, "target": "netyears", "icon": "wifi"},
|
||||||
|
|
|
||||||
135
src/cetba.c
135
src/cetba.c
|
|
@ -876,7 +876,9 @@ static void lit_quiz_show(LitQuiz *z) {
|
||||||
gtk_widget_set_visible(z->grid, TRUE);
|
gtk_widget_set_visible(z->grid, TRUE);
|
||||||
gtk_widget_set_visible(z->expl, FALSE);
|
gtk_widget_set_visible(z->expl, FALSE);
|
||||||
gtk_widget_set_visible(z->next, FALSE);
|
gtk_widget_set_visible(z->next, FALSE);
|
||||||
|
gtk_button_set_label(GTK_BUTTON(z->next), tr("lit_next"));
|
||||||
z->answered = 0;
|
z->answered = 0;
|
||||||
|
z->finished = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lit_quiz_finish(LitQuiz *z) {
|
static void lit_quiz_finish(LitQuiz *z) {
|
||||||
|
|
@ -1049,6 +1051,7 @@ static GtkWidget *lit_quiz_page(const LitQ *qs, int n, const char *back,
|
||||||
|
|
||||||
lit_quiz_show(z);
|
lit_quiz_show(z);
|
||||||
|
|
||||||
|
g_object_set_data(G_OBJECT(page), "lit-quiz", z);
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1129,8 +1132,10 @@ GtkWidget *build_cetba_fuks_plot_page(void) {
|
||||||
/* Reading list and 1984 overview */
|
/* Reading list and 1984 overview */
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
static GtkWidget *lit_link_card(const char *target, const char *title,
|
static GtkWidget *lit_link_card_ex(const char *target, const char *title,
|
||||||
const char *sub, GtkDrawingAreaDrawFunc icon) {
|
const char *sub,
|
||||||
|
GtkDrawingAreaDrawFunc icon,
|
||||||
|
GCallback clicked) {
|
||||||
GtkWidget *btn = gtk_button_new();
|
GtkWidget *btn = gtk_button_new();
|
||||||
GtkWidget *row = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 14);
|
GtkWidget *row = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 14);
|
||||||
GtkWidget *ic;
|
GtkWidget *ic;
|
||||||
|
|
@ -1165,11 +1170,18 @@ static GtkWidget *lit_link_card(const char *target, const char *title,
|
||||||
|
|
||||||
gtk_box_append(GTK_BOX(row), box);
|
gtk_box_append(GTK_BOX(row), box);
|
||||||
gtk_button_set_child(GTK_BUTTON(btn), row);
|
gtk_button_set_child(GTK_BUTTON(btn), row);
|
||||||
g_object_set_data_full(G_OBJECT(btn), "target", g_strdup(target), g_free);
|
if (target)
|
||||||
g_signal_connect(btn, "clicked", G_CALLBACK(on_nav_clicked), NULL);
|
g_object_set_data_full(G_OBJECT(btn), "target", g_strdup(target), g_free);
|
||||||
|
g_signal_connect(btn, "clicked",
|
||||||
|
clicked ? clicked : G_CALLBACK(on_nav_clicked), NULL);
|
||||||
return btn;
|
return btn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GtkWidget *lit_link_card(const char *target, const char *title,
|
||||||
|
const char *sub, GtkDrawingAreaDrawFunc icon) {
|
||||||
|
return lit_link_card_ex(target, title, sub, icon, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static void lit_note_card(GtkWidget *parent, const char *title,
|
static void lit_note_card(GtkWidget *parent, const char *title,
|
||||||
GtkDrawingAreaDrawFunc icon,
|
GtkDrawingAreaDrawFunc icon,
|
||||||
const char *const *lines) {
|
const char *const *lines) {
|
||||||
|
|
@ -1213,10 +1225,73 @@ static void lit_note_card(GtkWidget *parent, const char *title,
|
||||||
|
|
||||||
#include "cetba_catalog.inc"
|
#include "cetba_catalog.inc"
|
||||||
#include "cetba_book_notes.inc"
|
#include "cetba_book_notes.inc"
|
||||||
|
#include "cetba_book_exercises.inc"
|
||||||
|
|
||||||
static int stub_book_idx = -1;
|
static int stub_book_idx = -1;
|
||||||
static GtkWidget *stub_title_lbl;
|
static GtkWidget *stub_title_lbl;
|
||||||
|
static GtkWidget *stub_links_box;
|
||||||
static GtkWidget *stub_notes_box;
|
static GtkWidget *stub_notes_box;
|
||||||
|
static LitQuiz *stub_quiz;
|
||||||
|
static GtkWidget *stub_plot_host;
|
||||||
|
static UnitCtx stub_plot_unit;
|
||||||
|
|
||||||
|
static void cetba_prepare_stub_quiz(void) {
|
||||||
|
const BookExPack *p;
|
||||||
|
|
||||||
|
if (!stub_quiz || stub_book_idx < 0 || stub_book_idx >= BOOK_NODES)
|
||||||
|
return;
|
||||||
|
p = &book_ex_packs[stub_book_idx];
|
||||||
|
if (!p->qs || p->nq <= 0)
|
||||||
|
return;
|
||||||
|
stub_quiz->qs = p->qs;
|
||||||
|
stub_quiz->n = p->nq;
|
||||||
|
stub_quiz->idx = 0;
|
||||||
|
stub_quiz->score = 0;
|
||||||
|
stub_quiz->answered = 0;
|
||||||
|
stub_quiz->finished = 0;
|
||||||
|
lit_quiz_show(stub_quiz);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cetba_prepare_stub_plot(void) {
|
||||||
|
GtkWidget *child;
|
||||||
|
const BookExPack *p;
|
||||||
|
GtkWidget *inner;
|
||||||
|
|
||||||
|
if (!stub_plot_host || stub_book_idx < 0 || stub_book_idx >= BOOK_NODES)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while ((child = gtk_widget_get_first_child(stub_plot_host)))
|
||||||
|
gtk_box_remove(GTK_BOX(stub_plot_host), child);
|
||||||
|
|
||||||
|
p = &book_ex_packs[stub_book_idx];
|
||||||
|
if (!p->plot || p->nplot <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
stub_plot_unit.page = "cetbastub";
|
||||||
|
stub_plot_unit.progress_file = app_progress_cetba;
|
||||||
|
inner = build_assembly(&stub_plot_unit, tr("lit_plot_title"),
|
||||||
|
"lit_plot_sub", 1, p->plot, p->plot_meaning,
|
||||||
|
p->nplot);
|
||||||
|
gtk_widget_set_hexpand(inner, TRUE);
|
||||||
|
gtk_widget_set_vexpand(inner, TRUE);
|
||||||
|
gtk_box_append(GTK_BOX(stub_plot_host), inner);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_stub_quiz_clicked(GtkButton *button, gpointer user_data) {
|
||||||
|
(void)button;
|
||||||
|
(void)user_data;
|
||||||
|
cetba_prepare_stub_quiz();
|
||||||
|
if (main_stack)
|
||||||
|
gtk_stack_set_visible_child_name(main_stack, "cetbastubquiz");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_stub_plot_clicked(GtkButton *button, gpointer user_data) {
|
||||||
|
(void)button;
|
||||||
|
(void)user_data;
|
||||||
|
cetba_prepare_stub_plot();
|
||||||
|
if (main_stack)
|
||||||
|
gtk_stack_set_visible_child_name(main_stack, "cetbastubdej");
|
||||||
|
}
|
||||||
|
|
||||||
static GtkWidget *book_rail;
|
static GtkWidget *book_rail;
|
||||||
static GtkWidget *book_nodes[BOOK_NODES];
|
static GtkWidget *book_nodes[BOOK_NODES];
|
||||||
|
|
@ -1338,11 +1413,33 @@ void book_rail_theme_reset(void) {
|
||||||
static void rebuild_stub_about(int idx) {
|
static void rebuild_stub_about(int idx) {
|
||||||
GtkWidget *child;
|
GtkWidget *child;
|
||||||
const BookNotePack *pack;
|
const BookNotePack *pack;
|
||||||
|
const BookExPack *ex;
|
||||||
GtkDrawingAreaDrawFunc icons[4] = {
|
GtkDrawingAreaDrawFunc icons[4] = {
|
||||||
draw_book_icon, draw_globe_icon, draw_people_icon, draw_bulb_icon
|
draw_book_icon, draw_globe_icon, draw_people_icon, draw_bulb_icon
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!stub_notes_box || idx < 0 || idx >= BOOK_NODES)
|
if (idx < 0 || idx >= BOOK_NODES)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (stub_links_box) {
|
||||||
|
while ((child = gtk_widget_get_first_child(stub_links_box)))
|
||||||
|
gtk_box_remove(GTK_BOX(stub_links_box), child);
|
||||||
|
ex = &book_ex_packs[idx];
|
||||||
|
if (ex->qs && ex->nq > 0)
|
||||||
|
gtk_box_append(GTK_BOX(stub_links_box),
|
||||||
|
lit_link_card_ex(NULL, "book_quiz_heading",
|
||||||
|
"lit_quiz_sub", draw_quiz_icon,
|
||||||
|
G_CALLBACK(on_stub_quiz_clicked)));
|
||||||
|
if (ex->plot && ex->nplot > 0)
|
||||||
|
gtk_box_append(GTK_BOX(stub_links_box),
|
||||||
|
lit_link_card_ex(NULL, "lit_plot_title",
|
||||||
|
"lit_plot_sub", draw_order_icon,
|
||||||
|
G_CALLBACK(on_stub_plot_clicked)));
|
||||||
|
gtk_widget_set_visible(stub_links_box,
|
||||||
|
gtk_widget_get_first_child(stub_links_box) != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stub_notes_box)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while ((child = gtk_widget_get_first_child(stub_notes_box)))
|
while ((child = gtk_widget_get_first_child(stub_notes_box)))
|
||||||
|
|
@ -1631,6 +1728,7 @@ GtkWidget *build_cetba_stub_page(void) {
|
||||||
GtkWidget *top;
|
GtkWidget *top;
|
||||||
GtkWidget *center;
|
GtkWidget *center;
|
||||||
GtkWidget *scroll;
|
GtkWidget *scroll;
|
||||||
|
GtkWidget *body;
|
||||||
GtkWidget *sub;
|
GtkWidget *sub;
|
||||||
|
|
||||||
page = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
page = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||||
|
|
@ -1673,12 +1771,37 @@ GtkWidget *build_cetba_stub_page(void) {
|
||||||
gtk_widget_set_margin_bottom(scroll, 14);
|
gtk_widget_set_margin_bottom(scroll, 14);
|
||||||
gtk_box_append(GTK_BOX(page), scroll);
|
gtk_box_append(GTK_BOX(page), scroll);
|
||||||
|
|
||||||
|
body = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||||
|
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(scroll), body);
|
||||||
|
|
||||||
|
stub_links_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 12);
|
||||||
|
gtk_widget_set_margin_bottom(stub_links_box, 14);
|
||||||
|
gtk_box_append(GTK_BOX(body), stub_links_box);
|
||||||
|
|
||||||
stub_notes_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
stub_notes_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||||
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(scroll), stub_notes_box);
|
gtk_box_append(GTK_BOX(body), stub_notes_box);
|
||||||
|
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GtkWidget *build_cetba_stub_quiz_page(void) {
|
||||||
|
const LitQ *qs = book_ex_packs[0].qs;
|
||||||
|
int n = book_ex_packs[0].nq > 0 ? book_ex_packs[0].nq : 1;
|
||||||
|
GtkWidget *page;
|
||||||
|
|
||||||
|
page = lit_quiz_page(qs, n, "cetbastub",
|
||||||
|
"book_quiz_heading", "lit_quiz_sub");
|
||||||
|
stub_quiz = g_object_get_data(G_OBJECT(page), "lit-quiz");
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget *build_cetba_stub_plot_page(void) {
|
||||||
|
stub_plot_host = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||||
|
gtk_widget_set_hexpand(stub_plot_host, TRUE);
|
||||||
|
gtk_widget_set_vexpand(stub_plot_host, TRUE);
|
||||||
|
return stub_plot_host;
|
||||||
|
}
|
||||||
|
|
||||||
void cetba_open_stub(int idx) {
|
void cetba_open_stub(int idx) {
|
||||||
if (idx < 0 || idx >= BOOK_NODES || book_defs[idx].full)
|
if (idx < 0 || idx >= BOOK_NODES || book_defs[idx].full)
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
29642
src/cetba_book_exercises.inc
Normal file
29642
src/cetba_book_exercises.inc
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
||||||
/* Generated from data/cetba/*.json – do not edit by hand. */
|
/* Generated from data/cetba JSON packs – do not edit by hand. */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *title;
|
const char *title;
|
||||||
|
|
|
||||||
|
|
@ -556,6 +556,7 @@ const TrEntry tr_ui[] = {
|
||||||
{"book_practice", "Procvičení", "Practice"},
|
{"book_practice", "Procvičení", "Practice"},
|
||||||
{"book_done", "Hotovo", "Done"},
|
{"book_done", "Hotovo", "Done"},
|
||||||
{"book_open", "Otevřít", "Open"},
|
{"book_open", "Otevřít", "Open"},
|
||||||
|
{"book_quiz_heading", "Kvíz", "Quiz"},
|
||||||
{"book_1984_sub", "Antiutopický román • 1949", "Dystopian novel • 1949"},
|
{"book_1984_sub", "Antiutopický román • 1949", "Dystopian novel • 1949"},
|
||||||
{"cetba1984_sub", "Přehled knihy, klíčové pojmy a cvičení.",
|
{"cetba1984_sub", "Přehled knihy, klíčové pojmy a cvičení.",
|
||||||
"Book overview, key terms and exercises."},
|
"Book overview, key terms and exercises."},
|
||||||
|
|
|
||||||
|
|
@ -520,6 +520,10 @@ void activate(GtkApplication *app, gpointer user_data) {
|
||||||
gtk_stack_add_named(main_stack, build_cetba_fuks_plot_page(),
|
gtk_stack_add_named(main_stack, build_cetba_fuks_plot_page(),
|
||||||
"cetbaFuksDej");
|
"cetbaFuksDej");
|
||||||
gtk_stack_add_named(main_stack, build_cetba_stub_page(), "cetbastub");
|
gtk_stack_add_named(main_stack, build_cetba_stub_page(), "cetbastub");
|
||||||
|
gtk_stack_add_named(main_stack, build_cetba_stub_quiz_page(),
|
||||||
|
"cetbastubquiz");
|
||||||
|
gtk_stack_add_named(main_stack, build_cetba_stub_plot_page(),
|
||||||
|
"cetbastubdej");
|
||||||
gtk_stack_add_named(main_stack, build_hw_unit1_page(), "hwunit1");
|
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_unit1_exercise_page(), "hwex1");
|
||||||
gtk_stack_add_named(main_stack, build_hw_unit2_page(), "hwunit2");
|
gtk_stack_add_named(main_stack, build_hw_unit2_page(), "hwunit2");
|
||||||
|
|
|
||||||
|
|
@ -852,6 +852,8 @@ GtkWidget *build_cetba_fuks_page(void);
|
||||||
GtkWidget *build_cetba_fuks_quiz_page(void);
|
GtkWidget *build_cetba_fuks_quiz_page(void);
|
||||||
GtkWidget *build_cetba_fuks_plot_page(void);
|
GtkWidget *build_cetba_fuks_plot_page(void);
|
||||||
GtkWidget *build_cetba_stub_page(void);
|
GtkWidget *build_cetba_stub_page(void);
|
||||||
|
GtkWidget *build_cetba_stub_quiz_page(void);
|
||||||
|
GtkWidget *build_cetba_stub_plot_page(void);
|
||||||
void cetba_register_search(void);
|
void cetba_register_search(void);
|
||||||
void cetba_open_stub(int idx);
|
void cetba_open_stub(int idx);
|
||||||
void search_catalog_add(const char *title, const char *subtitle,
|
void search_catalog_add(const char *title, const char *subtitle,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue