------------------------------------------------------------ revno: 2333 committer: poy <p...@123gen.com> branch nick: trunk timestamp: Wed 2010-12-08 17:54:29 +0100 message: Add user information tooltips modified: changelog.txt dcpp/ClientManager.cpp dcpp/ClientManager.h dcpp/User.cpp dcpp/User.h dcpp/Util.cpp dcpp/Util.h dwt/include/dwt/util/StringUtils.h dwt/include/dwt/widgets/Table.h dwt/src/util/StringUtils.cpp dwt/src/widgets/TabView.cpp dwt/src/widgets/Table.cpp win32/HubFrame.cpp win32/TransferView.cpp win32/UserInfoBase.cpp win32/UserInfoBase.h win32/UsersFrame.cpp win32/WinUtil.h
-- 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 'changelog.txt' --- changelog.txt 2010-12-05 18:59:52 +0000 +++ changelog.txt 2010-12-08 16:54:29 +0000 @@ -51,6 +51,7 @@ * [L#534242] Better looking settings dialog (fleetcommand, poy) * Allow regular expressions in ADL searches (poy) * [L#395464] [ADC] Send "000" as the STA success code +* Add user information tooltips (poy) -- 0.770 2010-07-05 -- * [L#550300] Catch more potential file corruptions (thanks bigmuscle) === modified file 'dcpp/ClientManager.cpp' --- dcpp/ClientManager.cpp 2010-08-27 13:47:33 +0000 +++ dcpp/ClientManager.cpp 2010-12-08 16:54:29 +0000 @@ -324,7 +324,7 @@ } } -OnlineUser* ClientManager::findOnlineUser_hint(const CID& cid, const string& hintUrl, OnlinePair& p) throw() { +OnlineUser* ClientManager::findOnlineUser_hint(const CID& cid, const string& hintUrl, OnlinePair& p) { p = onlineUsers.equal_range(cid); if(p.first == p.second) // no user found with the given CID. return 0; @@ -341,7 +341,11 @@ return 0; } -OnlineUser* ClientManager::findOnlineUser(const CID& cid, const string& hintUrl, bool priv) throw() { +OnlineUser* ClientManager::findOnlineUser(const HintedUser& user, bool priv) { + return findOnlineUser(user.user->getCID(), user.hint, priv); +} + +OnlineUser* ClientManager::findOnlineUser(const CID& cid, const string& hintUrl, bool priv) { OnlinePair p; OnlineUser* u = findOnlineUser_hint(cid, hintUrl, p); if(u) // found an exact match (CID + hint). @@ -362,7 +366,7 @@ bool priv = FavoriteManager::getInstance()->isPrivate(user.hint); Lock l(cs); - OnlineUser* u = findOnlineUser(user.user->getCID(), user.hint, priv); + OnlineUser* u = findOnlineUser(user, priv); if(u) { u->getClient().connect(*u, token); @@ -373,7 +377,7 @@ bool priv = FavoriteManager::getInstance()->isPrivate(user.hint); Lock l(cs); - OnlineUser* u = findOnlineUser(user.user->getCID(), user.hint, priv); + OnlineUser* u = findOnlineUser(user, priv); if(u) { u->getClient().privateMessage(*u, msg, thirdPerson); === modified file 'dcpp/ClientManager.h' --- dcpp/ClientManager.h 2010-08-27 13:47:33 +0000 +++ dcpp/ClientManager.h 2010-12-08 16:54:29 +0000 @@ -73,7 +73,8 @@ * @param priv discard any user that doesn't match the hint. * @return OnlineUser* found by CID and hint; might be only by CID if priv is false. */ - OnlineUser* findOnlineUser(const CID& cid, const string& hintUrl, bool priv) throw(); + OnlineUser* findOnlineUser(const HintedUser& user, bool priv); + OnlineUser* findOnlineUser(const CID& cid, const string& hintUrl, bool priv); UserPtr findUser(const string& aNick, const string& aHubUrl) const throw() { return findUser(makeCid(aNick, aHubUrl)); } UserPtr findUser(const CID& cid) const throw(); @@ -156,7 +157,7 @@ void updateNick(const OnlineUser& user) throw(); /// @return OnlineUser* found by CID and hint; discard any user that doesn't match the hint. - OnlineUser* findOnlineUser_hint(const CID& cid, const string& hintUrl) throw() { + OnlineUser* findOnlineUser_hint(const CID& cid, const string& hintUrl) { OnlinePair p; return findOnlineUser_hint(cid, hintUrl, p); } @@ -164,7 +165,7 @@ * @param p OnlinePair of all the users found by CID, even those who don't match the hint. * @return OnlineUser* found by CID and hint; discard any user that doesn't match the hint. */ - OnlineUser* findOnlineUser_hint(const CID& cid, const string& hintUrl, OnlinePair& p) throw(); + OnlineUser* findOnlineUser_hint(const CID& cid, const string& hintUrl, OnlinePair& p); string getUsersFile() const { return Util::getPath(Util::PATH_USER_LOCAL) + "Users.xml"; } === modified file 'dcpp/User.cpp' --- dcpp/User.cpp 2010-02-11 21:44:13 +0000 +++ dcpp/User.cpp 2010-12-08 16:54:29 +0000 @@ -90,6 +90,10 @@ get("HR") + "/" + get("HO") + ",S:" + get("SL") + ">"; } +string Identity::getCountry() const { + return Util::getIpCountry(getIp()); +} + string Identity::get(const char* name) const { FastLock l(cs); InfMap::const_iterator i = info.find(*(short*)name); === modified file 'dcpp/User.h' --- dcpp/User.h 2010-12-03 17:26:12 +0000 +++ dcpp/User.h 2010-12-08 16:54:29 +0000 @@ -139,6 +139,7 @@ void setBot(bool bot) { set("BO", bot ? "1" : Util::emptyString); } void setHidden(bool hidden) { set("HI", hidden ? "1" : Util::emptyString); } string getTag() const; + string getCountry() const; bool supports(const string& name) const; bool isHub() const { return isClientType(CT_HUB) || isSet("HU"); } bool isOp() const { return isClientType(CT_OP) || isClientType(CT_SU) || isClientType(CT_OWNER) || isSet("OP"); } === modified file 'dcpp/Util.cpp' --- dcpp/Util.cpp 2010-12-01 16:03:18 +0000 +++ dcpp/Util.cpp 2010-12-08 16:54:29 +0000 @@ -899,9 +899,10 @@ for exemple: it returns "PT", whitch standards for "Portugal" more info: http://www.maxmind.com/app/csv */ -string Util::getIpCountry (string IP) { - if (BOOLSETTING(GET_USER_COUNTRY)) { - dcassert(count(IP.begin(), IP.end(), '.') == 3); +string Util::getIpCountry(const string& IP) { + if(BOOLSETTING(GET_USER_COUNTRY)) { + if(count(IP.begin(), IP.end(), '.') != 3) + return Util::emptyString; //e.g IP 23.24.25.26 : w=23, x=24, y=25, z=26 string::size_type a = IP.find('.'); @@ -920,7 +921,7 @@ } } - return Util::emptyString; //if doesn't returned anything already, something is wrong... + return Util::emptyString; } string Util::getTimeString() { === modified file 'dcpp/Util.h' --- dcpp/Util.h 2010-12-01 16:03:18 +0000 +++ dcpp/Util.h 2010-12-08 16:54:29 +0000 @@ -412,7 +412,7 @@ static int stricmp(const wstring& a, const wstring& b) { return stricmp(a.c_str(), b.c_str()); } static int strnicmp(const wstring& a, const wstring& b, size_t n) { return strnicmp(a.c_str(), b.c_str(), n); } - static string getIpCountry (string IP); + static string getIpCountry(const string& IP); static bool getAway() { return away; } static void setAway(bool aAway) { === modified file 'dwt/include/dwt/util/StringUtils.h' --- dwt/include/dwt/util/StringUtils.h 2010-02-11 21:44:13 +0000 +++ dwt/include/dwt/util/StringUtils.h 2010-12-08 16:54:29 +0000 @@ -38,6 +38,8 @@ tstring escapeMenu(tstring str); +void cutStr(tstring& str, size_t n); + } } #endif /*STRINGUTILS_H_*/ === modified file 'dwt/include/dwt/widgets/Table.h' --- dwt/include/dwt/widgets/Table.h 2010-07-10 14:36:48 +0000 +++ dwt/include/dwt/widgets/Table.h 2010-12-08 16:54:29 +0000 @@ -79,18 +79,26 @@ { typedef CommonControl BaseType; - struct HeaderDispatcher { - typedef std::function<void (int)> F; - - HeaderDispatcher(const F& f_) : f(f_) { } - - bool operator()(const MSG& msg, LRESULT& ret) const { - LPNMLISTVIEW p = (LPNMLISTVIEW) msg.lParam; - f(p->iSubItem); - return true; - } - - F f; + struct HeaderDispatcher : Dispatchers::Base<void (int)> { + typedef Dispatchers::Base<void (int)> BaseType; + HeaderDispatcher(const F& f_) : BaseType(f_) { } + + bool operator()(const MSG& msg, LRESULT& ret) const { + f(reinterpret_cast<LPNMLISTVIEW>(msg.lParam)->iSubItem); + return true; + } + }; + + struct TooltipDispatcher : Dispatchers::Base<tstring (int)> { + typedef Dispatchers::Base<tstring (int)> BaseType; + TooltipDispatcher(const F& f_) : BaseType(f_) { } + + bool operator()(const MSG& msg, LRESULT& ret) const { + NMLVGETINFOTIP& tip = *reinterpret_cast<LPNMLVGETINFOTIP>(msg.lParam); + tstring text(f(tip.iItem)); + _tcscpy_s(tip.pszText, tip.cchTextMax, text.c_str()); + return true; + } }; // Need to be friend to access private data... @@ -353,6 +361,8 @@ */ void setSingleRowSelection( bool value = true ); + void setTooltips(const TooltipDispatcher::F& f); + /// Adds (or removes) grid lines. /** A grid with grid lines will have lines surrounding every cell in it. <br> * value defines if we're supposed to add grid lines or remove them. <br> === modified file 'dwt/src/util/StringUtils.cpp' --- dwt/src/util/StringUtils.cpp 2010-02-11 21:44:13 +0000 +++ dwt/src/util/StringUtils.cpp 2010-12-08 16:54:29 +0000 @@ -43,4 +43,9 @@ return str; } +void cutStr(tstring& str, size_t n) { + if(str.size() > n) + str = str.substr(0, n - 3) + _T("..."); +} + } } === modified file 'dwt/src/widgets/TabView.cpp' --- dwt/src/widgets/TabView.cpp 2010-10-28 22:43:23 +0000 +++ dwt/src/widgets/TabView.cpp 2010-12-08 16:54:29 +0000 @@ -387,8 +387,8 @@ } tstring TabView::formatTitle(tstring title) { - if(widthConfig && title.length() > widthConfig) - title = title.substr(0, widthConfig - 3) + _T("..."); + if(widthConfig) + util::cutStr(title, widthConfig); return util::escapeMenu(title); } === modified file 'dwt/src/widgets/Table.cpp' --- dwt/src/widgets/Table.cpp 2010-07-10 14:36:48 +0000 +++ dwt/src/widgets/Table.cpp 2010-12-08 16:54:29 +0000 @@ -149,8 +149,8 @@ ListView_SetItemState(handle(), item, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); } -void Table::selectAll() { - for(size_t i = 0, n = size(); i < n; ++i) +void Table::selectAll() { + for(size_t i = 0, n = size(); i < n; ++i) setSelected(i); } @@ -554,4 +554,9 @@ return ListView_HitTest(handle(), &lvi); } +void Table::setTooltips(const TooltipDispatcher::F& f) { + addRemoveTableExtendedStyle(LVS_EX_INFOTIP, true); + addCallback(Message(WM_NOTIFY, LVN_GETINFOTIP), TooltipDispatcher(f)); +} + } === modified file 'win32/HubFrame.cpp' --- win32/HubFrame.cpp 2010-12-03 18:27:30 +0000 +++ win32/HubFrame.cpp 2010-12-08 16:54:29 +0000 @@ -162,6 +162,8 @@ users->onKeyDown(std::bind(&HubFrame::handleUsersKeyDown, this, _1)); users->onContextMenu(std::bind(&HubFrame::handleUsersContextMenu, this, _1)); + prepareUserList(users, true); + TextBox::Seed cs = WinUtil::Seeds::textBox; cs.style |= ES_AUTOHSCROLL; filter = userGrid->addChild(cs); @@ -639,10 +641,8 @@ columns[COLUMN_DESCRIPTION] = Text::toT(identity.getDescription()); columns[COLUMN_TAG] = Text::toT(identity.getTag()); columns[COLUMN_CONNECTION] = Text::toT(identity.getConnection()); - string ip = identity.getIp(); - string country = ip.empty()?Util::emptyString:Util::getIpCountry(ip); - columns[COLUMN_IP] = Text::toT(ip); - columns[COLUMN_COUNTRY] = Text::toT(country); + columns[COLUMN_IP] = Text::toT(identity.getIp()); + columns[COLUMN_COUNTRY] = Text::toT(identity.getCountry()); columns[COLUMN_EMAIL] = Text::toT(identity.getEmail()); columns[COLUMN_CID] = Text::toT(identity.getUser()->getCID().toBase32()); === modified file 'win32/TransferView.cpp' --- win32/TransferView.cpp 2010-12-03 13:59:16 +0000 +++ win32/TransferView.cpp 2010-12-08 16:54:29 +0000 @@ -125,6 +125,8 @@ connections->onKeyDown(std::bind(&TransferView::handleKeyDown, this, _1)); connections->onDblClicked(std::bind(&TransferView::handleDblClicked, this)); connections->onRaw(std::bind(&TransferView::handleCustomDraw, this, _1, _2), dwt::Message(WM_NOTIFY, NM_CUSTOMDRAW)); + + prepareUserList(connections); } { === modified file 'win32/UserInfoBase.cpp' --- win32/UserInfoBase.cpp 2010-02-11 21:44:13 +0000 +++ win32/UserInfoBase.cpp 2010-12-08 16:54:29 +0000 @@ -20,12 +20,15 @@ #include "UserInfoBase.h" +#include <dcpp/ClientManager.h> +#include <dcpp/FavoriteManager.h> +#include <dcpp/LogManager.h> #include <dcpp/QueueManager.h> -#include <dcpp/LogManager.h> -#include <dcpp/FavoriteManager.h> #include <dcpp/UploadManager.h> #include <dcpp/User.h> +#include <dwt/util/StringUtils.h> + #include "PrivateFrame.h" #include "HubFrame.h" @@ -78,6 +81,57 @@ } } +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 ret(WinUtil::getNicks(user, priv)); + dwt::util::cutStr(ret, maxChars); + + auto addLine = [&ret](tstring line) { + dwt::util::cutStr(line, maxChars); + ret += _T("\r\n") + line; + }; + + if(!hubSet) + addLine(str(TF_("Hubs: %1%") % WinUtil::getHubNames(user, priv).first)); + + OnlineUser* ou = ClientManager::getInstance()->findOnlineUser(user, priv); + if(!ou) + return ret; + const Identity& id = ou->getIdentity(); + + auto getField = [&id](const char* code) -> tstring { + string field = id.get(code); + return field.empty() ? _T("?") : Text::toT(field); + }; + + if(id.isHidden()) + addLine(T_("Hidden user")); + if(id.isBot()) + addLine(T_("Bot")); + if(id.isOp()) + addLine(T_("Hub operator")); + if(id.isAway()) + addLine(T_("In away mode")); + + addLine(str(TF_("Shared: %1%") % Text::toT(Util::formatBytes(id.getBytesShared())))); + addLine(str(TF_("Description: %1%") % Text::toT(id.getDescription()))); + addLine(str(TF_("Tag: %1%") % Text::toT(id.getTag()))); + addLine(str(TF_("Connection: %1%") % Text::toT(id.getConnection()))); + addLine(str(TF_("IP: %1%") % getField("I4"))); + const string country = id.getCountry(); + if(!country.empty()) + addLine(str(TF_("Country: %1%") % Text::toT(country))); + addLine(str(TF_("E-mail: %1%") % Text::toT(id.getEmail()))); + addLine(str(TF_("Slots: %1%/%2%") % getField("FS") % getField("SL"))); + + return ret; +} + void UserInfoBase::UserTraits::parse(UserInfoBase* ui) { if(ui->getUser().user->isSet(User::NMDC)) adcOnly = false; === modified file 'win32/UserInfoBase.h' --- win32/UserInfoBase.h 2010-07-10 14:36:48 +0000 +++ win32/UserInfoBase.h 2010-12-08 16:54:29 +0000 @@ -41,6 +41,8 @@ void removeFromQueue(); void connectFav(dwt::TabViewPtr); + tstring getTooltip(bool priv) const; + const HintedUser& getUser() const { return user; } struct UserTraits { @@ -140,6 +142,11 @@ menu->appendSeparator(); menu->appendItem(T_("Remove user from queue"), std::bind(&ThisType::handleRemoveFromQueue, this)); } + + template<typename TableType> + void prepareUserList(TableType* table, bool priv = false) { + table->setTooltips([table, priv](int i) -> tstring { return table->getData(i)->getTooltip(priv); }); + } }; #endif /*USERINFOBASE_H_*/ === modified file 'win32/UsersFrame.cpp' --- win32/UsersFrame.cpp 2010-11-30 18:21:53 +0000 +++ win32/UsersFrame.cpp 2010-12-08 16:54:29 +0000 @@ -55,6 +55,8 @@ users->onKeyDown(std::bind(&UsersFrame::handleKeyDown, this, _1)); users->onRaw(std::bind(&UsersFrame::handleItemChanged, this, _2), dwt::Message(WM_NOTIFY, LVN_ITEMCHANGED)); users->onContextMenu(std::bind(&UsersFrame::handleContextMenu, this, _1)); + + prepareUserList(users); } { === modified file 'win32/WinUtil.h' --- win32/WinUtil.h 2010-11-24 22:14:02 +0000 +++ win32/WinUtil.h 2010-12-08 16:54:29 +0000 @@ -167,12 +167,14 @@ static tstring getNicks(const UserPtr& u, const string& hintUrl); static tstring getNicks(const CID& cid, const string& hintUrl, bool priv); static tstring getNicks(const HintedUser& user) { return getNicks(user.user->getCID(), user.hint); } + static tstring getNicks(const HintedUser& user, bool priv) { return getNicks(user.user->getCID(), user.hint, priv); } /** @return Pair of hubnames as a string and a bool representing the user's online status */ static pair<tstring, bool> getHubNames(const CID& cid, const string& hintUrl); static pair<tstring, bool> getHubNames(const UserPtr& u, const string& hintUrl); static pair<tstring, bool> getHubNames(const CID& cid, const string& hintUrl, bool priv); static pair<tstring, bool> getHubNames(const HintedUser& user) { return getHubNames(user.user->getCID(), user.hint); } + static pair<tstring, bool> getHubNames(const HintedUser& user, bool priv) { return getHubNames(user.user->getCID(), user.hint, priv); } static void reducePaths(string& message);
_______________________________________________ Mailing list: https://launchpad.net/~linuxdcpp-team Post to : linuxdcpp-team@lists.launchpad.net Unsubscribe : https://launchpad.net/~linuxdcpp-team More help : https://help.launchpad.net/ListHelp