Ignore List - Implementation Help

Problems compiling? Don't understand the source code? Don't know how to code your feature? Post here.

Moderator: Moderators

Locked
Gratch06
Posts: 141
Joined: 2003-05-25 01:48
Location: USA

Ignore List - Implementation Help

Post by Gratch06 » 2003-05-25 01:58

I know this is really not the best way to code things usually, but I want to create a global variable. Where would I stick the declaration for it? (Sorry, I'm still learning C++, and by no means an expert.)

The reason for this is that I want to add an ignore option for PM's, and I need to be able to both add to and remove names from that list, as well as keeping that list readily available in memory (rather than reading it from a file every time). Doing it smartly involving the proper scope is going to take a major reworking of a LOT of functions. I plan to create an array of string variables for the purpose of holding a list of names. I can do most of the code once I actually get the global variable. Any help(or other suggestions on how to do this a bit more wisely) would be MUCH appreciated.

Thanks,
Gratch06
Last edited by Gratch06 on 2003-05-28 21:48, edited 1 time in total.

Sedulus
Forum Moderator
Posts: 687
Joined: 2003-01-04 09:32
Contact:

Post by Sedulus » 2003-05-25 06:19

imho you should add the ignored-users to the Favorites.xml through HubManager

make a User::List& HubManager::getIgnoredUsers()
look at how the favorite users are implemented, and add a IgnorePM attribute
http://dc.selwerd.nl/hublist.xml.bz2
http://www.b.ali.btinternet.co.uk/DCPlusPlus/index.html (TheParanoidOne's DC++ Guide)
http://www.dslreports.com/faq/dc (BSOD2600's Direct Connect FAQ)

Gratch06
Posts: 141
Joined: 2003-05-25 01:48
Location: USA

Post by Gratch06 » 2003-05-28 21:48

OK, I've went in and looked at some of that code, still not sure exactly how you mean to implement. I'm still fairly new to messing with the DC++ source...I can make a function User::List& HubManager::getIgnoredUsers() like you reccommended, but I'm not quite sure how to go about the lists. Are you talking about adding a totally different listing, another frame similar to favorites users frame based off of the source for the favs, OR are you talking about adding in an extra parameter on favorite users...I'm kind of lost as to which implentation you're looking at. If it's something totally different, I'd by all means be glad to learn =).

Things I need to work the list as I see it:
1) ignore/unignore right click menus on userlist (addressed in another post already)
2) A place to stick the blocker (right now that is in PrivateFrame::gotMessage)
3) A readout somewhere that shows the list of ignored names (I figure I can steal the frame stuff from another frame like favorite users, but again, suggestions would be welcomed)
4) (This post) How to implement the list of names. I don't need IPs, anything like that, just going based exclusively on screennames.

- Gratch

Gratch06
Posts: 141
Joined: 2003-05-25 01:48
Location: USA

Post by Gratch06 » 2003-05-30 16:05

Here's the code I have done so far in my attempt to implement the ignore feature:

Added stringdefs, and those show up correctly.
resource.h
#define IDC_IGNORE 1099
#define IDC_UNIGNORE 1100


hubframe.cpp:
//handlers for the menus
userMenu.AppendMenu(MF_STRING, IDC_IGNORE, CSTRING(IGNORE_USER));
userMenu.AppendMenu(MF_STRING, IDC_UNIGNORE, CSTRING(UNIGNORE_USER));


LRESULT onIgnore(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
//insert code to add a user to the ignore list
}

LRESULT onUnignore(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
//insert code to remove a user from the ignore list
}

PrivateFrame.cpp
in PrivateFrame::gotMessage(/*insert args here*/){
//add code to check if the aUser->getNick() matches one on our list, if so, simply return to the main, skipping the rest of the function.
}


