mirror of
https://github.com/pepaskopec-blip/Graduately.git
synced 2026-10-27 15:14:35 +00:00
Fix path layout and Czech stats, and rewrite the install docs.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
737e27deb0
commit
2cb3565df5
16 changed files with 349 additions and 869 deletions
Binary file not shown.
|
Before Width: | Height: | Size: 339 KiB After Width: | Height: | Size: 53 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 442 KiB After Width: | Height: | Size: 63 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 242 KiB After Width: | Height: | Size: 35 KiB |
26
czech.c
26
czech.c
|
|
@ -62,19 +62,27 @@ void czech_rail_theme_reset(void) {
|
|||
gtk_widget_queue_draw(cz_rail);
|
||||
}
|
||||
|
||||
static GtkWidget *cz_make_node(int index) {
|
||||
static GtkWidget *cz_make_node(int index, gboolean locked) {
|
||||
GtkWidget *btn;
|
||||
GtkWidget *label;
|
||||
|
||||
btn = gtk_button_new();
|
||||
gtk_widget_add_css_class(btn, "unit-node");
|
||||
gtk_widget_add_css_class(btn, "current");
|
||||
gtk_widget_set_can_focus(btn, FALSE);
|
||||
gtk_widget_set_size_request(btn, (int)CZ_BUBBLE, (int)CZ_BUBBLE);
|
||||
|
||||
label = gtk_label_new(cz_initials[index]);
|
||||
gtk_widget_add_css_class(label, "unit-number");
|
||||
gtk_button_set_child(GTK_BUTTON(btn), label);
|
||||
if (locked) {
|
||||
gtk_widget_add_css_class(btn, "locked");
|
||||
gtk_widget_set_sensitive(btn, FALSE);
|
||||
gtk_button_set_child(GTK_BUTTON(btn),
|
||||
icon_area_new(draw_lock_icon,
|
||||
0.3451, 0.3569, 0.4392, 26));
|
||||
} else {
|
||||
GtkWidget *label = gtk_label_new(cz_initials[index]);
|
||||
|
||||
gtk_widget_add_css_class(btn, "current");
|
||||
gtk_widget_add_css_class(label, "unit-number");
|
||||
gtk_button_set_child(GTK_BUTTON(btn), label);
|
||||
}
|
||||
|
||||
return btn;
|
||||
}
|
||||
|
|
@ -126,7 +134,9 @@ GtkWidget *build_czechmap_page(void) {
|
|||
cz_rail = rail;
|
||||
|
||||
for (int i = 0; i < CZ_NODES; i++) {
|
||||
GtkWidget *btn = cz_make_node(i);
|
||||
/* Literatura has no lessons yet; keep the node visible but locked. */
|
||||
gboolean locked = (i == 0);
|
||||
GtkWidget *btn = cz_make_node(i, locked);
|
||||
GtkWidget *name = gtk_label_new(NULL);
|
||||
|
||||
if (i == 2) {
|
||||
|
|
@ -146,6 +156,8 @@ GtkWidget *build_czechmap_page(void) {
|
|||
gtk_label_set_wrap(GTK_LABEL(name), TRUE);
|
||||
gtk_widget_add_css_class(name, "unit-name");
|
||||
gtk_widget_add_css_class(name, "cz-label");
|
||||
if (locked)
|
||||
gtk_widget_add_css_class(name, "unit-name-locked");
|
||||
|
||||
gtk_fixed_put(GTK_FIXED(fixed), btn, 0, 0);
|
||||
gtk_fixed_put(GTK_FIXED(fixed), name, 0, 0);
|
||||
|
|
|
|||
1
hw.c
1
hw.c
|
|
@ -366,6 +366,7 @@ GtkWidget *build_hwmap_page(void) {
|
|||
g_signal_connect(va, "notify::page-size",
|
||||
G_CALLBACK(hw_adjust_notify), NULL);
|
||||
|
||||
hw_apply_layout();
|
||||
hw_relayout_later();
|
||||
refresh_hw_completion_ui();
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ mkdir -p "$DEST_DIR"
|
|||
tmp=$(mktemp -d)
|
||||
trap 'rm -rf "$tmp"' EXIT INT TERM
|
||||
|
||||
say "Downloading the latest release..."
|
||||
say "Downloading the latest build..."
|
||||
curl -fL --progress-bar -o "$tmp/$ASSET" "$URL" ||
|
||||
die "the download failed. Check your internet connection."
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ fi
|
|||
tmp=$(mktemp -d)
|
||||
trap 'rm -rf "$tmp"' EXIT INT TERM
|
||||
|
||||
say "Downloading the latest release..."
|
||||
say "Downloading the latest build..."
|
||||
curl -fL --progress-bar -o "$tmp/$ASSET" "$URL" ||
|
||||
die "the download failed. Check your internet connection."
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ set "TMP_DIR=%TEMP%\maturita-installer"
|
|||
rmdir /s /q "%TMP_DIR%" 2>nul
|
||||
mkdir "%TMP_DIR%" || goto :fail_tmp
|
||||
|
||||
echo Downloading the latest release...
|
||||
echo Downloading the latest build...
|
||||
curl -fL --progress-bar -o "%TMP_DIR%\%ASSET%" "%URL%" || goto :fail_download
|
||||
|
||||
echo Installing to %DEST%
|
||||
|
|
|
|||
148
main.c
148
main.c
|
|
@ -310,6 +310,129 @@ static void setup_window_icon(GtkWindow *window) {
|
|||
G_CALLBACK(on_window_realize_icon), NULL);
|
||||
}
|
||||
|
||||
static gboolean open_settings_later(gpointer data) {
|
||||
(void)data;
|
||||
settings_open();
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static gboolean save_window_png(const char *path) {
|
||||
GtkWidget *widget;
|
||||
int width, height;
|
||||
GdkPaintable *paintable;
|
||||
GtkSnapshot *snapshot;
|
||||
GskRenderNode *node;
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *cr;
|
||||
cairo_status_t st;
|
||||
|
||||
if (!main_window || !path || !path[0])
|
||||
return FALSE;
|
||||
|
||||
widget = GTK_WIDGET(main_window);
|
||||
width = gtk_widget_get_width(widget);
|
||||
height = gtk_widget_get_height(widget);
|
||||
if (width < 80 || height < 80)
|
||||
return FALSE;
|
||||
|
||||
paintable = gtk_widget_paintable_new(widget);
|
||||
snapshot = gtk_snapshot_new();
|
||||
gdk_paintable_snapshot(paintable, snapshot, width, height);
|
||||
node = gtk_snapshot_free_to_node(snapshot);
|
||||
g_object_unref(paintable);
|
||||
if (!node)
|
||||
return FALSE;
|
||||
|
||||
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
|
||||
cr = cairo_create(surface);
|
||||
gsk_render_node_draw(node, cr);
|
||||
gsk_render_node_unref(node);
|
||||
cairo_destroy(cr);
|
||||
st = cairo_surface_write_to_png(surface, path);
|
||||
cairo_surface_destroy(surface);
|
||||
return st == CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void smoke_quit(int code) {
|
||||
GtkApplication *app = main_window
|
||||
? gtk_window_get_application(main_window) : NULL;
|
||||
|
||||
if (app)
|
||||
g_application_quit(G_APPLICATION(app));
|
||||
else
|
||||
exit(code);
|
||||
}
|
||||
|
||||
static gboolean shot_later(gpointer data) {
|
||||
const char *path = g_getenv("MATURITA_SHOT");
|
||||
int *tries = data;
|
||||
|
||||
if (!save_window_png(path)) {
|
||||
if (tries && *tries < 20) {
|
||||
(*tries)++;
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
g_printerr("MATURITA_SHOT: could not capture window\n");
|
||||
smoke_quit(1);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
if (g_getenv("MATURITA_SHOT_QUIT"))
|
||||
smoke_quit(0);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static gboolean run_smoke_test(gpointer data) {
|
||||
static const char *pages[] = {
|
||||
"welcome", "subjects", "roadmap", "stats",
|
||||
"netyears", "netmap", "hwmap", "czechmap",
|
||||
"mluvnice", "readinglist",
|
||||
"cetba1984", "cetba1984quiz", "cetba1984dej",
|
||||
"cetbaFuks", "cetbaFuksQuiz", "cetbaFuksDej",
|
||||
"hwunit1", "hwex1", "hwunit2", "hwex2", "hwunit3", "hwex3",
|
||||
"unit1", "unit2", "unit3",
|
||||
"u1e1", "u1e13", "u2e1", "u2e19", "u3e1", "u3e15",
|
||||
"u1vocab", "u2vocab", "u3vocab",
|
||||
"mluve1", "mluve20",
|
||||
"netunit1", "netex1", "netunit10", "netex10",
|
||||
"netunit27", "netex27",
|
||||
NULL
|
||||
};
|
||||
const char *report = g_getenv("MATURITA_SMOKE");
|
||||
FILE *f;
|
||||
int missing = 0;
|
||||
int i;
|
||||
|
||||
(void)data;
|
||||
f = report && report[0] ? fopen(report, "w") : stdout;
|
||||
if (!f) {
|
||||
g_printerr("MATURITA_SMOKE: cannot write %s\n", report);
|
||||
smoke_quit(1);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
fprintf(f, "commit=%s\n", APP_COMMIT);
|
||||
fprintf(f, "css=%s\n",
|
||||
g_file_test(CSS_FILE, G_FILE_TEST_IS_REGULAR) ? "ok" : "MISSING");
|
||||
fprintf(f, "progress_dir=%s\n", app_progress_dir ? app_progress_dir : "?");
|
||||
|
||||
for (i = 0; pages[i]; i++) {
|
||||
GtkWidget *child = gtk_stack_get_child_by_name(main_stack, pages[i]);
|
||||
|
||||
if (child) {
|
||||
fprintf(f, "OK %s\n", pages[i]);
|
||||
} else {
|
||||
fprintf(f, "MISSING %s\n", pages[i]);
|
||||
missing++;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(f, "missing=%d\n", missing);
|
||||
if (f != stdout)
|
||||
fclose(f);
|
||||
smoke_quit(missing ? 1 : 0);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
void activate(GtkApplication *app, gpointer user_data) {
|
||||
GtkWindow *window;
|
||||
GtkWidget *headerbar;
|
||||
|
|
@ -463,7 +586,18 @@ void activate(GtkApplication *app, gpointer user_data) {
|
|||
}
|
||||
}
|
||||
|
||||
gtk_stack_set_visible_child_name(main_stack, "welcome");
|
||||
{
|
||||
const char *start = g_getenv("MATURITA_PAGE");
|
||||
const char *size = g_getenv("MATURITA_SIZE");
|
||||
int w, h;
|
||||
|
||||
if (start && *start)
|
||||
gtk_stack_set_visible_child_name(main_stack, start);
|
||||
else
|
||||
gtk_stack_set_visible_child_name(main_stack, "welcome");
|
||||
if (size && sscanf(size, "%dx%d", &w, &h) == 2)
|
||||
gtk_window_set_default_size(window, w, h);
|
||||
}
|
||||
|
||||
refresh_completion_ui();
|
||||
|
||||
|
|
@ -482,6 +616,18 @@ void activate(GtkApplication *app, gpointer user_data) {
|
|||
update_init();
|
||||
|
||||
gtk_window_present(window);
|
||||
|
||||
if (g_getenv("MATURITA_SETTINGS"))
|
||||
g_timeout_add(350, open_settings_later, NULL);
|
||||
if (g_getenv("MATURITA_SMOKE"))
|
||||
g_timeout_add(200, run_smoke_test, NULL);
|
||||
if (g_getenv("MATURITA_SHOT")) {
|
||||
static int shot_tries;
|
||||
|
||||
shot_tries = 0;
|
||||
g_timeout_add(g_getenv("MATURITA_SETTINGS") ? 700 : 400,
|
||||
shot_later, &shot_tries);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
|
|
|||
|
|
@ -839,6 +839,7 @@ void mluvnice_init(void);
|
|||
GtkWidget *build_mluvnice_page(void);
|
||||
GtkWidget *build_mluvnice_exercise_page(int n);
|
||||
void mluvnice_refresh_ui(void);
|
||||
void progress_for_mluvnice(ProgressSum *out);
|
||||
GtkWidget *build_readinglist_page(void);
|
||||
GtkWidget *build_cetba1984_page(void);
|
||||
GtkWidget *build_cetba1984_quiz_page(void);
|
||||
|
|
@ -1124,6 +1125,7 @@ GtkWidget *make_theme_card(ThemeId id, GtkToggleButton *group);
|
|||
void on_settings_clicked(GtkButton *button, gpointer user_data);
|
||||
GtkWidget *build_stats_button(void);
|
||||
GtkWidget *build_settings_button(void);
|
||||
void settings_open(void);
|
||||
void unit_meta_init(void);
|
||||
void unit_configure(int idx, const char *const *names, int n);
|
||||
GtkWidget *build_exercise_page(UnitCtx *u, int n);
|
||||
|
|
|
|||
13
mluvnice.c
13
mluvnice.c
|
|
@ -71,6 +71,19 @@ void mluvnice_init(void) {
|
|||
unit_load_progress(&mluv_unit);
|
||||
}
|
||||
|
||||
void progress_for_mluvnice(ProgressSum *out) {
|
||||
int d;
|
||||
|
||||
if (!out || mluv_unit.n_ex <= 0)
|
||||
return;
|
||||
d = unit_done_count(&mluv_unit);
|
||||
out->total_ex += mluv_unit.n_ex;
|
||||
out->open_units += 1;
|
||||
out->done_ex += d;
|
||||
if (d == mluv_unit.n_ex)
|
||||
out->done_units++;
|
||||
}
|
||||
|
||||
void mluvnice_refresh_ui(void) {
|
||||
for (int i = 0; i < mluv_unit.n_ex; i++) {
|
||||
GtkWidget *btn = mluv_unit.ex_cells[i];
|
||||
|
|
|
|||
1
net.c
1
net.c
|
|
@ -687,6 +687,7 @@ GtkWidget *build_netmap_page(void) {
|
|||
g_signal_connect(va, "notify::page-size",
|
||||
G_CALLBACK(net_adjust_notify), NULL);
|
||||
|
||||
net_apply_layout();
|
||||
net_relayout_later();
|
||||
refresh_net_completion_ui();
|
||||
|
||||
|
|
|
|||
|
|
@ -401,6 +401,7 @@ GtkWidget *build_roadmap_page(void) {
|
|||
g_signal_connect(va, "notify::page-size",
|
||||
G_CALLBACK(road_adjust_notify), NULL);
|
||||
|
||||
road_apply_layout();
|
||||
road_relayout_later();
|
||||
|
||||
return page;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,13 @@
|
|||
/* Settings */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static GtkWidget *settings_popover;
|
||||
|
||||
void settings_open(void) {
|
||||
if (settings_popover)
|
||||
gtk_popover_popup(GTK_POPOVER(settings_popover));
|
||||
}
|
||||
|
||||
void draw_theme_swatch(GtkDrawingArea *area, cairo_t *cr,
|
||||
int width, int height, gpointer data) {
|
||||
ThemeId id = (ThemeId)GPOINTER_TO_INT(data);
|
||||
|
|
@ -215,6 +222,7 @@ GtkWidget *build_settings_button(void) {
|
|||
G_CALLBACK(gtk_widget_queue_draw), icon);
|
||||
|
||||
popover = gtk_popover_new();
|
||||
settings_popover = popover;
|
||||
gtk_widget_add_css_class(popover, "settings-popover");
|
||||
gtk_popover_set_has_arrow(GTK_POPOVER(popover), TRUE);
|
||||
gtk_popover_set_position(GTK_POPOVER(popover), GTK_POS_BOTTOM);
|
||||
|
|
|
|||
4
stats.c
4
stats.c
|
|
@ -69,6 +69,8 @@ void refresh_stats_ui(void) {
|
|||
progress_for_net(&all);
|
||||
else if (s == HW_SUBJ)
|
||||
progress_for_hw(&all);
|
||||
else if (s == CZ_SUBJ)
|
||||
progress_for_mluvnice(&all);
|
||||
else
|
||||
progress_for_units(sub_unit_start[s], sub_unit_count[s], &all);
|
||||
}
|
||||
|
|
@ -106,6 +108,8 @@ void refresh_stats_ui(void) {
|
|||
progress_for_net(&sp);
|
||||
else if (s == HW_SUBJ)
|
||||
progress_for_hw(&sp);
|
||||
else if (s == CZ_SUBJ)
|
||||
progress_for_mluvnice(&sp);
|
||||
else
|
||||
progress_for_units(sub_unit_start[s], sub_unit_count[s], &sp);
|
||||
if (has_content) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue