Add Scores Window
This commit is contained in:
parent
311d1e1d21
commit
3a3b3fe59b
|
@ -26,7 +26,8 @@ link_directories (${GTK4_LIBRARY_DIRS})
|
|||
# set(PO_DIR ${CMAKE_BINARY_DIR}/po/zh_CN/LC_MESSAGES)
|
||||
|
||||
#Source files
|
||||
set(SOURCE_FILE src/main.cpp src/MineSweeper.cpp src/MineCell.cpp src/InputBox.cpp)
|
||||
set(SOURCE_FILE src/main.cpp src/MineSweeper.cpp src/MineCell.cpp
|
||||
src/InputBox.cpp src/ScoresItem.cpp src/ScoresWin.cpp)
|
||||
|
||||
#Compile Resource
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <string>
|
||||
#include <fstream>
|
||||
#include "InputBox.h"
|
||||
#include "ScoresWin.h"
|
||||
#include "jsonfile.h"
|
||||
|
||||
struct _InputBox
|
||||
|
@ -12,6 +13,9 @@ struct _InputBox
|
|||
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)
|
||||
|
@ -42,7 +46,10 @@ static void btnok_clicked(GtkButton *btn, InputBox *self)
|
|||
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));
|
||||
}
|
||||
|
||||
|
@ -57,6 +64,7 @@ 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), "org.gtk.daleclack");
|
||||
|
||||
// Create widgets
|
||||
self->main_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
|
||||
|
@ -66,6 +74,10 @@ static void input_box_init(InputBox *self)
|
|||
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);
|
||||
|
@ -133,3 +145,8 @@ void input_box_set_game_time(InputBox *self, int time)
|
|||
// 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);
|
||||
}
|
||||
|
|
|
@ -9,3 +9,5 @@ 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);
|
||||
|
|
|
@ -304,6 +304,8 @@ static void newgame_activated(GSimpleAction *action, GVariant *parmeter, gpointe
|
|||
|
||||
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)
|
||||
|
|
|
@ -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);
|
|
@ -1,80 +0,0 @@
|
|||
#include "ScoresWin.hh"
|
||||
|
||||
ScoresWin::ScoresWin(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Builder> &ref_Glade)
|
||||
: Gtk::Window(cobject),
|
||||
ref_builder(ref_Glade)
|
||||
{
|
||||
// Get Widgets
|
||||
btnclose = ref_builder->get_widget<Gtk::Button>("btnclose");
|
||||
tree_view = ref_builder->get_widget<Gtk::TreeView>("scores_view");
|
||||
btnclose->signal_clicked().connect(sigc::mem_fun(*this, &ScoresWin::hide));
|
||||
|
||||
// Create the list store
|
||||
store = Gtk::ListStore::create(column1);
|
||||
store->set_sort_column(column1.win_time, Gtk::SortType::ASCENDING);
|
||||
store->set_sort_func(column1.win_time, sigc::mem_fun(*this, &ScoresWin::sort_func));
|
||||
// store->set_default_sort_func(sigc::mem_fun(*this, &ScoresWin::sort_func));
|
||||
tree_view->set_model(store);
|
||||
tree_view->append_column("name", column1.player_name);
|
||||
tree_view->append_column("time", column1.win_time);
|
||||
}
|
||||
|
||||
void ScoresWin::update_and_show()
|
||||
{
|
||||
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
|
||||
store->clear();
|
||||
|
||||
// Append data to the store
|
||||
for (int i = 0; i < name_vec.size(); i++)
|
||||
{
|
||||
auto row = *(store->append());
|
||||
row[column1.player_name] = name_vec[i];
|
||||
row[column1.win_time] = time_vec[i];
|
||||
}
|
||||
}
|
||||
|
||||
show();
|
||||
}
|
||||
|
||||
int ScoresWin::sort_func(const Gtk::TreeModel::const_iterator &iter1, const Gtk::TreeModel::const_iterator &iter2)
|
||||
{
|
||||
// Sort by the game time
|
||||
auto row1 = *iter1;
|
||||
auto row2 = *iter2;
|
||||
if (row1[column1.win_time] < row2[column1.win_time])
|
||||
{
|
||||
// g_print("test1\n");
|
||||
return -1;
|
||||
}
|
||||
if (row1[column1.win_time] == row2[column1.win_time])
|
||||
{
|
||||
// g_print("test2\n");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
ScoresWin *ScoresWin::create()
|
||||
{
|
||||
// Create a window
|
||||
auto builder = Gtk::Builder::create_from_resource("/org/gtk/daleclack/scoreswin.ui");
|
||||
ScoresWin *main_win;
|
||||
|
||||
// builder->get_widget_derived("scores_win", main_win);
|
||||
main_win = Gtk::Builder::get_widget_derived<ScoresWin>(builder, "scores_win");
|
||||
|
||||
return main_win;
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
#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), "org.gtk.daleclack");
|
||||
|
||||
// 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");
|
||||
g_signal_connect(self->btn_close, "clicked", G_CALLBACK(btnclose_clicked), self);
|
||||
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);
|
||||
|
||||
// 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);
|
|
@ -1,35 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include "jsonfile.hh"
|
||||
|
||||
class ScoresWin : public Gtk::Window{
|
||||
public:
|
||||
static ScoresWin *create();
|
||||
ScoresWin(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Builder> &ref_Glade);
|
||||
void update_and_show();
|
||||
|
||||
private:
|
||||
Glib::RefPtr<Gtk::Builder> ref_builder;
|
||||
|
||||
// Child widgets
|
||||
Gtk::Button *btnclose;
|
||||
Gtk::TreeView *tree_view;
|
||||
|
||||
// TreeView data
|
||||
class ModelColumns : public Gtk::TreeModelColumnRecord{
|
||||
public:
|
||||
ModelColumns(){
|
||||
add(player_name);
|
||||
add(win_time);
|
||||
}
|
||||
Gtk::TreeModelColumn<std::string> player_name;
|
||||
Gtk::TreeModelColumn<int> win_time;
|
||||
};
|
||||
ModelColumns column1;
|
||||
|
||||
Glib::RefPtr<Gtk::ListStore> store;
|
||||
|
||||
// Sort function
|
||||
int sort_func(const Gtk::TreeModel::const_iterator &iter1, const Gtk::TreeModel::const_iterator &iter2);
|
||||
};
|
Loading…
Reference in New Issue