mupen64plus-oldsvn/main/gui_gtk/rombrowser.c

941 lines
36 KiB
C

/***************************************************************************
rombrowser.c - Handles rombrowser GUI elements
----------------------------------------------------------------------------
Began : Sat Nov 9 2002
Copyright : (C) 2002 by blight, 2008 by Tillin9
****************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "rombrowser.h"
#include "romproperties.h"
#include "main_gtk.h"
#include "../main.h"
#include "../util.h"
#include "../config.h"
#include "../translate.h"
#include "../rom.h"
#include <gtk/gtk.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
/*********************************************************************************************************
* globals
*/
GList *g_RomList = NULL;
static GList *g_RomListCache = NULL; // roms in cache
GdkPixbuf *australia, *europe, *france, *germany, *italy, *japan, *spain, *usa, *japanusa, *n64cart, *star;
static GtkWidget *playRomItem;
static GtkWidget *romPropertiesItem;
static GtkWidget *refreshRomBrowserItem;
static GtkWidget *startNetGameItem;
static int g_iNumRoms = 0;
static int g_iSortColumn = 0; // sort column
static GtkSortType g_SortType = GTK_SORT_ASCENDING; // sort type (ascending/descending)
char *column_names[16] =
{
"Country",
"Good Name",
"Status",
"User Comments",
"File Name",
"MD5 Hash",
"CRC1",
"CRC2",
"Internal Name",
"Save Type",
"Players",
"Size",
"Compression",
"Image Type",
"CIC Chip",
"Rumble",
};
void countrycodeflag(unsigned short int countrycode, GdkPixbuf **flag)
{
switch(countrycode)
{
case 0x41: /* Japan / USA */
*flag = japanusa;
break;
case 0x44: /* Germany */
*flag = germany;
break;
case 0x45: /* USA */
*flag = usa;
break;
case 0x46: /* France */
*flag = france;
break;
case 'I': /* Italy */
*flag = italy;
break;
case 0x4A: /* Japan */
*flag = japan;
break;
case 'S': /* Spain */
*flag = spain;
break;
case 0x55: case 0x59: /* Australia */
*flag = australia;
break;
case 0x50: case 0x58: case 0x20:
case 0x21: case 0x38: case 0x70:
*flag = europe;
break;
default:
*flag = n64cart;
break;
}
}
/*********************************************************************************************************
* rombrowser functions
*/
gint return_zero( GtkTreeModel *model, GtkTreeIter *ptr1, GtkTreeIter *ptr2, gpointer user_data )
{
return 0;
}
// compare function
gint rombrowser_compare( GtkTreeModel *model, GtkTreeIter *ptr1, GtkTreeIter *ptr2, gpointer user_data )
{
short returnvalue;
if(g_MainWindow.romSortColumn==2||g_MainWindow.romSortColumn==11||g_MainWindow.romSortColumn==14)
{
cache_entry *entry1;
cache_entry *entry2;
int item1, item2;
gtk_tree_model_get ( model, ptr1, 22, &entry1, -1 );
gtk_tree_model_get ( model, ptr2, 22, &entry2, -1 );
if(g_MainWindow.romSortColumn==2)
{
item1 = entry1->inientry->status;
item2 = entry2->inientry->status;
}
else if(g_MainWindow.romSortColumn==11)
{
item1 = entry1->romsize;
item2 = entry2->romsize;
}
else if(g_MainWindow.romSortColumn==14)
{
item1 = entry1->cic;
item2 = entry2->cic;
}
if(item1==item2)
returnvalue = 0;
else if(item1>item2)
returnvalue = -1;
else
returnvalue = 1;
}
else
{
gchar *buffer1, *buffer2;
gtk_tree_model_get ( model, ptr1, g_MainWindow.romSortColumn, &buffer1, -1 );
gtk_tree_model_get ( model, ptr2, g_MainWindow.romSortColumn, &buffer2, -1 );
if (buffer1 == NULL && buffer2 == NULL)
returnvalue = 0;
else if (buffer1 == NULL)
returnvalue = 1;
else if (buffer2 == NULL)
returnvalue = -1;
else
returnvalue = strcasecmp(buffer1, buffer2);
if (buffer1)
g_free(buffer1);
if (buffer2)
g_free(buffer2);
}
//If items are equal, fallback on Good Name and then File Name.
if(returnvalue==0&&g_MainWindow.romSortColumn!=1)
{
gchar *buffer1, *buffer2;
gtk_tree_model_get ( model, ptr1, 1, &buffer1, -1 );
gtk_tree_model_get ( model, ptr2, 1, &buffer2, -1 );
if (buffer1 == NULL && buffer2 == NULL)
returnvalue = 0;
else if (buffer1 == NULL)
returnvalue = 1;
else if (buffer2 == NULL)
returnvalue = -1;
else
returnvalue = strcasecmp(buffer1, buffer2);
if (buffer1)
g_free(buffer1);
if (buffer2)
g_free(buffer2);
}
if(returnvalue==0&&g_MainWindow.romSortColumn!=4)
{
gchar *buffer1, *buffer2;
gtk_tree_model_get ( model, ptr1, 4, &buffer1, -1 );
gtk_tree_model_get ( model, ptr2, 4, &buffer2, -1 );
if (buffer1 == NULL && buffer2 == NULL)
returnvalue = 0;
else if (buffer1 == NULL)
returnvalue = 1;
else if (buffer2 == NULL)
returnvalue = -1;
else
returnvalue = strcasecmp(buffer1, buffer2);
if (buffer1)
g_free(buffer1);
if (buffer2)
g_free(buffer2);
}
return returnvalue;
}
char* filefrompath(const char *string)
{
int counter;
char* buffer;
for ( counter = strlen(string); counter > 0; --counter )
{
if(string[counter]=='/')
{
++counter;
break;
}
}
buffer = (char*)malloc((counter+1)*sizeof(char));
strncpy(buffer,string+counter,counter);
buffer[counter] = '\0';
return buffer;
}
void call_rcs(void)
{
g_romcache.rcstask = RCS_RESCAN;
}
//Load a fresh TreeView after re-scanning directories.
void rombrowser_refresh( unsigned int roms, unsigned short clear )
{
int arrayroms;
GtkTreeModel *model;
//If clear flag is set, clear the GUI rombrowser.
if(clear)
{
GtkTreeSelection *selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW(g_MainWindow.romFullList) );
gtk_tree_selection_select_all(selection);
model = gtk_tree_view_get_model ( GTK_TREE_VIEW(g_MainWindow.romFullList) );
gtk_tree_sortable_set_sort_func ( GTK_TREE_SORTABLE(model), g_MainWindow.romSortColumn, return_zero, (gpointer)NULL, (gpointer)NULL );
gtk_list_store_clear( GTK_LIST_STORE(model) );
selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW(g_MainWindow.romDisplay) );
gtk_tree_selection_select_all(selection);
model = gtk_tree_view_get_model ( GTK_TREE_VIEW(g_MainWindow.romDisplay) );
gtk_tree_sortable_set_sort_func ( GTK_TREE_SORTABLE(model), g_MainWindow.romSortColumn, return_zero, (gpointer)NULL, (gpointer)NULL );
gtk_list_store_clear( GTK_LIST_STORE(model) );
}
model = gtk_tree_view_get_model(GTK_TREE_VIEW(g_MainWindow.romFullList));
arrayroms = gtk_tree_model_iter_n_children(model, NULL);
//If there are currently more ROMs in cache than GUi rombrowser, add them.
if(roms>arrayroms)
{
gboolean fullpaths;
GtkTreeIter *iter = (GtkTreeIter *)malloc(sizeof(GtkTreeIter));
char *country, *goodname, *usercomments, *filename, *md5hash, *crc1, *crc2, *internalname, *savetype, *players, *size, *compressiontype, *imagetype, *cicchip, *rumble;
GdkPixbuf *flag;
GdkPixbuf *status[5];
unsigned int romcounter;
int counter;
country = (char*)calloc(32,sizeof(char));
md5hash = (char*)calloc(33,sizeof(char));
crc1 = (char*)calloc(9,sizeof(char));
crc2 = (char*)calloc(9,sizeof(char));
savetype = (char*)calloc(16,sizeof(char));
players = (char*)calloc(16,sizeof(char));
size = (char*)calloc(16,sizeof(char));
compressiontype = (char*)calloc(16,sizeof(char));
imagetype = (char*)calloc(32,sizeof(char));
cicchip = (char*)calloc(16,sizeof(char));
rumble = (char*)calloc(8,sizeof(char));
if(iter==NULL||country==NULL||md5hash==NULL||crc1==NULL||crc2==NULL||size==NULL||compressiontype==NULL||imagetype==NULL||cicchip==NULL)
{
fprintf( stderr, "%s, %c: Out of memory!\n", __FILE__, __LINE__ );
return;
}
fullpaths = config_get_bool( "RomBrowserShowFullPaths", FALSE);
cache_entry *entry;
entry = g_romcache.top;
//Advance cache pointer.
for ( romcounter=0; romcounter < arrayroms; ++romcounter )
{
entry = entry->next;
if((entry==NULL))
{ return; }
}
for ( romcounter=0; (romcounter<roms)&&(entry!=NULL); ++romcounter )
{
countrycodestring(entry->countrycode, country);
countrycodeflag(entry->countrycode, &flag);
goodname = entry->inientry->goodname;
for ( counter = 0; counter < 5; ++counter )
{
if(entry->inientry->status>counter)
status[counter] = star;
else
status[counter] = NULL;
}
usercomments = entry->usercomments;
if(fullpaths)
filename = entry->filename;
else
filename = filefrompath(entry->filename);
for ( counter = 0; counter < 16; ++counter )
sprintf(md5hash+counter*2, "%02X", entry->md5[counter]);
sprintf(crc1, "%08X", entry->crc1);
sprintf(crc2, "%08X", entry->crc2);
internalname=entry->internalname;
savestring(entry->inientry->savetype, savetype);
playersstring(entry->inientry->players, players);
sprintf(size, "%.1f MBits", (float)(entry->romsize / (float)0x20000) );
compressionstring(entry->compressiontype, compressiontype);
imagestring(entry->imagetype, imagetype);
cicstring(entry->cic, cicchip);
rumblestring(entry->inientry->rumble, rumble);
//Actually add entries to TreeModel
model = gtk_tree_view_get_model(GTK_TREE_VIEW(g_MainWindow.romFullList));
gtk_list_store_append ( GTK_LIST_STORE(model), iter);
gtk_list_store_set ( GTK_LIST_STORE(model), iter, 0, country, 1, goodname, 2, NULL, 3, usercomments, 4, filename, 5, md5hash, 6, crc1, 7, crc2, 8, internalname, 9, savetype, 10, players, 11, size, 12, compressiontype, 13, imagetype, 14, cicchip, 15, rumble, 16, status[0], 17, status[1], 18, status[2], 19, status[3], 20, status[4], 21, flag, 22, entry, -1);
model = gtk_tree_view_get_model(GTK_TREE_VIEW(g_MainWindow.romDisplay));
gtk_list_store_append ( GTK_LIST_STORE(model), iter);
gtk_list_store_set ( GTK_LIST_STORE(model), iter, 0, country, 1, goodname, 2, NULL, 3, usercomments, 4, filename, 5, md5hash, 6, crc1, 7, crc2, 8, internalname, 9, savetype, 10, players, 11, size, 12, compressiontype, 13, imagetype, 14, cicchip, 15, rumble, 16, status[0], 17, status[1], 18, status[2], 19, status[3], 20, status[4], 21, flag, 22, entry, -1);
//printf("Added: %s\n", goodname);
entry = entry->next;
}
free(country);
free(md5hash);
free(crc1);
free(crc2);
free(savetype);
free(players);
free(size);
free(compressiontype);
free(imagetype);
free(cicchip);
free(rumble);
if(fullpaths)
free(filename);
free(iter);
//Do an initial sort.
gtk_tree_sortable_set_sort_func ( GTK_TREE_SORTABLE(model), g_MainWindow.romSortColumn, rombrowser_compare, (gpointer)NULL, (gpointer)NULL );
gtk_tree_sortable_set_sort_column_id ( GTK_TREE_SORTABLE(model), g_MainWindow.romSortColumn, g_MainWindow.romSortType );
gtk_tree_view_set_model ( GTK_TREE_VIEW(g_MainWindow.romDisplay), model );
}
}
//We're going our own filtering, but this is a GtkTreeModelFilter function.
//We do filtering manually since GtkTreeModelFilter can not implement automatic
//sorting and GtkTreeModelSort can't implement automatic filtering.
gboolean filter_function( GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
{
const gchar *filter;
filter = gtk_entry_get_text ( GTK_ENTRY(g_MainWindow.filter) );
//printf("Filter: %s\n", filter);
if(g_MainWindow.romSortColumn==2)
{
cache_entry *entry;
gtk_tree_model_get ( model, iter, 22, &entry, -1 );
if(filter[0]=='\0')
return TRUE;
if(atoi(filter)==entry->inientry->status)
return TRUE;
else
return FALSE;
}
char *buffer1, *buffer2;
gboolean returnvalue;
gtk_tree_model_get (model, iter, g_MainWindow.romSortColumn, &buffer1, -1);
//printf("Value %s\n", buffer1);
if(buffer1==NULL||filter==NULL)
returnvalue = TRUE;
else
{
buffer2 = strcasestr( buffer1, filter );
if ( buffer2 != NULL )
returnvalue = TRUE;
else
returnvalue = FALSE;
}
free(buffer1);
return returnvalue;
}
/*********************************************************************************************************
* callbacks
*/
// row double clicked -> play rom
static gboolean callback_rowSelected(GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data)
{
GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW(g_MainWindow.romDisplay) );
cache_entry *entry;
GtkTreeIter iter;
gtk_tree_model_get_iter(model, &iter, path);
gtk_tree_model_get (model, &iter, 22, &entry, -1);
if(open_rom(entry->filename, entry->archivefile)==0)
startEmulation();
return FALSE;
}
//Rombrowser right click context menu.
gboolean callback_rombrowser_context( GtkWidget *widget, GdkEventButton *event, gpointer data )
{
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(g_MainWindow.romDisplay));
if( event->type == GDK_BUTTON_PRESS )
{
if( event->button == 3 ) // right click
{
if( gtk_tree_selection_count_selected_rows (selection) > 0 )
{
gtk_widget_set_sensitive( playRomItem, TRUE );
gtk_widget_set_sensitive( romPropertiesItem, TRUE );
}
else
{
gtk_widget_set_sensitive( playRomItem, FALSE );
gtk_widget_set_sensitive( romPropertiesItem, FALSE );
}
gtk_menu_popup( GTK_MENU(data), NULL, NULL, NULL, NULL,
event->button, event->time );
return TRUE;
}
}
return FALSE;
}
static void callback_netplayCreateGameShow( GtkWidget *widget, gpointer window ) {
show_creategame_dialog();
}
// activate filter widget -> filter and resort.
static void callback_apply_filter( GtkWidget *widget, gpointer data )
{
apply_filter();
}
void apply_filter( void )
{
int g_iNumRoms;
static short resort = 0;
GtkTreeModel *destination;
const gchar *filter;
filter = gtk_entry_get_text ( GTK_ENTRY(g_MainWindow.filter) );
if(filter[0]!='\0'||resort==1)
{
if(filter[0]!='\0')
resort=1;
else
resort=0;
GtkTreeModel *model, *source;
GtkTreeIter sourceiter, destinationiter;
gboolean validiter;
char *country, *goodname, *usercomments, *filename, *md5hash, *crc1, *crc2, *internalname, *savetype, *players, *size, *compressiontype, *imagetype, *cicchip, *rumble;
GdkPixbuf *status[5];
GdkPixbuf *flag;
cache_entry *entry;
short int counter;
//Clear the Display Tree View.
GtkTreeSelection *selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW(g_MainWindow.romDisplay) );
gtk_tree_selection_select_all(selection);
model = gtk_tree_view_get_model ( GTK_TREE_VIEW(g_MainWindow.romDisplay) );
gtk_list_store_clear( GTK_LIST_STORE(model) );
source = gtk_tree_view_get_model(GTK_TREE_VIEW(g_MainWindow.romFullList) );
g_iNumRoms = gtk_tree_model_iter_n_children(source, NULL);
validiter = gtk_tree_model_get_iter_first(source, &sourceiter);
destination = gtk_tree_view_get_model ( GTK_TREE_VIEW(g_MainWindow.romDisplay) );
gtk_tree_sortable_set_sort_func ( GTK_TREE_SORTABLE(destination), g_MainWindow.romSortColumn, return_zero, (gpointer)NULL, (gpointer)NULL );
if(validiter)
{
for ( counter = 0; counter < g_iNumRoms; ++counter )
{
if ( filter_function( source, &sourceiter, (gpointer)NULL) )
{
gtk_tree_model_get ( GTK_TREE_MODEL(source), &sourceiter, 0, &country, 1, &goodname, 3, &usercomments, 4, &filename, 5, &md5hash, 6, &crc1, 7, &crc2, 8, &internalname, 9, &savetype, 10, &players, 11, &size, 12, &compressiontype, 13, &imagetype, 14, &cicchip, 15, &rumble, 16, &status[0], 17, &status[1], 18, &status[2], 19, &status[3], 20, &status[4], 21, &flag, 22, &entry, -1);
gtk_list_store_append ( GTK_LIST_STORE(destination), &destinationiter);
gtk_list_store_set ( GTK_LIST_STORE(destination), &destinationiter, 0, country, 1, goodname, 2, NULL, 3, usercomments, 4, filename, 5, md5hash, 6, crc1, 7, crc2, 8, internalname, 9, savetype, 10, players, 11, size, 12, compressiontype, 13, imagetype, 14, cicchip, 15, rumble, 16, status[0], 17, status[1], 18, status[2], 19, status[3], 20, status[4], 21, flag, 22, entry, -1);
}
if(!gtk_tree_model_iter_next(source, &sourceiter))
break;
}
}
gtk_tree_sortable_set_sort_func ( GTK_TREE_SORTABLE(destination), g_MainWindow.romSortColumn, rombrowser_compare, (gpointer)NULL, (gpointer)NULL );
gtk_tree_sortable_set_sort_column_id ( GTK_TREE_SORTABLE(destination), g_MainWindow.romSortColumn, g_MainWindow.romSortType );
}
else
{
destination = gtk_tree_view_get_model ( GTK_TREE_VIEW(g_MainWindow.romDisplay) );
gtk_tree_sortable_set_sort_func ( GTK_TREE_SORTABLE(destination), g_MainWindow.romSortColumn, rombrowser_compare, (gpointer)NULL, (gpointer)NULL );
gtk_tree_sortable_set_sort_column_id ( GTK_TREE_SORTABLE(destination), g_MainWindow.romSortColumn, g_MainWindow.romSortType );
}
}
static gboolean callback_filter_selected( GtkWidget *widget, gpointer data )
{
if(g_MainWindow.accelUnsafeActive)
gtk_window_remove_accel_group(GTK_WINDOW(g_MainWindow.window), g_MainWindow.accelUnsafe);
return FALSE;
}
static gboolean callback_filter_unselected( GtkWidget *widget, gpointer data )
{
if(g_MainWindow.accelUnsafeActive)
gtk_window_add_accel_group(GTK_WINDOW(g_MainWindow.window), g_MainWindow.accelUnsafe);
return FALSE;
}
static gboolean callback_filter_grab_unselected( GtkWidget *widget, gpointer data )
{
if(!g_MainWindow.accelUnsafeActive)
gtk_window_add_accel_group(GTK_WINDOW(g_MainWindow.window), g_MainWindow.accelUnsafe);
gtk_window_set_focus(GTK_WINDOW(g_MainWindow.window), NULL);
return FALSE;
}
// create GUI filter widgets.
int create_filter( void )
{
GtkToolItem *toolitem;
GtkWidget *label;
GtkWidget *Hbox;
Hbox = gtk_hbox_new(FALSE, 0);
toolitem = gtk_tool_item_new();
gtk_tool_item_set_expand(toolitem, TRUE);
g_MainWindow.filterBar = gtk_toolbar_new();
gtk_toolbar_set_orientation( GTK_TOOLBAR(g_MainWindow.filterBar), GTK_ORIENTATION_HORIZONTAL );
label = gtk_label_new_with_mnemonic ( tr("F_ilter:") );
g_MainWindow.filter = gtk_entry_new();
gtk_entry_set_text ( GTK_ENTRY(g_MainWindow.filter), "" );
gtk_signal_connect ( GTK_OBJECT(g_MainWindow.filter), "changed",
GTK_SIGNAL_FUNC(callback_apply_filter), (gpointer)NULL );
gtk_signal_connect ( GTK_OBJECT(g_MainWindow.filter), "focus-in-event",
GTK_SIGNAL_FUNC(callback_filter_selected), (gpointer)NULL );
gtk_signal_connect ( GTK_OBJECT(g_MainWindow.filter), "focus-out-event",
GTK_SIGNAL_FUNC(callback_filter_unselected), (gpointer)NULL );
gtk_signal_connect ( GTK_OBJECT(g_MainWindow.filter), "grab-notify",
GTK_SIGNAL_FUNC(callback_filter_grab_unselected), (gpointer)NULL );
gtk_label_set_mnemonic_widget ( GTK_LABEL(label), g_MainWindow.filter );
gtk_box_pack_start ( GTK_BOX(Hbox), label, FALSE, FALSE, 5);
gtk_box_pack_start ( GTK_BOX(Hbox), g_MainWindow.filter, TRUE, TRUE, 5);
gtk_container_add(GTK_CONTAINER(toolitem), Hbox);
gtk_toolbar_insert ( GTK_TOOLBAR(g_MainWindow.filterBar), toolitem, 0);
gtk_box_pack_start ( GTK_BOX(g_MainWindow.toplevelVBox), g_MainWindow.filterBar, FALSE, FALSE, 0 );
}
// play rom menu item
static void callback_playRom( GtkWidget *widget, gpointer data )
{
GList *list = NULL, *llist = NULL;
cache_entry *entry;
GtkTreeIter iter;
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(g_MainWindow.romDisplay));
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(g_MainWindow.romDisplay));
list = gtk_tree_selection_get_selected_rows (selection, &model);
if( !list ) // should never happen since the item is only active when a row is selected
return;
llist = g_list_first (list);
gtk_tree_model_get_iter (model, &iter,(GtkTreePath *) llist->data);
gtk_tree_model_get(model, &iter, 22, &entry, -1);
g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
g_list_free (list);
if(open_rom(entry->filename, entry->archivefile)==0)
startEmulation();
}
static void callback_column_visible(GtkWidget *widget, int column)
{
int i;
char buffer1[32], buffer2[32];
gboolean visible = gtk_tree_view_column_get_visible(GTK_TREE_VIEW_COLUMN(g_MainWindow.column[column]));
gtk_tree_view_column_set_visible(g_MainWindow.column[column], !visible);
g_MainWindow.columnVisible[column]=!g_MainWindow.columnVisible[column];
strncpy(buffer1,column_names[column],31);
buffer1[31]='\0';
snprintf(buffer2, 31, "Column%sVisible", strnstrip(buffer1,31));
config_put_bool(buffer2,g_MainWindow.columnVisible[column]);
//Control if emptry header column is visibile.
gtk_tree_view_column_set_visible(g_MainWindow.column[16], FALSE);
for ( i = 0; i < 16; ++i )
{
if(g_MainWindow.columnVisible[i])
return;
}
gtk_tree_view_column_set_visible(g_MainWindow.column[16], TRUE);
}
static void callback_header_clicked(GtkWidget *widget, GdkEventButton *event, gpointer column)
{
if(event->type==GDK_BUTTON_PRESS)
{
if(event->button==3) //Right click.
{
gtk_menu_popup( GTK_MENU(g_MainWindow.romHeaderMenu), NULL, NULL, NULL, NULL,
event->button, event->time );
}
else if(event->button==1) //Left click.
{
if(g_MainWindow.romSortColumn==gtk_tree_view_column_get_sort_column_id(column))
g_MainWindow.romSortType = ( g_MainWindow.romSortType == GTK_SORT_ASCENDING ) ? GTK_SORT_DESCENDING : GTK_SORT_ASCENDING;
else
{
g_MainWindow.romSortColumn = gtk_tree_view_column_get_sort_column_id(column);
g_MainWindow.romSortType = GTK_SORT_ASCENDING;
}
config_put_number("RomSortColumn",g_MainWindow.romSortColumn);
config_put_number("RomSortType",g_MainWindow.romSortType);
apply_filter();
}
}
}
// rom properties
static void callback_romProperties( GtkWidget *widget, gpointer data )
{
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(g_MainWindow.romDisplay));
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(g_MainWindow.romDisplay));
if (gtk_tree_selection_count_selected_rows (selection) > 0)
{
GList *list = NULL, *llist = NULL;
list = gtk_tree_selection_get_selected_rows (selection, &model);
llist = g_list_first (list);
gtk_tree_model_get_iter (model, &g_RomPropDialog.iter,(GtkTreePath *) llist->data);
gtk_tree_model_get (model, &g_RomPropDialog.iter, 22, &g_RomPropDialog.entry, -1);
g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
show_romPropDialog();
}
}
static void setup_view (GtkWidget *view)
{
GtkListStore *store = gtk_list_store_new (23,
G_TYPE_STRING, //Country 0
G_TYPE_STRING, //Good Name 1
GDK_TYPE_PIXBUF, //NULL for padding... 2
G_TYPE_STRING, //User Comments 3
G_TYPE_STRING, //File Name 4
G_TYPE_STRING, //MD5 Hash 5
G_TYPE_STRING, //CRC1 6
G_TYPE_STRING, //CRC2 7
G_TYPE_STRING, //Internal Name 8
G_TYPE_STRING, //Save Type 9
G_TYPE_STRING, //Players 10
G_TYPE_STRING, //Size 11
G_TYPE_STRING, //Compression 12
G_TYPE_STRING, //Image Type 13
G_TYPE_STRING, //CIC Chip 14
G_TYPE_STRING, //Rumble 15
GDK_TYPE_PIXBUF, //Pixbufs for Status stars. 16,17,18,19,20
GDK_TYPE_PIXBUF,
GDK_TYPE_PIXBUF,
GDK_TYPE_PIXBUF,
GDK_TYPE_PIXBUF,
GDK_TYPE_PIXBUF, //Flag 21
G_TYPE_POINTER, //Entry 22
-1);
GtkCellRenderer *renderer;
GtkTreeModel *model;
GtkTreeViewColumn *column;
int i;
model = GTK_TREE_MODEL (store);
char buffer1[32], buffer2[32];
renderer = gtk_cell_renderer_pixbuf_new ();
g_MainWindow.column[0] = gtk_tree_view_column_new();
column = g_MainWindow.column[0];
gtk_tree_view_column_set_title(column, tr(column_names[0]));
gtk_tree_view_column_pack_start(column, renderer, FALSE);
gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", 21);
g_object_set(renderer, "xpad", 5, NULL);
renderer = gtk_cell_renderer_text_new();
gtk_tree_view_column_pack_start(column, renderer, TRUE);
gtk_tree_view_column_add_attribute(column, renderer, "text", 0);
gtk_tree_view_column_set_resizable (column, TRUE);
gtk_tree_view_column_set_reorderable (column, TRUE);
gtk_tree_view_column_set_sort_column_id(column, 0);
gtk_tree_view_insert_column(GTK_TREE_VIEW (view), column, 0);
gtk_signal_connect( GTK_OBJECT(column->button), "button-press-event", G_CALLBACK(callback_header_clicked), column);
renderer = gtk_cell_renderer_text_new ();
g_MainWindow.column[1] = gtk_tree_view_column_new_with_attributes (tr(column_names[1]), renderer, "text", 1, NULL);
column = g_MainWindow.column[1];
gtk_tree_view_column_set_resizable (column, TRUE);
gtk_tree_view_column_set_reorderable (column, TRUE);
gtk_tree_view_column_set_sort_column_id(column, 1);
gtk_tree_view_insert_column(GTK_TREE_VIEW (view), column, 1);
gtk_signal_connect( GTK_OBJECT(column->button), "button-press-event", G_CALLBACK(callback_header_clicked), column);
g_MainWindow.column[2] = gtk_tree_view_column_new();
column = g_MainWindow.column[2];
gtk_tree_view_column_set_title(column, tr(column_names[2]));
renderer = gtk_cell_renderer_pixbuf_new ();
g_object_set(renderer, "xpad", 2, NULL);
gtk_tree_view_column_pack_start(column, renderer, FALSE);
gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", 2);
for ( i = 0; i < 5; ++i )
{
renderer = gtk_cell_renderer_pixbuf_new ();
gtk_tree_view_column_pack_start(column, renderer, FALSE);
gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", 16+i);
}
renderer = gtk_cell_renderer_pixbuf_new ();
g_object_set(renderer, "xpad", 2, NULL);
gtk_tree_view_column_pack_start(column, renderer, FALSE);
gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", 2);
gtk_tree_view_column_set_resizable (column, TRUE);
gtk_tree_view_column_set_reorderable (column, TRUE);
gtk_tree_view_column_set_sort_column_id(column, 2);
gtk_tree_view_insert_column(GTK_TREE_VIEW (view), column, 2);
gtk_signal_connect( GTK_OBJECT(column->button), "button-press-event", G_CALLBACK(callback_header_clicked), column);
for ( i = 3; i < 16; ++i )
{
renderer = gtk_cell_renderer_text_new ();
g_MainWindow.column[i] = gtk_tree_view_column_new_with_attributes (tr(column_names[i]), renderer, "text", i, NULL);
column = g_MainWindow.column[i];
gtk_tree_view_column_set_resizable (column, TRUE);
gtk_tree_view_column_set_reorderable (column, TRUE);
gtk_tree_view_column_set_sort_column_id(column, i);
gtk_tree_view_insert_column(GTK_TREE_VIEW (view), column, i);
gtk_signal_connect( GTK_OBJECT(column->button), "button-press-event", G_CALLBACK(callback_header_clicked), column);
}
renderer = gtk_cell_renderer_text_new ();
g_MainWindow.column[16] = gtk_tree_view_column_new();
column = g_MainWindow.column[16];
gtk_tree_view_column_set_visible(column, FALSE);
gtk_tree_view_insert_column(GTK_TREE_VIEW (view), column, 2);
gtk_signal_connect( GTK_OBJECT(column->button), "button-press-event", G_CALLBACK(callback_header_clicked), column);
gtk_tree_view_set_model (GTK_TREE_VIEW (view), model );
g_object_unref (model);
g_MainWindow.romHeaderMenu = gtk_menu_new();
GtkWidget *item;
for (i = 0; i < 16; ++i)
{
strncpy(buffer1,column_names[i],31);
buffer1[31]='\0';
item = gtk_check_menu_item_new_with_label(tr(buffer1));
snprintf(buffer2, 31, "Column%sVisible", strnstrip(buffer1,31));
if((g_MainWindow.columnVisible[i]=config_get_bool(buffer2,2))==2)
{
if(i<5)
g_MainWindow.columnVisible[i] = TRUE;
else
g_MainWindow.columnVisible[i] = FALSE;
config_put_bool(buffer2,g_MainWindow.columnVisible[i]);
}
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), g_MainWindow.columnVisible[i]);
gtk_tree_view_column_set_visible(g_MainWindow.column[i], g_MainWindow.columnVisible[i]);
gtk_menu_append(GTK_MENU(g_MainWindow.romHeaderMenu), item);
gtk_widget_show(item);
g_signal_connect(item, "activate", G_CALLBACK(callback_column_visible), GUINT_TO_POINTER(i));
}
gtk_tree_view_column_set_visible(g_MainWindow.column[16], FALSE);
for ( i = 0; i < 16; ++i )
{
if(g_MainWindow.columnVisible[i])
return;
}
gtk_tree_view_column_set_visible(g_MainWindow.column[16], TRUE);
}
/*********************************************************************************************************
* gui functions
*/
//Create rom browser.
int create_romBrowser( void )
{
GtkWidget *rightClickMenu;
GtkWidget *separatorItem;
GtkIconTheme *theme = gtk_icon_theme_get_default();
if(gtk_icon_theme_has_icon(theme, "emblem-new"))
star = gtk_icon_theme_load_icon(theme, "emblem-new", 16, 0, NULL);
else
star = gdk_pixbuf_new_from_file( get_iconpath("16x16/star.png"), NULL);
australia = gdk_pixbuf_new_from_file( get_iconpath("australia.png"), NULL);
europe = gdk_pixbuf_new_from_file( get_iconpath("europe.png"), NULL);
france = gdk_pixbuf_new_from_file( get_iconpath("france.png"), NULL);
germany = gdk_pixbuf_new_from_file( get_iconpath("germany.png"), NULL);
italy = gdk_pixbuf_new_from_file( get_iconpath("italy.png"), NULL);
japan = gdk_pixbuf_new_from_file( get_iconpath("japan.png"), NULL);
spain = gdk_pixbuf_new_from_file( get_iconpath("spain.png"), NULL);
usa = gdk_pixbuf_new_from_file( get_iconpath("usa.png"), NULL);
japanusa = gdk_pixbuf_new_from_file( get_iconpath("japanusa.png"), NULL);
n64cart = gdk_pixbuf_new_from_file( get_iconpath("n64cart.xpm"), NULL);
//Setup right-click menu.
rightClickMenu = gtk_menu_new();
playRomItem = gtk_menu_item_new_with_label( tr("Play Rom") );
startNetGameItem = gtk_menu_item_new_with_label( tr("Start Net Game...") );
romPropertiesItem = gtk_menu_item_new_with_label( tr("Rom Properties") );
separatorItem = gtk_menu_item_new();
refreshRomBrowserItem = gtk_menu_item_new_with_label( tr("Refresh") );
gtk_menu_append ( GTK_MENU(rightClickMenu), playRomItem );
gtk_menu_append ( GTK_MENU(rightClickMenu), startNetGameItem );
gtk_menu_append ( GTK_MENU(rightClickMenu), romPropertiesItem );
gtk_menu_append ( GTK_MENU(rightClickMenu), separatorItem );
gtk_menu_append ( GTK_MENU(rightClickMenu), refreshRomBrowserItem );
gtk_widget_show ( rightClickMenu );
gtk_widget_show ( playRomItem );
gtk_widget_show ( startNetGameItem );
gtk_widget_show ( romPropertiesItem );
gtk_widget_show ( separatorItem );
gtk_widget_show ( refreshRomBrowserItem );
gtk_signal_connect ( GTK_OBJECT(playRomItem), "activate", GTK_SIGNAL_FUNC(callback_playRom), (gpointer)NULL );
gtk_signal_connect ( GTK_OBJECT(startNetGameItem), "activate", GTK_SIGNAL_FUNC(callback_netplayCreateGameShow), (gpointer)NULL );
gtk_signal_connect ( GTK_OBJECT(romPropertiesItem), "activate", GTK_SIGNAL_FUNC(callback_romProperties), (gpointer)NULL );
gtk_signal_connect ( GTK_OBJECT(refreshRomBrowserItem), "activate", GTK_SIGNAL_FUNC(call_rcs), (gpointer)NULL );
g_MainWindow.romFullList = gtk_tree_view_new();
g_MainWindow.romDisplay = gtk_tree_view_new();
//This is needed due to the way we clear the TreeViews.
GtkTreeSelection *selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW(g_MainWindow.romFullList) );
gtk_tree_selection_set_mode ( selection, GTK_SELECTION_MULTIPLE );
selection = gtk_tree_view_get_selection ( GTK_TREE_VIEW(g_MainWindow.romDisplay) );
gtk_tree_selection_set_mode ( selection, GTK_SELECTION_MULTIPLE );
//Initialize TreeViews - i.e. setup column info.
setup_view(g_MainWindow.romFullList);
setup_view(g_MainWindow.romDisplay);
//Create a scrolled window to contain the rom list, make scrollbar visibility automatic.
g_MainWindow.romScrolledWindow = gtk_scrolled_window_new ( NULL, NULL );
gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW(g_MainWindow.romScrolledWindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
//Add the Display TreeView into our scrolled window.
gtk_container_add (GTK_CONTAINER (g_MainWindow.romScrolledWindow), g_MainWindow.romDisplay );
gtk_container_add (GTK_CONTAINER (g_MainWindow.toplevelVBox), g_MainWindow.romScrolledWindow );
//Instruct the widget to become visible.
gtk_widget_show(g_MainWindow.romScrolledWindow);
gtk_tree_view_set_headers_clickable ( GTK_TREE_VIEW(g_MainWindow.romDisplay), TRUE );
gtk_tree_view_set_rules_hint (GTK_TREE_VIEW(g_MainWindow.romDisplay), TRUE );
gtk_tree_view_set_reorderable (GTK_TREE_VIEW(g_MainWindow.romDisplay), FALSE );
gtk_signal_connect( GTK_OBJECT(g_MainWindow.romDisplay), "row-activated", GTK_SIGNAL_FUNC(callback_rowSelected), (gpointer)NULL );
gtk_signal_connect( GTK_OBJECT(g_MainWindow.romDisplay), "button-press-event", GTK_SIGNAL_FUNC(callback_rombrowser_context), (gpointer)rightClickMenu);
return 0;
}