The actual implementation of the list has me stuck. I played with doing the array of strings (as I had first thought of), but that caused me some scoping issues.
User::List& HubManager::getIgnoredUsers()
This function would handle saving and retrieving from a file it appears after a closer look. That is definitely necessary, but I'm trying to get the actual implementation of the list down first, then will worry about saving and other necessary features.

Thanks for the help yet again!

- Gratch

sarf
Posts: 382
Joined: 2003-01-24 05:43
Location: Sweden
Contact:

Post by sarf » 2003-05-31 03:54

Hmm... well, here's how you do it :

Add "User::List ignoredUsers;" to the private part of the HubManager class.

Add this to the public part of the class:

Code: Select all

// This method is... well... unnecessary for most things 
// (except if some other class than HubManager has the responsability to save the ignored user list).
User::List& getIgnoredUsers() {
	return ignoredUsers;
}
void addIgnoredUser(User::Ptr userToIgnore) {
	// check to see that we haven't already ignored this fella
	User::Iter userIter = find(ignoredUsers.begin(), ignoredUsers.end(), userToIgnore);
	if(userIter == ignoredUsers.end()) {
		ignoredUsers.push_back(userToIgnore);
	}
}
void removeIgnoredUser(User::Ptr userToListenToAgain) {
	// get the "index" of the user to remove
	User::Iter userIter = find(ignoredUsers.begin(), ignoredUsers.end(), userToListenToAgain);
	// if there actually *is* such a user, let's remove him/her from the list
	if(userIter != ignoredUsers.end()) {
		ignoredUsers.erase(userIter);
	}
}
I hope this helps you out somewhat.

Sarf
---
Cut the conversation, just open your mouth

Gratch06
Posts: 141
Joined: 2003-05-25 01:48
Location: USA

Post by Gratch06 » 2003-06-01 02:12

OK, added all functions, implemented calls, etc.

Presumably, I should now be able to add users to the list and remove them from the list. Trying to get AT the userlist is a bit of a problem for me. I need to check received PM's to see if they are from a user on the ignore list, then ignore them if so. The place I am trying to implement the actual use of the ignore list is in PrivateFrame::gotMessage.
Code:
//need to call from an instance of Hubframe since variable isn't static.
User::Iter userIter = find((HubFrame::ignoredUsers).begin(), (HubFrame::ignoredUsers).end(), aUser);
if(userIter != (HubFrame::ignoredUsers).end()) return;

OR

//ignoredUsers is not defined, obviously.
User::Iter userIter = find(ignoredUsers.begin(), ignoredUsers.end(), aUser);
if(userIter != ignoredUsers.end()) return;

OR

//need to call from an instance of HubFrame since not static
User::List templist = HubFrame.getIgnoredUsers();
User::Iter userIter = find(templist.begin(), templist.end(), aUser);
if(userIter != templist.end()) return;
Those were my attempts to make it work, just missing something that should be right before my face... If there is a better place to put it than in the PrivateFrame::gotMessage (didn't see anything relating to it in HubFrame), please let me know.

I know this is really an elementary C++ question, but I'm still learning it here at college. Adding this feature in for someone else who has less of a clue than I do.

Thanks again,
- Gratch

sarf
Posts: 382
Joined: 2003-01-24 05:43
Location: Sweden
Contact:

Post by sarf » 2003-06-01 04:33

I'd recommend adding a method to HubManager and then calling that method from the gotMessage... and this is how you do it:

Code: Select all

// add this to HubManager...
bool isUserIgnored(User::Ptr userToCheck)
{
	return (find(ignoredUsers.begin(), ignoredUsers.end(), userToCheck) != ignoredUsers.end());
}

// add this code to your gotMessage 
	if(HubManager::getInstance()->isUserIgnored(aUser))
	{
		return;
	}
I hope this was the push in the right direction that you were looking for.

Sarf
---
The Bible contains six admonishments to homosexuals and three hundred sixty-two admonishments to heterosexuals. That doesn't mean that God doesn't love heterosexuals. It's just that they need more supervision.

Gratch06
Posts: 141
Joined: 2003-05-25 01:48
Location: USA

Post by Gratch06 » 2003-06-01 12:09

OK, got it all to compile, but I'm only suffering from one little problem...the list isn't actually ignoring people.
1) The list is disappearing before I can check it (out of scope)
2) The onIgnore/onUnignorearen't calling the addIgnoredUser/removeIgnoredUser functions properly
3) The list is not correctly being read from
4) The list is not correctly being written to

