📄 fax_list_manager.cpp
字号:
TreeModelRowReference folder_row_ref(folder_tree_store_r, Gtk::TreePath(base_folder_row)); folder_to_row_map.insert(FolderToRowMap::value_type(base_path, folder_row_ref)); if (!dir_list.empty()) { // first sort them dir_list.sort(); // populate the tree store, and get the fax description (if any) std::string filename; std::string line; std::ifstream file; filename = dir; filename += "/PathList";#ifdef HAVE_IOS_NOCREATE file.open(filename.c_str(), std::ios::in | std::ios::nocreate);#else // we must have Std C++ so we probably don't need a ios::nocreate // flag on a read open to ensure uniqueness file.open(filename.c_str(), std::ios::in);#endif if (file) { while (std::getline(file, line)) get_folders(folder_to_row_map, line); } filename = ""; line = ""; file.close(); file.clear(); std::list<std::string>::const_iterator iter; for (iter = dir_list.begin(); iter!= dir_list.end(); ++iter) { // get the fax list Path for each fax filename = dir + '/'; filename += *iter; filename += "/Path";#ifdef HAVE_IOS_NOCREATE file.open(filename.c_str(), std::ios::in | std::ios::nocreate);#else // we must have Std C++ so we probably don't need a ios::nocreate // flag on a read open to ensure uniqueness file.open(filename.c_str(), std::ios::in);#endif if (file) { while (std::getline(file, line) && line.empty()); } if (!Glib::ustring(line).validate()) { // not valid UTF-8! write_error("Invalid UTF-8 string in folder path name in FaxListManager::populate_fax_list()\n"); line = ""; } // sort the faxes into a multimap keyed by the folder and indicating // the faxes belong to that folder, and then enter the faxes into a // map keyed by the fax and indicating its folder path (this gives // faster look up of the fax to its folder by enabling a binary search // in both directions) if (line.size() == 1 && line[0] == PATH_DIVIDER) { folder_to_fax_map.insert(FolderToFaxMap::value_type(base_path, *iter)); fax_to_folder_map.insert(FaxToFolderMap::value_type(*iter, base_path)); } // include a call to get_folders() in case something has gone wrong // and the fax belongs to a folder not listed in the PathList file else if (!line.empty() && get_folders(folder_to_row_map, line)) { folder_to_fax_map.insert(FolderToFaxMap::value_type(line, *iter)); fax_to_folder_map.insert(FaxToFolderMap::value_type(*iter, line)); } else { folder_to_fax_map.insert(FolderToFaxMap::value_type(base_path, *iter)); fax_to_folder_map.insert(FaxToFolderMap::value_type(*iter, base_path)); } filename = ""; line = ""; file.close(); file.clear(); } } // write path in case this is the first time the program has started or // something else has changed write_path(); // select the main folder Glib::ustring base_folder; if (mode == FaxListEnum::received) base_folder = gettext("Inbox"); else base_folder = gettext("Sent box"); bool found_it = false; Gtk::TreeModel::Children children = folder_tree_store_r->children(); Gtk::TreeModel::iterator row_iter = children.begin(); while (!found_it && row_iter != children.end()) { if ((*row_iter)[folder_model_columns.name] == base_folder) found_it = true; else ++row_iter; } if (found_it) { folder_tree_view.get_selection()->select(row_iter); display_faxes_slot(); } } // reset current directory std::string temp(prog_config.working_dir + "/faxin"); chdir(temp.c_str());}bool FaxListManager::get_folders(FolderToRowMap& folder_to_row_map, const std::string& line) { bool return_val; if (!line.empty()) return_val = true; else return_val = false; std::vector<std::string> child_rowlist; std::string remaining_path(line); if (!Glib::ustring(line).validate()) { // not valid UTF-8! write_error("Invalid UTF-8 string in folder path name in FaxListManager::get_folders()\n"); remaining_path = ""; return_val = false; } // keep going until we get to the root tree store or to a parent row in existence while (!remaining_path.empty() && folder_to_row_map.find(remaining_path) == folder_to_row_map.end()) { std::string::size_type pos = remaining_path.rfind(PATH_DIVIDER); if (pos == std::string::npos) { // input error remaining_path = ""; child_rowlist.clear(); return_val = false; } else { child_rowlist.push_back(remaining_path.substr(pos + 1)); folder_name_validator.insert_folder_name(remaining_path.substr(pos + 1)); remaining_path.resize(pos); } } // now create the missing child level(s) stored in child_rowlist if (!child_rowlist.empty()) { std::vector<std::string>::reverse_iterator r_iter = child_rowlist.rbegin(); TreeModelRowReference row_ref; std::string pathname(remaining_path); pathname += PATH_DIVIDER; pathname += *r_iter; if (remaining_path.empty()) { // we need to make a first level node Gtk::TreeModel::Row row = *folder_tree_store_r->append(); // no need for a Glib conversion function here - we store folder // names in Path in UTF-8 row[folder_model_columns.name] = *r_iter; row[folder_model_columns.root_only] = false; row[folder_model_columns.icon] = folder_icon_r; row_ref = TreeModelRowReference(folder_tree_store_r, Gtk::TreePath(row)); folder_to_row_map.insert(FolderToRowMap::value_type(pathname, row_ref)); } else { // build on the nearest ancestor already created row_ref = folder_to_row_map[remaining_path]; Gtk::TreeModel::Row row = *folder_tree_store_r->append(folder_tree_store_r->get_iter(row_ref.get_path())->children()); // TODO if (!row) // no need for a Glib conversion function here - we store folder // names in Path in UTF-8 row[folder_model_columns.name] = *r_iter; row[folder_model_columns.root_only] = false; row[folder_model_columns.icon] = folder_icon_r; row_ref = TreeModelRowReference(folder_tree_store_r, Gtk::TreePath(row)); folder_to_row_map.insert(FolderToRowMap::value_type(pathname, row_ref)); } // now deal with any further children remaining to be created for (++r_iter; r_iter != child_rowlist.rend(); ++r_iter) { Gtk::TreeModel::Row row = *folder_tree_store_r->append(folder_tree_store_r->get_iter(row_ref.get_path())->children()); // no need for a Glib conversion function here - we store folder // names in Path in UTF-8 row[folder_model_columns.name] = *r_iter; row[folder_model_columns.root_only] = false; row[folder_model_columns.icon] = folder_icon_r; pathname += PATH_DIVIDER; pathname += *r_iter; row_ref = TreeModelRowReference(folder_tree_store_r, Gtk::TreePath(row)); folder_to_row_map.insert(FolderToRowMap::value_type(pathname, row_ref)); } } return return_val;}void FaxListManager::move_fax(const Gtk::TreeModel::iterator& folder_iter, const std::string& faxname) { // check pre-conditions if (!drag_row_iter) return; std::string source_pathname(fax_to_folder_map[faxname]); std::string dest_pathname(get_pathname_for_folder(folder_iter)); if (source_pathname == dest_pathname) return; if (fax_to_folder_map.find(faxname) != fax_to_folder_map.end()) { fax_to_folder_map[faxname] = dest_pathname; } else write_error("Database mapping error in FaxListManager::move_fax()\n"); std::pair<FolderToFaxMap::iterator, FolderToFaxMap::iterator> result(folder_to_fax_map.equal_range(source_pathname)); if (result.first == result.second) { write_error("Equal range: database mapping error in FaxListManager::move_fax()\n"); return; } FolderToFaxMap::iterator iter = result.first; bool found_it = false; while (!found_it && iter != result.second) { if (iter->second == faxname) { found_it = true; folder_to_fax_map.erase(iter); folder_to_fax_map.insert(FolderToFaxMap::value_type(dest_pathname, faxname)); fax_list_store_r->erase(drag_row_iter); drag_row_iter = fax_list_store_r->children().end(); } else ++iter; } if (!found_it) { write_error("Fax to move not found: database mapping error in FaxListManager::move_fax()\n"); } write_path();}void FaxListManager::move_folder(Gtk::TreeModel::iterator folder_iter, Gtk::TreeViewDropPosition drop_pos, const std::string& foldername) { // check pre-conditions if (!drag_row_iter) return; std::string source_pathname(get_pathname_for_folder(drag_row_iter)); std::string drop_pathname(get_pathname_for_folder(folder_iter)); if (source_pathname != drop_pathname) { // get the new pathname for the folder and put it in new_pathname std::string new_pathname(drop_pathname); std::string::size_type pos; if (drop_pos == Gtk::TREE_VIEW_DROP_BEFORE || drop_pos == Gtk::TREE_VIEW_DROP_AFTER) { if ((pos = new_pathname.rfind(PATH_DIVIDER)) != std::string::npos) { new_pathname.resize(pos); } else { write_error("Folder with no pathname in FaxListManager::move_folder()\n"); new_pathname = ""; } } new_pathname += PATH_DIVIDER; new_pathname += foldername; if (is_valid_drop_path(source_pathname, new_pathname) && (!(*drag_row_iter)[folder_model_columns.root_only] || new_pathname.rfind(PATH_DIVIDER) == 0)) { Gtk::TreeModel::iterator new_row_iter; switch (drop_pos) { case Gtk::TREE_VIEW_DROP_BEFORE: new_row_iter = folder_tree_store_r->insert(folder_iter); break; case Gtk::TREE_VIEW_DROP_AFTER: new_row_iter = folder_tree_store_r->insert(++folder_iter); break; default: new_row_iter = folder_tree_store_r->prepend(folder_iter->children()); break; } (*new_row_iter)[folder_model_columns.name] = Glib::ustring(foldername); bool is_root_only = (*drag_row_iter)[folder_model_columns.root_only]; (*new_row_iter)[folder_model_columns.root_only] = is_root_only; (*new_row_iter)[folder_model_columns.icon] = folder_icon_r; bool adjust_mapping = false; if (source_pathname != new_pathname) { remap_faxes_in_folder(source_pathname, new_pathname); // and make sure that move_child_folders_for_level() also adjusts mapping adjust_mapping = true; } // now move all the children of the move folder to rejoin their parent move_child_folders_for_level(drag_row_iter->children(), new_row_iter->children(), source_pathname, new_pathname, adjust_mapping); folder_tree_store_r->erase(drag_row_iter); drag_row_iter = folder_tree_store_r->children().end(); write_path(); } }}bool FaxListManager::is_valid_drop_path(const std::string& old_pathname, const std::string& new_pathname) { // check that the folder is not being dropped on one of its children - // with drag and drop syncing issues this can happen if (new_pathname.find(old_pathname) == 0 && new_pathname.size() > old_pathname.size()) { // we can have the new pathname the same // as the old pathname - say if folder // is being moved at same level return false; } return true;}void FaxListManager::remap_faxes_in_folder(const std::string& old_pathname, const std::string& new_pathname) { // this method adjusts the mapping for the faxes in a moved folder // before calling it check that old_pathname != new_pathname // otherwise this method will just waste time // first get a listing of the faxes in the folder being moved std::vector<std::string> fax_list; std::pair<FolderToFaxMap::iterator, FolderToFaxMap::iterator> result(folder_to_fax_map.equal_range(old_pathname)); FolderToFaxMap::iterator map_iter; for (map_iter = result.first; map_iter != result.second; ++map_iter) { fax_list.push_back(map_iter->second); } // erase old elements folder_to_fax_map.erase(result.first, result.second); // insert new ones std::vector<std::string>::iterator vec_iter; for (vec_iter = fax_list.begin(); vec_iter != fax_list.end(); ++vec_iter) { folder_to_fax_map.insert(FolderToFaxMap::value_type(new_pathname, *vec_iter)); fax_to_folder_map[*vec_iter] = new_pathname; }}void FaxListManager::move_child_folders_for_level(const Gtk::TreeModel::Children& source_level, const Gtk::TreeModel::Children& dest_level, const std::string& source_level_pathname, const std::string& dest_level_pathname, bool adjust_mapping) { if (source_level && !source_level.empty()) { Gtk::TreeModel::Children::iterator source_row_iter; for (source_row_iter = source_level.begin(); source_row_iter != source_level.end(); ++source_row_iter) { std::string node_name = Glib::ustring((*source_row_iter)[folder_model_columns.name]); std::string full_source_pathname(source_level_pathname); full_source_pathname += PATH_DIVIDER; full_source_pathname += node_name; std::string full_dest_pathname(dest_level_pathname); full_dest_pathname += PATH_DIVIDER; full_dest_pathname += node_name; Gtk::TreeModel::Children::iterator dest_row_iter = folder_tree_store_r->append(dest_level); (*dest_row_iter)[folder_model_columns.name] = Glib::ustring(node_name); // as we are not at the root level we know folder_model_columns.root_only must be false (*dest_row_iter)[folder_model_columns.root_only] = false; (*dest_row_iter)[folder_model_columns.icon] = folder_icon_r; if (adjust_mapping) remap_faxes_in_folder(full_source_pathname, full_dest_pathname); // now recursively work the way up children of this node (if any) move_child_folders_for_level(source_row_iter->children(), dest_row_iter->children(), full_source_pathname, full_dest_pathname, adjust_mapping); } }}std::string FaxListManager::get_pathname_for_folder(Gtk::TreeModel::iterator folder_iter) { std::string pathname;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -