13#include <QtConcurrentRun>
44 for (
const auto& list : Items_)
46 const auto pos = std::find_if (list.begin (), list.end (),
47 [&
id] (
const Item_ptr& item) { return item->GetPermanentID () == id; });
48 if (pos != list.end ())
57 using Cat2ID2Item_t = QHash<QString, QHash<QString, Item_ptr>>;
59 Cat2ID2Item_t ItemsList2Map (
const Cat2Items_t& items)
65 auto& map = result [pair.first];
66 for (
const auto& item : pair.second)
67 map [item->GetPermanentID ()] = item;
73 Cat2Items_t ItemsMap2List (
const Cat2ID2Item_t& items)
78 std::copy (pair.second.begin (), pair.second.end (),
79 std::back_inserter (result [pair.first]));
84 QStringList ScanDir (
const QString& path)
86 const auto& infos = QDir (path).entryInfoList ({ QStringLiteral (
"*.desktop") },
87 QDir::Files | QDir::AllDirs | QDir::NoDotAndDotDot);
90 [] (
const QFileInfo& info)
92 return info.isDir () ?
93 ScanDir (info.absoluteFilePath ()) :
94 QStringList { info.absoluteFilePath () };
98 Cat2ID2Item_t FindAndParse (
const QList<Type>& types)
100 Cat2ID2Item_t result;
103 for (
const auto& dir :
ToPaths (types))
104 paths << ScanDir (dir);
106 for (
const auto& path : paths)
113 catch (
const std::exception& e)
115 qWarning () << Q_FUNC_INFO
122 if (!item->IsValid ())
124 qWarning () << Q_FUNC_INFO
130 for (
const auto& cat : item->GetCategories ())
131 if (!cat.startsWith (
"X-"_ql))
132 result [cat] [item->GetPermanentID ()] = item;
141 std::decay_t<T> Added_;
142 std::decay_t<T> Removed_;
143 std::decay_t<T> Intersection_;
145 DiffResult (T&& oldCont, T&& newCont)
147 std::set_difference (oldCont.begin (), oldCont.end (),
148 newCont.begin (), newCont.end (),
149 std::back_inserter (Removed_));
150 std::set_difference (newCont.begin (), newCont.end (),
151 oldCont.begin (), oldCont.end (),
152 std::back_inserter (Added_));
154 std::set_intersection (oldCont.begin (), oldCont.end (),
155 newCont.begin (), newCont.end (),
156 std::back_inserter (Intersection_));
159 bool HasChanges ()
const
161 return !Removed_.isEmpty () || !Added_.isEmpty ();
165 template<
typename Container>
166 DiffResult<Container> CalcDiff (Container&& oldCont, Container&& newCont)
168 return { std::forward<Container> (oldCont), std::forward<Container> (newCont) };
171 std::optional<Cat2Items_t> Merge (
const Cat2Items_t& existing, Cat2ID2Item_t result)
173 auto ourItems = ItemsList2Map (existing);
177 const auto& diffCats = CalcDiff (
Util::Sorted (existing.keys ()),
180 for (
const auto& removed : diffCats.Removed_)
181 ourItems.remove (removed);
182 for (
const auto& added : diffCats.Added_)
183 swap (ourItems [added], result [added]);
185 bool changed = diffCats.HasChanges ();
187 for (
const auto& cat : diffCats.Intersection_)
189 auto& ourList = ourItems [cat];
190 auto& newList = result [cat];
191 const auto& diffItems = CalcDiff (
Util::Sorted (ourList.keys ()),
194 changed = changed || diffItems.HasChanges ();
196 for (
const auto& removed : diffItems.Removed_)
197 ourList.remove (removed);
198 for (
const auto& added : diffItems.Added_)
199 swap (ourList [added], newList [added]);
201 for (
const auto& existing : diffItems.Intersection_)
202 if (*ourList [existing] != *newList [existing])
204 swap (ourList [existing], newList [existing]);
212 return ItemsMap2List (ourItems);
226 const auto& cat2id2item =
co_await QtConcurrent::run (FindAndParse, Types_);
227 const auto& result =
co_await QtConcurrent::run (Merge, Items_, cat2id2item);
static Item_ptr FromDesktopFile(const QString &file)
Loads the XDG .desktop item from file.
bool IsReady() const
Checks whether this items finder is ready.
ItemsFinder(const ICoreProxy_ptr &, const QList< Type > &types, QObject *parent=nullptr)
Constructs the items finder for the given types.
Item_ptr FindItem(const QString &permanentID) const
Finds an XDG item for the given permanent ID.
void itemsListChanged()
Notifies when the list of items changes in any way.
Cat2Items_t GetItems() const
Returns the categorized list of XDG items.
std::shared_ptr< ICoreProxy > ICoreProxy_ptr
QHash< QString, QList< Item_ptr > > Cat2Items_t
std::shared_ptr< Item > Item_ptr
QStringList ToPaths(const QList< Type > &types)
Returns a set of typical directories with desktop files of the given types.
auto Stlize(Assoc &&assoc) noexcept
Converts an Qt's associative sequence assoc to an STL-like iteratable range.
auto ConcatMap(Cont &&c, F &&f)
Task< R, ContextExtensions > ContextTask
decltype(auto) Sorted(Cont &&cont)
void swap(FDGuard &g1, FDGuard &g2)