diff --git a/bazaar/Updater/Posix.cpp b/bazaar/Updater/Posix.cpp new file mode 100644 index 000000000..c7f768723 --- /dev/null +++ b/bazaar/Updater/Posix.cpp @@ -0,0 +1,138 @@ +#include "Updater.h" + +#ifdef PLATFORM_POSIX + +// scans for theme folders on which put/delete the mimetype icons +// that's needed because if themed icons aren't available, the system +// uses fallback ones instead of going through hicolor ones +// btw...that must be some ill-brained people there +// the routine builds a list of folders containing 32x32 icons +// it would be of course better with svg, but Upp don't support them +VectorUpdater::ScanTheme(void) +{ + // gathers all subfolders of /usr/share/icons that contains 32x32 subfolder + VectorsubFolders; + FindFile ff("/usr/share/icons/*"); + while(ff) + { + if( + ff.IsFolder() && + ff.GetName() != "." && + ff.GetName() != ".." && + DirectoryExists("/usr/share/icons/" + ff.GetName() + "/32x32/") + ) + subFolders.Add("/usr/share/icons/" + ff.GetName() + "/"); + ff.Next(); + } + return subFolders; +} + +// save an image as png inside multiple theme folders +// retrieved with ScanTheme +void Updater::InstallThemeIcons(Image const &img, String const &name) +{ + Vectorfolders = ScanTheme(); + String imgs = PNGEncoder().SaveString(img); + for(int i = 0; i < folders.GetCount(); i++) + { + SaveFile(folders[i] + "32x32/mimetypes/" + name + ".png", imgs); + SysStart("gtk-update-icon-cache", "--quiet " + folders[i]); + } +} + +// deletes all icons with given name inside folders retrieved with ScanTheme +void Updater::RemoveThemeIcons(String const &name) +{ + Vectorfolders = ScanTheme(); + for(int i = 0; i < folders.GetCount(); i++) + { + FileDelete(folders[i] + "32x32/mimetypes/" + name + ".png"); + SysStart("gtk-update-icon-cache", "--quiet " + folders[i]); + } +} + +// links application to OS shell +// (i.e., add icon, menu entry, mimetype....) +bool Updater::ShellLink(void) +{ + bool success = true; + + // build desktop file + String desktop = + "[Desktop Entry]\n" + "Type=Application\n" + "Encoding=UTF-8\n" + ; + desktop += "Name=" + appName + "\n"; + if(comment != "") + desktop += "Comment=" + comment + "\n"; + if(cathegory != "") + desktop += "Categories=" + cathegory + "\n"; + desktop += "Exec=" + appName + " %f\n"; + if(!IsNull(icon)) + desktop += "Icon=" + appName + "\n"; + desktop += "MimeType=application/x-" + appName + ";\n"; + desktop += "Terminal=false\n"; + + // stores desktop file in global applications folder + success = SaveFile("/usr/share/applications/" + appName + ".desktop", desktop); + + // places icon in /usr/share/icons/hicolor/32x32/apps + // maybe we should look for some better handling of icons... + // by now, we support only 32x32 ones in default theme + if(!IsNull(icon)) + { + success &= PNGEncoder().SaveFile("/usr/share/icons/hicolor/32x32/apps/" + appName + ".png", icon); + InstallThemeIcons(icon, "application-x-" + appName); + } + + // add mime type for supported extensions + String mime = + "\n" + "\n" + "\n"; + if(comment != "") + mime += "" + comment + "\n"; + for(int i = 0; i < extensions.GetCount(); i++) + mime += "\n"; + mime += + "\n" + "\n" + ; + success &= SaveFile("/usr/share/mime/packages/" + appName + ".xml", mime); + success &= (SysStart("update-mime-database", "/usr/share/mime") != -1); + + // updates desktop database to make it sense the changes in mimetype and application + success &= (SysStart("update-desktop-database", "") != -1); + + return success; +} + +// unlinks application +bool Updater::ShellUnlink(void) +{ + bool success = true; + + // remove desktop file + FileDelete("/usr/share/applications/" + appName + ".desktop"); + + // remove icon + bool appIcon = FileExists("/usr/share/icons/hicolor/32x32/apps/" + appName + ".png"); + if(appIcon) + FileDelete("/usr/share/icons/hicolor/32x32/apps/" + appName + ".png"); + RemoveThemeIcons("application-x-" + appName); + + if(FileExists("/usr/share/mime/packages/" + appName + ".xml")) + { + FileDelete("/usr/share/mime/packages/" + appName + ".xml"); + SysStart("update-mime-database", "/usr/share/mime"); + } + + // updates desktop database to make it sense the changes in mimetype and application + SysStart("update-desktop-database", ""); + + return success; +} + + +#endif diff --git a/bazaar/Updater/Updater.cpp b/bazaar/Updater/Updater.cpp index ef7e5db58..93c066d35 100644 --- a/bazaar/Updater/Updater.cpp +++ b/bazaar/Updater/Updater.cpp @@ -116,6 +116,9 @@ Updater::Updater() // sets default confirm for install and uninstall confirmInstall = true; confirmUninstall = true; + + // no desktop icon installation by default + desktopIcon = false; } /////////////////////////////////////////////////////////////////////////////////////// @@ -718,146 +721,3 @@ Image Updater::DefaultIcon(void) { return UpdaterImg::DefaultIcon(); } - -// scans for theme folders on which put/delete the mimetype icons -// that's needed because if themed icons aren't available, the system -// uses fallback ones instead of going through hicolor ones -// btw...that must be some ill-brained people there -// the routine builds a list of folders containing 32x32 icons -// it would be of course better with svg, but Upp don't support them -VectorUpdater::ScanTheme(void) -{ - // gathers all subfolders of /usr/share/icons that contains 32x32 subfolder - VectorsubFolders; - FindFile ff("/usr/share/icons/*"); - while(ff) - { - if( - ff.IsFolder() && - ff.GetName() != "." && - ff.GetName() != ".." && - DirectoryExists("/usr/share/icons/" + ff.GetName() + "/32x32/") - ) - subFolders.Add("/usr/share/icons/" + ff.GetName() + "/"); - ff.Next(); - } - return subFolders; -} - -// save an image as png inside multiple theme folders -// retrieved with ScanTheme -void Updater::InstallThemeIcons(Image const &img, String const &name) -{ - Vectorfolders = ScanTheme(); - String imgs = PNGEncoder().SaveString(img); - for(int i = 0; i < folders.GetCount(); i++) - { - SaveFile(folders[i] + "32x32/mimetypes/" + name + ".png", imgs); - SysStart("gtk-update-icon-cache", "--quiet " + folders[i]); - } -} - -// deletes all icons with given name inside folders retrieved with ScanTheme -void Updater::RemoveThemeIcons(String const &name) -{ - Vectorfolders = ScanTheme(); - for(int i = 0; i < folders.GetCount(); i++) - { - FileDelete(folders[i] + "32x32/mimetypes/" + name + ".png"); - SysStart("gtk-update-icon-cache", "--quiet " + folders[i]); - } -} - -// links application to OS shell -// (i.e., add icon, menu entry, mimetype....) -bool Updater::ShellLink(void) -{ - bool success = true; - -#ifdef PLATFORM_POSIX - - // build desktop file - String desktop = - "[Desktop Entry]\n" - "Type=Application\n" - "Encoding=UTF-8\n" - ; - desktop += "Name=" + appName + "\n"; - if(comment != "") - desktop += "Comment=" + comment + "\n"; - if(cathegory != "") - desktop += "Categories=" + cathegory + "\n"; - desktop += "Exec=" + appName + " %f\n"; - if(!IsNull(icon)) - desktop += "Icon=" + appName + "\n"; - desktop += "MimeType=application/x-" + appName + ";\n"; - desktop += "Terminal=false\n"; - - // stores desktop file in global applications folder - success = SaveFile("/usr/share/applications/" + appName + ".desktop", desktop); - - // places icon in /usr/share/icons/hicolor/32x32/apps - // maybe we should look for some better handling of icons... - // by now, we support only 32x32 ones in default theme - if(!IsNull(icon)) - { - success &= PNGEncoder().SaveFile("/usr/share/icons/hicolor/32x32/apps/" + appName + ".png", icon); - InstallThemeIcons(icon, "application-x-" + appName); - } - - // add mime type for supported extensions - String mime = - "\n" - "\n" - "\n"; - if(comment != "") - mime += "" + comment + "\n"; - for(int i = 0; i < extensions.GetCount(); i++) - mime += "\n"; - mime += - "\n" - "\n" - ; - success &= SaveFile("/usr/share/mime/packages/" + appName + ".xml", mime); - success &= (SysStart("update-mime-database", "/usr/share/mime") != -1); - - // updates desktop database to make it sense the changes in mimetype and application - success &= (SysStart("update-desktop-database", "") != -1); - -#else -#endif - - return success; -} - -// unlinks application -bool Updater::ShellUnlink(void) -{ - bool success = true; - -#ifdef PLATFORM_POSIX - - // remove desktop file - FileDelete("/usr/share/applications/" + appName + ".desktop"); - - // remove icon - bool appIcon = FileExists("/usr/share/icons/hicolor/32x32/apps/" + appName + ".png"); - if(appIcon) - FileDelete("/usr/share/icons/hicolor/32x32/apps/" + appName + ".png"); - RemoveThemeIcons("application-x-" + appName); - - if(FileExists("/usr/share/mime/packages/" + appName + ".xml")) - { - FileDelete("/usr/share/mime/packages/" + appName + ".xml"); - SysStart("update-mime-database", "/usr/share/mime"); - } - - // updates desktop database to make it sense the changes in mimetype and application - SysStart("update-desktop-database", ""); - -#else -#endif - - return success; -} - diff --git a/bazaar/Updater/Updater.h b/bazaar/Updater/Updater.h index bdac076ec..23864fd23 100644 --- a/bazaar/Updater/Updater.h +++ b/bazaar/Updater/Updater.h @@ -162,6 +162,10 @@ class Updater Vector extensions; String comment; + // flag for desktop icon install + bool desktopIcon; + +#ifdef PLATFORM_POSIX // scans for theme folders on which put/delete the mimetype icons // that's needed because if themed icons aren't available, the system // uses fallback ones instead of going through hicolor ones @@ -176,6 +180,7 @@ class Updater // deletes all icons with given name inside folders retrieved with ScanTheme void RemoveThemeIcons(String const &name); +#endif // links application to OS shell // (i.e., add icon, menu entry, mimetype....) @@ -247,6 +252,10 @@ class Updater // setup application comment Updater &SetComment(String const &c) { comment = c; return *this; } + + // desktop icon + Updater &DesktopIcon(void) { desktopIcon = true; return *this; } + Updater &NoDesktopIcon(void) { desktopIcon = false; return *this; } }; diff --git a/bazaar/Updater/Updater.upp b/bazaar/Updater/Updater.upp index 84c9ec509..a399322fd 100644 --- a/bazaar/Updater/Updater.upp +++ b/bazaar/Updater/Updater.upp @@ -7,6 +7,8 @@ uses file Updater.iml, + Windows.cpp, + Posix.cpp, Updater.h, Updater.cpp; diff --git a/bazaar/Updater/Windows.cpp b/bazaar/Updater/Windows.cpp new file mode 100644 index 000000000..1d5947404 --- /dev/null +++ b/bazaar/Updater/Windows.cpp @@ -0,0 +1,138 @@ +#include "Updater.h" + +#ifdef PLATFORM_WIN32 + + +#define Ptr Ptr_ +#define byte byte_ +#define CY win32_CY_ + + +#include +#include + +#include +#include + +#undef Ptr +#undef byte +#undef CY + + +// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ò + +String GetShellFolder(const char *name, HKEY type) +{ + return GetWinRegString(name, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", type); +} + +void DelKey(const char *dir, const char *key) +{ + HKEY hkey; + if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &hkey) != ERROR_SUCCESS) + return; + RegDeleteKey(hkey, key); + RegCloseKey(hkey); +} + +bool CreateShellLink(const char *filepath, const char *linkpath, const char *desc, int icon) +{ + HRESULT hres; + IShellLink* psl; + IPersistFile* ppf; + CoInitialize(NULL); + hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (PVOID *) &psl); + if(SUCCEEDED(hres)) + { + psl->SetPath(filepath); + psl->SetDescription(desc); + if(icon >= 0) + psl->SetIconLocation(filepath, icon); + hres = psl->QueryInterface(IID_IPersistFile, (PVOID *) &ppf); + if (SUCCEEDED(hres)) + { + WCHAR szPath[_MAX_PATH] = { 0 }; + MultiByteToWideChar(CP_ACP, 0, linkpath, (int)strlen(linkpath), szPath, _MAX_PATH); + hres = ppf->Save(szPath, TRUE); + ppf->Release(); + } + } + psl->Release(); + CoUninitialize(); + return SUCCEEDED(hres); +} + +// links application to OS shell +// (i.e., add icon, menu entry, mimetype....) +bool Updater::ShellLink(void) +{ + bool success = true; + + String exePath = GetProgramsFolder() + "/" + appName + "/" + appName + ".exe"; + String linkName = appName + ".lnk"; + + // installs desktop icon + if(desktopIcon) + { + String desktopPath = GetShellFolder("Desktop", HKEY_USERS); + CreateShellLink(exePath, AppendFileName(desktopPath, linkName), comment, -1); + } + + // installs program group + // we could use "cathegory" to create a menu group... but I don't + // know how internationalize it. On ubuntu is automatic. + // maybe we could add it later + String groupName = ""; // that could be GetLNGString(cathegory) ???? + String groupFolder = GetShellFolder("Common Programs", HKEY_LOCAL_MACHINE); + if(groupName != "") + { + groupFolder = AppendFileName(groupFolder, groupName); + CreateDirectory(groupFolder, NULL); + } + CreateShellLink(exePath, AppendFileName(groupFolder, linkName), comment, -1); + + // installs uninstaller + String uninstallRegPath = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + appName; + SetWinRegString(appName, "DisplayName", uninstallRegPath); + SetWinRegString(appName + " --UNINSTALL", "UninstallString", uninstallRegPath); + + return success; +} + +// unlinks application +bool Updater::ShellUnlink(void) +{ + bool success = true; + + String linkName = appName + ".lnk"; + + // remove uninstaller + DelKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + appName, "DisplayName"); + DelKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + appName, "UninstallString"); + DelKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", appName); + + // remove program group + String groupName = ""; // that could be GetLNGString(cathegory) ???? + String groupFolder = GetShellFolder("Common Programs", HKEY_LOCAL_MACHINE); + if(groupName != "") + { + groupFolder = AppendFileName(groupFolder, groupName); + if(PathExists(groupFolder)) + DeleteFolderDeep(groupFolder); + } + else + { + Strink linkPath = AppendFileName(groupFolder, linkName); + if(FileExists(linkPath)) + FileDelete(linkPath); + } + + // remove desktop icon + String desktopLink = AppendFileName(GetShellFolder("Desktop", HKEY_USERS), linkName); + if(FileExists(desktopLink)) + FileDelete(desktopLine); + + return success; +} + +#endif