Code: Select all

LRESULT HubFrame::onIgnore(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
	int i = -1;
	while((i = ctrlUsers.GetNextItem(i, LVNI_SELECTED)) != -1) {
		HubManager::getInstance()->addIgnoredUser(((UserInfo*)ctrlUsers.GetItemData(i))->user);
	}
	return 0;
}

LRESULT HubFrame::onUnignore(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{ 
	int i = -1;
	while((i = ctrlUsers.GetNextItem(i, LVNI_SELECTED)) != -1) {
		HubManager::getInstance()->removeIgnoredUser(((UserInfo*)ctrlUsers.GetItemData(i))->user);
	}
	return 0;
}

As I have been working with the command line primarily in college courses, is there a similar "poor man's debugger" (like cout << randomdata;) available in Visual C++? It would just be a temporary debugging tool to see what values the list held when. I don't care WHERE it actually shows up, so long as it actually does (i.e. a dialogue box, the status bar, wherever).

All code has been implemented as written in above posts, with the addition of the code listed in this post.

Thanks for the help yet again guys...

- Gratch

sarf
Posts: 382
Joined: 2003-01-24 05:43
Location: Sweden
Contact:

Post by sarf » 2003-06-02 07:05

To get some debug output :

Add the following code right after the "addLine("*** " + WinUtil::commands + ", /join <hub-ip>, /clear, /ts, /showjoins, /close, /userlist, /connection, /favorite");" in HubFrame.cpp

Code: Select all

			} else if(Util::stricmp(s.c_str(), "showignored") == 0) {
				//User::List ignoredUserList = HubManager::getInstance()->getIgnoredUsers();
				User::List ignoredUserList;
				if(ignoredUserList.size() > 0)
				{
					addLine("--- Currently ignoring the following users:");
					for(User::Iter userIter = ignoredUserList.begin() ; userIter != ignoredUserList.end() ; userIter++)
					{
						addLine((*userIter)->getNick());
					}
					addLine("--- User ignore list ENDS");
				}
				else
				{
					addLine("--- Currently not ignoring anyone");
				}
			} else if(Util::stricmp(s.c_str(), "ignore") == 0) {
				User::Ptr user = ClientManager::getInstance()->getUser(param);
				if(HubManager::getInstance()->isUserIgnored(user))
				{
					addLine("Removing " + user->getNick() + " from the ignored list.");
					HubManager::getInstance()->removeIgnoredUser(user);
				} else {
					addLine("Adding " + user->getNick() + " to the ignored list.");
					HubManager::getInstance()->addIgnoredUser(user);
				}
This will allow you to use /showignored and /ignore <nick> as commands, and may help you with the debug.

Sarf
---
So long, and thanks for all the fish.

Gratch06
Posts: 141
Joined: 2003-05-25 01:48
Location: USA

Post by Gratch06 » 2003-06-02 18:11

OK, gone back through and debugged somewhat, here's where I'm at...
[15:16] --- Currently not ignoring anyone <<< fresh, before doing anything
[15:16] Adding [10mbt]Gratch06 to the ignored list. <<< /ignore [10mbt]Gratch06
[15:17] --- Currently not ignoring anyone <<< after /ignore
Appears to be one of two things:
1) List is going out of scope. I don't know how GetInstance works with scoping really...It just seems that the list is vanishing before I can do anything with it.
2) The list isn't actually getting added to.

