mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-13 14:07:01 -04:00
Put PackageUpdateList into its own file
git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@904 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
@@ -254,9 +254,9 @@ DownloadableInstaller::~DownloadableInstaller() {
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Installable package
|
// ----------------------------------------------------------------------------- : Installable package
|
||||||
|
|
||||||
InstallablePackage::InstallablePackage(const PackageVersionP& installed, const PackageDescriptionP& description)
|
InstallablePackage::InstallablePackage(const PackageDescriptionP& description, const PackageVersionP& installed)
|
||||||
: installed(installed)
|
: description(description)
|
||||||
, description(description)
|
, installed(installed)
|
||||||
, status(PACKAGE_INSTALLED)
|
, status(PACKAGE_INSTALLED)
|
||||||
, action(PACKAGE_NOTHING)
|
, action(PACKAGE_NOTHING)
|
||||||
{}
|
{}
|
||||||
@@ -586,5 +586,5 @@ InstallablePackageP mse_installable_package() {
|
|||||||
mse_description->position_hint = -100;
|
mse_description->position_hint = -100;
|
||||||
mse_description->icon = load_resource_image(_("installer_program"));
|
mse_description->icon = load_resource_image(_("installer_program"));
|
||||||
//mse_description->description = _LABEL_("magic set editor package");
|
//mse_description->description = _LABEL_("magic set editor package");
|
||||||
return new_intrusive2<InstallablePackage>(mse_version,mse_description);
|
return new_intrusive2<InstallablePackage>(mse_description, mse_version);
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-3
@@ -18,6 +18,13 @@ DECLARE_POINTER_TYPE(PackageDescription);
|
|||||||
DECLARE_POINTER_TYPE(DownloadableInstaller);
|
DECLARE_POINTER_TYPE(DownloadableInstaller);
|
||||||
DECLARE_POINTER_TYPE(InstallablePackage);
|
DECLARE_POINTER_TYPE(InstallablePackage);
|
||||||
|
|
||||||
|
// The installer system consists of several layers:
|
||||||
|
// - Installer = an actual package available in memory, containing packages to be installed
|
||||||
|
// - DownloadableInstaller = an installar (possibly) not yet available, i.e. just its URL
|
||||||
|
// - PackageDescription = description of a package version
|
||||||
|
// - InstallablePackage = the complete status of a package, both local and remote
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Installer
|
// ----------------------------------------------------------------------------- : Installer
|
||||||
|
|
||||||
/// A package that contains other packages that can be installed
|
/// A package that contains other packages that can be installed
|
||||||
@@ -125,12 +132,13 @@ inline bool flag(int flags, int flag) { return (flags & flag) == flag; }
|
|||||||
/// A package that can be installed, or is already installed
|
/// A package that can be installed, or is already installed
|
||||||
class InstallablePackage : public IntrusivePtrVirtualBase {
|
class InstallablePackage : public IntrusivePtrVirtualBase {
|
||||||
public:
|
public:
|
||||||
//InstallablePackage();
|
/// A new package
|
||||||
InstallablePackage(const PackageDescriptionP&, const DownloadableInstallerP&);
|
InstallablePackage(const PackageDescriptionP&, const DownloadableInstallerP&);
|
||||||
InstallablePackage(const PackageVersionP&, const PackageDescriptionP&);
|
/// An installed package
|
||||||
|
InstallablePackage(const PackageDescriptionP&, const PackageVersionP&);
|
||||||
|
|
||||||
PackageVersionP installed; ///< The information of the installed package (if installed)
|
|
||||||
PackageDescriptionP description; ///< The details of the package. Either from the installed package or from an installer
|
PackageDescriptionP description; ///< The details of the package. Either from the installed package or from an installer
|
||||||
|
PackageVersionP installed; ///< The information of the installed package (if installed)
|
||||||
DownloadableInstallerP installer; ///< The installer to install from (if updates are available)
|
DownloadableInstallerP installer; ///< The installer to install from (if updates are available)
|
||||||
PackageStatus status; ///< Status of installation
|
PackageStatus status; ///< Status of installation
|
||||||
PackageAction action; ///< What to do with this package?
|
PackageAction action; ///< What to do with this package?
|
||||||
|
|||||||
@@ -0,0 +1,298 @@
|
|||||||
|
//+----------------------------------------------------------------------------+
|
||||||
|
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
|
||||||
|
//| Copyright: (C) 2001 - 2008 Twan van Laarhoven and "coppro" |
|
||||||
|
//| License: GNU General Public License 2 or later (see file COPYING) |
|
||||||
|
//+----------------------------------------------------------------------------+
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : Includes
|
||||||
|
|
||||||
|
#include <util/prec.hpp>
|
||||||
|
#include <gui/package_update_list.hpp>
|
||||||
|
#include <gui/thumbnail_thread.hpp>
|
||||||
|
#include <gui/util.hpp>
|
||||||
|
#include <gfx/gfx.hpp>
|
||||||
|
#include <boost/scoped_ptr.hpp>
|
||||||
|
#include <wx/url.h>
|
||||||
|
|
||||||
|
DECLARE_TYPEOF_COLLECTION(InstallablePackageP);
|
||||||
|
DECLARE_TYPEOF_COLLECTION(PackageUpdateList::TreeItemP);
|
||||||
|
DECLARE_TYPEOF_COLLECTION(TreeList::ItemP);
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : PackageUpdateList::TreeItem
|
||||||
|
|
||||||
|
void PackageUpdateList::TreeItem::add(const InstallablePackageP& package, const String& path, int level) {
|
||||||
|
// this node
|
||||||
|
this->level = level;
|
||||||
|
PackageType new_type = package_type(*package->description);
|
||||||
|
int new_hint = package->description->position_hint;
|
||||||
|
if (new_type < position_type || (new_type == position_type && new_hint < position_hint)) {
|
||||||
|
// this is a lower position hint, use it
|
||||||
|
position_type = new_type;
|
||||||
|
position_hint = new_hint;
|
||||||
|
}
|
||||||
|
// end of the path?
|
||||||
|
if (path.empty()) {
|
||||||
|
assert(!this->package);
|
||||||
|
this->package = package;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// split path
|
||||||
|
size_t pos = path.find_first_of(_('/'));
|
||||||
|
String name = path.substr(0,pos);
|
||||||
|
String rest = pos == String::npos ? _("") : path.substr(pos+1);
|
||||||
|
// find/add child
|
||||||
|
FOR_EACH(ti, children) {
|
||||||
|
if (ti->label == name) {
|
||||||
|
// already have this child
|
||||||
|
if (pos == String::npos && ti->package) {
|
||||||
|
// two packages with the same path
|
||||||
|
TreeItemP ti2(new TreeItem);
|
||||||
|
ti2->label = name;
|
||||||
|
children.insert(ti_IT.first, ti2);
|
||||||
|
ti2->add(package, rest, level + 1);
|
||||||
|
} else {
|
||||||
|
ti->add(package, rest, level + 1);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// don't have this child
|
||||||
|
TreeItemP ti(new TreeItem);
|
||||||
|
children.push_back(ti);
|
||||||
|
ti->label = name;
|
||||||
|
ti->add(package, rest, level + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool compare_pos_hint(const PackageUpdateList::TreeItemP& a, const PackageUpdateList::TreeItemP& b) {
|
||||||
|
if (a->position_type < b->position_type) return true;
|
||||||
|
if (a->position_type > b->position_type) return false;
|
||||||
|
if (a->position_hint < b->position_hint) return true;
|
||||||
|
if (a->position_hint > b->position_hint) return false;
|
||||||
|
return a->label < b->label;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PackageUpdateList::TreeItem::toItems(vector<TreeList::ItemP>& items) {
|
||||||
|
sort(children.begin(), children.end(), compare_pos_hint);
|
||||||
|
FOR_EACH(c, children) {
|
||||||
|
items.push_back(c);
|
||||||
|
c->toItems(items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PackageUpdateList::TreeItem::highlight() const {
|
||||||
|
if (package && package->willBeInstalled()) return true;
|
||||||
|
FOR_EACH_CONST(c,children) if (c->highlight()) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PackageUpdateList::TreeItem::PackageType PackageUpdateList::TreeItem::package_type(const PackageDescription& desc) {
|
||||||
|
if (desc.name == mse_package) return TYPE_PROG;
|
||||||
|
size_t pos = desc.name.find_last_of(_('.'));
|
||||||
|
if (pos == String::npos) return TYPE_OTHER;
|
||||||
|
if (is_substr(desc.name,pos,_(".mse-locale"))) return TYPE_LOCALE;
|
||||||
|
if (is_substr(desc.name,pos,_(".mse-game"))) return TYPE_GAME;
|
||||||
|
if (is_substr(desc.name,pos,_(".mse-style"))) return TYPE_STYLESHEET;
|
||||||
|
if (is_substr(desc.name,pos,_(".mse-export-template"))) return TYPE_EXPORT_TEMPLATE;
|
||||||
|
if (is_substr(desc.name,pos,_(".mse-symbol-font"))) return TYPE_SYMBOL_FONT;
|
||||||
|
if (is_substr(desc.name,pos,_(".mse-include"))) return TYPE_INCLUDE;
|
||||||
|
if (is_substr(desc.name,pos,_(".ttf"))) return TYPE_FONT;
|
||||||
|
return TYPE_OTHER;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PackageUpdateList::TreeItem::setIcon(const Image& img) {
|
||||||
|
Image image = img;
|
||||||
|
int iw = image.GetWidth(), ih = image.GetHeight();
|
||||||
|
if (ih > 107) {
|
||||||
|
int w = 107 * iw / ih;
|
||||||
|
image = resample(image, w, 107);
|
||||||
|
} else if (iw > 107) {
|
||||||
|
int h = 107 * ih / iw;
|
||||||
|
image = resample(image, 107, h);
|
||||||
|
}
|
||||||
|
if (package) package->description->icon = image;
|
||||||
|
Image resampled = resample_preserve_aspect(image,16,16);
|
||||||
|
icon = Bitmap(resampled);
|
||||||
|
saturate(resampled, -.75);
|
||||||
|
set_alpha(resampled,0.5);
|
||||||
|
icon_grey = Bitmap(resampled);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : PackageIconRequest
|
||||||
|
|
||||||
|
/// wx doesn't allow seeking on InputStreams from a wxURL
|
||||||
|
/// The built in buffer class is too stupid to seek, so we must do it ourselfs
|
||||||
|
class SeekAtStartInputStream : public wxFilterInputStream {
|
||||||
|
public:
|
||||||
|
SeekAtStartInputStream(wxInputStream& stream)
|
||||||
|
: wxFilterInputStream(stream)
|
||||||
|
, buffer_pos(0)
|
||||||
|
{
|
||||||
|
m_parent_i_stream->Read(buffer, 1024);
|
||||||
|
buffer_size = m_parent_i_stream->LastRead();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsSeekable() const { return true; }
|
||||||
|
protected:
|
||||||
|
virtual size_t OnSysRead(void *buffer, size_t bufsize) {
|
||||||
|
size_t len = min(buffer_size - buffer_pos, bufsize);
|
||||||
|
memcpy(buffer, this->buffer + buffer_pos, len);
|
||||||
|
buffer_pos += len;
|
||||||
|
m_parent_i_stream->Read((Byte*)buffer + len, bufsize - len);
|
||||||
|
return m_parent_i_stream->LastRead() + len;
|
||||||
|
}
|
||||||
|
virtual wxFileOffset OnSysSeek(wxFileOffset seek, wxSeekMode mode) {
|
||||||
|
if (mode == wxFromStart) buffer_pos = seek;
|
||||||
|
else if (mode == wxFromCurrent) buffer_pos += seek;
|
||||||
|
else assert(false);
|
||||||
|
assert(buffer_pos < buffer_size);
|
||||||
|
return buffer_pos;
|
||||||
|
}
|
||||||
|
virtual wxFileOffset OnSysTell() const {
|
||||||
|
assert(buffer_pos < buffer_size);
|
||||||
|
return buffer_pos;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
size_t buffer_size, buffer_pos;
|
||||||
|
Byte buffer[1024];
|
||||||
|
};
|
||||||
|
|
||||||
|
class PackageIconRequest : public ThumbnailRequest {
|
||||||
|
public:
|
||||||
|
PackageIconRequest(PackageUpdateList* list, PackageUpdateList::TreeItem* ti)
|
||||||
|
: ThumbnailRequest(
|
||||||
|
list,
|
||||||
|
_("package_") + ti->package->description->icon_url + _("_") + ti->package->description->version.toString(),
|
||||||
|
wxDateTime(1,wxDateTime::Jan,2000))
|
||||||
|
, list(list), ti(ti)
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual Image generate() {
|
||||||
|
wxURL url(ti->package->description->icon_url);
|
||||||
|
scoped_ptr<wxInputStream> isP(url.GetInputStream());
|
||||||
|
if (!isP) return wxImage();
|
||||||
|
SeekAtStartInputStream is2(*isP);
|
||||||
|
Image result(is2);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
virtual void store(const Image& image) {
|
||||||
|
if (!image.Ok()) return;
|
||||||
|
ti->setIcon(image);
|
||||||
|
list->Refresh(false);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
PackageUpdateList* list;
|
||||||
|
PackageUpdateList::TreeItem* ti;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : PackageUpdateList : implementation
|
||||||
|
|
||||||
|
PackageUpdateList::PackageUpdateList(Window* parent, const InstallablePackages& packages, int id)
|
||||||
|
: TreeList(parent, id)
|
||||||
|
, packages(packages)
|
||||||
|
{
|
||||||
|
item_height = max(item_height,17);
|
||||||
|
rebuild();
|
||||||
|
}
|
||||||
|
PackageUpdateList::~PackageUpdateList() {
|
||||||
|
thumbnail_thread.abort(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PackageUpdateList::initItems() {
|
||||||
|
// add packages to tree
|
||||||
|
TreeItem root;
|
||||||
|
FOR_EACH_CONST(ip, packages) {
|
||||||
|
String group = ip->description->installer_group;
|
||||||
|
if (group.empty()) group = _("custom");
|
||||||
|
root.add(ip, group);
|
||||||
|
}
|
||||||
|
// tree to treelist items
|
||||||
|
items.clear();
|
||||||
|
root.toItems(items);
|
||||||
|
// init image list
|
||||||
|
FOR_EACH(i,items) {
|
||||||
|
TreeItem& ti = static_cast<TreeItem&>(*i);
|
||||||
|
const InstallablePackageP& p = ti.package;
|
||||||
|
// load icon
|
||||||
|
Image image;
|
||||||
|
if (p && p->description->icon.Ok()) { // it has an icon
|
||||||
|
ti.setIcon(p->description->icon);
|
||||||
|
} else if (p) { // it doesn't have an icon (yet)
|
||||||
|
ti.setIcon(load_resource_image(_("installer_package")));
|
||||||
|
if (!p->description->icon_url.empty()) {
|
||||||
|
// download icon
|
||||||
|
thumbnail_thread.request(new_intrusive2<PackageIconRequest>(this,&ti));
|
||||||
|
}
|
||||||
|
} else if (ti.position_type == TreeItem::TYPE_LOCALE) { // locale folder
|
||||||
|
ti.setIcon(load_resource_image(_("installer_locales")));
|
||||||
|
} else { // other folder
|
||||||
|
ti.setIcon(load_resource_image(_("installer_group")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PackageUpdateList::drawItem(DC& dc, size_t index, size_t column, int x, int y, bool selected) const {
|
||||||
|
const TreeItem& ti = static_cast<const TreeItem&>(*items[index]);
|
||||||
|
Color color = wxSystemSettings::GetColour(selected ? wxSYS_COLOUR_HIGHLIGHTTEXT : wxSYS_COLOUR_WINDOWTEXT);
|
||||||
|
if (column == 0) {
|
||||||
|
// Name
|
||||||
|
const Bitmap& bmp = ti.highlight() ? ti.icon : ti.icon_grey;
|
||||||
|
if (bmp.Ok()) dc.DrawBitmap(bmp,x,y);
|
||||||
|
dc.SetTextForeground(color);
|
||||||
|
dc.DrawText(capitalize_sentence(ti.label), x+18, y+2);
|
||||||
|
} else if (column == 1 && ti.package) {
|
||||||
|
// Status
|
||||||
|
int stat = ti.package->status;
|
||||||
|
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);
|
||||||
|
} 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);
|
||||||
|
} 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);
|
||||||
|
} else if ((stat & PACKAGE_INSTALLED) == PACKAGE_INSTALLED) {
|
||||||
|
dc.SetTextForeground(color);
|
||||||
|
dc.DrawText(_LABEL_("package installed"), x+1,y+2);
|
||||||
|
} 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);
|
||||||
|
}
|
||||||
|
} else if (column == 2 && ti.package) {
|
||||||
|
// Action
|
||||||
|
int act = ti.package->action;
|
||||||
|
if (act & PACKAGE_INSTALL) {
|
||||||
|
if (ti.package->status & PACKAGE_INSTALLED) {
|
||||||
|
dc.SetTextForeground(lerp(color,Color(0,0,255),0.5));
|
||||||
|
dc.DrawText(_LABEL_("upgrade package"), x+1,y+2);
|
||||||
|
} else {
|
||||||
|
dc.SetTextForeground(lerp(color,Color(0,255,0),0.5));
|
||||||
|
dc.DrawText(_LABEL_("install package"), x+1,y+2);
|
||||||
|
}
|
||||||
|
} else if (act & PACKAGE_REMOVE) {
|
||||||
|
dc.SetTextForeground(lerp(color,Color(255,0,0),0.5));
|
||||||
|
dc.DrawText(_LABEL_("remove package"), x+1,y+2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String PackageUpdateList::columnText(size_t column) const {
|
||||||
|
if (column == 0) return _LABEL_("package name");
|
||||||
|
else if (column == 1) return _LABEL_("package status");
|
||||||
|
else if (column == 2) return _LABEL_("package action");
|
||||||
|
else throw InternalError(_("Unknown column"));
|
||||||
|
}
|
||||||
|
|
||||||
|
int PackageUpdateList::columnWidth(size_t column) const {
|
||||||
|
if (column == 0) {
|
||||||
|
wxSize cs = GetClientSize();
|
||||||
|
return cs.x - 300;
|
||||||
|
} else {
|
||||||
|
return 150;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
//+----------------------------------------------------------------------------+
|
||||||
|
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
|
||||||
|
//| Copyright: (C) 2001 - 2008 Twan van Laarhoven and "coppro" |
|
||||||
|
//| License: GNU General Public License 2 or later (see file COPYING) |
|
||||||
|
//+----------------------------------------------------------------------------+
|
||||||
|
|
||||||
|
#ifndef HEADER_GUI_PACKAGE_UPDATE_LIST
|
||||||
|
#define HEADER_GUI_PACKAGE_UPDATE_LIST
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : Includes
|
||||||
|
|
||||||
|
#include <util/prec.hpp>
|
||||||
|
#include <gui/control/tree_list.hpp>
|
||||||
|
#include <data/installer.hpp>
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : PackageUpdateList
|
||||||
|
|
||||||
|
/// A list of installed and downloadable packages
|
||||||
|
class PackageUpdateList : public TreeList {
|
||||||
|
public:
|
||||||
|
PackageUpdateList(Window* parent, const InstallablePackages& packages, int id = wxID_ANY);
|
||||||
|
~PackageUpdateList();
|
||||||
|
|
||||||
|
inline InstallablePackageP getSelection() const {
|
||||||
|
return selection == NOTHING ? InstallablePackageP() : get(selection);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline InstallablePackageP get(size_t item) const {
|
||||||
|
return static_pointer_cast<TreeItem>(items[item])->package;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// overridden methods from TreeList
|
||||||
|
virtual void initItems();
|
||||||
|
virtual void drawItem(DC& dc, size_t index, size_t column, int x, int y, bool selected) const;
|
||||||
|
|
||||||
|
virtual size_t columnCount() const { return 3; }
|
||||||
|
virtual String columnText(size_t column) const;
|
||||||
|
virtual int columnWidth(size_t column) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const InstallablePackages& packages;
|
||||||
|
|
||||||
|
class TreeItem;
|
||||||
|
public:
|
||||||
|
typedef intrusive_ptr<TreeItem> TreeItemP;
|
||||||
|
private:
|
||||||
|
class TreeItem : public Item {
|
||||||
|
public:
|
||||||
|
TreeItem() : position_type(TYPE_OTHER), position_hint(1000000) {}
|
||||||
|
String label;
|
||||||
|
vector<TreeItemP> children;
|
||||||
|
InstallablePackageP package;
|
||||||
|
Bitmap icon, icon_grey;
|
||||||
|
// positioning
|
||||||
|
enum PackageType {
|
||||||
|
TYPE_PROG,
|
||||||
|
TYPE_LOCALE,
|
||||||
|
TYPE_GAME,
|
||||||
|
TYPE_STYLESHEET,
|
||||||
|
TYPE_EXPORT_TEMPLATE,
|
||||||
|
TYPE_SYMBOL_FONT,
|
||||||
|
TYPE_INCLUDE,
|
||||||
|
TYPE_FONT,
|
||||||
|
TYPE_OTHER,
|
||||||
|
} position_type;
|
||||||
|
int position_hint;
|
||||||
|
|
||||||
|
void add(const InstallablePackageP& package, const String& path, int level = -1);
|
||||||
|
void toItems(vector<TreeList::ItemP>& items);
|
||||||
|
void setIcon(const Image& image);
|
||||||
|
bool highlight() const;
|
||||||
|
|
||||||
|
static PackageType package_type(const PackageDescription& desc);
|
||||||
|
};
|
||||||
|
friend class PackageIconRequest;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : EOF
|
||||||
|
#endif
|
||||||
+3
-340
@@ -8,15 +8,11 @@
|
|||||||
|
|
||||||
#include <util/prec.hpp>
|
#include <util/prec.hpp>
|
||||||
#include <gui/packages_window.hpp>
|
#include <gui/packages_window.hpp>
|
||||||
#include <gui/control/tree_list.hpp>
|
#include <gui/package_update_list.hpp>
|
||||||
#include <gui/thumbnail_thread.hpp>
|
|
||||||
#include <gui/util.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 <boost/scoped_ptr.hpp>
|
|
||||||
#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>
|
||||||
@@ -29,7 +25,6 @@ DECLARE_POINTER_TYPE(Installer);
|
|||||||
DECLARE_TYPEOF_COLLECTION(PackageDependencyP);
|
DECLARE_TYPEOF_COLLECTION(PackageDependencyP);
|
||||||
DECLARE_TYPEOF_COLLECTION(InstallablePackageP);
|
DECLARE_TYPEOF_COLLECTION(InstallablePackageP);
|
||||||
DECLARE_TYPEOF_COLLECTION(DownloadableInstallerP);
|
DECLARE_TYPEOF_COLLECTION(DownloadableInstallerP);
|
||||||
DECLARE_TYPEOF_COLLECTION(TreeList::ItemP);
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : TODO: MOVE
|
// ----------------------------------------------------------------------------- : TODO: MOVE
|
||||||
|
|
||||||
@@ -102,341 +97,9 @@ wxThread::ExitCode DownloadableInstallerList::Thread::Entry() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : PackageUpdateList
|
|
||||||
|
|
||||||
/// A list of installed and downloadable packages
|
|
||||||
class PackageUpdateList : public TreeList {
|
|
||||||
public:
|
|
||||||
PackageUpdateList(PackagesWindow* parent, int id = wxID_ANY)
|
|
||||||
: TreeList(parent, id)
|
|
||||||
, parent(parent)
|
|
||||||
{
|
|
||||||
item_height = max(item_height,17);
|
|
||||||
rebuild();
|
|
||||||
}
|
|
||||||
~PackageUpdateList() {
|
|
||||||
thumbnail_thread.abort(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
InstallablePackageP getSelection() const {
|
|
||||||
return selection == NOTHING ? InstallablePackageP() : get(selection);
|
|
||||||
}
|
|
||||||
|
|
||||||
InstallablePackageP get(size_t item) const {
|
|
||||||
return static_pointer_cast<TreeItem>(items[item])->package;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void initItems();
|
|
||||||
virtual void drawItem(DC& dc, size_t index, size_t column, int x, int y, bool selected) const;
|
|
||||||
|
|
||||||
virtual size_t columnCount() const { return 3; }
|
|
||||||
virtual String columnText(size_t column) const;
|
|
||||||
virtual int columnWidth(size_t column) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
PackagesWindow* parent;
|
|
||||||
public:
|
|
||||||
class TreeItem;
|
|
||||||
typedef intrusive_ptr<TreeItem> TreeItemP;
|
|
||||||
class TreeItem : public Item {
|
|
||||||
public:
|
|
||||||
TreeItem() : position_type(TYPE_OTHER), position_hint(1000000) {}
|
|
||||||
String label;
|
|
||||||
vector<TreeItemP> children;
|
|
||||||
InstallablePackageP package;
|
|
||||||
Bitmap icon, icon_grey;
|
|
||||||
// positioning
|
|
||||||
enum PackageType {
|
|
||||||
TYPE_PROG,
|
|
||||||
TYPE_LOCALE,
|
|
||||||
TYPE_GAME,
|
|
||||||
TYPE_STYLESHEET,
|
|
||||||
TYPE_EXPORT_TEMPLATE,
|
|
||||||
TYPE_SYMBOL_FONT,
|
|
||||||
TYPE_INCLUDE,
|
|
||||||
TYPE_FONT,
|
|
||||||
TYPE_OTHER,
|
|
||||||
} position_type;
|
|
||||||
int position_hint;
|
|
||||||
|
|
||||||
void add(const InstallablePackageP& package, const String& path, int level = -1);
|
|
||||||
void toItems(vector<TreeList::ItemP>& items);
|
|
||||||
void setIcon(const Image& image);
|
|
||||||
bool highlight() const;
|
|
||||||
|
|
||||||
static PackageType package_type(const PackageDescription& desc);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : PackageUpdateList::TreeItem
|
|
||||||
|
|
||||||
DECLARE_TYPEOF_COLLECTION(PackageUpdateList::TreeItemP);
|
|
||||||
|
|
||||||
|
|
||||||
void PackageUpdateList::TreeItem::add(const InstallablePackageP& package, const String& path, int level) {
|
|
||||||
// this node
|
|
||||||
this->level = level;
|
|
||||||
PackageType new_type = package_type(*package->description);
|
|
||||||
int new_hint = package->description->position_hint;
|
|
||||||
if (new_type < position_type || (new_type == position_type && new_hint < position_hint)) {
|
|
||||||
// this is a lower position hint, use it
|
|
||||||
position_type = new_type;
|
|
||||||
position_hint = new_hint;
|
|
||||||
}
|
|
||||||
// end of the path?
|
|
||||||
if (path.empty()) {
|
|
||||||
assert(!this->package);
|
|
||||||
this->package = package;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// split path
|
|
||||||
size_t pos = path.find_first_of(_('/'));
|
|
||||||
String name = path.substr(0,pos);
|
|
||||||
String rest = pos == String::npos ? _("") : path.substr(pos+1);
|
|
||||||
// find/add child
|
|
||||||
FOR_EACH(ti, children) {
|
|
||||||
if (ti->label == name) {
|
|
||||||
// already have this child
|
|
||||||
if (pos == String::npos && ti->package) {
|
|
||||||
// two packages with the same path
|
|
||||||
TreeItemP ti2(new TreeItem);
|
|
||||||
ti2->label = name;
|
|
||||||
children.insert(ti_IT.first, ti2);
|
|
||||||
ti2->add(package, rest, level + 1);
|
|
||||||
} else {
|
|
||||||
ti->add(package, rest, level + 1);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// don't have this child
|
|
||||||
TreeItemP ti(new TreeItem);
|
|
||||||
children.push_back(ti);
|
|
||||||
ti->label = name;
|
|
||||||
ti->add(package, rest, level + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool compare_pos_hint(const PackageUpdateList::TreeItemP& a, const PackageUpdateList::TreeItemP& b) {
|
|
||||||
if (a->position_type < b->position_type) return true;
|
|
||||||
if (a->position_type > b->position_type) return false;
|
|
||||||
if (a->position_hint < b->position_hint) return true;
|
|
||||||
if (a->position_hint > b->position_hint) return false;
|
|
||||||
return a->label < b->label;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PackageUpdateList::TreeItem::toItems(vector<TreeList::ItemP>& items) {
|
|
||||||
sort(children.begin(), children.end(), compare_pos_hint);
|
|
||||||
FOR_EACH(c, children) {
|
|
||||||
items.push_back(c);
|
|
||||||
c->toItems(items);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PackageUpdateList::TreeItem::highlight() const {
|
|
||||||
if (package && package->willBeInstalled()) return true;
|
|
||||||
FOR_EACH_CONST(c,children) if (c->highlight()) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
PackageUpdateList::TreeItem::PackageType PackageUpdateList::TreeItem::package_type(const PackageDescription& desc) {
|
|
||||||
if (desc.name == mse_package) return TYPE_PROG;
|
|
||||||
size_t pos = desc.name.find_last_of(_('.'));
|
|
||||||
if (pos == String::npos) return TYPE_OTHER;
|
|
||||||
if (is_substr(desc.name,pos,_(".mse-locale"))) return TYPE_LOCALE;
|
|
||||||
if (is_substr(desc.name,pos,_(".mse-game"))) return TYPE_GAME;
|
|
||||||
if (is_substr(desc.name,pos,_(".mse-style"))) return TYPE_STYLESHEET;
|
|
||||||
if (is_substr(desc.name,pos,_(".mse-export-template"))) return TYPE_EXPORT_TEMPLATE;
|
|
||||||
if (is_substr(desc.name,pos,_(".mse-symbol-font"))) return TYPE_SYMBOL_FONT;
|
|
||||||
if (is_substr(desc.name,pos,_(".mse-include"))) return TYPE_INCLUDE;
|
|
||||||
if (is_substr(desc.name,pos,_(".ttf"))) return TYPE_FONT;
|
|
||||||
return TYPE_OTHER;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PackageUpdateList::TreeItem::setIcon(const Image& img) {
|
|
||||||
Image image = img;
|
|
||||||
int iw = image.GetWidth(), ih = image.GetHeight();
|
|
||||||
if (ih > 107) {
|
|
||||||
int w = 107 * iw / ih;
|
|
||||||
image = resample(image, w, 107);
|
|
||||||
} else if (iw > 107) {
|
|
||||||
int h = 107 * ih / iw;
|
|
||||||
image = resample(image, 107, h);
|
|
||||||
}
|
|
||||||
if (package) package->description->icon = image;
|
|
||||||
Image resampled = resample_preserve_aspect(image,16,16);
|
|
||||||
icon = Bitmap(resampled);
|
|
||||||
saturate(resampled, -.75);
|
|
||||||
set_alpha(resampled,0.5);
|
|
||||||
icon_grey = Bitmap(resampled);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : PackageIconRequest
|
|
||||||
|
|
||||||
/// wx doesn't allow seeking on InputStreams from a wxURL
|
|
||||||
/// The built in buffer class is too stupid to seek, so we must do it ourselfs
|
|
||||||
class SeekAtStartInputStream : public wxFilterInputStream {
|
|
||||||
public:
|
|
||||||
SeekAtStartInputStream(wxInputStream& stream)
|
|
||||||
: wxFilterInputStream(stream)
|
|
||||||
, buffer_pos(0)
|
|
||||||
{
|
|
||||||
m_parent_i_stream->Read(buffer, 1024);
|
|
||||||
buffer_size = m_parent_i_stream->LastRead();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsSeekable() const { return true; }
|
|
||||||
protected:
|
|
||||||
virtual size_t OnSysRead(void *buffer, size_t bufsize) {
|
|
||||||
size_t len = min(buffer_size - buffer_pos, bufsize);
|
|
||||||
memcpy(buffer, this->buffer + buffer_pos, len);
|
|
||||||
buffer_pos += len;
|
|
||||||
m_parent_i_stream->Read((Byte*)buffer + len, bufsize - len);
|
|
||||||
return m_parent_i_stream->LastRead() + len;
|
|
||||||
}
|
|
||||||
virtual wxFileOffset OnSysSeek(wxFileOffset seek, wxSeekMode mode) {
|
|
||||||
if (mode == wxFromStart) buffer_pos = seek;
|
|
||||||
else if (mode == wxFromCurrent) buffer_pos += seek;
|
|
||||||
else assert(false);
|
|
||||||
assert(buffer_pos < buffer_size);
|
|
||||||
return buffer_pos;
|
|
||||||
}
|
|
||||||
virtual wxFileOffset OnSysTell() const {
|
|
||||||
assert(buffer_pos < buffer_size);
|
|
||||||
return buffer_pos;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
size_t buffer_size, buffer_pos;
|
|
||||||
Byte buffer[1024];
|
|
||||||
};
|
|
||||||
|
|
||||||
class PackageIconRequest : public ThumbnailRequest {
|
|
||||||
public:
|
|
||||||
PackageIconRequest(PackageUpdateList* list, PackageUpdateList::TreeItem* ti)
|
|
||||||
: ThumbnailRequest(
|
|
||||||
list,
|
|
||||||
_("package_") + ti->package->description->icon_url + _("_") + ti->package->description->version.toString(),
|
|
||||||
wxDateTime(1,wxDateTime::Jan,2000))
|
|
||||||
, list(list), ti(ti)
|
|
||||||
{}
|
|
||||||
|
|
||||||
virtual Image generate() {
|
|
||||||
wxURL url(ti->package->description->icon_url);
|
|
||||||
scoped_ptr<wxInputStream> isP(url.GetInputStream());
|
|
||||||
if (!isP) return wxImage();
|
|
||||||
SeekAtStartInputStream is2(*isP);
|
|
||||||
Image result(is2);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
virtual void store(const Image& image) {
|
|
||||||
if (!image.Ok()) return;
|
|
||||||
ti->setIcon(image);
|
|
||||||
list->Refresh(false);
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
PackageUpdateList* list;
|
|
||||||
PackageUpdateList::TreeItem* ti;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : PackageUpdateList : implementation
|
|
||||||
|
|
||||||
void PackageUpdateList::initItems() {
|
|
||||||
// packages to tree
|
|
||||||
TreeItem root;
|
|
||||||
FOR_EACH(ip, parent->installable_packages) {
|
|
||||||
String group = ip->description->installer_group;
|
|
||||||
if (group.empty()) group = _("custom");
|
|
||||||
root.add(ip, group);
|
|
||||||
}
|
|
||||||
// tree to treelist items
|
|
||||||
items.clear();
|
|
||||||
root.toItems(items);
|
|
||||||
// init image list
|
|
||||||
FOR_EACH(i,items) {
|
|
||||||
TreeItem& ti = static_cast<TreeItem&>(*i);
|
|
||||||
const InstallablePackageP& p = ti.package;
|
|
||||||
Image image;
|
|
||||||
if (p && p->description->icon.Ok()) {
|
|
||||||
ti.setIcon(p->description->icon);
|
|
||||||
} else if (p) {
|
|
||||||
ti.setIcon(load_resource_image(_("installer_package")));
|
|
||||||
if (!p->description->icon_url.empty()) {
|
|
||||||
// download icon
|
|
||||||
thumbnail_thread.request(new_intrusive2<PackageIconRequest>(this,&ti));
|
|
||||||
}
|
|
||||||
} else if (ti.position_type == TreeItem::TYPE_LOCALE) {
|
|
||||||
ti.setIcon(load_resource_image(_("installer_locales")));
|
|
||||||
} else {
|
|
||||||
ti.setIcon(load_resource_image(_("installer_group")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PackageUpdateList::drawItem(DC& dc, size_t index, size_t column, int x, int y, bool selected) const {
|
|
||||||
const TreeItem& ti = static_cast<const TreeItem&>(*items[index]);
|
|
||||||
Color color = wxSystemSettings::GetColour(selected ? wxSYS_COLOUR_HIGHLIGHTTEXT : wxSYS_COLOUR_WINDOWTEXT);
|
|
||||||
if (column == 0) {
|
|
||||||
// Name
|
|
||||||
const Bitmap& bmp = ti.highlight() ? ti.icon : ti.icon_grey;
|
|
||||||
if (bmp.Ok()) dc.DrawBitmap(bmp,x,y);
|
|
||||||
dc.SetTextForeground(color);
|
|
||||||
dc.DrawText(capitalize_sentence(ti.label), x+18, y+2);
|
|
||||||
} else if (column == 1 && ti.package) {
|
|
||||||
// Status
|
|
||||||
int stat = ti.package->status;
|
|
||||||
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);
|
|
||||||
} 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);
|
|
||||||
} 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);
|
|
||||||
} else if ((stat & PACKAGE_INSTALLED) == PACKAGE_INSTALLED) {
|
|
||||||
dc.SetTextForeground(color);
|
|
||||||
dc.DrawText(_LABEL_("package installed"), x+1,y+2);
|
|
||||||
} 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);
|
|
||||||
}
|
|
||||||
} else if (column == 2 && ti.package) {
|
|
||||||
// Action
|
|
||||||
int act = ti.package->action;
|
|
||||||
if (act & PACKAGE_INSTALL) {
|
|
||||||
if (ti.package->status & PACKAGE_INSTALLED) {
|
|
||||||
dc.SetTextForeground(lerp(color,Color(0,0,255),0.5));
|
|
||||||
dc.DrawText(_LABEL_("upgrade package"), x+1,y+2);
|
|
||||||
} else {
|
|
||||||
dc.SetTextForeground(lerp(color,Color(0,255,0),0.5));
|
|
||||||
dc.DrawText(_LABEL_("install package"), x+1,y+2);
|
|
||||||
}
|
|
||||||
} else if (act & PACKAGE_REMOVE) {
|
|
||||||
dc.SetTextForeground(lerp(color,Color(255,0,0),0.5));
|
|
||||||
dc.DrawText(_LABEL_("remove package"), x+1,y+2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String PackageUpdateList::columnText(size_t column) const {
|
|
||||||
if (column == 0) return _LABEL_("package name");
|
|
||||||
else if (column == 1) return _LABEL_("package status");
|
|
||||||
else if (column == 2) return _LABEL_("package action");
|
|
||||||
else throw InternalError(_("Unknown column"));
|
|
||||||
}
|
|
||||||
int PackageUpdateList::columnWidth(size_t column) const {
|
|
||||||
if (column == 0) {
|
|
||||||
wxSize cs = GetClientSize();
|
|
||||||
return cs.x - 300;
|
|
||||||
} else {
|
|
||||||
return 150;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : PackageInfoPanel
|
// ----------------------------------------------------------------------------- : PackageInfoPanel
|
||||||
|
|
||||||
|
/// Information on a package
|
||||||
class PackageInfoPanel : public wxPanel {
|
class PackageInfoPanel : public wxPanel {
|
||||||
public:
|
public:
|
||||||
PackageInfoPanel(Window* parent);
|
PackageInfoPanel(Window* parent);
|
||||||
@@ -508,7 +171,7 @@ PackagesWindow::PackagesWindow(Window* parent, bool download_package_list)
|
|||||||
|
|
||||||
// ui elements
|
// ui elements
|
||||||
SetIcon(wxIcon());
|
SetIcon(wxIcon());
|
||||||
package_list = new PackageUpdateList(this, ID_PACKAGE_LIST);
|
package_list = new PackageUpdateList(this, installable_packages, ID_PACKAGE_LIST);
|
||||||
package_info = new PackageInfoPanel(this);
|
package_info = new PackageInfoPanel(this);
|
||||||
|
|
||||||
//wxToolbar* buttons = new wxToolbar
|
//wxToolbar* buttons = new wxToolbar
|
||||||
|
|||||||
@@ -20,9 +20,13 @@ class PackageInfoPanel;
|
|||||||
/// A window that displays the installed packages and updates to them
|
/// A window that displays the installed packages and updates to them
|
||||||
class PackagesWindow : public wxDialog {
|
class PackagesWindow : public wxDialog {
|
||||||
public:
|
public:
|
||||||
|
/// Show the packages window, optionally downloading the package database from the website
|
||||||
PackagesWindow(Window* parent, bool download_package_list = true);
|
PackagesWindow(Window* parent, bool download_package_list = true);
|
||||||
|
/// Show the packages window for an installer
|
||||||
|
PackagesWindow(Window* parent, const InstallerP& installer);
|
||||||
~PackagesWindow();
|
~PackagesWindow();
|
||||||
|
|
||||||
|
/// List of the packages shown in this window
|
||||||
InstallablePackages installable_packages;
|
InstallablePackages installable_packages;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -42,6 +46,8 @@ class PackagesWindow : public wxDialog {
|
|||||||
void onUpdateUI(wxUpdateUIEvent&);
|
void onUpdateUI(wxUpdateUIEvent&);
|
||||||
void onIdle(wxIdleEvent&);
|
void onIdle(wxIdleEvent&);
|
||||||
|
|
||||||
|
/// Check whether we have downloaded the list of installers
|
||||||
|
/** If the download is (partially) complete, update the installable_packages list */
|
||||||
bool checkInstallerList(bool refresh = true);
|
bool checkInstallerList(bool refresh = true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+22
-12
@@ -1000,12 +1000,6 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath=".\gui\new_window.hpp">
|
RelativePath=".\gui\new_window.hpp">
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath=".\gui\packages_window.cpp">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\gui\packages_window.hpp">
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath=".\gui\preferences_window.cpp">
|
RelativePath=".\gui\preferences_window.cpp">
|
||||||
</File>
|
</File>
|
||||||
@@ -1024,18 +1018,34 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath=".\gui\thumbnail_thread.hpp">
|
RelativePath=".\gui\thumbnail_thread.hpp">
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath=".\gui\update_checker.cpp">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\gui\update_checker.hpp">
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath=".\gui\welcome_window.cpp">
|
RelativePath=".\gui\welcome_window.cpp">
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\gui\welcome_window.hpp">
|
RelativePath=".\gui\welcome_window.hpp">
|
||||||
</File>
|
</File>
|
||||||
|
<Filter
|
||||||
|
Name="package"
|
||||||
|
Filter="">
|
||||||
|
<File
|
||||||
|
RelativePath=".\gui\package_update_list.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\gui\package_update_list.hpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\gui\packages_window.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\gui\packages_window.hpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\gui\update_checker.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\gui\update_checker.hpp">
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="value"
|
Name="value"
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ void PackageDirectory::installedPackages(vector<InstallablePackageP>& packages_o
|
|||||||
PackageVersionP ver(new PackageVersion(
|
PackageVersionP ver(new PackageVersion(
|
||||||
is_local ? PackageVersion::STATUS_LOCAL : PackageVersion::STATUS_GLOBAL));
|
is_local ? PackageVersion::STATUS_LOCAL : PackageVersion::STATUS_GLOBAL));
|
||||||
ver->check_status(*pack);
|
ver->check_status(*pack);
|
||||||
packages_out.push_back(new_intrusive2<InstallablePackage>(ver, new_intrusive1<PackageDescription>(*pack)));
|
packages_out.push_back(new_intrusive2<InstallablePackage>(new_intrusive1<PackageDescription>(*pack), ver));
|
||||||
} catch (const Error&) {}
|
} catch (const Error&) {}
|
||||||
++it2;
|
++it2;
|
||||||
} else if ((*it1)->name < *it2) {
|
} else if ((*it1)->name < *it2) {
|
||||||
@@ -246,7 +246,7 @@ void PackageDirectory::installedPackages(vector<InstallablePackageP>& packages_o
|
|||||||
try {
|
try {
|
||||||
PackagedP pack = ::packages.openAny(*it2, true);
|
PackagedP pack = ::packages.openAny(*it2, true);
|
||||||
(*it1)->check_status(*pack);
|
(*it1)->check_status(*pack);
|
||||||
packages_out.push_back(new_intrusive2<InstallablePackage>(*it1, new_intrusive1<PackageDescription>(*pack)));
|
packages_out.push_back(new_intrusive2<InstallablePackage>(new_intrusive1<PackageDescription>(*pack), *it1));
|
||||||
} catch (const Error&) { db_changed = true; }
|
} catch (const Error&) { db_changed = true; }
|
||||||
++it1, ++it2;
|
++it1, ++it2;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user