Merge pull request #1 from fbastani/master

Added optional reason to the ignore feature
This commit is contained in:
soliton- 2013-05-17 11:36:22 -07:00
commit e827728e78
8 changed files with 279 additions and 124 deletions

View file

@ -46,11 +46,9 @@ std::set<t_translation::t_terrain> encountered_terrains_set;
std::map<std::string, std::vector<std::string> > history_map;
const unsigned max_history_saved = 50;
std::set<std::string> friends;
std::set<std::string> ignores;
std::map<std::string, preferences::acquaintance> acquaintances;
bool friends_initialized = false;
bool ignores_initialized = false;
bool acquaintances_initialized = false;
std::vector<std::string> mp_modifications;
bool modifications_initialized = false;
@ -187,73 +185,101 @@ void parse_admin_authentication(const std::string& sender, const std::string& me
}
}
static void initialize_friends() {
if(!friends_initialized) {
std::vector<std::string> names = utils::split(preferences::get("friends"));
std::set<std::string> tmp(names.begin(), names.end());
friends.swap(tmp);
friends_initialized = true;
void load_acquaintances() {
if(!acquaintances_initialized) {
acquaintances.clear();
BOOST_FOREACH(const config &acfg, preferences::get_prefs()->child_range("acquaintance")) {
acquaintance ac = acquaintance(acfg);
acquaintances[ac.get_nick()] = ac;
}
}
}
const std::set<std::string> & get_friends() {
initialize_friends();
return friends;
}
void save_acquaintances()
{
config *cfg = preferences::get_prefs();
cfg->clear_children("acquaintance");
static void initialize_ignores() {
if(!ignores_initialized) {
std::vector<std::string> names = utils::split(preferences::get("ignores"));
std::set<std::string> tmp(names.begin(), names.end());
ignores.swap(tmp);
ignores_initialized = true;
for(std::map<std::string, acquaintance>::iterator i = acquaintances.begin();
i != acquaintances.end(); ++i)
{
config& item = cfg->add_child("acquaintance");
i->second.save(item);
}
}
const std::set<std::string> & get_ignores() {
return ignores;
const std::map<std::string, acquaintance> & get_acquaintances() {
load_acquaintances();
return acquaintances;
}
bool add_friend(const std::string& nick) {
//returns acquaintances in the form nick => notes where the status = filter
std::map<std::string, std::string> get_acquaintances_nice(const std::string& filter) {
load_acquaintances();
std::map<std::string, std::string> ac_nice;
for(std::map<std::string, acquaintance>::iterator i = acquaintances.begin(); i != acquaintances.end(); ++i)
{
if(i->second.get_status() == filter) {
ac_nice[i->second.get_nick()] = i->second.get_notes();
}
}
return ac_nice;
}
bool add_friend(const std::string& nick, const std::string& notes) {
if (!utils::isvalid_wildcard(nick)) return false;
friends.insert(nick);
preferences::set("friends", utils::join(friends));
acquaintances[nick] = preferences::acquaintance(nick, "friend", notes);
save_acquaintances();
return true;
}
bool add_ignore(const std::string& nick) {
bool add_ignore(const std::string& nick, const std::string& reason) {
if (!utils::isvalid_wildcard(nick)) return false;
ignores.insert(nick);
preferences::set("ignores", utils::join(ignores));
acquaintances[nick] = preferences::acquaintance(nick, "ignore", reason);
save_acquaintances();
return true;
}
void remove_friend(const std::string& nick) {
std::set<std::string>::iterator i = friends.find(nick);
if(i != friends.end()) {
friends.erase(i);
preferences::set("friends", utils::join(friends));
}
}
void remove_acquaintance(const std::string& nick) {
std::map<std::string, acquaintance>::iterator i = acquaintances.find(nick);
void remove_ignore(const std::string& nick) {
std::set<std::string>::iterator i = ignores.find(nick);
if(i != ignores.end()) {
ignores.erase(i);
preferences::set("ignores", utils::join(ignores));
//nick might include the notes, depending on how we're removing
if(i == acquaintances.end()) {
size_t pos = nick.find_first_of(' ');
if(pos != std::string::npos) {
i = acquaintances.find(nick.substr(0, pos));
}
}
if(i != acquaintances.end()) {
acquaintances.erase(i);
save_acquaintances();
}
}
bool is_friend(const std::string& nick) {
initialize_friends();
return friends.find(nick) != friends.end();
load_acquaintances();
std::map<std::string, acquaintance>::iterator it = acquaintances.find(nick);
if(it == acquaintances.end()) {
return false;
} else {
return it->second.get_status() == "friend";
}
}
bool is_ignored(const std::string& nick) {
initialize_ignores();
return ignores.find(nick) != ignores.end();
load_acquaintances();
std::map<std::string, acquaintance>::iterator it = acquaintances.find(nick);
if(it == acquaintances.end()) {
return false;
} else {
return it->second.get_status() == "ignore";
}
}
void add_completed_campaign(const std::string& campaign_id) {
@ -1022,4 +1048,18 @@ void encounter_map_terrain(gamemap& map){
}
}
void acquaintance::load_from_config(const config& cfg)
{
nick_ = cfg["nick"].str();
status_ = cfg["status"].str();
notes_ = cfg["notes"].str();
}
void acquaintance::save(config& item)
{
item["nick"] = nick_;
item["status"] = status_;
item["notes"] = notes_;
}
} // preferences namespace

View file

@ -26,6 +26,8 @@ class unit_map;
namespace preferences {
class acquaintance;
struct manager
{
manager();
@ -44,13 +46,12 @@ namespace preferences {
bool new_lobby();
const std::set<std::string> & get_friends();
const std::set<std::string> & get_ignores();
bool add_friend(const std::string& nick);
bool add_ignore(const std::string& nick);
const std::map<std::string, acquaintance> & get_acquaintances();
std::map<std::string, std::string> get_acquaintances_nice(const std::string& filter);
bool add_friend(const std::string& nick, const std::string& notes);
bool add_ignore(const std::string& nick, const std::string& reason);
void add_completed_campaign(const std::string& campaign_id);
void remove_friend(const std::string& nick);
void remove_ignore(const std::string& nick);
void remove_acquaintance(const std::string& nick);
bool is_friend(const std::string& nick);
bool is_ignored(const std::string& nick);
bool is_campaign_completed(const std::string& campaign_id);
@ -263,6 +264,45 @@ namespace preferences {
// Add all terrains on the map as encountered terrains.
void encounter_map_terrain(gamemap& map);
class acquaintance {
public:
explicit acquaintance()
{
}
explicit acquaintance(const config& cfg)
{
load_from_config(cfg);
}
explicit acquaintance(const std::string &nick, const std::string status, const std::string notes):
nick_(nick), status_(status), notes_(notes)
{
}
void load_from_config(const config& cfg);
const std::string get_nick() const { return nick_; };
const std::string get_status() const { return status_; };
const std::string get_notes() const { return notes_; };
void save(config& cfg);
protected:
// acquaintance's MP nick
std::string nick_;
// status (e.g., "friend", "ignore")
std::string status_;
// notes on the acquaintance
std::string notes_;
};
}
#endif

View file

@ -389,8 +389,8 @@ preferences_dialog::preferences_dialog(display& disp, const config& game_cfg)
mp_server_search_button_.set_help_string(_("Find and set path to MP server to host LAN games"));
friends_list_button_.set_help_string(_("View and edit your friends and ignores list"));
friends_back_button_.set_help_string(_("Back to the multiplayer options"));
friends_add_friend_button_.set_help_string(_("Add this username to your friends list"));
friends_add_ignore_button_.set_help_string(_("Add this username to your ignores list"));
friends_add_friend_button_.set_help_string(_("Add this username to your friends list (add optional notes, e.g., 'player_name notes on friend')"));
friends_add_ignore_button_.set_help_string(_("Add this username to your ignores list (add optional reason, e.g., 'player_name reason ignored')"));
friends_remove_button_.set_help_string(_("Remove this username from your list"));
friends_input_.set_text("");
@ -953,15 +953,33 @@ void preferences_dialog::process_event()
set_selection(MULTIPLAYER_TAB);
if (friends_add_friend_button_.pressed()) {
if (preferences::add_friend(friends_input_.text())) {
std::string notes = "";
std::string username = friends_input_.text();
size_t pos = username.find_first_of(' ');
if(pos != std::string::npos) {
notes = username.substr(pos + 1);
username = username.substr(0, pos);
}
if (preferences::add_friend(username, notes)) {
friends_input_.clear();
set_friends_menu();
} else {
gui2::show_transient_error_message(disp_.video(), _("Invalid username"));
}
}
}
}
if (friends_add_ignore_button_.pressed()) {
if (preferences::add_ignore(friends_input_.text())) {
std::string reason = "";
std::string username = friends_input_.text();
size_t pos = username.find_first_of(' ');
if(pos != std::string::npos) {
reason = username.substr(pos + 1);
username = username.substr(0, pos);
}
if (preferences::add_ignore(username, reason)) {
friends_input_.clear();
set_friends_menu();
} else {
@ -975,8 +993,7 @@ void preferences_dialog::process_event()
}
if(!to_remove.empty()) {
/** @todo Better to remove from a specific relation. */
preferences::remove_friend(to_remove);
preferences::remove_ignore(to_remove);
preferences::remove_acquaintance(to_remove);
friends_input_.clear();
set_friends_menu();
}
@ -1093,25 +1110,31 @@ void preferences_dialog::sort_advanced_preferences()
void preferences_dialog::set_friends_menu()
{
const std::set<std::string>& friends = preferences::get_friends();
const std::set<std::string>& ignores = preferences::get_ignores();
const std::map<std::string, acquaintance>& acquaintances = preferences::get_acquaintances();
std::vector<std::string> friends_items;
std::vector<std::string> friends_names;
std::string const imgpre = IMAGE_PREFIX + std::string("misc/status-");
std::set<std::string>::const_iterator i;
for (i = friends.begin(); i != friends.end(); ++i)
for (std::map<std::string, acquaintance>::const_iterator i = acquaintances.begin(); i != acquaintances.end(); ++i)
{
friends_items.push_back(imgpre + "friend.png" + COLUMN_SEPARATOR
+ *i + COLUMN_SEPARATOR + _("friend"));
friends_names.push_back(*i);
}
for (i = ignores.begin(); i != ignores.end(); ++i)
{
friends_items.push_back(imgpre + "ignore.png" + COLUMN_SEPARATOR
+ *i + COLUMN_SEPARATOR + _("ignored"));
friends_names.push_back(*i);
std::string image = "friend.png";
std::string descriptor = _("friend");
if(i->second.get_status() == "ignore") {
image = "ignore.png";
descriptor = _("ignored");
}
std::string notes;
if(!i->second.get_notes().empty()) {
notes = " (" + i->second.get_notes() + ")";
}
friends_items.push_back(imgpre + image + COLUMN_SEPARATOR
+ i->second.get_nick() + notes + COLUMN_SEPARATOR + descriptor);
friends_names.push_back(i->first);
}
if (friends_items.empty()) {
friends_items.push_back(_("(empty list)"));

View file

@ -91,21 +91,12 @@ public:
msg_label->set_label("");
}
std::string replace(std::string str, const std::string &src, const std::string &dst)
{
std::string::size_type pos = 0;
while ( (pos = str.find(src, pos)) != std::string::npos ) {
str.replace( pos, src.size(), dst );
pos++;
}
return str;
}
std::string escape(const std::string &str)
{
// need pango escape here
std::string result = replace(str,"&","&amp;");
result = replace(result,"<","&lt;");
result = replace(result,">","&gt;");
std::string result = utils::replace(str, "&", "&amp;");
result = utils::replace(result, "<", "&lt;");
result = utils::replace(result, ">", "&gt;");
return result;
}

View file

@ -151,22 +151,21 @@ void tlobby_player_info::update_relation(twindow& w)
void tlobby_player_info::add_to_friends_button_callback(twindow& w)
{
preferences::add_friend(info_.name);
preferences::add_friend(info_.name, "");
info_.relation = user_info::FRIEND;
update_relation(w);
}
void tlobby_player_info::add_to_ignores_button_callback(twindow& w)
{
preferences::add_ignore(info_.name);
preferences::add_ignore(info_.name, "");
info_.relation = user_info::IGNORED;
update_relation(w);
}
void tlobby_player_info::remove_from_list_button_callback(twindow& w)
{
preferences::remove_friend(info_.name);
preferences::remove_ignore(info_.name);
preferences::remove_acquaintance(info_.name);
info_.relation = user_info::NEUTRAL;
update_relation(w);
}

View file

@ -2287,18 +2287,18 @@ void chat_command_handler::do_log()
void chat_command_handler::do_ignore()
{
if (get_arg(1).empty()) {
const std::set<std::string>& tmp = preferences::get_ignores();
print(_("ignores list"), tmp.empty() ? _("(empty)") : utils::join(tmp));
const std::map<std::string, std::string>& tmp = preferences::get_acquaintances_nice("ignore");
print(_("ignores list"), tmp.empty() ? _("(empty)") : utils::join_map(tmp, ")\n", " (") + ")");
} else {
for(int i = 1; !get_arg(i).empty(); i++){
utils::string_map symbols;
symbols["nick"] = get_arg(i);
if (preferences::add_ignore(get_arg(i))) {
print(_("ignores list"), VGETTEXT("Added to ignore list: $nick", symbols));
chat_handler_.user_relation_changed(get_arg(i));
} else {
command_failed(VGETTEXT("Invalid username: $nick", symbols));
}
std::string reason = get_data(2);
utils::string_map symbols;
symbols["nick"] = get_arg(1);
if (preferences::add_ignore(get_arg(1), reason)) {
print(_("ignores list"), VGETTEXT("Added to ignore list: $nick", symbols));
chat_handler_.user_relation_changed(get_arg(1));
} else {
command_failed(VGETTEXT("Invalid username: $nick", symbols));
}
}
}
@ -2306,18 +2306,18 @@ void chat_command_handler::do_ignore()
void chat_command_handler::do_friend()
{
if (get_arg(1).empty()) {
const std::set<std::string>& tmp = preferences::get_friends();
print(_("friends list"), tmp.empty() ? _("(empty)") : utils::join(tmp));
const std::map<std::string, std::string>& tmp = preferences::get_acquaintances_nice("friend");
print(_("friends list"), tmp.empty() ? _("(empty)") : utils::join_map(tmp, ")\n", " (") + ")");
} else {
for(int i = 1;!get_arg(i).empty();i++){
utils::string_map symbols;
symbols["nick"] = get_arg(i);
if (preferences::add_friend(get_arg(i))) {
chat_handler_.user_relation_changed(get_arg(i));
print(_("friends list"), VGETTEXT("Added to friends list: $nick", symbols));
} else {
command_failed(VGETTEXT("Invalid username: $nick", symbols));
}
std::string notes = get_data(2);
utils::string_map symbols;
symbols["nick"] = get_arg(1);
if (preferences::add_friend(get_arg(1), notes)) {
print(_("friends list"), VGETTEXT("Added to friends list: $nick", symbols));
chat_handler_.user_relation_changed(get_arg(1));
} else {
command_failed(VGETTEXT("Invalid username: $nick", symbols));
}
}
}
@ -2325,8 +2325,7 @@ void chat_command_handler::do_friend()
void chat_command_handler::do_remove()
{
for(int i = 1;!get_arg(i).empty();i++){
preferences::remove_friend(get_arg(i));
preferences::remove_ignore(get_arg(i));
preferences::remove_acquaintance(get_arg(i));
chat_handler_.user_relation_changed(get_arg(i));
utils::string_map symbols;
symbols["nick"] = get_arg(i);
@ -2336,15 +2335,15 @@ void chat_command_handler::do_remove()
void chat_command_handler::do_display()
{
const std::set<std::string> & friends = preferences::get_friends();
const std::set<std::string> & ignores = preferences::get_ignores();
const std::map<std::string, std::string>& friends = preferences::get_acquaintances_nice("friend");
const std::map<std::string, std::string>& ignores = preferences::get_acquaintances_nice("ignore");
if (!friends.empty()) {
print(_("friends list"), utils::join(friends));
print(_("friends list"), utils::join_map(friends, ")\n", " (") + ")");
}
if (!ignores.empty()) {
print(_("ignores list"), utils::join(ignores));
print(_("ignores list"), utils::join_map(ignores, ")\n", " (") + ")");
}
if (friends.empty() && ignores.empty()) {
@ -3174,4 +3173,3 @@ void menu_handler::change_side_controller(const std::string& side, const std::st
network::send_data(cfg, 0);
}
} // end namespace events

View file

@ -65,6 +65,16 @@ bool notspace(const char c)
return !portable_isspace(c);
}
std::string replace(std::string str, const std::string &src, const std::string &dst)
{
std::string::size_type pos = 0;
while ( (pos = str.find(src, pos)) != std::string::npos ) {
str.replace( pos, src.size(), dst );
pos++;
}
return str;
}
std::string &strip(std::string &str)
{
// If all the string contains is whitespace,
@ -97,7 +107,7 @@ std::vector< std::string > split(std::string const &val, const char c, const int
++i1;
}
i2=i1;
while (i2 != val.end()) {
if (*i2 == c) {
std::string new_val(i1, i2);
@ -151,7 +161,7 @@ std::vector< std::string > square_parenthetical_split(std::string const &val,
j1=i1;
if (i1 == val.end()) return res;
if (!separator) {
ERR_GENERAL << "Separator must be specified for square bracket split funtion.\n";
return res;
@ -220,7 +230,7 @@ std::vector< std::string > square_parenthetical_split(std::string const &val,
}
size_square_exp = square_expansion.size();
}
//combine square contents and rest of string for comma zone block
size_t j = 0;
size_t j_max = 0;
@ -245,7 +255,7 @@ std::vector< std::string > square_parenthetical_split(std::string const &val,
res.push_back(new_val);
j++;
} while (j<j_max);
if (i2 == val.end()) //escape loop
break;
++i2;
@ -291,6 +301,32 @@ std::vector< std::string > square_parenthetical_split(std::string const &val,
return res;
}
std::map< std::string, std::string > map_split(std::string const &val, char major, char minor, int flags, std::string const default_value)
{
//first split by major so that we get a vector with the key-value pairs
std::vector< std::string > v = split(val, major, flags);
//now split by minor to extract keys and values
std::map< std::string, std::string > res;
for( std::vector< std::string >::iterator i = v.begin(); i != v.end(); ++i) {
size_t pos = i->find_first_of(minor);
std::string key, value;
if(pos == std::string::npos) {
key = (*i);
value = default_value;
} else {
key = i->substr(0, pos);
value = i->substr(pos + 1);
}
res[key] = value;
}
return res;
}
std::vector< std::string > parenthetical_split(std::string const &val,
const char separator, std::string const &left,
std::string const &right,const int flags)
@ -309,7 +345,7 @@ std::vector< std::string > parenthetical_split(std::string const &val,
++i1;
}
i2=i1;
if(left.size()!=right.size()){
ERR_GENERAL << "Left and Right Parenthesis lists not same length\n";
return res;

View file

@ -54,6 +54,18 @@ enum { REMOVE_EMPTY = 0x01, /**< REMOVE_EMPTY : remove empty elements. */
std::vector< std::string > split(std::string const &val, const char c = ',', const int flags = REMOVE_EMPTY | STRIP_SPACES);
/**
* Splits a string based on two separators into a map.
* major: the separator between elements of the map
* minor: the separator between keys and values in one element
*
* For example, the string 'a:b,c:d,e:f' would be parsed into:
* a => b
* c => d
* e => f
*/
std::map< std::string, std::string > map_split(std::string const &val, char major = ',', char minor = ':', int flags = REMOVE_EMPTY | STRIP_SPACES, std::string const default_value = "");
/**
* Splits a string based either on a separator where text within parenthesis
* is protected from splitting (Note that one can use the same character for
@ -84,7 +96,7 @@ std::vector< std::string > parenthetical_split(std::string const &val,
* must match in each section.
* Leading zeros are preserved if specified between square brackets.
* An asterisk as in [a*n] indicates to expand 'a' n times
*
*
* This is useful to expand animation WML code.
* Examples:
* square_parenthetical_split("a[1-3](1,[5,6,7]),b[8,9]",",") should return
@ -123,6 +135,19 @@ std::string join(T const &v, const std::string& s = ",")
return str.str();
}
template <typename T>
std::string join_map(T const &v, std::string major = ",", std::string minor = ":")
{
std::stringstream str;
for(typename T::const_iterator i = v.begin(); i != v.end(); ++i) {
str << i->first << minor << i->second;
if (boost::next(i) != v.end())
str << major;
}
return str.str();
}
/**
* Generates a new string containing a bullet list.
*
@ -184,6 +209,9 @@ inline std::string escape(const std::string &str)
/** Remove all escape characters (backslash) */
std::string unescape(const std::string &str);
/** Replace all instances of src in str with dst */
std::string replace(std::string str, const std::string &src, const std::string &dst);
/** Remove whitespace from the front and back of the string 'str'. */
std::string &strip(std::string &str);