#include "Cadabra.hh" #include #include #include #include #if GTKMM_MINOR_VERSION < 10 #include #endif #include #include #include "Snoop.hh" #include "Config.hh" // Signal handler for ctrl-C cadabra::NotebookWindow *signal_window; void signal_handler(int) { #if GTKMM_MINOR_VERSION >= 10 signal_window->close(); #else Gtk::Main::quit(); #endif } Glib::RefPtr Cadabra::create(int argc, char **argv) { return Glib::RefPtr( new Cadabra(argc, argv) ); } Cadabra::Cadabra(int argc, char **argv) : Gtk::Application(argc, argv, "science.cadabra.cadabra2-gtk", Gio::APPLICATION_HANDLES_OPEN | Gio::APPLICATION_NON_UNIQUE), compute(0), compute_thread(0), server_port(0), server_ip_address("127.0.0.1") { // https://stackoverflow.com/questions/43886686/how-does-one-make-gtk3-look-native-on-windows-7 // https://github.com/shoes/shoes3/wiki/Changing-Gtk-theme-on-Windows #if defined(_WIN32) // Gtk::Settings::get_default()->property_gtk_theme_name()="win32"; #endif //https://github.com/GNOME/gtkmm-documentation/blob/master/examples/book/application/command_line_handling/exampleapplication.cc signal_handle_local_options().connect( sigc::mem_fun(*this, &Cadabra::on_handle_local_options), false); add_main_option_entry(Gio::Application::OptionType::OPTION_TYPE_INT, "server-port", 's', "Connect to running server on given port.", "number"); add_main_option_entry(Gio::Application::OptionType::OPTION_TYPE_STRING, "server-ip-address", 'a', "Connect to running server on given ip address.", "string"); add_main_option_entry(Gio::Application::OptionType::OPTION_TYPE_FILENAME, "token", 't', "Use the given authentication token to connect to the server.", "string"); } template static bool get_arg_value(const Glib::RefPtr& options, const Glib::ustring& arg_name, T_ArgType& arg_value) { arg_value = T_ArgType(); if(options->lookup_value(arg_name, arg_value)) return true; else return false; } Cadabra::~Cadabra() { // The app is going away; stop the compute logic and join that // thread waiting for it to complete. if(compute) compute->terminate(); if(compute_thread) compute_thread->join(); if(compute) delete compute; if(compute_thread) delete compute_thread; // for(auto w: windows) // delete w; } int Cadabra::on_handle_local_options(const Glib::RefPtr& options) { if(!options) return -1; get_arg_value(options, "server-port", server_port); get_arg_value(options, "server-ip-address", server_ip_address); get_arg_value(options, "token", server_token); // std::cerr << server_port << ", " << server_token << std::endl; return -1; } void Cadabra::on_startup() { Gtk::Application::on_startup(); } void Cadabra::on_activate() { compute = new cadabra::ComputeThread(server_port, server_token, server_ip_address); compute_thread = new std::thread(&cadabra::ComputeThread::run, compute); auto nw = new cadabra::NotebookWindow(this); compute->set_master(nw, nw); // Connect the two threads. nw->set_compute_thread(compute); // Setup ctrl-C handler so we can shut down gracefully (i.e. ask // for confirmation, shut down server). signal_window = nw; signal(SIGINT, signal_handler); add_window(*nw); nw->show(); std::string version=std::string(CADABRA_VERSION_MAJOR)+"."+CADABRA_VERSION_MINOR+"."+CADABRA_VERSION_PATCH; snoop::log("start") << version << snoop::flush; if(!nw->prefs.is_registered && !nw->prefs.is_anonymous) { nw->on_help_register(); } } void Cadabra::on_open(const Gio::Application::type_vec_files& files, const Glib::ustring& hint) { on_activate(); // Load the first file into a string. char* contents = nullptr; gsize length = 0; std::string text; bool file_exists=false; try { if(files[0]->load_contents(contents, length)) { if(contents && length) { text=std::string(contents); } g_free(contents); } file_exists=true; } catch (const Glib::Error& ex) { // std::cerr << "Open error: " << ex.what() << std::endl; // File cannot be opened, assume the user wants to create a // new file with this name. file_exists=false; } // Tell the window to open the notebook stored in the string. auto wins = get_windows(); auto nw = static_cast(wins[0]); nw->set_name(files[0]->get_path()); snoop::log("open") << "command-line" << snoop::flush; if(file_exists) { nw->load_file(text); Gtk::Application::on_open(files, hint); } } bool Cadabra::open_help(const std::string& nm, const std::string& title) { #ifdef DEBUG std::cerr << "Opening help file " << nm << std::endl; #endif std::ifstream fl(nm); if(fl) { auto nw = new cadabra::NotebookWindow(this, true); nw->set_title_prefix("Cadabra help for "); nw->set_name(title); add_window(*nw); std::stringstream buffer; buffer << fl.rdbuf(); nw->load_file(buffer.str()); nw->show(); return true; } else return false; }