2424#include " utils/IconHandle.h"
2525#include " utils/path_utils.h"
2626#include " DesktopEntryEditor.h"
27+ #include " MimeInfoEditor.h"
2728#include " Integrator.h"
2829#include " constants.h"
2930
@@ -50,6 +51,7 @@ namespace appimage {
5051
5152 ResourcesExtractor resourcesExtractor;
5253 DesktopEntry desktopEntry;
54+ std::map<std::string, appimage::desktop_integration::integrator::MimeInfoEditor> mimeInfoFiles;
5355
5456 Priv (const AppImage& appImage, const bf::path& xdgDataHome)
5557 : appImage(appImage), xdgDataHome(xdgDataHome),
@@ -58,17 +60,34 @@ namespace appimage {
5860 if (xdgDataHome.empty ())
5961 throw DesktopIntegrationError (" Invalid XDG_DATA_HOME: " + xdgDataHome.string ());
6062
61- // Extract desktop entry, DesktopIntegrationError will be throw if missing
63+ extractDesktopEntry ();
64+ extractMimeInfoFiles ();
65+
66+ appImageId = hashPath (appImage.getPath ());
67+ }
68+
69+ /* *
70+ * Extract desktop entry, DesktopIntegrationError will be throw if missing
71+ */
72+ void extractDesktopEntry () {
6273 auto desktopEntryPath = resourcesExtractor.getDesktopEntryPath ();
6374 auto desktopEntryData = resourcesExtractor.extractText (desktopEntryPath);
6475 try {
6576 desktopEntry = std::move (DesktopEntry (desktopEntryData));
6677 } catch (const DesktopEntryError& error) {
6778 throw DesktopIntegrationError (std::string (" Malformed desktop entry: " ) + error.what ());
6879 }
80+ }
6981
70-
71- appImageId = hashPath (appImage.getPath ());
82+ /* *
83+ * Extract and store mime info files to be used latter
84+ */
85+ void extractMimeInfoFiles () {
86+ std::vector<std::string> mimeInfoPaths = resourcesExtractor.getMimeTypePackagesPaths ();
87+ for (const std::string& path: mimeInfoPaths) {
88+ std::string mimeInfoFileData = resourcesExtractor.extractText (path);
89+ mimeInfoFiles.insert (std::make_pair (path, MimeInfoEditor (mimeInfoFileData)));
90+ }
7291 }
7392
7493 /* *
@@ -160,6 +179,11 @@ namespace appimage {
160179 * Icons at usr/share/icons will be preferred if not available the ".DirIcon" will be used.
161180 */
162181 void deployIcons () {
182+ deployApplicationIcon ();
183+ deployMimeTypeIcons ();
184+ }
185+
186+ void deployApplicationIcon () const {
163187 static const std::string dirIconPath = " .DirIcon" ;
164188 static const auto iconsDirPath = " usr/share/icons" ;
165189
@@ -177,7 +201,7 @@ namespace appimage {
177201 try {
178202 Logger::warning (" Using .DirIcon as default app icon" );
179203 auto dirIconData = resourcesExtractor.extract (dirIconPath);
180- deployApplicationIcon ( desktopEntryIconName, dirIconData);;
204+ deployIcon ( " apps " , desktopEntryIconName, dirIconData);;
181205 } catch (const PayloadIteratorError& error) {
182206 Logger::error (error.what ());
183207 Logger::error (" No icon was generated for: " + appImage.getPath ());
@@ -192,17 +216,68 @@ namespace appimage {
192216 }
193217 }
194218
219+ void deployMimeTypeIcons () {
220+ std::list<std::string> mimeTypeIconNames;
221+ for (const auto & editor : mimeInfoFiles) {
222+ auto names = editor.second .getMimeTypeIconNames ();
223+ mimeTypeIconNames.merge (names);
224+ }
225+
226+ std::vector<std::string> mimeTypeIconPaths;
227+ for (const auto & iconName: mimeTypeIconNames) {
228+ auto paths = resourcesExtractor.getIconFilePaths (iconName);
229+ mimeTypeIconPaths.insert (mimeTypeIconPaths.end (), paths.begin (), paths.end ());
230+ }
231+
232+ // Generate deploy paths
233+ std::map<std::string, std::string> mimeTypeIconsTargetPaths;
234+ for (const auto & path: mimeTypeIconPaths)
235+ mimeTypeIconsTargetPaths[path] = generateMimeTypeIconDeployPath (path).string ();
236+
237+ resourcesExtractor.extractTo (mimeTypeIconsTargetPaths);
238+ }
239+
240+ /* *
241+ * Append vendor prefix and appImage id to the file names to identify the appImage that owns
242+ * this file. Replace the default XDG_DATA_DIR by the one at <xdgDataHome>
243+ *
244+ * @param path resource path
245+ * @return path with a prefixed file name
246+ */
247+ bf::path generateMimeTypeIconDeployPath (bf::path path) const {
248+ // add appImage resource identification prefix to the filename
249+ std::stringstream fileNameBuilder;
250+ fileNameBuilder << path.stem () << " -" << VENDOR_PREFIX << " -" << appImageId << path.extension ();
251+
252+ // build the relative parent path ignoring the default XDG_DATA_DIR prefix ("usr/share")
253+ path.remove_filename ();
254+ bf::path relativeParentPath;
255+ const bf::path defaultXdgDataDirPath = " usr/share" ;
256+
257+ for (const auto & itr : path) {
258+ relativeParentPath /= itr;
259+
260+ if (relativeParentPath == defaultXdgDataDirPath)
261+ relativeParentPath.clear ();
262+ }
263+
264+ bf::path newPath = xdgDataHome / relativeParentPath / fileNameBuilder.str ();
265+ return newPath;
266+ }
267+
195268 /* *
196269 * Deploy <iconData> as the main application icon to
197- * XDG_DATA_HOME/icons/hicolor/<size>/apps /<vendorPrefix>_<appImageId>_<iconName>.<format extension>
270+ * XDG_DATA_HOME/icons/hicolor/<size>/<iconGroup> /<vendorPrefix>_<appImageId>_<iconName>.<format extension>
198271 *
199- * size: actual icon dimenzions , in case of vectorial image "scalable" is used
272+ * size: actual icon dimensions , in case of vectorial image "scalable" is used
200273 * format extension: in case of vectorial image "svg" otherwise "png"
201274 *
275+ * @param iconGroup
202276 * @param iconName
203277 * @param iconData
204278 */
205- void deployApplicationIcon (const std::string& iconName, std::vector<char >& iconData) const {
279+ void deployIcon (const std::string& iconGroup, const std::string& iconName,
280+ std::vector<char >& iconData) const {
206281 try {
207282 IconHandle icon (iconData);
208283
@@ -224,14 +299,14 @@ namespace appimage {
224299 iconPath /= (iconSize + " x" + iconSize);
225300 }
226301
227- iconPath /= " apps " ;
302+ iconPath /= iconGroup ;
228303 iconPath /= iconNameBuilder.str ();
229304
230305 auto deployPath = generateDeployPath (iconPath);
231306 icon.save (deployPath.string (), icon.format ());
232- } catch (const IconHandleError& er ) {
233- Logger::error (er. what ());
234- Logger::error ( " No icon was generated for: " + appImage.getPath ());
307+ } catch (const IconHandleError& error ) {
308+ Logger::error (" Icon deploy failed " + iconGroup + " / " + iconName
309+ + " from " + appImage.getPath () + " : " + error. what ());
235310 }
236311 }
237312
0 commit comments