I would keep on beating on this some more, but I think this might be tied to something totally different...After accessing the ignore list through /ignore, then quitting the program, I get this error:
The instruction at "0x004ce87b" referenced memory at "0x409942bf". The memory could not be "written".
Memory error, but why it would show up when the program is closing, and not while writing to or reading from the List? Is there something possibly going on with the Iterators that is causing this memory error? (they aren't my strong point, only touched on them briefly in class a few weeks back).

- Gratch

sarf
Posts: 382
Joined: 2003-01-24 05:43
Location: Sweden
Contact:

Post by sarf » 2003-06-03 10:31

I found one problem with my code (stupid me forgot to remove a comment when I got the code out of Visual Studio) :oops: :

Code: Select all

        //User::List ignoredUserList = HubManager::getInstance()->getIgnoredUsers(); 
        User::List ignoredUserList;
should be

Code: Select all

        User::List ignoredUserList = HubManager::getInstance()->getIgnoredUsers();
The memory access error might be due to some function accessing the ignoredUsers after it is deleted, but... I don't know.

Sarf
---
Those who can, do; those who can't, simulate.

Gratch06
Posts: 141
Joined: 2003-05-25 01:48
Location: USA

Post by Gratch06 » 2003-06-03 14:12

Doh...I should have looked closer, would have seen that one. *makes note to examine source he's given a lot more closely next time*

Code: Select all

User::List ignoredUserList = HubManager::getInstance()->getIgnoredUsers();
Adjusting that line yields a "memory at ...... cannot be 'written'" error.
I've tested it out and declaring the variable is clean, calling the function is clean, but assigning the list to ignoredUserList causes the issues. Is a list by default not writeable? What about the assignment operator for the list...what kind of overloading is there with that (couldn't find that in the source anywhere)

Replacing all instances of ignoredUserList with (HubManager::getInstance()->getIgnoredUsers()) yields:

Code: Select all

else if(Util::stricmp(s.c_str(), "showignored") == 0) {
                    if((HubManager::getInstance()->getIgnoredUsers()).size() > 0){ 
                        addLine("--- Currently ignoring the following users:"); 
                        for(User::Iter userIter = (HubManager::getInstance()->getIgnoredUsers()).begin() ; userIter != (HubManager::getInstance()->getIgnoredUsers()).end() ; userIter++) 
						{ 
                            addLine((*userIter)->getNick()); 
						} 
                        addLine("--- User ignore list ENDS"); 
					} 
                    else
					{ 
						addLine("--- Currently not ignoring anyone"); 
					}

				}
This code segment yields a memory could not be READ error. I never did like memory errors, but this one is throwing me for a loop.

Now the important information that is going to come into play next:
Compiled using MS VC++ 6
Based off of v. .181 source code (due to other non related modifications to the source)
Windows XP Professional

Sorry to keep being a bother on this one....If it would be easier to discuss in a chat rather than a forum, just let me know...would be glad to swap IM's or meet you in a hub of your choosing.

Thanks for all the help!

- Gratch

sarf
Posts: 382
Joined: 2003-01-24 05:43
Location: Sweden
Contact:

Post by sarf » 2003-06-04 09:56

Hmm... well, it seems like you can't make a direct reference to another list. Try using User::List* and returning a pointer or something like that - it might work. You can also copy the list (but that means some memory management).

Sarf
---
The sharks can smell blood in the water - make sure that its theirs.

Gratch06
Posts: 141
Joined: 2003-05-25 01:48
Location: USA

Post by Gratch06 » 2003-06-09 02:20

After toying with an implementation using User::List* and another using a stack and getting very similar errors, I decided to just to give up on implementing this on the .181 codebase and start bumping the other source updates into .251. I haven't actually hit implementing this yet, so I can't confirm it works. I'll get back to you with whether any of these methods works using the most recent source or not.

Many thanks!
- Gratch

Locked