commit 0bfb6515f1c6f10d4d9d5d7297ca56a18ac3c138 Author: James Meyer Date: Sun Nov 17 18:58:50 2013 -0600 mythutil updated with myth_settings for .27 diff --git a/mythtv/libs/libmythbase/mythcorecontext.cpp b/mythtv/libs/libmythbase/mythcorecontext.cpp index e9cc880..4f7a3bd 100644 --- a/mythtv/libs/libmythbase/mythcorecontext.cpp +++ b/mythtv/libs/libmythbase/mythcorecontext.cpp @@ -1262,6 +1262,90 @@ void MythCoreContext::ResetLanguage(void) d->language.clear(); } +//JM ADDED +void MythCoreContext::savesettings_togroup (QString src_hostname, + QString saved_settingsgroupname ) +{ + return d->m_database->savesettings_togroup(src_hostname, + saved_settingsgroupname); +} + +void MythCoreContext::deletesettings(QString delete_hostname, + QString saved_settingsgroupname) +{ + return d->m_database->deletesettings(delete_hostname, + saved_settingsgroupname); +} + +QMap MythCoreContext::list_settingsgroupname() +{ + return d->m_database->list_settingsgroupname(); +} + +QMap MythCoreContext::diff_settingsgroupname( + QString diff_hostname1, + QString diff_hostname2, + QStringList table_list) +{ + return d->m_database->diff_settingsgroupname(diff_hostname1, + diff_hostname2, + table_list); +} + +void MythCoreContext::clonesettings(QString src_hostname, + QString saved_settingsgroupname, + QStringList table_list, + bool is_full_clone, + QString dest_hostname) +{ + return d->m_database->clonesettings(src_hostname, + saved_settingsgroupname, + table_list, + is_full_clone, + dest_hostname); +} + +void MythCoreContext::restoresettings(QString dest_hostname, + QString saved_settingsgroupname, + QStringList table_list ) +{ + return d->m_database->restoresettings( dest_hostname, + saved_settingsgroupname, + table_list); +} + +void MythCoreContext::change_hostname(QString old_hostname, + QString new_hostname) +{ + return d->m_database->change_hostname(old_hostname, new_hostname) ; +} + +bool MythCoreContext::settings_check(QString src_hostname, + QString saved_settingsgroupname) +{ + return d->m_database->settings_check(src_hostname,saved_settingsgroupname); +} + +void MythCoreContext::import_settings(QMap vp_map, + QString table) +{ + return d->m_database->import_settings(vp_map, table); +} + + +QMap > MythCoreContext::export_settings( + QString src_hostname, + QString saved_settingsgroupname, + QStringList table_list, bool skip_host ) +{ + return d->m_database->export_settings(src_hostname, + saved_settingsgroupname, + table_list , skip_host ); +} + +//END JM ADDED + + void MythCoreContext::InitLocale(void ) { if (!d->m_locale) diff --git a/mythtv/libs/libmythbase/mythcorecontext.h b/mythtv/libs/libmythbase/mythcorecontext.h index aed83d7..3f0de5e 100644 --- a/mythtv/libs/libmythbase/mythcorecontext.h +++ b/mythtv/libs/libmythbase/mythcorecontext.h @@ -198,7 +198,42 @@ class MBASE_PUBLIC MythCoreContext : public QObject, public MythObservable, publ void emitTVPlaybackUnpaused(void) { emit TVPlaybackUnpaused(); } void emitTVPlaybackAborted(void) { emit TVPlaybackAborted(); } void emitTVPlaybackPlaying(void) { emit TVPlaybackPlaying(); } - + + //JM ADDED + void savesettings_togroup(QString src_hostname, + QString saved_settingsgroupname ); + + void deletesettings(QString delete_hostname, + QString saved_settingsgroupname); + + QMap list_settingsgroupname(); + QMap diff_settingsgroupname(QString diff_hostname1, + QString diff_hostname2, + QStringList table_list); + + void clonesettings(QString src_hostname, + QString saved_settingsgroupname, + QStringList table_list, + bool is_full_clone = true, + QString dest_hostname=""); + + void restoresettings (QString dest_hostname, + QString saved_settingsgroupname, + QStringList table_list); + + void change_hostname (QString old_hostname, QString new_hostname); + + bool settings_check (QString src_hostname ,QString saved_settingsgroupname); + void import_settings(QMap vp_map, QString table); + + QMap > export_settings( + QString src_hostname, + QString saved_settingsgroupname, + QStringList table_list, + bool skip_host = false ); + //END JM ADDED + + signals: void TVPlaybackStarted(void); //// TVPlaybackStopped signal should be used in combination with @@ -211,6 +246,7 @@ class MBASE_PUBLIC MythCoreContext : public QObject, public MythObservable, publ void TVPlaybackAboutToStart(void); void TVPlaybackPlaying(void); + private: MythCoreContextPrivate *d; diff --git a/mythtv/libs/libmythbase/mythdb.cpp b/mythtv/libs/libmythbase/mythdb.cpp index e60fce0..ed3bdf7 100644 --- a/mythtv/libs/libmythbase/mythdb.cpp +++ b/mythtv/libs/libmythbase/mythdb.cpp @@ -896,6 +896,1015 @@ void MythDB::WriteDelayedSettings(void) } } +//JM ADDED +void MythDB::savesettings_togroup(QString src_hostname, + QString saved_settingsgroupname ) +{ + LOG(VB_GENERAL, LOG_ERR, QString("Using hostname of : %1") + .arg(src_hostname)); + LOG(VB_GENERAL, LOG_ERR, QString("Saving to group: %1") + .arg(saved_settingsgroupname)); + if ( settings_check( src_hostname , "current" ) ) + { + QStringList table_list; + QString hostname_clause; + table_list.append("settings"); + table_list.append("keybindings"); + table_list.append("jumppoints"); + if ( src_hostname == "GLOBAL" ) + hostname_clause = "hostname IS NULL"; + else + hostname_clause ="hostname = :HOSTNAME"; + + foreach (QString table, table_list) + { + QString dest_tablename = table +"_" + saved_settingsgroupname ; + create_new_table(dest_tablename,table); + + QString query_string; + // Remove old saved values + MSqlQuery query(MSqlQuery::InitCon()); + query_string = QString("DELETE FROM %1 WHERE %2") + .arg(dest_tablename) + .arg(hostname_clause); + + //query_string = QString("DELETE FROM %1 WHERE " + // "hostname = :HOSTNAME").arg(dest_tablename); + + query.prepare(query_string); + query.bindValue(":HOSTNAME" ,src_hostname); + query.exec(); + + //insert all new settings + query_string = QString("REPLACE INTO %1 " + "SELECT * from %2 where %3") + .arg(dest_tablename) + .arg(table) + .arg(hostname_clause); +// query_string = QString("REPLACE INTO %1 " +// "SELECT * from %2 where hostname = :HOSTNAME)") +// .arg(dest_tablename) +// .arg(table); + + query.prepare(query_string); + query.bindValue(":HOSTNAME",src_hostname); + query.exec(); + } + } + else + LOG(VB_GENERAL| VB_STDIO|VB_FLUSH, LOG_ERR, + QString("Couldn't find settings for: %1 \n").arg(src_hostname)); + return; + +}; + +void MythDB::deletesettings(QString delete_hostname, + QString saved_settingsgroupname) +{ + LOG(VB_GENERAL, LOG_ERR, QString("Using hostname of : %1") + .arg(delete_hostname)); + LOG(VB_GENERAL, LOG_ERR, QString("Deleting: %1") + .arg(saved_settingsgroupname)); + int tempItem; + QString src_tablename; + QStringList table_list; + + table_list.append("settings"); + table_list.append("keybindings"); + table_list.append("jumppoints"); + QString hostname_clause; + if ( delete_hostname == "GLOBAL" ) + hostname_clause = "hostname IS NULL"; + else + hostname_clause ="hostname = :HOSTNAME"; + + foreach (QString table, table_list) + { + src_tablename = find_group_table_name(table, saved_settingsgroupname); + MSqlQuery query(MSqlQuery::InitCon()); + // Remove old saved values + if ( does_table_exist(src_tablename)) + { + QString query_string = QString("DELETE from %1 " + "WHERE %2") + .arg(src_tablename) + .arg(hostname_clause); + query.prepare(query_string); + query.bindValue(":HOSTNAME" ,delete_hostname); + query.exec(); + + //check if ok to delete table + query_string = QString("SELECT count(*) from %1") + .arg(src_tablename); + query.prepare(query_string); + if (query.exec() && query.isActive() && query.size() > 0) + { + query.next(); + tempItem = query.value(0).toInt(); + if ( tempItem == 0 ) + drop_temp_table(src_tablename); + } + } + else + LOG(VB_GENERAL, LOG_ERR, + QString("Couldn't find table: %1").arg(src_tablename)); + } + return; +}; // end delete settings + + +QMap MythDB::list_settingsgroupname() +{ + //Returns a QMAP of "settings_groups: hostname" + MSqlQuery query(MSqlQuery::InitCon()); + MSqlQuery subquery(MSqlQuery::InitCon()); + QString tempItem; + QString temp_hostnameItem; + QStringList hostname_list; + QMap return_list; + QString full_table_name; + query.prepare( "show tables like \"settings%\" " ); + if (query.exec() && query.isActive() && query.size() > 0) + { + while (query.next()) + { + full_table_name = query.value(0).toString(); + tempItem=query.value(0).toString().remove(QRegExp("settings_")); + if ( tempItem != "distro_default" ) + { + //loop over tables looking for hostnames + QString query_string = QString("SELECT DISTINCT " + "hostname from %1") + .arg(full_table_name); + subquery.prepare(query_string); + + if (subquery.exec() && subquery.isActive() + && subquery.size() > 0) + { + while (subquery.next()) + { + temp_hostnameItem = subquery.value(0).toString(); + hostname_list.append(temp_hostnameItem); + } + } + //Special case of naming for the settings table; + //This only affects output. + if ( tempItem == "settings" ) + return_list["current"] = hostname_list; + else + return_list[tempItem] = hostname_list; + + //reset hostname_list for the next group + hostname_list = QStringList(); + } + } + } + return return_list; +}; // end list_settingsgroupname + +QMap MythDB::diff_settingsgroupname( + QString diff_hostname1 , + QString diff_hostname2, + QStringList table_list ) +{ + // Returns a QMAP of tablename : diff results + LOG(VB_GENERAL, LOG_ERR, QString("Comparing settings for:")); + LOG(VB_GENERAL, LOG_ERR, QString("host 1: %1").arg(diff_hostname1)); + LOG(VB_GENERAL, LOG_ERR, QString("host 2: %1").arg(diff_hostname2)); + + QString qstr; + QString tempItem; + QString tempString; + + QStringList diff_list; + QStringList settings_list; + QStringList keybinding_list; + + QMap return_list; + if ( table_list.isEmpty() ) + { + table_list.append("settings"); + table_list.append("keybindings"); + } + + MSqlQuery query(MSqlQuery::InitCon()); + foreach (QString table, table_list) + { + if ( table == "settings") + { + + qstr= "SELECT distinct settings.value, :DIFF_HOSTNAME1 AS `hostname`, settings_a.data, :DIFF_HOSTNAME2 AS `hostname`" + " , settings_b.data FROM settings LEFT JOIN settings AS settings_a ON settings_a.value = settings.value AND settings_a.hostname = :DIFF_HOSTNAME1" + " LEFT JOIN settings AS settings_b ON settings_b.value = settings.value AND settings_b.hostname = :DIFF_HOSTNAME2" + " WHERE settings_a.data != settings_b.data OR " + " (settings_a.data IS NULL AND settings_b.data IS NOT NULL) OR (settings_a.data IS NOT NULL AND settings_b.data IS NULL);"; + + query.prepare(qstr); + query.bindValue(":DIFF_HOSTNAME1" , diff_hostname1); + query.bindValue(":DIFF_HOSTNAME2" , diff_hostname2); + + if (query.exec() && query.isActive() && query.size() > 0) + { + while (query.next()) + { + tempString=""; + //value + tempItem = query.value(0).toString(); + tempString.append(tempItem); + tempString.append("|"); + + //hostname_1 + tempItem = query.value(1).toString(); + if (tempItem.isEmpty()) + tempItem=diff_hostname1; + tempString.append(tempItem); + tempString.append("|"); + + //data + tempItem = query.value(2).toString(); + if (tempItem.isEmpty()) + tempItem="NULL"; + tempString.append(tempItem); + tempString.append("|"); + + //hostname_2 + tempItem = query.value(3).toString(); + if (tempItem.isEmpty()) + tempItem=diff_hostname2; + tempString.append(tempItem); + tempString.append("|"); + + //data + tempItem = query.value(4).toString(); + if (tempItem.isEmpty()) + tempItem="NULL"; + tempString.append(tempItem); + + settings_list.append(tempString); + } + return_list["Settings"] = settings_list; + } + } + else if ( table == "keybindings") + { + + qstr="SELECT distinct keybindings.context, keybindings.action, :DIFF_HOSTNAME1 AS `hostname`, keybindings_a.keylist, :DIFF_HOSTNAME2 AS `hostname`, keybindings_b.keylist FROM keybindings " + " LEFT JOIN keybindings AS keybindings_a ON keybindings_a.context = keybindings.context AND keybindings_a.action = keybindings.action " + " AND keybindings_a.hostname = :DIFF_HOSTNAME1 " + " LEFT JOIN keybindings AS keybindings_b ON keybindings_b.context = keybindings.context " + " AND keybindings_b.action = keybindings.action AND keybindings_b.hostname = :DIFF_HOSTNAME2 " + " WHERE keybindings_a.keylist != keybindings_b.keylist OR " + " (keybindings_a.keylist IS NULL AND keybindings_b.keylist IS NOT NULL) OR (keybindings_a.keylist IS NOT NULL AND keybindings_b.keylist IS NULL);"; + query.prepare(qstr); + query.bindValue(":DIFF_HOSTNAME1" , diff_hostname1); + query.bindValue(":DIFF_HOSTNAME2" , diff_hostname2); + + if (query.exec() && query.isActive() && query.size() > 0) + { + while (query.next()) + { + tempString=""; + //context + tempItem = query.value(0).toString(); + tempString.append(tempItem); + tempString.append("|"); + + //action + tempItem = query.value(1).toString(); + tempString.append(tempItem); + tempString.append("|"); + + //hostname + tempItem = query.value(2).toString(); + if (tempItem.isEmpty()) + tempItem=diff_hostname1; + tempString.append(tempItem); + tempString.append("|"); + + //keylist + tempItem = query.value(3).toString(); + if (tempItem.isEmpty()) + tempItem="NULL"; + tempString.append(tempItem); + tempString.append("|"); + + //hostname + tempItem = query.value(4).toString(); + if (tempItem.isEmpty()) + tempItem=diff_hostname2; + tempString.append(tempItem); + tempString.append("|"); + + //keylist + tempItem = query.value(5).toString(); + if (tempItem.isEmpty()) + tempItem="NULL"; + tempString.append(tempItem); + keybinding_list.append(tempString); + } + return_list["Keybindings"] = keybinding_list; + } + } + + } + return return_list; +}; //end diff_settingsgroupname + +void MythDB::clonesettings(QString src_hostname, + QString saved_settingsgroupname, + QStringList table_list, + bool is_full_clone, QString dest_hostname) +{ + LOG(VB_GENERAL, LOG_ERR, QString("Using src hostname of : %1") + .arg(src_hostname)); + LOG(VB_GENERAL, LOG_ERR, QString("Using dest hostname of : %1") + .arg(dest_hostname)); + LOG(VB_GENERAL, LOG_ERR, QString("Cloning setting group: %1") + .arg(saved_settingsgroupname)); + LOG(VB_GENERAL, LOG_ERR, QString("Full Copy : %1") + .arg(is_full_clone)); + + MSqlQuery query(MSqlQuery::InitCon()); + QStringList::Iterator it; + QString current_table; + QString dest_tablename; + QString temptable; + + if ( table_list.isEmpty() ) + { + table_list.append("settings"); + table_list.append("keybindings"); + table_list.append("jumppoints"); + } + + for ( it = table_list.begin(); it != table_list.end(); ++it ) + { + current_table = *it ; + dest_tablename = find_group_table_name(current_table, + saved_settingsgroupname); + + if ( does_table_exist(dest_tablename)) + { + // create temp table for merging settings + temptable="temp_table_" + dest_tablename; + create_temp_table(temptable, current_table ); + + // copy in stored settings + QString query_string = QString("REPLACE INTO %1 " + "(SELECT * from %2 where hostname = :HOSTNAME)") + .arg(temptable) + .arg(dest_tablename); + + query.prepare(query_string); + query.bindValue(":HOSTNAME",src_hostname ); + query.exec(); + + // update hostname for dest_hostname + query_string = QString("UPDATE %1 set hostname = :HOSTNAME") + .arg(temptable); + + query.prepare(query_string); + query.bindValue(":HOSTNAME" , dest_hostname ); + query.exec(); + + //if not full clone remove HOST% settings from temp table; + if ( current_table == "settings" && !is_full_clone) + { + query_string = QString("DELETE FROM %1 WHERE " + "hostname=:HOSTNAME and value like 'HOST%' " ) + .arg(temptable); + + query.prepare(query_string); + query.bindValue( ":HOSTNAME" , dest_hostname ); + query.exec(); + } + + //remove current settings from dest table, + //if not full clone, then leave HOST% + //Need to remove because the old table allows for duplicates + + if ( current_table == "settings" && !is_full_clone) + query_string = QString ("DELETE FROM %1 WHERE " + "hostname = :HOSTNAME " + "and value not like 'HOST%'") + .arg(dest_tablename); + + else + query_string = QString ("DELETE FROM %1 WHERE " + "hostname = :HOSTNAME ") + .arg(dest_tablename); + + query.prepare(query_string); + query.bindValue(":HOSTNAME",dest_hostname); + query.exec(); + + // copy new settings from temp to current + query_string = QString("REPLACE INTO %1 " + "(SELECT * from %2)") + .arg(dest_tablename) + .arg(temptable); + + query.prepare(query_string); + query.exec(); + + // drop temptable + drop_temp_table(temptable); + } + else + LOG(VB_GENERAL, LOG_NOTICE, QString("Couldn't find table: %1") + .arg(dest_tablename)); + } +}; //end clonesettings + +void MythDB::restoresettings (QString dest_hostname, + QString saved_settingsgroupname, + QStringList table_list ) +{ + LOG(VB_GENERAL, LOG_NOTICE, QString("Restoring Settings:")); + LOG(VB_GENERAL, LOG_NOTICE, QString(" src: %1") + .arg(saved_settingsgroupname)); + LOG(VB_GENERAL, LOG_NOTICE, QString(" dest:%1") + .arg(dest_hostname)); + + QString hostname_clause; + if ( dest_hostname == "GLOBAL" ) + hostname_clause = "hostname IS NULL"; + else + hostname_clause ="hostname = :HOSTNAME"; + + bool table_check; + if ( saved_settingsgroupname == "distro_default" ) + table_check = settings_check ( "distro_default" , saved_settingsgroupname ); + else + table_check = settings_check ( dest_hostname , saved_settingsgroupname ); + + + if ( table_check == true ) + { + MSqlQuery query(MSqlQuery::InitCon()); + QStringList::Iterator it; + QString current_table; + if ( table_list.isEmpty() ) + { + table_list.append("settings"); + table_list.append("keybindings"); + table_list.append("jumppoints"); + } + + for ( it = table_list.begin(); it != table_list.end(); ++it ) + { + current_table = *it ; + //find tablenames to use + QString src_tablename = find_group_table_name(current_table, + saved_settingsgroupname); + + QString temptable="temp_table_" + src_tablename; + if ( ! does_table_exist(src_tablename)) + { + LOG(VB_GENERAL, LOG_NOTICE, QString("table does not exist: %1") + .arg(src_tablename)); + continue; + } + // create temp table for merging settings + create_temp_table(temptable, current_table ); + + //could copy in current settings here to account for new stuff + + + + // copy in stored settings + QString query_string; + if ( saved_settingsgroupname == "distro_default" ) + { //special case for restoring default settings + query_string = QString("REPLACE INTO %1 " + "(SELECT * from %2 WHERE %3)") + .arg(temptable) + .arg(src_tablename) + .arg(hostname_clause); + + query.prepare(query_string); + query.bindValue(":HOSTNAME", "distro_default" ); + query.exec(); + + // update hostname in temp table from distro_default + query_string = QString("UPDATE %1 set hostname = :HOSTNAME") + .arg(temptable); + + query.prepare(query_string); + query.bindValue(":HOSTNAME" , dest_hostname ); + query.exec(); + + } + else + { //normal use case + query_string = QString("REPLACE INTO %1 " + "(SELECT * from %2 WHERE %3)") + .arg(temptable) + .arg(src_tablename) + .arg(hostname_clause); + + query.prepare(query_string); + query.bindValue(":HOSTNAME",dest_hostname ); + query.exec(); + } + + //Remove current settings. + //Need to remove because the old table allows for duplicates + query_string = QString("DELETE FROM %1 WHERE " + "%2") + .arg(current_table) + .arg(hostname_clause); + + query.prepare(query_string); + query.bindValue(":HOSTNAME",dest_hostname); + query.exec(); + + // copy new settings from temp to current + query_string = QString("REPLACE INTO %1 " + "(SELECT * from %2)") + .arg(current_table) + .arg(temptable); + + query.prepare(query_string); + query.exec(); + // drop temptable + drop_temp_table(temptable); + } + } +}; //end restore settings + +void MythDB::change_hostname (QString old_hostname, QString new_hostname) +{ + LOG(VB_GENERAL, LOG_NOTICE, QString("Changing hostname from %1 -> %2") + .arg(old_hostname) + .arg(new_hostname)); + + MSqlQuery query(MSqlQuery::InitCon()); + MSqlQuery sub_query(MSqlQuery::InitCon()); + query.prepare( "SHOW TABLES" ); + + if (query.exec() && query.isActive() && query.size() > 0) + { + while (query.next()) + { + QString table_name = query.value(0).toString(); + LOG(VB_GENERAL, LOG_NOTICE, QString("Scanning %1") + .arg(table_name)); + + // LOOP OVER TABLES, CHECK IF IT HAS A HOSTNAME FIELD + QString query_string=QString("SHOW COLUMNS from %1 " + "where field='hostname'") + .arg(table_name); + sub_query.prepare(query_string); + + if (sub_query.exec() && sub_query.size() > 0) + { //update hostname + LOG(VB_GENERAL, LOG_NOTICE, QString(" Updating hostname in: %1") + .arg(table_name)); + query_string = QString("UPDATE %1 SET hostname = :NEW_HOSTNAME " + "WHERE hostname = :OLD_HOSTNAME") + .arg(table_name); + sub_query.prepare(query_string); + sub_query.bindValue(":NEW_HOSTNAME" , new_hostname); + sub_query.bindValue(":OLD_HOSTNAME" , old_hostname); + sub_query.exec(); + } + } + } + + + + + + +} + +bool MythDB::settings_check(QString src_hostname, + QString saved_settingsgroupname) +{ + int tempItem; + bool returncode = false ; + QString table="settings"; + + QString tablename = find_group_table_name(table, saved_settingsgroupname); + QString hostname_clause; + if ( src_hostname == "GLOBAL" ) + hostname_clause = "hostname IS NULL"; + else + hostname_clause ="hostname = :HOSTNAME"; + + if (does_table_exist (tablename)) + { + MSqlQuery query(MSqlQuery::InitCon()); + QString query_string = QString("SELECT COUNT(data) from %1 " + "WHERE %2") + .arg(tablename) + .arg(hostname_clause); + + query.prepare(query_string); + query.bindValue(":HOSTNAME" , src_hostname ); + + if (query.exec() && query.isActive() && query.size() > 0 ) + { + while (query.next()) + { + tempItem = query.value(0).toInt(); + if ( tempItem >= 1 ) + returncode = true; + else + { + LOG(VB_GENERAL, LOG_NOTICE, + QString("Group %1 does not contain" + " valid settings") + .arg(saved_settingsgroupname)); + } + } + } + } + else + LOG(VB_GENERAL, LOG_NOTICE, QString("Couldn't find table: %1") + .arg(tablename)); + return returncode; +}; // end settings_check + +void MythDB::import_settings(QMap vp_map, + QString table) +{ + MSqlQuery query(MSqlQuery::InitCon()); + + //IMPORT SETTINGS TABLE + if (table.startsWith("settings")) + { + if ( table != "settings" ) + create_new_table(table,"settings"); + QString hostname = vp_map.value("hostname"); + QString value = vp_map.value("value"); + QString data = vp_map.value("data"); + + QString hostname_clause; + QVariant import_hostname = QVariant(QVariant::String); + + if ( hostname.isEmpty()) + hostname_clause = "hostname IS NULL"; + else + { + hostname_clause ="hostname = :HOSTNAME"; + import_hostname = hostname; + } + + QString query_string=QString("SELECT value, data, hostname " + "FROM %1 " + "WHERE %2 AND value = :VALUE " + "ORDER BY value") + .arg(table) + .arg(hostname_clause); + + query.prepare(query_string); + query.bindValue(":HOSTNAME", hostname); + query.bindValue(":VALUE", value); + + // if already exisiting records then update, otherwise insert + if (query.exec() && query.isActive()) + { + MSqlQuery sub_query(MSqlQuery::InitCon()); + if ( query.size() > 0 ) + { + query_string = QString("UPDATE " + "%1 " + "set data = :DATA " + "WHERE %2 AND " + "value = :VALUE ") + .arg(table) + .arg(hostname_clause); + + sub_query.prepare(query_string); + sub_query.bindValue(":HOSTNAME", import_hostname); + sub_query.bindValue(":VALUE", value); + sub_query.bindValue(":DATA", data); + sub_query.exec(); + } + else + { + query_string = QString("INSERT INTO " + " %1 " + "(value,data,hostname) " + "VALUES ( :VALUE , :DATA , :HOSTNAME)").arg(table); + + sub_query.prepare(query_string); + sub_query.bindValue(":HOSTNAME", import_hostname); + sub_query.bindValue(":VALUE", value); + sub_query.bindValue(":DATA", data); + sub_query.exec(); + } + } + } + //KEYBINDINGS TABLE + else if (table.startsWith("keybindings")) + { + if ( table != "keybindings" ) + create_new_table(table,"keybindings"); + QString hostname = vp_map.value("hostname"); + QString context = vp_map.value("context"); + QString action = vp_map.value("action"); + QString description = vp_map.value("description"); + QString keylist = vp_map.value("keylist"); + + QString query_string=QString("SELECT context,action,hostname " + "FROM %1 " + "WHERE hostname = :HOSTNAME AND " + "context = :CONTEXT " + "AND action = :ACTION ").arg(table); + query.prepare(query_string); + query.bindValue(":HOSTNAME", hostname); + query.bindValue(":CONTEXT", context); + query.bindValue(":ACTION", action); + + if (query.exec() && query.isActive()) + { + MSqlQuery sub_query(MSqlQuery::InitCon()); + if ( query.size() > 0 ) + { + query_string = QString("UPDATE " + " %1 " + "set keylist = :KEYLIST " + "WHERE hostname = :HOSTNAME AND " + "context = :CONTEXT " + "AND action = :ACTION ").arg(table); + + sub_query.prepare(query_string); + sub_query.bindValue(":HOSTNAME", hostname); + sub_query.bindValue(":KEYLIST", keylist); + sub_query.bindValue(":CONTEXT", context); + sub_query.bindValue(":ACTION", action); + sub_query.exec(); + } + else + { + query_string = QString("INSERT INTO " + " %1 " + " (context , action , description , keylist , hostname) " + " VALUES( " + " :CONTEXT ," + " :ACTION , " + " :DESCRIPTION , " + " :KEYLIST , " + " :HOSTNAME)").arg(table) ; + + sub_query.prepare(query_string); + sub_query.bindValue(":HOSTNAME", hostname); + sub_query.bindValue(":KEYLIST", keylist); + sub_query.bindValue(":CONTEXT", context); + sub_query.bindValue(":ACTION", action); + sub_query.bindValue(":DESCRIPTION", description); + sub_query.exec(); + } + } + } + //JUMP POINTS + else if (table.startsWith("jumppoints")) + { + if ( table != "jumppoints" ) + create_new_table(table,"jumppoints"); + QString hostname = vp_map.value("hostname"); + QString description = vp_map.value("description"); + QString destination = vp_map.value("destination"); + QString keylist = vp_map.value("keylist"); + + QString query_string=QString("SELECT destination, keylist " + "FROM %1 " + "WHERE hostname = :HOSTNAME AND " + "destination = :DESTINATION " + "AND keylist = :KEYLIST ").arg(table); + query.prepare(query_string); + query.bindValue(":HOSTNAME", hostname); + query.bindValue(":DESTINATION", destination); + query.bindValue(":KEYLIST", keylist); + + if (query.exec() && query.isActive()) + { + MSqlQuery sub_query(MSqlQuery::InitCon()); + if ( query.size() > 0 ) + { + query_string = QString("UPDATE " + " %1 " + "set keylist = :KEYLIST " + "WHERE hostname = :HOSTNAME AND " + "destination = :DESTINATION ").arg(table); + + sub_query.prepare(query_string); + sub_query.bindValue(":HOSTNAME", hostname); + sub_query.bindValue(":KEYLIST", keylist); + sub_query.bindValue(":DESTINATION", destination); + sub_query.exec(); + } + else + { + query_string = QString("INSERT INTO " + " %1 " + " (description , destination, keylist , hostname) " + " VALUES( " + " :DESCRIPTION ," + " :DESTINATION , " + " :KEYLIST , " + " :HOSTNAME)").arg(table) ; + + sub_query.prepare(query_string); + sub_query.bindValue(":HOSTNAME", hostname); + sub_query.bindValue(":KEYLIST", keylist); + sub_query.bindValue(":DESTINATION", destination); + sub_query.bindValue(":DESCRIPTION", description); + sub_query.exec(); + } + } + } +}; //end import_settings + +QMap > + MythDB::export_settings(QString src_hostname, + QString saved_settingsgroupname, + QStringList table_list, bool skip_host ) +{ + QMap > result_set; + QStringList::Iterator it; + QString current_table; + int record_count = 0; + + if ( table_list.isEmpty() ) + { + table_list.append("settings"); + table_list.append("keybindings"); + table_list.append("jumppoints"); + } + + MSqlQuery query(MSqlQuery::InitCon()); + QString query_string; + + //loop over tablelist + for ( it = table_list.begin(); it != table_list.end(); ++it ) + { + current_table = *it ; + QString sub_sql; + QStringList fields; + QString field_query; + + QString table_name = find_group_table_name(current_table, + saved_settingsgroupname); + + QString hostname_clause; + if ( src_hostname == "GLOBAL" ) + hostname_clause = "hostname IS NULL"; + else + hostname_clause ="hostname = :HOSTNAME"; + + // find field names + query_string = QString("SHOW COLUMNS from %1").arg(table_name); + query.prepare(query_string); + + //build up field name vars + if (query.exec() && query.isActive() && query.size() > 0) + { + while (query.next()) + { + if (! field_query.isEmpty()) + field_query +=','; + QString tempItem = query.value(0).toString(); + fields.append(tempItem); + field_query += tempItem; + } + } + // when working with settings table skip HOST if skip_host is true + if ( current_table == "settings" && skip_host == true ) + { + QString skip_host_clause; + skip_host_clause = " VALUE not like 'HOST%' AND DATA not like 'HardwareProfile%UUID'" ; + query_string = QString("SELECT %1 FROM %2 WHERE %3 AND %4") + .arg(field_query) + .arg(table_name) + .arg(hostname_clause) + .arg(skip_host_clause); + + } + else + { + query_string = QString("SELECT %1 FROM %2 WHERE %3") + .arg(field_query) + .arg(table_name) + .arg(hostname_clause); + } + query.prepare(query_string); + query.bindValue(":HOSTNAME" , src_hostname); + + //looping over each record in the table query + if (query.exec() && query.isActive() && query.size() > 0) + { + while (query.next()) + { + //construct qmap of elements + //add table name + QMap value_pair; + value_pair["table"]=table_name; + + for ( int i=0 ; i < fields.size();i++ ) + { + QString tempvalue = fields[i]; + QString tempItem = query.value(i).toString(); + value_pair[tempvalue]=tempItem; + } + result_set[QString(record_count)] = value_pair; + record_count++; + } + } + + } // end table loop + return result_set; +}; //end export_settings + + +void MythDB::create_new_table (QString create_table_name,QString like_name) +{ + if ( ! does_table_exist(create_table_name)) + { + MSqlQuery query(MSqlQuery::InitCon()); + QString query_string = QString("CREATE TABLE %1 like %2") + .arg(create_table_name) + .arg(like_name); + + query.prepare(query_string); + query.exec(); + } + else + LOG(VB_GENERAL, LOG_NOTICE, QString("Table is already present," + "will not create it: %1") + .arg(create_table_name)); +}; + + +void MythDB::drop_temp_table (QString table_name) +{ + MSqlQuery query(MSqlQuery::InitCon()); + if (table_name == "settings" | table_name == "keybindings" | table_name == "jumppoints") + return; + QString query_string = QString("DROP TABLE %1").arg(table_name); + query.prepare(query_string); + query.exec(); + return; +} + +void MythDB::create_temp_table (QString create_table_name,QString like_name) +{ + MSqlQuery query(MSqlQuery::InitCon()); + create_new_table(create_table_name,like_name); + QString query_string; + if ( like_name == "settings") + { + query_string = QString ("ALTER TABLE %1 ADD UNIQUE( value)") + .arg(create_table_name); + query.prepare(query_string); + query.exec(); + } + + query_string = QString("TRUNCATE %1").arg(create_table_name); + query.prepare(query_string); + query.exec(); + return; +} + +bool MythDB::does_table_exist(QString table_name) +{ + bool table_exist = false; + QString full_table_name; + MSqlQuery query(MSqlQuery::InitCon()); + + query.prepare( "SHOW TABLES" ); + if (query.exec() && query.isActive() && query.size() > 0) + { + while (query.next()) + { + full_table_name = query.value(0).toString(); + if (table_name == full_table_name) + { + table_exist = true; + break; + } + } + } + return table_exist; +}; + + +QString MythDB::find_group_table_name(QString current_table, + QString saved_settingsgroupname) +{ + QString table_name; + if ( saved_settingsgroupname.toLower() == "current" ) + table_name = current_table ; + else + table_name = current_table + "_" + saved_settingsgroupname ; + + return table_name; +}; +//END JM ADDED + /** * \brief Set a flag indicating we have successfully connected to the database */ diff --git a/mythtv/libs/libmythbase/mythdb.h b/mythtv/libs/libmythbase/mythdb.h index ac2a8ec..f3689a5 100644 --- a/mythtv/libs/libmythbase/mythdb.h +++ b/mythtv/libs/libmythbase/mythdb.h @@ -74,6 +74,49 @@ class MBASE_PUBLIC MythDB void WriteDelayedSettings(void); + //JM ADDED + void savesettings_togroup(QString src_hostname, + QString saved_settingsgroupname ); + void deletesettings(QString delete_hostname, + QString saved_settingsgroupname); + + QMap list_settingsgroupname(); + + QMap diff_settingsgroupname(QString diff_hostname1, + QString diff_hostname2, + QStringList table_list); + + void clonesettings(QString src_hostname, + QString saved_settingsgroupname, + QStringList table_list, + bool is_full_clone = true, + QString dest_hostname=""); + + void restoresettings (QString dest_hostname, + QString saved_settingsgroupname, + QStringList table_list); + + void change_hostname (QString old_hostname, QString new_hostname); + bool settings_check (QString src_hostname, QString saved_settingsgroupname); + void import_settings(QMap vp_map, QString table); + + + QMap > export_settings( + QString src_hostname, + QString saved_settingsgroupname, + QStringList table_list, + bool skip_host = false); + + void create_new_table (QString create_table_name,QString like_name); + void drop_temp_table (QString table_name); + void create_temp_table (QString create_table_name,QString like_name); + bool does_table_exist(QString table_name); + QString find_group_table_name(QString current_table, + QString saved_settingsgroupname); + //END JM ADDED + + + void SetHaveDBConnection(bool connected); void SetHaveSchema(bool schema); bool HaveSchema(void) const; diff --git a/mythtv/programs/mythutil/commandlineparser.cpp b/mythtv/programs/mythutil/commandlineparser.cpp index 902314d..d86b548 100644 --- a/mythtv/programs/mythutil/commandlineparser.cpp +++ b/mythtv/programs/mythutil/commandlineparser.cpp @@ -144,6 +144,37 @@ void MythUtilCommandLineParser::LoadArguments(void) << add("--print-notification-template", "printntemplate", false, "Print the template to be sent to the frontend", "") ->SetGroup("Messaging") + + //settingsutil.cpp + << add("--save-settings", "savesettings", false, + "Save current settings", "") + ->SetGroup("Settings") + << add("--delete-settings", "deletesettings", false, + "Delete current settings", "") + ->SetGroup("Settings") + << add("--restore-settings", "restoresettings", false, + "Restore settings from previous backup", "") + ->SetGroup("Settings") + << add("--list-groups", "listgroups", false, + "List hosts and groups of settings", "") + ->SetGroup("Settings") + << add("--copy-settings", "copysettings", false, + "Copy or Clone settings from one host to another", "") + ->SetGroup("Settings") + << add("--diff-settings", "diffsettings", false, + "Show settings that are different between two hosts", "") + ->SetGroup("Settings") + << add("--change-hostname", "changehostname", false, + "Change the hostname", "") + ->SetGroup("Settings") + << add("--import-settings", "importsettings", false, + "import settings", "") + ->SetRequiredChild("infile") + + << add("--export-settings", "exportsettings", false, + "export settings", "") + ->SetRequiredChild("outfile") + // musicmetautils.cpp << add("--scanmusic", "scanmusic", false, @@ -194,6 +225,59 @@ void MythUtilCommandLineParser::LoadArguments(void) add("--type", "type", "type", "(optional) type of notification (normal, error, warning, check, busy", "") ->SetChildOf("notification"); + //settingsutils.cpp + add("--groupname", "groupname", "", "Group of settings name", "") + ->SetRequiredChildOf("savesettings") + ->SetRequiredChildOf("restoresettings") + ->SetRequiredChildOf("deletesettings") + ->SetChildOf("copysettings"); + + add("--hostname", "hostname", "", "System name to save/restore settings", "") + ->SetChildOf("savesettings") + ->SetChildOf("restoresettings") + ->SetChildOf("copysettings") + ->SetChildOf("deletesettings") + ->SetChildOf("exportsettings") + ->SetChildOf("importsettings"); + + add("--host_1", "host_1", "", "First host in compare list", "") + ->SetRequiredChildOf("diffsettings"); + + add("--host_2", "host_2", "", "Second host in compare list", "") + ->SetRequiredChildOf("diffsettings"); + + + add("--tablelist", "table_list", "", "List of tables to operate on " + "[keybindings,settings]", "") + ->SetChildOf("diffsettings") + ->SetChildOf("restoresettings") + ->SetChildOf("copysettings") + ->SetChildOf("exportsettings"); + + add("--clone", "fullclone", false, "Enable copy of all settings, " + "including those that are unique to each system.", "") + ->SetChildOf("copysettings"); + + + add("--old-host", "oldhost", "", "Hostname to change", "") + ->SetRequiredChildOf("changehostname"); + + add("--new-host", "newhost", "", "New hostname", "") + ->SetRequiredChildOf("changehostname") + ->SetRequiredChildOf("copysettings"); + + add("--format", "format", false, "Format output of differences", "") + ->SetChildOf("diffsettings"); + add("--distro-default", "distro-default", false, "Export settings for" + "import into the default table", "") + ->SetChildOf("exportsettings"); + add("--generic", "generic", false, "export settings without saving " + "the hostname", "") + ->SetChildOf("exportsettings"); + + + + // Generic Options used by more than one utility addRecording(); addInFile(true); diff --git a/mythtv/programs/mythutil/main.cpp b/mythtv/programs/mythutil/main.cpp index 0bc49f2..faada3d 100644 --- a/mythtv/programs/mythutil/main.cpp +++ b/mythtv/programs/mythutil/main.cpp @@ -26,6 +26,7 @@ #include "musicmetautils.h" #include "recordingutils.h" #include "signalhandling.h" +#include "settingsutils.h" int main(int argc, char *argv[]) @@ -110,6 +111,7 @@ registerJobUtils(utilMap); registerMarkupUtils(utilMap); registerMessageUtils(utilMap); + registerSettingsUtils(utilMap); registerMusicUtils(utilMap); registerRecordingUtils(utilMap); diff --git a/mythtv/programs/mythutil/mythutil.pro b/mythtv/programs/mythutil/mythutil.pro index f0ecbf5..f9472fc 100644 --- a/mythtv/programs/mythutil/mythutil.pro +++ b/mythtv/programs/mythutil/mythutil.pro @@ -22,8 +22,10 @@ QMAKE_CLEAN += $(TARGET) HEADERS += backendutils.h fileutils.h jobutils.h markuputils.h HEADERS += messageutils.h mpegutils.h musicmetautils.h HEADERS += recordingutils.h +HEADERS += settingsutils.h SOURCES += main.cpp mythutil.cpp commandlineparser.cpp SOURCES += backendutils.cpp fileutils.cpp jobutils.cpp markuputils.cpp SOURCES += messageutils.cpp mpegutils.cpp musicmetautils.cpp eitutils.cpp SOURCES += recordingutils.cpp +SOURCES += settingsutils.cpp mingw|win32-msvc*: LIBS += -lwinmm -lws2_32 diff --git a/mythtv/programs/mythutil/settingsutils.cpp b/mythtv/programs/mythutil/settingsutils.cpp new file mode 100644 index 0000000..8fc7b0e --- /dev/null +++ b/mythtv/programs/mythutil/settingsutils.cpp @@ -0,0 +1,586 @@ +// C++ includes +#include +using namespace std; + +//QT includes +#include +#include +#include + +// libmyth* includes +#include "compat.h" +#include "exitcodes.h" +#include "mythlogging.h" +#include "mythcontext.h" + + +#include "settingsutils.h" + + +static int SaveSettings(const MythUtilCommandLineParser &cmdline) +{ + QString src_hostname; + QString groupname; + + if (cmdline.toBool("groupname")) + groupname = cmdline.toString("groupname"); + + if (cmdline.toBool("hostname")) + src_hostname = cmdline.toString("hostname"); + else + src_hostname = gCoreContext->GetHostName(); + + gCoreContext->savesettings_togroup(src_hostname,groupname); + return GENERIC_EXIT_OK; +} + +static int DeleteSettings(const MythUtilCommandLineParser &cmdline) +{ + + QString delete_hostname; + QString groupname; + + if (cmdline.toBool("groupname")) + groupname = cmdline.toString("groupname"); + + if (cmdline.toBool("hostname")) + delete_hostname = cmdline.toString("hostname"); + else + delete_hostname = gCoreContext->GetHostName(); + + + gCoreContext->deletesettings(delete_hostname,groupname); + + return GENERIC_EXIT_OK; +} + + +static int RestoreSettings(const MythUtilCommandLineParser &cmdline) +{ + QString dest_hostname; + QString groupname; + QString tablestring; + QStringList table_list; + + if (cmdline.toBool("groupname")) + groupname = cmdline.toString("groupname"); + + + if (cmdline.toBool("hostname")) + dest_hostname = cmdline.toString("hostname"); + else + dest_hostname = gCoreContext->GetHostName(); + + if (cmdline.toBool("table_list")) + { + tablestring = QString(cmdline.toString("table_list")); + table_list = tablestring.split(",", QString::SkipEmptyParts); + } + + gCoreContext->restoresettings(dest_hostname, + groupname, + table_list); + + return GENERIC_EXIT_OK; +} + + +static int CopySettings(const MythUtilCommandLineParser &cmdline) +{ + QString src_hostname; + QString groupname; + QString tablestring; + QStringList table_list; + bool is_full_clone; + QString dest_hostname; + + if (cmdline.toBool("groupname")) + groupname = cmdline.toString("groupname"); + else + groupname = "Current"; + + if (cmdline.toBool("hostname")) + src_hostname = cmdline.toString("hostname"); + else + src_hostname = gCoreContext->GetHostName(); + + if (cmdline.toBool("newhost")) + dest_hostname = cmdline.toString("newhost"); + + if (cmdline.toBool("table_list")) + { + tablestring = QString(cmdline.toString("table_list")); + table_list = tablestring.split(",", QString::SkipEmptyParts); + } + + if (cmdline.toBool("fullclone")) + is_full_clone = true; + else + is_full_clone = false; + + gCoreContext->clonesettings(src_hostname, + groupname, + table_list, + is_full_clone, + dest_hostname); + + return GENERIC_EXIT_OK; +} + +void print_out_diff_formated(QMap resultset) +{ + QString settings_header; + QString keybindings_header; + QString tempString; + QString tempItem; + QString dashline_settings; + QString dashline_key; + QStringList tempList; + + QString host_1; + QString host_2; + QString data_1; + QString data_2; + QString value; + QString context; + QString action; + + int value_width = 35; + int data_width = 40; + + int context_width = 22; + int action_width = 22; + int key_width = 35; + + dashline_key = (tempString.fill('-', 133)); + dashline_settings = (tempString.fill('-', 130)); + + QMap::iterator i; + + + for (i = resultset.begin(); i != resultset.end(); ++i) + { + cout << endl< resultset; + QString diff_hostname1; + QString diff_hostname2; + QStringList table_list; + bool format_results = false; + QMap::iterator i; + + if (cmdline.toBool("host_1")) + diff_hostname1 = cmdline.toString("host_1"); + if (cmdline.toBool("host_2")) + diff_hostname2 = cmdline.toString("host_2"); + + if (cmdline.toBool("table_list")) + { + QString tablestring = QString(cmdline.toString("table_list")); + table_list = tablestring.split(",", QString::SkipEmptyParts); + } + + if (cmdline.toBool("format")) + format_results = true; + + resultset = gCoreContext->diff_settingsgroupname(diff_hostname1, + diff_hostname2, + table_list); + if (resultset.isEmpty()) + cout << "No differences found" << endl; + else + { + if (format_results) + print_out_diff_formated(resultset); + else + { + for (i = resultset.begin(); i != resultset.end(); ++i) + { + cout << i.key().toLocal8Bit().constData() << " : \t" << endl;; + for (int y = 0; y < i.value().size(); ++y) + cout << i.value().at(y).toLocal8Bit().constData()< resultset; + resultset = gCoreContext->list_settingsgroupname(); + QMap::iterator i; + cout << endl; + for (i = resultset.begin(); i != resultset.end(); ++i) + { + cout << i.key().toLocal8Bit().constData() << " : \t"; + for (int y = 0; y < i.value().size(); ++y) + cout << i.value().at(y).toLocal8Bit().constData()<<" " ; + cout << endl; + } + return GENERIC_EXIT_OK; +}; + +static int ImportSettings(const MythUtilCommandLineParser &cmdline) +{ + + if (cmdline.toString("infile").isEmpty()) + { + LOG(VB_STDIO|VB_FLUSH, LOG_ERR, "Missing --infile option\n"); + return GENERIC_EXIT_INVALID_CMDLINE; + } + QString import_hostname; + bool change_name = false; + if (cmdline.toBool("hostname")) + { + change_name = true; + import_hostname = cmdline.toString("hostname"); + } + QString import_filename = cmdline.toString("infile"); + QFile myFile(import_filename); + + QDomDocument doc( "exported_xml" ); + doc.setContent( &myFile ); + + QDomElement docElement = doc.documentElement(); + QDomElement record_element; + + if ( docElement.nodeName() != "exported_xml" ) + { + cout << "not a valid exported xml file" << endl; + return 1; + } + + QString out_string = "Importing records, please be patient"; + cout << out_string.toLocal8Bit().constData() << endl; + //Gives list of records in the file + count + QDomNodeList nodeList = docElement.childNodes(); + int total_records = nodeList.count(); + out_string = QString("\nFound %1 records \n").arg(total_records); + cout << out_string.toLocal8Bit().constData() << endl; + LOG(VB_STDIO|VB_FLUSH, LOG_ERR, out_string); + + for(QDomNode n = docElement.firstChild(); !n.isNull(); n = n.nextSibling()) + { + QString table_name=QString(); + QMap value_pair_map ; + + //find table name for this record + QDomNode tablenode=n.namedItem("table"); + record_element = tablenode.toElement(); + table_name = record_element.text(); + + //loop over childern of n and convert to element + for(QDomNode subn = n.firstChild(); + !subn.isNull(); + subn = subn.nextSibling()) + { + record_element = subn.toElement(); + if ( record_element.nodeName() == "table" ) + continue; + if ( change_name && record_element.nodeName() == "hostname" ) + value_pair_map[record_element.nodeName()] = import_hostname; + else + value_pair_map[record_element.nodeName()] = record_element.text(); + } + if (import_filename.endsWith("syssettings.xml")) + { + if ( value_pair_map["value"] == "BackendServerIP") + { + out_string = "sysettings, ignoring backendserver ip record"; + cout << out_string.toLocal8Bit().constData() << endl; + } + else + gCoreContext->import_settings(value_pair_map,table_name); + } + else + //perform insert + gCoreContext->import_settings(value_pair_map,table_name); + } + return GENERIC_EXIT_OK; +}; //end ImportSettings + + +static int ExportSettings(const MythUtilCommandLineParser &cmdline) +{ + QMap > records; + QString src_hostname; + QString groupname; + QStringList table_list; + QString tablestring; + bool distro_default = false; + bool generic = false; + bool skip_host = false; + + + + QDomDocument doc("mythutils_exported_settings"); + + if (cmdline.toBool("groupname")) + groupname = cmdline.toString("groupname"); + else + groupname = "current"; + + if (cmdline.toBool("hostname")) + src_hostname = cmdline.toString("hostname"); + else + src_hostname = gCoreContext->GetHostName(); + + if (cmdline.toBool("distro-default")) + { + distro_default = true; + skip_host = true; + } + if (cmdline.toBool("generic")) + { + generic = true; + //skip_host = true; + } + if (cmdline.toBool("table_list")) + { + tablestring = QString(cmdline.toString("table_list")); + table_list = tablestring.split(",", QString::SkipEmptyParts); + } + else + table_list << "settings" <<"keybindings" <<"jumppoints" ; + + if (cmdline.toString("outfile").isEmpty()) + { + LOG(VB_STDIO|VB_FLUSH, LOG_ERR, "Missing --outfile option\n"); + return GENERIC_EXIT_INVALID_CMDLINE; + } + + QString export_filename = cmdline.toString("outfile"); + + records = gCoreContext->export_settings(src_hostname,groupname, + table_list, skip_host); + + QDomElement exported_xml = doc.createElement("exported_xml"); + doc.appendChild(exported_xml); + + QMap record_count; + QMap >::iterator i; + for (i = records.begin(); i != records.end(); ++i ) + { + QDomElement record = doc.createElement("record"); + exported_xml.appendChild(record); + + //loop over all values in the record + QMap value_pair = i.value(); + QMap::iterator y; + //because we don't know the name of the key, we loop over it + for (y = value_pair.begin(); y != value_pair.end(); ++y) + { + //add key/pair to xml document + QDomElement tag = doc.createElement(y.key()); + record.appendChild(tag); + QDomText t; + if ( distro_default == true ) + { // If exporting distro_default then change hostname + table + if ( y.key() == "hostname" ) + { //check for global values here, empty value means global + if ( y.value().isEmpty() ) + t = doc.createTextNode(y.value()); + else + t = doc.createTextNode("distro_default"); + } + else if ( y.key() == "table") + t = doc.createTextNode(y.value()+"_distro_default"); + else + t = doc.createTextNode(y.value()); + } + + else if ( generic == true ) + { // If exporting generic then change hostname + if ( y.key() == "hostname" ) + { //check for global values here, empty value means global + if ( y.value().isEmpty() ) + t = doc.createTextNode(y.value()); + else + t = doc.createTextNode("REPLACE_ME"); + } + else + t = doc.createTextNode(y.value()); + } + else + t = doc.createTextNode(y.value()); + + tag.appendChild(t); + //create record counts + if ( y.key() == "table" ) + { + if ( record_count.contains( y.value()) ) + { + int record_num = record_count[y.value()]; + record_count[y.value()] = ++record_num; + } + else + record_count[y.value()] = 1; + } + } + } + QFile file( export_filename ); + + if( !file.open(QIODevice::WriteOnly) ) + return -1; + + QTextStream ts( &file ); + ts << doc.toString(); + file.close(); + QMap::iterator rc_it; + for ( rc_it = record_count.begin(); rc_it != record_count.end(); ++rc_it) + { + QString table = rc_it.key(); + int rc_count = rc_it.value(); + QString out_string = QString ("Exported table %1: %2 records") + .arg(table) + .arg(rc_count); + cout << out_string.toLocal8Bit().constData() << endl; + } + return GENERIC_EXIT_OK; +}; // end export_settings + + +static int ChangeHostname(const MythUtilCommandLineParser &cmdline) +{ + + QString old_hostname; + QString new_hostname; + + + if (cmdline.toBool("oldhost")) + old_hostname = cmdline.toString("oldhost"); + + if (cmdline.toBool("newhost")) + new_hostname = cmdline.toString("newhost"); + + if (old_hostname.isEmpty()) + { + LOG(VB_STDIO|VB_FLUSH, LOG_ERR, "Missing or empty --old-host option\n"); + return GENERIC_EXIT_INVALID_CMDLINE; + } + + if (new_hostname.isEmpty()) + { + LOG(VB_STDIO|VB_FLUSH, LOG_ERR, "Missing or empty --new-host option\n"); + return GENERIC_EXIT_INVALID_CMDLINE; + } + + gCoreContext->change_hostname(old_hostname, new_hostname); + + return GENERIC_EXIT_OK; +}; //end ChangeHostname + +void registerSettingsUtils(UtilMap &utilMap) +{ + utilMap["savesettings"] = &SaveSettings; + utilMap["deletesettings"] = &DeleteSettings; + utilMap["restoresettings"] = &RestoreSettings; + utilMap["copysettings"] = &CopySettings; + utilMap["diffsettings"] = &DiffSettings; + utilMap["listgroups"] = &ListGroups; + utilMap["importsettings"] = &ImportSettings; + utilMap["exportsettings"] = &ExportSettings; + utilMap["changehostname"] = &ChangeHostname; +} + +/* vim: set expandtab tabstop=4 shiftwidth=4: */ \ No newline at end of file diff --git a/mythtv/programs/mythutil/settingsutils.h b/mythtv/programs/mythutil/settingsutils.h new file mode 100644 index 0000000..413496c --- /dev/null +++ b/mythtv/programs/mythutil/settingsutils.h @@ -0,0 +1,3 @@ +#include "mythutil.h" + +void registerSettingsUtils(UtilMap &utilMap);