mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 04:57:00 -04:00
Finally got precompiled headers to work.
Now all C++ files need to #include <util/prec.hpp>
That is why all .cpp files are touched by this commit
Many changes to installers and update checking:
- the window is now called PackagesWindow, in a new source file
- update checking is now independent from the PackagesWindow. For update checking only a list of package versions are needed (vector<PackageDependency>). This is much less information to download at each startup.
- the list of available packages is now a list of available Installers, since an installer can contain multiple packages.
- moved the logic of dependency checking etc. to data/installer
- moved the actual installation to util/io/package_manager
- moved directory iteration/creation logic to util/file_utils
- added PackageDirectory: the local and global package directory now have their own object (was part of PackageManager)
- added PackageVersion: for detecting if a package has been modified after it was installed.
- added PackageDescription: description/header of a package. Basicly the same as what Packaged provides.
- added DownloadableInstaller: where to find an insaller, what does it contain?
- added InstallablePackage: brining it all together: installer, package, status, action.
Current status: the insaller is currently broken in a few places, more on that soon.
git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@792 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
+57
-530
@@ -6,7 +6,9 @@
|
||||
|
||||
// ----------------------------------------------------------------------------- : Includes
|
||||
|
||||
#include <util/prec.hpp>
|
||||
#include <gui/update_checker.hpp>
|
||||
#include <gui/packages_window.hpp>
|
||||
#include <data/settings.hpp>
|
||||
#include <data/installer.hpp>
|
||||
#include <util/io/package_manager.hpp>
|
||||
@@ -17,26 +19,17 @@
|
||||
#include <wx/dialup.h>
|
||||
#include <wx/url.h>
|
||||
#include <wx/html/htmlwin.h>
|
||||
#include <wx/vlbox.h>
|
||||
#include <wx/wfstream.h>
|
||||
#include <wx/dir.h>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <iostream>
|
||||
|
||||
DECLARE_POINTER_TYPE(PackageVersionData);
|
||||
DECLARE_POINTER_TYPE(Installer);
|
||||
//%DECLARE_POINTER_TYPE(PackageVersionData);
|
||||
|
||||
DECLARE_POINTER_TYPE(VersionData);
|
||||
|
||||
DECLARE_TYPEOF_COLLECTION(PackageVersionDataP);
|
||||
DECLARE_TYPEOF_COLLECTION(PackageDependencyP);
|
||||
DECLARE_TYPEOF(list<PackageVersionDataP>);
|
||||
DECLARE_TYPEOF(set<String>);
|
||||
|
||||
// ----------------------------------------------------------------------------- : Update data
|
||||
|
||||
/*
|
||||
/// Information on available packages
|
||||
class PackageVersionData : public IntrusivePtrBase<PackageVersionData> {
|
||||
class PackageVersionData : public IntrusivePtrVirtualBase {
|
||||
public:
|
||||
PackageVersionData() {}
|
||||
|
||||
@@ -62,23 +55,39 @@ class VersionData : public IntrusivePtrBase<VersionData> {
|
||||
|
||||
DECLARE_REFLECTION();
|
||||
};
|
||||
*/
|
||||
|
||||
IMPLEMENT_REFLECTION(PackageVersionData) {
|
||||
REFLECT(name);
|
||||
REFLECT(type);
|
||||
REFLECT(display_name);
|
||||
REFLECT(description);
|
||||
REFLECT(url);
|
||||
REFLECT(version);
|
||||
REFLECT(app_version);
|
||||
REFLECT_N("depends ons", depends);
|
||||
/// Information on the latest available versions
|
||||
class VersionData : public IntrusivePtrBase<VersionData> {
|
||||
public:
|
||||
vector<PackageDependencyP> packages; ///< Available packages + versions
|
||||
String new_updates_url; ///< updates url has moved?
|
||||
|
||||
DECLARE_REFLECTION();
|
||||
};
|
||||
|
||||
/*
|
||||
IMPLEMENT_REFLECTION_NO_SCRIPT(PackageVersionData) {
|
||||
REFLECT_NO_SCRIPT(name);
|
||||
REFLECT_NO_SCRIPT(type);
|
||||
REFLECT_NO_SCRIPT(display_name);
|
||||
REFLECT_NO_SCRIPT(description);
|
||||
REFLECT_NO_SCRIPT(url);
|
||||
REFLECT_NO_SCRIPT(version);
|
||||
REFLECT_NO_SCRIPT(app_version);
|
||||
REFLECT_NO_SCRIPT_N("depends ons", depends);
|
||||
}
|
||||
|
||||
IMPLEMENT_REFLECTION(VersionData) {
|
||||
REFLECT(version);
|
||||
REFLECT(description);
|
||||
REFLECT(new_updates_url);
|
||||
REFLECT(packages);
|
||||
IMPLEMENT_REFLECTION_NO_SCRIPT(VersionData) {
|
||||
REFLECT_NO_SCRIPT(version);
|
||||
REFLECT_NO_SCRIPT(description);
|
||||
REFLECT_NO_SCRIPT(new_updates_url);
|
||||
REFLECT_NO_SCRIPT(packages);
|
||||
}*/
|
||||
|
||||
IMPLEMENT_REFLECTION_NO_SCRIPT(VersionData) {
|
||||
REFLECT_NO_SCRIPT(packages);
|
||||
REFLECT_NO_SCRIPT(new_updates_url);
|
||||
}
|
||||
|
||||
// The information for the latest version
|
||||
@@ -89,7 +98,18 @@ bool shown_dialog = false;
|
||||
volatile bool checking_updates = false;
|
||||
|
||||
bool update_data_found() { return !!update_version_data; }
|
||||
bool update_available() { return update_version_data && update_version_data->version > app_version; }
|
||||
bool update_available() {
|
||||
if (!update_version_data) return false;
|
||||
// updates to any installed package?
|
||||
FOR_EACH_CONST(p, update_version_data->packages) {
|
||||
if (!settings.check_updates_all && p->package != mse_package) continue;
|
||||
Version v;
|
||||
if (packages.installedVersion(p->package, v) && v < p->version) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Update checking
|
||||
|
||||
@@ -113,17 +133,18 @@ class CheckUpdateThread : public wxThread {
|
||||
if (checking_updates) return; // don't check multiple times simultaniously
|
||||
checking_updates = true;
|
||||
try {
|
||||
wxURL url(settings.updates_url);
|
||||
wxURL url(settings.package_versions_url);
|
||||
wxInputStream* isP = url.GetInputStream();
|
||||
if (!isP) return; // failed to get data
|
||||
InputStreamP is(isP);
|
||||
// Read version data
|
||||
// ignore errors for forwards compatability
|
||||
VersionDataP version_data;
|
||||
Reader reader(is, nullptr, _("updates"));
|
||||
Reader reader(is, nullptr, _("updates"), true);
|
||||
reader.handle(version_data);
|
||||
// has the updates url changed?
|
||||
if (!version_data->new_updates_url.empty()) {
|
||||
settings.updates_url = version_data->new_updates_url;
|
||||
settings.package_versions_url = version_data->new_updates_url;
|
||||
}
|
||||
// Make available
|
||||
update_version_data = version_data;
|
||||
@@ -174,11 +195,14 @@ struct HtmlWindowToBrowser : public wxHtmlWindow {
|
||||
|
||||
void show_update_dialog(Window* parent) {
|
||||
if (!update_available() || shown_dialog) return; // we already have the latest version, or this has already been displayed.
|
||||
shown_dialog = true;
|
||||
(new PackagesWindow(parent))->Show();
|
||||
/*
|
||||
// Show update dialog
|
||||
wxDialog* dlg = new wxDialog(parent, wxID_ANY, _TITLE_("updates available"), wxDefaultPosition);
|
||||
// controls
|
||||
wxHtmlWindow* html = new HtmlWindowToBrowser(dlg, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_AUTO | wxSUNKEN_BORDER);
|
||||
html->SetPage(update_version_data->description);
|
||||
//% html->SetPage(update_version_data->description);
|
||||
wxButton* close = new wxButton(dlg, wxID_OK, _BUTTON_("close"));
|
||||
close->SetDefault();
|
||||
// layout
|
||||
@@ -189,502 +213,5 @@ void show_update_dialog(Window* parent) {
|
||||
dlg->SetSize(400,400);
|
||||
dlg->Show();
|
||||
// And never show it again this run
|
||||
shown_dialog = true;
|
||||
*/
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : PackageUpdateList
|
||||
|
||||
class PackageUpdateList : public wxVListBox {
|
||||
public:
|
||||
PackageUpdateList(UpdatesWindow* parent)
|
||||
: wxVListBox (parent, ID_PACKAGE_LIST, wxDefaultPosition, wxSize(540,210), wxNO_BORDER | wxVSCROLL)
|
||||
, parent(parent)
|
||||
{
|
||||
if (!checking_updates && !update_version_data) {
|
||||
check_updates_now(true);
|
||||
}
|
||||
SetItemCount(update_version_data ? update_version_data->packages.size() : 1);
|
||||
}
|
||||
|
||||
virtual void OnDrawItem(wxDC& dc, const wxRect& rect, size_t n) const {
|
||||
static wxBrush greyBrush(Color(224,224,224));
|
||||
if (checking_updates) {
|
||||
String text = _ERROR_("checking updates");
|
||||
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
dc.SetBrush(greyBrush);
|
||||
dc.DrawRectangle(rect);
|
||||
|
||||
int w, h;
|
||||
dc.GetTextExtent(text, &w, &h);
|
||||
dc.DrawText(text, rect.GetLeft() + (rect.GetWidth() - w) / 2, rect.GetTop() + (rect.GetHeight() - h) / 2);
|
||||
} else if (!update_version_data || update_version_data->packages.empty()) {
|
||||
String text = _ERROR_("no packages");
|
||||
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
dc.SetBrush(greyBrush);
|
||||
dc.DrawRectangle(rect);
|
||||
|
||||
int w, h;
|
||||
dc.GetTextExtent(text, &w, &h);
|
||||
dc.DrawText(text, rect.GetLeft() + (rect.GetWidth() - w) / 2, rect.GetTop() + (rect.GetHeight() - h) / 2);
|
||||
} else {
|
||||
static wxBrush darkBrush(Color(192,224,255));
|
||||
static wxBrush selectBrush(Color(96,96,192));
|
||||
|
||||
PackageVersionDataP pack = update_version_data->packages[n];
|
||||
UpdatesWindow::PackageStatus status = parent->package_data[pack].first;
|
||||
UpdatesWindow::PackageAction action = parent->package_data[pack].second;
|
||||
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
dc.SetBrush(IsSelected(n) ? selectBrush : (n % 2 ? *wxWHITE_BRUSH : darkBrush));
|
||||
|
||||
dc.DrawRectangle(rect);
|
||||
|
||||
// These two arrays correspond to PackageStatus and PackageAction, respectively
|
||||
static Color status_colors [] = {
|
||||
Color(32,160,32)
|
||||
,Color(32,32,255)
|
||||
,Color(192,32,32)
|
||||
};
|
||||
|
||||
static Color action_colors [] = {
|
||||
Color(32,160,32)
|
||||
,Color(192,32,32)
|
||||
,Color(192,192,32)
|
||||
,Color(32,32,255)
|
||||
,Color(32,32,32)
|
||||
};
|
||||
|
||||
// Ditto here (these are the locale names)
|
||||
static String status_texts [] = {
|
||||
_TYPE_("installed")
|
||||
,_TYPE_("uninstalled")
|
||||
,_TYPE_("upgradeable")
|
||||
};
|
||||
|
||||
static String action_texts [] = {
|
||||
_TYPE_("install")
|
||||
,_TYPE_("uninstall")
|
||||
,_TYPE_("upgrade")
|
||||
,_TYPE_("do nothing")
|
||||
,_TYPE_("new mse")
|
||||
};
|
||||
|
||||
static Color packageFront(64,64,64);
|
||||
|
||||
#define SELECT_WHITE(color) (IsSelected(n) ? *wxWHITE : color)
|
||||
|
||||
dc.SetClippingRegion(wxRect(rect.x, rect.y, 180, rect.height));
|
||||
dc.SetTextForeground(SELECT_WHITE(packageFront));
|
||||
dc.DrawText(pack->display_name, rect.GetLeft() + 1, rect.GetTop());
|
||||
dc.DestroyClippingRegion();
|
||||
|
||||
dc.SetClippingRegion(wxRect(rect.x + 180, rect.y, 120, rect.height));
|
||||
dc.DrawText(pack->type, rect.GetLeft() + 180, rect.GetTop());
|
||||
dc.DestroyClippingRegion();
|
||||
|
||||
dc.SetTextForeground(SELECT_WHITE(status_colors[status]));
|
||||
dc.DrawText(status_texts[status], rect.GetLeft() + 300, rect.GetTop());
|
||||
|
||||
dc.SetTextForeground(SELECT_WHITE(action_colors[action]));
|
||||
dc.DrawText(action_texts[action], rect.GetLeft() + 420, rect.GetTop());
|
||||
|
||||
#undef SELECT_WHITE
|
||||
}
|
||||
}
|
||||
|
||||
virtual wxCoord OnMeasureItem(size_t) const {
|
||||
return (update_version_data && !update_version_data->packages.empty()) ? 15 : 210;
|
||||
}
|
||||
|
||||
void onUpdateCheckingFinished(wxEvent& event) {
|
||||
SetItemCount(update_version_data ? update_version_data->packages.size() : 1);
|
||||
}
|
||||
|
||||
virtual wxCoord EstimateTotalHeight() const {
|
||||
return (update_version_data && !update_version_data->packages.empty())
|
||||
? 15 * (int)update_version_data->packages.size()
|
||||
: 210;
|
||||
}
|
||||
private:
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
UpdatesWindow* parent;
|
||||
};
|
||||
|
||||
BEGIN_EVENT_TABLE(PackageUpdateList, wxVListBox)
|
||||
EVT_CUSTOM(UPDATE_CHECK_FINISHED_EVT, wxID_ANY, PackageUpdateList::onUpdateCheckingFinished)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
// ----------------------------------------------------------------------------- : RecursiveDelete
|
||||
// Move somewhere better?
|
||||
|
||||
class RecursiveDeleter : public wxDirTraverser {
|
||||
public:
|
||||
set<String> to_delete;
|
||||
String start_dir;
|
||||
RecursiveDeleter (String start)
|
||||
: start_dir (start)
|
||||
{
|
||||
to_delete.insert(start_dir);
|
||||
}
|
||||
|
||||
wxDirTraverseResult OnFile(const String& filename) {
|
||||
if (!wxRemoveFile(filename))
|
||||
handle_error(_("Cannot delete ") + filename + _(". ")
|
||||
_("The remainder of the package has still been removed, if possible.")
|
||||
_("Other packages may have been removed, including packages that this on is dependent on. Please remove manually."));
|
||||
return wxDIR_CONTINUE;
|
||||
}
|
||||
|
||||
wxDirTraverseResult OnDir(const String& dirname) {
|
||||
to_delete.insert(dirname);
|
||||
return wxDIR_CONTINUE;
|
||||
}
|
||||
|
||||
void finishDelete() {
|
||||
FOR_EACH_REVERSE(dir, to_delete) {
|
||||
wxRmdir(dir);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : UpdateWindow
|
||||
|
||||
UpdatesWindow::UpdatesWindow()
|
||||
: Frame(nullptr, wxID_ANY, _TITLE_("package list"), wxDefaultPosition, wxSize(540,440), wxDEFAULT_DIALOG_STYLE | wxCLIP_CHILDREN)
|
||||
{
|
||||
SetIcon(wxIcon());
|
||||
wxBoxSizer *v = new wxBoxSizer(wxVERTICAL);
|
||||
wxBoxSizer *h1 = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxBoxSizer *h2 = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxBoxSizer *h3 = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
package_list = new PackageUpdateList(this);
|
||||
description_window = new HtmlWindowToBrowser(this, wxID_ANY, wxDefaultPosition, wxSize(540,100), wxHW_SCROLLBAR_AUTO | wxSUNKEN_BORDER);
|
||||
|
||||
setDefaultPackageStatus();
|
||||
|
||||
package_title = new wxStaticText(this, wxID_ANY, _TITLE_("package name"), wxDefaultPosition, wxSize(180,15), wxALIGN_LEFT | wxST_NO_AUTORESIZE);
|
||||
type_title = new wxStaticText(this, wxID_ANY, _TITLE_("package type"), wxDefaultPosition, wxSize(120,15), wxALIGN_LEFT | wxST_NO_AUTORESIZE);
|
||||
status_title = new wxStaticText(this, wxID_ANY, _TITLE_("package status"), wxDefaultPosition, wxSize(120,15), wxALIGN_LEFT | wxST_NO_AUTORESIZE);
|
||||
new_title = new wxStaticText(this, wxID_ANY, _TITLE_("new status"), wxDefaultPosition, wxSize(120,15), wxALIGN_LEFT | wxST_NO_AUTORESIZE);
|
||||
|
||||
h1->Add(package_title, 3);
|
||||
h1->Add(type_title, 2);
|
||||
h1->Add(status_title, 2);
|
||||
h1->Add(new_title, 2);
|
||||
|
||||
(install_button = new wxButton(this, ID_INSTALL, _MENU_("install package")))->Disable();
|
||||
(upgrade_button = new wxButton(this, ID_UPGRADE, _MENU_("upgrade package")))->Disable();
|
||||
(remove_button = new wxButton(this, ID_REMOVE, _MENU_("remove package")))->Disable();
|
||||
(cancel_button = new wxButton(this, ID_CANCEL, _MENU_("cancel changes")))->Disable();
|
||||
|
||||
apply_button = new wxButton(this, ID_APPLY, _MENU_("apply changes"));
|
||||
|
||||
h2->AddStretchSpacer();
|
||||
h2->Add(install_button);
|
||||
h2->AddStretchSpacer();
|
||||
h2->Add(upgrade_button);
|
||||
h2->AddStretchSpacer();
|
||||
h2->Add(remove_button);
|
||||
h2->AddStretchSpacer();
|
||||
h2->Add(cancel_button);
|
||||
h2->AddStretchSpacer();
|
||||
|
||||
h3->AddStretchSpacer();
|
||||
h3->Add(apply_button);
|
||||
h3->AddStretchSpacer();
|
||||
|
||||
v->Add(h1);
|
||||
v->Add(package_list);
|
||||
v->AddStretchSpacer(2);
|
||||
v->Add(description_window);
|
||||
v->AddStretchSpacer(2);
|
||||
v->Add(h2);
|
||||
v->AddStretchSpacer(1);
|
||||
v->Add(h3);
|
||||
v->AddStretchSpacer(2);
|
||||
|
||||
SetSizer(v);
|
||||
}
|
||||
|
||||
UpdatesWindow::~UpdatesWindow() {
|
||||
(new WelcomeWindow)->Show();
|
||||
}
|
||||
|
||||
void UpdatesWindow::onUpdateCheckFinished(wxCommandEvent&) {
|
||||
setDefaultPackageStatus();
|
||||
}
|
||||
|
||||
void UpdatesWindow::onPackageSelect(wxCommandEvent& ev) {
|
||||
updateButtons(ev.GetInt());
|
||||
}
|
||||
|
||||
void UpdatesWindow::onActionChange(wxCommandEvent& ev) {
|
||||
PackageVersionDataP pack = update_version_data->packages[package_list->GetSelection()];
|
||||
PackageAction& action = package_data[pack].second;
|
||||
switch (ev.GetId()) {
|
||||
case ID_INSTALL:
|
||||
action = ACTION_INSTALL;
|
||||
SelectPackageDependencies(pack);
|
||||
break;
|
||||
case ID_REMOVE:
|
||||
action = ACTION_UNINSTALL;
|
||||
RemovePackageDependencies(pack);
|
||||
break;
|
||||
case ID_UPGRADE:
|
||||
action = ACTION_UPGRADE;
|
||||
SelectPackageDependencies(pack);
|
||||
break;
|
||||
case ID_CANCEL:
|
||||
switch (package_data[pack].first) {
|
||||
case STATUS_INSTALLED:
|
||||
SelectPackageDependencies(pack);
|
||||
break;
|
||||
case STATUS_NOT_INSTALLED:
|
||||
RemovePackageDependencies(pack);
|
||||
break;
|
||||
case STATUS_UPGRADEABLE:
|
||||
if (action == ACTION_UPGRADE)
|
||||
DowngradePackageDependencies(pack);
|
||||
else
|
||||
SelectPackageDependencies(pack);
|
||||
break;
|
||||
}
|
||||
action = (pack->app_version > file_version) ? ACTION_NEW_MSE : ACTION_NOTHING;
|
||||
break;
|
||||
}
|
||||
updateButtons(package_list->GetSelection());
|
||||
package_list->Refresh();
|
||||
}
|
||||
|
||||
void UpdatesWindow::onApplyChanges(wxCommandEvent& ev) {
|
||||
list<PackageVersionDataP> to_install, to_remove;
|
||||
|
||||
FOR_EACH(pack, update_version_data->packages) {
|
||||
switch (package_data[pack].second) {
|
||||
case ACTION_INSTALL:
|
||||
to_install.push_back(pack);
|
||||
break;
|
||||
case ACTION_UPGRADE:
|
||||
to_install.push_back(pack);
|
||||
case ACTION_UNINSTALL:
|
||||
to_remove.push_back(pack);
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
FOR_EACH(pack, to_remove) {
|
||||
String filename = packages.openAny(pack->name, true)->absoluteFilename();
|
||||
if (wxDirExists(filename)) {
|
||||
wxDir dir(filename);
|
||||
RecursiveDeleter rd (filename);
|
||||
dir.Traverse(rd);
|
||||
rd.finishDelete();
|
||||
} else {
|
||||
if (!wxRemoveFile(filename))
|
||||
handle_error(_("Cannot delete ") + filename + _(" to remove package ") + pack->name + _(". ")
|
||||
_("Other packages may have been removed, including packages that this on is dependent on. Please remove manually."));
|
||||
}
|
||||
}
|
||||
|
||||
FOR_EACH(pack, to_install) {
|
||||
wxURL url(pack->url);
|
||||
wxInputStream* is = url.GetInputStream();
|
||||
if (!is) {
|
||||
handle_error(_("Cannot fetch file ") + pack->url + _(" to install package ") + pack->name + _(". ")
|
||||
_("Other packages may have been installed, including packages that depend on this one. ")
|
||||
_("Please remove those packages manually or install this one manually."));
|
||||
}
|
||||
wxString filename = wxFileName::CreateTempFileName(_(""));
|
||||
wxFileOutputStream os (filename);
|
||||
|
||||
os.Write(*is);
|
||||
os.Close();
|
||||
|
||||
InstallerP inst(new Installer);
|
||||
inst->open(filename);
|
||||
inst->install(isInstallLocal(settings.install_type), false);
|
||||
|
||||
delete is;
|
||||
wxRemoveFile(filename);
|
||||
}
|
||||
|
||||
setDefaultPackageStatus();
|
||||
updateButtons(package_list->GetSelection());
|
||||
package_list->Refresh();
|
||||
|
||||
handle_pending_errors();
|
||||
|
||||
packages.clearPackageCache();
|
||||
}
|
||||
|
||||
void UpdatesWindow::updateButtons(int id) {
|
||||
PackageVersionDataP pack = update_version_data->packages[id];
|
||||
|
||||
description_window->SetPage(pack->description);
|
||||
|
||||
PackageStatus status = package_data[pack].first;
|
||||
PackageAction action = package_data[pack].second;
|
||||
|
||||
if (action == ACTION_NEW_MSE) {
|
||||
install_button->Disable();
|
||||
remove_button->Enable(status != STATUS_NOT_INSTALLED);
|
||||
upgrade_button->Disable();
|
||||
cancel_button->Disable();
|
||||
} else if (status == STATUS_INSTALLED) {
|
||||
install_button->Disable();
|
||||
remove_button->Enable(action != ACTION_UNINSTALL);
|
||||
upgrade_button->Disable();
|
||||
cancel_button->Enable(action == ACTION_UNINSTALL);
|
||||
} else if (status == STATUS_NOT_INSTALLED) {
|
||||
install_button->Enable(action != ACTION_INSTALL);
|
||||
remove_button->Disable();
|
||||
upgrade_button->Disable();
|
||||
cancel_button->Enable(action == ACTION_INSTALL);
|
||||
} else /* status == STATUS_UPGRADEABLE */ {
|
||||
install_button->Disable();
|
||||
remove_button->Enable(action != ACTION_UNINSTALL);
|
||||
upgrade_button->Enable(action != ACTION_UPGRADE);
|
||||
cancel_button->Enable(action != ACTION_NOTHING);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdatesWindow::setDefaultPackageStatus() {
|
||||
if (!update_version_data) return;
|
||||
FOR_EACH(p, update_version_data->packages) {
|
||||
PackagedP pack;
|
||||
try { pack = packages.openAny(p->name, true); }
|
||||
catch (PackageNotFoundError&) { } // We couldn't open a package... no cause for alarm
|
||||
|
||||
if (!pack || !(wxFileExists(pack->absoluteFilename()) || wxDirExists(pack->absoluteFilename()))) {
|
||||
// not installed
|
||||
if (p->app_version > file_version) {
|
||||
package_data[p] = PackageData(STATUS_NOT_INSTALLED, ACTION_NEW_MSE);
|
||||
} else {
|
||||
package_data[p] = PackageData(STATUS_NOT_INSTALLED, ACTION_NOTHING);
|
||||
}
|
||||
} else if (pack->version < p->version) {
|
||||
// newer version
|
||||
if (p->app_version > file_version) {
|
||||
package_data[p] = PackageData(STATUS_UPGRADEABLE, ACTION_NEW_MSE);
|
||||
} else {
|
||||
package_data[p] = PackageData(STATUS_UPGRADEABLE, ACTION_UPGRADE);
|
||||
}
|
||||
} else {
|
||||
package_data[p] = PackageData(STATUS_INSTALLED, ACTION_NOTHING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Select the dependencies for a package
|
||||
/**
|
||||
* \param pack The package data to check dependencies for.
|
||||
*
|
||||
* This function will select all the dependencies for the package, to ensure
|
||||
* that the user can't install a package without it's dependencies.
|
||||
*/
|
||||
void UpdatesWindow::SelectPackageDependencies (PackageVersionDataP pack) {
|
||||
FOR_EACH(dep, pack->depends) {
|
||||
if (packages.checkDependency(*dep, false)) //It's already installed.
|
||||
continue;
|
||||
FOR_EACH(p, update_version_data->packages) {
|
||||
if (p->name == dep->package) { //We have a match.
|
||||
if (p->version >= dep->version) { //Versions line up
|
||||
|
||||
PackageStatus& status = package_data[p].first;
|
||||
PackageAction& action = package_data[p].second;
|
||||
if (status == STATUS_NOT_INSTALLED)
|
||||
action = ACTION_INSTALL;
|
||||
else if (status == STATUS_UPGRADEABLE)
|
||||
action = ACTION_UPGRADE;
|
||||
else //status == STATUS_INSTALLED
|
||||
action = ACTION_NOTHING;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: Decide what to do if a dependency can't be met.
|
||||
// It shouldn't happen with a decently maintained updates list.
|
||||
// But it could, and we need to decide what to do in this situation.
|
||||
}
|
||||
}
|
||||
|
||||
/// This finds all packages that depend on the one provided and marks them for removal.
|
||||
void UpdatesWindow::RemovePackageDependencies (PackageVersionDataP pack) {
|
||||
FOR_EACH(p, update_version_data->packages) {
|
||||
FOR_EACH(dep, p->depends) {
|
||||
if (pack->name == dep->package) {
|
||||
PackageStatus& status = package_data[p].first;
|
||||
PackageAction& action = package_data[p].second;
|
||||
|
||||
if (status != STATUS_NOT_INSTALLED)
|
||||
action = ACTION_UNINSTALL;
|
||||
else // status == STATUS_NOT_INSTALLED
|
||||
action = p->app_version > file_version ? ACTION_NEW_MSE : ACTION_NOTHING;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This deals with the complexities of a downgrade and its dependencies.
|
||||
void UpdatesWindow::DowngradePackageDependencies (PackageVersionDataP pack) {
|
||||
PackagedP old_pack = packages.openAny(pack->name, true);
|
||||
FOR_EACH(dep, old_pack->dependencies) {
|
||||
// dependencies the old version has, but the new one might not.
|
||||
if (packages.checkDependency(*dep, false)) //It's already installed.
|
||||
continue;
|
||||
FOR_EACH(p, update_version_data->packages) {
|
||||
if (p->name == dep->package) { //We have a match.
|
||||
if (p->version >= dep->version) { //Versions line up
|
||||
if (p->app_version > file_version) //We can't install this
|
||||
continue;
|
||||
|
||||
PackageStatus& status = package_data[p].first;
|
||||
PackageAction& action = package_data[p].second;
|
||||
if (status == STATUS_NOT_INSTALLED)
|
||||
action = ACTION_INSTALL;
|
||||
else if (status == STATUS_UPGRADEABLE)
|
||||
action = ACTION_UPGRADE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: Decide what to do if a dependency can't be met.
|
||||
// It shouldn't happen with a decently maintained updates list.
|
||||
// But it could, and we need to decide what to do in this situation.
|
||||
// Ideally, some sort of error should occur, such that we don't have packages
|
||||
// with unmet dependencies.
|
||||
}
|
||||
|
||||
FOR_EACH(p, update_version_data->packages) {
|
||||
// dependencies that can no longer be met.
|
||||
FOR_EACH(dep, p->depends) {
|
||||
if (pack->name == dep->package) {
|
||||
if (old_pack->version > dep->version) {
|
||||
PackageStatus& status = package_data[p].first;
|
||||
PackageAction& action = package_data[p].second;
|
||||
|
||||
if (status != STATUS_NOT_INSTALLED)
|
||||
action = ACTION_UNINSTALL;
|
||||
else // status == STATUS_NOT_INSTALLED
|
||||
action = p->app_version > file_version ? ACTION_NEW_MSE : ACTION_NOTHING;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_EVENT_TABLE(UpdatesWindow, Frame)
|
||||
EVT_COMMAND(wxID_ANY, UPDATE_CHECK_FINISHED_EVT, UpdatesWindow::onUpdateCheckFinished)
|
||||
EVT_LISTBOX(ID_PACKAGE_LIST, UpdatesWindow::onPackageSelect)
|
||||
EVT_BUTTON(ID_INSTALL, UpdatesWindow::onActionChange)
|
||||
EVT_BUTTON(ID_REMOVE, UpdatesWindow::onActionChange)
|
||||
EVT_BUTTON(ID_UPGRADE, UpdatesWindow::onActionChange)
|
||||
EVT_BUTTON(ID_CANCEL, UpdatesWindow::onActionChange)
|
||||
EVT_BUTTON(ID_APPLY, UpdatesWindow::onApplyChanges)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
Reference in New Issue
Block a user