Commit 9c2ef1cf authored by twanvl's avatar twanvl

Now actually downloads a list of installers.

parent 17319f04
...@@ -327,6 +327,7 @@ void merge(InstallablePackages& installed, const DownloadableInstallerP& install ...@@ -327,6 +327,7 @@ void merge(InstallablePackages& installed, const DownloadableInstallerP& install
ip->installer = installer; ip->installer = installer;
ips.push_back(ip); ips.push_back(ip);
} }
sort(ips);
merge(installed, ips); merge(installed, ips);
} }
......
...@@ -11,14 +11,11 @@ ...@@ -11,14 +11,11 @@
#include <gui/control/tree_list.hpp> #include <gui/control/tree_list.hpp>
//%#include <gui/update_checker.hpp> //%#include <gui/update_checker.hpp>
#include <gui/util.hpp> #include <gui/util.hpp>
#include <util/io/package_repository.hpp>
#include <util/io/package_manager.hpp> #include <util/io/package_manager.hpp>
#include <util/window_id.hpp> #include <util/window_id.hpp>
#include <data/installer.hpp> #include <data/installer.hpp>
#include <data/settings.hpp> #include <data/settings.hpp>
#include <gfx/gfx.hpp> #include <gfx/gfx.hpp>
//%#include <list>
//%#include <set>
#include <wx/wfstream.h> #include <wx/wfstream.h>
#include <wx/html/htmlwin.h> #include <wx/html/htmlwin.h>
#include <wx/dialup.h> #include <wx/dialup.h>
...@@ -26,49 +23,16 @@ ...@@ -26,49 +23,16 @@
#include <wx/dcbuffer.h> #include <wx/dcbuffer.h>
#include <wx/progdlg.h> #include <wx/progdlg.h>
//%DECLARE_POINTER_TYPE(VersionData); //%% TODO
DECLARE_POINTER_TYPE(Installer); DECLARE_POINTER_TYPE(Installer);
//%DECLARE_POINTER_TYPE(PackageVersionData);
DECLARE_TYPEOF_COLLECTION(PackageVersionDataP);
DECLARE_TYPEOF_COLLECTION(PackageDependencyP); DECLARE_TYPEOF_COLLECTION(PackageDependencyP);
DECLARE_TYPEOF_COLLECTION(InstallablePackageP); DECLARE_TYPEOF_COLLECTION(InstallablePackageP);
DECLARE_TYPEOF_COLLECTION(DownloadableInstallerP);
DECLARE_TYPEOF_COLLECTION(TreeList::ItemP); DECLARE_TYPEOF_COLLECTION(TreeList::ItemP);
//%DECLARE_TYPEOF(list<PackageVersionDataP>);
//%DECLARE_TYPEOF(set<String>);
// ----------------------------------------------------------------------------- : TODO: MOVE // ----------------------------------------------------------------------------- : TODO: MOVE
/* /*
/// Information on available packages
class PackageVersionData : public IntrusivePtrVirtualBase {
public:
PackageVersionData() {}
String name; ///< Name of the package
String type; ///< Type of package ("magic style" or "game")
String display_name; ///< Name to show on package list.
String description; ///< html description
String url; ///< Where can the package be downloaded?
Version version; ///< Version number of the download
Version app_version; ///< The minimium version of MSE required
vector<PackageDependencyP> depends; ///< Packages this depends on
DECLARE_REFLECTION();
};
/// Information on the latest available version
class VersionData : public IntrusivePtrBase<VersionData> {
public:
Version version; ///< Latest version number of MSE
String description; ///< html description of the latest MSE release
String new_updates_url; ///< updates url has moved?
vector<PackageVersionDataP> packages; ///< Available packages
DECLARE_REFLECTION();
};
extern VersionDataP update_version_data;
// A HTML control that opens all pages in an actual browser // A HTML control that opens all pages in an actual browser
struct HtmlWindowToBrowser : public wxHtmlWindow { struct HtmlWindowToBrowser : public wxHtmlWindow {
HtmlWindowToBrowser(Window* parent, int id, const wxPoint& pos, const wxSize& size, long flags) HtmlWindowToBrowser(Window* parent, int id, const wxPoint& pos, const wxSize& size, long flags)
...@@ -79,134 +43,61 @@ struct HtmlWindowToBrowser : public wxHtmlWindow { ...@@ -79,134 +43,61 @@ struct HtmlWindowToBrowser : public wxHtmlWindow {
wxLaunchDefaultBrowser( info.GetHref() ); wxLaunchDefaultBrowser( info.GetHref() );
} }
}; };
*/
// ----------------------------------------------------------------------------- : PackageUpdateList // ----------------------------------------------------------------------------- : DownloadableInstallers
/* class DownloadableInstallerList {
class PackageUpdateList : public wxVListBox {
public: public:
PackageUpdateList(UpdatesWindow* parent) DownloadableInstallerList() : status(NONE) {}
: 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 { /// are we done? if not, start downloading
static wxBrush greyBrush(Color(224,224,224)); bool done();
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 { vector<DownloadableInstallerP> installers;
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: private:
DECLARE_EVENT_TABLE() enum Status { NONE, DOWNLOADING, DONE } status;
wxMutex lock;
UpdatesWindow* parent;
struct Thread : public wxThread {
virtual ExitCode Entry();
};
}; };
BEGIN_EVENT_TABLE(PackageUpdateList, wxVListBox) DownloadableInstallerList downloadable_installers;
EVT_CUSTOM(UPDATE_CHECK_FINISHED_EVT, wxID_ANY, PackageUpdateList::onUpdateCheckingFinished)
END_EVENT_TABLE()
*/
bool DownloadableInstallerList::done() {
if (status == DONE) return true;
if (status == NONE) {
status = DOWNLOADING;
Thread* thread = new Thread();
thread->Create();
thread->Run();
}
return false;
}
wxThread::ExitCode DownloadableInstallerList::Thread::Entry() {
// open url
wxURL url(settings.installer_list_url);
wxInputStream* isP = url.GetInputStream();
if (!isP) {
wxMutexLocker l(downloadable_installers.lock);
downloadable_installers.status = DONE;
return 0;
}
InputStreamP is(isP);
// Read installer list
Reader reader(is, nullptr, _("installers"), true);
vector<DownloadableInstallerP> installers;
reader.handle(_("installers"),installers);
// done
wxMutexLocker l(downloadable_installers.lock);
swap(installers, downloadable_installers.installers);
downloadable_installers.status = DONE;
return 0;
}
// ----------------------------------------------------------------------------- : PackageUpdateList // ----------------------------------------------------------------------------- : PackageUpdateList
...@@ -216,7 +107,6 @@ class PackageUpdateList : public TreeList { ...@@ -216,7 +107,6 @@ class PackageUpdateList : public TreeList {
PackageUpdateList(PackagesWindow* parent, int id = wxID_ANY) PackageUpdateList(PackagesWindow* parent, int id = wxID_ANY)
: TreeList(parent, id) : TreeList(parent, id)
, parent(parent) , parent(parent)
, images(16,16)
{ {
item_height = max(item_height,17); item_height = max(item_height,17);
rebuild(); rebuild();
...@@ -240,7 +130,6 @@ class PackageUpdateList : public TreeList { ...@@ -240,7 +130,6 @@ class PackageUpdateList : public TreeList {
private: private:
PackagesWindow* parent; PackagesWindow* parent;
mutable wxImageList images;
class TreeItem; class TreeItem;
public: public:
typedef intrusive_ptr<TreeItem> TreeItemP; typedef intrusive_ptr<TreeItem> TreeItemP;
...@@ -250,9 +139,11 @@ class PackageUpdateList : public TreeList { ...@@ -250,9 +139,11 @@ class PackageUpdateList : public TreeList {
String label; String label;
vector<TreeItemP> children; vector<TreeItemP> children;
InstallablePackageP package; InstallablePackageP package;
Bitmap icon, icon_grey;
void add(const InstallablePackageP& package, const String& path, int level = -1); void add(const InstallablePackageP& package, const String& path, int level = -1);
void toItems(vector<TreeList::ItemP>& items); void toItems(vector<TreeList::ItemP>& items);
bool highlight() const;
}; };
}; };
...@@ -312,14 +203,21 @@ void PackageUpdateList::TreeItem::toItems(vector<TreeList::ItemP>& items) { ...@@ -312,14 +203,21 @@ void PackageUpdateList::TreeItem::toItems(vector<TreeList::ItemP>& items) {
} }
} }
bool PackageUpdateList::TreeItem::highlight() const {
if (package && ((package->installed && !(package->action & PACKAGE_REMOVE))
|| package->action & (PACKAGE_INSTALL | PACKAGE_UPGRADE))) {
return true;
}
FOR_EACH_CONST(c,children) if (c->highlight()) return true;
return false;
}
void PackageUpdateList::initItems() { void PackageUpdateList::initItems() {
// packages to tree // packages to tree
TreeItem root; TreeItem root;
FOR_EACH(ip, parent->installable_packages) { FOR_EACH(ip, parent->installable_packages) {
String group = ip->description->installer_group; String group = ip->description->installer_group;
//% if (group.empty()) group = _("Custom");
//% group += _("/");
if (!group.empty()) group += _("/"); if (!group.empty()) group += _("/");
group += ip->description->short_name; group += ip->description->short_name;
root.add(ip, group); root.add(ip, group);
...@@ -328,21 +226,25 @@ void PackageUpdateList::initItems() { ...@@ -328,21 +226,25 @@ void PackageUpdateList::initItems() {
items.clear(); items.clear();
root.toItems(items); root.toItems(items);
// init image list // init image list
images.RemoveAll();
Image resampled(16,16,false);
FOR_EACH(i,items) { FOR_EACH(i,items) {
const TreeItem& ti = static_cast<const TreeItem&>(*i); TreeItem& ti = static_cast<TreeItem&>(*i);
const InstallablePackageP& p = ti.package; const InstallablePackageP& p = ti.package;
Image image;
if (p && p->description->icon.Ok()) { if (p && p->description->icon.Ok()) {
Image resampled(16,16,false);
resample_preserve_aspect(p->description->icon, resampled); resample_preserve_aspect(p->description->icon, resampled);
images.Add(resampled); image = resampled;
} else if (p) { } else if (p) {
images.Add(load_resource_image(_("installer_package"))); image = load_resource_image(_("installer_package"));
} else if (ti.label == _("locales")) { } else if (ti.label == _("locales")) {
images.Add(load_resource_image(_("installer_locales"))); image = load_resource_image(_("installer_locales"));
} else { } else {
images.Add(load_resource_image(_("installer_group"))); image = load_resource_image(_("installer_group"));
} }
ti.icon = Bitmap(image);
desaturate(image);
set_alpha(image, 0.5);
ti.icon_grey = Bitmap(image);
} }
} }
...@@ -351,31 +253,41 @@ void PackageUpdateList::drawItem(DC& dc, size_t index, size_t column, int x, int ...@@ -351,31 +253,41 @@ void PackageUpdateList::drawItem(DC& dc, size_t index, size_t column, int x, int
Color color = wxSystemSettings::GetColour(selected ? wxSYS_COLOUR_HIGHLIGHTTEXT : wxSYS_COLOUR_WINDOWTEXT); Color color = wxSystemSettings::GetColour(selected ? wxSYS_COLOUR_HIGHLIGHTTEXT : wxSYS_COLOUR_WINDOWTEXT);
if (column == 0) { if (column == 0) {
// Name // Name
images.Draw((int)index, dc, x, y); const Bitmap& bmp = ti.highlight() ? ti.icon : ti.icon_grey;
if (bmp.Ok()) dc.DrawBitmap(bmp,x,y);
dc.SetTextForeground(color); dc.SetTextForeground(color);
dc.DrawText(ti.label, x+18, y+2); dc.DrawText(ti.label, x+18, y+2);
} else if (column == 1 && ti.package) { } else if (column == 1 && ti.package) {
// Status // Status
int stat = ti.package->status; int stat = ti.package->status;
if ((stat & PACKAGE_CONFLICTS) == PACKAGE_CONFLICTS) { if ((stat & PACKAGE_CONFLICTS) == PACKAGE_CONFLICTS) {
dc.SetTextForeground(lerp(color,Color(255,0,0),0.8));
dc.DrawText(_LABEL_("package conflicts"), x+1,y+2); dc.DrawText(_LABEL_("package conflicts"), x+1,y+2);
} else if ((stat & PACKAGE_MODIFIED) == PACKAGE_MODIFIED) { } else if ((stat & PACKAGE_MODIFIED) == PACKAGE_MODIFIED) {
dc.SetTextForeground(lerp(color,Color(255,255,0),0.5));
dc.DrawText(_LABEL_("package modified"), x+1,y+2); dc.DrawText(_LABEL_("package modified"), x+1,y+2);
} else if ((stat & PACKAGE_UPDATES) == PACKAGE_UPDATES) { } else if ((stat & PACKAGE_UPDATES) == PACKAGE_UPDATES) {
dc.SetTextForeground(lerp(color,Color(0,0,255),0.5));
dc.DrawText(_LABEL_("package updates"), x+1,y+2); dc.DrawText(_LABEL_("package updates"), x+1,y+2);
} else if ((stat & PACKAGE_INSTALLED) == PACKAGE_INSTALLED) { } else if ((stat & PACKAGE_INSTALLED) == PACKAGE_INSTALLED) {
dc.SetTextForeground(color);
dc.DrawText(_LABEL_("package installed"), x+1,y+2); dc.DrawText(_LABEL_("package installed"), x+1,y+2);
} else if ((stat & PACKAGE_INSTALLABLE) == PACKAGE_INSTALLABLE) { } else if ((stat & PACKAGE_INSTALLABLE) == PACKAGE_INSTALLABLE) {
dc.SetTextForeground(lerp(color,Color(128,128,128),0.6));
dc.SetTextForeground(color);
dc.DrawText(_LABEL_("package installable"), x+1,y+2); dc.DrawText(_LABEL_("package installable"), x+1,y+2);
} }
} else if (column == 2 && ti.package) { } else if (column == 2 && ti.package) {
// Action // Action
int act = ti.package->action; int act = ti.package->action;
if (act & PACKAGE_INSTALL) { if (act & PACKAGE_INSTALL) {
dc.SetTextForeground(lerp(color,Color(0,255,0),0.5));
dc.DrawText(_LABEL_("install package"), x+1,y+2); dc.DrawText(_LABEL_("install package"), x+1,y+2);
} else if (act & PACKAGE_UPGRADE) { } else if (act & PACKAGE_UPGRADE) {
dc.SetTextForeground(lerp(color,Color(0,0,255),0.5));
dc.DrawText(_LABEL_("upgrade package"), x+1,y+2); dc.DrawText(_LABEL_("upgrade package"), x+1,y+2);
} else if (act & PACKAGE_REMOVE) { } else if (act & PACKAGE_REMOVE) {
dc.SetTextForeground(lerp(color,Color(255,0,0),0.5));
dc.DrawText(_LABEL_("remove package"), x+1,y+2); dc.DrawText(_LABEL_("remove package"), x+1,y+2);
} }
} }
...@@ -457,11 +369,16 @@ END_EVENT_TABLE() ...@@ -457,11 +369,16 @@ END_EVENT_TABLE()
PackagesWindow::PackagesWindow(Window* parent, bool download_package_list) PackagesWindow::PackagesWindow(Window* parent, bool download_package_list)
: wxDialog(parent, wxID_ANY, _TITLE_("package list"), wxDefaultPosition, wxSize(640,480), wxDEFAULT_DIALOG_STYLE | wxCLIP_CHILDREN | wxRESIZE_BORDER) : wxDialog(parent, wxID_ANY, _TITLE_("package list"), wxDefaultPosition, wxSize(640,480), wxDEFAULT_DIALOG_STYLE | wxCLIP_CHILDREN | wxRESIZE_BORDER)
, where(is_install_local(settings.install_type) ? PACKAGE_LOCAL : PACKAGE_GLOBAL) , where(is_install_local(settings.install_type) ? PACKAGE_LOCAL : PACKAGE_GLOBAL)
, waiting_for_list(download_package_list)
{ {
// request download before searching disk so we do two things at once
if (download_package_list) downloadable_installers.done();
// get packages // get packages
wxBusyCursor busy; wxBusyCursor busy;
packages.installedPackages(installable_packages); packages.installedPackages(installable_packages);
FOR_EACH(p, installable_packages) p->determineStatus(); FOR_EACH(p, installable_packages) p->determineStatus();
checkInstallerList();
// ui elements // ui elements
SetIcon(wxIcon()); SetIcon(wxIcon());
package_list = new PackageUpdateList(this, ID_PACKAGE_LIST); package_list = new PackageUpdateList(this, ID_PACKAGE_LIST);
...@@ -471,38 +388,8 @@ PackagesWindow::PackagesWindow(Window* parent, bool download_package_list) ...@@ -471,38 +388,8 @@ PackagesWindow::PackagesWindow(Window* parent, bool download_package_list)
wxButton* install_button = new wxButton(this, ID_INSTALL, _BUTTON_("install package")); wxButton* install_button = new wxButton(this, ID_INSTALL, _BUTTON_("install package"));
wxButton* upgrade_button = new wxButton(this, ID_UPGRADE, _BUTTON_("upgrade package")); wxButton* upgrade_button = new wxButton(this, ID_UPGRADE, _BUTTON_("upgrade package"));
wxButton* remove_button = new wxButton(this, ID_REMOVE, _BUTTON_("remove package")); wxButton* remove_button = new wxButton(this, ID_REMOVE, _BUTTON_("remove package"));
/*
description_window = new HtmlWindowToBrowser(this, wxID_ANY, wxDefaultPosition, wxSize(540,100), wxHW_SCROLLBAR_AUTO | wxSUNKEN_BORDER);
setDefaultPackageStatus();
(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"));
// Init sizer // Init sizer
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();
*/
/* wxBoxSizer *h2 = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer *h3 = new wxBoxSizer(wxHORIZONTAL);
h3->AddStretchSpacer();
h3->Add(apply_button);
h3->AddStretchSpacer();
// v->Add(h2);
// v->Add(h3);*/
wxBoxSizer* v = new wxBoxSizer(wxVERTICAL); wxBoxSizer* v = new wxBoxSizer(wxVERTICAL);
v->Add(package_list, 1, wxEXPAND | wxALL & ~wxBOTTOM, 8); v->Add(package_list, 1, wxEXPAND | wxALL & ~wxBOTTOM, 8);
v->AddSpacer(4); v->AddSpacer(4);
...@@ -522,16 +409,10 @@ PackagesWindow::PackagesWindow(Window* parent, bool download_package_list) ...@@ -522,16 +409,10 @@ PackagesWindow::PackagesWindow(Window* parent, bool download_package_list)
} }
PackagesWindow::~PackagesWindow() { PackagesWindow::~PackagesWindow() {
//(new WelcomeWindow)->Show();
} }
/*
void PackagesWindow::onUpdateCheckFinished(wxCommandEvent&) {
setDefaultPackageStatus();
}*/
void PackagesWindow::onPackageSelect(wxCommandEvent& ev) { void PackagesWindow::onPackageSelect(wxCommandEvent& ev) {
// updateButtons(package_list->getSelection());
package_info->setPackage(package = package_list->getSelection()); package_info->setPackage(package = package_list->getSelection());
UpdateWindowUI(wxUPDATE_UI_RECURSE); UpdateWindowUI(wxUPDATE_UI_RECURSE);
} }
...@@ -620,265 +501,32 @@ void PackagesWindow::onUpdateUI(wxUpdateUIEvent& ev) { ...@@ -620,265 +501,32 @@ void PackagesWindow::onUpdateUI(wxUpdateUIEvent& ev) {
} }
} }
/* void PackagesWindow::onIdle(wxIdleEvent& ev) {
void PackagesWindow::onActionChange(wxCommandEvent& ev) { ev.RequestMore(!checkInstallerList());
PackageVersionDataP pack = package_list->getSelection();
if (!pack) return;
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 PackagesWindow::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 (!remove_file_or_dir(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 PackagesWindow::updateButtons(const PackageVersionDataP& pack) {
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 PackagesWindow::setDefaultPackageStatus() { bool PackagesWindow::checkInstallerList() {
if (!update_version_data) return; if (!waiting_for_list) return true;
FOR_EACH(p, update_version_data->packages) { if (!downloadable_installers.done()) return false;
PackagedP pack; waiting_for_list = false;
try { pack = packages.openAny(p->name, true); } // merge installer lists
catch (PackageNotFoundError&) { } // We couldn't open a package... no cause for alarm FOR_EACH(inst, downloadable_installers.installers) {
merge(installable_packages, inst);
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 PackagesWindow::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 PackagesWindow::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 PackagesWindow::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;
}
}
}
} }
FOR_EACH(p, installable_packages) p->determineStatus();
// refresh
package_list->rebuild();
package_info->setPackage(package = package_list->getSelection());
UpdateWindowUI(wxUPDATE_UI_RECURSE);
return true;
} }
*/
BEGIN_EVENT_TABLE(PackagesWindow, wxDialog) BEGIN_EVENT_TABLE(PackagesWindow, wxDialog)
// EVT_COMMAND(wxID_ANY, UPDATE_CHECK_FINISHED_EVT, PackagesWindow::onUpdateCheckFinished)
EVT_LISTBOX(ID_PACKAGE_LIST, PackagesWindow::onPackageSelect) EVT_LISTBOX(ID_PACKAGE_LIST, PackagesWindow::onPackageSelect)
EVT_BUTTON(ID_INSTALL, PackagesWindow::onActionChange) EVT_BUTTON(ID_INSTALL, PackagesWindow::onActionChange)
EVT_BUTTON(ID_REMOVE, PackagesWindow::onActionChange) EVT_BUTTON(ID_REMOVE, PackagesWindow::onActionChange)
EVT_BUTTON(ID_UPGRADE, PackagesWindow::onActionChange) EVT_BUTTON(ID_UPGRADE, PackagesWindow::onActionChange)
EVT_BUTTON(wxID_OK, PackagesWindow::onOk) EVT_BUTTON(wxID_OK, PackagesWindow::onOk)
EVT_UPDATE_UI(wxID_ANY, PackagesWindow::onUpdateUI) EVT_UPDATE_UI(wxID_ANY, PackagesWindow::onUpdateUI)
EVT_IDLE ( PackagesWindow::onIdle)
END_EVENT_TABLE() END_EVENT_TABLE()
...@@ -44,13 +44,17 @@ class PackagesWindow : public wxDialog { ...@@ -44,13 +44,17 @@ class PackagesWindow : public wxDialog {
InstallablePackageP package; ///< Selected package InstallablePackageP package; ///< Selected package
PackageAction where; ///< Where to install? (PACKAGE_LOCAL or PACKAGE_GLOBAL) PackageAction where; ///< Where to install? (PACKAGE_LOCAL or PACKAGE_GLOBAL)
bool waiting_for_list; ///< waiting for the list of installers?
DECLARE_EVENT_TABLE(); DECLARE_EVENT_TABLE();
void onOk(wxCommandEvent&); void onOk(wxCommandEvent&);
void onActionChange(wxCommandEvent&); void onActionChange(wxCommandEvent&);
void onPackageSelect(wxCommandEvent&); void onPackageSelect(wxCommandEvent&);
void onUpdateUI(wxUpdateUIEvent&); void onUpdateUI(wxUpdateUIEvent&);
void onIdle(wxIdleEvent&);
bool checkInstallerList();
/* /*
wxHtmlWindow* description_window; wxHtmlWindow* description_window;
......
...@@ -14,49 +14,16 @@ ...@@ -14,49 +14,16 @@
#include <util/io/package_manager.hpp> #include <util/io/package_manager.hpp>
#include <util/version.hpp> #include <util/version.hpp>
#include <util/window_id.hpp> #include <util/window_id.hpp>
#include <script/value.hpp> // for some strange reason the profile build needs this :( //#include <script/value.hpp> // for some strange reason the profile build needs this :(
#include <script/to_value.hpp> //#include <script/to_value.hpp>
#include <wx/dialup.h> #include <wx/dialup.h>
#include <wx/url.h> #include <wx/url.h>
#include <wx/html/htmlwin.h>
//%DECLARE_POINTER_TYPE(PackageVersionData);
DECLARE_POINTER_TYPE(VersionData); DECLARE_POINTER_TYPE(VersionData);
DECLARE_TYPEOF_COLLECTION(PackageDependencyP); DECLARE_TYPEOF_COLLECTION(PackageDependencyP);
// ----------------------------------------------------------------------------- : Update data // ----------------------------------------------------------------------------- : Update data
/*
/// Information on available packages
class PackageVersionData : public IntrusivePtrVirtualBase {
public:
PackageVersionData() {}
String name; ///< Name of the package
String type; ///< Type of package ("magic style" or "game")
String display_name; ///< Name to show on package list.
String description; ///< html description
String url; ///< Where can the package be downloaded?
Version version; ///< Version number of the download
Version app_version; ///< The minimium version of MSE required
vector<PackageDependencyP> depends; ///< Packages this depends on
DECLARE_REFLECTION();
};
/// Information on the latest available version
class VersionData : public IntrusivePtrBase<VersionData> {
public:
Version version; ///< Latest version number of MSE
String description; ///< html description of the latest MSE release
String new_updates_url; ///< updates url has moved?
vector<PackageVersionDataP> packages; ///< Available packages
DECLARE_REFLECTION();
};
*/
/// Information on the latest available versions /// Information on the latest available versions
class VersionData : public IntrusivePtrBase<VersionData> { class VersionData : public IntrusivePtrBase<VersionData> {
public: public:
...@@ -66,25 +33,6 @@ class VersionData : public IntrusivePtrBase<VersionData> { ...@@ -66,25 +33,6 @@ class VersionData : public IntrusivePtrBase<VersionData> {
DECLARE_REFLECTION(); 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_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) { IMPLEMENT_REFLECTION_NO_SCRIPT(VersionData) {
REFLECT_NO_SCRIPT(packages); REFLECT_NO_SCRIPT(packages);
REFLECT_NO_SCRIPT(new_updates_url); REFLECT_NO_SCRIPT(new_updates_url);
...@@ -113,12 +61,6 @@ bool update_available() { ...@@ -113,12 +61,6 @@ bool update_available() {
// ----------------------------------------------------------------------------- : Update checking // ----------------------------------------------------------------------------- : Update checking
BEGIN_DECLARE_EVENT_TYPES()
DECLARE_EVENT_TYPE(UPDATE_CHECK_FINISHED_EVT, -1)
END_DECLARE_EVENT_TYPES()
DEFINE_EVENT_TYPE(UPDATE_CHECK_FINISHED_EVT)
// Thread to retrieve update information // Thread to retrieve update information
// Checks if the current version is the latest version // Checks if the current version is the latest version
// If not, displays a message // If not, displays a message
...@@ -182,36 +124,8 @@ void check_updates_now(bool async) { ...@@ -182,36 +124,8 @@ void check_updates_now(bool async) {
// ----------------------------------------------------------------------------- : Dialog // ----------------------------------------------------------------------------- : Dialog
// A HTML control that opens all pages in an actual browser
struct HtmlWindowToBrowser : public wxHtmlWindow {
HtmlWindowToBrowser(Window* parent, int id, const wxPoint& pos, const wxSize& size, long flags)
: wxHtmlWindow(parent, id, pos, size, flags)
{}
virtual void OnLinkClicked(const wxHtmlLinkInfo& info) {
wxLaunchDefaultBrowser( info.GetHref() );
}
};
void show_update_dialog(Window* parent) { void show_update_dialog(Window* parent) {
if (!update_available() || shown_dialog) return; // we already have the latest version, or this has already been displayed. if (!update_available() || shown_dialog) return; // we already have the latest version, or this has already been displayed.
shown_dialog = true; shown_dialog = true;
(new PackagesWindow(parent))->Show(); (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);
wxButton* close = new wxButton(dlg, wxID_OK, _BUTTON_("close"));
close->SetDefault();
// layout
wxSizer* s = new wxBoxSizer(wxVERTICAL);
s->Add(html, 1, wxEXPAND | wxALL, 8);
s->Add(close, 0, wxALIGN_RIGHT | wxALL & ~wxTOP, 8);
dlg->SetSizer(s);
dlg->SetSize(400,400);
dlg->Show();
// And never show it again this run
*/
} }
...@@ -2088,12 +2088,6 @@ ...@@ -2088,12 +2088,6 @@
<File <File
RelativePath=".\util\io\package_manager.hpp"> RelativePath=".\util\io\package_manager.hpp">
</File> </File>
<File
RelativePath=".\util\io\package_repository.cpp">
</File>
<File
RelativePath=".\util\io\package_repository.hpp">
</File>
<File <File
RelativePath=".\util\io\reader.cpp"> RelativePath=".\util\io\reader.cpp">
<FileConfiguration <FileConfiguration
......
...@@ -156,6 +156,8 @@ void PackageManager::installedPackages(vector<InstallablePackageP>& packages) { ...@@ -156,6 +156,8 @@ void PackageManager::installedPackages(vector<InstallablePackageP>& packages) {
merge(packages, more_packages); merge(packages, more_packages);
// the magic appliation package // the magic appliation package
packages.push_back(mse_installable_package()); packages.push_back(mse_installable_package());
// invariant: sorted:
sort(packages);
} }
void PackageManager::install(const InstallablePackage& package) { void PackageManager::install(const InstallablePackage& package) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment