#include #include #include #include #include #include #include #include #include "databasewindow.hpp" #include "filesystem.hpp" #include "functions.hpp" #include "gtkfunctions.hpp" #include "progresswindow.hpp" #include "resources_linux.h" #include "tv_rename.hpp" DatabaseWindow::~DatabaseWindow() { auto children = get_children(); freeChildren( children ); } DatabaseWindow::DatabaseWindow( bool _linux, std::map< std::string, std::string > &_language_map, Glib::RefPtr< Gtk::Application > _app ) : linux( _linux ), language_map( _language_map ), app( _app ) { set_title( _( DATABASE ) ); property_modal().set_value( true ); set_default_size( 550, 350 ); set_resizable( false ); auto *box = new Gtk::Box( Gtk::ORIENTATION_VERTICAL ); add( *box ); auto *scrolled_window = new Gtk::ScrolledWindow(); auto *buttons = new Gtk::Box( Gtk::ORIENTATION_HORIZONTAL ); auto *button_save = new Gtk::Button(); auto *button_remove = new Gtk::Button(); auto *button_quit = new Gtk::Button(); // pack boxes box->pack_start( *scrolled_window, Gtk::PACK_EXPAND_WIDGET ); box->pack_start( *buttons, Gtk::PACK_SHRINK ); // set margins scrolled_window->set_margin_left( 5 ); scrolled_window->set_margin_right( 5 ); scrolled_window->set_margin_top( 5 ); buttons->set_margin_left( 5 ); buttons->set_margin_right( 5 ); buttons->set_margin_top( 5 ); buttons->set_margin_bottom( 5 ); scrolled_window->add( *m_tree_database ); buttons->pack_start( *button_save, Gtk::PACK_SHRINK ); buttons->pack_start( *button_remove, Gtk::PACK_SHRINK ); buttons->pack_end( *button_quit, Gtk::PACK_SHRINK ); button_save->set_margin_right( 5 ); // set button texts button_save->set_label( _( SAVE ) ); button_remove->set_label( _( DELETE ) ); button_quit->set_label( _( QUIT ) ); // set dimensions button_save->set_size_request( 80, 30 ); button_remove->set_size_request( 80, 30 ); button_quit->set_size_request( 80, 30 ); // set database model m_model = Gtk::TreeStore::create( m_columns_database ); m_tree_database->set_model( m_model ); for ( auto &x : dbGetShows() ) { if ( x["SHOW"] == "pattern" ) continue; auto row = *( m_model->append() ); row[m_columns_database.m_col_id] = std::stoi( x["ID"] ); row[m_columns_database.m_col_show] = x["SHOW"]; row[m_columns_database.m_col_path] = x["PATH"]; row[m_columns_database.m_col_lang] = x["LANGUAGE"]; row[m_columns_database.m_col_lang_full] = language_map[x["LANGUAGE"]]; row[m_columns_database.m_col_show_id] = x["TVID"]; row[m_columns_database.m_col_dvd] = x["DVD"] == "1"; } m_tree_database->append_column( _( SHOW ), m_columns_database.m_col_show ); m_tree_database->append_column( _( PATH ), m_columns_database.m_col_path ); m_tree_database->append_column( _( LANGUAGE ), m_combo_language ); m_tree_database->append_column_editable( _( DVD ), m_columns_database.m_col_dvd ); m_tree_database->signal_button_press_event().connect( sigc::mem_fun( *this, &DatabaseWindow::treeViewClick ) ); // create language combobox for treeview auto model = Gtk::ListStore::create( m_columns_language ); m_combo_language.property_model().set_value( model ); m_combo_language.property_editable().set_value( true ); // the combobox should show value with index 1 in its model // (meaning the full language name) m_combo_language.property_text_column().set_value( 1 ); m_combo_language.property_has_entry().set_value( false ); m_combo_language.signal_changed().connect( sigc::mem_fun( *this, &DatabaseWindow::languageChange ) ); for ( const auto &x : language_map ) { auto row = model->append(); ( *row )[m_columns_language.m_col_code] = x.first; ( *row )[m_columns_language.m_col_language] = x.second; } // set text of m_combo_language to m_columns_database.m_col_lang_full m_tree_database->get_column( 2 )->add_attribute( m_combo_language, "text", m_columns_database.m_col_lang_full ); button_save->signal_clicked().connect( sigc::mem_fun( *this, &DatabaseWindow::save ) ); button_remove->signal_clicked().connect( sigc::mem_fun( *this, &DatabaseWindow::remove ) ); button_quit->signal_clicked().connect( sigc::mem_fun( *this, &DatabaseWindow::quit ) ); m_model->signal_row_changed().connect( sigc::mem_fun( *this, &DatabaseWindow::changed ) ); // show everything show_all_children(); } void DatabaseWindow::languageChange( const Glib::ustring &str, const Gtk::TreeIter &it ) { // set new language and language code in database auto lang_row = *it; auto database_row = *( m_model->get_iter( str ) ); database_row[m_columns_database.m_col_lang] = std::string( lang_row[m_columns_language.m_col_code] ); database_row[m_columns_database.m_col_lang_full] = std::string( lang_row[m_columns_language.m_col_language] ); } bool DatabaseWindow::treeViewClick( GdkEventButton *event ) { Gtk::TreeModel::Path path; Gtk::TreeViewColumn *column; // these variables are unused, but required for get_path_at_pos int x_column, y_column; m_tree_database->get_path_at_pos( event->x, event->y, path, column, x_column, y_column ); if ( column->get_title() == _( SHOW ) ) { // set default values id_search = "_"; show_search = "_"; lang_search = "_"; sw.reset( new SearchWindow( show_search, id_search, lang_search, language_map ) ); sw->signal_hide().connect( sigc::mem_fun( *this, &DatabaseWindow::finishedSearch ) ); app->add_window( *sw ); sw->show(); } else if ( column->get_title() == _( PATH ) ) { Gtk::FileChooserDialog dialog( _( SELECT_DIR ), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER ); dialog.set_transient_for( *this ); dialog.add_button( "_" + _( CANCEL ), Gtk::RESPONSE_CANCEL ); dialog.add_button( _( SELECT ), Gtk::RESPONSE_OK ); auto result = dialog.run(); if ( result == Gtk::RESPONSE_OK ) { auto selection = m_tree_database->get_selection(); auto row = *( selection->get_selected() ); ( *row )[m_columns_database.m_col_path] = dialog.get_filename(); } } return true; } void DatabaseWindow::finishedSearch() { app->remove_window( *sw ); sw.reset(); if ( id_search == "_" || show_search == "_" || lang_search == "_" ) return; // set new show name/id/language auto selection = m_tree_database->get_selection(); auto row = *( selection->get_selected() ); ( *row )[m_columns_database.m_col_show] = show_search; ( *row )[m_columns_database.m_col_show_id] = id_search; ( *row )[m_columns_database.m_col_lang] = lang_search; ( *row )[m_columns_database.m_col_lang_full] = language_map[lang_search]; } void DatabaseWindow::save() { if ( changed_rows.size() == 0 ) return; for ( auto &x : m_model->children() ) { auto index = static_cast< size_t >( x[m_columns_database.m_col_id] ); if ( changed_rows.find( index ) != changed_rows.end() ) { std::string show = x[m_columns_database.m_col_show]; std::string path = x[m_columns_database.m_col_path]; std::string lang = x[m_columns_database.m_col_lang]; std::string show_id = x[m_columns_database.m_col_show_id]; bool dvd = x[m_columns_database.m_col_dvd]; changeDB( index, path, lang, show_id, dvd ); } } auto *pw = new ProgressWindow; app->add_window( *pw ); std::thread t = std::thread( refreshSelectDB, changed_rows, linux, pw ); t.detach(); // lambda capture auto *app_ptr = app.get(); pw->signal_hide().connect( [pw, app_ptr]() { cleanDB(); app_ptr->remove_window( *pw ); delete pw; } ); pw->show(); changed_rows.clear(); } void DatabaseWindow::remove() { auto selected = m_tree_database->get_selection()->get_selected(); removeFromDB( static_cast< std::string >( ( *selected )[m_columns_database.m_col_path] ) ); m_model->erase( selected ); } void DatabaseWindow::changed( const Gtk::TreeModel::Path & /*UNUSED*/, const Gtk::TreeModel::iterator &row ) { std::string path = ( *row )[m_columns_database.m_col_path]; if ( !FSLib::isDirectory( path ) ) { return errorPath( path ); } changed_rows.insert( static_cast< size_t >( ( *row )[m_columns_database.m_col_id] ) ); } void DatabaseWindow::errorPath( const std::string &path ) { Gtk::MessageDialog d( *this, _( INVALID_PATH ), false, Gtk::MESSAGE_ERROR ); d.set_secondary_text( _( DIR_NOT_EXIST, path.c_str() ) ); d.run(); } void DatabaseWindow::quit() { hide(); }