The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
migrate_version_selection.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2008 - 2025
3 Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY.
11
12 See the COPYING file for more details.
13*/
14
15#define GETTEXT_DOMAIN "wesnoth-lib"
16
18
19#include "addon/manager_ui.hpp"
20#include "filesystem.hpp"
21#include "game_version.hpp"
22#include "gettext.hpp"
23#include "gui/gui.hpp"
29
30#include <boost/algorithm/string.hpp>
31
32static lg::log_domain log_version_migration{"gui/dialogs/migrate_version_selection"};
33#define ERR_LOG_VERSION_MIGRATION LOG_STREAM(err, log_version_migration)
34#define WRN_LOG_VERSION_MIGRATION LOG_STREAM(warn, log_version_migration)
35#define LOG_LOG_VERSION_MIGRATION LOG_STREAM(info, log_version_migration)
36#define DBG_LOG_VERSION_MIGRATION LOG_STREAM(debug, log_version_migration)
37
38namespace gui2::dialogs
39{
40REGISTER_DIALOG(migrate_version_selection)
41
43{
45 if(mig.versions_.size() > 0) {
46 mig.show();
47 } else {
48 // Select initial theme for Wesnoth, fresh install
50 gui2::switch_theme(prefs::get().gui2_theme());
51
52 gui2::show_message(_("No Other Version Found"), _("This would import settings from a previous version of Wesnoth, but no other version was found on this device"), gui2::dialogs::message::button_style::auto_close);
53 }
54}
55
57 : modal_dialog(window_id())
58{
60 std::string current_version_str = filesystem::get_version_path_suffix();
61
62 for(unsigned int i = 1; i < current_version.minor_version(); i++) {
63 std::string previous_version_str = std::to_string(current_version.major_version()) + "."
64 + std::to_string(current_version.minor_version() - i);
65 std::string previous_addons_dir
66 = boost::replace_all_copy(filesystem::get_addons_dir(), current_version_str, previous_version_str);
67
68 if(previous_addons_dir != filesystem::get_addons_dir() && filesystem::file_exists(previous_addons_dir)) {
69 versions_.push_back(previous_version_str);
70 }
71 }
72}
73
75{
76 listbox& version_list = find_widget<listbox>("versions_listbox");
77
78 for(const auto& version : versions_) {
79 version_list.add_row(widget_data{{ "version_label", {{ "label", version }}}});
80 }
81}
82
84{
85 if(get_retval() == gui2::OK) {
86 std::string current_version_str = filesystem::get_version_path_suffix();
87 listbox& version_list = find_widget<listbox>("versions_listbox");
88 int selected_row = version_list.get_selected_row();
89 std::string selected = versions_.at(selected_row);
90
91 std::string migrate_addons_dir
92 = boost::replace_all_copy(filesystem::get_addons_dir(), current_version_str, selected);
93 std::string migrate_synced_prefs_file
94 = boost::replace_all_copy(filesystem::get_synced_prefs_file(), current_version_str, selected);
95 std::string migrate_unsynced_prefs_file
96 = boost::replace_all_copy(filesystem::get_unsynced_prefs_file(), current_version_str, selected);
97 std::string migrate_credentials_file
98 = boost::replace_all_copy(filesystem::get_credentials_file(), current_version_str, selected);
99
100 // given self-compilation and linux distros being able to do whatever they want plus command line options to
101 // alter locations make sure the directories/files are actually different before doing anything with them
102 if(migrate_addons_dir != filesystem::get_addons_dir()) {
103 std::vector<std::string> old_addons;
104 std::vector<std::string> current_addons;
105 std::vector<std::string> migrate_addons;
106
107 filesystem::get_files_in_dir(migrate_addons_dir, nullptr, &old_addons);
108 filesystem::get_files_in_dir(filesystem::get_addons_dir(), nullptr, &current_addons);
109
110 std::set_difference(old_addons.begin(), old_addons.end(), current_addons.begin(), current_addons.end(), std::back_inserter(migrate_addons));
111
112 if(migrate_addons.size() > 0) {
113 ad_hoc_addon_fetch_session(migrate_addons);
114 }
115 }
116
117#if !defined(_WIN32) && !defined(__APPLE__)
118 bool already_migrated = false;
119 std::string linux_old_config_dir = old_config_dir();
120 std::string old_migrate_prefs_file = linux_old_config_dir + "/preferences";
121 std::string old_migrate_credentials_file = linux_old_config_dir + "/credentials-aes";
122
123 if(filesystem::file_exists(old_migrate_prefs_file)) {
124 already_migrated = true;
125 prefs::get().migrate_preferences(old_migrate_prefs_file);
126 }
127 if(filesystem::file_exists(old_migrate_credentials_file)) {
128 already_migrated = true;
129 migrate_credentials(old_migrate_credentials_file);
130 }
131
132 if(!already_migrated)
133#endif
134 {
135 prefs::get().migrate_preferences(migrate_unsynced_prefs_file);
136 prefs::get().migrate_preferences(migrate_synced_prefs_file);
137 migrate_credentials(migrate_credentials_file);
138 }
139
140 // reload preferences and credentials
141 // otherwise the copied files won't be used and also will get overwritten/deleted when Wesnoth closes
142
144
145 // TODO: remove after 1.20. (Not used after that. Needs no replacement.)
147 }
148
150 gui2::switch_theme(prefs::get().gui2_theme());
151}
152
153/**
154 * Prior to 1.19 linux installs would usually store the credentials and preferences file under XDG_CONFIG_HOME with no version separation.
155 * That special handling has been removed, but still needs to be accounted for when migrating
156 */
158{
159 char const* xdg_config = getenv("XDG_CONFIG_HOME");
160 std::string old_config_dir;
161
162 if(!xdg_config || xdg_config[0] == '\0') {
163 xdg_config = getenv("HOME");
164 if(!xdg_config) {
166 return old_config_dir;
167 }
168
169 old_config_dir = xdg_config;
170 old_config_dir += "/.config";
171 } else {
172 old_config_dir = xdg_config;
173 }
174
175 old_config_dir += "/wesnoth";
176 return old_config_dir;
177}
178
179void migrate_version_selection::migrate_credentials(const std::string& migrate_credentials_file)
180{
181 // don't touch the credentials file on migrator re-run if it already exists
182 if(migrate_credentials_file != filesystem::get_credentials_file() && filesystem::file_exists(migrate_credentials_file) && !filesystem::file_exists(filesystem::get_credentials_file())) {
183 filesystem::copy_file(migrate_credentials_file, filesystem::get_credentials_file());
184 }
185}
186
187} // namespace gui2::dialogs
@ auto_close
Enables auto close.
Definition message.hpp:71
This shows the dialog to select a previous version of Wesnoth to migrate preferences from and redownl...
virtual void post_show() override
Actions to be taken after the window has been shown.
std::string old_config_dir()
Prior to 1.19 linux installs would usually store the credentials and preferences file under XDG_CONFI...
void migrate_credentials(const std::string &credentials_dir)
virtual void pre_show() override
Actions to be taken before showing the window.
Abstract base class for all modal dialogs.
bool show(const unsigned auto_close_time=0)
Shows the window.
The listbox class.
Definition listbox.hpp:41
grid & add_row(const widget_item &item, const int index=-1)
When an item in the list is selected by the user we need to update the state.
Definition listbox.cpp:92
int get_selected_row() const
Returns the first selected row.
Definition listbox.cpp:290
int get_retval()
Definition window.hpp:394
static prefs & get()
void set_initial_gui2_theme()
void set_campaign_rng_mode_default_for_migration()
void migrate_preferences(const std::string &prefs_dir)
void reload_preferences()
Represents version numbers.
unsigned int minor_version() const
Retrieves the minor version number (x2 in "x1.x2.x3").
unsigned int major_version() const
Retrieves the major version number (x1 in "x1.x2.x3").
Declarations for File-IO.
Interfaces for manipulating version numbers of engine, add-ons, etc.
static std::string _(const char *str)
Definition gettext.hpp:100
This file contains the window object, this object is a top level container which has the event manage...
bool ad_hoc_addon_fetch_session(const std::vector< std::string > &addon_ids)
Conducts an ad-hoc add-ons server connection to download an add-on with a particular id and all it's ...
static lg::log_domain log_version_migration
#define REGISTER_DIALOG(window_id)
Wrapper for REGISTER_DIALOG2.
const std::string & get_version_path_suffix()
bool file_exists(const std::string &name)
Returns true if a file or directory with such name already exists.
void get_files_in_dir(const std::string &dir, std::vector< std::string > *files, std::vector< std::string > *dirs=nullptr, name_mode mode=name_mode::FILE_NAME_ONLY, filter_mode filter=filter_mode::NO_FILTER, reorder_mode reorder=reorder_mode::DONT_REORDER, file_tree_checksum *checksum=nullptr)
Get a list of all files and/or directories in a given directory.
std::string get_user_data_dir()
void copy_file(const std::string &src, const std::string &dest)
Read a file and then writes it back out.
std::string get_synced_prefs_file()
location of preferences file containing preferences that are synced between computers note that wesno...
std::string get_unsynced_prefs_file()
location of preferences file containing preferences that aren't synced between computers
std::string get_credentials_file()
std::string get_addons_dir()
const version_info wesnoth_version(VERSION)
std::map< std::string, widget_item > widget_data
Definition widget.hpp:36
void switch_theme(const std::string &theme_id)
Set and activate the given gui2 theme.
Definition gui.cpp:149
void show_message(const std::string &title, const std::string &msg, const std::string &button_caption, const bool auto_close, const bool message_use_markup, const bool title_use_markup)
Shows a message to the user.
Definition message.cpp:148
@ OK
Dialog was closed with the OK button.
Definition retval.hpp:35
#define i