//
// Updates a document's properties.
//
void IndexTree::updateDocumentInfo(unsigned int docId, const DocumentInfo &docInfo)
{
	if (docId == 0)
	{
		return;
	}

	// Go through the list of indexed documents
	TreeModel::Children children = m_refStore->children();
	for (TreeModel::Children::iterator iter = children.begin(); iter != children.end(); ++iter)
	{
		TreeModel::Row row = *iter;

		if (docId == row[m_indexColumns.m_id])
		{
			row[m_indexColumns.m_text] = to_utf8(docInfo.getTitle());
			row[m_indexColumns.m_type] = to_utf8(docInfo.getType());
			row[m_indexColumns.m_language] = to_utf8(docInfo.getLanguage());
			row[m_indexColumns.m_timestamp] = to_utf8(docInfo.getTimestamp());
#ifdef DEBUG
			cout << "IndexTree::updateDocumentInfo: language now " << docInfo.getLanguage() << endl;
#endif
			break;
		}
	}
}
//
// Deletes the current selection.
//
bool IndexTree::deleteSelection(void)
{
	bool empty = false;

	// Go through selected items
	list<TreeModel::Path> selectedItems = get_selection()->get_selected_rows();
	list<TreeModel::Path>::iterator itemPath = selectedItems.begin();
	while (itemPath != selectedItems.end())
	{
		TreeModel::iterator iter = m_refStore->get_iter(*itemPath);
		TreeModel::Row row = *iter;

		// Unselect and erase
		get_selection()->unselect(iter);
		m_refStore->erase(row);

		selectedItems = get_selection()->get_selected_rows();
		itemPath = selectedItems.begin();
	}
#ifdef DEBUG
	cout << "IndexTree::deleteSelection: deleted " << selectedItems.size() << " documents" << endl;
#endif

	TreeModel::Children children = m_refStore->children();
	if (children.empty() == true)
	{
		// The index tree is now empty
		m_listingIndex = false;
		empty = true;
	}

	return empty;
}
void EnginesTree::save(void)
{
	std::map<string, bool> &channels = m_settings.getSearchEnginesChannels();

	TreeModel::Children children = m_refStore->children();
	for (TreeModel::Children::iterator iter = children.begin(); iter != children.end(); ++iter)
	{
		TreeModel::Row row = *iter;

		if (row[m_enginesColumns.m_type] == EnginesModelColumns::ENGINE_FOLDER)
		{
			ustring channelName(row[m_enginesColumns.m_name]);
			TreeModel::Path channelPath = m_refStore->get_path(iter);

			std::map<string, bool>::iterator channelIter = channels.find(from_utf8(channelName));
			if (channelIter != channels.end())
			{
#ifdef DEBUG
				cout << "EnginesTree::save: " << channelName << " is " << row_expanded(channelPath) << endl;
#endif
				channelIter->second = row_expanded(channelPath);
			}
		}
	}
}
//
// Clears the tree.
//
void ResultsTree::clear(void)
{
	// Unselect results
	get_selection()->unselect_all();

	// Remove existing rows in the tree
	TreeModel::Children children = m_refStore->children();
	if (children.empty() == false)
	{
		// Clear the groups map
		m_resultsGroups.clear();

		TreeModel::Children::iterator iter = children.begin();
		while (iter != children.end())
		{
			// Erase this row
			m_refStore->erase(*iter);

			// Get the new first row
			children = m_refStore->children();
			iter = children.begin();
		}
		m_refStore->clear();

		// Clear the extract field
		RefPtr<TextBuffer> refBuffer = m_extractTextview->get_buffer();
		refBuffer->set_text("");
		m_extractTextview->set_editable(false);
		m_extractTextview->set_cursor_visible(false);

		onSelectionChanged();
	}
}
//
// Deletes the current selection.
//
bool ResultsTree::deleteSelection(void)
{
	bool empty = false;

	// Go through selected items
	list<TreeModel::Path> selectedItems = get_selection()->get_selected_rows();
	list<TreeModel::Path>::iterator itemPath = selectedItems.begin();
	while (itemPath != selectedItems.end())
	{
		TreeModel::iterator iter = m_refStore->get_iter(*itemPath);
		TreeModel::Row row = *iter;
		TreeModel::iterator parentIter;
		bool updateParent = false;

		// This could be a group that's in the map and should be removed first
		if (row[m_resultsColumns.m_type] != ResultsModelColumns::RESULT_TITLE)
		{
			string groupName = from_utf8(row[m_resultsColumns.m_text]);
			std::map<string, TreeModel::iterator>::iterator mapIter = m_resultsGroups.find(groupName);
			if (mapIter != m_resultsGroups.end())
			{
				m_resultsGroups.erase(mapIter);
#ifdef DEBUG
				cout << "ResultsTree::deleteResults: erased group " << groupName << endl;
#endif
			}
		}
		else
		{
			// This item is a result
			parentIter = row.parent();
			updateParent = true;
		}

		// Unselect and erase
		get_selection()->unselect(iter);
		m_refStore->erase(row);

		// Update group ?
		if (updateParent == true)
		{
			// Update the group this result belongs to
			updateGroup(parentIter);
		}

		selectedItems = get_selection()->get_selected_rows();
		itemPath = selectedItems.begin();
	}

	TreeModel::Children children = m_refStore->children();
	empty = children.empty();

	refresh();

	return empty;
}
void WelcomeWindow::PlayerLeftEvent()
{
	CallbackChange *change = m_callbackHandler->PopCallbackChange();
	if(change->m_type == CALLBACK_ERROR)
	{
		cerr << "ERROR: Got an error in callback processing" << endl;
		return;
	}
	MainLobbyCallbackChange *lobbyChange = (MainLobbyCallbackChange*)change;
	TreeModel::Children rows = m_playerListStore->children();
	TreeModel::iterator rowIter;
	for(rowIter=rows.begin(); rowIter!=rows.end(); rowIter++)
	{
		if(!rowIter)
		{
			cerr << "ERROR: A player row was corrupt\n";
			continue;
		}
		TreeModel::Row row=*rowIter;
		uint ID = row[m_playerColumns->m_ID];
		if(ID == lobbyChange->m_playerID)
		{
			m_playerListStore->erase(rowIter);
		}
	}
	for(rowIter=rows.begin(); rowIter!=rows.end(); rowIter++)
	{
		TreeModel::Row row=*rowIter;
		uint ID = row[m_playerColumns->m_ID];
		if(ID == lobbyChange->m_newLeaderID )
		{
			row[m_playerColumns->m_isLeader] = true;
		}
		else
		{
			row[m_playerColumns->m_isLeader] = false;
		}
		if(m_playerDescription.m_ID == lobbyChange->m_newLeaderID)
		{
			row[m_playerColumns->m_leaderSelectable] = true;
			swap_leader_widgets(true);
		}
		else
		{
			row[m_playerColumns->m_leaderSelectable] = false;
			swap_leader_widgets(false);
		}
	}
	m_currentMatch.m_leaderID = lobbyChange->m_newLeaderID;
	m_player_list_view->show_all();
}
void WelcomeWindow::TeamChangedEvent()
{
	CallbackChange *change = m_callbackHandler->PopCallbackChange();
	if(change->m_type == CALLBACK_ERROR)
	{
		cerr << "ERROR: Got an error in callback processing" << endl;
		return;
	}
	MainLobbyCallbackChange *lobbyChange = (MainLobbyCallbackChange*)change;

	PlayerListColumns playerColumns;
	TeamComboColumns teamColumns;

	TreeModel::Children rows = m_playerListStore->children();
	TreeModel::iterator rowIter;
	for(rowIter=rows.begin(); rowIter!=rows.end(); rowIter++)
	{
		if(!rowIter)
		{
			cerr << "ERROR: A player row was corrupt\n";
			continue;
		}
		TreeModel::Row playerRow=*rowIter;
		int ID = playerRow[playerColumns.m_ID];
		if( ID == (int)lobbyChange->m_playerID )
		{
			playerRow[playerColumns.m_teamName] =
					Team::TeamNumberToString((enum TeamNumber)lobbyChange->m_team);

//						//Get set the new team number back into the combobox's data
//						TreeValueProxy<Glib::RefPtr<TreeModel> > teamNumberListStore =
//								playerRow[playerColumns.teamChosen];
//						Glib::RefPtr<TreeModel> treeModelPtr = teamNumberListStore;
//						TreeModel::iterator chosenTeamIter = treeModelPtr->get_iter("0");
//						TreeModel::Row existingTeamRow = (*chosenTeamIter);
//						existingTeamRow[teamColumns.teamNum] = change.team;
//						existingTeamRow[teamColumns.teamString] =
//								Team::TeamNumberToString((enum TeamNumber)change.team);

			m_player_list_view->show_all();
			break;
		}
	}
}
//
// Clear the tree.
//
void EnginesTree::clear(void)
{
	// Unselect engines
	get_selection()->unselect_all();

	// Remove existing rows in the tree
	TreeModel::Children children = m_refStore->children();
	if (children.empty() == false)
	{
		TreeModel::Children::iterator iter = children.begin();
		while (iter != children.end())
		{
			// Erase this row
			m_refStore->erase(*iter);

			// Get the new first row
			children = m_refStore->children();
			iter = children.begin();
		}
		m_refStore->clear();
	}
}
//
// Updates a results group.
//
void ResultsTree::updateGroup(TreeModel::iterator &groupIter)
{
	TreeModel::Row groupRow = (*groupIter);

	// Check the iterator doesn't point to a result
	if (groupRow[m_resultsColumns.m_type] == ResultsModelColumns::RESULT_TITLE)
	{
		return;
	}

	// Modify the "score" column to indicate the number of results in that group
	TreeModel::Children groupChildren = groupIter->children();
	char scoreStr[64];
	snprintf(scoreStr, 64, "%u", groupChildren.size());
	groupRow[m_resultsColumns.m_score] = scoreStr;
#ifdef DEBUG
	cout << "ResultsTree::updateGroup: group " << groupRow[m_resultsColumns.m_text] << " has " << groupChildren.size() << " children" << endl;
#endif

	// Expand this group
	TreeModel::Path groupPath = m_refStore->get_path(groupIter);
	expand_row(groupPath, true);
}
Beispiel #10
0
Gtk::TreeModel::iterator TaskList::subSearch(int id, TreeModel::Children children)
{
	TreeIter iter;

	for (iter = children.begin(); iter != children.end(); iter++)
	{
		TreeModel::Row row = *iter;
		if (row.children().size() > 0)
		{
			TreeIter subIter = subSearch(id, row.children());
			if (subIter != row.children().end())
			{
				iter = subIter;
				break;
			}
		}
		if (row[columns.col_id] == id)
		{
			break;
		}
	}
	return iter;
}
void WelcomeWindow::on_leader_toggled(const Glib::ustring& path)
{
	PlayerListColumns playerColumns;

	Glib::RefPtr<TreeModel> playerModelPtr = m_playerListStore;
	TreeModel::iterator chosenPlayerIter = playerModelPtr->get_iter(path);
	if(!chosenPlayerIter)
	{
		cerr << "ERROR: Invalid player row selected for changing leader\n";
		m_match_lobby_status->push("Could not change the leader");
		m_player_list_view->show_all();
		return;
	}
	TreeModel::Row chosenPlayerRow = (*chosenPlayerIter);
	uint newLeaderID = chosenPlayerRow[playerColumns.m_ID];

	if(ChangeLeader(newLeaderID) == false)
	{
		cerr << "WARNING: Change of leader on the server failed\n";
		m_match_lobby_status->push("Could not change the leader");
		m_player_list_view->show_all();
		return;
	}

	TreeModel::Children rows = m_playerListStore->children();
	TreeModel::iterator r;
	for(r=rows.begin(); r!=rows.end(); r++)
	{
		TreeModel::Row row=*r;
		row[playerColumns.m_isLeader] = false;
		row[playerColumns.m_leaderSelectable] = false;
	}
	chosenPlayerRow[playerColumns.m_isLeader] = true;
	m_currentMatch.m_leaderID = newLeaderID;

	m_player_list_view->show_all();
}
//
// Updates a results group.
//
void ResultsTree::updateGroup(TreeModel::iterator &groupIter)
{
	TreeModel::Row groupRow = (*groupIter);
	int averageScore = 0;

	// Check the iterator doesn't point to a result
	if (groupRow[m_resultsColumns.m_type] == ResultsModelColumns::RESULT_TITLE)
	{
		return;
	}

	// Modify the "score" column to indicate the number of results in that group
	TreeModel::Children groupChildren = groupIter->children();
	if (groupChildren.empty() == false)
	{
		for (TreeModel::Children::iterator childIter = groupChildren.begin();
			childIter != groupChildren.end(); ++childIter)
		{
			TreeModel::Row row = *childIter;

			averageScore += row[m_resultsColumns.m_score];
		}

		averageScore = (int)(averageScore / groupChildren.size());
	}
	groupRow[m_resultsColumns.m_score] = averageScore;

#ifdef DEBUG
	cout << "ResultsTree::updateGroup: group " << groupRow[m_resultsColumns.m_text]
		<< " has score " << averageScore << endl;
#endif

	// Expand this group
	TreeModel::Path groupPath = m_refStore->get_path(groupIter);
	expand_row(groupPath, true);
}
//
// Sets how results are grouped.
//
void ResultsTree::setGroupMode(bool groupBySearchEngine)
{
	ResultsModelColumns::ResultType currentType, newType;

	if (m_groupBySearchEngine == groupBySearchEngine)
	{
		// No change
		return;
	}
	m_groupBySearchEngine = groupBySearchEngine;

	// Do we need to update the tree ?
	TreeModel::Children children = m_refStore->children();
	if (children.empty() == true)
	{
		return;
	}

	// What's the new grouping criteria ?
	if (groupBySearchEngine == true)
	{
		// By search engine
		currentType = ResultsModelColumns::RESULT_HOST;
		newType = ResultsModelColumns::RESULT_ROOT;
	}
	else
	{
		// By host
		currentType = ResultsModelColumns::RESULT_ROOT;
		newType = ResultsModelColumns::RESULT_HOST;
	}

	// Clear the map
	m_resultsGroups.clear();

	// Unselect results
	get_selection()->unselect_all();

	TreeModel::Children::iterator iter = children.begin();
	while (iter != children.end())
	{
		TreeModel::Row row = *iter;
#ifdef DEBUG
		cout << "ResultsTree::groupBySearchEngine: looking at " << row[m_resultsColumns.m_text] << endl;
#endif
		ResultsModelColumns::ResultType type = row[m_resultsColumns.m_type];
		// Skip new type rows
		if (type == newType)
		{
			iter++;
			continue;
		}

		TreeModel::Children child = iter->children();
		if (child.empty() == false)
		{
			TreeModel::Children::iterator childIter = child.begin();
			// Type RESULT_TITLE
			while (childIter != child.end())
			{
				TreeModel::Row childRow = *childIter;
				TreeModel::iterator groupIter, newIter;
				bool success = false;

				// We will need the URL and engines columns in all cases
				string url = from_utf8(childRow[m_resultsColumns.m_url]);
				unsigned int engineIds = childRow[m_resultsColumns.m_engines];
				unsigned int indexIds = childRow[m_resultsColumns.m_indexes];

				// Get the name of the group this should go into
				if (newType == ResultsModelColumns::RESULT_HOST)
				{
					Url urlObj(url);
#ifdef DEBUG
					cout << "ResultsTree::groupBySearchEngine: row " << url << endl;
#endif
					string groupName = urlObj.getHost();
					// Add group
					if (appendGroup(groupName, newType, groupIter) == true)
					{
						// Add result
						success = appendResult(childRow[m_resultsColumns.m_text],
							childRow[m_resultsColumns.m_url],
							(float)atof(from_utf8(childRow[m_resultsColumns.m_score]).c_str()),
							from_utf8(childRow[m_resultsColumns.m_language]),
							childRow[m_resultsColumns.m_rankDiff],
							from_utf8(childRow[m_resultsColumns.m_queryName]),
							engineIds, indexIds, newIter, &(*groupIter), true);
					}
				}
				else
				{
					// Look at the engines column and see which engines this result is for
					set<string> engineNames;
					m_settings.getEngineNames(engineIds, engineNames);
					if (engineNames.empty() == false)
					{
#ifdef DEBUG
						cout << "ResultsTree::groupBySearchEngine: row is for " << engineNames.size() << endl;
#endif
						// Are there indexes in the list ?
						set<string>::iterator xapianIter = engineNames.find("Xapian");
						if ((xapianIter != engineNames.end()) &&
							(indexIds > 0))
						{
							// Erase this
							engineNames.erase(xapianIter);

							// Add entries for each index name so that we can loop once on engine names
							set<string> indexNames;
							m_settings.getIndexNames(indexIds, indexNames);
							for (set<string>::iterator iter = indexNames.begin(); iter != indexNames.end(); ++iter)
							{
								string indexName = (*iter);
								engineNames.insert(indexName);
#ifdef DEBUG
								cout << "ResultsTree::groupBySearchEngine: row is for index " << indexName << endl;
#endif
							}
						}

						for (set<string>::iterator iter = engineNames.begin(); iter != engineNames.end(); ++iter)
						{
							string engineName = (*iter);
							unsigned int indexId = 0;
							unsigned int engineId = m_settings.getEngineId(engineName);

							if (engineId == 0)
							{
								// This is actually an index, not an engine...
								indexId = m_settings.getIndexId(engineName);
								if (indexId > 0)
								{
									engineId = m_settings.getEngineId("Xapian");
								}
							}

							// Add group
							if (appendGroup(engineName, newType, groupIter) == true)
							{
								// Add result
								appendResult(childRow[m_resultsColumns.m_text],
									childRow[m_resultsColumns.m_url],
									(float)atof(from_utf8(childRow[m_resultsColumns.m_score]).c_str()),
									from_utf8(childRow[m_resultsColumns.m_language]),
									childRow[m_resultsColumns.m_rankDiff],
									from_utf8(childRow[m_resultsColumns.m_queryName]),
									engineId, indexId,
									newIter, &(*groupIter), true);
#ifdef DEBUG
								cout << "ResultsTree::groupBySearchEngine: row for " << *iter << endl;
#endif
							}
						}

						// FIXME: make sure at least one row was added
						success = true;
					}
				}

				if (success == true)
				{
					// Delete it
					m_refStore->erase(*childIter);
					childIter = child.begin();
				}
				else
				{
					// Don't delete anything then, just go to the next child
					childIter++;
				}
			}
		}

		// Erase this row
		m_refStore->erase(*iter);

		// Get the new first row, that way we don't have to worry about iterators validity
		iter = children.begin();
	}

	for (std::map<string, TreeModel::iterator>::iterator mapIter = m_resultsGroups.begin();
		mapIter != m_resultsGroups.end(); mapIter++)
	{
		TreeModel::iterator groupIter = mapIter->second;
		updateGroup(groupIter);
	}

	onSelectionChanged();
}
//
// Adds a new row in the results tree.
//
bool ResultsTree::appendResult(const ustring &text, const ustring &url,
	float score, const string &language, int rankDiff,
	const string &queryName, unsigned int engineId, unsigned int indexId,
	TreeModel::iterator &newRowIter, const TreeModel::Row *parentRow, bool noDuplicates)
{
	if (parentRow == NULL)
	{
		newRowIter = m_refStore->append();
	}
	else
	{
		// Merge duplicates within groups ?
		if (noDuplicates == true)
		{
			// Look for a row with the same URL and query. For instance, in group
			// by host mode, if a page is returned by several search engines, it
			// should appear only once
			TreeModel::Children children = parentRow->children();
			if (children.empty() == false)
			{
				TreeModel::Children::iterator childIter = children.begin();
				for (; childIter != children.end(); ++childIter)
				{
					TreeModel::Row row = *childIter;
					if ((row[m_resultsColumns.m_url] == to_utf8(url)) &&
						(row[m_resultsColumns.m_queryName] == to_utf8(queryName)))
					{
						// Update the engines column...
						row[m_resultsColumns.m_engines] = row[m_resultsColumns.m_engines] | engineId;
						// ...and the indexes column too
						row[m_resultsColumns.m_indexes] = row[m_resultsColumns.m_indexes] | engineId;
#ifdef DEBUG
						cout << "ResultsTree::appendResult: merged " << text << " " << engineId << " (" << row[m_resultsColumns.m_engines] << "," << row[m_resultsColumns.m_indexes] << ")" << endl;
#endif

						newRowIter = childIter;
						return true;
					}
				}
			}
		}

		newRowIter = m_refStore->append(parentRow->children());
#ifdef DEBUG
		cout << "ResultsTree::appendResult: added " << text << ", " << score << " to "
			<< (*parentRow)[m_resultsColumns.m_text] << endl;
#endif
	}

	XapianIndex index(m_settings.m_indexLocation);
	ViewHistory viewHistory(m_settings.m_historyDatabase);
	bool isIndexed = false;

	// Is this document indexed ?
	if ((index.isGood() == true) &&
		(index.hasDocument(url) > 0))
	{
		isIndexed = true;
	}

	// Has it been already viewed ?
	bool wasViewed = viewHistory.hasItem(url);

	char scoreStr[128];
	snprintf(scoreStr, 128, "%.f", score);

	TreeModel::Row childRow = *newRowIter;
	updateRow(childRow, text, url, scoreStr,
		to_utf8(language), to_utf8(queryName), engineId, indexId,
		ResultsModelColumns::RESULT_TITLE, isIndexed,
		wasViewed, rankDiff);

	return true;
}
//
// Deletes results.
//
bool ResultsTree::deleteResults(QueryProperties &queryProps, const string &engineName)
{
	ustring queryName(queryProps.getName());
	unsigned int indexId = 0;
	unsigned int engineId = m_settings.getEngineId(engineName);
	unsigned int count = 0;

	if (engineId == 0)
	{
		// Chances are this engine is an index
		std::map<string, string>::const_iterator mapIter = m_settings.getIndexes().find(engineName);
		if (mapIter != m_settings.getIndexes().end())
		{
			// Yes, it is
			indexId = m_settings.getIndexId(engineName);
			engineId = m_settings.getEngineId("Xapian");
		}
	}

	TreeModel::Children groups = m_refStore->children();
	for (TreeModel::Children::iterator parentIter = groups.begin();
		parentIter != groups.end(); ++parentIter)
	{
		TreeModel::Row row = *parentIter;

		if ((row[m_resultsColumns.m_type] != ResultsModelColumns::RESULT_ROOT) &&
			(row[m_resultsColumns.m_type] != ResultsModelColumns::RESULT_HOST))
		{
			continue;
		}

		TreeModel::Children children = parentIter->children();
		TreeModel::Children::iterator iter = children.begin();
		while (iter != children.end())
		{
			row = *iter;

			if ((row[m_resultsColumns.m_type] == ResultsModelColumns::RESULT_TITLE) &&
				(row[m_resultsColumns.m_engines] == engineId) &&
				(row[m_resultsColumns.m_indexes] == indexId))
			{
				TreeModel::Children::iterator nextIter = iter;
				++nextIter;
				++count;

				// Erase this row
				m_refStore->erase(*iter);
				iter = nextIter;
				continue;
			}

			// Next
			++iter;
		}
	}

	if (count > 0)
	{
		onSelectionChanged();
#ifdef DEBUG
		cout << "ResultsTree::deleteResults: erased " << count << " rows" << endl;
#endif
		return true;
	}

	return false;
}