/*
* Copyright (c) 2006
* Morten Slot Kristensen, Århus, Denmark. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include <fstream>
#include <vector>
#include <ctype.h>
#include <gtk/gtk.h>
#include "matrix.hpp"
#include "operations.hpp"
#include "gtk.hpp"
#include "defs.hpp"
using namespace std;
/* METHODS */
int id_in_use(int id);
matrix get_by_id(int id);
void do_trivial(matrix*);
int get_input(int type, string msg);
float get_input_f(int type, string msg);
/* GTK METHODS */
void interactive_dialog(int);
void define_matrix_dialog();
void build_menu();
void update_tree_view();
static void selection_changed (GtkTreeSelection*);
void set_statusbar_text(string);
void do_gtk_trivial(matrix*);
/* GLOBAL VARIABLES */
vector<matrix> matrix_vector;
int global_preview_id = -1,
global_rows = -1,
global_columns = -1,
global_order = -1,
global_from = 0,
global_to = 0,
m1 = -1,
m2 = -1;
GtkWidget *window, *menubar, *menuitem, *menu, *menuMenu, *menuMatrices,
*menuHelp, *scrolledwindow_m1, *scrolledwindow_m2, *scrolledwindow_pre,
*scrolledwindow_res, *scrolledwindow_list, *vbox_1, *vbox_2, *hbox_1,
*hpaned, *hpaned_2, *vpaned, *treeview, *textview_m1, *textview_m2,
*textview_pre, *textview_res, *frame_list, *frame_pre, *frame_m1,
*frame_m2, *frame_res, *vbox_2_1, *hbox_2, *hbox_3, *btn_sel_m1,
*btn_sel_m2, *btn_del_m1, *btn_del_m2, *btn_del_chosen, *btn_del_all,
*menuOperations, *statusbar;
GtkTreeModel *list_model;
GtkListStore *store;
GtkTreeSelection *selection;
GtkTextBuffer *textbuf_m1, *textbuf_m2, *textbuf_pre, *textbuf_res;
int main(int argc, char *argv[])
{
// If the option '-gui' is used then start up GUI
if(argc == 2 && string(argv[1]) == "-gui")
{
cout << "Starting with gui.." << endl;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_signal_connect(GTK_OBJECT(window), "delete_event",
GTK_SIGNAL_FUNC(destroy_app), NULL);
gtk_window_set_default_size(GTK_WINDOW(window), WINWIDTH, WINHEIGHT);
gtk_window_set_title(GTK_WINDOW(window), WINTITLE);
gtk_container_border_width(GTK_CONTAINER(window), WINBORDER);
vbox_1 = gtk_vbox_new(FALSE, 0);
vbox_2 = gtk_vbox_new(FALSE, 0);
vbox_2_1 = gtk_vbox_new(FALSE, 0);
hbox_1 = gtk_hbox_new(FALSE, 0);
hbox_2 = gtk_hbox_new(FALSE, 0);
hbox_3 = gtk_hbox_new(FALSE, 0);
hpaned = gtk_hpaned_new();
hpaned_2 = gtk_hpaned_new();
vpaned = gtk_vpaned_new();
frame_m1 = gtk_frame_new("[M1] Matrix 1:");
frame_m2 = gtk_frame_new("[M2] Matrix 2:");
frame_pre = gtk_frame_new("Preview Matrix:");
frame_res = gtk_frame_new("Result Matrix:");
frame_list = gtk_frame_new("Matrix list:");
scrolledwindow_list = gtk_scrolled_window_new(NULL, NULL);
scrolledwindow_m1 = gtk_scrolled_window_new(NULL, NULL);
scrolledwindow_m2 = gtk_scrolled_window_new(NULL, NULL);
scrolledwindow_pre = gtk_scrolled_window_new(NULL, NULL);
scrolledwindow_res = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow_m1),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow_m2),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow_res),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow_pre),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow_list),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
textbuf_m1 = gtk_text_buffer_new(NULL);
textbuf_m2 = gtk_text_buffer_new(NULL);
textbuf_pre = gtk_text_buffer_new(NULL);
textbuf_res = gtk_text_buffer_new(NULL);
textview_m1 = gtk_text_view_new_with_buffer(textbuf_m1);
textview_m2 = gtk_text_view_new_with_buffer(textbuf_m2);
textview_pre = gtk_text_view_new_with_buffer(textbuf_pre);
textview_res = gtk_text_view_new_with_buffer(textbuf_res);
gtk_text_view_set_editable(GTK_TEXT_VIEW(textview_m1), FALSE);
gtk_text_view_set_editable(GTK_TEXT_VIEW(textview_m2), FALSE);
gtk_text_view_set_editable(GTK_TEXT_VIEW(textview_pre), FALSE);
gtk_text_view_set_editable(GTK_TEXT_VIEW(textview_res), FALSE);
gtk_container_add(GTK_CONTAINER(scrolledwindow_m1), textview_m1);
gtk_container_add(GTK_CONTAINER(scrolledwindow_m2), textview_m2);
gtk_container_add(GTK_CONTAINER(scrolledwindow_pre), textview_pre);
gtk_container_add(GTK_CONTAINER(scrolledwindow_res), textview_res);
gtk_container_add(GTK_CONTAINER(frame_m1), scrolledwindow_m1);
gtk_container_add(GTK_CONTAINER(frame_m2), scrolledwindow_m2);
gtk_container_add(GTK_CONTAINER(frame_res), scrolledwindow_res);
gtk_container_add(GTK_CONTAINER(frame_pre), scrolledwindow_pre);
gtk_container_add(GTK_CONTAINER(frame_list), scrolledwindow_list);
menubar = gtk_menu_bar_new();
gtk_box_pack_start(GTK_BOX(vbox_1), menubar, FALSE, TRUE, 0);
gtk_widget_show(menubar);
build_menu();
// add and show it
store = gtk_list_store_new(NUMBER_OF_COLUMNS, G_TYPE_INT, G_TYPE_STRING);
list_model = GTK_TREE_MODEL(store);
treeview = gtk_tree_view_new_with_model(list_model);
gtk_container_add(GTK_CONTAINER(scrolledwindow_list), treeview);
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
g_signal_connect (selection, "changed",
G_CALLBACK (selection_changed),
NULL);
// add the columns
add_columns_to_treeview(GTK_TREE_VIEW(treeview));
btn_sel_m1 = gtk_button_new_with_mnemonic("Select M_1");
btn_sel_m2 = gtk_button_new_with_mnemonic("Select M_2");
btn_del_m1 = gtk_button_new_with_mnemonic("U_nset M1");
btn_del_m2 = gtk_button_new_with_mnemonic("Un_set M2");
btn_del_all = gtk_button_new_with_mnemonic("Re_move all");
btn_del_chosen = gtk_button_new_with_mnemonic("Remove _chosen");
gtk_signal_connect(GTK_OBJECT(btn_sel_m1), "clicked",
GTK_SIGNAL_FUNC(btn_sel_m1_clicked), NULL);
gtk_signal_connect(GTK_OBJECT(btn_sel_m2), "clicked",
GTK_SIGNAL_FUNC(btn_sel_m2_clicked), NULL);
gtk_signal_connect(GTK_OBJECT(btn_del_m1), "clicked",
GTK_SIGNAL_FUNC(btn_del_m1_clicked), NULL);
gtk_signal_connect(GTK_OBJECT(btn_del_m2), "clicked",
GTK_SIGNAL_FUNC(btn_del_m2_clicked), NULL);
gtk_signal_connect(GTK_OBJECT(btn_del_all), "clicked",
GTK_SIGNAL_FUNC(btn_del_all_clicked), NULL);
gtk_signal_connect(GTK_OBJECT(btn_del_chosen), "clicked",
GTK_SIGNAL_FUNC(btn_del_chosen_clicked), NULL);
gtk_box_pack_start(GTK_BOX(hbox_1), btn_sel_m1, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(hbox_1), btn_sel_m2, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(hbox_2), btn_del_m1, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(hbox_2), btn_del_m2, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(hbox_3), btn_del_all, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(hbox_3), btn_del_chosen, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox_2_1), hbox_1, FALSE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox_2_1), hbox_2, FALSE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox_2_1), hbox_3, FALSE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox_2), frame_list, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox_2), vbox_2_1, FALSE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox_2), frame_pre, TRUE, TRUE, 0);
gtk_paned_pack1(GTK_PANED(hpaned_2), frame_m1, TRUE, TRUE);
gtk_paned_pack2(GTK_PANED(hpaned_2), frame_m2, TRUE, TRUE);
gtk_paned_pack1(GTK_PANED(vpaned), hpaned_2, TRUE, TRUE);
gtk_paned_pack2(GTK_PANED(vpaned), frame_res, TRUE, TRUE);
gtk_paned_pack1(GTK_PANED(hpaned), vbox_2, FALSE, FALSE);
gtk_paned_pack2(GTK_PANED(hpaned), vpaned, TRUE, TRUE);
gtk_container_add(GTK_CONTAINER(vbox_1), hpaned);
statusbar = gtk_statusbar_new();
gtk_box_pack_end(GTK_BOX(vbox_1), statusbar, FALSE, TRUE, 0);
gtk_container_add(GTK_CONTAINER(window), vbox_1);
gtk_widget_show(statusbar);
gtk_widget_show(btn_sel_m1);
gtk_widget_show(btn_sel_m2);
gtk_widget_show(btn_del_m1);
gtk_widget_show(btn_del_m2);
gtk_widget_show(btn_del_all);
gtk_widget_show(btn_del_chosen);
gtk_widget_show(treeview);
gtk_widget_show(hpaned);
gtk_widget_show(hpaned_2);
gtk_widget_show(vpaned);
gtk_widget_show(scrolledwindow_list);
gtk_widget_show(scrolledwindow_m1);
gtk_widget_show(scrolledwindow_m2);
gtk_widget_show(scrolledwindow_res);
gtk_widget_show(scrolledwindow_pre);
gtk_widget_show(frame_m1);
gtk_widget_show(frame_m2);
gtk_widget_show(frame_list);
gtk_widget_show(frame_pre);
gtk_widget_show(frame_res);
gtk_widget_show(textview_m1);
gtk_widget_show(textview_m2);
gtk_widget_show(textview_res);
gtk_widget_show(textview_pre);
gtk_widget_show(menuitem);
gtk_widget_show(menuMenu);
gtk_widget_show(menuMatrices);
gtk_widget_show(menuHelp);
gtk_widget_show(vbox_1);
gtk_widget_show(vbox_2);
gtk_widget_show(vbox_2_1);
gtk_widget_show(hbox_1);
gtk_widget_show(hbox_2);
gtk_widget_show(hbox_3);
gtk_widget_show(window);
gtk_main();
return 0;
}
// If not then run as normal
cout << APPNAME << " " << VERSION << " - Matrix Calculator\n"
<< "Copyright (c) " << CRYEAR << " " << DEVNAME << "\n"
<< "<" << DEVMAIL << ">\n\n"
<< "NOTE: To run the GTK version of this program\n"
<< " you can execute with the following option:\n"
<< " % " << argv[0] << " -gui\n\n"
<< "Type 'help' for usage information!" << endl;
string line = "", input = "";
while(1)
{
cout << "\n# ";
getline(cin, line);
if(line == "exit")
exit(0);
else if(line == "help")
{
cout << APPNAME << " is a program which can do calculations"
<< " on several matrices.\n\nBeneath is a list of"
<< " commands:\n"
<< " createm Create a matrix.\n"
<< " createrm Create a random matrix.\n"
<< " createum Create a unit-matrix.\n"
<< " delete Remove a given matrix.\n"
<< " deleteall Remove all matrices.\n\n"
<< " mul Multiplicate two matrices.\n"
<< " muln Multiplicate a matrix with a number.\n"
<< " add Add two matrices.\n"
<< " sub Subtract two matrices.\n"
<< " invert Invert a matrix.\n"
<< " trans Transpose a matrix.\n"
<< " det Get the determinant of a matrix.\n"
<< " show Print all matrices.\n\n"
<< " help Shows this information.\n"
<< " exit Exit the program." << endl;
}
else if(line == "createm" || line == "createrm")
{
int rows = get_input(2, "Define rows: ");
int columns = get_input(2, "Define columns: ");
matrix m(rows, columns);
if(line == "createm")
{
cout << "\nCreating a " << rows << "x" << columns << " matrix:\n";
for(int i=0; i<rows; i++)
{
for(int j=0; j<columns; j++)
{
float value;
while(1)
{
cout << "[" << i+1 << "," << j+1 << "] = ";
getline(cin, input);
value = atof(input.c_str());
if(value == NULL && !isdigit((char)input[0]))
cout << "Error: You have to input an integer!\n";
else
break;
}
m.set_value(i, j, value);
}
}
}
else
{
int from, to;
while(1)
{
from = get_input(3, "Random from: ");
to = get_input(3, "To max: ");
if(from > to)
cout << "Error: 'from' has to be smaller than or equal to 'max'\n";
else
break;
}
for(int i=0; i<rows; i++)
{
for(int j=0; j<columns; j++)
m.set_value(i, j, (float)random_number(from, to));
}
}
do_trivial(&m);
}
else if(line == "createum")
{
int order = get_input(1, "Define order: ");
matrix m(order, order);
cout << "\nCreating a " << order << "x" << order << " unit-matrix:\n";
int checker = 0, cnt = 0;
for(int i=0; i<order; i++)
{
for(int j=0; j<order; j++)
{
if(cnt == checker)
{
m.set_value(i, j, 1.0);
checker += order+1;
}
else
m.set_value(i, j, 0.0);
cnt++;
}
}
do_trivial(&m);
}
else if(line == "show")
{
if(matrix_vector.size() > 0)
{
for(vector<matrix>::iterator it = matrix_vector.begin();
it != matrix_vector.end();
it++)
{
cout << endl << "id: " << it->get_id() << endl;
it->print();
}
}
else
cout << "There are no matrices present!\nCreate one with the 'createm' command.\n";
}
else if(line == "mul")
{
matrix m1 = get_by_id(get_input(0, "Id of the first matrix: "));
matrix m2 = get_by_id(get_input(0, "Id of the second matrix: "));
if(m1.get_columns() == m2.get_rows())
{
matrix m = multiplicate(&m1, &m2);
do_trivial(&m);
}
else
cout << "Can't multiplicate two matrices when the first's number of columns is not equal to the second's number of rows!" << endl;
}
else if(line == "muln")
{
matrix tmp = get_by_id(get_input(0, "Id of matrix: "));
matrix m = multiplicate(&tmp, get_input_f(0, "Input the number to multiplicate with: "));
do_trivial(&m);
}
else if(line == "add")
{
matrix m1 = get_by_id(get_input(0, "Id of the first matrix: "));
matrix m2 = get_by_id(get_input(0, "Id of the second matrix: "));
if(m1.get_rows() == m2.get_rows() && m1.get_columns() == m2.get_columns())
{
matrix m = add(&m1, &m2);
do_trivial(&m);
}
else
cout << "Can't add two matrices when their rows and columns are not the same!" << endl;
}
else if(line == "sub")
{
matrix m1 = get_by_id(get_input(0, "Id of the first matrix: "));
matrix m2 = get_by_id(get_input(0, "Id of the second matrix: "));
if(m1.get_rows() == m2.get_rows() && m1.get_columns() == m2.get_columns())
{
matrix m = substract(&m1, &m2);
do_trivial(&m);
}
else
cout << "Can't substract two matrices when their rows and columns are not the same!" << endl;
}
else if(line == "delete")
{
int id = get_input(0, "Id to delete: ");
vector<matrix>::iterator loc;
for(loc = matrix_vector.begin();
loc != matrix_vector.end();
loc++)
{
if(loc->get_id() == id)
break;
}
matrix_vector.erase(loc);
}
else if(line == "deleteall")
{
matrix_vector.clear();
}
else if(line == "invert")
{
matrix tmp = get_by_id(get_input(0, "Id to invert: "));
matrix m = invert(&tmp);
do_trivial(&m);
}
else if(line == "trans")
{
matrix tmp = get_by_id(get_input(0, "Id to transpose: "));
matrix m = transpose(&tmp);
do_trivial(&m);
}
else if(line == "det")
{
int id = get_input(0, "Id to get the determinant of: ");
matrix tmp = get_by_id(id);
if(tmp.get_rows() == tmp.get_columns())
{
if(tmp.get_rows() == 1)
cout << "Determinant is: " << tmp.get_value(0, 0) << "\n";
else
cout << "Determinant is: " << determinant(&tmp) << "\n";
}
else
cout << "The matrix has to be square! 2x2, MxM etc.\n";
}
else
cout << "Command not recognized!\nTry 'help'.\n";
}
return 0;
}
/*
* Determines wether the id is in use or not
*/
int id_in_use(int id)
{
int exists = 0;
for(vector<matrix>::iterator it = matrix_vector.begin();
it != matrix_vector.end();
it++)
{
if(it->get_id() == id)
exists = 1;
}
return exists;
}
/*
* Retrieves the matrix of a given id
*/
matrix get_by_id(int id)
{
for(vector<matrix>::iterator it = matrix_vector.begin();
it != matrix_vector.end();
it++)
{
if(it->get_id() == id)
return *it;
}
}
/*
* Method to do trivial stuff.. Used often at the end of subrutines
*/
void do_trivial(matrix *m)
{
m->print();
m->set_id();
cout << "New matrix created, id: " << m->get_id() << endl;
matrix_vector.push_back(*m);
}
/*
* Gtk version of the above method
*/
void do_gtk_trivial(matrix *m)
{
m->set_id();
insert_matrix(textbuf_res, &(*m));
matrix_vector.push_back(*m);
update_tree_view();
}
/*
* Gets the input of the user
* Returns an integer
*/
int get_input(int type, string msg)
{
string input = "";
int res;
while(1)
{
cout << msg;
getline(cin, input);
res = atoi(input.c_str());
if(type == 0)
{
if(res == NULL || !id_in_use(res))
cout << "Error: You have to choose a correct id!\n";
else
break;
}
else if(type == 1)
{
if(res == NULL || res < 1)
cout << "Error: You have to input an integer greater than or equal to 1!\n";
else
break;
}
else if(type == 2)
{
if(res == NULL || res <= 0)
cout << "Error: You need to input an integer greater than zero!\n";
else
break;
}
else if(type == 3)
{
if(res == NULL && !isdigit((char)res))
cout << "Error: You have to input an integer!\n";
else
break;
}
}
return res;
}
/*
* Gets the input of the user
* Returns a float
*/
float get_input_f(int type, string msg)
{
string input = "";
float res;
while(1)
{
cout << msg;
getline(cin, input);
res = atof(input.c_str());
if(type == 0)
{
if(res == NULL)
cout << "Error: You have to input a non-zero number!\n";
else
break;
}
}
return res;
}
/*
* Method for building the GUI menu
*/
void build_menu()
{
/* Exit menu */
menuMenu = gtk_menu_item_new_with_mnemonic("M_enu");
gtk_menu_bar_append(GTK_MENU_BAR(menubar), menuMenu);
gtk_widget_show(menuMenu);
menu = gtk_menu_new();
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuMenu), menu);
menuitem = gtk_menu_item_new_with_mnemonic("Import matrix");
gtk_menu_append(GTK_MENU(menu), menuitem);
gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
GTK_SIGNAL_FUNC(menu_import_clicked), NULL);
gtk_widget_show(menuitem);
menuitem = gtk_menu_item_new_with_mnemonic("Export matrix");
gtk_menu_append(GTK_MENU(menu), menuitem);
gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
GTK_SIGNAL_FUNC(menu_export_clicked), NULL);
gtk_widget_show(menuitem);
menuitem = gtk_separator_menu_item_new();
gtk_menu_append(GTK_MENU(menu), menuitem);
gtk_widget_show(menuitem);
menuitem = gtk_menu_item_new_with_mnemonic("E_xit");
gtk_menu_append(GTK_MENU(menu), menuitem);
gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
GTK_SIGNAL_FUNC(destroy_app), NULL);
gtk_widget_show(menuitem);
/* Matrices menu */
menuMatrices = gtk_menu_item_new_with_mnemonic("M_atrices");
gtk_menu_bar_append(GTK_MENU_BAR(menubar), menuMatrices);
gtk_widget_show(menuMatrices);
menu = gtk_menu_new();
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuMatrices), menu);
menuitem = gtk_menu_item_new_with_mnemonic("Create _new matrix");
gtk_menu_append(GTK_MENU(menu), menuitem);
gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
GTK_SIGNAL_FUNC(menu_new_matrix), NULL);
gtk_widget_show(menuitem);
menuitem = gtk_menu_item_new_with_mnemonic("Create new _random matrix");
gtk_menu_append(GTK_MENU(menu), menuitem);
gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
GTK_SIGNAL_FUNC(menu_new_rnd_matrix), NULL);
gtk_widget_show(menuitem);
menuitem = gtk_menu_item_new_with_mnemonic("Create new _unit-matrix");
gtk_menu_append(GTK_MENU(menu), menuitem);
gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
GTK_SIGNAL_FUNC(menu_new_unit_matrix), NULL);
gtk_widget_show(menuitem);
/* Operations menu */
menuOperations = gtk_menu_item_new_with_mnemonic("O_perations");
gtk_menu_bar_append(GTK_MENU_BAR(menubar), menuOperations);
gtk_widget_show(menuOperations);
menu = gtk_menu_new();
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuOperations), menu);
menuitem = gtk_menu_item_new_with_mnemonic("M_ultiplicate (M1*M2)");
gtk_menu_append(GTK_MENU(menu), menuitem);
gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
GTK_SIGNAL_FUNC(menu_mul_clicked), NULL);
gtk_widget_show(menuitem);
menuitem = gtk_menu_item_new_with_mnemonic("A_dd (M1+M2)");
gtk_menu_append(GTK_MENU(menu), menuitem);
gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
GTK_SIGNAL_FUNC(menu_add_clicked), NULL);
gtk_widget_show(menuitem);
menuitem = gtk_menu_item_new_with_mnemonic("S_ubstract (M1-M2)");
gtk_menu_append(GTK_MENU(menu), menuitem);
gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
GTK_SIGNAL_FUNC(menu_sub_clicked), NULL);
gtk_widget_show(menuitem);
menuitem = gtk_menu_item_new_with_mnemonic("I_nvert (M1)");
gtk_menu_append(GTK_MENU(menu), menuitem);
gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
GTK_SIGNAL_FUNC(menu_invert_clicked), NULL);
gtk_widget_show(menuitem);
menuitem = gtk_menu_item_new_with_mnemonic("T_ranspose (M1)");
gtk_menu_append(GTK_MENU(menu), menuitem);
gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
GTK_SIGNAL_FUNC(menu_transpose_clicked), NULL);
gtk_widget_show(menuitem);
menuitem = gtk_menu_item_new_with_mnemonic("G_et determinant (M1)");
gtk_menu_append(GTK_MENU(menu), menuitem);
gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
GTK_SIGNAL_FUNC(menu_det_clicked), NULL);
gtk_widget_show(menuitem);
/* Help menu */
menuHelp = gtk_menu_item_new_with_mnemonic("He_lp");
gtk_menu_bar_append(GTK_MENU_BAR(menubar), menuHelp);
gtk_widget_show(menuHelp);
menu = gtk_menu_new();
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuHelp), menu);
menuitem = gtk_menu_item_new_with_mnemonic(string("A_bout "+string(APPNAME)).c_str());
gtk_menu_append(GTK_MENU(menu), menuitem);
gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
GTK_SIGNAL_FUNC(show_about), NULL);
gtk_widget_show(menuitem);
}
/*
* Executed when the list's selection changes
*/
static void selection_changed(GtkTreeSelection *selection)
{
GtkTreeModel *model;
GtkTreeIter iter;
if(gtk_tree_selection_get_selected(selection, &model, &iter))
{
gtk_tree_model_get(model, &iter, 0, &global_preview_id, -1);
// set the preview matrix
matrix m = get_by_id(global_preview_id);
insert_matrix(textbuf_pre, &m);
}
}
gint btn_sel_m1_clicked(GtkWidget *widget, gpointer gdata)
{
if(global_preview_id != -1)
{
matrix m = get_by_id(global_preview_id);
insert_matrix(textbuf_m1, &m);
m1 = global_preview_id;
gtk_frame_set_label(GTK_FRAME(frame_m1), to_string("[M1] Matrix 1: ID = "+to_string(m1)).c_str());
}
else
{
m1 = -1;
msgbox("Select a matrix first!", GTK_MESSAGE_INFO, GTK_BUTTONS_OK);
}
}
gint btn_sel_m2_clicked(GtkWidget *widget, gpointer gdata)
{
if(global_preview_id != -1)
{
matrix m = get_by_id(global_preview_id);
insert_matrix(textbuf_m2, &m);
m2 = global_preview_id;
gtk_frame_set_label(GTK_FRAME(frame_m2), to_string("[M2] Matrix 2: ID = "+to_string(m2)).c_str());
}
else
{
m2 = -1;
msgbox("Select a matrix first!", GTK_MESSAGE_INFO, GTK_BUTTONS_OK);
}
}
gint btn_del_m1_clicked(GtkWidget *widget, gpointer gdata)
{
gtk_text_buffer_set_text(textbuf_m1, "", 0);
gtk_frame_set_label(GTK_FRAME(frame_m1), "[M1] Matrix 1:");
}
gint btn_del_m2_clicked(GtkWidget *widget, gpointer gdata)
{
gtk_text_buffer_set_text(textbuf_m2, "", 0);
gtk_frame_set_label(GTK_FRAME(frame_m2), "[M2] Matrix 2:");
}
gint btn_del_all_clicked(GtkWidget *widget, gpointer gdata)
{
matrix_vector.clear();
update_tree_view();
global_preview_id = -1;
gtk_text_buffer_set_text(textbuf_pre, "", 0);
gtk_text_buffer_set_text(textbuf_m1, "", 0);
gtk_text_buffer_set_text(textbuf_m2, "", 0);
gtk_text_buffer_set_text(textbuf_res, "", 0);
gtk_frame_set_label(GTK_FRAME(frame_m1), "[M1] Matrix 1:");
gtk_frame_set_label(GTK_FRAME(frame_m2), "[M2] Matrix 2:");
gtk_frame_set_label(GTK_FRAME(frame_res), "Result Matrix:");
}
gint btn_del_chosen_clicked(GtkWidget *widget, gpointer gdata)
{
if(global_preview_id != -1)
{
vector<matrix>::iterator loc;
for(loc = matrix_vector.begin(); loc != matrix_vector.end(); loc++)
{
if(loc->get_id() == global_preview_id)
break;
}
matrix_vector.erase(loc);
update_tree_view();
}
else
msgbox("Select a matrix first!", GTK_MESSAGE_INFO, GTK_BUTTONS_OK);
}
/*
* Updates the treeview with the matrices
* stored in the vector
*/
void update_tree_view()
{
gtk_list_store_clear(store);
vector<matrix>::iterator loc;
for(loc = matrix_vector.begin(); loc != matrix_vector.end(); loc++)
add_matrix_to_treeview(GTK_TREE_VIEW(treeview), &(*loc), GTK_LIST_STORE(store));
gtk_tree_view_set_model(GTK_TREE_VIEW(treeview), GTK_TREE_MODEL(store));
}
/*
* Shows a dialog for defining rows, columns and
* orders of matrices to create.
*
* type:
* 0 = rows + columns (matrix)
* 1 = order (unit matrix)
* 2 = random (matrix)
*/
void interactive_dialog(int type)
{
global_rows = global_columns = -1;
GtkWidget *dialog, *hbox, *stock, *table, *local_entry1,
*local_entry2, *label, *local_entry3, *local_entry4;
gint response;
dialog = gtk_dialog_new_with_buttons ("New matrix: Define dimensions.",
GTK_WINDOW (window), GTK_DIALOG_MODAL,
GTK_STOCK_OK, GTK_RESPONSE_OK,
"_Cancel", GTK_RESPONSE_CANCEL,
NULL);
hbox = gtk_hbox_new (FALSE, 8);
gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox, TRUE, TRUE, 0);
stock = gtk_image_new_from_stock (GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG);
gtk_box_pack_start (GTK_BOX (hbox), stock, FALSE, FALSE, 0);
if(type == 0 || type == 1)
table = gtk_table_new (2, 2, FALSE);
else
table = gtk_table_new (2, 4, FALSE);
gtk_table_set_row_spacings (GTK_TABLE (table), 4);
gtk_table_set_col_spacings (GTK_TABLE (table), 4);
gtk_box_pack_start (GTK_BOX (hbox), table, TRUE, TRUE, 0);
if(type == 0 || type == 2)
{
label = gtk_label_new_with_mnemonic ("Ro_ws");
gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 0, 1);
local_entry1 = gtk_entry_new ();
gtk_entry_set_text (GTK_ENTRY (local_entry1), to_string("1").c_str());
gtk_table_attach_defaults (GTK_TABLE (table), local_entry1, 1, 2, 0, 1);
gtk_label_set_mnemonic_widget (GTK_LABEL (label), local_entry1);
label = gtk_label_new_with_mnemonic ("Co_lmns");
gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 1, 2);
local_entry2 = gtk_entry_new ();
gtk_entry_set_text (GTK_ENTRY (local_entry2), to_string("1").c_str());
gtk_table_attach_defaults (GTK_TABLE (table), local_entry2, 1, 2, 1, 2);
gtk_label_set_mnemonic_widget (GTK_LABEL (label), local_entry2);
if(type == 2)
{
label = gtk_label_new_with_mnemonic ("R_andom from:");
gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 2, 3);
local_entry3 = gtk_entry_new ();
gtk_entry_set_text (GTK_ENTRY (local_entry3), to_string("1").c_str());
gtk_table_attach_defaults (GTK_TABLE (table), local_entry3, 1, 2, 2, 3);
gtk_label_set_mnemonic_widget (GTK_LABEL (label), local_entry3);
label = gtk_label_new_with_mnemonic ("T_o max:");
gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 3, 4);
local_entry4 = gtk_entry_new ();
gtk_entry_set_text (GTK_ENTRY (local_entry4), to_string("100").c_str());
gtk_table_attach_defaults (GTK_TABLE (table), local_entry4, 1, 2, 3, 4);
gtk_label_set_mnemonic_widget (GTK_LABEL (label), local_entry4);
}
}
else if(type == 1)
{
label = gtk_label_new_with_mnemonic ("O_rder");
gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 0, 1);
local_entry1 = gtk_entry_new ();
gtk_entry_set_text (GTK_ENTRY (local_entry1), to_string("1").c_str());
gtk_table_attach_defaults (GTK_TABLE (table), local_entry1, 1, 2, 0, 1);
gtk_label_set_mnemonic_widget (GTK_LABEL (label), local_entry1);
}
gtk_widget_show_all(hbox);
response = gtk_dialog_run(GTK_DIALOG (dialog));
if(response == GTK_RESPONSE_OK)
{
if(type == 0)
{
string rows = gtk_entry_get_text(GTK_ENTRY (local_entry1));
string cols = gtk_entry_get_text(GTK_ENTRY (local_entry2));
global_rows = atoi(rows.c_str());
global_columns = atoi(cols.c_str());
if(global_rows == NULL || global_columns == NULL)
{
global_columns = global_rows = -1;
msgbox("You have to input integers greater than zero!", GTK_MESSAGE_INFO, GTK_BUTTONS_OK);
}
}
else if(type == 1)
{
string order = gtk_entry_get_text(GTK_ENTRY(local_entry1));
global_order = atoi(order.c_str());
if(global_order == NULL)
{
global_order = -1;
msgbox("You have to input an integer greater than zero!", GTK_MESSAGE_INFO, GTK_BUTTONS_OK);
}
}
else if(type == 2)
{
string rows = gtk_entry_get_text(GTK_ENTRY (local_entry1));
string cols = gtk_entry_get_text(GTK_ENTRY (local_entry2));
string from = gtk_entry_get_text(GTK_ENTRY (local_entry3));
string to = gtk_entry_get_text(GTK_ENTRY (local_entry4));
global_rows = atoi(rows.c_str());
global_columns = atoi(cols.c_str());
global_from = atoi(from.c_str());
global_to = atoi(to.c_str());
if(global_rows == NULL || global_columns == NULL ||
(!isdigit((char)from.c_str()[0]) &&
to_string(from.c_str()[0]) != "-") ||
(!isdigit((char)to.c_str()[0]) &&
to_string(to.c_str()[0]) != "-"))
{
global_rows = global_columns = -1;
msgbox("You have to input an integer greater than zero for rows and columns. And for random 'from' to 'max' needs to be a valid integer!", GTK_MESSAGE_INFO, GTK_BUTTONS_OK);
}
}
}
else
global_rows = global_columns = -1;
gtk_widget_destroy(dialog);
}
gint menu_new_matrix(GtkWidget *widget, gpointer gdata)
{
interactive_dialog(0);
if(global_rows > 0 && global_columns > 0)
define_matrix_dialog();
}
/*
* Shows a dialog to fill in the contents of the matrix
*/
void define_matrix_dialog()
{
if((global_rows * global_columns) > 1000)
{
msgbox(to_string("You're trying to create "+to_string(global_rows*global_columns)+" fields which will take up quite a bit of memory! The limit is set to a 1000 fields which is also very many to fill out manually; It is better to import matrices of that size from the menu.\n\nThe format of these matrices is as follows:\n\nnumber of rows<linebreak>\nnumber of columns<linebreak>\nall data chronically separated by commas and with no whitespace\n\nExample:\n2\n2\n1,2,3,4\n\nWill represent:\n\t1\t2\n\t3\t4\n\nRemember that there can only be ONE matrix in each file!"), GTK_MESSAGE_INFO, GTK_BUTTONS_OK);
return;
}
GtkWidget *dialog, *table, *sw;
gint response;
vector<GtkWidget*> entries;
int w, h;
dialog = gtk_dialog_new_with_buttons ("New matrix: Fill in the context.",
GTK_WINDOW (window), GTK_DIALOG_MODAL,
GTK_STOCK_OK, GTK_RESPONSE_OK,
"_Cancel", GTK_RESPONSE_CANCEL,
NULL);
w = global_columns*53;
if(w > 800)
w = 800;
h = global_rows*27;
if(h > 600)
h = 600;
gtk_window_set_default_size(GTK_WINDOW(dialog), w, h);
table = gtk_table_new(global_rows, global_columns, TRUE);
sw = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw), table);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), sw, TRUE, TRUE, 0);
for(int i=0; i<global_rows; i++)
{
for(int j=0; j<global_columns; j++)
{
GtkWidget *entry = gtk_entry_new_with_max_length(7);
gtk_widget_set_size_request(entry, 50, 15);
gtk_table_attach(GTK_TABLE(table), entry, j, j+1, i, i+1, GTK_EXPAND, GTK_EXPAND, 0, 0);
entries.push_back(entry);
}
}
matrix response_matrix(global_rows, global_columns);
gtk_widget_show_all (table);
gtk_widget_show(sw);
response = gtk_dialog_run (GTK_DIALOG (dialog));
if(response == GTK_RESPONSE_OK)
{
int i = 0;
for(vector<GtkWidget*>::iterator it = entries.begin();
it != entries.end(); it++)
{
string input = to_string(gtk_entry_get_text(GTK_ENTRY(*it))).c_str();
float value = strtod(input.c_str(), 0);
if(value == NULL && !isdigit((char)input.c_str()[0]))
{
msgbox("Everything you input has to be floats! (fx.: 11.2)",
GTK_MESSAGE_INFO, GTK_BUTTONS_OK);
break;
}
else
{
response_matrix.set_value_t(i, value);
i++;
}
}
if(i == entries.size())
{
response_matrix.set_id();
matrix_vector.push_back(response_matrix);
update_tree_view();
}
}
gtk_widget_destroy(dialog);
}
gint menu_new_rnd_matrix(GtkWidget *widget, gpointer gdata)
{
interactive_dialog(2);
if(global_rows > 0 && global_columns > 0)
{
matrix m(global_rows, global_columns);
for(int i=0; i<global_rows; i++)
{
for(int j=0; j<global_columns; j++)
m.set_value(i, j, (float)random_number(global_from, global_to));
}
m.set_id();
matrix_vector.push_back(m);
update_tree_view();
}
}
gint menu_new_unit_matrix(GtkWidget *widget, gpointer gdata)
{
interactive_dialog(1);
if(global_order > 0)
{
matrix m(global_order, global_order);
int checker = 0, cnt = 0;
for(int i=0; i<global_order; i++)
{
for(int j=0; j<global_order; j++)
{
if(cnt == checker)
{
m.set_value(i, j, 1.0);
checker += global_order+1;
}
else
m.set_value(i, j, 0.0);
cnt++;
}
}
m.set_id();
matrix_vector.push_back(m);
update_tree_view();
}
}
gint menu_mul_clicked(GtkWidget *widget, gpointer gdata)
{
if(m1 != -1 && m2 != -1)
{
matrix m_1 = get_by_id(m1);
matrix m_2 = get_by_id(m2);
matrix res;
int set_ = 0;
if(m_1.get_rows() == 1 && m_1.get_columns() == 1)
{
res = multiplicate(&m_2, m_1.get_value(0, 0));
set_ = 1;
}
else if(m_2.get_rows() == 1 && m_2.get_columns() == 1)
{
res = multiplicate(&m_1, &m_2);
set_ = 1;
}
else if(m_1.get_rows() == m_2.get_columns())
{
res = multiplicate(&m_1, &m_2);
set_ = 1;
}
else
msgbox("You cannot multiply two matrices when the first one's rows doesn't match the second one's columns", GTK_MESSAGE_INFO, GTK_BUTTONS_OK);
if(set_)
{
do_gtk_trivial(&res);
set_statusbar_text("The multiplication of M1 and M2 created a new matrix, id: "+
to_string(res.get_id()));
}
}
else
msgbox("You have to set both M1 and M2!", GTK_MESSAGE_INFO, GTK_BUTTONS_OK);
}
gint menu_add_clicked(GtkWidget *widget, gpointer gdata)
{
if(m1 != -1 && m2 != -1)
{
matrix m1_1 = get_by_id(m1);
matrix m2_1 = get_by_id(m2);
if(m1_1.get_rows() == m2_1.get_rows() && m1_1.get_columns() == m2_1.get_columns())
{
matrix m = add(&m1_1, &m2_1);
do_gtk_trivial(&m);
set_statusbar_text("The addition of M1 and M2 created a new matrix, id: "+
to_string(m.get_id()));
}
else
{
msgbox("Can't add two matrices when their rows and columns are not the same!",
GTK_MESSAGE_INFO, GTK_BUTTONS_OK);
}
}
else
msgbox("You have to set both M1 and M2!", GTK_MESSAGE_INFO, GTK_BUTTONS_OK);
}
gint menu_sub_clicked(GtkWidget *widget, gpointer gdata)
{
if(m1 != -1 && m2 != -1)
{
matrix m1_1 = get_by_id(m1);
matrix m2_1 = get_by_id(m2);
if(m1_1.get_rows() == m2_1.get_rows() && m1_1.get_columns() == m2_1.get_columns())
{
matrix m = substract(&m1_1, &m2_1);
do_gtk_trivial(&m);
set_statusbar_text("The substraction of M1 and M2 created a new matrix, id: "+
to_string(m.get_id()));
}
else
{
msgbox("Can't substract two matrices when their rows and columns are not the same!",
GTK_MESSAGE_INFO, GTK_BUTTONS_OK);
}
}
else
msgbox("You have to set both M1 and M2!", GTK_MESSAGE_INFO, GTK_BUTTONS_OK);
}
gint menu_invert_clicked(GtkWidget *widget, gpointer gdata)
{
if(m1 != -1)
{
matrix tmp = get_by_id(m1);
matrix m = invert(&tmp);
do_gtk_trivial(&m);
set_statusbar_text("The invertion of M1 created a new matrix, id: "+
to_string(m.get_id()));
}
else
msgbox("You have to set both M1!", GTK_MESSAGE_INFO, GTK_BUTTONS_OK);
}
gint menu_transpose_clicked(GtkWidget *widget, gpointer gdata)
{
if(m1 != -1)
{
matrix tmp = get_by_id(m1);
matrix m = transpose(&tmp);
do_gtk_trivial(&m);
set_statusbar_text("The transposition of M1 created a new matrix, id: "+
to_string(m.get_id()));
}
else
msgbox("You have to set both M1!", GTK_MESSAGE_INFO, GTK_BUTTONS_OK);
}
gint menu_det_clicked(GtkWidget *widget, gpointer gdata)
{
if(m1 != -1)
{
matrix tmp = get_by_id(m1);
if(tmp.get_rows() == tmp.get_columns())
{
if(tmp.get_rows() == 1)
{
msgbox(to_string("Determinant is: "+to_string(tmp.get_value(0, 0))).c_str(),
GTK_MESSAGE_INFO, GTK_BUTTONS_OK);
}
else
{
msgbox(to_string("Determinant is: "+to_string(determinant(&tmp))).c_str(),
GTK_MESSAGE_INFO, GTK_BUTTONS_OK);
}
}
else
msgbox("The matrix has to be square! 2x2, MxM etc.",
GTK_MESSAGE_INFO, GTK_BUTTONS_OK);
}
else
msgbox("You have to set both M1!", GTK_MESSAGE_INFO, GTK_BUTTONS_OK);
}
/*
* Sets the text of the statusbar
*/
void set_statusbar_text(string text)
{
gtk_statusbar_pop(GTK_STATUSBAR(statusbar), 0);
gtk_statusbar_push(GTK_STATUSBAR(statusbar),
gtk_statusbar_get_context_id(GTK_STATUSBAR(statusbar), "don't care"),
text.c_str());
}
gint menu_import_clicked(GtkWidget *widget, gpointer gdata)
{
GtkWidget *filechooser;
filechooser = gtk_file_chooser_dialog_new("Choose a file containing a matrix to open",
GTK_WINDOW(window), GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN,
GTK_RESPONSE_ACCEPT, NULL);
if(gtk_dialog_run(GTK_DIALOG(filechooser)) == GTK_RESPONSE_ACCEPT)
{
string filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filechooser));
// convert filename into UTF-8
GError *err = NULL;
gchar *utf8_filename = g_filename_to_utf8(filename.c_str(), filename.length(),
NULL, NULL, &err);
if(utf8_filename == NULL)
{
msgbox("Error: " + string(err->message), GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE);
return 1;
}
ifstream reader(utf8_filename);
string line, contents = "";
if(reader.is_open())
{
int r, c, i = 0;
while(!reader.eof())
{
getline(reader, line);
if(i == 0)
r = atoi(line.c_str());
else if(i == 1)
c = atoi(line.c_str());
else
contents += line;
i++;
}
reader.close();
if(contents != "")
{
// convert the contents to UTF-8
gchar *utf8_data = g_convert(contents.c_str(), contents.length(),
"UTF-8", "", NULL, NULL, NULL);
// create matrix
if(r == NULL || c == NULL)
{
msgbox("Error while importing matrix! The contents of the file is not valid!",
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE);
}
else
{
string dat = to_string(utf8_data);
matrix m = gen_matrix_from_text(r, c, dat);
m.set_id();
matrix_vector.push_back(m);
update_tree_view();
set_statusbar_text("Imported matrix, id: "+to_string(m.get_id()));
}
}
}
else
msgbox("An error occurred while trying to read from: " + string(filename), GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE);
}
gtk_widget_destroy(filechooser);
}
gint menu_export_clicked(GtkWidget *widget, gpointer gdata)
{
GtkWidget *filechooser;
if(global_preview_id != -1)
{
filechooser = gtk_file_chooser_dialog_new("Save file",
GTK_WINDOW(window), GTK_FILE_CHOOSER_ACTION_SAVE,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE,
GTK_RESPONSE_ACCEPT, NULL);
// ask for confirmation when overwriting a file in the dialog
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(filechooser), TRUE);
if(gtk_dialog_run(GTK_DIALOG(filechooser)) == GTK_RESPONSE_ACCEPT)
{
string filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filechooser));
GError *err = NULL;
gchar *utf8_filename = g_filename_to_utf8(filename.c_str(), filename.length(),
NULL, NULL, &err);
if(utf8_filename == NULL)
{
msgbox("Error: " + string(err->message), GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE);
return 1;
}
matrix ex = get_by_id(global_preview_id);
ofstream writer(utf8_filename);
if(writer.is_open())
{
writer << export_matrix(&ex);
writer.close();
set_statusbar_text("Exported matrix (id="+to_string(global_preview_id)+") to: "+filename);
}
else
msgbox("An error occurred while trying to write to: " + string(utf8_filename), GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE);
}
gtk_widget_destroy(filechooser);
}
else
msgbox("You have to select the matrix in the list to export!", GTK_MESSAGE_INFO, GTK_BUTTONS_OK);
}
syntax highlighted by Code2HTML, v. 0.9.1