void Subtitles::load(const std::string& file_path) throw(m::Exception) { Time_ms time = 0; std::string text; Glib::ustring line; size_t line_num = 1; char buf[PIPE_BUF]; enum { GET_SUBTITLE, GET_TIME, GET_TEXT } state = GET_SUBTITLE; Glib::RefPtr<Glib::Regex> tag_regex = Glib::Regex::create("</{0,1}[a-zA-Z]>"); Glib::RefPtr<Glib::Regex> empty_line_regex = Glib::Regex::create("^\\s*$"); Glib::RefPtr<Glib::Regex> id_regex = Glib::Regex::create("^\\s*\\d+\\s*$"); Glib::RefPtr<Glib::Regex> time_regex = Glib::Regex::create( "^\\s*(\\d{1,2}):(\\d{1,2}):(\\d{1,2}),(\\d{1,3})\\s+-{1,2}>\\s+\\d{1,2}:\\d{1,2}:\\d{1,2},\\d{1,3}\\s*$" ); this->subtitles.clear(); // Открываем файл --> std::ifstream file; file.open(U2L(file_path).c_str(), std::ios::in); if(!file.is_open()) M_THROW(EE(errno)); file.exceptions(file.eofbit | file.failbit | file.badbit); // Открываем файл <-- while(file.good()) { // Считываем очередную строку из файла --> { size_t size = 0; try { char byte; bool work = true; while(work) { if(size + 1 >= sizeof buf) M_THROW(__("line %1 is too big", line_num)); file.get(byte); switch(byte) { case '\r': { file.get(byte); if(byte != '\n') file.unget(); } case '\n': { line = smart_convert(std::string(buf, buf + size)); // Отрезаем Byte order mark, если он присутствует // (http://en.wikipedia.org/wiki/Byte_order_mark). if(line_num == 1 && !line.empty() && line[0] == 0xFEFF) line = line.substr(1); work = false; } break; default: buf[size++] = byte; break; } } } catch(m::Exception& e) { // Чтобы деструктор не сгенерировал исключение file.exceptions(file.goodbit); throw; } catch(std::ofstream::failure& e) { // Чтобы деструктор не сгенерировал исключение file.exceptions(file.goodbit); if(file.bad()) M_THROW(EE(errno)); else { if(state == GET_SUBTITLE || GET_TEXT) line = smart_convert(std::string(buf, buf + size)); else M_THROW(__("unexpected end of file at line %1 ('%2')", line_num, line)); } } } // Считываем очередную строку из файла <-- // Парсим полученную строку --> switch(state) { case GET_SUBTITLE: { bool dont_break = false; if(!empty_line_regex->match(line)) { if(id_regex->match(line)) state = GET_TIME; // Иногда субтитры не имеют идентификатора else if(time_regex->match(line)) { state = GET_TIME; dont_break = true; } else M_THROW(__("invalid line %1 ('%2')", line_num, line)); } if(!dont_break) break; } case GET_TIME: { Glib::StringArrayHandle matches = time_regex->split(line); if(matches.size() < 5) M_THROW(__("invalid line %1 ('%2')", line_num, line)); else { Time_ms hours = boost::lexical_cast<int>(matches.data()[1]); Time_ms minutes = boost::lexical_cast<int>(matches.data()[2]); Time_ms seconds = boost::lexical_cast<int>(matches.data()[3]); Time_ms mseconds = boost::lexical_cast<int>(matches.data()[4]); if( hours < 0 || minutes < 0 || minutes > 59 || seconds < 0 || seconds > 59 || mseconds < 0 || mseconds > 999 ) M_THROW(__("invalid line %1 ('%2')", line_num, line)); Time_ms gotten_time = ( (hours * 60 + minutes) * 60 + seconds ) * 1000 + mseconds; if(gotten_time < time) { MLIB_SW(__( "Gotten smaller time offset than previous at line %1 in subtitles file '%2'.", line_num, file_path )); } else time = gotten_time; } state = GET_TEXT; } break; case GET_TEXT: { if(empty_line_regex->match(line)) { if(!text.empty()) { this->subtitles.push_back(Subtitle(time, text)); text = ""; } state = GET_SUBTITLE; } else { line = tag_regex->replace(line, 0, "", static_cast<Glib::RegexMatchFlags>(0)); if(!text.empty()) text += "\n"; text += line; } } break; default: MLIB_LE(); break; } // Парсим полученную строку <-- line_num++; } if(this->subtitles.empty()) M_THROW(_("there is no subtitles in this file")); }
void Settings_window::load_settings(void) { // Client --> { Private::Client& client = priv->client; const Client_settings& client_settings = this->client_settings; // GUI --> { Private::Gui& gui = client.gui; const Gui_settings& gui_settings = client_settings.gui; // Misc --> { Private::Gui_misc& misc = gui.misc; misc.show_speed_in_window_title->set_active( gui_settings.show_speed_in_window_title); misc.show_zero_values->set_active( gui_settings.show_zero_values); misc.compact_details_tab->set_active( gui_settings.compact_details_tab); misc.gui_update_interval->set_value( gui_settings.update_interval); misc.max_log_lines->set_value( gui_settings.max_log_lines); misc.show_tray_icon->set_active( gui_settings.show_tray_icon); misc.hide_app_to_tray_at_startup->set_active( gui_settings.hide_app_to_tray_at_startup); misc.minimize_to_tray->set_active( gui_settings.minimize_to_tray); misc.close_to_tray->set_active( gui_settings.close_to_tray); misc.download_completed_notification->set_active( gui_settings.download_completed_notification); misc.all_downloads_completed_notification->set_active( gui_settings.all_downloads_completed_notification); } // Misc <-- // Status bar --> { Private::Status_bar& bar = gui.status_bar; const Status_bar_settings& bar_settings = gui_settings.main_window.status_bar; bar.download_speed->set_active( bar_settings.download_speed); bar.download_payload_speed->set_active( bar_settings.download_payload_speed); bar.upload_speed->set_active( bar_settings.upload_speed); bar.upload_payload_speed->set_active( bar_settings.upload_payload_speed); bar.download->set_active( bar_settings.download); bar.payload_download->set_active( bar_settings.payload_download); bar.upload->set_active( bar_settings.upload); bar.payload_upload->set_active( bar_settings.payload_upload); bar.share_ratio->set_active( bar_settings.share_ratio); bar.failed->set_active( bar_settings.failed); bar.redundant->set_active( bar_settings.redundant); } // Status bar <-- } // GUI <-- // Main --> this->show_add_torrent_dialog.set_active(this->client_settings.gui.show_add_torrent_dialog); this->start_torrent_on_adding_check_button.set_active(this->client_settings.user.start_torrent_on_adding); this->download_to_button.set_current_folder(U2L(this->client_settings.user.download_to)); if(this->client_settings.user.copy_finished_to != "") { this->copy_finished_to_check_button.set_active(); this->copy_finished_to_button.set_current_folder(U2L(this->client_settings.user.copy_finished_to)); } else this->copy_finished_to_check_button.set_active(false); this->open_command.set_text(this->client_settings.user.open_command); // Main <-- } // Client <-- // daemon settings --> { Daemon_settings& settings = this->daemon_settings; // Network --> // Misc --> { Private::Network_misc& misc = priv->daemon.network.misc; misc.random_port ->set_active(settings.listen_random_port); // Сначала задаем to, чтобы обработчик сигнала выставил ограничение для from misc.to_port ->set_value(settings.listen_ports_range.second); misc.from_port ->set_value(settings.listen_ports_range.first); misc.custom_port ->set_active(!settings.listen_random_port); misc.current_port->set_label( settings.listen_port < m::PORT_MIN ? _("none") : m::to_string(settings.listen_port)); misc.dht ->set_active(settings.dht); misc.lsd ->set_active(settings.lsd); misc.upnp ->set_active(settings.upnp); misc.natpmp ->set_active(settings.natpmp); misc.pex ->set_active(settings.pex); misc.smart_ban ->set_active(settings.smart_ban); misc.download_rate_limit ->set_value(settings.download_rate_limit); misc.upload_rate_limit ->set_value(settings.upload_rate_limit); misc.max_uploads ->set_value(settings.max_uploads); misc.max_connections ->set_value(settings.max_connections); misc.ignore_limits_on_local_network ->set_active(settings.ignore_limits_on_local_network); misc.use_max_announce_interval ->set_active(settings.use_max_announce_interval); misc.max_announce_interval ->set_value(settings.max_announce_interval / 60); } // Misc <-- // IP filter --> priv->daemon.network.ip_filter->set_enabled(settings.ip_filter_enabled); priv->daemon.network.ip_filter->set(settings.ip_filter); // IP filter <-- // Network <-- // Automation --> { Private::Automation& automation = priv->daemon.automation; // Auto load --> { Daemon_settings::Torrents_auto_load& auto_load = daemon_settings.torrents_auto_load; automation.load.is->set_active(auto_load.is); automation.load.from->set_current_folder(U2L(auto_load.from)); automation.load.to->set_current_folder(U2L(auto_load.to)); automation.load.copy->set_active(auto_load.copy); automation.load.copy_to->set_current_folder(U2L(auto_load.copy_to)); automation.load.delete_loaded->set_active(auto_load.delete_loaded); } // Auto load <-- // Auto clean --> { Daemon_settings::Auto_clean& daemon_clean = daemon_settings.torrents_auto_clean; Private::Auto_clean& clean = automation.clean; clean.max_seeding_time_type = daemon_clean.max_seeding_time_type; clean.max_seeding_time->set_value(daemon_clean.max_seeding_time / 60); this->auto_clean_widgets_update_for( clean.max_seeding_time_type, clean.max_seeding_time_type_button, clean.max_seeding_time_type_label, clean.max_seeding_time ); clean.max_ratio_type = daemon_clean.max_ratio_type; clean.max_ratio->set_value(daemon_clean.max_ratio); this->auto_clean_widgets_update_for( clean.max_ratio_type, clean.max_ratio_type_button, clean.max_ratio_type_label, clean.max_ratio ); clean.max_seeding_torrents_type = daemon_clean.max_seeding_torrents_type; clean.max_seeding_torrents->set_value(daemon_clean.max_seeding_torrents); this->auto_clean_widgets_update_for( clean.max_seeding_torrents_type, clean.max_seeding_torrents_type_button, clean.max_seeding_torrents_type_label, clean.max_seeding_torrents ); } // Auto clean <-- } // Automation <-- } // daemon settings <-- }