Added a version check for the skins which come with Rainmeter so they can be upgraded.

This commit is contained in:
Kimmo Pekkola 2009-09-18 18:42:50 +00:00
parent 1de7706678
commit fa6d437a71
3 changed files with 129 additions and 7 deletions

View File

@ -51,11 +51,12 @@ public:
std::wstring& GetFilename() { return m_Filename; }
std::vector<std::wstring> GetSections();
static std::vector<std::wstring> Tokenize(const std::wstring& str, const std::wstring delimiters);
private:
void ReadVariables();
void ReplaceVariables(std::wstring& result);
Gdiplus::Color ParseColor(LPCTSTR string);
std::vector<std::wstring> Tokenize(const std::wstring& str, const std::wstring delimiters);
void ReadIniFile(const std::wstring& strFileName, int depth = 0);
void SetValue(const std::wstring& strSection, const std::wstring& strKey, const std::wstring& strValue);

View File

@ -30,6 +30,7 @@
#include <commctrl.h>
#include <gdiplus.h>
#include <fstream>
#include <iostream>
#include <shlobj.h>
using namespace Gdiplus;
@ -840,6 +841,12 @@ int CRainmeter::Initialize(HWND Parent, HINSTANCE Instance, LPCSTR szPath)
// Test that the Rainmeter.ini file is writable
TestSettingsFile(bDefaultIniLocation);
// If the skin folder is somewhere else than in the program path
if (wcsnicmp(m_Path.c_str(), m_SkinPath.c_str(), m_Path.size()) != 0)
{
CheckSkinVersions();
}
// Tray must exist before configs are read
m_TrayWindow = new CTrayWindow(m_Instance);
@ -920,6 +927,115 @@ int CRainmeter::Initialize(HWND Parent, HINSTANCE Instance, LPCSTR szPath)
return Result; // Alles OK
}
/*
** CheckSkinVersions
**
** Checks if any of the skins in the program folder are newer than in the skin folder.
**
*/
void CRainmeter::CheckSkinVersions()
{
// List all skins in the program folder
std::wstring strMainSkinsPath = m_Path + L"Skins\\";
std::vector<CONFIGMENU> menu;
ScanForConfigsRecursive(strMainSkinsPath, L"", 0, menu, true);
for (size_t i = 0; i < menu.size(); i++)
{
// DebugLog(L"%s", menu[i].name.c_str());
// Read the version files
std::wstring strNewVersionFile = strMainSkinsPath + menu[i].name + L"\\version";
std::wstring strCurrentVersionFile = m_SkinPath + menu[i].name + L"\\version";
std::string strVersion;
std::wstring strVersionNew;
std::wstring strVersionCurrent;
std::wstring strVersionInIni;
std::ifstream newFile(strNewVersionFile.c_str(), std::ios_base::in);
if (getline(newFile, strVersion))
{
strVersionNew = ConvertToWide(strVersion.c_str());
// DebugLog(L"New: %s", strVersionNew.c_str());
// Compare with the version entry in the Rainmeter.ini
WCHAR tmpSz[MAX_LINE_LENGTH] = {0};
GetPrivateProfileString(menu[i].name.c_str(), L"Version", L"", tmpSz, MAX_LINE_LENGTH, m_IniFile.c_str());
strVersionInIni = tmpSz;
// DebugLog(L"In Ini: %s", strVersionInIni.c_str());
// Compare with the version file in the skin folder
std::ifstream currentFile(strCurrentVersionFile.c_str(), std::ios_base::in);
if (getline(currentFile, strVersion))
{
strVersionCurrent = ConvertToWide(strVersion.c_str());
// DebugLog(L"Current: %s", strVersionCurrent.c_str());
}
}
// If the skin doesn't define a version file no need to do anything
if (!strVersionNew.empty())
{
// Compare the version files
if (CompareVersions(strVersionNew, strVersionInIni) == 1 &&
CompareVersions(strVersionNew, strVersionCurrent) == 1)
{
std::wstring strMessage = L"The config called \"" + menu[i].name + L"\" is newer\nthan the one you are currently using.\n\n";
strMessage += L"New config: " + (strVersionNew.empty() ? L"Unknown" : strVersionNew) + L"\n";
strMessage += L"Current config: " + (strVersionCurrent.empty() ? L"Unknown" : strVersionCurrent) + L"\n";
strMessage += L"\n";
strMessage += L"Do you want to upgrade it?";
if (IDYES == MessageBox(NULL, strMessage.c_str(), APPNAME, MB_YESNO | MB_ICONQUESTION))
{
// Upgrade the skin by overwriting the existing skin.
CopyFiles(strMainSkinsPath + menu[i].name, m_SkinPath);
}
// Even if the user doesn't want to upgrade mark it to the Rainmeter.ini so we don't ask the upgrade question again
WritePrivateProfileString(menu[i].name.c_str(), L"Version", strVersionNew.c_str(), m_IniFile.c_str());
}
}
}
}
/*
** CompareVersions
**
** Compares two version strings. Returns 0 if they are equal, 1 if A > B and -1 if A < B.
**
*/
int CRainmeter::CompareVersions(std::wstring strA, std::wstring strB)
{
if (strA.empty() && strB.empty()) return 0;
if (strA.empty()) return -1;
if (strB.empty()) return 1;
std::vector<std::wstring> arrayA = CConfigParser::Tokenize(strA, L".");
std::vector<std::wstring> arrayB = CConfigParser::Tokenize(strB, L".");
size_t len = max(arrayA.size(), arrayB.size());
for (size_t i = 0; i < len; i++)
{
int a = 0;
int b = 0;
if (i < arrayA.size())
{
a = _wtoi(arrayA[i].c_str());
}
if (i < arrayB.size())
{
b = _wtoi(arrayB[i].c_str());
}
if (a > b) return 1;
if (a < b) return -1;
}
return 0;
}
/*
** CopyFiles
@ -939,7 +1055,7 @@ void CRainmeter::CopyFiles(std::wstring strFrom, std::wstring strTo)
fo.wFunc = FO_COPY;
fo.pFrom = strFrom.c_str();
fo.pTo = strTo.c_str();
fo.fFlags = FOF_NO_UI;
fo.fFlags = FOF_NO_UI | FOF_NOCONFIRMATION | FOF_ALLOWUNDO;
int result = SHFileOperation(&fo);
if (result != 0)
@ -1157,10 +1273,10 @@ void CRainmeter::ScanForConfigs(std::wstring& path)
m_ConfigStrings.clear();
m_ConfigMenu.clear();
ScanForConfigsRecursive(path, L"", 0, m_ConfigMenu);
ScanForConfigsRecursive(path, L"", 0, m_ConfigMenu, false);
}
int CRainmeter::ScanForConfigsRecursive(std::wstring& path, std::wstring base, int index, std::vector<CONFIGMENU>& menu)
int CRainmeter::ScanForConfigsRecursive(std::wstring& path, std::wstring base, int index, std::vector<CONFIGMENU>& menu, bool DontRecurse)
{
WIN32_FIND_DATA fileData; // Data structure describes the file found
WIN32_FIND_DATA fileDataIni; // Data structure describes the file found
@ -1220,8 +1336,11 @@ int CRainmeter::ScanForConfigsRecursive(std::wstring& path, std::wstring base, i
menuItem.index = -1;
menu.push_back(menuItem);
std::vector<CONFIGMENU>::iterator iter = menu.end() - 1;
index = ScanForConfigsRecursive(path, base + fileData.cFileName, index, (*iter).children);
if (!DontRecurse)
{
std::vector<CONFIGMENU>::iterator iter = menu.end() - 1;
index = ScanForConfigsRecursive(path, base + fileData.cFileName, index, (*iter).children, false);
}
}
} while(FindNextFile(hSearch, &fileData));

View File

@ -175,12 +175,14 @@ private:
void Refresh(const WCHAR* arg);
HMENU CreateSkinMenu(CMeterWindow* meterWindow, int index);
void ChangeSkinIndex(HMENU subMenu, int index);
int ScanForConfigsRecursive(std::wstring& path, std::wstring base, int index, std::vector<CONFIGMENU>& menu);
int ScanForConfigsRecursive(std::wstring& path, std::wstring base, int index, std::vector<CONFIGMENU>& menu, bool DontRecurse);
HMENU CreateConfigMenu(std::vector<CONFIGMENU>& configMenuData);
HMENU CreateThemeMenu();
void CreateDefaultConfigFile(std::wstring strFile);
void TestSettingsFile(bool bDefaultIniLocation);
void CopyFiles(std::wstring strFrom, std::wstring strTo);
void CheckSkinVersions();
int CompareVersions(std::wstring strA, std::wstring strB);
CTrayWindow* m_TrayWindow;