mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
Bazaar/Updater : added Windows shell install -- still unbuilt
git-svn-id: svn://ultimatepp.org/upp/trunk@3024 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
16cc1bc8d1
commit
643081eb12
5 changed files with 290 additions and 143 deletions
138
bazaar/Updater/Posix.cpp
Normal file
138
bazaar/Updater/Posix.cpp
Normal file
|
|
@ -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
|
||||
Vector<String>Updater::ScanTheme(void)
|
||||
{
|
||||
// gathers all subfolders of /usr/share/icons that contains 32x32 subfolder
|
||||
Vector<String>subFolders;
|
||||
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)
|
||||
{
|
||||
Vector<String>folders = 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)
|
||||
{
|
||||
Vector<String>folders = 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 =
|
||||
"<?xml version=\"1.0\"?>\n"
|
||||
"<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>\n"
|
||||
"<mime-type type=\"application/x-" + appName + "\">\n";
|
||||
if(comment != "")
|
||||
mime += "<comment>" + comment + "</comment>\n";
|
||||
for(int i = 0; i < extensions.GetCount(); i++)
|
||||
mime += "<glob pattern=\"" + extensions[i] + "\"/>\n";
|
||||
mime +=
|
||||
"</mime-type>\n"
|
||||
"</mime-info>\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
|
||||
|
|
@ -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
|
||||
Vector<String>Updater::ScanTheme(void)
|
||||
{
|
||||
// gathers all subfolders of /usr/share/icons that contains 32x32 subfolder
|
||||
Vector<String>subFolders;
|
||||
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)
|
||||
{
|
||||
Vector<String>folders = 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)
|
||||
{
|
||||
Vector<String>folders = 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 =
|
||||
"<?xml version=\"1.0\"?>\n"
|
||||
"<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>\n"
|
||||
"<mime-type type=\"application/x-" + appName + "\">\n";
|
||||
if(comment != "")
|
||||
mime += "<comment>" + comment + "</comment>\n";
|
||||
for(int i = 0; i < extensions.GetCount(); i++)
|
||||
mime += "<glob pattern=\"" + extensions[i] + "\"/>\n";
|
||||
mime +=
|
||||
"</mime-type>\n"
|
||||
"</mime-info>\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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -162,6 +162,10 @@ class Updater
|
|||
Vector<String> 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; }
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ uses
|
|||
|
||||
file
|
||||
Updater.iml,
|
||||
Windows.cpp,
|
||||
Posix.cpp,
|
||||
Updater.h,
|
||||
Updater.cpp;
|
||||
|
||||
|
|
|
|||
138
bazaar/Updater/Windows.cpp
Normal file
138
bazaar/Updater/Windows.cpp
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
#include "Updater.h"
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
|
||||
|
||||
#define Ptr Ptr_
|
||||
#define byte byte_
|
||||
#define CY win32_CY_
|
||||
|
||||
|
||||
#include <winnls.h>
|
||||
#include <winnetwk.h>
|
||||
|
||||
#include <wincon.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
#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
|
||||
Loading…
Add table
Add a link
Reference in a new issue