diff options
Diffstat (limited to 'Swift/Controllers/Roster/TableRoster.cpp')
| -rw-r--r-- | Swift/Controllers/Roster/TableRoster.cpp | 291 | 
1 files changed, 146 insertions, 145 deletions
diff --git a/Swift/Controllers/Roster/TableRoster.cpp b/Swift/Controllers/Roster/TableRoster.cpp index 9f3cd54..713f390 100644 --- a/Swift/Controllers/Roster/TableRoster.cpp +++ b/Swift/Controllers/Roster/TableRoster.cpp @@ -1,185 +1,186 @@  /* - * Copyright (c) 2011 Isode Limited. + * Copyright (c) 2011-2016 Isode Limited.   * All rights reserved.   * See the COPYING file for more information.   */  #include <Swift/Controllers/Roster/TableRoster.h> -#include <boost/cast.hpp> -#include <cassert>  #include <algorithm> +#include <cassert> + +#include <boost/cast.hpp>  #include <boost/numeric/conversion/cast.hpp> -#include <Swiften/Base/foreach.h> -#include <Swiften/Network/TimerFactory.h>  #include <Swiften/Network/Timer.h> -#include <Swift/Controllers/Roster/Roster.h> +#include <Swiften/Network/TimerFactory.h> +  #include <Swift/Controllers/Roster/GroupRosterItem.h>  #include <Swift/Controllers/Roster/LeastCommonSubsequence.h> +#include <Swift/Controllers/Roster/Roster.h>  namespace Swift { -	struct SectionNameEquals { -		bool operator()(const TableRoster::Section& s1, const TableRoster::Section& s2) const { -			return s1.name == s2.name; -		} -	}; - -	template<typename T> -	struct True { -		bool operator()(const T&, const T&) const { -			return true; -		} -	}; - -	struct ItemEquals { -			bool operator()(const TableRoster::Item& i1, const TableRoster::Item& i2) const { -				return i1.jid == i2.jid; -			} -	}; - - -	struct ItemNeedsUpdate { -			bool operator()(const TableRoster::Item& i1, const TableRoster::Item& i2) const { -				return i1.status != i2.status || i1.description != i2.description || i1.name != i2.name || i1.avatarPath.empty() != i2.avatarPath.empty(); -			} -	}; - -	struct CreateIndexForSection { -			CreateIndexForSection(size_t section) : section(section) { -			} - -			TableRoster::Index operator()(size_t row) const { -				return TableRoster::Index(section, row); -			} - -			size_t section; -	}; +    struct SectionNameEquals { +        bool operator()(const TableRoster::Section& s1, const TableRoster::Section& s2) const { +            return s1.name == s2.name; +        } +    }; + +    template<typename T> +    struct True { +        bool operator()(const T&, const T&) const { +            return true; +        } +    }; + +    struct ItemEquals { +            bool operator()(const TableRoster::Item& i1, const TableRoster::Item& i2) const { +                return i1.jid == i2.jid; +            } +    }; + + +    struct ItemNeedsUpdate { +            bool operator()(const TableRoster::Item& i1, const TableRoster::Item& i2) const { +                return i1.status != i2.status || i1.description != i2.description || i1.name != i2.name || i1.avatarPath.empty() != i2.avatarPath.empty(); +            } +    }; + +    struct CreateIndexForSection { +            CreateIndexForSection(size_t section) : section(section) { +            } + +            TableRoster::Index operator()(size_t row) const { +                return TableRoster::Index(section, row); +            } + +            size_t section; +    };  }  using namespace Swift;  TableRoster::TableRoster(Roster* model, TimerFactory* timerFactory, int updateDelay) : model(model), updatePending(false) { -	updateTimer = timerFactory->createTimer(updateDelay); -	updateTimer->onTick.connect(boost::bind(&TableRoster::handleUpdateTimerTick, this)); -	if (model) { -		model->onChildrenChanged.connect(boost::bind(&TableRoster::scheduleUpdate, this)); -		model->onGroupAdded.connect(boost::bind(&TableRoster::scheduleUpdate, this)); -		model->onDataChanged.connect(boost::bind(&TableRoster::scheduleUpdate, this)); -	} +    updateTimer = timerFactory->createTimer(updateDelay); +    updateTimer->onTick.connect(boost::bind(&TableRoster::handleUpdateTimerTick, this)); +    if (model) { +        model->onChildrenChanged.connect(boost::bind(&TableRoster::scheduleUpdate, this)); +        model->onGroupAdded.connect(boost::bind(&TableRoster::scheduleUpdate, this)); +        model->onDataChanged.connect(boost::bind(&TableRoster::scheduleUpdate, this)); +    }  }  TableRoster::~TableRoster() { -	updateTimer->stop(); -	updateTimer->onTick.disconnect(boost::bind(&TableRoster::handleUpdateTimerTick, this)); -	if (model) { -		model->onDataChanged.disconnect(boost::bind(&TableRoster::scheduleUpdate, this)); -		model->onGroupAdded.disconnect(boost::bind(&TableRoster::scheduleUpdate, this)); -		model->onChildrenChanged.disconnect(boost::bind(&TableRoster::scheduleUpdate, this)); -	} +    updateTimer->stop(); +    updateTimer->onTick.disconnect(boost::bind(&TableRoster::handleUpdateTimerTick, this)); +    if (model) { +        model->onDataChanged.disconnect(boost::bind(&TableRoster::scheduleUpdate, this)); +        model->onGroupAdded.disconnect(boost::bind(&TableRoster::scheduleUpdate, this)); +        model->onChildrenChanged.disconnect(boost::bind(&TableRoster::scheduleUpdate, this)); +    }  } -			 +  size_t TableRoster::getNumberOfSections() const { -	return sections.size(); +    return sections.size();  }  const std::string& TableRoster::getSectionTitle(size_t section) { -	return sections[section].name; +    return sections[section].name;  }  size_t TableRoster::getNumberOfRowsInSection(size_t section) const { -	return sections[section].items.size(); +    return sections[section].items.size();  }  const TableRoster::Item& TableRoster::getItem(const Index& index) const { -	return sections[index.section].items[index.row]; +    return sections[index.section].items[index.row];  } -			 +  void TableRoster::handleUpdateTimerTick() { -	updateTimer->stop(); -	updatePending = false; - -	// Get a model for the new roster -	std::vector<Section> newSections; -	if (model) { -		foreach(RosterItem* item, model->getRoot()->getDisplayedChildren()) { -			if (GroupRosterItem* groupItem = boost::polymorphic_downcast<GroupRosterItem*>(item)) { -				//std::cerr << "* " << groupItem->getDisplayName() << std::endl; -				Section section(groupItem->getDisplayName()); -				foreach(RosterItem* groupChildItem, groupItem->getDisplayedChildren()) { -					if (ContactRosterItem* contact = boost::polymorphic_downcast<ContactRosterItem*>(groupChildItem)) { -						//std::cerr << "  - " << contact->getDisplayJID() << std::endl; -						section.items.push_back(Item(contact->getDisplayName(), contact->getStatusText(), contact->getDisplayJID(), contact->getStatusShow(), contact->getAvatarPath())); -					} -				} -				newSections.push_back(section); -			} -		} -	} - -	// Do a diff with the previous roster -	Update update; -	std::vector<size_t> sectionUpdates; -	std::vector<size_t> sectionPostUpdates; -	computeIndexDiff<Section,SectionNameEquals,True<Section> >(sections, newSections, sectionUpdates, sectionPostUpdates, update.deletedSections, update.insertedSections); -	assert(sectionUpdates.size() == sectionPostUpdates.size()); -	for (size_t i = 0; i < sectionUpdates.size(); ++i) { -		assert(sectionUpdates[i] < sections.size()); -		assert(sectionPostUpdates[i] < newSections.size()); -		std::vector<size_t> itemUpdates; -		std::vector<size_t> itemPostUpdates; -		std::vector<size_t> itemRemoves; -		std::vector<size_t> itemInserts; -		computeIndexDiff<Item, ItemEquals, ItemNeedsUpdate >(sections[sectionUpdates[i]].items, newSections[sectionPostUpdates[i]].items, itemUpdates, itemPostUpdates, itemRemoves, itemInserts); -		size_t end = update.insertedRows.size(); -		update.insertedRows.resize(update.insertedRows.size() + itemInserts.size()); -		std::transform(itemInserts.begin(), itemInserts.end(), update.insertedRows.begin() + boost::numeric_cast<long long>(end), CreateIndexForSection(sectionPostUpdates[i])); -		end = update.deletedRows.size(); -		update.deletedRows.resize(update.deletedRows.size() + itemRemoves.size()); -		std::transform(itemRemoves.begin(), itemRemoves.end(), update.deletedRows.begin() + boost::numeric_cast<long long>(end), CreateIndexForSection(sectionUpdates[i])); -		end = update.updatedRows.size(); -		update.updatedRows.resize(update.updatedRows.size() + itemUpdates.size()); -		std::transform(itemUpdates.begin(), itemUpdates.end(), update.updatedRows.begin() + boost::numeric_cast<long long>(end), CreateIndexForSection(sectionPostUpdates[i])); -	} -	 -	// Switch the old model with the new -	sections.swap(newSections); - -	/* -	std::cerr << "-S: "; -	for (size_t i = 0; i < update.deletedSections.size(); ++i) { -		std::cerr << update.deletedSections[i] << " "; -	} -	std::cerr << std::endl; -	std::cerr << "+S: "; -	for (size_t i = 0; i < update.insertedSections.size(); ++i) { -		std::cerr << update.insertedSections[i] << " "; -	} -	std::cerr << std::endl; -	std::cerr << "-R: "; -	for (size_t i = 0; i < update.deletedRows.size(); ++i) { -		std::cerr << update.deletedRows[i].section << "," << update.deletedRows[i].row << " "; -	} -	std::cerr << std::endl; -	std::cerr << "*R: "; -	for (size_t i = 0; i < update.updatedRows.size(); ++i) { -		std::cerr << update.updatedRows[i].section << "," << update.updatedRows[i].row << " "; -	} -	std::cerr << std::endl; -	std::cerr << "+R: "; -	for (size_t i = 0; i < update.insertedRows.size(); ++i) { -		std::cerr << update.insertedRows[i].section << "," << update.insertedRows[i].row << " "; -	} -	std::cerr << std::endl; -	*/ - -	// Emit the update -	onUpdate(update); +    updateTimer->stop(); +    updatePending = false; + +    // Get a model for the new roster +    std::vector<Section> newSections; +    if (model) { +        for (auto item : model->getRoot()->getDisplayedChildren()) { +            if (GroupRosterItem* groupItem = boost::polymorphic_downcast<GroupRosterItem*>(item)) { +                //std::cerr << "* " << groupItem->getDisplayName() << std::endl; +                Section section(groupItem->getDisplayName()); +                for (auto groupChildItem : groupItem->getDisplayedChildren()) { +                    if (ContactRosterItem* contact = boost::polymorphic_downcast<ContactRosterItem*>(groupChildItem)) { +                        //std::cerr << "  - " << contact->getDisplayJID() << std::endl; +                        section.items.push_back(Item(contact->getDisplayName(), contact->getStatusText(), contact->getDisplayJID(), contact->getStatusShow(), contact->getAvatarPath())); +                    } +                } +                newSections.push_back(section); +            } +        } +    } + +    // Do a diff with the previous roster +    Update update; +    std::vector<size_t> sectionUpdates; +    std::vector<size_t> sectionPostUpdates; +    computeIndexDiff<Section,SectionNameEquals,True<Section> >(sections, newSections, sectionUpdates, sectionPostUpdates, update.deletedSections, update.insertedSections); +    assert(sectionUpdates.size() == sectionPostUpdates.size()); +    for (size_t i = 0; i < sectionUpdates.size(); ++i) { +        assert(sectionUpdates[i] < sections.size()); +        assert(sectionPostUpdates[i] < newSections.size()); +        std::vector<size_t> itemUpdates; +        std::vector<size_t> itemPostUpdates; +        std::vector<size_t> itemRemoves; +        std::vector<size_t> itemInserts; +        computeIndexDiff<Item, ItemEquals, ItemNeedsUpdate >(sections[sectionUpdates[i]].items, newSections[sectionPostUpdates[i]].items, itemUpdates, itemPostUpdates, itemRemoves, itemInserts); +        size_t end = update.insertedRows.size(); +        update.insertedRows.resize(update.insertedRows.size() + itemInserts.size()); +        std::transform(itemInserts.begin(), itemInserts.end(), update.insertedRows.begin() + boost::numeric_cast<long long>(end), CreateIndexForSection(sectionPostUpdates[i])); +        end = update.deletedRows.size(); +        update.deletedRows.resize(update.deletedRows.size() + itemRemoves.size()); +        std::transform(itemRemoves.begin(), itemRemoves.end(), update.deletedRows.begin() + boost::numeric_cast<long long>(end), CreateIndexForSection(sectionUpdates[i])); +        end = update.updatedRows.size(); +        update.updatedRows.resize(update.updatedRows.size() + itemUpdates.size()); +        std::transform(itemUpdates.begin(), itemUpdates.end(), update.updatedRows.begin() + boost::numeric_cast<long long>(end), CreateIndexForSection(sectionPostUpdates[i])); +    } + +    // Switch the old model with the new +    sections.swap(newSections); + +    /* +    std::cerr << "-S: "; +    for (size_t i = 0; i < update.deletedSections.size(); ++i) { +        std::cerr << update.deletedSections[i] << " "; +    } +    std::cerr << std::endl; +    std::cerr << "+S: "; +    for (size_t i = 0; i < update.insertedSections.size(); ++i) { +        std::cerr << update.insertedSections[i] << " "; +    } +    std::cerr << std::endl; +    std::cerr << "-R: "; +    for (size_t i = 0; i < update.deletedRows.size(); ++i) { +        std::cerr << update.deletedRows[i].section << "," << update.deletedRows[i].row << " "; +    } +    std::cerr << std::endl; +    std::cerr << "*R: "; +    for (size_t i = 0; i < update.updatedRows.size(); ++i) { +        std::cerr << update.updatedRows[i].section << "," << update.updatedRows[i].row << " "; +    } +    std::cerr << std::endl; +    std::cerr << "+R: "; +    for (size_t i = 0; i < update.insertedRows.size(); ++i) { +        std::cerr << update.insertedRows[i].section << "," << update.insertedRows[i].row << " "; +    } +    std::cerr << std::endl; +    */ + +    // Emit the update +    onUpdate(update);  }  void TableRoster::scheduleUpdate() { -	if (!updatePending) { -		updatePending = true; -		updateTimer->start(); -	} +    if (!updatePending) { +        updatePending = true; +        updateTimer->start(); +    }  }  | 
 Swift