📄 mainwindow.cpp
字号:
/* Copyright (C) 2001 to 2004 Chris VineThis program is distributed under the General Public Licence, version 2.For particulars of this and relevant disclaimers see the fileCOPYING distributed with the source files.*/#include <sys/types.h>#include <unistd.h>#include <signal.h>#include <sys/wait.h>#include <sys/stat.h>#include <ctime>#include <cstdlib>#include <cstring>// we only need to include iostream if we are doing debugging// in childexit_signalhandler()//#include <iostream>#include <gtkmm/menu.h>#include <gtkmm/image.h>#include <gtkmm/style.h>#include <gdkmm/color.h>#include <gdkmm/colormap.h>#include <gdkmm/pixbuf.h>#include <gdkmm/gc.h>#include <glibmm/main.h>#include <glibmm/convert.h>#include "mainwindow.h"#include "dialogs.h"#include "addressbook.h"#include "file_list.h"#include "settings.h"#include "socket_notify.h"#ifdef ENABLE_NLS#include <libintl.h>#endif#define TIMER_INTERVAL 200 // number of milliseconds between timer events for the main timer#define LOGFILE_TIMER_INTERVAL 60000 // number of milliseconds between flushing of logfileextern "C" void childexit_signalhandler(int);extern "C" void close_signalhandler(int);static volatile sig_atomic_t close_flag = false;Pipe_fifo MainWindow::error_pipe(Pipe_fifo::non_block);bool MainWindow::connected_to_stderr = false;MainWindow::MainWindow(const std::string& messages, const char* filename): // filename has a default value of 0 Gtk::Window(Gtk::WINDOW_TOPLEVEL), standard_size(24), file_entry_table(3, 3, false), win_table(5, 3, false), file_entry_frame(gettext("Fax to send")), file_button(gettext("File ")), socket_button(gettext("Socket")), fax_method_label(gettext("Fax entry method: ")), single_file_button(gettext("Single file")), multiple_file_button(gettext("Multiple files")), socket_list_button(gettext("Socket list")), number_button(gettext("Tel number: ")), send_button(gettext("Send fax")), receive_answer_button(gettext("Answer call")), receive_takeover_button(gettext("Take over call")), receive_standby_button(gettext("Standby")), stop_button(gettext("Stop")), status_line(standard_size) { // catch any relevant Unix signals for an orderly closedown // catch SIGQUIT, SIGTERM SIGINT SIGHUP // it is safe to use signal() for these signal(SIGQUIT, close_signalhandler); signal(SIGTERM, close_signalhandler); signal(SIGINT, close_signalhandler); signal(SIGHUP, close_signalhandler); // ignore SIGPIPE struct sigaction sig_act_pipe; sig_act_pipe.sa_handler = SIG_IGN; // we don't need to mask off any signals sigemptyset(&sig_act_pipe.sa_mask); sig_act_pipe.sa_flags = 0; sigaction(SIGPIPE, &sig_act_pipe, 0); // set up child signal handler struct sigaction sig_act_chld; sig_act_chld.sa_handler = childexit_signalhandler; // we don't need to mask off any signals sigemptyset(&sig_act_chld.sa_mask);#ifdef SA_RESTART sig_act_chld.sa_flags = SA_NOCLDSTOP | SA_RESTART;#else sig_act_chld.sa_flags = SA_NOCLDSTOP;#endif sigaction(SIGCHLD, &sig_act_chld, 0); get_longest_button_text(); Gtk::RadioButton::Group class_group(file_button.get_group()); socket_button.set_group(class_group); file_button.set_active(true); fax_method_radio_box.pack_start(file_button, false, false, 0); fax_method_radio_box.pack_start(socket_button, false, false, 0); fax_method_radio_frame.add(fax_method_radio_box); fax_method_box.pack_start(fax_method_label, false, false, 0); fax_method_box.pack_start(fax_method_radio_frame, false, false, 0); fax_method_box.pack_start(fax_method_filler, true, false, 0); fax_method_box.pack_start(drawing_area, false, false, 0); file_entry_table.attach(file_entry, 0, 3, 0, 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, standard_size/3, standard_size/3); file_entry_table.attach(fax_method_box, 0, 3, 1, 2, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, standard_size/3, standard_size/3); file_entry_table.attach(single_file_button, 0, 1, 2, 3, Gtk::EXPAND, Gtk::SHRINK, standard_size/3, standard_size/3); file_entry_table.attach(multiple_file_button, 1, 2, 2, 3, Gtk::EXPAND, Gtk::SHRINK, standard_size/3, standard_size/3); file_entry_table.attach(socket_list_button, 2, 3, 2, 3, Gtk::EXPAND, Gtk::SHRINK, standard_size/3, standard_size/3); file_entry_frame.add(file_entry_table); number_box.pack_start(number_button, false, false, standard_size/2); number_box.pack_start(number_entry, true, true, 0); win_table.attach(file_entry_frame, 0, 3, 0, 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, standard_size/3, standard_size/3); win_table.attach(number_box, 0, 3, 1, 2, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, standard_size/3, standard_size/3); win_table.attach(text_window, 0, 3, 2, 3, Gtk::EXPAND | Gtk::FILL, Gtk::EXPAND | Gtk::FILL, standard_size/3, standard_size/3); win_table.attach(send_button, 0, 1, 3, 4, Gtk::EXPAND, Gtk::SHRINK, standard_size/3, standard_size/3); win_table.attach(receive_answer_button, 1, 2, 3, 4, Gtk::EXPAND, Gtk::SHRINK, standard_size/3, standard_size/3); win_table.attach(receive_takeover_button, 2, 3, 3, 4, Gtk::EXPAND, Gtk::SHRINK, standard_size/3, standard_size/3); win_table.attach(receive_standby_button, 0, 1, 4, 5, Gtk::EXPAND, Gtk::SHRINK, standard_size/3, standard_size/3); win_table.attach(stop_button, 2, 3, 4, 5, Gtk::EXPAND, Gtk::SHRINK, standard_size/3, standard_size/3); file_button.signal_clicked().connect(sigc::mem_fun(*this, &MainWindow::set_file_items_sensitive_slot)); socket_button.signal_clicked().connect(sigc::mem_fun(*this, &MainWindow::set_socket_items_sensitive_slot)); single_file_button.signal_clicked().connect(sigc::mem_fun(*this, &MainWindow::get_file_slot)); multiple_file_button.signal_clicked().connect(sigc::mem_fun(*this, &MainWindow::file_list_slot)); socket_list_button.signal_clicked().connect(sigc::mem_fun(*this, &MainWindow::socket_list_slot)); number_button.signal_clicked().connect(sigc::mem_fun(*this, &MainWindow::addressbook_slot)); send_button.signal_clicked().connect(sigc::mem_fun(*this, &MainWindow::sendfax_slot)); receive_answer_button.signal_clicked().connect(sigc::bind(sigc::mem_fun(*this, &MainWindow::receive_slot), static_cast<int>(EfaxController::receive_answer))); receive_takeover_button.signal_clicked().connect(sigc::bind(sigc::mem_fun(*this, &MainWindow::receive_slot), static_cast<int>(EfaxController::receive_takeover))); receive_standby_button.signal_clicked().connect(sigc::bind(sigc::mem_fun(*this, &MainWindow::receive_slot), static_cast<int>(EfaxController::receive_standby))); stop_button.signal_clicked().connect(sigc::mem_fun(efax_controller, &EfaxController::stop_slot)); single_file_button.set_flags(Gtk::CAN_DEFAULT); multiple_file_button.set_flags(Gtk::CAN_DEFAULT); socket_list_button.set_flags(Gtk::CAN_DEFAULT); number_button.set_flags(Gtk::CAN_DEFAULT); send_button.set_flags(Gtk::CAN_DEFAULT); receive_answer_button.set_flags(Gtk::CAN_DEFAULT); receive_takeover_button.set_flags(Gtk::CAN_DEFAULT); receive_standby_button.set_flags(Gtk::CAN_DEFAULT); stop_button.set_flags(Gtk::CAN_DEFAULT); // set up the menu bar { using namespace Gtk::Menu_Helpers; // Create the file menu Gtk::Menu* file_menu_p = manage(new Gtk::Menu); // now fill the file menu MenuList& file_list = file_menu_p->items(); file_list.push_back(MenuElem(gettext("List _received faxes"), sigc::bind(sigc::mem_fun(*this, &MainWindow::fax_list_slot), FaxListDialog::received))); file_list.push_back(MenuElem(gettext("_List sent faxes"), sigc::bind(sigc::mem_fun(*this, &MainWindow::fax_list_slot), FaxListDialog::sent))); file_list.push_back(SeparatorElem()); file_list.push_back(MenuElem(gettext("Queued _faxes from socket"), sigc::mem_fun(*this, &MainWindow::socket_list_slot))); // save this menu item for future use socket_list_item_p = &file_list.back(); file_list.push_back(MenuElem(gettext("_Enter single file"), sigc::mem_fun(*this, &MainWindow::get_file_slot))); // save this menu item for future use single_file_item_p = &file_list.back(); file_list.push_back(MenuElem(gettext("Enter _multiple files"), sigc::mem_fun(*this, &MainWindow::file_list_slot))); // save this menu item for future use multiple_file_item_p = &file_list.back(); file_list.push_back(SeparatorElem()); file_list.push_back(MenuElem(gettext("_Address book"), sigc::mem_fun(*this, &MainWindow::addressbook_slot))); file_list.push_back(SeparatorElem()); file_list.push_back(MenuElem(gettext("_Settings"), sigc::mem_fun(*this, &MainWindow::settings_slot))); file_list.push_back(SeparatorElem()); file_list.push_back(MenuElem(gettext("_Quit"), sigc::mem_fun(*this, &MainWindow::quit_slot))); // Create the about menu Gtk::Menu* help_menu_p = manage(new Gtk::Menu); // now fill the about menu MenuList& help_list = help_menu_p->items(); help_list.push_back(MenuElem(gettext("About efax-_gtk"), sigc::bind(sigc::mem_fun(*this, &MainWindow::about_slot), true))); help_list.push_back(MenuElem(gettext("About _efax"), sigc::bind(sigc::mem_fun(*this, &MainWindow::about_slot), false))); help_list.push_back(MenuElem(gettext("_Translations"), sigc::mem_fun(*this, &MainWindow::translations_slot))); help_list.push_back(SeparatorElem()); help_list.push_back(MenuElem(gettext("_Help"), sigc::mem_fun(*this, &MainWindow::helpfile_slot))); // now fill the menu bar MenuList& bar_list = menu_bar.items(); bar_list.push_front(MenuElem(gettext("_Help"), *help_menu_p)); bar_list.push_front(MenuElem(gettext("_File"), *file_menu_p)); } window_box.pack_start(menu_bar, false, false); window_box.pack_start(win_table, true, true); window_box.pack_start(status_line, false, false); add(window_box); win_table.set_border_width(standard_size/3); std::vector<Gtk::Widget*> focus_chain; focus_chain.push_back(&file_entry_frame); focus_chain.push_back(&number_box); focus_chain.push_back(&send_button); focus_chain.push_back(&receive_answer_button); focus_chain.push_back(&receive_takeover_button); focus_chain.push_back(&receive_standby_button); focus_chain.push_back(&stop_button); win_table.set_focus_chain(focus_chain); drawing_area.set_size_request(standard_size, standard_size); Glib::signal_timeout().connect(sigc::mem_fun(*this, &MainWindow::timer_event_handler), TIMER_INTERVAL); Glib::signal_io().connect(sigc::mem_fun(*this, &MainWindow::read_error_slot), error_pipe.get_read_fd(), Glib::IO_IN); efax_controller.stdout_message.connect(sigc::mem_fun(text_window, &MessageText::write_black_slot)); efax_controller.write_state.connect(sigc::mem_fun(status_line, &StatusLine::write_status)); efax_controller.remove_from_socket_server_filelist.connect(sigc::mem_fun(*this, &MainWindow::remove_from_socket_server_filelist)); drawing_area.signal_expose_event().connect(sigc::mem_fun(*this, &MainWindow::draw_fax_from_socket_notifier), false); // we want to minimise the effect on efax, so make writing to the error pipe non-blocking error_pipe.make_write_non_block(); set_icon(prog_config.window_icon_r); set_file_items_sensitive_slot(); get_window_settings(); if (filename) { // this will also call set_file_items_sensitive_slot() if the call to // get_window_settings has set socket_button active file_button.set_active(true); file_entry.set_text(filename); set_focus(number_entry); } else set_focus(single_file_button); show_all(); if (!messages.empty()) { text_window.write_red_slot(messages.c_str()); text_window.write_red_slot("\n\n"); } // make sure that we have the faxin, faxout, faxsent, faxin/oldfax and faxsent/oldfax directories chdir(prog_config.homedir.c_str()); mkdir("faxin", S_IRUSR | S_IWUSR | S_IXUSR); mkdir("faxout", S_IRUSR | S_IWUSR | S_IXUSR); mkdir("faxsent", S_IRUSR | S_IWUSR | S_IXUSR); mkdir("faxin/oldfax", S_IRUSR | S_IWUSR | S_IXUSR); mkdir("faxsent/oldfax", S_IRUSR | S_IWUSR | S_IXUSR); // set the working directory for the parent process chdir("faxin"); // if there is no config file installed, then bring up the settings dialog if (!prog_config.found_rcfile) { // we don't want to use MainWindow::settings_slot(), or the absence of // a configuration file will be reported twice -- not a big deal, but ... // so pass true as the last parameter to skip detection of settings file SettingsDialog dialog(standard_size, *this, true); dialog.accepted.connect(sigc::mem_fun(*this, &MainWindow::settings_changed_slot)); dialog.exec(); } // this connects the stdout facilities of Socket_server to MessageText socket_server.stdout_message.connect(sigc::mem_fun(text_window, &MessageText::write_black_slot)); // this connects the SigC object in Socket_server to a method in this class // which will update the Socket_list object (if such a dialog is displayed) socket_server.filelist_changed_notify.connect(sigc::mem_fun(*this, &MainWindow::socket_filelist_changed_notify_slot)); // and this connects the SigC object which indicates a fax has been received // from the socket for sending to the method which will pop up a "fax to send" // notify dialog socket_server.fax_to_send_notify.connect(sigc::mem_fun(*this, &MainWindow::fax_to_send_notify_slot)); // this connects the SigC object which indicates that a fax has been received // from the modem by the EfaxController object efax_controller.fax_received_notify.connect(sigc::mem_fun(*this, &MainWindow::fax_received_notify_slot)); // start the socket server if (prog_config.sock_server && !prog_config.sock_server_port.empty()) { socket_server.start(std::string(prog_config.sock_server_port), prog_config.other_sock_client_address); } // the notifed_fax pair is used by sendfax_slot() if no number is shown // to dial, for use if the option to send on an open connection without // dialling is refused and sendfax_slot() was called by a // SocketNotifyDialog::sendfax_sig signal, so that a SocketNotifyDialog // dialog can be brought up again for the user to have another chance to // choose what he/she wants to do. When the second member of the // notified_fax pair is not 0, then that indicates that sendfax_slot() // was called by a SocketNotifyDialog object (it is normally set to 0 and // only holds another value when set in MainWindow::fax_to_send_dialog()) notified_fax.second = 0;}bool MainWindow::on_key_press_event(GdkEventKey* event_p) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -