From b61ed7b631b596f7c87c944b781df43835da6355 Mon Sep 17 00:00:00 2001 From: Eric House Date: Sat, 5 Jan 2013 21:01:26 -0800 Subject: [PATCH] opening saved games and saving of changes now work. --- xwords4/linux/gamesdb.c | 54 +++++++++++++++++++++++++++---------- xwords4/linux/gamesdb.h | 2 +- xwords4/linux/gtkboard.c | 18 ++++++++++--- xwords4/linux/gtkmain.c | 56 ++++++++++++++++++++++++++++++++++++--- xwords4/linux/linuxmain.c | 2 +- xwords4/linux/main.h | 3 ++- 6 files changed, 111 insertions(+), 24 deletions(-) diff --git a/xwords4/linux/gamesdb.c b/xwords4/linux/gamesdb.c index de8589ae3..dedbdc525 100644 --- a/xwords4/linux/gamesdb.c +++ b/xwords4/linux/gamesdb.c @@ -55,29 +55,37 @@ writeToDB( XWStreamCtxt* stream, void* closure ) { int result; CommonGlobals* cGlobals = (CommonGlobals*)closure; - sqlite3_int64 rowid = cGlobals->rowid; + sqlite3_int64 selRow = cGlobals->selRow; sqlite3* pDb = cGlobals->pDb; XP_U16 len = stream_getSize( stream ); + char buf[256]; + char* query; sqlite3_stmt* stmt = NULL; - if ( 0 == rowid ) { /* new row; need to insert blob first */ - const char* txt = "INSERT INTO games (game) VALUES (?)"; - result = sqlite3_prepare_v2( pDb, txt, -1, &stmt, NULL ); - XP_ASSERT( SQLITE_OK == result ); - result = sqlite3_bind_zeroblob( stmt, 1 /*col 0 ??*/, len ); - XP_ASSERT( SQLITE_OK == result ); - result = sqlite3_step( stmt ); - XP_ASSERT( SQLITE_DONE == result ); + if ( -1 == selRow ) { /* new row; need to insert blob first */ + query = "INSERT INTO games (game) VALUES (?)"; + } else { + const char* fmt = "UPDATE games SET game=? where rowid=%lld"; + snprintf( buf, sizeof(buf), fmt, selRow ); + query = buf; + } - rowid = sqlite3_last_insert_rowid( pDb ); - XP_LOGF( "%s: new rowid: %lld", __func__, rowid ); - cGlobals->rowid = rowid; - sqlite3_finalize( stmt ); + result = sqlite3_prepare_v2( pDb, query, -1, &stmt, NULL ); + XP_ASSERT( SQLITE_OK == result ); + result = sqlite3_bind_zeroblob( stmt, 1 /*col 0 ??*/, len ); + XP_ASSERT( SQLITE_OK == result ); + result = sqlite3_step( stmt ); + XP_ASSERT( SQLITE_DONE == result ); + + if ( -1 == selRow ) { /* new row; need to insert blob first */ + selRow = sqlite3_last_insert_rowid( pDb ); + XP_LOGF( "%s: new rowid: %lld", __func__, selRow ); + cGlobals->selRow = selRow; } sqlite3_blob* blob; result = sqlite3_blob_open( pDb, "main", "games", "game", - rowid, 1 /*flags: writeable*/, &blob ); + selRow, 1 /*flags: writeable*/, &blob ); XP_ASSERT( SQLITE_OK == result ); const XP_U8* ptr = stream_getPtr( stream ); result = sqlite3_blob_write( blob, ptr, len, 0 ); @@ -128,3 +136,21 @@ getGameName( GTKGamesGlobals* XP_UNUSED(gg), const sqlite3_int64* rowid, snprintf( buf, len, "Game %lld", *rowid ); LOG_RETURNF( "%s", buf ); } + +XP_Bool +loadGame( XWStreamCtxt* stream, sqlite3* pDb, sqlite3_int64 rowid ) +{ + char buf[256]; + snprintf( buf, sizeof(buf), "SELECT game from games WHERE rowid = %lld", rowid ); + + sqlite3_stmt *ppStmt; + int result = sqlite3_prepare_v2( pDb, buf, -1, &ppStmt, NULL ); + XP_ASSERT( SQLITE_OK == result ); + result = sqlite3_step( ppStmt ); + XP_ASSERT( SQLITE_ROW == result ); + const void* ptr = sqlite3_column_blob( ppStmt, 0 ); + int size = sqlite3_column_bytes( ppStmt, 0 ); + stream_putBytes( stream, ptr, size ); + sqlite3_finalize( ppStmt ); + return XP_TRUE; +} diff --git a/xwords4/linux/gamesdb.h b/xwords4/linux/gamesdb.h index 5a6a4d067..bbda321f4 100644 --- a/xwords4/linux/gamesdb.h +++ b/xwords4/linux/gamesdb.h @@ -36,6 +36,6 @@ void writeToDB( XWStreamCtxt* stream, void* closure ); GSList* listGames( GTKGamesGlobals* gg ); void getGameName( GTKGamesGlobals* gg, const sqlite3_int64* rowid, XP_UCHAR* buf, XP_U16 len ); - +XP_Bool loadGame( XWStreamCtxt* stream, sqlite3* pDb, sqlite3_int64 rowid ); #endif diff --git a/xwords4/linux/gtkboard.c b/xwords4/linux/gtkboard.c index 87267d110..2d9b6ceb7 100644 --- a/xwords4/linux/gtkboard.c +++ b/xwords4/linux/gtkboard.c @@ -63,6 +63,7 @@ #include "gtkdraw.h" #include "memstream.h" #include "filestream.h" +#include "gamesdb.h" /* static guint gtkSetupClientSocket( GtkAppGlobals* globals, int sock ); */ static void setCtrlsForTray( GtkAppGlobals* globals ); @@ -396,7 +397,8 @@ createOrLoadObjects( GtkAppGlobals* globals ) #ifndef XWFEATURE_STANDALONE_ONLY #endif - LaunchParams* params = globals->cGlobals.params; + CommonGlobals* cGlobals = &globals->cGlobals; + LaunchParams* params = cGlobals->params; globals->draw = (GtkDrawCtx*)gtkDrawCtxtMake( globals->drawing_area, globals ); @@ -415,11 +417,19 @@ createOrLoadObjects( GtkAppGlobals* globals ) }; if ( !!params->fileName && file_exists( params->fileName ) ) { - stream = streamFromFile( &globals->cGlobals, params->fileName, globals ); + stream = streamFromFile( cGlobals, params->fileName, globals ); #ifdef USE_SQLITE } else if ( !!params->dbFileName && file_exists( params->dbFileName ) ) { - stream = streamFromDB( &globals->cGlobals, globals ); + stream = streamFromDB( cGlobals, globals ); #endif + } else if ( !!cGlobals->pDb && 0 <= cGlobals->selRow ) { + stream = mem_stream_make( MPPARM(params->util->mpool) + params->vtMgr, + cGlobals, CHANNEL_NONE, NULL ); + if ( !loadGame( stream, cGlobals->pDb, cGlobals->selRow ) ) { + stream_destroy( stream ); + stream = NULL; + } } if ( !!stream ) { @@ -2501,6 +2511,8 @@ makeNewGame( GtkAppGlobals* globals ) globals->cGlobals.params->dict = linux_dictionary_make( MEMPOOL globals->cGlobals.params, gi->dictName, XP_TRUE ); + } else { + success = XP_FALSE; } return success; } diff --git a/xwords4/linux/gtkmain.c b/xwords4/linux/gtkmain.c index dfcc374f8..1952ddbb3 100644 --- a/xwords4/linux/gtkmain.c +++ b/xwords4/linux/gtkmain.c @@ -27,9 +27,29 @@ enum { ROW_ITEM, NAME_ITEM, N_ITEMS }; -static void -init_games_list( GtkWidget* list ) +/* Prototype for selection handler callback */ +static void +tree_selection_changed_cb( GtkTreeSelection* selection, gpointer data ) { + LOG_FUNC(); + GTKGamesGlobals* gg = (GTKGamesGlobals*)data; + + GtkTreeIter iter; + GtkTreeModel *model; + gchar *row; + + if ( gtk_tree_selection_get_selected( selection, &model, &iter ) ) { + gtk_tree_model_get( model, &iter, ROW_ITEM, &row, -1 ); + sscanf( row, "%lld", &gg->selRow ); + g_print ("You selected row %s (parsed: %lld)\n", row, gg->selRow ); + g_free( row ); + } +} + +static GtkWidget* +init_games_list( GTKGamesGlobals* gg ) +{ + GtkWidget* list = gtk_tree_view_new(); GtkCellRenderer* renderer = gtk_cell_renderer_text_new(); GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes( "Row", renderer, "text", @@ -45,6 +65,13 @@ init_games_list( GtkWidget* list ) G_TYPE_STRING, G_TYPE_STRING ); gtk_tree_view_set_model( GTK_TREE_VIEW(list), GTK_TREE_MODEL(store) ); g_object_unref( store ); + + GtkTreeSelection* select = + gtk_tree_view_get_selection( GTK_TREE_VIEW (list) ); + gtk_tree_selection_set_mode( select, GTK_SELECTION_SINGLE ); + g_signal_connect( G_OBJECT(select), "changed", + G_CALLBACK (tree_selection_changed_cb), gg ); + return list; } static void @@ -77,10 +104,25 @@ handle_newgame_button( GtkWidget* XP_UNUSED(widget), void* closure ) } else { GtkWidget* gameWindow = globals->window; globals->cGlobals.pDb = gg->pDb; + globals->cGlobals.selRow = -1; gtk_widget_show( gameWindow ); } } +static void +handle_open_button( GtkWidget* XP_UNUSED(widget), void* closure ) +{ + GTKGamesGlobals* gg = (GTKGamesGlobals*)closure; + if ( -1 != gg->selRow ) { + gg->params->needsNewGame = XP_FALSE; + GtkAppGlobals* globals = malloc( sizeof(*globals) ); + initGlobals( globals, gg->params ); + globals->cGlobals.pDb = gg->pDb; + globals->cGlobals.selRow = gg->selRow; + gtk_widget_show( globals->window ); + } +} + static void handle_quit_button( GtkWidget* XP_UNUSED(widget), gpointer data ) { @@ -111,9 +153,9 @@ makeGamesWindow( GTKGamesGlobals* gg ) GtkWidget* vbox = gtk_vbox_new( FALSE, 0 ); gtk_container_add( GTK_CONTAINER(window), vbox ); gtk_widget_show( vbox ); - GtkWidget* list = gtk_tree_view_new(); + GtkWidget* list = init_games_list( gg ); gtk_container_add( GTK_CONTAINER(vbox), list ); - init_games_list( list ); + gtk_widget_show( list ); GSList* games = listGames( gg ); @@ -134,6 +176,11 @@ makeGamesWindow( GTKGamesGlobals* gg ) G_CALLBACK(handle_newgame_button), gg ); gtk_widget_show( button ); + button = gtk_button_new_with_label( "Open" ); + gtk_container_add( GTK_CONTAINER(hbox), button ); + g_signal_connect( GTK_OBJECT(button), "clicked", + G_CALLBACK(handle_open_button), gg ); + gtk_widget_show( button ); button = gtk_button_new_with_label( "Quit" ); gtk_container_add( GTK_CONTAINER(hbox), button ); g_signal_connect( GTK_OBJECT(button), "clicked", @@ -148,6 +195,7 @@ int gtkmain( LaunchParams* params ) { GTKGamesGlobals gg = {0}; + gg.selRow = -1; gg.params = params; XP_LOGF( "%s: I'M HERE!!! (calling makeGamesDB())", __func__ ); gg.pDb = openGamesDB(); diff --git a/xwords4/linux/linuxmain.c b/xwords4/linux/linuxmain.c index bbb4cd3e1..9392a4620 100644 --- a/xwords4/linux/linuxmain.c +++ b/xwords4/linux/linuxmain.c @@ -261,7 +261,7 @@ saveGame( CommonGlobals* cGlobals ) if ( !!cGlobals->params->fileName || !!cGlobals->pDb ) { XP_Bool doSave = XP_TRUE; XP_Bool newGame = !file_exists( cGlobals->params->fileName ) - || 0 == cGlobals->rowid; + || -1 == cGlobals->selRow; /* don't fail to save first time! */ if ( 0 < cGlobals->params->saveFailPct && !newGame ) { XP_U16 pct = XP_RANDOM() % 100; diff --git a/xwords4/linux/main.h b/xwords4/linux/main.h index bb8af4fa0..0c63eee7f 100644 --- a/xwords4/linux/main.h +++ b/xwords4/linux/main.h @@ -169,11 +169,11 @@ struct CommonGlobals { CommonPrefs cp; XWGame game; - sqlite3_int64 rowid; XP_U16 lastNTilesToUse; XP_U16 lastStreamSize; XP_Bool manualFinal; /* use asked for final scores */ sqlite3* pDb; + sqlite3_int64 selRow; SocketChangedFunc socketChanged; void* socketChangedClosure; @@ -211,6 +211,7 @@ struct CommonGlobals { typedef struct _GTKGamesGlobals { sqlite3* pDb; + sqlite3_int64 selRow; LaunchParams* params; } GTKGamesGlobals;