committed by
Paul Licameli
14 changed files with 799 additions and 0 deletions
-
8CMakeLists.txt
-
1scripts/ci/configure.sh
-
5src/AudacityApp.cpp
-
5src/AudacityApp.h
-
16src/CMakeLists.txt
-
152src/update/UpdateDataParser.cpp
-
66src/update/UpdateDataParser.h
-
150src/update/UpdateManager.cpp
-
57src/update/UpdateManager.h
-
136src/update/UpdatePopupDialog.cpp
-
46src/update/UpdatePopupDialog.h
-
85src/update/VersionId.cpp
-
49src/update/VersionId.h
-
23src/update/VersionPatch.h
@ -0,0 +1,152 @@ |
|||
/*!********************************************************************
|
|||
Audacity: A Digital Audio Editor |
|||
|
|||
@file UpdateDataParser.cpp |
|||
@brief Declare a class that parse update server data format. |
|||
|
|||
Anton Gerasimov |
|||
**********************************************************************/ |
|||
|
|||
#include "UpdateDataParser.h"
|
|||
|
|||
#include "xml/XMLFileReader.h"
|
|||
|
|||
UpdateDataParser::UpdateDataParser() |
|||
{} |
|||
|
|||
UpdateDataParser::~UpdateDataParser() |
|||
{} |
|||
|
|||
bool UpdateDataParser::Parse(const VersionPatch::UpdateDataFormat& updateData, VersionPatch* versionPatch) |
|||
{ |
|||
XMLFileReader xmlReader; |
|||
|
|||
mVersionPatch = versionPatch; |
|||
auto ok = xmlReader.ParseString(this, updateData); |
|||
mVersionPatch = nullptr; |
|||
|
|||
return ok; |
|||
} |
|||
|
|||
wxArrayString UpdateDataParser::splitChangelogSentences(const wxString& changelogContent) |
|||
{ |
|||
wxArrayString changelogSentenceList; |
|||
|
|||
size_t pos = 0; |
|||
std::string s(changelogContent.ToStdString()); |
|||
std::string token; |
|||
const std::string delimiter(". "); |
|||
|
|||
while ((pos = s.find(delimiter)) != std::string::npos) |
|||
{ |
|||
token = s.substr(0, pos + 1); |
|||
changelogSentenceList.Add(token); |
|||
|
|||
s.erase(0, pos + delimiter.length()); |
|||
} |
|||
changelogSentenceList.Add(s); |
|||
|
|||
return changelogSentenceList; |
|||
} |
|||
|
|||
bool UpdateDataParser::HandleXMLTag(const wxChar* tag, const wxChar** attrs) |
|||
{ |
|||
if (wxStrcmp(tag, mXmlTagNames[XmlParsedTags::kDescriptionTag]) == 0) |
|||
{ |
|||
mXmlParsingState = XmlParsedTags::kDescriptionTag; |
|||
return true; |
|||
} |
|||
|
|||
if (wxStrcmp(tag, mXmlTagNames[XmlParsedTags::kWindowsTag]) == 0) |
|||
{ |
|||
if (wxPlatformInfo::Get().GetOperatingSystemId() & wxOS_WINDOWS) |
|||
mXmlParsingState = XmlParsedTags::kOsTag; |
|||
return true; |
|||
} |
|||
|
|||
if (wxStrcmp(tag, mXmlTagNames[XmlParsedTags::kMacosTag]) == 0) |
|||
{ |
|||
if (wxPlatformInfo::Get().GetOperatingSystemId() & wxOS_MAC) |
|||
mXmlParsingState = XmlParsedTags::kOsTag; |
|||
return true; |
|||
} |
|||
|
|||
if (wxStrcmp(tag, mXmlTagNames[XmlParsedTags::kLinuxTag]) == 0) |
|||
{ |
|||
if (wxPlatformInfo::Get().GetOperatingSystemId() & wxOS_UNIX_LINUX) |
|||
mXmlParsingState = XmlParsedTags::kOsTag; |
|||
return true; |
|||
} |
|||
|
|||
if (wxStrcmp(tag, mXmlTagNames[XmlParsedTags::kVersionTag]) == 0) |
|||
{ |
|||
if (mXmlParsingState == XmlParsedTags::kOsTag) |
|||
mXmlParsingState = XmlParsedTags::kVersionTag; |
|||
return true; |
|||
} |
|||
|
|||
if (wxStrcmp(tag, mXmlTagNames[XmlParsedTags::kLinkTag]) == 0) |
|||
{ |
|||
if (mXmlParsingState == XmlParsedTags::kOsTag) |
|||
mXmlParsingState = XmlParsedTags::kLinkTag; |
|||
return true; |
|||
} |
|||
|
|||
for (auto& xmlTag : mXmlTagNames) |
|||
{ |
|||
if (wxStrcmp(tag, xmlTag.second) == 0) |
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
void UpdateDataParser::HandleXMLEndTag(const wxChar* tag) |
|||
{ |
|||
if (mXmlParsingState == XmlParsedTags::kDescriptionTag || |
|||
mXmlParsingState == XmlParsedTags::kLinkTag) |
|||
mXmlParsingState = XmlParsedTags::kNotUsedTag; |
|||
|
|||
if (mXmlParsingState == XmlParsedTags::kVersionTag) |
|||
mXmlParsingState = XmlParsedTags::kOsTag; |
|||
} |
|||
|
|||
void UpdateDataParser::HandleXMLContent(const wxString& content) |
|||
{ |
|||
if (mVersionPatch == nullptr) |
|||
return; |
|||
|
|||
wxString trimedContent(content); |
|||
|
|||
switch (mXmlParsingState) |
|||
{ |
|||
case XmlParsedTags::kDescriptionTag: |
|||
trimedContent.Trim(true).Trim(false); |
|||
mVersionPatch->changelog = splitChangelogSentences(trimedContent); |
|||
break; |
|||
|
|||
case XmlParsedTags::kVersionTag: |
|||
trimedContent.Trim(true).Trim(false); |
|||
mVersionPatch->version = VersionId::ParseFromString(trimedContent); |
|||
break; |
|||
|
|||
case XmlParsedTags::kLinkTag: |
|||
trimedContent.Trim(true).Trim(false); |
|||
mVersionPatch->download = trimedContent; |
|||
break; |
|||
|
|||
default: |
|||
break; |
|||
} |
|||
} |
|||
|
|||
XMLTagHandler* UpdateDataParser::HandleXMLChild(const wxChar* tag) |
|||
{ |
|||
for (auto& xmlTag : mXmlTagNames) |
|||
{ |
|||
if (wxStrcmp(tag, xmlTag.second) == 0) |
|||
return this; |
|||
} |
|||
|
|||
return NULL; |
|||
} |
@ -0,0 +1,66 @@ |
|||
/*!******************************************************************** |
|||
Audacity: A Digital Audio Editor |
|||
|
|||
@file UpdateDataParser.h |
|||
@brief Declare a class that parse update server data format. |
|||
|
|||
Anton Gerasimov |
|||
**********************************************************************/ |
|||
#pragma once |
|||
|
|||
#include "VersionPatch.h" |
|||
|
|||
#include "xml/XMLTagHandler.h" |
|||
|
|||
#include <wx/arrstr.h> |
|||
#include <map> |
|||
|
|||
/// A class that parse update server data format. |
|||
class UpdateDataParser final : public XMLTagHandler |
|||
{ |
|||
public: |
|||
UpdateDataParser(); |
|||
~UpdateDataParser(); |
|||
|
|||
/// <summary> |
|||
/// Parsing from update data format to VersionPatch fields. |
|||
/// </summary> |
|||
/// <param name="updateData">Input data.</param> |
|||
/// <param name="versionPatch">Parsed output data.</param> |
|||
/// <returns>True if success.</returns> |
|||
bool Parse(const VersionPatch::UpdateDataFormat& updateData, VersionPatch* versionPatch); |
|||
|
|||
private: |
|||
enum class XmlParsedTags : int { |
|||
kNotUsedTag, |
|||
kUpdateTag, |
|||
kDescriptionTag, |
|||
kOsTag, |
|||
kWindowsTag, |
|||
kMacosTag, |
|||
kLinuxTag, |
|||
kVersionTag, |
|||
kLinkTag |
|||
}; |
|||
XmlParsedTags mXmlParsingState{ XmlParsedTags::kNotUsedTag }; |
|||
|
|||
std::map<XmlParsedTags, wxString> mXmlTagNames{ |
|||
{ XmlParsedTags::kUpdateTag, wxT("Updates") }, |
|||
{ XmlParsedTags::kDescriptionTag, wxT("Description") }, |
|||
{ XmlParsedTags::kOsTag, wxT("OS") }, |
|||
{ XmlParsedTags::kWindowsTag, wxT("Windows") }, |
|||
{ XmlParsedTags::kMacosTag, wxT("Macos") }, |
|||
{ XmlParsedTags::kLinuxTag, wxT("Linux") }, |
|||
{ XmlParsedTags::kVersionTag, wxT("Version") }, |
|||
{ XmlParsedTags::kLinkTag, wxT("Link") }, |
|||
}; |
|||
|
|||
bool HandleXMLTag(const wxChar* tag, const wxChar** attrs) override; |
|||
void HandleXMLEndTag(const wxChar* tag) override; |
|||
void HandleXMLContent(const wxString& content) override; |
|||
XMLTagHandler* HandleXMLChild(const wxChar* tag) override; |
|||
|
|||
wxArrayString splitChangelogSentences(const wxString& changelogContent); |
|||
|
|||
VersionPatch* mVersionPatch{ nullptr }; |
|||
}; |
@ -0,0 +1,150 @@ |
|||
/*!********************************************************************
|
|||
Audacity: A Digital Audio Editor |
|||
|
|||
@file UpdateManager.cpp |
|||
@brief Declare a class that managing of updates. |
|||
|
|||
Anton Gerasimov |
|||
**********************************************************************/ |
|||
|
|||
#include "UpdateManager.h"
|
|||
#include "UpdatePopupDialog.h"
|
|||
|
|||
#include "NetworkManager.h"
|
|||
#include "IResponse.h"
|
|||
#include "Request.h"
|
|||
|
|||
#include "widgets/AudacityMessageBox.h"
|
|||
|
|||
#include <wx/platinfo.h>
|
|||
#include <wx/utils.h>
|
|||
|
|||
static const char* prefsUpdatePopupDialogShown = "/Update/UpdatePopupDialogShown"; |
|||
static const char* prefsUpdateScheduledTime = "/Update/UpdateScheduledTime"; |
|||
|
|||
enum { ID_TIMER = wxID_HIGHEST + 1 }; |
|||
|
|||
BEGIN_EVENT_TABLE(UpdateManager, wxEvtHandler) |
|||
EVT_TIMER(ID_TIMER, UpdateManager::OnTimer) |
|||
END_EVENT_TABLE() |
|||
|
|||
UpdateManager::UpdateManager(AudacityProject& project) |
|||
: mTrackingInterval( |
|||
std::chrono::milliseconds(std::chrono::hours(12)).count()) |
|||
{ |
|||
mParent = (wxWindow*)(&GetProjectFrame(project)); |
|||
wxASSERT(mParent); |
|||
|
|||
mTimer.SetOwner(this, ID_TIMER); |
|||
mTimer.StartOnce(); |
|||
} |
|||
|
|||
UpdateManager::~UpdateManager() |
|||
{ |
|||
mTimer.Stop(); |
|||
} |
|||
|
|||
void UpdateManager::enableTracking(bool enable) |
|||
{ |
|||
gPrefs->Write(prefsUpdatePopupDialogShown, enable); |
|||
gPrefs->Flush(); |
|||
} |
|||
|
|||
bool UpdateManager::isTrackingEnabled() |
|||
{ |
|||
return gPrefs->ReadBool(prefsUpdatePopupDialogShown, true); |
|||
} |
|||
|
|||
VersionPatch UpdateManager::getVersionPatch() const |
|||
{ |
|||
return mVersionPatch; |
|||
} |
|||
|
|||
void UpdateManager::getUpdates() |
|||
{ |
|||
audacity::network_manager::Request request("https://updates.audacityteam.org/feed/latest.xml"); |
|||
auto response = audacity::network_manager::NetworkManager::GetInstance().doGet(request); |
|||
|
|||
response->setRequestFinishedCallback([response, this](audacity::network_manager::IResponse*) { |
|||
|
|||
if (response->getError() != audacity::network_manager::NetworkError::NoError) |
|||
{ |
|||
AudacityMessageBox( |
|||
XO("Unable to connect to Audacity update server."), |
|||
XO("Error checking for update"), |
|||
wxOK | wxCENTRE, |
|||
NULL); |
|||
|
|||
return; |
|||
} |
|||
|
|||
if (!mUpdateDataParser.Parse(response->readAll<VersionPatch::UpdateDataFormat>(), &mVersionPatch)) |
|||
{ |
|||
AudacityMessageBox( |
|||
XO("Update data was corrupted."), |
|||
XO("Error checking for update"), |
|||
wxOK | wxCENTRE, |
|||
NULL); |
|||
|
|||
return; |
|||
} |
|||
|
|||
if (mVersionPatch.version > CurrentBuildVersion()) |
|||
{ |
|||
mParent->CallAfter([this] { |
|||
UpdatePopupDialog dlg(mParent, this); |
|||
const int code = dlg.ShowModal(); |
|||
|
|||
if (code == wxID_YES) |
|||
{ |
|||
if (!wxLaunchDefaultBrowser(mVersionPatch.download)) |
|||
{ |
|||
AudacityMessageBox( |
|||
XO("Can't open the Audacity download link."), |
|||
XO("Error downloading update"), |
|||
wxOK | wxCENTRE, |
|||
NULL); |
|||
|
|||
return; |
|||
} |
|||
} |
|||
}); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
void UpdateManager::OnTimer(wxTimerEvent& WXUNUSED(event)) |
|||
{ |
|||
if (isTrackingEnabled() && isTimeToUpdate()) |
|||
getUpdates(); |
|||
|
|||
mTimer.StartOnce(mTrackingInterval); |
|||
} |
|||
|
|||
bool UpdateManager::isTimeToUpdate() |
|||
{ |
|||
long long nextTrackingTime = std::stoll( |
|||
gPrefs->Read(prefsUpdateScheduledTime, "0").ToStdString()); |
|||
|
|||
// Get current time in milliseconds
|
|||
auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>( |
|||
std::chrono::system_clock::now()); |
|||
|
|||
auto currentTimeInMillisec = std::chrono::duration_cast<std::chrono::milliseconds>( |
|||
now_ms.time_since_epoch()).count(); |
|||
|
|||
// If next update time 0 or less then current time -> show update dialog,
|
|||
// else this condition allow us to avoid from duplicating update notifications.
|
|||
if (nextTrackingTime < currentTimeInMillisec) |
|||
{ |
|||
nextTrackingTime = currentTimeInMillisec + mTrackingInterval; |
|||
|
|||
gPrefs->Write(prefsUpdateScheduledTime, |
|||
wxString(std::to_string(nextTrackingTime))); |
|||
gPrefs->Flush(); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
@ -0,0 +1,57 @@ |
|||
/*!******************************************************************** |
|||
Audacity: A Digital Audio Editor |
|||
|
|||
@file UpdateManager.h |
|||
@brief Declare a class that managing of updates. |
|||
|
|||
Anton Gerasimov |
|||
**********************************************************************/ |
|||
#pragma once |
|||
|
|||
#include "VersionId.h" |
|||
#include "VersionPatch.h" |
|||
#include "UpdateDataParser.h" |
|||
|
|||
#include "Project.h" |
|||
#include "Prefs.h" |
|||
|
|||
#include <wx/string.h> |
|||
#include <wx/event.h> |
|||
#include <wx/timer.h> |
|||
|
|||
/// A class that managing of updates. |
|||
/** |
|||
Opt-in request and show update dialog by the scheduled time. |
|||
Have a built-in check that allows avoiding multiplying update notifications |
|||
when multiple Audacity windows are shown. |
|||
*/ |
|||
class UpdateManager final : public wxEvtHandler |
|||
{ |
|||
public: |
|||
UpdateManager(AudacityProject& project); |
|||
~UpdateManager(); |
|||
|
|||
void getUpdates(); |
|||
|
|||
void enableTracking(bool enable); |
|||
bool isTrackingEnabled(); |
|||
|
|||
VersionPatch getVersionPatch() const; |
|||
|
|||
private: |
|||
UpdateDataParser mUpdateDataParser; |
|||
VersionPatch mVersionPatch; |
|||
|
|||
wxWindow* mParent; |
|||
|
|||
wxTimer mTimer; |
|||
const int mTrackingInterval; |
|||
|
|||
void OnTimer(wxTimerEvent& event); |
|||
|
|||
/// Scheduling update time for avoiding multiplying update notifications. |
|||
bool isTimeToUpdate(); |
|||
|
|||
public: |
|||
DECLARE_EVENT_TABLE() |
|||
}; |
@ -0,0 +1,136 @@ |
|||
/*!********************************************************************
|
|||
Audacity: A Digital Audio Editor |
|||
|
|||
@file UpdatePopupDialog.cpp |
|||
@brief Define a dialog for notifying users about new version available. |
|||
|
|||
Anton Gerasimov |
|||
**********************************************************************/ |
|||
|
|||
#include "update/UpdatePopupDialog.h"
|
|||
|
|||
#include "ShuttleGui.h"
|
|||
#include "widgets/HelpSystem.h"
|
|||
|
|||
#include <wx/debug.h>
|
|||
#include <wx/sstream.h>
|
|||
#include <wx/txtstrm.h>
|
|||
|
|||
enum { DontShowID = wxID_HIGHEST + 1 }; |
|||
|
|||
BEGIN_EVENT_TABLE (UpdatePopupDialog, wxDialogWrapper) |
|||
EVT_BUTTON (wxID_YES, UpdatePopupDialog::OnUpdate) |
|||
EVT_BUTTON (wxID_NO, UpdatePopupDialog::OnSkip) |
|||
EVT_CHECKBOX (DontShowID, UpdatePopupDialog::OnDontShow) |
|||
END_EVENT_TABLE() |
|||
|
|||
IMPLEMENT_CLASS (UpdatePopupDialog, wxDialogWrapper) |
|||
|
|||
UpdatePopupDialog::UpdatePopupDialog (wxWindow* parent, UpdateManager* updateManager) |
|||
: wxDialogWrapper (parent, -1, XO ("Update Audacity"), |
|||
wxDefaultPosition, wxDefaultSize, |
|||
wxCAPTION), |
|||
mUpdateManager (updateManager) |
|||
{ |
|||
wxASSERT(mUpdateManager); |
|||
|
|||
ShuttleGui S (this, eIsCreating); |
|||
S.SetBorder (5); |
|||
S.StartVerticalLay (wxEXPAND, 1); |
|||
{ |
|||
S.AddWindow (AddHtmlContent (S.GetParent())); |
|||
|
|||
S.StartHorizontalLay (wxEXPAND, 0); |
|||
{ |
|||
S.SetBorder (5); |
|||
|
|||
S.Id (DontShowID).AddCheckBox ( |
|||
XO ("Don't show this again at start up"), !mUpdateManager->isTrackingEnabled()); |
|||
|
|||
S.Prop(1).AddSpace(1, 0, 1); |
|||
|
|||
S.Id (wxID_NO).AddButton (XO ("Skip")); |
|||
S.Id (wxID_YES).AddButton (XO ("Install update")); |
|||
|
|||
S.SetBorder (5); |
|||
} |
|||
S.EndHorizontalLay(); |
|||
} |
|||
S.EndVerticalLay(); |
|||
|
|||
Layout(); |
|||
Fit(); |
|||
Center(); |
|||
} |
|||
|
|||
UpdatePopupDialog::~UpdatePopupDialog() |
|||
{ |
|||
; |
|||
} |
|||
|
|||
void UpdatePopupDialog::OnUpdate (wxCommandEvent&) |
|||
{ |
|||
EndModal (wxID_YES); |
|||
} |
|||
|
|||
void UpdatePopupDialog::OnSkip (wxCommandEvent&) |
|||
{ |
|||
EndModal (wxID_NO); |
|||
} |
|||
|
|||
void UpdatePopupDialog::OnDontShow (wxCommandEvent& event) |
|||
{ |
|||
mUpdateManager->enableTracking(!event.IsChecked()); |
|||
} |
|||
|
|||
HtmlWindow* UpdatePopupDialog::AddHtmlContent (wxWindow* parent) |
|||
{ |
|||
wxStringOutputStream o; |
|||
wxTextOutputStream informationStr (o); |
|||
|
|||
static const auto title = XO("Audacity %s is available!") |
|||
.Format(mUpdateManager->getVersionPatch().version.getString()); |
|||
|
|||
informationStr |
|||
<< wxT("<html><body><h3>") |
|||
<< title.Translation() |
|||
<< wxT("</h3><h5>") |
|||
<< XO("Changelog") |
|||
<< wxT("</h5><p>"); |
|||
|
|||
informationStr << wxT("<ul>"); |
|||
for (auto& logLine : mUpdateManager->getVersionPatch().changelog) |
|||
{ |
|||
informationStr << wxT("<li>"); |
|||
// We won't to translate downloaded text.
|
|||
informationStr << logLine; |
|||
informationStr << wxT("</li>"); |
|||
} |
|||
informationStr << wxT("</ul></p>"); |
|||
|
|||
informationStr << wxT("<p>"); |
|||
informationStr << XO("<a href = \"https://github.com/audacity/audacity/releases\">Read more on GitHub</a>"); |
|||
informationStr << wxT("</p>"); |
|||
|
|||
informationStr << wxT("</body></html>"); |
|||
|
|||
HtmlWindow* html = safenew LinkingHtmlWindow (parent, -1, |
|||
wxDefaultPosition, |
|||
wxSize (500, -1), |
|||
wxHW_SCROLLBAR_AUTO | wxSUNKEN_BORDER); |
|||
|
|||
html->SetBorders (20); |
|||
html->SetPage (o.GetString()); |
|||
|
|||
wxHtmlContainerCell* cell = html->GetInternalRepresentation(); |
|||
|
|||
cell->Layout (500); |
|||
|
|||
const wxSize size = wxSize (500, cell->GetHeight()); |
|||
|
|||
html->SetMinSize (size); |
|||
html->SetMaxSize (size); |
|||
html->SetSize (size); |
|||
|
|||
return html; |
|||
} |
@ -0,0 +1,46 @@ |
|||
/*!******************************************************************** |
|||
Audacity: A Digital Audio Editor |
|||
|
|||
@file UpdatePopupDialog.h |
|||
@brief Define a dialog for notifying users about new version available. |
|||
|
|||
Anton Gerasimov |
|||
**********************************************************************/ |
|||
|
|||
#pragma once |
|||
|
|||
#include "widgets/wxPanelWrapper.h" |
|||
#include "wx/string.h" |
|||
|
|||
#include "Project.h" |
|||
|
|||
#include "update/UpdateManager.h" |
|||
|
|||
class HtmlWindow; |
|||
class wxWindow; |
|||
class AudacityProject; |
|||
class UpdateManager; |
|||
|
|||
/// Show dialog window with update information for the user. |
|||
/** |
|||
Support user action behaviors as skip, download a new version, |
|||
and a checkbox that does not allow tracking version again. |
|||
*/ |
|||
class UpdatePopupDialog final : public wxDialogWrapper |
|||
{ |
|||
DECLARE_DYNAMIC_CLASS (AboutDialog) |
|||
public: |
|||
explicit UpdatePopupDialog (wxWindow* parent, UpdateManager *updateManager); |
|||
virtual ~UpdatePopupDialog(); |
|||
|
|||
void OnUpdate (wxCommandEvent& event); |
|||
void OnSkip (wxCommandEvent& event); |
|||
void OnDontShow (wxCommandEvent& event); |
|||
|
|||
DECLARE_EVENT_TABLE() |
|||
|
|||
private: |
|||
HtmlWindow* AddHtmlContent (wxWindow* parent); |
|||
|
|||
UpdateManager* const mUpdateManager; |
|||
}; |
@ -0,0 +1,85 @@ |
|||
/*!********************************************************************
|
|||
Audacity: A Digital Audio Editor |
|||
|
|||
@file VersionId.h |
|||
@brief Declare a class with version number manipulation. |
|||
|
|||
Anton Gerasimov |
|||
**********************************************************************/ |
|||
#include "VersionId.h"
|
|||
|
|||
VersionId::VersionId(int version, int release, int revision) |
|||
: mVersion(version), |
|||
mRelease(release), |
|||
mRevision(revision) |
|||
{} |
|||
|
|||
wxString VersionId::MakeString(int version, int release, int revision) |
|||
{ |
|||
return std::to_string(version) |
|||
+ "." + std::to_string(release) |
|||
+ "." + std::to_string(revision); |
|||
} |
|||
|
|||
VersionId VersionId::ParseFromString(wxString& versionString) |
|||
{ |
|||
auto versionStringParts = wxSplit(versionString, '.'); |
|||
|
|||
// If we have corrupted version string,
|
|||
// then return the zero version number, that not allow us to update.
|
|||
if (versionStringParts.size() != 3) |
|||
return VersionId{}; |
|||
|
|||
for (auto& v : versionStringParts) |
|||
{ |
|||
if (v.empty() || !v.IsNumber()) |
|||
return VersionId{}; |
|||
} |
|||
|
|||
return VersionId( |
|||
std::stoi(versionStringParts[0].ToStdString()), |
|||
std::stoi(versionStringParts[1].ToStdString()), |
|||
std::stoi(versionStringParts[2].ToStdString()) |
|||
); |
|||
} |
|||
|
|||
wxString VersionId::getString() const |
|||
{ |
|||
return MakeString(mVersion, mRelease, mRevision); |
|||
} |
|||
|
|||
bool VersionId::operator== (const VersionId& other) |
|||
{ |
|||
return mVersion == other.mVersion && |
|||
mRelease == other.mRelease && |
|||
mRevision == other.mRevision; |
|||
} |
|||
|
|||
bool VersionId::operator!= (const VersionId& other) |
|||
{ |
|||
return !(*this == other); |
|||
} |
|||
|
|||
bool VersionId::operator< (const VersionId& other) |
|||
{ |
|||
if (mVersion < other.mVersion) |
|||
return true; |
|||
|
|||
if (mRelease < other.mRelease && |
|||
mVersion == other.mVersion) |
|||
return true; |
|||
|
|||
if (mRevision < other.mRevision && |
|||
mVersion == other.mVersion && |
|||
mRelease == other.mRelease) |
|||
return true; |
|||
|
|||
return false; |
|||
} |
|||
|
|||
bool VersionId::operator> (const VersionId& other) |
|||
{ |
|||
if (*this == other) return false; |
|||
|
|||
return !(*this < other); |
|||
} |
@ -0,0 +1,49 @@ |
|||
/*!******************************************************************** |
|||
Audacity: A Digital Audio Editor |
|||
|
|||
@file VersionId.h |
|||
@brief Declare a class with version number manipulation. |
|||
|
|||
Anton Gerasimov |
|||
**********************************************************************/ |
|||
#pragma once |
|||
|
|||
#include <wx/arrstr.h> |
|||
|
|||
/// A class, that support base manipulation with version number. |
|||
/** |
|||
By default initialized by zero version number (Version = 0, Release = 0, Revision = 0), |
|||
that not allow us to update. |
|||
*/ |
|||
class VersionId final |
|||
{ |
|||
public: |
|||
/// Creates an zero version object. |
|||
VersionId() = default; |
|||
VersionId(int version, int release, int revision); |
|||
|
|||
/// Creates version string like "1.2.3" by parameters. |
|||
static wxString MakeString(int version, int release, int revision); |
|||
/// Parse and return version object from version string like "1.2.3". |
|||
static VersionId ParseFromString(wxString& versionString); |
|||
|
|||
/// Make string with version by MakeString() from instance values. |
|||
wxString getString() const; |
|||
|
|||
bool operator== (const VersionId& other); |
|||
bool operator!= (const VersionId& other); |
|||
|
|||
bool operator< (const VersionId& other); |
|||
bool operator> (const VersionId& other); |
|||
|
|||
private: |
|||
int mVersion{ 0 }; |
|||
int mRelease{ 0 }; |
|||
int mRevision{ 0 }; |
|||
}; |
|||
|
|||
/// Return version (VersionId) object with current Audacity build version. |
|||
static inline VersionId CurrentBuildVersion() |
|||
{ |
|||
return VersionId{ AUDACITY_VERSION, AUDACITY_RELEASE, AUDACITY_REVISION }; |
|||
} |
@ -0,0 +1,23 @@ |
|||
/*!******************************************************************** |
|||
Audacity: A Digital Audio Editor |
|||
|
|||
@file VersionPatch.h |
|||
@brief Declare a structure that describes patch fields. |
|||
|
|||
Anton Gerasimov |
|||
**********************************************************************/ |
|||
#pragma once |
|||
|
|||
#include "VersionId.h" |
|||
|
|||
/// A structure that describes patch fields. |
|||
struct VersionPatch final |
|||
{ |
|||
using UpdateDataFormat = std::string; |
|||
|
|||
VersionPatch() = default; |
|||
|
|||
VersionId version; |
|||
wxArrayString changelog; |
|||
wxString download; |
|||
}; |
Write
Preview
Loading…
Cancel
Save
Reference in new issue