← Back to team overview

linuxdcpp-team team mailing list archive

[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 2712: add commands to ignore / un-ignore users

 

------------------------------------------------------------
revno: 2712
committer: poy <poy@xxxxxxxxxx>
branch nick: trunk
timestamp: Sat 2011-12-10 19:51:47 +0100
message:
  add commands to ignore / un-ignore users
modified:
  dcpp/UserMatch.cpp
  dcpp/UserMatch.h
  dcpp/UserMatchManager.cpp
  dcpp/UserMatchManager.h
  win32/HubFrame.cpp
  win32/HubFrame.h
  win32/StylesPage.cpp
  win32/StylesPage.h
  win32/UserInfoBase.cpp
  win32/UserInfoBase.h
  win32/UserMatchPage.cpp
  win32/UserMatchPage.h
  win32/WinUtil.cpp


--
lp:dcplusplus
https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk

Your team Dcplusplus-team is subscribed to branch lp:dcplusplus.
To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk/+edit-subscription
=== modified file 'dcpp/UserMatch.cpp'
--- dcpp/UserMatch.cpp	2011-12-05 19:20:06 +0000
+++ dcpp/UserMatch.cpp	2011-12-10 18:51:47 +0000
@@ -38,6 +38,10 @@
 	case REGEX: search = boost::regex(); break;
 	}
 }
