X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=radiant%2Fpreferences.cpp;h=8aaa30b59e720646f00aadfeda890eacb33e402c;hb=f100a82117cc13e8a646e39349865cd35d54b891;hp=4209fdb35d6c5196fc1cae7e0c1909b2663d414b;hpb=e4287c28bb2dafedc81c66e63951d947cfbeb225;p=xonotic%2Fnetradiant.git diff --git a/radiant/preferences.cpp b/radiant/preferences.cpp index 4209fdb3..8aaa30b5 100644 --- a/radiant/preferences.cpp +++ b/radiant/preferences.cpp @@ -26,25 +26,13 @@ // #include "preferences.h" +#include "globaldefs.h" + +#include #include "environment.h" #include "debugging/debugging.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include "generic/callback.h" #include "math/vector.h" #include "string/string.h" @@ -70,12 +58,12 @@ void Global_constructPreferences( PreferencesPage& page ){ } void Interface_constructPreferences( PreferencesPage& page ){ -#ifdef WIN32 +#if GDEF_OS_WINDOWS page.appendCheckBox( "", "Default Text Editor", g_TextEditor_useWin32Editor ); #else { - GtkWidget* use_custom = page.appendCheckBox( "Text Editor", "Custom", g_TextEditor_useCustomEditor ); - GtkWidget* custom_editor = page.appendPathEntry( "Text Editor Command", g_TextEditor_editorCommand, true ); + ui::CheckButton use_custom = page.appendCheckBox( "Text Editor", "Custom", g_TextEditor_useCustomEditor ); + ui::Widget custom_editor = page.appendPathEntry( "Text Editor Command", g_TextEditor_editorCommand, true ); Widget_connectToggleDependency( custom_editor, use_custom ); } #endif @@ -93,7 +81,7 @@ void Mouse_constructPage( PreferenceGroup& group ){ Mouse_constructPreferences( page ); } void Mouse_registerPreferencesPage(){ - PreferencesDialog_addInterfacePage( FreeCaller1() ); + PreferencesDialog_addInterfacePage( makeCallbackF(Mouse_constructPage) ); } @@ -104,6 +92,7 @@ void Mouse_registerPreferencesPage(){ */ #include +#include inline const char* xmlAttr_getName( xmlAttrPtr attr ){ return reinterpret_cast( attr->name ); @@ -132,7 +121,7 @@ CGameDescription::CGameDescription( xmlDocPtr pDoc, const CopiedString& gameFile { StringOutputStream path( 256 ); - path << AppPath_get() << gameFile.c_str() << "/"; + path << DataPath_get() << "gamepacks/" << gameFile.c_str() << "/"; mGameToolsPath = path.c_str(); } @@ -215,30 +204,32 @@ bool Preferences_Save( PreferenceDictionary& preferences, const char* filename ) } bool Preferences_Save_Safe( PreferenceDictionary& preferences, const char* filename ){ - Array tmpName( filename, filename + strlen( filename ) + 1 + 3 ); - *( tmpName.end() - 4 ) = 'T'; - *( tmpName.end() - 3 ) = 'M'; - *( tmpName.end() - 2 ) = 'P'; - *( tmpName.end() - 1 ) = '\0'; + std::string tmpName( filename ); + tmpName += "TMP"; - return Preferences_Save( preferences, tmpName.data() ) + return Preferences_Save( preferences, tmpName.c_str() ) && ( !file_exists( filename ) || file_remove( filename ) ) && file_move( tmpName.data(), filename ); } +struct LogConsole { + static void Export(const Callback &returnz) { + returnz(g_Console_enableLogging); + } -void LogConsole_importString( const char* string ){ - g_Console_enableLogging = string_equal( string, "true" ); - Sys_LogFile( g_Console_enableLogging ); -} -typedef FreeCaller1 LogConsoleImportStringCaller; + static void Import(bool value) { + g_Console_enableLogging = value; + Sys_EnableLogFile(g_Console_enableLogging); + } +}; void RegisterGlobalPreferences( PreferenceSystem& preferences ){ - preferences.registerPreference( "gamefile", CopiedStringImportStringCaller( g_GamesDialog.m_sGameFile ), CopiedStringExportStringCaller( g_GamesDialog.m_sGameFile ) ); - preferences.registerPreference( "gamePrompt", BoolImportStringCaller( g_GamesDialog.m_bGamePrompt ), BoolExportStringCaller( g_GamesDialog.m_bGamePrompt ) ); - preferences.registerPreference( "log console", LogConsoleImportStringCaller(), BoolExportStringCaller( g_Console_enableLogging ) ); + preferences.registerPreference( "gamefile", make_property_string( g_GamesDialog.m_sGameFile ) ); + preferences.registerPreference( "gamePrompt", make_property_string( g_GamesDialog.m_bGamePrompt ) ); + preferences.registerPreference( "skipGamePromptOnce", make_property_string( g_GamesDialog.m_bSkipGamePromptOnce ) ); + preferences.registerPreference( "log console", make_property_string() ); } @@ -288,10 +279,21 @@ void CGameDialog::GameFileImport( int value ){ { ++iGame; } - m_sGameFile = ( *iGame )->mGameFile; + + if ( ( *iGame )->mGameFile != m_sGameFile ) { + m_sGameFile = ( *iGame )->mGameFile; + + // do not trigger radiant restart when switching game on startup using Global Preferences dialog + if ( !onStartup ) { + PreferencesDialog_restartRequired( "Selected Game" ); + } + } + + // onStartup can only be true once, when Global Preferences are displayed at startup + onStartup = false; } -void CGameDialog::GameFileExport( const IntImportCallback& importCallback ) const { +void CGameDialog::GameFileExport( const Callback & importCallback ) const { // use m_sGameFile to set value std::list::const_iterator iGame; int i = 0; @@ -306,13 +308,15 @@ void CGameDialog::GameFileExport( const IntImportCallback& importCallback ) cons importCallback( m_nComboSelect ); } -void CGameDialog_GameFileImport( CGameDialog& self, int value ){ - self.GameFileImport( value ); -} +struct CGameDialog_GameFile { + static void Export(const CGameDialog &self, const Callback &returnz) { + self.GameFileExport(returnz); + } -void CGameDialog_GameFileExport( CGameDialog& self, const IntImportCallback& importCallback ){ - self.GameFileExport( importCallback ); -} + static void Import(CGameDialog &self, int value) { + self.GameFileImport(value); + } +}; void CGameDialog::CreateGlobalFrame( PreferencesPage& page ){ std::vector games; @@ -324,57 +328,29 @@ void CGameDialog::CreateGlobalFrame( PreferencesPage& page ){ page.appendCombo( "Select the game", StringArrayRange( &( *games.begin() ), &( *games.end() ) ), - ReferenceCaller1( *this ), - ReferenceCaller1( *this ) + make_property(*this) ); page.appendCheckBox( "Startup", "Show Global Preferences", m_bGamePrompt ); } -GtkWindow* CGameDialog::BuildDialog(){ - GtkFrame* frame = create_dialog_frame( "Game settings", GTK_SHADOW_ETCHED_IN ); +ui::Window CGameDialog::BuildDialog(){ + auto frame = create_dialog_frame( "Game settings", ui::Shadow::ETCHED_IN ); - GtkVBox* vbox2 = create_dialog_vbox( 0, 4 ); - gtk_container_add( GTK_CONTAINER( frame ), GTK_WIDGET( vbox2 ) ); + auto vbox2 = create_dialog_vbox( 0, 4 ); + frame.add(vbox2); { - PreferencesPage preferencesPage( *this, GTK_WIDGET( vbox2 ) ); + PreferencesPage preferencesPage( *this, vbox2 ); Global_constructPreferences( preferencesPage ); CreateGlobalFrame( preferencesPage ); } - return create_simple_modal_dialog_window( "Global Preferences", m_modal, GTK_WIDGET( frame ) ); -} - -class LoadGameFile -{ -std::list& mGames; -const char* mPath; -public: -LoadGameFile( std::list& games, const char* path ) : mGames( games ), mPath( path ){ -} -void operator()( const char* name ) const { - if ( !extension_equal( path_get_extension( name ), "game" ) ) { - return; - } - StringOutputStream strPath( 256 ); - strPath << mPath << name; - globalOutputStream() << strPath.c_str() << '\n'; - - xmlDocPtr pDoc = xmlParseFile( strPath.c_str() ); - if ( pDoc ) { - mGames.push_front( new CGameDescription( pDoc, name ) ); - xmlFreeDoc( pDoc ); - } - else - { - globalErrorStream() << "XML parser failed on '" << strPath.c_str() << "'\n"; - } + return create_simple_modal_dialog_window( "Global Preferences", m_modal, frame ); } -}; void CGameDialog::ScanForGames(){ StringOutputStream strGamesPath( 256 ); - strGamesPath << AppPath_get() << "games/"; + strGamesPath << DataPath_get() << "gamepacks/games/"; const char *path = strGamesPath.c_str(); globalOutputStream() << "Scanning for game description files: " << path << '\n'; @@ -388,7 +364,22 @@ void CGameDialog::ScanForGames(){ (if that's really needed) */ - Directory_forEach( path, LoadGameFile( mGames, path ) ); + Directory_forEach(path, [&](const char *name) { + if (!extension_equal(path_get_extension(name), "game")) { + return; + } + StringOutputStream strPath(256); + strPath << path << name; + globalOutputStream() << strPath.c_str() << '\n'; + + xmlDocPtr pDoc = xmlParseFile(strPath.c_str()); + if (pDoc) { + mGames.push_front(new CGameDescription(pDoc, name)); + xmlFreeDoc(pDoc); + } else { + globalErrorStream() << "XML parser failed on '" << strPath.c_str() << "'\n"; + } + }); } CGameDescription* CGameDialog::GameDescriptionForComboItem(){ @@ -417,9 +408,12 @@ void CGameDialog::Reset(){ } void CGameDialog::Init(){ + bool gamePrompt = false; + InitGlobalPrefPath(); LoadPrefs(); ScanForGames(); + if ( mGames.empty() ) { Error( "Didn't find any valid game file descriptions, aborting\n" ); } @@ -440,7 +434,15 @@ void CGameDialog::Init(){ CGameDescription* currentGameDescription = 0; - if ( !m_bGamePrompt ) { + // m_bSkipGamePromptOnce is used to not prompt for game on restart, only on fresh startup + if ( m_bGamePrompt && !m_bSkipGamePromptOnce ) { + gamePrompt = true; + } + + m_bSkipGamePromptOnce = false; + g_GamesDialog.SavePrefs(); + + if ( !gamePrompt ) { // search by .game name std::list::iterator iGame; for ( iGame = mGames.begin(); iGame != mGames.end(); ++iGame ) @@ -451,13 +453,19 @@ void CGameDialog::Init(){ } } } - if ( m_bGamePrompt || !currentGameDescription ) { + + if ( gamePrompt || !currentGameDescription ) { + onStartup = true; Create(); DoGameDialog(); // use m_nComboSelect to identify the game to run as and set the globals currentGameDescription = GameDescriptionForComboItem(); ASSERT_NOTNULL( currentGameDescription ); } + else { + onStartup = false; + } + g_pGameDescription = currentGameDescription; g_pGameDescription->Dump(); @@ -471,7 +479,7 @@ CGameDialog::~CGameDialog(){ delete ( *iGame ); *iGame = 0; } - if ( GetWidget() != 0 ) { + if ( GetWidget() ) { Destroy(); } } @@ -484,15 +492,6 @@ inline const char* GameDescription_getIdentifier( const CGameDescription& gameDe return identifier; } -void CGameDialog::AddPacksURL( StringOutputStream &URL ){ - // add the URLs for the list of game packs installed - // FIXME: this is kinda hardcoded for now.. - std::list::iterator iGame; - for ( iGame = mGames.begin(); iGame != mGames.end(); ++iGame ) - { - URL << "&Games_dlup%5B%5D=" << GameDescription_getIdentifier( *( *iGame ) ); - } -} CGameDialog g_GamesDialog; @@ -500,11 +499,11 @@ CGameDialog g_GamesDialog; // ============================================================================= // Widget callbacks for PrefsDlg -static void OnButtonClean( GtkWidget *widget, gpointer data ){ +static void OnButtonClean( ui::Widget widget, gpointer data ){ // make sure this is what the user wants - if ( gtk_MessageBox( GTK_WIDGET( g_Preferences.GetWidget() ), "This will close Radiant and clean the corresponding registry entries.\n" - "Next time you start Radiant it will be good as new. Do you wish to continue?", - "Reset Registry", eMB_YESNO, eMB_ICONASTERISK ) == eIDYES ) { + if ( ui::alert( g_Preferences.GetWidget(), "This will close " RADIANT_NAME " and clean the corresponding registry entries.\n" + "Next time you start " RADIANT_NAME " it will be good as new. Do you wish to continue?", + "Reset Registry", ui::alert_type::YESNO, ui::alert_icon::Asterisk ) == ui::alert_response::YES ) { PrefsDlg *dlg = (PrefsDlg*)data; dlg->EndModal( eIDCANCEL ); @@ -530,7 +529,7 @@ static void OnButtonClean( GtkWidget *widget, gpointer data ){ ======== */ -#define PREFS_LOCAL_FILENAME "local.pref" +const char *PREFS_LOCAL_FILENAME = "local.pref"; void PrefsDlg::Init(){ // m_global_rc_path has been set above @@ -550,25 +549,25 @@ void PrefsDlg::Init(){ g_string_append( m_inipath, PREFS_LOCAL_FILENAME ); } -void notebook_set_page( GtkWidget* notebook, GtkWidget* page ){ +void notebook_set_page( ui::Widget notebook, ui::Widget page ){ int pagenum = gtk_notebook_page_num( GTK_NOTEBOOK( notebook ), page ); if ( gtk_notebook_get_current_page( GTK_NOTEBOOK( notebook ) ) != pagenum ) { gtk_notebook_set_current_page( GTK_NOTEBOOK( notebook ), pagenum ); } } -void PrefsDlg::showPrefPage( GtkWidget* prefpage ){ +void PrefsDlg::showPrefPage( ui::Widget prefpage ){ notebook_set_page( m_notebook, prefpage ); return; } -static void treeSelection( GtkTreeSelection* selection, gpointer data ){ +static void treeSelection( ui::TreeSelection selection, gpointer data ){ PrefsDlg *dlg = (PrefsDlg*)data; GtkTreeModel* model; GtkTreeIter selected; if ( gtk_tree_selection_get_selected( selection, &model, &selected ) ) { - GtkWidget* prefpage; + ui::Widget prefpage{ui::null}; gtk_tree_model_get( model, &selected, 1, (gpointer*)&prefpage, -1 ); dlg->showPrefPage( prefpage ); } @@ -628,50 +627,50 @@ void PreferencesDialog_addSettingsPage( const PreferenceGroupCallback& callback PreferenceGroupCallbacks_pushBack( g_settingsCallbacks, callback ); } -void Widget_updateDependency( GtkWidget* self, GtkWidget* toggleButton ){ - gtk_widget_set_sensitive( self, gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( toggleButton ) ) && GTK_WIDGET_IS_SENSITIVE( toggleButton ) ); +void Widget_updateDependency( ui::Widget self, ui::Widget toggleButton ){ + gtk_widget_set_sensitive( self, gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( toggleButton ) ) && gtk_widget_is_sensitive( toggleButton ) ); } -void ToggleButton_toggled_Widget_updateDependency( GtkWidget *toggleButton, GtkWidget* self ){ +void ToggleButton_toggled_Widget_updateDependency( ui::Widget toggleButton, ui::Widget self ){ Widget_updateDependency( self, toggleButton ); } -void ToggleButton_state_changed_Widget_updateDependency( GtkWidget* toggleButton, GtkStateType state, GtkWidget* self ){ +void ToggleButton_state_changed_Widget_updateDependency( ui::Widget toggleButton, GtkStateType state, ui::Widget self ){ if ( state == GTK_STATE_INSENSITIVE ) { Widget_updateDependency( self, toggleButton ); } } -void Widget_connectToggleDependency( GtkWidget* self, GtkWidget* toggleButton ){ - g_signal_connect( G_OBJECT( toggleButton ), "state_changed", G_CALLBACK( ToggleButton_state_changed_Widget_updateDependency ), self ); - g_signal_connect( G_OBJECT( toggleButton ), "toggled", G_CALLBACK( ToggleButton_toggled_Widget_updateDependency ), self ); +void Widget_connectToggleDependency( ui::Widget self, ui::Widget toggleButton ){ + toggleButton.connect( "state_changed", G_CALLBACK( ToggleButton_state_changed_Widget_updateDependency ), self ); + toggleButton.connect( "toggled", G_CALLBACK( ToggleButton_toggled_Widget_updateDependency ), self ); Widget_updateDependency( self, toggleButton ); } -inline GtkWidget* getVBox( GtkWidget* page ){ - return gtk_bin_get_child( GTK_BIN( page ) ); +inline ui::VBox getVBox( ui::Bin page ){ + return ui::VBox::from(gtk_bin_get_child(page)); } -GtkTreeIter PreferenceTree_appendPage( GtkTreeStore* store, GtkTreeIter* parent, const char* name, GtkWidget* page ){ +GtkTreeIter PreferenceTree_appendPage( ui::TreeStore store, GtkTreeIter* parent, const char* name, ui::Widget page ){ GtkTreeIter group; gtk_tree_store_append( store, &group, parent ); gtk_tree_store_set( store, &group, 0, name, 1, page, -1 ); return group; } -GtkWidget* PreferencePages_addPage( GtkWidget* notebook, const char* name ){ - GtkWidget* preflabel = gtk_label_new( name ); - gtk_widget_show( preflabel ); +ui::Bin PreferencePages_addPage( ui::Widget notebook, const char* name ){ + ui::Widget preflabel = ui::Label( name ); + preflabel.show(); - GtkWidget* pageframe = gtk_frame_new( name ); + auto pageframe = ui::Frame( name ); gtk_container_set_border_width( GTK_CONTAINER( pageframe ), 4 ); - gtk_widget_show( pageframe ); + pageframe.show(); - GtkWidget* vbox = gtk_vbox_new( FALSE, 4 ); - gtk_widget_show( vbox ); + ui::Widget vbox = ui::VBox( FALSE, 4 ); + vbox.show(); gtk_container_set_border_width( GTK_CONTAINER( vbox ), 4 ); - gtk_container_add( GTK_CONTAINER( pageframe ), vbox ); + pageframe.add(vbox); // Add the page to the notebook gtk_notebook_append_page( GTK_NOTEBOOK( notebook ), pageframe, preflabel ); @@ -682,94 +681,97 @@ GtkWidget* PreferencePages_addPage( GtkWidget* notebook, const char* name ){ class PreferenceTreeGroup : public PreferenceGroup { Dialog& m_dialog; -GtkWidget* m_notebook; -GtkTreeStore* m_store; +ui::Widget m_notebook; +ui::TreeStore m_store; GtkTreeIter m_group; public: -PreferenceTreeGroup( Dialog& dialog, GtkWidget* notebook, GtkTreeStore* store, GtkTreeIter group ) : +PreferenceTreeGroup( Dialog& dialog, ui::Widget notebook, ui::TreeStore store, GtkTreeIter group ) : m_dialog( dialog ), m_notebook( notebook ), m_store( store ), m_group( group ){ } PreferencesPage createPage( const char* treeName, const char* frameName ){ - GtkWidget* page = PreferencePages_addPage( m_notebook, frameName ); + auto page = PreferencePages_addPage( m_notebook, frameName ); PreferenceTree_appendPage( m_store, &m_group, treeName, page ); return PreferencesPage( m_dialog, getVBox( page ) ); } }; -GtkWindow* PrefsDlg::BuildDialog(){ - PreferencesDialog_addInterfacePreferences( FreeCaller1() ); +ui::Window PrefsDlg::BuildDialog(){ + PreferencesDialog_addInterfacePreferences( makeCallbackF(Interface_constructPreferences) ); Mouse_registerPreferencesPage(); - GtkWindow* dialog = create_floating_window( "NetRadiant Preferences", m_parent ); + ui::Window dialog = ui::Window(create_floating_window( RADIANT_NAME " Preferences", m_parent )); + + gtk_window_set_transient_for( dialog, m_parent ); + gtk_window_set_position( dialog, GTK_WIN_POS_CENTER_ON_PARENT ); { - GtkWidget* mainvbox = gtk_vbox_new( FALSE, 5 ); - gtk_container_add( GTK_CONTAINER( dialog ), mainvbox ); + auto mainvbox = ui::VBox( FALSE, 5 ); + dialog.add(mainvbox); gtk_container_set_border_width( GTK_CONTAINER( mainvbox ), 5 ); - gtk_widget_show( mainvbox ); + mainvbox.show(); { - GtkWidget* hbox = gtk_hbox_new( FALSE, 5 ); - gtk_widget_show( hbox ); - gtk_box_pack_end( GTK_BOX( mainvbox ), hbox, FALSE, TRUE, 0 ); + auto hbox = ui::HBox( FALSE, 5 ); + hbox.show(); + mainvbox.pack_end(hbox, FALSE, TRUE, 0); { - GtkButton* button = create_dialog_button( "OK", G_CALLBACK( dialog_button_ok ), &m_modal ); - gtk_box_pack_end( GTK_BOX( hbox ), GTK_WIDGET( button ), FALSE, FALSE, 0 ); + auto button = create_dialog_button( "OK", G_CALLBACK( dialog_button_ok ), &m_modal ); + hbox.pack_end(button, FALSE, FALSE, 0); } { - GtkButton* button = create_dialog_button( "Cancel", G_CALLBACK( dialog_button_cancel ), &m_modal ); - gtk_box_pack_end( GTK_BOX( hbox ), GTK_WIDGET( button ), FALSE, FALSE, 0 ); + auto button = create_dialog_button( "Cancel", G_CALLBACK( dialog_button_cancel ), &m_modal ); + hbox.pack_end(button, FALSE, FALSE, 0); } { - GtkButton* button = create_dialog_button( "Clean", G_CALLBACK( OnButtonClean ), this ); - gtk_box_pack_end( GTK_BOX( hbox ), GTK_WIDGET( button ), FALSE, FALSE, 0 ); + auto button = create_dialog_button( "Clean", G_CALLBACK( OnButtonClean ), this ); + hbox.pack_end(button, FALSE, FALSE, 0); } } { - GtkWidget* hbox = gtk_hbox_new( FALSE, 5 ); - gtk_box_pack_start( GTK_BOX( mainvbox ), hbox, TRUE, TRUE, 0 ); - gtk_widget_show( hbox ); + auto hbox = ui::HBox( FALSE, 5 ); + mainvbox.pack_start( hbox, TRUE, TRUE, 0 ); + hbox.show(); { - GtkWidget* sc_win = gtk_scrolled_window_new( 0, 0 ); + auto sc_win = ui::ScrolledWindow(ui::New); gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( sc_win ), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC ); - gtk_box_pack_start( GTK_BOX( hbox ), sc_win, FALSE, FALSE, 0 ); - gtk_widget_show( sc_win ); + hbox.pack_start( sc_win, FALSE, FALSE, 0 ); + sc_win.show(); gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW( sc_win ), GTK_SHADOW_IN ); // prefs pages notebook - m_notebook = gtk_notebook_new(); + m_notebook = ui::Widget::from(gtk_notebook_new()); // hide the notebook tabs since its not supposed to look like a notebook gtk_notebook_set_show_tabs( GTK_NOTEBOOK( m_notebook ), FALSE ); - gtk_box_pack_start( GTK_BOX( hbox ), m_notebook, TRUE, TRUE, 0 ); - gtk_widget_show( m_notebook ); + hbox.pack_start( m_notebook, TRUE, TRUE, 0 ); + m_notebook.show(); { - GtkTreeStore* store = gtk_tree_store_new( 2, G_TYPE_STRING, G_TYPE_POINTER ); + auto store = ui::TreeStore::from(gtk_tree_store_new( 2, G_TYPE_STRING, G_TYPE_POINTER )); - GtkWidget* view = gtk_tree_view_new_with_model( GTK_TREE_MODEL( store ) ); - gtk_tree_view_set_headers_visible( GTK_TREE_VIEW( view ), FALSE ); + auto view = ui::TreeView(ui::TreeModel::from(store._handle)); + gtk_tree_view_set_headers_visible(view, FALSE ); { - GtkCellRenderer* renderer = gtk_cell_renderer_text_new(); - GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes( "Preferences", renderer, "text", 0, NULL ); - gtk_tree_view_append_column( GTK_TREE_VIEW( view ), column ); + auto renderer = ui::CellRendererText(ui::New); + auto column = ui::TreeViewColumn( "Preferences", renderer, {{"text", 0}} ); + gtk_tree_view_append_column(view, column ); } { - GtkTreeSelection* selection = gtk_tree_view_get_selection( GTK_TREE_VIEW( view ) ); - g_signal_connect( G_OBJECT( selection ), "changed", G_CALLBACK( treeSelection ), this ); + auto selection = ui::TreeSelection::from(gtk_tree_view_get_selection(view)); + selection.connect( "changed", G_CALLBACK( treeSelection ), this ); } - gtk_widget_show( view ); + view.show(); - gtk_container_add( GTK_CONTAINER( sc_win ), view ); + sc_win.add(view); { /********************************************************************/ @@ -780,14 +782,14 @@ GtkWindow* PrefsDlg::BuildDialog(){ PreferencePages_addPage( m_notebook, "Front Page" ); { - GtkWidget* global = PreferencePages_addPage( m_notebook, "Global Preferences" ); + auto global = PreferencePages_addPage( m_notebook, "Global Preferences" ); { PreferencesPage preferencesPage( *this, getVBox( global ) ); Global_constructPreferences( preferencesPage ); } - GtkTreeIter group = PreferenceTree_appendPage( store, 0, "Global", global ); + auto group = PreferenceTree_appendPage( store, 0, "Global", global ); { - GtkWidget* game = PreferencePages_addPage( m_notebook, "Game" ); + auto game = PreferencePages_addPage( m_notebook, "Game" ); PreferencesPage preferencesPage( *this, getVBox( game ) ); g_GamesDialog.CreateGlobalFrame( preferencesPage ); @@ -796,45 +798,45 @@ GtkWindow* PrefsDlg::BuildDialog(){ } { - GtkWidget* interfacePage = PreferencePages_addPage( m_notebook, "Interface Preferences" ); + auto interfacePage = PreferencePages_addPage( m_notebook, "Interface Preferences" ); { PreferencesPage preferencesPage( *this, getVBox( interfacePage ) ); PreferencesPageCallbacks_constructPage( g_interfacePreferences, preferencesPage ); } - GtkTreeIter group = PreferenceTree_appendPage( store, 0, "Interface", interfacePage ); + auto group = PreferenceTree_appendPage( store, 0, "Interface", interfacePage ); PreferenceTreeGroup preferenceGroup( *this, m_notebook, store, group ); PreferenceGroupCallbacks_constructGroup( g_interfaceCallbacks, preferenceGroup ); } { - GtkWidget* display = PreferencePages_addPage( m_notebook, "Display Preferences" ); + auto display = PreferencePages_addPage( m_notebook, "Display Preferences" ); { PreferencesPage preferencesPage( *this, getVBox( display ) ); PreferencesPageCallbacks_constructPage( g_displayPreferences, preferencesPage ); } - GtkTreeIter group = PreferenceTree_appendPage( store, 0, "Display", display ); + auto group = PreferenceTree_appendPage( store, 0, "Display", display ); PreferenceTreeGroup preferenceGroup( *this, m_notebook, store, group ); PreferenceGroupCallbacks_constructGroup( g_displayCallbacks, preferenceGroup ); } { - GtkWidget* settings = PreferencePages_addPage( m_notebook, "General Settings" ); + auto settings = PreferencePages_addPage( m_notebook, "General Settings" ); { PreferencesPage preferencesPage( *this, getVBox( settings ) ); PreferencesPageCallbacks_constructPage( g_settingsPreferences, preferencesPage ); } - GtkTreeIter group = PreferenceTree_appendPage( store, 0, "Settings", settings ); + auto group = PreferenceTree_appendPage( store, 0, "Settings", settings ); PreferenceTreeGroup preferenceGroup( *this, m_notebook, store, group ); PreferenceGroupCallbacks_constructGroup( g_settingsCallbacks, preferenceGroup ); } } - gtk_tree_view_expand_all( GTK_TREE_VIEW( view ) ); + gtk_tree_view_expand_all(view ); g_object_unref( G_OBJECT( store ) ); } @@ -842,7 +844,7 @@ GtkWindow* PrefsDlg::BuildDialog(){ } } - gtk_notebook_set_page( GTK_NOTEBOOK( m_notebook ), 0 ); + gtk_notebook_set_current_page( GTK_NOTEBOOK( m_notebook ), 0 ); return dialog; } @@ -852,7 +854,7 @@ preferences_globals_t g_preferences_globals; PrefsDlg g_Preferences; // global prefs instance -void PreferencesDialog_constructWindow( GtkWindow* main_window ){ +void PreferencesDialog_constructWindow( ui::Window main_window ){ g_Preferences.m_parent = main_window; g_Preferences.Create(); } @@ -904,6 +906,7 @@ void Preferences_Save(){ return; } + // save global preferences g_GamesDialog.SavePrefs(); globalOutputStream() << "saving local preferences to " << g_Preferences.m_inipath->str << "\n"; @@ -931,54 +934,69 @@ void PreferencesDialog_restartRequired( const char* staticName ){ g_restart_required.push_back( staticName ); } -void PreferencesDialog_showDialog(){ - if ( ConfirmModified( "Edit Preferences" ) && g_Preferences.DoModal() == eIDOK ) { - if ( !g_restart_required.empty() ) { - StringOutputStream message( 256 ); - message << "Preference changes require a restart:\n"; - for ( std::vector::iterator i = g_restart_required.begin(); i != g_restart_required.end(); ++i ) - { - message << ( *i ) << '\n'; - } - gtk_MessageBox( GTK_WIDGET( MainFrame_getWindow() ), message.c_str() ); - g_restart_required.clear(); - } - } +bool PreferencesDialog_isRestartRequired(){ + return !g_restart_required.empty(); } +void PreferencesDialog_restartIfRequired(){ + if ( !g_restart_required.empty() ) { + StringOutputStream message( 256 ); + message << "Preference changes require a restart:\n\n"; + for ( std::vector::iterator i = g_restart_required.begin(); i != g_restart_required.end(); ++i ) + { + message << ( *i ) << '\n'; + } + message << "\nRestart now?"; + auto ret = ui::alert( MainFrame_getWindow(), message.c_str(), "Restart " RADIANT_NAME "?", ui::alert_type::YESNO, ui::alert_icon::Question ); -void GameName_importString( const char* value ){ - gamename_set( value ); -} -typedef FreeCaller1 GameNameImportStringCaller; -void GameName_exportString( const StringImportCallback& importer ){ - importer( gamename_get() ); -} -typedef FreeCaller1 GameNameExportStringCaller; + g_restart_required.clear(); -void GameMode_importString( const char* value ){ - gamemode_set( value ); + if ( ret == ui::alert_response::YES ) { + g_GamesDialog.m_bSkipGamePromptOnce = true; + Radiant_Restart(); + } + } } -typedef FreeCaller1 GameModeImportStringCaller; -void GameMode_exportString( const StringImportCallback& importer ){ - importer( gamemode_get() ); + +void PreferencesDialog_showDialog(){ + if ( ConfirmModified( "Edit Preferences" ) && g_Preferences.DoModal() == eIDOK ) { + PreferencesDialog_restartIfRequired(); + } } -typedef FreeCaller1 GameModeExportStringCaller; +struct GameName { + static void Export(const Callback &returnz) { + returnz(gamename_get()); + } + + static void Import(const char *value) { + gamename_set(value); + } +}; + +struct GameMode { + static void Export(const Callback &returnz) { + returnz(gamemode_get()); + } + + static void Import(const char *value) { + gamemode_set(value); + } +}; void RegisterPreferences( PreferenceSystem& preferences ){ -#ifdef WIN32 - preferences.registerPreference( "UseCustomShaderEditor", BoolImportStringCaller( g_TextEditor_useWin32Editor ), BoolExportStringCaller( g_TextEditor_useWin32Editor ) ); +#if GDEF_OS_WINDOWS + preferences.registerPreference( "UseCustomShaderEditor", make_property_string( g_TextEditor_useWin32Editor ) ); #else - preferences.registerPreference( "UseCustomShaderEditor", BoolImportStringCaller( g_TextEditor_useCustomEditor ), BoolExportStringCaller( g_TextEditor_useCustomEditor ) ); - preferences.registerPreference( "CustomShaderEditorCommand", CopiedStringImportStringCaller( g_TextEditor_editorCommand ), CopiedStringExportStringCaller( g_TextEditor_editorCommand ) ); + preferences.registerPreference( "UseCustomShaderEditor", make_property_string( g_TextEditor_useCustomEditor ) ); + preferences.registerPreference( "CustomShaderEditorCommand", make_property_string( g_TextEditor_editorCommand ) ); #endif - preferences.registerPreference( "GameName", GameNameImportStringCaller(), GameNameExportStringCaller() ); - preferences.registerPreference( "GameMode", GameModeImportStringCaller(), GameModeExportStringCaller() ); + preferences.registerPreference( "GameName", make_property() ); + preferences.registerPreference( "GameMode", make_property() ); } void Preferences_Init(){