mirror of https://github.com/daleclack/My_GtkUi
Update MineSweeper app
This commit is contained in:
parent
8bdcbeb9d3
commit
33196352f7
|
@ -30,7 +30,8 @@ set(SOURCES src/core/main.cpp src/core/MainWin.cpp src/core/MyStack.cpp
|
|||
src/calc_app/CalcApp.cpp src/run_app/RunApp.cpp src/draw_app/DrawApp.cpp
|
||||
src/game24_app/Game24.cpp src/game24_app/Game24App.cpp src/text_app/TextEditor.cpp
|
||||
src/text_app/MyInfoBar.cpp src/image_app/ImageApp.cpp src/image_app/MyImage.cpp
|
||||
src/mine_app/MineSweeper.cpp src/mine_app/MineCell.cpp)
|
||||
src/mine_app/MineSweeper.cpp src/mine_app/MineCell.cpp src/mine_app/InputBox.cpp
|
||||
src/mine_app/ScoresItem.cpp src/mine_app/ScoresWin.cpp)
|
||||
|
||||
#Compile resources with GCR_CMake
|
||||
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
#include <vector>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include "InputBox.h"
|
||||
#include "ScoresWin.h"
|
||||
#include "jsonfile.h"
|
||||
|
||||
struct _InputBox
|
||||
{
|
||||
GtkWindow parent_instance;
|
||||
GtkWidget *main_box, *btn_box;
|
||||
GtkWidget *entry_name;
|
||||
GtkWidget *scores_check;
|
||||
GtkWidget *btn_ok, *btn_cancel;
|
||||
int game_time;
|
||||
|
||||
// Scores Window
|
||||
ScoresWin *scores_win;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(InputBox, input_box, GTK_TYPE_WINDOW)
|
||||
|
||||
static std::vector<std::string> names;
|
||||
static std::vector<int> times;
|
||||
static json data;
|
||||
|
||||
static void btnok_clicked(GtkButton *btn, InputBox *self)
|
||||
{
|
||||
// Save score to json file
|
||||
// Open a file to save json data
|
||||
std::fstream outfile;
|
||||
outfile.open("scores.json", std::ios_base::out);
|
||||
if (outfile.is_open())
|
||||
{
|
||||
// Insert data to json
|
||||
const char *c_name = gtk_editable_get_text(GTK_EDITABLE(self->entry_name));
|
||||
std::string name = std::string(c_name);
|
||||
names.push_back(name);
|
||||
times.push_back(self->game_time);
|
||||
data["name"] = names;
|
||||
data["time"] = times;
|
||||
|
||||
// Output data
|
||||
outfile << data;
|
||||
}
|
||||
outfile.close();
|
||||
|
||||
// Show Scores window
|
||||
if (gtk_check_button_get_active(GTK_CHECK_BUTTON(self->scores_check)))
|
||||
{
|
||||
scores_win_update_and_show(self->scores_win);
|
||||
}
|
||||
gtk_window_close(GTK_WINDOW(self));
|
||||
}
|
||||
|
||||
static gboolean input_box_closed(GtkWidget *win, InputBox *self)
|
||||
{
|
||||
// Hide the window
|
||||
gtk_widget_set_visible(win, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void input_box_init(InputBox *self)
|
||||
{
|
||||
// Initalize window
|
||||
gtk_window_set_default_size(GTK_WINDOW(self), 300, 150);
|
||||
gtk_window_set_icon_name(GTK_WINDOW(self), "mines_app");
|
||||
|
||||
// Create widgets
|
||||
self->main_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
|
||||
self->btn_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
|
||||
self->entry_name = gtk_entry_new();
|
||||
self->scores_check = gtk_check_button_new_with_label("Show scores window");
|
||||
self->btn_ok = gtk_button_new_with_label("OK");
|
||||
self->btn_cancel = gtk_button_new_with_label("Cancel");
|
||||
|
||||
// Create Scores Window
|
||||
GtkWindow *window = gtk_window_get_transient_for(GTK_WINDOW(self));
|
||||
self->scores_win = scores_win_new(window);
|
||||
|
||||
// Link signals
|
||||
g_signal_connect(self->btn_ok, "clicked", G_CALLBACK(btnok_clicked), self);
|
||||
g_signal_connect(self, "close-request", G_CALLBACK(input_box_closed), self);
|
||||
g_signal_connect_swapped(self->btn_cancel, "clicked", G_CALLBACK(gtk_window_close), self);
|
||||
|
||||
// Pack widgets
|
||||
gtk_box_append(GTK_BOX(self->main_box), self->entry_name);
|
||||
gtk_box_append(GTK_BOX(self->main_box), self->scores_check);
|
||||
gtk_box_append(GTK_BOX(self->btn_box), self->btn_ok);
|
||||
gtk_box_append(GTK_BOX(self->btn_box), self->btn_cancel);
|
||||
gtk_box_append(GTK_BOX(self->main_box), self->btn_box);
|
||||
gtk_widget_set_margin_bottom(self->main_box, 10);
|
||||
gtk_widget_set_margin_end(self->main_box, 10);
|
||||
gtk_widget_set_margin_start(self->main_box, 10);
|
||||
gtk_widget_set_margin_top(self->main_box, 10);
|
||||
gtk_widget_set_halign(self->btn_box, GTK_ALIGN_END);
|
||||
// gtk_widget_set_halign(self->main_box, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_valign(self->main_box, GTK_ALIGN_CENTER);
|
||||
gtk_window_set_child(GTK_WINDOW(self), self->main_box);
|
||||
}
|
||||
|
||||
static void input_box_class_init(InputBoxClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
InputBox *input_box_new(GtkWindow *parent)
|
||||
{
|
||||
return Input_Box(g_object_new(input_box_get_type(),
|
||||
"transient-for", parent, NULL));
|
||||
}
|
||||
|
||||
void input_box_present(InputBox *self)
|
||||
{
|
||||
// Show the input box
|
||||
gtk_window_present(GTK_WINDOW(self));
|
||||
}
|
||||
|
||||
void input_box_set_game_time(InputBox *self, int time)
|
||||
{
|
||||
// Try to open json file
|
||||
std::fstream jsonfile;
|
||||
jsonfile.open("scores.json", std::ios_base::in);
|
||||
|
||||
// If json file opened, read the data
|
||||
if (jsonfile.is_open())
|
||||
{
|
||||
data = json::parse(jsonfile);
|
||||
std::vector<std::string> names1 = data["name"];
|
||||
std::vector<int> times1 = data["time"];
|
||||
names = names1;
|
||||
times = times1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwist, create json data
|
||||
data = json::parse(R"(
|
||||
{
|
||||
"name":[" "],
|
||||
"time":[0]
|
||||
}
|
||||
)");
|
||||
}
|
||||
jsonfile.close();
|
||||
|
||||
// Set game time for input box
|
||||
self->game_time = time;
|
||||
}
|
||||
|
||||
void input_box_show_scores(InputBox *self)
|
||||
{
|
||||
scores_win_update_and_show(self->scores_win);
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_DECLARE_FINAL_TYPE(InputBox, input_box, Input, Box, GtkWindow)
|
||||
|
||||
InputBox *input_box_new(GtkWindow *parent);
|
||||
|
||||
void input_box_set_game_time(InputBox *self, int time);
|
||||
|
||||
void input_box_present(InputBox *self);
|
||||
|
||||
void input_box_show_scores(InputBox *self);
|
|
@ -1,5 +1,6 @@
|
|||
#include "MineSweeper.h"
|
||||
#include "MineCell.h"
|
||||
#include "InputBox.h"
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
|
||||
|
@ -16,6 +17,10 @@ struct _MineSweeper
|
|||
{
|
||||
GtkApplicationWindow parent_instance;
|
||||
|
||||
// Header widgets
|
||||
GtkWidget *header, *menu_btn;
|
||||
GtkBuilder *menu_builder;
|
||||
|
||||
// Child widgets
|
||||
GtkWidget *main_box, *btn_box;
|
||||
GtkWidget *mine_grid;
|
||||
|
@ -28,6 +33,9 @@ struct _MineSweeper
|
|||
gboolean started;
|
||||
int mines_clear, mine_count;
|
||||
GameStatus game_status;
|
||||
|
||||
// InputBox for game win
|
||||
InputBox *input_box;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(MineSweeper, mine_sweeper, GTK_TYPE_APPLICATION_WINDOW)
|
||||
|
@ -170,9 +178,9 @@ static void mine_sweeper_check_mines(MineSweeper *self, int pos_x, int pos_y)
|
|||
self->game_status = GameStatus::Winned;
|
||||
self->started = FALSE;
|
||||
|
||||
// // Save the time of game
|
||||
// input_dialog->set_game_time(timer_count);
|
||||
// input_dialog->show();
|
||||
// Save the time of game
|
||||
input_box_set_game_time(self->input_box, self->time_count);
|
||||
input_box_present(self->input_box);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -244,9 +252,13 @@ static gboolean time_func(gpointer data)
|
|||
{
|
||||
MineSweeper *mine_app = MINE_SWEEPER(data);
|
||||
char tmp[50];
|
||||
// Update time when game is running
|
||||
if (mine_app->game_status == GameStatus::Running)
|
||||
{
|
||||
(mine_app->time_count)++;
|
||||
sprintf(tmp, "Time:%d", mine_app->time_count);
|
||||
gtk_label_set_label(GTK_LABEL(mine_app->time_label), tmp);
|
||||
}
|
||||
return mine_app->started;
|
||||
}
|
||||
|
||||
|
@ -284,16 +296,67 @@ static void btnshow_clicked(GtkButton *btn, MineSweeper *self)
|
|||
}
|
||||
}
|
||||
|
||||
// Signal Handler for menus
|
||||
static void newgame_activated(GSimpleAction *action, GVariant *parmeter, gpointer data)
|
||||
{
|
||||
btnstart_clicked(NULL, MINE_SWEEPER(data));
|
||||
}
|
||||
|
||||
static void scores_activated(GSimpleAction *action, GVariant *parmeter, gpointer data)
|
||||
{
|
||||
MineSweeper *app = MINE_SWEEPER(data);
|
||||
input_box_show_scores(app->input_box);
|
||||
}
|
||||
|
||||
static void showmines_activated(GSimpleAction *action, GVariant *parmeter, gpointer data)
|
||||
{
|
||||
btnshow_clicked(NULL, MINE_SWEEPER(data));
|
||||
}
|
||||
|
||||
static void quit_activated(GSimpleAction *action, GVariant *parmeter, gpointer data)
|
||||
{
|
||||
gtk_window_destroy(GTK_WINDOW(data));
|
||||
}
|
||||
|
||||
static void mine_sweeper_init(MineSweeper *self)
|
||||
{
|
||||
// Initalize window
|
||||
gtk_window_set_title(GTK_WINDOW(self), "MineSweeper");
|
||||
gtk_window_set_icon_name(GTK_WINDOW(self), "mine_app");
|
||||
self->header = gtk_header_bar_new();
|
||||
gtk_window_set_titlebar(GTK_WINDOW(self), self->header);
|
||||
|
||||
// Add action for menu
|
||||
GActionEntry entries[] =
|
||||
{
|
||||
{"new_game", newgame_activated, NULL, NULL, NULL},
|
||||
{"scores", scores_activated, NULL, NULL, NULL},
|
||||
{"show_mines", showmines_activated, NULL, NULL, NULL},
|
||||
{"quit", quit_activated, NULL, NULL, NULL}};
|
||||
g_action_map_add_action_entries(G_ACTION_MAP(self), entries,
|
||||
G_N_ELEMENTS(entries), self);
|
||||
|
||||
// Create Menu and button
|
||||
self->menu_btn = gtk_menu_button_new();
|
||||
gtk_menu_button_set_icon_name(GTK_MENU_BUTTON(self->menu_btn), "open-menu");
|
||||
gtk_header_bar_pack_end(GTK_HEADER_BAR(self->header), self->menu_btn);
|
||||
|
||||
// Create Menu
|
||||
self->menu_builder = gtk_builder_new_from_resource("/org/gtk/daleclack/mine_menu.xml");
|
||||
GMenuModel *model = G_MENU_MODEL(gtk_builder_get_object(self->menu_builder, "mine_menu"));
|
||||
gtk_menu_button_set_menu_model(GTK_MENU_BUTTON(self->menu_btn), model);
|
||||
GtkPopover *popover = gtk_menu_button_get_popover(GTK_MENU_BUTTON(self->menu_btn));
|
||||
gtk_popover_set_has_arrow(popover, FALSE);
|
||||
gtk_widget_set_halign(GTK_WIDGET(popover), GTK_ALIGN_END);
|
||||
|
||||
// Create Input Box
|
||||
self->input_box = input_box_new(GTK_WINDOW(self));
|
||||
|
||||
// Create widgets
|
||||
self->main_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
|
||||
self->mine_grid = gtk_grid_new();
|
||||
self->time_label = gtk_label_new("");
|
||||
self->status_label = gtk_label_new("Game not started");
|
||||
self->status_label = gtk_label_new("");
|
||||
self->btn_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
|
||||
self->btn_start = gtk_button_new_with_label("Start/Reset");
|
||||
self->btn_show = gtk_button_new_with_label("Show All");
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
#include "ScoresItem.h"
|
||||
|
||||
struct _ScoresItem
|
||||
{
|
||||
GObject parent_instance;
|
||||
char name[NAME_MAX];
|
||||
int time;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(ScoresItem, scores_item, G_TYPE_OBJECT)
|
||||
|
||||
static void scores_item_init(ScoresItem *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void scores_item_class_init(ScoresItemClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
ScoresItem *scores_item_new(const char *win_name, int win_time)
|
||||
{
|
||||
ScoresItem *item = Scores_Item(g_object_new(scores_item_get_type(), NULL));
|
||||
strncpy(item->name, win_name, NAME_MAX);
|
||||
item->time = win_time;
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
const char *scores_item_get_name(ScoresItem *item)
|
||||
{
|
||||
return item->name;
|
||||
}
|
||||
|
||||
void scores_item_set_name(ScoresItem *item, const char *win_name)
|
||||
{
|
||||
strncpy(item->name, win_name, NAME_MAX);
|
||||
}
|
||||
|
||||
int scores_item_get_time(ScoresItem *item)
|
||||
{
|
||||
return item->time;
|
||||
}
|
||||
|
||||
void scores_item_set_time(ScoresItem *item, int win_time)
|
||||
{
|
||||
item->time = win_time;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_DECLARE_FINAL_TYPE(ScoresItem, scores_item, Scores, Item, GObject)
|
||||
|
||||
ScoresItem *scores_item_new(const char *win_name, int win_time);
|
||||
|
||||
const char *scores_item_get_name(ScoresItem *item);
|
||||
|
||||
void scores_item_set_name(ScoresItem *item, const char *win_name);
|
||||
|
||||
int scores_item_get_time(ScoresItem *item);
|
||||
|
||||
void scores_item_set_time(ScoresItem *item, int win_time);
|
|
@ -0,0 +1,181 @@
|
|||
#include "jsonfile.h"
|
||||
#include "ScoresWin.h"
|
||||
#include "ScoresItem.h"
|
||||
#include <fstream>
|
||||
|
||||
struct _ScoresWin
|
||||
{
|
||||
GtkWindow parent;
|
||||
// Child widgets
|
||||
GtkWidget *scrolled_win;
|
||||
GtkWidget *main_box;
|
||||
GtkWidget *btn_close;
|
||||
|
||||
// List widgets
|
||||
GtkWidget *list_view;
|
||||
GtkSingleSelection *selection;
|
||||
GtkListItemFactory *factory_name, *factory_time;
|
||||
GtkColumnViewColumn *column_name, *column_time;
|
||||
GListStore *store;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(ScoresWin, scores_win, GTK_TYPE_WINDOW)
|
||||
|
||||
static gboolean scores_win_closed(GtkWidget *window, ScoresWin *self)
|
||||
{
|
||||
gtk_widget_set_visible(window, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void btnclose_clicked(GtkButton *btn, GtkWindow *self)
|
||||
{
|
||||
gtk_window_close(self);
|
||||
}
|
||||
|
||||
static void name_factory_setup(GtkSignalListItemFactory *factory,
|
||||
GtkListItem *item)
|
||||
{
|
||||
GtkWidget *label = gtk_label_new("");
|
||||
gtk_list_item_set_child(item, label);
|
||||
}
|
||||
|
||||
static void name_factory_bind(GtkListItemFactory *factory,
|
||||
GtkListItem *item)
|
||||
{
|
||||
// Get child
|
||||
GtkWidget *label;
|
||||
label = gtk_list_item_get_child(item);
|
||||
|
||||
// Get Item
|
||||
ScoresItem *item1 = Scores_Item(gtk_list_item_get_item(item));
|
||||
gtk_label_set_label(GTK_LABEL(label),
|
||||
scores_item_get_name(item1));
|
||||
}
|
||||
|
||||
static void time_factory_setup(GtkSignalListItemFactory *factory,
|
||||
GtkListItem *item)
|
||||
{
|
||||
GtkWidget *label = gtk_label_new("");
|
||||
gtk_list_item_set_child(item, label);
|
||||
}
|
||||
|
||||
static void time_factory_bind(GtkListItemFactory *factory,
|
||||
GtkListItem *item)
|
||||
{
|
||||
// Get child
|
||||
GtkWidget *label;
|
||||
label = gtk_list_item_get_child(item);
|
||||
|
||||
// Get Item
|
||||
ScoresItem *item1 = Scores_Item(gtk_list_item_get_item(item));
|
||||
char *time_str = g_strdup_printf("%d", scores_item_get_time(item1));
|
||||
gtk_label_set_label(GTK_LABEL(label), time_str);
|
||||
}
|
||||
|
||||
static gint sort_func(gpointer a, gpointer b, gpointer user_data)
|
||||
{
|
||||
ScoresItem *item_a = Scores_Item(a);
|
||||
ScoresItem *item_b = Scores_Item(b);
|
||||
int time_a = scores_item_get_time(item_a);
|
||||
int time_b = scores_item_get_time(item_b);
|
||||
|
||||
// Return result
|
||||
if (time_a > time_b)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (time_a == time_b)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (time_a < time_b)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void scores_win_init(ScoresWin *self)
|
||||
{
|
||||
// Initalize window
|
||||
gtk_window_set_title(GTK_WINDOW(self), "Scores");
|
||||
gtk_window_set_icon_name(GTK_WINDOW(self), "mines_app");
|
||||
|
||||
// Create widgets
|
||||
self->main_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
|
||||
self->scrolled_win = gtk_scrolled_window_new();
|
||||
self->btn_close = gtk_button_new_with_label("Close");
|
||||
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(self->scrolled_win),
|
||||
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
||||
gtk_widget_set_size_request(self->scrolled_win, 300, 400);
|
||||
gtk_widget_set_halign(self->btn_close, GTK_ALIGN_CENTER);
|
||||
|
||||
// Link signals
|
||||
g_signal_connect(self->btn_close, "clicked", G_CALLBACK(btnclose_clicked), self);
|
||||
g_signal_connect(self, "close-request", G_CALLBACK(scores_win_closed), self);
|
||||
|
||||
// Create store
|
||||
self->store = g_list_store_new(scores_item_get_type());
|
||||
self->selection = gtk_single_selection_new(G_LIST_MODEL(self->store));
|
||||
|
||||
// Create Column View
|
||||
self->list_view = gtk_column_view_new(GTK_SELECTION_MODEL(self->selection));
|
||||
|
||||
// Create factory for name
|
||||
self->factory_name = gtk_signal_list_item_factory_new();
|
||||
g_signal_connect(self->factory_name, "bind", G_CALLBACK(name_factory_bind), NULL);
|
||||
g_signal_connect(self->factory_name, "setup", G_CALLBACK(name_factory_setup), NULL);
|
||||
self->column_name = gtk_column_view_column_new("Name", self->factory_name);
|
||||
gtk_column_view_append_column(GTK_COLUMN_VIEW(self->list_view), self->column_name);
|
||||
|
||||
// Create factory for time
|
||||
self->factory_time = gtk_signal_list_item_factory_new();
|
||||
g_signal_connect(self->factory_time, "bind", G_CALLBACK(time_factory_bind), NULL);
|
||||
g_signal_connect(self->factory_time, "setup", G_CALLBACK(time_factory_setup), NULL);
|
||||
self->column_time = gtk_column_view_column_new("Time", self->factory_time);
|
||||
gtk_column_view_append_column(GTK_COLUMN_VIEW(self->list_view), self->column_time);
|
||||
|
||||
// Pack widgets
|
||||
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(self->scrolled_win), self->list_view);
|
||||
gtk_box_append(GTK_BOX(self->main_box), self->scrolled_win);
|
||||
gtk_box_append(GTK_BOX(self->main_box), self->btn_close);
|
||||
gtk_window_set_child(GTK_WINDOW(self), self->main_box);
|
||||
}
|
||||
|
||||
static void scores_win_class_init(ScoresWinClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
ScoresWin *scores_win_new(GtkWindow *parent)
|
||||
{
|
||||
return Scores_Win(g_object_new(scores_win_get_type(),
|
||||
"transient-for", parent, NULL));
|
||||
}
|
||||
|
||||
void scores_win_update_and_show(ScoresWin *self)
|
||||
{
|
||||
std::fstream infile;
|
||||
infile.open("scores.json", std::ios_base::in);
|
||||
|
||||
if (infile.is_open())
|
||||
{
|
||||
// Read data from json file
|
||||
json data = json::parse(infile);
|
||||
std::vector<std::string> name_vec = data["name"];
|
||||
std::vector<int> time_vec = data["time"];
|
||||
|
||||
// Clear the store
|
||||
g_list_store_remove_all(self->store);
|
||||
|
||||
// Append data to the store
|
||||
for (int i = 0; i < name_vec.size(); i++)
|
||||
{
|
||||
g_list_store_append(self->store,
|
||||
scores_item_new(name_vec[i].c_str(), time_vec[i]));
|
||||
}
|
||||
g_list_store_sort(self->store, (GCompareDataFunc)sort_func, NULL);
|
||||
}
|
||||
gtk_window_present(GTK_WINDOW(self));
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_DECLARE_FINAL_TYPE(ScoresWin, scores_win, Scores, Win, GtkWindow)
|
||||
|
||||
ScoresWin *scores_win_new(GtkWindow *parent);
|
||||
|
||||
void scores_win_update_and_show(ScoresWin *self);
|
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../json_nlohmann/json.hpp"
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
using json = nlohmann::json;
|
Loading…
Reference in New Issue