34 #include <QtConcurrentRun>
53 QTimer::singleShot (1000,
this, SLOT (update ()));
68 for (
const auto& list : Items_)
70 const auto pos = std::find_if (list.begin (), list.end (),
71 [&id] (
const Item_ptr& item) {
return item->GetPermanentID () == id; });
72 if (pos != list.end ())
81 using Cat2ID2Item_t = QHash<QString, QHash<QString, Item_ptr>>;
83 Cat2ID2Item_t ItemsList2Map (
const Cat2Items_t& items)
89 auto& map = result [pair.first];
90 for (
const auto& item : pair.second)
91 map [item->GetPermanentID ()] = item;
97 Cat2Items_t ItemsMap2List (
const Cat2ID2Item_t& items)
102 std::copy (pair.second.begin (), pair.second.end (),
103 std::back_inserter (result [pair.first]));
108 QStringList ScanDir (
const QString& path)
110 const auto& infos = QDir (path).entryInfoList ({
"*.desktop" },
111 QDir::Files | QDir::AllDirs | QDir::NoDotAndDotDot);
114 [] (
const QFileInfo& info)
116 return info.isDir () ?
117 ScanDir (info.absoluteFilePath ()) :
118 QStringList { info.absoluteFilePath () };
122 Cat2ID2Item_t FindAndParse (
const QList<Type>& types)
124 Cat2ID2Item_t result;
127 for (
const auto& dir :
ToPaths (types))
128 paths << ScanDir (dir);
130 for (
const auto& path : paths)
137 catch (
const std::exception& e)
139 qWarning () << Q_FUNC_INFO
146 if (!item->IsValid ())
148 qWarning () << Q_FUNC_INFO
154 for (
const auto& cat : item->GetCategories ())
155 if (!cat.startsWith (
"X-"))
156 result [cat] [item->GetPermanentID ()] = item;
169 DiffResult (T&& oldCont, T&& newCont)
171 std::set_difference (oldCont.begin (), oldCont.end (),
172 newCont.begin (), newCont.end (),
174 std::set_difference (newCont.begin (), newCont.end (),
175 oldCont.begin (), oldCont.end (),
176 std::back_inserter (
Added_));
178 std::set_intersection (oldCont.begin (), oldCont.end (),
179 newCont.begin (), newCont.end (),
183 bool HasChanges ()
const
189 template<
typename Container>
190 DiffResult<Container> CalcDiff (Container&& oldCont, Container&& newCont)
192 return { std::forward<Container> (oldCont), std::forward<Container> (newCont) };
195 boost::optional<Cat2Items_t> Merge (
const Cat2Items_t& existing, Cat2ID2Item_t result)
197 auto ourItems = ItemsList2Map (existing);
201 const auto& diffCats = CalcDiff (
Util::Sorted (existing.keys ()),
204 for (
const auto& removed : diffCats.Removed_)
205 ourItems.remove (removed);
206 for (
const auto& added : diffCats.Added_)
207 swap (ourItems [added], result [added]);
209 bool changed = diffCats.HasChanges ();
211 for (
const auto& cat : diffCats.Intersection_)
213 auto& ourList = ourItems [cat];
214 auto& newList = result [cat];
215 const auto& diffItems = CalcDiff (
Util::Sorted (ourList.keys ()),
218 changed = changed || diffItems.HasChanges ();
220 for (
const auto& removed : diffItems.Removed_)
221 ourList.remove (removed);
222 for (
const auto& added : diffItems.Added_)
223 swap (ourList [added], newList [added]);
225 for (
const auto& existing : diffItems.Intersection_)
226 if (*ourList [existing] != *newList [existing])
228 swap (ourList [existing], newList [existing]);
236 return ItemsMap2List (ourItems);
247 Util::Sequence (
this, QtConcurrent::run (FindAndParse, Types_)) >>
248 [
this] (Cat2ID2Item_t result)
250 return QtConcurrent::run (Merge,
Items_, result);
252 [
this] (
const boost::optional<Cat2Items_t>& result)