#include "mainwindow.hpp" #include "functions.hpp" #include "filesystem.hpp" #include "tv_rename.hpp" #include #include #include #include #include #include constexpr std::array languages{ "en", "English", "sv", "Svenska", "no", "Norsk", "da", "Dansk", "fi", "Suomeksi", "nl", "Nederlands", "de", "Deutsch", "it", "Italiano", "es", "Español", "fr", "Français", "pl", "Polski", "hu", "Magyar", "el", "Greek", "tr", "Turkish", "ru", "Russian", "he", "Hebrew", "ja", "Japanese", "pt", "Portuguese", "zh", "Chinese", "cs", "Czech", "sl", "Slovenian", "hr", "Croatian", "ko","Korea" }; void MainWindow::chooseFile() { // create a dialog for choosing directory Gtk::FileChooserDialog dialog("Select a directory", Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER); dialog.set_transient_for(*this); // add cancel and select buttons dialog.add_button("_Cancel", Gtk::RESPONSE_CANCEL); dialog.add_button("Select", Gtk::RESPONSE_OK); auto result = dialog.run(); switch(result) { case Gtk::RESPONSE_OK: m_entry_dir.set_text(dialog.get_filename()); std::cout << dialog.get_filename() << std::endl; break; case Gtk::RESPONSE_CANCEL: std::cout << "Canceled" << std::endl; break; default: std::cout << "Closed dialog" << std::endl; break; } } void MainWindow::quit() { std::cout << "Quitting" << std::endl; hide(); } void MainWindow::patternHelp() { Gtk::MessageDialog dialog(*this, "Pattern escape sequences"); dialog.set_secondary_text( "%filename - original filename (without type extension)\n" "%show - show name from thetvdb\n" "%epname - episode name from thetvdb\n" "%season - season number\n" "%episode - episode number\n" "Both season number and episode number can be padded with zeros, just add width of padding" " right after %, like this: %2season.\n" "Default pattern is \"%filename - %epname\", you might want to change this to" " \"S%2seasonE%2episode - %epname\" or \"%show - S%2seasonE%2episode - %epname\"" ); dialog.run(); } void MainWindow::process() { // check required fields are filled out if( m_entry_show.get_text().empty() ) { Gtk::MessageDialog dialog(*this, "Show field is empty"); dialog.run(); return; } // language code language_code = (*m_combo_language.get_active())[m_columns_language.m_col_code]; // fill up m_combo_possible with possible tv shows auto possible_shows = getPossibleShows( std::string(m_entry_show.get_text()), language_code, c ); // if no possible shows were found, tell the user if( possible_shows.size() == 0 ) { Gtk::MessageDialog dialog(*this, "No results found for given show name"); dialog.run(); return; } //show widgets m_label_possible.show(); m_button_get_names.show(); m_combo_possible.show(); // fill up combo box with results from thetvdb auto model = Gtk::ListStore::create(m_columns_url); m_combo_possible.set_model(model); auto row = *(model->append()); row[m_columns_url.m_col_show] = possible_shows[0].first; row[m_columns_url.m_col_url] = possible_shows[0].second; m_combo_possible.set_active(row); for( size_t i = 1; i < possible_shows.size(); i++ ) { auto row = *(model->append()); row[m_columns_url.m_col_show] = possible_shows[i].first; row[m_columns_url.m_col_url] = possible_shows[i].second; } } void MainWindow::getNames() { // check required fields are filled out if( m_entry_dir.get_text().empty() ) { Gtk::MessageDialog dialog(*this, "Directory field is empty"); dialog.run(); return; } // check directory exists if( !FSLib::isDirectory(m_entry_dir.get_text()) ) { Gtk::MessageDialog dialog(*this, "Directory doesn't exist"); dialog.run(); return; } path = m_entry_dir.get_text(); selected.clear(); files.clear(); std::vector options; // get all files in path and seperate them in map `files` by season iterateFS(files, path); for( auto &x : files ) { options.push_back(x.first); } // create a window with possible seasons to rename // store selected seasons in `selected` sw = new SeasonWindow(options, selected); sw->signal_hide().connect(sigc::mem_fun(*this, &MainWindow::finishedSelection)); app->add_window(*sw); sw->show(); } /* change names of original files to generated new names * orig - original filenames * renamed - renamed filenames (sorted in the same order as `orig`) */ void renameFiles(const std::set &orig, const std::vector> &renamed) { auto orig_it = orig.begin(); for(auto renamed_it = renamed.begin(); renamed_it != renamed.end(); ++renamed_it) { std::cout << *orig_it << " --> " << renamed_it->first + "/" + renamed_it->second << std::endl; FSLib::rename(*orig_it, renamed_it->first + "/" + renamed_it->second); ++orig_it; } } void MainWindow::finishedSelection() { // remove created SeasonWindow and delete it from memory app->remove_window(*sw); delete sw; auto iter = m_combo_possible.get_active(); // debug output std::cout << (*iter)[m_columns_url.m_col_show] << " " << language_code << std::endl; std::cout << "https://www.thetvdb.com" << static_cast((*iter)[m_columns_url.m_col_url]) << std::endl; std::string input_pattern = m_entry_pattern.get_text(); if( input_pattern != default_pattern ) { std::ofstream file(userHome() + "/.cache/tv_rename_pattern"); if( file ) { file << input_pattern; } } for( auto &x : selected ) { // get renamed files for given season auto renamed_files = singleSeason( static_cast((*iter)[m_columns_url.m_col_show]), x, "https://www.thetvdb.com" + static_cast((*iter)[m_columns_url.m_col_url]), language_code, (input_pattern.empty() ? default_pattern : input_pattern), !m_check_linux.get_active(), c, files[x] ); if( renamed_files.empty() ) continue; // if trust checkbox is ticked, rename files if( m_check_trust.get_active() ) { renameFiles(files[x], renamed_files); continue; } // create a custom dialog box with textview of new episode names Gtk::Dialog dialog("Rename confirmation", *this); auto content = dialog.get_content_area(); Gtk::TextView tx; content->pack_start(tx); tx.set_editable(false); dialog.add_button("_No", Gtk::RESPONSE_CANCEL); dialog.add_button("_Yes", Gtk::RESPONSE_OK); tx.show(); auto buff = tx.get_buffer(); buff->place_cursor(buff->begin()); buff->insert_at_cursor(renamed_files[0].second.c_str()); for( size_t i = 1; i < renamed_files.size(); i++ ) { buff->insert_at_cursor("\n"); buff->insert_at_cursor(renamed_files[i].second.c_str()); } auto response = dialog.run(); // if user clicked "Yes" in dialog, rename files switch(response) { case Gtk::RESPONSE_OK: renameFiles(files[x], renamed_files); default: break; } } } MainWindow::MainWindow(const Glib::RefPtr &ptr) : app(ptr) { set_title("TV Rename"); set_default_size(400, 310); set_resizable(false); { std::ifstream file(userHome() + "/.cache/tv_rename_pattern"); if( file ) { std::getline( file, default_pattern ); } else { default_pattern = "%filename - %epname"; } } add(m_layout); m_layout.put( m_label_show, 5, 5 ); m_layout.put( m_label_language, 190, 5 ); m_layout.put( m_entry_show, 5, 25 ); m_layout.put( m_combo_language, 190, 25 ); m_layout.put( m_label_dir, 5, 60 ); m_layout.put( m_entry_dir, 5, 80 ); m_layout.put( m_button_dir, 190, 80 ); m_layout.put( m_label_pattern, 5, 115 ); m_layout.put( m_entry_pattern, 5, 135 ); m_layout.put( m_button_pattern, 190, 135 ); m_layout.put( m_check_linux, 95, 169 ); m_layout.put( m_button_process, 5, 173 ); m_layout.put( m_check_trust, 95, 187 ); m_layout.put( m_label_possible, 5, 210 ); m_layout.put( m_combo_possible, 5, 230 ); m_layout.put( m_button_get_names, 5, 265 ); m_layout.put( m_button_quit, 315, 275 ); // set button texts m_button_process.set_label( "Process" ); m_button_get_names.set_label( "Get names" ); m_button_quit.set_label( "Quit" ); m_button_dir.set_label( "Choose directory" ); m_button_pattern.set_label( "Pattern help" ); m_check_linux.set_label( "Replace windows-illegal characters" ); m_check_trust.set_label( "Don't ask for rename confirmation" ); // set label texts m_label_show.set_label( "Show:" ); m_label_language.set_label( "Language:" ); m_label_possible.set_label( "Possible shows:" ); m_label_dir.set_label( "Directory:" ); m_label_pattern.set_label( "Pattern:" ); // set dimensions m_combo_language.set_size_request( 120 ); m_combo_possible.set_size_request( 200 ); m_entry_show.set_size_request( 170, 30 ); m_entry_dir.set_size_request( 170, 30 ); m_button_dir.set_size_request( 80, 30 ); m_button_quit.set_size_request( 80, 30 ); m_button_process.set_size_request( 80, 30 ); m_button_get_names.set_size_request( 80, 30 ); // set default pattern m_entry_pattern.set_text(default_pattern); // put languages in combo box { auto model = Gtk::ListStore::create(m_columns_language); m_combo_language.set_model(model); auto row = *(model->append()); row[m_columns_language.m_col_code] = "en"; row[m_columns_language.m_col_language] = "English"; m_combo_language.set_active(row); for(size_t i = 2; i < languages.size(); i += 2) { row = *(model->append()); row[m_columns_language.m_col_code] = languages[i]; row[m_columns_language.m_col_language] = languages[i+1]; } } // set column to be shown in comboboxes m_combo_language.pack_start(m_columns_language.m_col_language); m_combo_possible.pack_start(m_columns_url.m_col_show); // set signals m_button_dir.signal_clicked().connect(sigc::mem_fun(*this, &MainWindow::chooseFile)); m_button_quit.signal_clicked().connect(sigc::mem_fun(*this, &MainWindow::quit)); m_button_process.signal_clicked().connect(sigc::mem_fun(*this, &MainWindow::process)); m_button_get_names.signal_clicked().connect(sigc::mem_fun(*this, &MainWindow::getNames)); m_entry_show.signal_activate().connect(sigc::mem_fun(*this, &MainWindow::process)); m_entry_dir.signal_activate().connect(sigc::mem_fun(*this, &MainWindow::process)); m_button_pattern.signal_clicked().connect(sigc::mem_fun(*this, &MainWindow::patternHelp)); // show everything except possible shows and items related to them m_layout.show(); m_label_show.show(); m_label_language.show(); m_entry_show.show(); m_entry_dir.show(); m_combo_language.show(); m_button_process.show(); m_button_quit.show(); m_button_dir.show(); m_check_linux.show(); m_check_linux.set_active(true); m_check_trust.show(); m_button_pattern.show(); m_entry_pattern.show(); m_label_pattern.show(); m_label_dir.show(); }