2020-01-17 13:13:58 +00:00
|
|
|
#include <gtkmm/box.h>
|
|
|
|
#include <gtkmm/button.h>
|
2020-02-12 10:44:34 +00:00
|
|
|
#include <gtkmm/filechooserdialog.h>
|
|
|
|
#include <gtkmm/liststore.h>
|
2020-01-17 13:13:58 +00:00
|
|
|
#include <gtkmm/messagedialog.h>
|
|
|
|
#include <gtkmm/scrolledwindow.h>
|
2020-02-12 10:44:34 +00:00
|
|
|
#include <iostream>
|
2020-01-18 20:16:43 +00:00
|
|
|
#include <thread>
|
2019-07-12 21:10:40 +00:00
|
|
|
|
|
|
|
#include "databasewindow.hpp"
|
2020-01-17 13:13:58 +00:00
|
|
|
#include "filesystem.hpp"
|
2019-07-12 21:10:40 +00:00
|
|
|
#include "functions.hpp"
|
2020-02-12 10:44:34 +00:00
|
|
|
#include "gtkfunctions.hpp"
|
2020-01-17 13:13:58 +00:00
|
|
|
#include "progresswindow.hpp"
|
|
|
|
#include "tv_rename.hpp"
|
2019-07-12 21:10:40 +00:00
|
|
|
|
|
|
|
DatabaseWindow::~DatabaseWindow() {
|
2020-01-17 13:13:58 +00:00
|
|
|
auto children = get_children();
|
2020-02-12 10:44:34 +00:00
|
|
|
freeChildren( children );
|
2019-07-12 21:10:40 +00:00
|
|
|
}
|
|
|
|
|
2020-02-12 10:44:34 +00:00
|
|
|
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 ) {
|
2019-07-12 21:10:40 +00:00
|
|
|
set_title( "Database" );
|
2020-02-12 10:44:34 +00:00
|
|
|
property_modal().set_value( true );
|
2019-07-12 21:10:40 +00:00
|
|
|
|
|
|
|
set_default_size( 550, 350 );
|
|
|
|
set_resizable( false );
|
|
|
|
|
2020-01-17 13:13:58 +00:00
|
|
|
auto *box = new Gtk::Box( Gtk::ORIENTATION_VERTICAL );
|
|
|
|
add( *box );
|
|
|
|
|
|
|
|
auto *scrolled_window = new Gtk::ScrolledWindow();
|
2020-01-18 10:15:20 +00:00
|
|
|
auto *buttons = new Gtk::Box( Gtk::ORIENTATION_HORIZONTAL );
|
2020-01-17 13:13:58 +00:00
|
|
|
|
|
|
|
auto *button_save = new Gtk::Button();
|
|
|
|
auto *button_remove = new Gtk::Button();
|
|
|
|
auto *button_quit = new Gtk::Button();
|
2019-07-12 21:10:40 +00:00
|
|
|
|
2020-01-17 13:13:58 +00:00
|
|
|
// pack boxes
|
|
|
|
box->pack_start( *scrolled_window, Gtk::PACK_EXPAND_WIDGET );
|
2020-01-18 10:15:20 +00:00
|
|
|
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 );
|
|
|
|
|
2020-01-18 20:16:43 +00:00
|
|
|
scrolled_window->add( *m_tree_database );
|
|
|
|
|
2020-01-18 10:15:20 +00:00
|
|
|
buttons->pack_start( *button_save, Gtk::PACK_SHRINK );
|
|
|
|
buttons->pack_start( *button_remove, Gtk::PACK_SHRINK );
|
|
|
|
buttons->pack_end( *button_quit, Gtk::PACK_SHRINK );
|
2020-01-17 13:13:58 +00:00
|
|
|
|
2020-01-18 20:16:43 +00:00
|
|
|
button_save->set_margin_right( 5 );
|
2019-07-12 21:10:40 +00:00
|
|
|
|
|
|
|
// set button texts
|
2020-01-17 13:13:58 +00:00
|
|
|
button_save->set_label( "Save" );
|
|
|
|
button_remove->set_label( "Delete" );
|
|
|
|
button_quit->set_label( "Quit" );
|
2019-07-12 21:10:40 +00:00
|
|
|
|
|
|
|
// set dimensions
|
2020-01-17 13:13:58 +00:00
|
|
|
button_save->set_size_request( 80, 30 );
|
|
|
|
button_remove->set_size_request( 80, 30 );
|
|
|
|
button_quit->set_size_request( 80, 30 );
|
2019-07-12 21:10:40 +00:00
|
|
|
|
2020-01-17 13:13:58 +00:00
|
|
|
// set database model
|
2020-02-09 15:57:37 +00:00
|
|
|
m_model = Gtk::TreeStore::create( m_columns_database );
|
2019-07-12 21:10:40 +00:00
|
|
|
m_tree_database->set_model( m_model );
|
|
|
|
|
2020-01-17 13:13:58 +00:00
|
|
|
for ( auto &x : dbGetShows() ) {
|
|
|
|
if ( x["SHOW"] == "pattern" )
|
2019-07-12 21:10:40 +00:00
|
|
|
continue;
|
|
|
|
auto row = *( m_model->append() );
|
2020-01-17 13:13:58 +00:00
|
|
|
row[m_columns_database.m_col_id] = std::stoi( x["ID"] );
|
2019-07-12 21:10:40 +00:00
|
|
|
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"];
|
2020-02-12 10:44:34 +00:00
|
|
|
row[m_columns_database.m_col_lang_full] = language_map[x["LANGUAGE"]];
|
2020-01-16 10:12:22 +00:00
|
|
|
row[m_columns_database.m_col_show_id] = x["TVID"];
|
2020-02-09 15:57:37 +00:00
|
|
|
row[m_columns_database.m_col_dvd] = x["DVD"] == "1";
|
2019-07-12 21:10:40 +00:00
|
|
|
}
|
|
|
|
|
2020-01-17 13:13:58 +00:00
|
|
|
m_tree_database->append_column( "Show", m_columns_database.m_col_show );
|
2020-02-12 10:44:34 +00:00
|
|
|
m_tree_database->append_column( "Path", m_columns_database.m_col_path );
|
|
|
|
m_tree_database->append_column( "Language", m_combo_language );
|
2020-01-17 13:13:58 +00:00
|
|
|
m_tree_database->append_column_editable( "DVD",
|
|
|
|
m_columns_database.m_col_dvd );
|
2020-02-12 10:44:34 +00:00
|
|
|
m_tree_database->signal_button_press_event().connect(
|
|
|
|
sigc::mem_fun( *this, &DatabaseWindow::treeViewClick ) );
|
|
|
|
|
|
|
|
auto model = Gtk::ListStore::create( m_columns_language );
|
|
|
|
m_combo_language.property_model().set_value( model );
|
|
|
|
m_combo_language.property_editable().set_value( true );
|
|
|
|
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 );
|
2020-01-17 13:13:58 +00:00
|
|
|
|
|
|
|
button_save->signal_clicked().connect(
|
2019-07-12 21:10:40 +00:00
|
|
|
sigc::mem_fun( *this, &DatabaseWindow::save ) );
|
2020-01-17 13:13:58 +00:00
|
|
|
button_remove->signal_clicked().connect(
|
2019-07-12 21:10:40 +00:00
|
|
|
sigc::mem_fun( *this, &DatabaseWindow::remove ) );
|
2020-01-17 13:13:58 +00:00
|
|
|
button_quit->signal_clicked().connect(
|
|
|
|
sigc::mem_fun( *this, &DatabaseWindow::quit ) );
|
2019-07-12 21:10:40 +00:00
|
|
|
m_model->signal_row_changed().connect(
|
|
|
|
sigc::mem_fun( *this, &DatabaseWindow::changed ) );
|
|
|
|
|
|
|
|
// show everything
|
2020-01-17 13:13:58 +00:00
|
|
|
show_all_children();
|
2019-07-12 21:10:40 +00:00
|
|
|
}
|
|
|
|
|
2020-02-12 10:44:34 +00:00
|
|
|
void DatabaseWindow::languageChange( const Glib::ustring &str,
|
|
|
|
const Gtk::TreeIter &it ) {
|
|
|
|
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 a directory",
|
|
|
|
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;
|
|
|
|
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];
|
|
|
|
}
|
|
|
|
|
2019-07-12 21:10:40 +00:00
|
|
|
void DatabaseWindow::save() {
|
2020-01-17 13:13:58 +00:00
|
|
|
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];
|
2020-02-09 15:57:37 +00:00
|
|
|
bool dvd = x[m_columns_database.m_col_dvd];
|
2020-01-16 10:12:22 +00:00
|
|
|
changeDB( index, path, lang, show_id, dvd );
|
2019-07-12 21:10:40 +00:00
|
|
|
}
|
|
|
|
}
|
2020-01-17 13:13:58 +00:00
|
|
|
|
|
|
|
auto *pw = new ProgressWindow;
|
|
|
|
app->add_window( *pw );
|
|
|
|
|
2020-01-18 20:16:43 +00:00
|
|
|
std::thread t = std::thread( refreshSelectDB, changed_rows, linux, pw );
|
2020-01-17 15:24:47 +00:00
|
|
|
t.detach();
|
|
|
|
|
2020-01-17 13:13:58 +00:00
|
|
|
// lambda capture
|
2020-01-17 15:24:47 +00:00
|
|
|
auto *app_ptr = app.get();
|
2020-01-17 13:13:58 +00:00
|
|
|
|
2020-01-17 15:24:47 +00:00
|
|
|
pw->signal_hide().connect( [pw, app_ptr]() {
|
2020-01-17 13:13:58 +00:00
|
|
|
cleanDB();
|
|
|
|
app_ptr->remove_window( *pw );
|
|
|
|
delete pw;
|
|
|
|
} );
|
|
|
|
|
|
|
|
pw->show();
|
2019-07-12 21:10:40 +00:00
|
|
|
changed_rows.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseWindow::remove() {
|
|
|
|
auto selected = m_tree_database->get_selection()->get_selected();
|
2020-01-17 13:13:58 +00:00
|
|
|
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];
|
|
|
|
std::string lang = ( *row )[m_columns_database.m_col_lang];
|
|
|
|
std::string show_id = ( *row )[m_columns_database.m_col_show_id];
|
|
|
|
|
|
|
|
if ( !FSLib::isDirectory( path ) ) {
|
|
|
|
return errorPath( path );
|
|
|
|
} else if ( !findLanguage( lang.c_str() ) ) {
|
|
|
|
return errorLanguage( lang );
|
|
|
|
} else if ( !validID( show_id ) ) {
|
|
|
|
return errorID( show_id );
|
|
|
|
}
|
|
|
|
|
|
|
|
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( "Directory '" + path + "' doesn't exist" );
|
|
|
|
d.run();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseWindow::errorLanguage( const std::string &lang ) {
|
|
|
|
Gtk::MessageDialog d( *this, "Invalid language", false,
|
|
|
|
Gtk::MESSAGE_ERROR );
|
|
|
|
d.set_secondary_text( "Language '" + lang + "' isn't valid" );
|
|
|
|
d.run();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DatabaseWindow::errorID( const std::string &show_id ) {
|
|
|
|
Gtk::MessageDialog d( *this, "Invalid ID", false, Gtk::MESSAGE_ERROR );
|
|
|
|
d.set_secondary_text( "ID '" + show_id + "' isn't valid" );
|
|
|
|
d.run();
|
2019-07-12 21:10:40 +00:00
|
|
|
}
|
|
|
|
|
2020-01-17 13:13:58 +00:00
|
|
|
void DatabaseWindow::quit() {
|
|
|
|
hide();
|
2019-07-12 21:10:40 +00:00
|
|
|
}
|