📄 fax_list_manager.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 <vector>#include <cstring>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <dirent.h>#include <gtkmm/treesortable.h>#include <gdkmm/pixmap.h>#include <gdkmm/bitmap.h>#include <gdkmm/colormap.h>#include "fax_list_manager.h"#include "fax_list_manager_icons.h"#ifdef ENABLE_NLS#include <libintl.h>#endif#define PATH_DIVIDER '@'std::pair<bool, Glib::ustring> FolderNameValidator::validate(const Glib::ustring& folder_name) { std::pair<bool, Glib::ustring> return_val; if (folder_name.find(PATH_DIVIDER) != Glib::ustring::npos) { return_val.first = false; return_val.second = gettext("Folder name cannot contain character: "); return_val.second += PATH_DIVIDER; } else { std::pair<std::set<std::string>::iterator, bool> result = folder_set.insert(folder_name); // we only want a return value - erase the element if the insert succeeded if ((return_val.first = result.second)) folder_set.erase(folder_name); else { return_val.second = gettext("The following folder already exists: "); return_val.second += folder_name; } } return return_val;}FaxListManager::FaxListManager(FaxListEnum::Mode mode_): mode(mode_), folder_drag_source_enabled(false), fax_drag_source_enabled(false), folder_tree_view_column(gettext("Folder")) { folder_icon_r = Gdk::Pixbuf::create_from_xpm_data(folder_xpm); folder_icon_r = folder_icon_r->scale_simple(12, 12, Gdk::INTERP_BILINEAR); // create the tree model for the folders: folder_tree_store_r = Gtk::TreeStore::create(folder_model_columns); // connect it to the tree view folder_tree_view.set_model(folder_tree_store_r); // add first and second column of the tree model to tree view column // (the third column of tree model is data not for display) folder_tree_view_column.pack_start(folder_model_columns.icon, false); folder_tree_view_column.pack_start(folder_model_columns.name); // add the folder tree view column to the folder tree view folder_tree_view.append_column(folder_tree_view_column); // single line selection folder_tree_view.get_selection()->set_mode(Gtk::SELECTION_SINGLE); // create the tree model for the faxes: fax_list_store_r = Gtk::ListStore::create(fax_model_columns); // connect it to the tree view fax_tree_view.set_model(fax_list_store_r); // add columns of the tree model to tree view fax_tree_view.append_column(gettext("Fax"), fax_model_columns.name); fax_tree_view.append_column(gettext("Description"), fax_model_columns.fax_description); // single line selection fax_tree_view.get_selection()->set_mode(Gtk::SELECTION_SINGLE); // populate the fax list populate_fax_list(); // populate_fax_list() will pre-sort for efficiency reasons but make the fax // list sortable here for any changes introduced from drag and drop to be sorted#if GTKMM_VERSION >= 24 fax_list_store_r->set_sort_column(fax_model_columns.name, Gtk::SORT_ASCENDING);#else fax_list_store_r->set_sort_column_id(fax_model_columns.name, Gtk::SORT_ASCENDING);#endif // now provide drag and drop from the fax tree view to the folder tree view // first load target_list target_list.push_back( Gtk::TargetEntry("STRING")); target_list.push_back( Gtk::TargetEntry("text/plain")); // connect slots to ensure that a drag only starts with a valid row to drag folder_tree_view.signal_motion_notify_event().connect_notify(sigc::mem_fun(*this, &FaxListManager::folder_tree_view_motion_notify_slot)); fax_tree_view.signal_motion_notify_event().connect_notify(sigc::mem_fun(*this, &FaxListManager::fax_tree_view_motion_notify_slot)); // connect slots to handle the drag source in the fax tree view fax_tree_view.signal_drag_data_get().connect(sigc::mem_fun(*this, &FaxListManager::fax_drag_data_get_slot)); fax_tree_view.signal_drag_begin().connect(sigc::mem_fun(*this, &FaxListManager::fax_tree_view_drag_begin_slot)); // connect slots to handle the drag source in the folder tree view folder_tree_view.signal_drag_data_get().connect(sigc::mem_fun(*this, &FaxListManager::folder_drag_data_get_slot)); folder_tree_view.signal_drag_begin().connect(sigc::mem_fun(*this, &FaxListManager::folder_tree_view_drag_begin_slot)); // connect slots to handle the drag destination in the folder tree view folder_tree_view.signal_drag_motion().connect(sigc::mem_fun(*this, &FaxListManager::drag_motion_slot)); folder_tree_view.drag_dest_set(target_list, Gtk::DEST_DEFAULT_ALL, Gdk::ACTION_MOVE); folder_tree_view.signal_drag_data_received().connect(sigc::mem_fun(*this, &FaxListManager::drag_data_received_slot)); // handle selection of a row in the tree views fax_tree_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &FaxListManager::fax_selected_slot)); folder_tree_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &FaxListManager::folder_selected_slot)); folder_tree_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &FaxListManager::display_faxes_slot));}void FaxListManager::folder_tree_view_drag_begin_slot(const Glib::RefPtr<Gdk::DragContext>& context) { drag_is_fax = false; drag_row_iter = folder_tree_view.get_selection()->get_selected(); if (drag_row_iter) { int x_off, y_off, cell_width, cell_height; Gdk::Rectangle area; folder_tree_view.get_column(0)->cell_get_size(area, x_off, y_off, cell_width, cell_height); if (cell_height < 0) cell_height = 0; Glib::RefPtr<Gdk::Pixmap> pixmap_r = folder_tree_view.create_row_drag_icon(Gtk::TreeModel::Path(drag_row_iter)); Glib::RefPtr<Gdk::Colormap> colormap_r = Gtk::Widget::get_default_colormap(); Glib::RefPtr<Gdk::Bitmap> bitmap_r; context->set_icon(colormap_r, pixmap_r, bitmap_r, 5, cell_height/2); }}void FaxListManager::fax_tree_view_drag_begin_slot(const Glib::RefPtr<Gdk::DragContext>& context) { drag_is_fax = true; drag_row_iter = fax_tree_view.get_selection()->get_selected(); if (drag_row_iter) { int x_off, y_off, cell_width, cell_height; Gdk::Rectangle area; fax_tree_view.get_column(0)->cell_get_size(area, x_off, y_off, cell_width, cell_height); int x_pos, y_pos; fax_tree_view.get_pointer(x_pos, y_pos); if (cell_height < 0) cell_height = 0; if (x_pos < 0) x_pos = 0; Glib::RefPtr<Gdk::Pixmap> pixmap_r = fax_tree_view.create_row_drag_icon(Gtk::TreeModel::Path(drag_row_iter)); Glib::RefPtr<Gdk::Colormap> colormap_r = Gtk::Widget::get_default_colormap(); Glib::RefPtr<Gdk::Bitmap> bitmap_r; context->set_icon(colormap_r, pixmap_r, bitmap_r, x_pos, cell_height/2); }}bool FaxListManager::drag_motion_slot(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time) { bool return_val = false; Gtk::TreeModel::Path path; Gtk::TreeViewDropPosition drop_pos; folder_tree_view.get_dest_row_at_pos(x, y, path, drop_pos); if (path.gobj()) { if (drag_is_fax) folder_tree_view.set_drag_dest_row(path, Gtk::TREE_VIEW_DROP_INTO_OR_AFTER); else folder_tree_view.set_drag_dest_row(path, drop_pos); return_val = true; } return return_val;}void FaxListManager::folder_drag_data_get_slot(const Glib::RefPtr<Gdk::DragContext>& context,#if GTKMM_VERSION >= 24 Gtk::SelectionData& selection_data,#else GtkSelectionData* selection_data_p,#endif guint info, guint time) { Gtk::TreeModel::iterator row_iter = folder_tree_view.get_selection()->get_selected(); std::string message("efax-gtk-"); if (row_iter) message += Glib::ustring((*row_iter)[folder_model_columns.name]); else message = "Error";#if GTKMM_VERSION >= 24 //selection_data.set(selection_data.get_target(), 8, (const guchar*) message.c_str() , message.size()); selection_data.set(selection_data.get_target(), message);#else gtk_selection_data_set(selection_data_p, selection_data_p->target, 8, (const guchar*) message.c_str() , message.size() + 1);#endif}void FaxListManager::fax_drag_data_get_slot(const Glib::RefPtr<Gdk::DragContext>& context,#if GTKMM_VERSION >= 24 Gtk::SelectionData& selection_data,#else GtkSelectionData* selection_data_p,#endif guint info, guint time) { Gtk::TreeModel::iterator row_iter = fax_tree_view.get_selection()->get_selected(); std::string message("efax-gtk-"); if (row_iter) message += Glib::ustring((*row_iter)[fax_model_columns.name]); else message = "Error";#if GTKMM_VERSION >= 24 //selection_data.set(selection_data.get_target(), 8, (const guchar*) message.c_str() , message.size()); selection_data.set(selection_data.get_target(), message);#else gtk_selection_data_set(selection_data_p, selection_data_p->target, 8, (const guchar*) message.c_str() , message.size() + 1);#endif}void FaxListManager::drag_data_received_slot(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y,#if GTKMM_VERSION >= 24 const Gtk::SelectionData& selection_data,#else GtkSelectionData* selection_data_p,#endif guint info, guint time) { bool success = false; std::string message;#if GTKMM_VERSION >= 24 if (selection_data.get_length() >= 0 && selection_data.get_format() == 8) { message = selection_data.get_data_as_string(); }#else if(selection_data_p->length >= 0 && selection_data_p->format == 8) { message = (const char*)selection_data_p->data; }#endif if (message.find("efax-gtk-") == 0) { message.erase(0, 9); Gtk::TreeModel::Path path; Gtk::TreeViewDropPosition drop_pos; folder_tree_view.get_dest_row_at_pos(x, y, path, drop_pos); if (path.gobj()) { Gtk::TreeIter iter = folder_tree_store_r->get_iter(path); if (iter) { if (drag_is_fax) move_fax(iter, message); else move_folder(iter, drop_pos, message); success = true; } else write_error("Invalid iterator in FaxListDialog::drag_data_received_slot()\n"); } } context->drag_finish(success, false, time);}void FaxListManager::folder_tree_view_motion_notify_slot(GdkEventMotion*) { int x, y; folder_tree_view.get_pointer(x, y); if (x >= 0 && y >= 0){ Gtk::TreeModel::Path path; Gtk::TreeViewDropPosition drop_pos; folder_tree_view.get_dest_row_at_pos(x, y, path, drop_pos); if (path.gobj() && !folder_drag_source_enabled) { folder_tree_view.drag_source_set(target_list, Gdk::MODIFIER_MASK, Gdk::ACTION_MOVE); folder_drag_source_enabled = true; } else if (!path.gobj() && folder_drag_source_enabled) { folder_tree_view.drag_source_unset(); folder_drag_source_enabled = false; } }}void FaxListManager::fax_tree_view_motion_notify_slot(GdkEventMotion*) { int x, y; fax_tree_view.get_pointer(x, y); if (x >= 0 && y >= 0){ Gtk::TreeModel::Path path; Gtk::TreeViewDropPosition drop_pos; fax_tree_view.get_dest_row_at_pos(x, y, path, drop_pos); if (path.gobj() && !fax_drag_source_enabled) { fax_tree_view.drag_source_set(target_list, Gdk::MODIFIER_MASK, Gdk::ACTION_MOVE); fax_drag_source_enabled = true; } else if (!path.gobj() && fax_drag_source_enabled) { fax_tree_view.drag_source_unset(); fax_drag_source_enabled = false; } }}void FaxListManager::populate_fax_list(void) { std::string dir(prog_config.working_dir); if (mode == FaxListEnum::received) dir += "/faxin"; else dir += "/faxsent"; chdir(dir.c_str()); DIR* dir_p; if ((dir_p = opendir(dir.c_str())) == 0) { std::string msg("Can't open directory "); msg += dir; msg += '\n'; write_error(msg.c_str()); } else { struct dirent* direntry; struct stat statinfo; std::list<std::string> dir_list; // first populate dir_list with the directory names in $HOME/faxin while ((direntry = readdir(dir_p)) != 0) { stat(direntry->d_name, &statinfo); if (S_ISDIR(statinfo.st_mode) && std::strcmp(direntry->d_name, "oldfax") && std::strcmp(direntry->d_name, ".") && std::strcmp(direntry->d_name, "..") && (mode == FaxListEnum::sent || std::strcmp(direntry->d_name, prog_config.receive_dirname))) { dir_list.push_back(direntry->d_name); } } closedir(dir_p); // now insert the directory names in fax_list, with description (if any) // first clear the list store -- we need to clear it here before // testing for an empty dir_list, or on deleting the last fax in the list, // the clear won't take out the former last entry folder_tree_store_r->clear(); fax_list_store_r->clear(); folder_to_fax_map.clear(); fax_to_folder_map.clear(); folder_name_validator.clear(); // we always have an 'Inbox' and 'Sent box' row items to which children are attached Gtk::TreeModel::Row base_folder_row = *folder_tree_store_r->append(); std::string base_path; base_path = PATH_DIVIDER; if (mode == FaxListEnum::received) { base_folder_row[folder_model_columns.name] = gettext("Inbox"); base_path += gettext("Inbox"); folder_name_validator.insert_folder_name(gettext("Inbox")); } else { base_folder_row[folder_model_columns.name] = gettext("Sent box"); base_path += gettext("Sent box"); folder_name_validator.insert_folder_name(gettext("Sent box")); } base_folder_row[folder_model_columns.icon] = folder_icon_r; base_folder_row[folder_model_columns.root_only] = true; FolderToRowMap folder_to_row_map;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -