666 lines
20 KiB
C
666 lines
20 KiB
C
|
/*
|
||
|
* TilEm II
|
||
|
*
|
||
|
* Copyright (c) 2010-2011 Thibault Duponchelle
|
||
|
*
|
||
|
* 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 3 of the
|
||
|
* License, or (at your option) any later version.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful, but
|
||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
* General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
#ifdef HAVE_CONFIG_H
|
||
|
# include <config.h>
|
||
|
#endif
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <errno.h>
|
||
|
#include <gtk/gtk.h>
|
||
|
#include <glib/gstdio.h>
|
||
|
#include <ticalcs.h>
|
||
|
#include <ticonv.h>
|
||
|
#include <tilem.h>
|
||
|
#include <tilemdb.h>
|
||
|
#include <scancodes.h>
|
||
|
|
||
|
#include "gui.h"
|
||
|
#include "disasmview.h"
|
||
|
#include "memmodel.h"
|
||
|
#include "files.h"
|
||
|
#include "filedlg.h"
|
||
|
#include "msgbox.h"
|
||
|
#include "fixedtreeview.h"
|
||
|
|
||
|
static GtkTreeModel* fill_varlist(TilemReceiveDialog *rcvdialog);
|
||
|
TilemReceiveDialog* create_receive_menu(TilemCalcEmulator *emu);
|
||
|
|
||
|
/* Columns */
|
||
|
enum
|
||
|
{
|
||
|
COL_ENTRY = 0,
|
||
|
COL_SLOT_STR,
|
||
|
COL_NAME_STR,
|
||
|
COL_TYPE_STR,
|
||
|
COL_SIZE_STR,
|
||
|
COL_SIZE,
|
||
|
NUM_COLS
|
||
|
};
|
||
|
|
||
|
#define RESPONSE_REFRESH 1
|
||
|
|
||
|
/* Prompt to overwrite a list of files. */
|
||
|
static gboolean prompt_overwrite(GtkWindow *win, const char *dirname,
|
||
|
char **filenames)
|
||
|
{
|
||
|
int i;
|
||
|
char *dname;
|
||
|
GString *conflicts = NULL;
|
||
|
int nconflicts = 0;
|
||
|
GtkWidget *dlg, *btn;
|
||
|
int response;
|
||
|
|
||
|
for (i = 0; filenames[i]; i++) {
|
||
|
if (g_file_test(filenames[i], G_FILE_TEST_EXISTS)) {
|
||
|
if (conflicts)
|
||
|
g_string_append_c(conflicts, '\n');
|
||
|
else
|
||
|
conflicts = g_string_new(NULL);
|
||
|
dname = g_filename_display_basename(filenames[i]);
|
||
|
g_string_append(conflicts, dname);
|
||
|
g_free(dname);
|
||
|
nconflicts++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!conflicts)
|
||
|
return TRUE;
|
||
|
|
||
|
dname = g_filename_display_basename(dirname);
|
||
|
|
||
|
dlg = gtk_message_dialog_new
|
||
|
(win, GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
|
||
|
(nconflicts == 1
|
||
|
? "Replace existing file?"
|
||
|
: "Replace existing files?"));
|
||
|
|
||
|
gtk_message_dialog_format_secondary_text
|
||
|
(GTK_MESSAGE_DIALOG(dlg),
|
||
|
(nconflicts == 1
|
||
|
? "The file \"%2$s\" already exists in \"%1$s\"."
|
||
|
" Replacing it will overwrite its contents."
|
||
|
: "The following files already exist in \"%s\"."
|
||
|
" Replacing them will overwrite their contents:\n%s"),
|
||
|
dname, conflicts->str);
|
||
|
|
||
|
g_free(dname);
|
||
|
g_string_free(conflicts, TRUE);
|
||
|
|
||
|
gtk_dialog_add_button(GTK_DIALOG(dlg),
|
||
|
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
|
||
|
|
||
|
btn = gtk_button_new_with_mnemonic("_Replace");
|
||
|
gtk_button_set_image(GTK_BUTTON(btn),
|
||
|
gtk_image_new_from_stock(GTK_STOCK_SAVE,
|
||
|
GTK_ICON_SIZE_BUTTON));
|
||
|
gtk_widget_show(btn);
|
||
|
gtk_dialog_add_action_widget(GTK_DIALOG(dlg), btn,
|
||
|
GTK_RESPONSE_ACCEPT);
|
||
|
|
||
|
gtk_dialog_set_alternative_button_order(GTK_DIALOG(dlg),
|
||
|
GTK_RESPONSE_ACCEPT,
|
||
|
GTK_RESPONSE_CANCEL,
|
||
|
-1);
|
||
|
|
||
|
response = gtk_dialog_run(GTK_DIALOG(dlg));
|
||
|
gtk_widget_destroy(dlg);
|
||
|
return (response == GTK_RESPONSE_ACCEPT);
|
||
|
}
|
||
|
|
||
|
/* #### SIGNALS CALLBACK #### */
|
||
|
|
||
|
/* Prompt to save a single file. */
|
||
|
static gboolean prompt_save_single(TilemReceiveDialog *rcvdialog, TilemVarEntry *tve)
|
||
|
{
|
||
|
char *dir, *default_filename, *default_filename_r, *filename, *pattern;
|
||
|
|
||
|
default_filename = get_default_filename(tve);
|
||
|
default_filename_r = utf8_to_restricted_utf8(default_filename);
|
||
|
g_free(default_filename);
|
||
|
|
||
|
tilem_config_get("download", "receivefile_recentdir/f", &dir, NULL);
|
||
|
if (!dir) dir = g_get_current_dir();
|
||
|
|
||
|
pattern = g_strconcat("*.", tve->file_ext, NULL);
|
||
|
|
||
|
filename = prompt_save_file("Save File", GTK_WINDOW(rcvdialog->window),
|
||
|
default_filename_r, dir,
|
||
|
tve->filetype_desc, pattern,
|
||
|
"All files", "*",
|
||
|
NULL);
|
||
|
g_free(default_filename_r);
|
||
|
g_free(pattern);
|
||
|
g_free(dir);
|
||
|
|
||
|
if (!filename)
|
||
|
return FALSE;
|
||
|
|
||
|
dir = g_path_get_dirname(filename);
|
||
|
tilem_config_set("download", "receivefile_recentdir/f", dir, NULL);
|
||
|
g_free(dir);
|
||
|
|
||
|
tilem_link_receive_file(rcvdialog->emu, tve, filename);
|
||
|
g_free(filename);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/* Prompt to save a list of variables as a group file. */
|
||
|
static gboolean prompt_save_group(TilemReceiveDialog *rcvdialog, GList *rows)
|
||
|
{
|
||
|
char *dir, *default_filename, *pattern_desc, *pattern, *filename, *fext;
|
||
|
int tfmodel;
|
||
|
gboolean can_group = TRUE;
|
||
|
const char *model_str;
|
||
|
GList *l;
|
||
|
GtkTreePath *path;
|
||
|
GtkTreeIter iter;
|
||
|
TilemVarEntry *tve;
|
||
|
GSList *velist = NULL;
|
||
|
|
||
|
tilem_config_get("download", "receivefile_recentdir/f", &dir, NULL);
|
||
|
if (!dir) dir = g_get_current_dir();
|
||
|
|
||
|
for (l = rows; l; l = l->next) {
|
||
|
path = (GtkTreePath*) l->data;
|
||
|
gtk_tree_model_get_iter(rcvdialog->model, &iter, path);
|
||
|
gtk_tree_model_get(rcvdialog->model, &iter, COL_ENTRY, &tve, -1);
|
||
|
velist = g_slist_prepend(velist, tve);
|
||
|
if (!tve->can_group)
|
||
|
can_group = FALSE;
|
||
|
}
|
||
|
|
||
|
velist = g_slist_reverse(velist);
|
||
|
|
||
|
tfmodel = get_calc_model(rcvdialog->emu->calc);
|
||
|
|
||
|
fext = g_ascii_strdown(tifiles_fext_of_group(tfmodel), -1);
|
||
|
pattern = g_strconcat("*.", fext, NULL);
|
||
|
default_filename = g_strdup_printf("untitled.%s",
|
||
|
(can_group ? fext : "tig"));
|
||
|
g_free(fext);
|
||
|
|
||
|
model_str = tifiles_model_to_string(tfmodel);
|
||
|
pattern_desc = g_strdup_printf("%s group files", model_str);
|
||
|
|
||
|
filename = prompt_save_file("Save File", GTK_WINDOW(rcvdialog->window),
|
||
|
default_filename, dir,
|
||
|
pattern_desc, (can_group ? pattern : ""),
|
||
|
"TIGroup files", "*.tig",
|
||
|
"All files", "*",
|
||
|
NULL);
|
||
|
|
||
|
g_free(default_filename);
|
||
|
g_free(dir);
|
||
|
g_free(pattern_desc);
|
||
|
g_free(pattern);
|
||
|
|
||
|
if (!filename) {
|
||
|
g_slist_free(velist);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
dir = g_path_get_dirname(filename);
|
||
|
tilem_config_set("download",
|
||
|
"receivefile_recentdir/f", dir,
|
||
|
"save_as_group/b", TRUE,
|
||
|
NULL);
|
||
|
g_free(dir);
|
||
|
|
||
|
tilem_link_receive_group(rcvdialog->emu, velist, filename);
|
||
|
|
||
|
g_free(filename);
|
||
|
g_slist_free(velist);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/* Prompt to save a list of files. Input is a list of GtkTreePaths */
|
||
|
static gboolean prompt_save_multiple(TilemReceiveDialog *rcvdialog, GList *rows)
|
||
|
{
|
||
|
char *dir, *dir_selected, *default_filename, *default_filename_f;
|
||
|
GList *l;
|
||
|
GtkTreePath *path;
|
||
|
GtkTreeIter iter;
|
||
|
TilemVarEntry *tve, **vars;
|
||
|
char **names;
|
||
|
gboolean is_81, use_group;
|
||
|
int i;
|
||
|
|
||
|
is_81 = (rcvdialog->emu->calc->hw.model_id == TILEM_CALC_TI81);
|
||
|
use_group = gtk_toggle_button_get_active
|
||
|
(GTK_TOGGLE_BUTTON(rcvdialog->group_rb));
|
||
|
|
||
|
if (use_group && !is_81)
|
||
|
return prompt_save_group(rcvdialog, rows);
|
||
|
|
||
|
tilem_config_get("download", "receivefile_recentdir/f", &dir, NULL);
|
||
|
if (!dir) dir = g_get_current_dir();
|
||
|
|
||
|
dir_selected = prompt_select_dir("Save Files to Directory",
|
||
|
GTK_WINDOW(rcvdialog->window),
|
||
|
dir);
|
||
|
g_free(dir);
|
||
|
|
||
|
if (!dir_selected)
|
||
|
return FALSE;
|
||
|
|
||
|
tilem_config_set("download",
|
||
|
"receivefile_recentdir/f", dir_selected,
|
||
|
"save_as_group/b", use_group,
|
||
|
NULL);
|
||
|
|
||
|
vars = g_new(TilemVarEntry *, g_list_length(rows) + 1);
|
||
|
names = g_new(char *, g_list_length(rows) + 1);
|
||
|
|
||
|
for (l = rows, i = 0; l; l = l->next, i++) {
|
||
|
path = (GtkTreePath*) l->data;
|
||
|
gtk_tree_model_get_iter(rcvdialog->model, &iter, path);
|
||
|
gtk_tree_model_get(rcvdialog->model, &iter, COL_ENTRY, &tve, -1);
|
||
|
|
||
|
vars[i] = tve;
|
||
|
|
||
|
default_filename = get_default_filename(tve);
|
||
|
default_filename_f = utf8_to_filename(default_filename);
|
||
|
names[i] = g_build_filename(dir_selected,
|
||
|
default_filename_f, NULL);
|
||
|
g_free(default_filename);
|
||
|
g_free(default_filename_f);
|
||
|
}
|
||
|
|
||
|
vars[i] = NULL;
|
||
|
names[i] = NULL;
|
||
|
|
||
|
if (!prompt_overwrite(GTK_WINDOW(rcvdialog->window),
|
||
|
dir_selected, names)) {
|
||
|
g_free(vars);
|
||
|
g_strfreev(names);
|
||
|
g_free(dir_selected);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
for (i = 0; vars[i]; i++)
|
||
|
tilem_link_receive_file(rcvdialog->emu, vars[i], names[i]);
|
||
|
|
||
|
g_free(vars);
|
||
|
g_strfreev(names);
|
||
|
g_free(dir_selected);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/* Event called on Send button click. Get the selected var/app and save it. */
|
||
|
static gboolean prompt_save(TilemReceiveDialog *rcvdialog)
|
||
|
{
|
||
|
TilemVarEntry *tve; /* Variable entry */
|
||
|
GtkTreeSelection* selection = NULL; /* GtkTreeSelection */
|
||
|
GtkTreeModel *model;
|
||
|
GtkTreeIter iter;
|
||
|
GList *rows, *l;
|
||
|
GtkTreePath *path;
|
||
|
gboolean status;
|
||
|
|
||
|
/* Get the selected entry */
|
||
|
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(rcvdialog->treeview));
|
||
|
rows = gtk_tree_selection_get_selected_rows(selection, &model);
|
||
|
|
||
|
if (!rows)
|
||
|
return FALSE;
|
||
|
|
||
|
if (!rows->next) {
|
||
|
path = (GtkTreePath*) rows->data;
|
||
|
gtk_tree_model_get_iter(model, &iter, path);
|
||
|
gtk_tree_model_get(model, &iter, COL_ENTRY, &tve, -1);
|
||
|
status = prompt_save_single(rcvdialog, tve);
|
||
|
}
|
||
|
else {
|
||
|
status = prompt_save_multiple(rcvdialog, rows);
|
||
|
}
|
||
|
|
||
|
for (l = rows; l; l = l->next)
|
||
|
gtk_tree_path_free(l->data);
|
||
|
g_list_free(rows);
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
/* Dialog response button clicked */
|
||
|
static void dialog_response(GtkDialog *dlg, gint response, gpointer data)
|
||
|
{
|
||
|
TilemReceiveDialog* rcvdialog = (TilemReceiveDialog*) data;
|
||
|
|
||
|
switch (response) {
|
||
|
case RESPONSE_REFRESH:
|
||
|
if (!rcvdialog->refresh_pending) {
|
||
|
rcvdialog->refresh_pending = TRUE;
|
||
|
tilem_link_get_dirlist(rcvdialog->emu);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case GTK_RESPONSE_ACCEPT:
|
||
|
if (!prompt_save(rcvdialog))
|
||
|
break;
|
||
|
default:
|
||
|
gtk_widget_hide(GTK_WIDGET(dlg));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Selection changed */
|
||
|
static void selection_changed(GtkTreeSelection *sel, gpointer data)
|
||
|
{
|
||
|
TilemReceiveDialog* rcvdialog = data;
|
||
|
int n = gtk_tree_selection_count_selected_rows(sel);
|
||
|
|
||
|
gtk_dialog_set_response_sensitive(GTK_DIALOG(rcvdialog->window),
|
||
|
GTK_RESPONSE_ACCEPT, (n > 0));
|
||
|
gtk_widget_set_sensitive(rcvdialog->mode_box, (n > 1));
|
||
|
}
|
||
|
|
||
|
/* Row activated in tree view */
|
||
|
static void row_activated(G_GNUC_UNUSED GtkTreeView *treeview,
|
||
|
G_GNUC_UNUSED GtkTreePath *path,
|
||
|
G_GNUC_UNUSED GtkTreeViewColumn *col,
|
||
|
gpointer data)
|
||
|
{
|
||
|
TilemReceiveDialog* rcvdialog = (TilemReceiveDialog*) data;
|
||
|
gtk_dialog_response(GTK_DIALOG(rcvdialog->window), GTK_RESPONSE_ACCEPT);
|
||
|
}
|
||
|
|
||
|
/* #### WIDGET CREATION #### */
|
||
|
|
||
|
/* Create a new scrolled window with sensible default settings. */
|
||
|
static GtkWidget *new_scrolled_window(GtkWidget *contents)
|
||
|
{
|
||
|
GtkWidget *sw;
|
||
|
sw = gtk_scrolled_window_new(NULL, NULL);
|
||
|
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
|
||
|
GTK_POLICY_NEVER,
|
||
|
GTK_POLICY_AUTOMATIC);
|
||
|
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
|
||
|
GTK_SHADOW_IN);
|
||
|
gtk_container_add(GTK_CONTAINER(sw), contents);
|
||
|
return sw;
|
||
|
}
|
||
|
|
||
|
/* Create the (empty) GtkTreeView to show the vars list */
|
||
|
static GtkWidget *create_varlist(TilemReceiveDialog *rcvdialog)
|
||
|
{
|
||
|
GtkCellRenderer *renderer;
|
||
|
GtkWidget *treeview;
|
||
|
GtkTreeSelection *sel;
|
||
|
GtkTreeViewColumn *c1, *c2, *c3, *c4;
|
||
|
gboolean is_81;
|
||
|
|
||
|
g_return_val_if_fail(rcvdialog->emu != NULL, NULL);
|
||
|
g_return_val_if_fail(rcvdialog->emu->calc != NULL, NULL);
|
||
|
|
||
|
is_81 = (rcvdialog->emu->calc->hw.model_id == TILEM_CALC_TI81);
|
||
|
|
||
|
/* Create the stack list tree view and set title invisible */
|
||
|
treeview = gtk_tree_view_new();
|
||
|
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), TRUE);
|
||
|
gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(treeview), TRUE);
|
||
|
gtk_tree_view_set_fixed_height_mode(GTK_TREE_VIEW(treeview), TRUE);
|
||
|
|
||
|
/* Allow multiple selection */
|
||
|
sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
|
||
|
gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE);
|
||
|
|
||
|
/* Create the columns */
|
||
|
renderer = gtk_cell_renderer_text_new();
|
||
|
|
||
|
if (is_81) {
|
||
|
c1 = gtk_tree_view_column_new_with_attributes
|
||
|
("Slot", renderer, "text", COL_SLOT_STR, NULL);
|
||
|
|
||
|
gtk_tree_view_column_set_sizing(c1, GTK_TREE_VIEW_COLUMN_FIXED);
|
||
|
gtk_tree_view_column_set_sort_column_id(c1, COL_SLOT_STR);
|
||
|
gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), c1);
|
||
|
}
|
||
|
|
||
|
c2 = gtk_tree_view_column_new_with_attributes
|
||
|
("Name", renderer, "text", COL_NAME_STR, NULL);
|
||
|
|
||
|
gtk_tree_view_column_set_sizing(c2, GTK_TREE_VIEW_COLUMN_FIXED);
|
||
|
gtk_tree_view_column_set_sort_column_id(c2, COL_NAME_STR);
|
||
|
gtk_tree_view_column_set_expand(c2, TRUE);
|
||
|
gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), c2);
|
||
|
|
||
|
if (!is_81) {
|
||
|
c3 = gtk_tree_view_column_new_with_attributes
|
||
|
("Type", renderer, "text", COL_TYPE_STR, NULL);
|
||
|
|
||
|
gtk_tree_view_column_set_sizing(c3, GTK_TREE_VIEW_COLUMN_FIXED);
|
||
|
gtk_tree_view_column_set_sort_column_id(c3, COL_TYPE_STR);
|
||
|
gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), c3);
|
||
|
}
|
||
|
|
||
|
renderer = gtk_cell_renderer_text_new();
|
||
|
g_object_set(renderer, "xalign", 1.0, NULL);
|
||
|
c4 = gtk_tree_view_column_new_with_attributes
|
||
|
("Size", renderer, "text", COL_SIZE_STR, NULL);
|
||
|
|
||
|
gtk_tree_view_column_set_sizing(c4, GTK_TREE_VIEW_COLUMN_FIXED);
|
||
|
gtk_tree_view_column_set_sort_column_id(c4, COL_SIZE);
|
||
|
gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), c4);
|
||
|
|
||
|
g_signal_connect(sel, "changed",
|
||
|
G_CALLBACK(selection_changed), rcvdialog);
|
||
|
|
||
|
g_signal_connect(treeview, "row-activated",
|
||
|
G_CALLBACK(row_activated), rcvdialog);
|
||
|
|
||
|
return treeview;
|
||
|
}
|
||
|
|
||
|
/* Fill the list of vars. In fact, add all vars from list to a GtkListStore */
|
||
|
static GtkTreeModel* fill_varlist(TilemReceiveDialog *rcvdialog)
|
||
|
{
|
||
|
GSList *l;
|
||
|
TilemVarEntry *tve;
|
||
|
GtkListStore *store;
|
||
|
GtkTreeIter iter;
|
||
|
char *size_str;
|
||
|
|
||
|
store = gtk_list_store_new(6,
|
||
|
G_TYPE_POINTER,
|
||
|
G_TYPE_STRING,
|
||
|
G_TYPE_STRING,
|
||
|
G_TYPE_STRING,
|
||
|
G_TYPE_STRING,
|
||
|
G_TYPE_INT);
|
||
|
|
||
|
for (l = rcvdialog->vars; l; l = l->next) {
|
||
|
tve = l->data;
|
||
|
gtk_list_store_append(store, &iter);
|
||
|
#ifdef G_OS_WIN32
|
||
|
size_str = g_strdup_printf("%d", tve->size);
|
||
|
#else
|
||
|
size_str = g_strdup_printf("%'d", tve->size);
|
||
|
#endif
|
||
|
gtk_list_store_set(store, &iter,
|
||
|
COL_ENTRY, tve,
|
||
|
COL_SLOT_STR, tve->slot_str,
|
||
|
COL_NAME_STR, tve->name_str,
|
||
|
COL_TYPE_STR, tve->type_str,
|
||
|
COL_SIZE_STR, size_str,
|
||
|
COL_SIZE, tve->size,
|
||
|
-1);
|
||
|
g_free(size_str);
|
||
|
}
|
||
|
|
||
|
return GTK_TREE_MODEL(store);
|
||
|
}
|
||
|
|
||
|
/* Create a new menu for receiving vars. */
|
||
|
/* Previous allocated and filled varlist is needed */
|
||
|
TilemReceiveDialog* tilem_receive_dialog_new(TilemCalcEmulator *emu)
|
||
|
{
|
||
|
TilemReceiveDialog* rcvdialog = g_slice_new0(TilemReceiveDialog);
|
||
|
GtkWidget *scroll, *btn, *vbox, *lbl, *rb, *vbox2;
|
||
|
int defheight = 300;
|
||
|
gboolean is_81;
|
||
|
gboolean use_group;
|
||
|
|
||
|
g_return_val_if_fail(emu != NULL, NULL);
|
||
|
g_return_val_if_fail(emu->ewin != NULL, NULL);
|
||
|
g_return_val_if_fail(emu->calc != NULL, NULL);
|
||
|
|
||
|
rcvdialog->emu = emu;
|
||
|
emu->rcvdlg = rcvdialog;
|
||
|
|
||
|
is_81 = (emu->calc->hw.model_id == TILEM_CALC_TI81);
|
||
|
|
||
|
rcvdialog->window = gtk_dialog_new();
|
||
|
gtk_window_set_transient_for(GTK_WINDOW(rcvdialog->window),
|
||
|
GTK_WINDOW(emu->ewin->window));
|
||
|
|
||
|
gtk_window_set_title(GTK_WINDOW(rcvdialog->window), "Receive File");
|
||
|
|
||
|
btn = gtk_dialog_add_button(GTK_DIALOG(rcvdialog->window),
|
||
|
GTK_STOCK_REFRESH, RESPONSE_REFRESH);
|
||
|
|
||
|
if (is_81)
|
||
|
gtk_widget_hide(btn);
|
||
|
|
||
|
gtk_dialog_add_button(GTK_DIALOG(rcvdialog->window),
|
||
|
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
|
||
|
gtk_dialog_add_button(GTK_DIALOG(rcvdialog->window),
|
||
|
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT);
|
||
|
|
||
|
gtk_dialog_set_default_response(GTK_DIALOG(rcvdialog->window),
|
||
|
GTK_RESPONSE_ACCEPT);
|
||
|
gtk_dialog_set_alternative_button_order(GTK_DIALOG(rcvdialog->window),
|
||
|
RESPONSE_REFRESH,
|
||
|
GTK_RESPONSE_ACCEPT,
|
||
|
GTK_RESPONSE_CANCEL,
|
||
|
-1);
|
||
|
|
||
|
/* Set the size of the dialog */
|
||
|
gtk_window_set_default_size(GTK_WINDOW(rcvdialog->window), -1, defheight);
|
||
|
|
||
|
/* Create and fill tree view */
|
||
|
rcvdialog->treeview = create_varlist(rcvdialog);
|
||
|
|
||
|
/* Allow scrolling the list because we can't know how many vars the calc contains */
|
||
|
scroll = new_scrolled_window(rcvdialog->treeview);
|
||
|
|
||
|
vbox = gtk_vbox_new(FALSE, 6);
|
||
|
gtk_container_set_border_width(GTK_CONTAINER(vbox), 6);
|
||
|
gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(scroll), TRUE, TRUE, 0);
|
||
|
|
||
|
rcvdialog->mode_box = gtk_hbox_new(FALSE, 6);
|
||
|
lbl = gtk_label_new("Save as:");
|
||
|
gtk_box_pack_start(GTK_BOX(rcvdialog->mode_box), lbl, FALSE, FALSE, 0);
|
||
|
|
||
|
rb = gtk_radio_button_new_with_mnemonic(NULL, "S_eparate files");
|
||
|
gtk_box_pack_start(GTK_BOX(rcvdialog->mode_box), rb, FALSE, FALSE, 0);
|
||
|
rcvdialog->multiple_rb = rb;
|
||
|
|
||
|
rb = gtk_radio_button_new_with_mnemonic_from_widget
|
||
|
(GTK_RADIO_BUTTON(rb), "_Group file");
|
||
|
gtk_box_pack_start(GTK_BOX(rcvdialog->mode_box), rb, FALSE, FALSE, 0);
|
||
|
rcvdialog->group_rb = rb;
|
||
|
|
||
|
tilem_config_get("download", "save_as_group/b=1", &use_group, NULL);
|
||
|
if (use_group)
|
||
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb), TRUE);
|
||
|
|
||
|
if (is_81)
|
||
|
gtk_widget_set_no_show_all(rcvdialog->mode_box, TRUE);
|
||
|
|
||
|
gtk_box_pack_start(GTK_BOX(vbox), rcvdialog->mode_box, FALSE, FALSE, 0);
|
||
|
vbox2 = gtk_dialog_get_content_area(GTK_DIALOG(rcvdialog->window));
|
||
|
gtk_box_pack_start(GTK_BOX(vbox2), vbox, TRUE, TRUE, 0);
|
||
|
|
||
|
/* Signals callback */
|
||
|
g_signal_connect(rcvdialog->window, "response",
|
||
|
G_CALLBACK(dialog_response), rcvdialog);
|
||
|
g_signal_connect(rcvdialog->window, "delete-event",
|
||
|
G_CALLBACK(gtk_widget_hide_on_delete), NULL);
|
||
|
|
||
|
gtk_widget_show_all(vbox);
|
||
|
|
||
|
return rcvdialog;
|
||
|
}
|
||
|
|
||
|
/* Destroy a TilemReceiveDialog */
|
||
|
void tilem_receive_dialog_free(TilemReceiveDialog *rcvdialog)
|
||
|
{
|
||
|
GSList *l;
|
||
|
|
||
|
g_return_if_fail(rcvdialog != NULL);
|
||
|
|
||
|
gtk_widget_destroy(rcvdialog->window);
|
||
|
|
||
|
for (l = rcvdialog->vars; l; l = l->next)
|
||
|
tilem_var_entry_free(l->data);
|
||
|
g_slist_free(rcvdialog->vars);
|
||
|
|
||
|
g_slice_free(TilemReceiveDialog, rcvdialog);
|
||
|
}
|
||
|
|
||
|
void tilem_receive_dialog_update(TilemReceiveDialog *rcvdialog, GSList *varlist)
|
||
|
{
|
||
|
GSList *l;
|
||
|
|
||
|
g_return_if_fail(rcvdialog != NULL);
|
||
|
|
||
|
rcvdialog->refresh_pending = FALSE;
|
||
|
|
||
|
for (l = rcvdialog->vars; l; l = l->next)
|
||
|
tilem_var_entry_free(l->data);
|
||
|
g_slist_free(rcvdialog->vars);
|
||
|
|
||
|
rcvdialog->vars = varlist;
|
||
|
rcvdialog->model = fill_varlist(rcvdialog);
|
||
|
gtk_tree_view_set_model(GTK_TREE_VIEW(rcvdialog->treeview), rcvdialog->model);
|
||
|
|
||
|
fixed_tree_view_init(rcvdialog->treeview, 0,
|
||
|
COL_SLOT_STR, "PrgmM ",
|
||
|
COL_NAME_STR, "MMMMMMMMM ",
|
||
|
COL_TYPE_STR, "MMMMMM ",
|
||
|
COL_SIZE_STR, "00,000,000",
|
||
|
-1);
|
||
|
|
||
|
gtk_widget_grab_focus(rcvdialog->treeview);
|
||
|
gtk_window_present(GTK_WINDOW(rcvdialog->window));
|
||
|
}
|
||
|
|
||
|
/* Popup the receive window */
|
||
|
/* This is the entry point */
|
||
|
void popup_receive_menu(TilemEmulatorWindow *ewin)
|
||
|
{
|
||
|
g_return_if_fail(ewin != NULL);
|
||
|
g_return_if_fail(ewin->emu != NULL);
|
||
|
g_return_if_fail(ewin->emu->calc != NULL);
|
||
|
|
||
|
if (ewin->emu->rcvdlg && ewin->emu->rcvdlg->refresh_pending)
|
||
|
return;
|
||
|
|
||
|
/* TI-81 takes no time to refresh, so do it automatically */
|
||
|
if (!ewin->emu->rcvdlg
|
||
|
|| ewin->emu->calc->hw.model_id == TILEM_CALC_TI81) {
|
||
|
tilem_link_get_dirlist(ewin->emu);
|
||
|
}
|
||
|
else {
|
||
|
gtk_widget_grab_focus(ewin->emu->rcvdlg->treeview);
|
||
|
gtk_window_present(GTK_WINDOW(ewin->emu->rcvdlg->window));
|
||
|
}
|
||
|
}
|