+
+bool UserMatch::Rule::operator==(const Rule& rhs) const {
+	return field == rhs.field && pattern == rhs.pattern && getMethod() == rhs.getMethod();
+}
 	
 struct Prepare : boost::static_visitor<bool> {
 	Prepare(const string& pattern) : pattern(pattern) { }

=== modified file 'dcpp/UserMatch.h'
--- dcpp/UserMatch.h	2011-12-05 19:20:06 +0000
+++ dcpp/UserMatch.h	2011-12-10 18:51:47 +0000
@@ -38,9 +38,12 @@
 /** Defines rules to match users. */
 struct UserMatch : public Flags {
 	enum {
-		FAVS = 1 << 1,
-		OPS = 1 << 2,
-		BOTS = 1 << 3
+		GENERATED = 1 << 1, /** Generated by DC++. Matchers that the user touches become precious
+							and cannot be modified anymore by DC++ when automating actions. */
+
+		FAVS = 1 << 2,
+		OPS = 1 << 3,
+		BOTS = 1 << 4
 	};
 
 	string name;
@@ -68,6 +71,8 @@
 		Method getMethod() const;
 		void setMethod(Method method);
 
+		bool operator==(const Rule& rhs) const;
+
 	private:
 		friend struct UserMatch;
 		bool prepare();

=== modified file 'dcpp/UserMatchManager.cpp'
--- dcpp/UserMatchManager.cpp	2011-12-05 19:20:06 +0000
+++ dcpp/UserMatchManager.cpp	2011-12-10 18:51:47 +0000
@@ -21,7 +21,10 @@
 
 #include "Client.h"
 #include "ClientManager.h"
+#include "format.h"
+#include "ScopedFunctor.h"
 #include "SimpleXML.h"
+#include "version.h"
 
 namespace dcpp {
 
@@ -33,7 +36,7 @@
 	SettingsManager::getInstance()->removeListener(this);
 }
 
-UserMatchManager::UserMatches UserMatchManager::getList() const {
+const UserMatchManager::UserMatches& UserMatchManager::getList() const {
 	return list;
 }
 
@@ -65,6 +68,60 @@
 	user.getIdentity().setMatch(nullptr);
 }
 
+void UserMatchManager::ignoreChat(const HintedUser& user, bool ignore) {
+	auto nick = ClientManager::getInstance()->getNicks(user)[0];
+
+	UserMatch matcher;
+	matcher.setFlag(UserMatch::GENERATED);
+
+	matcher.name = str(F_("Match %1% (added by %2%)") % nick % APPNAME);
+
+	if(!user.user->isNMDC()) {
+		// for ADC, just match the CID.
+		UserMatch::Rule rule;
+		rule.field = UserMatch::Rule::CID;
+		rule.pattern = user.user->getCID().toBase32();
+		rule.setMethod(UserMatch::Rule::EXACT);
+		matcher.addRule(std::move(rule));
+
+	} else {
+		// for NMDC, match both the nick and the hub name.
+		UserMatch::Rule rule;
+		rule.field = UserMatch::Rule::NICK;
+		rule.pattern = nick;
+		rule.setMethod(UserMatch::Rule::EXACT);
+		matcher.addRule(std::move(rule));
+
+		rule = UserMatch::Rule();
+		rule.field = UserMatch::Rule::HUB_ADDRESS;
+		rule.pattern = user.hint;
+		rule.setMethod(UserMatch::Rule::EXACT);
+		matcher.addRule(std::move(rule));
+	}
+
+	auto newList = list;
+
+	ScopedFunctor(([this, &newList, &matcher] {
+		newList.insert(newList.begin(), std::move(matcher));
+		setList(std::move(newList));
+	}));
+
+	// first, see if an automatic matcher with these rules already exists.
+	for(auto i = newList.begin(), iend = newList.end(); i != iend; ++i) {
+		if(i->isSet(UserMatch::GENERATED) && i->rules == matcher.rules) {
+			matcher.props = i->props;
+			matcher.props->noChat = ignore;
+			newList.erase(i);
+			return;
+		}
+	}
+
+	matcher.props = new UserMatchProps();
+	matcher.props->noChat = ignore;
+	matcher.props->textColor = -1;
+	matcher.props->bgColor = -1;
+}
+
 void UserMatchManager::on(SettingsManagerListener::Load, SimpleXML& xml) noexcept {
 	UserMatches newList;
 
@@ -78,6 +135,7 @@
 
 			match.name = xml.getChildAttrib("Name");
 
+			if(xml.getBoolChildAttrib("Generated")) { match.setFlag(UserMatch::GENERATED); }
 			if(xml.getBoolChildAttrib("Favs")) { match.setFlag(UserMatch::FAVS); }
 			if(xml.getBoolChildAttrib("Ops")) { match.setFlag(UserMatch::OPS); }
 			if(xml.getBoolChildAttrib("Bots")) { match.setFlag(UserMatch::BOTS); }
@@ -119,6 +177,7 @@
 
 		xml.addChildAttrib("Name", i->name);
 
+		if(i->isSet(UserMatch::GENERATED)) { xml.addChildAttrib("Generated", true); }
 		if(i->isSet(UserMatch::FAVS)) { xml.addChildAttrib("Favs", true); }
 		if(i->isSet(UserMatch::OPS)) { xml.addChildAttrib("Ops", true); }
 		if(i->isSet(UserMatch::BOTS)) { xml.addChildAttrib("Bots", true); }

=== modified file 'dcpp/UserMatchManager.h'
--- dcpp/UserMatchManager.h	2011-12-05 19:20:06 +0000
+++ dcpp/UserMatchManager.h	2011-12-10 18:51:47 +0000
@@ -34,8 +34,8 @@
 	typedef std::vector<UserMatch> UserMatches;
 
 public:
-	/// Retrieve a copy of the list of user matching definitions.
-	UserMatches getList() const;
+	/// Retrieve the list of user matching definitions.
+	const UserMatches& getList() const;
 	/// Assign a new list of user matching definitions. All current users will be re-matched.
 	void setList(UserMatches&& newList);
 
@@ -43,6 +43,8 @@
 	user's identity object will point to the properties of the matched definition on success. */
 	void match(OnlineUser& user) const;
 
+	void ignoreChat(const HintedUser& user, bool ignore);
+
 private:
 	friend class Singleton<UserMatchManager>;
 

=== modified file 'win32/HubFrame.cpp'
--- win32/HubFrame.cpp	2011-12-04 14:56:09 +0000
+++ win32/HubFrame.cpp	2011-12-10 18:51:47 +0000
@@ -200,7 +200,7 @@
 		users->onKeyDown([this](int c) { return handleUsersKeyDown(c); });
 		users->onContextMenu([this](const dwt::ScreenCoordinate &sc) { return handleUsersContextMenu(sc); });
 
-		prepareUserList(users, true);
+		prepareUserList(users);
 
 		TextBox::Seed cs = WinUtil::Seeds::textBox;
 		cs.style |= ES_AUTOHSCROLL;

=== modified file 'win32/HubFrame.h'
--- win32/HubFrame.h	2011-12-03 21:53:57 +0000
+++ win32/HubFrame.h	2011-12-10 18:51:47 +0000
@@ -121,7 +121,7 @@
 
 	class UserInfo : public UserInfoBase, public FastAlloc<UserInfo> {
 	public:
-		UserInfo(const UserTask& u) : UserInfoBase(u.user) {
+		UserInfo(const UserTask& u) : UserInfoBase(u.user, true) {
 			update(u.identity, -1);
 		}
 

=== modified file 'win32/StylesPage.cpp'
--- win32/StylesPage.cpp	2011-12-04 14:56:09 +0000
+++ win32/StylesPage.cpp	2011-12-10 18:51:47 +0000
@@ -19,7 +19,9 @@
 #include "stdafx.h"
 #include "StylesPage.h"
 
+#include <dcpp/format.h>
 #include <dcpp/SettingsManager.h>
+#include <dcpp/version.h>
 
 #include <dwt/widgets/Button.h>
 #include <dwt/widgets/ColorDialog.h>
@@ -51,6 +53,7 @@
 #define IDH_SETTINGS_STYLES_TEXT 0
 #define IDH_SETTINGS_STYLES_BG 0
 #define IDH_SETTINGS_STYLES_CONF_USER_MATCHING 0
+#define IDH_SETTINGS_STYLES_SHOW_GEN_MATCHERS 0
 #define IDH_SETTINGS_STYLES_GLOBAL 0
 #define IDH_SETTINGS_STYLES_UPLOADS 0
 #define IDH_SETTINGS_STYLES_DOWNLOADS 0
@@ -58,7 +61,7 @@
 #define IDH_SETTINGS_STYLES_NO_USER_MATCH 0
 
 StylesPage::StylesPage(dwt::Widget* parent) :
-PropPage(parent, 2, 1),
+PropPage(parent, 1, 1),
 globalData(0),
 noUserMatchData(0),
 table(0),
@@ -68,7 +71,8 @@
 customTextColor(0),
 textColor(0),
 customBgColor(0),
-bgColor(0)
+bgColor(0),
+showGen(0)
 {
 	setHelpId(IDH_STYLESPAGE);
 
@@ -77,7 +81,7 @@
 	grid->row(0).align = GridInfo::STRETCH;
 
 	{
-		auto cur = grid->addChild(GroupBox::Seed(T_("Styles")))->addChild(Grid::Seed(4, 1));
+		auto cur = grid->addChild(GroupBox::Seed(T_("Styles")))->addChild(Grid::Seed(5, 1));
 		cur->column(0).mode = GridInfo::FILL;
 		cur->row(0).mode = GridInfo::FILL;
 		cur->row(0).align = GridInfo::STRETCH;
@@ -133,12 +137,17 @@
 
 		bgColor = cur2->addChild(Button::Seed(T_("Select color")));
 		bgColor->onClicked([this] { handleBgColor(); });
-	}
-
-	{
-		auto button = grid->addChild(Grid::Seed(1, 1))->addChild(Button::Seed(T_("Configure user matching definitions")));
+
+		row = cur->addChild(Grid::Seed(1, 2));
+		row->setSpacing(cur->getSpacing());
+
+		auto button = row->addChild(Button::Seed(T_("Configure user matching definitions")));
 		button->setHelpId(IDH_SETTINGS_STYLES_CONF_USER_MATCHING);
 		button->onClicked([this] { static_cast<SettingsDialog*>(getRoot())->activatePage<UserMatchPage>(); });
+
+		showGen = row->addChild(CheckBox::Seed(str(TF_("Show those generated by %1%") % APPNAME)));
+		showGen->setHelpId(IDH_SETTINGS_STYLES_SHOW_GEN_MATCHERS);
+		showGen->onClicked([this] { static_cast<SettingsDialog*>(getRoot())->getPage<UserMatchPage>()->updateStyles(); });
 	}
 
 	WinUtil::makeColumns(table, columns, COLUMN_LAST);
@@ -200,13 +209,17 @@
 		}
 	}
 
-	if(userMatches.empty()) {
+	bool added = false;
+	for(auto i = userMatches.begin(), iend = userMatches.end(); i != iend; ++i) {
+		if(showGen->getChecked() || !i->isSet(UserMatch::GENERATED)) {
+			table->insert(table->isGrouped() ? GROUP_USERS : -1, new UserMatchData(*i));
+			added = true;
+		}
+	}
+
+	if(!added) {
 		noUserMatchData = new Data(T_("No user matching definition has been set yet"), IDH_SETTINGS_STYLES_NO_USER_MATCH);
 		table->insert(table->isGrouped() ? GROUP_USERS : -1, noUserMatchData);
-	} else {
-		for(auto i = userMatches.begin(), iend = userMatches.end(); i != iend; ++i) {
-			table->insert(table->isGrouped() ? GROUP_USERS : -1, new UserMatchData(*i));
-		}
 	}
 }
 
@@ -378,21 +391,21 @@
 void StylesPage::handleCustomFont() {
 	auto data = table->getSelectedData();
 	data->customFont = customFont->getChecked();
+	if(data->customFont) {
+		initFont(data);
+	}
 	update(data);
 	handleSelectionChanged();
 }
 
 void StylesPage::handleFont() {
 	auto data = table->getSelectedData();
+	initFont(data);
 	FontDialog::Options options;
 	options.strikeout = false;
 	options.underline = false;
 	options.color = false;
 	options.bgColor = getBgColor(data);
-	if(!data->font.first) {
-		// initialize the LOGFONT structure.
-		data->font.second = data->defaultFont.first ? data->defaultFont.second : globalData->getFont().second;
-	}
 	auto color = getTextColor(data);
 	if(FontDialog(this).open(data->font.second, color, &options)) {
 		data->font.first.reset(new dwt::Font(data->font.second));
@@ -403,6 +416,7 @@
 void StylesPage::handleCustomTextColor() {
 	auto data = table->getSelectedData();
 	data->customTextColor = customTextColor->getChecked();
+	data->textColor = getTextColor(data);
 	update(data);
 	handleSelectionChanged();
 }
@@ -419,6 +433,7 @@
 void StylesPage::handleCustomBgColor() {
 	auto data = table->getSelectedData();
 	data->customBgColor = customBgColor->getChecked();
+	data->bgColor = getBgColor(data);
 	update(data);
 	handleSelectionChanged();
 }
@@ -440,6 +455,13 @@
 	return -1;
 }
 
+void StylesPage::initFont(Data* const data) const {
+	if(!data->font.first) {
+		// initialize the LOGFONT structure.
+		data->font.second = data->defaultFont.first ? data->defaultFont.second : globalData->getFont().second;
+	}
+}
+
 COLORREF StylesPage::getTextColor(const Data* const data) const {
 	auto color = data->getTextColor();
 	return (color >= 0) ? color : globalData->getTextColor();

=== modified file 'win32/StylesPage.h'
--- win32/StylesPage.h	2011-12-04 14:56:09 +0000
+++ win32/StylesPage.h	2011-12-10 18:51:47 +0000
@@ -131,6 +131,8 @@
 	CheckBoxPtr customBgColor;
 	ButtonPtr bgColor;
 
+	CheckBoxPtr showGen;
+
 	void handleSelectionChanged();
 	void handleTableHelp(unsigned id);
 	void handleTableHelpId(unsigned& id);
@@ -145,6 +147,7 @@
 	void handleBgColor();
 
 	int colorDialog(COLORREF color);
+	void initFont(Data* const data) const;
 	COLORREF getTextColor(const Data* const data) const;
 	COLORREF getBgColor(const Data* const data) const;
 	void update(Data* const data);

=== modified file 'win32/UserInfoBase.cpp'
--- win32/UserInfoBase.cpp	2011-05-04 19:32:00 +0000
+++ win32/UserInfoBase.cpp	2011-12-10 18:51:47 +0000
@@ -26,6 +26,7 @@
 #include <dcpp/QueueManager.h>
 #include <dcpp/UploadManager.h>
 #include <dcpp/User.h>
+#include <dcpp/UserMatchManager.h>
 
 #include <dwt/util/StringUtils.h>
 
@@ -81,12 +82,14 @@
 	}
 }
 
+void UserInfoBase::ignoreChat(bool ignore) {
+	UserMatchManager::getInstance()->ignoreChat(user, ignore);
+}
+
 const size_t maxChars = 100; // max chars per tooltip line
 
-tstring UserInfoBase::getTooltip(bool priv) const {
-	bool hubSet = priv;
-	if(!priv)
-		priv = FavoriteManager::getInstance()->isPrivate(user.hint);
+tstring UserInfoBase::getTooltip() const {
+	auto priv = keepHub();
 
 	tstring ret(WinUtil::getNicks(user, priv));
 	dwt::util::cutStr(ret, maxChars);
@@ -100,12 +103,12 @@
 		addLine(str(TF_("Hubs: %1%") % WinUtil::getHubNames(user, priv).first));
 
 	auto lock = ClientManager::getInstance()->lock();
-	OnlineUser* ou = ClientManager::getInstance()->findOnlineUser(user, priv);
+	auto ou = ClientManager::getInstance()->findOnlineUser(user, priv);
 	if(!ou)
 		return ret;
 	const Identity& id = ou->getIdentity();
 
-	auto addValue = [&id, &addLine](const tstring& descr, const string& value) {
+	auto addValue = [&addLine](const tstring& descr, const string& value) {
 		if(!value.empty())
 			addLine(str(TF_("%1%: %2%") % descr % Text::toT(value)));
 	};
@@ -138,12 +141,33 @@
 	return ret;
 }
 
-void UserInfoBase::UserTraits::parse(const UserInfoBase* ui) {
-	if(ui->getUser().user->isSet(User::NMDC))
-		adcOnly = false;
+bool UserInfoBase::keepHub() const {
+	return hubSet || FavoriteManager::getInstance()->isPrivate(user.hint);
+}
+
+UserTraits::UserTraits() :
+Flags(adcOnly | favOnly | nonFavOnly | chatIgnoredOnly | chatNotIgnoredOnly)
+{
+}
+
+void UserTraits::parse(const UserInfoBase* ui) {
+	if(ui->getUser().user->isSet(User::NMDC)) {
+		unsetFlag(adcOnly);
+	}
+
 	bool fav = FavoriteManager::getInstance()->isFavoriteUser(ui->getUser());
-	if(fav)
-		nonFavOnly = false;
-	else
-		favOnly = false;
+	if(fav) {
+		unsetFlag(nonFavOnly);
+	} else {
+		unsetFlag(favOnly);
+	}
+
+	auto priv = ui->keepHub();
+	auto lock = ClientManager::getInstance()->lock();
+	auto ou = ClientManager::getInstance()->findOnlineUser(ui->getUser(), priv);
+	if(ou && ou->getIdentity().noChat()) {
+		unsetFlag(chatNotIgnoredOnly);
+	} else {
+		unsetFlag(chatIgnoredOnly);
+	}
 }

=== modified file 'win32/UserInfoBase.h'
--- win32/UserInfoBase.h	2011-10-15 22:58:51 +0000
+++ win32/UserInfoBase.h	2011-12-10 18:51:47 +0000
@@ -22,6 +22,7 @@
 #include <boost/range/algorithm/for_each.hpp>
 
 #include <dcpp/forward.h>
+#include <dcpp/Flags.h>
 #include <dcpp/Text.h>
 #include <dcpp/User.h>
 
@@ -34,7 +35,7 @@
 
 class UserInfoBase {
 public:
-	UserInfoBase(const HintedUser& u) : user(u) { }
+	UserInfoBase(const HintedUser& u, bool hubSet = false) : user(u), hubSet(hubSet) { }
 
 	virtual void getList();
 	virtual void browseList();
@@ -44,23 +45,34 @@
 	virtual void addFav();
 	virtual void removeFromQueue();
 	virtual void connectFav(TabViewPtr);
+	virtual void ignoreChat(bool ignore);
 
-	tstring getTooltip(bool priv) const;
+	tstring getTooltip() const;
 
 	const HintedUser& getUser() const { return user; }
-
-	struct UserTraits {
-		UserTraits() : adcOnly(true), favOnly(true), nonFavOnly(true) { }
-
-		void parse(const UserInfoBase* ui);
-
-		bool adcOnly;
-		bool favOnly;
-		bool nonFavOnly;
-	};
+	bool keepHub() const;
 
 protected:
 	HintedUser user;
+
+private:
+	bool hubSet; // always respect the user's hub hint
+};
+
+struct UserTraits : Flags {
+	enum {
+		adcOnly = 1 << 1,
+		favOnly = 1 << 2,
+		nonFavOnly = 1 << 3,
+		chatIgnoredOnly = 1 << 4,
+		chatNotIgnoredOnly = 1 << 5
+	};
+
+	UserMatchPropsPtr match;
+
+	UserTraits();
+
+	void parse(const UserInfoBase* ui);
 };
 
 template<typename T>
@@ -118,33 +130,42 @@
 	void handleConnectFav(TabViewPtr parent) {
 		handleUserFunction([&](UserInfoBase* u) { u->connectFav(parent); });
 	}
+	void handleIgnoreChat(bool ignore) {
+		handleUserFunction([ignore](UserInfoBase* u) { u->ignoreChat(ignore); });
+	}
 
 	void appendUserItems(TabViewPtr parent, dwt::MenuPtr menu, bool defaultIsGetList = true, bool includeSendPM = true) {
 		auto users = t().selectedUsersImpl();
 		if(users.empty())
 			return;
 
-		UserInfoBase::UserTraits traits;
+		UserTraits traits;
 		for_each(users, [&](const UserInfoBase* u) { traits.parse(u); });
 
 		menu->appendItem(T_("&Get file list"), [this] { this->t().handleGetList(); }, dwt::IconPtr(), true, defaultIsGetList);
-		if(traits.adcOnly)
+		if(traits.isSet(UserTraits::adcOnly))
 			menu->appendItem(T_("&Browse file list"), [this] { this->t().handleBrowseList(); });
 		menu->appendItem(T_("&Match queue"), [this] { this->t().handleMatchQueue(); });
 		if(includeSendPM)
-			menu->appendItem(T_("&Send private message"), [=] { this->t().handlePrivateMessage(parent); }, dwt::IconPtr(), true, !defaultIsGetList);
-		if(!traits.favOnly)
+			menu->appendItem(T_("&Send private message"), [this, parent] { this->t().handlePrivateMessage(parent); }, dwt::IconPtr(), true, !defaultIsGetList);
+		if(!traits.isSet(UserTraits::favOnly))
 			menu->appendItem(T_("Add To &Favorites"), [this] { this->t().handleAddFavorite(); }, WinUtil::menuIcon(IDI_FAVORITE_USER_ON));
 		menu->appendItem(T_("Grant &extra slot"), [this] { this->t().handleGrantSlot(); });
-		if(!traits.nonFavOnly)
-			menu->appendItem(T_("Connect to hub"), [=] { this->t().handleConnectFav(parent); }, WinUtil::menuIcon(IDI_HUB));
+		if(!traits.isSet(UserTraits::nonFavOnly))
+			menu->appendItem(T_("Connect to hub"), [this, parent] { this->t().handleConnectFav(parent); }, WinUtil::menuIcon(IDI_HUB));
 		menu->appendSeparator();
 		menu->appendItem(T_("Remove user from queue"), [this] { this->t().handleRemoveFromQueue(); });
+
+		menu->appendSeparator();
+		if(!traits.isSet(UserTraits::chatIgnoredOnly))
+			menu->appendItem(T_("Ignore chat"), [this] { this->t().handleIgnoreChat(true); });
+		if(!traits.isSet(UserTraits::chatNotIgnoredOnly))
+			menu->appendItem(T_("Un-ignore chat"), [this] { this->t().handleIgnoreChat(false); });
 	}
 
 	template<typename TableType>
-	void prepareUserList(TableType* table, bool priv = false) {
-		table->setTooltips([table, priv](int i) -> tstring { return table->getData(i)->getTooltip(priv); });
+	void prepareUserList(TableType* table) {
+		table->setTooltips([table](int i) -> tstring { return table->getData(i)->getTooltip(); });
 	}
 };
 

=== modified file 'win32/UserMatchPage.cpp'
--- win32/UserMatchPage.cpp	2011-12-03 21:53:57 +0000
+++ win32/UserMatchPage.cpp	2011-12-10 18:51:47 +0000
@@ -145,6 +145,10 @@
 	dirty = true;
 }
 
+void UserMatchPage::updateStyles() {
+	static_cast<SettingsDialog*>(getRoot())->getPage<StylesPage>()->updateUserMatches(list);
+}
+
 void UserMatchPage::handleDoubleClick() {
 	if(table->hasSelected()) {
 		handleEditClicked();
@@ -258,7 +262,3 @@
 void UserMatchPage::addEntry(const UserMatch& matcher, int index) {
 	table->insert(TStringList(1, Text::toT(matcher.name)), 0, index);
 }
-
-void UserMatchPage::updateStyles() {
-	static_cast<SettingsDialog*>(getRoot())->getPage<StylesPage>()->updateUserMatches(list);
-}

=== modified file 'win32/UserMatchPage.h'
--- win32/UserMatchPage.h	2011-12-03 21:53:57 +0000
+++ win32/UserMatchPage.h	2011-12-10 18:51:47 +0000
@@ -33,6 +33,7 @@
 	virtual void write();
 
 	void setDirty();
+	void updateStyles();
 
 private:
 	TablePtr table;
@@ -52,7 +53,6 @@
 	void handleRemoveClicked();
 
 	void addEntry(const UserMatch& matcher, int index = -1);
-	void updateStyles();
 };
 
 #endif

=== modified file 'win32/WinUtil.cpp'
--- win32/WinUtil.cpp	2011-12-03 21:53:57 +0000
+++ win32/WinUtil.cpp	2011-12-10 18:51:47 +0000
@@ -412,7 +412,7 @@
 void WinUtil::updateUserMatchFonts() {
 	userMatchFonts.clear();
 
-	auto list = UserMatchManager::getInstance()->getList();
+	const auto& list = UserMatchManager::getInstance()->getList();
 	for(auto i = list.cbegin(), iend = list.cend(); i != iend; ++i) {
 		if(!i->props->font.empty()) {
 			LOGFONT lf;