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:
twanvl
2007-12-29 18:30:41 +00:00
parent 361488b4fe
commit d2196eea09
182 changed files with 2508 additions and 809 deletions
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/about_window.hpp>
#include <gui/util.hpp>
#include <util/version.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/auto_replace_window.hpp>
#include <gui/control/item_list.hpp>
#include <gui/util.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/card_select_window.hpp>
#include <gui/control/select_card_list.hpp>
#include <util/window_id.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/control/card_editor.hpp>
#include <gui/value/editor.hpp>
#include <gui/icon_menu.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/control/card_list.hpp>
#include <gui/control/card_list_column_select.hpp>
#include <gui/icon_menu.hpp>
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/control/card_list_column_select.hpp>
#include <data/game.hpp>
#include <data/field.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/control/card_viewer.hpp>
#include <data/stylesheet.hpp>
#include <data/settings.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/control/filtered_card_list.hpp>
DECLARE_TYPEOF_COLLECTION(CardP);
+1 -1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/control/gallery_list.hpp>
#include <gfx/gfx.hpp>
#include <wx/dcbuffer.h>
@@ -91,7 +92,6 @@ void GalleryList::scrollTo(int top, bool update_scrollbar) {
top = max(0, top);
// scroll
if (top == visible_start) return;
//%int old_top = visible_start;
visible_start = top;
if (update_scrollbar) {
// scroll bar
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/control/graph.hpp>
#include <util/alignment.hpp>
#include <gfx/gfx.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/control/image_card_list.hpp>
#include <gui/thumbnail_thread.hpp>
#include <data/field/image.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/control/item_list.hpp>
#include <gui/util.hpp>
#include <wx/imaglist.h>
-2
View File
@@ -12,8 +12,6 @@
#include <util/prec.hpp>
#include <wx/listctrl.h>
typedef intrusive_ptr<IntrusivePtrVirtualBase> VoidP;
// ----------------------------------------------------------------------------- : ItemList
/// A generic list of items
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/control/keyword_list.hpp>
#include <gui/icon_menu.hpp>
#include <data/set.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/control/native_look_editor.hpp>
#include <gui/value/editor.hpp>
#include <gui/util.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/control/package_list.hpp>
#include <util/io/package_manager.hpp>
#include <util/alignment.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/control/select_card_list.hpp>
#include <gui/util.hpp>
#include <data/card.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/control/text_ctrl.hpp>
#include <gui/value/editor.hpp>
#include <gui/util.hpp>
+48 -37
View File
@@ -6,12 +6,13 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/control/tree_list.hpp>
#include <gfx/gfx.hpp>
#include <wx/renderer.h>
#include <wx/dcbuffer.h>
DECLARE_TYPEOF_COLLECTION(TreeList::Item);
DECLARE_TYPEOF_COLLECTION(TreeList::ItemP);
// ----------------------------------------------------------------------------- : TreeList : item managment
@@ -23,21 +24,28 @@ void TreeList::rebuild(bool full) {
}
bool TreeList::hasChildren(size_t item) const {
return item < items.size() && items[item].level < items[item+1].level;
return item + 1 < items.size() && items[item]->level < items[item+1]->level;
}
void TreeList::expand(size_t item, bool expand) {
if (hasChildren(item) && items[item].expanded != expand) {
items[item].expanded = expand;
if (hasChildren(item) && items[item]->expanded != expand) {
items[item]->expanded = expand;
rebuild(false);
}
}
void TreeList::select(size_t item) {
void TreeList::select(size_t item, bool event) {
if (item >= items.size() || selection == item) return;
size_t oldpos = selection < items.size() ? items[selection].position : 0;
// select
size_t oldpos = selection < items.size() ? items[selection]->position : 0;
selection = item;
size_t pos = items[selection].position;
size_t pos = items[selection]->position;
// event
if (event) {
wxCommandEvent ev(wxEVT_COMMAND_LISTBOX_SELECTED, GetId());
ProcessEvent(ev);
}
// redraw
if (pos < first_line) {
ScrollToLine(pos);
} else if (pos >= first_line + visible_lines_t) {
@@ -53,28 +61,28 @@ void TreeList::calcItemCount() {
total_lines = 0;
int visible_level = 0;
FOR_EACH(i,items) {
if (i.level <= visible_level) {
i.position = total_lines;
if (i->level <= visible_level) {
i->position = total_lines;
++total_lines;
if (i.expanded) visible_level = i.level + 1;
else visible_level = i.level;
if (i->expanded) visible_level = i->level + 1;
else visible_level = i->level;
} else {
i.position = NOTHING;
i->position = NOTHING;
}
}
// update lines
UInt lines = 0;
FOR_EACH_REVERSE(i,items) {
if (i.visible()) {
i.lines = lines;
lines &= (1 << i.level) - 1;
lines |= 1 << i.level;
if (i->visible()) {
i->lines = lines;
lines &= (1 << i->level) - 1;
lines |= 1 << i->level;
}
}
// selection hidden? move to first visible item before it
if (selection < items.size()) {
for ( ; selection + 1 > 0 ; --selection) {
if (items[selection].visible()) break; // visible
if (items[selection]->visible()) break; // visible
}
if (selection >= items.size()) selection = 0;
}
@@ -86,20 +94,20 @@ size_t TreeList::findItemByPos(int y) const {
}
size_t TreeList::findItem(size_t line, size_t start) const {
for (size_t i = start ; i < items.size() ; ++i) {
if (items[i].visible() && items[i].position >= line) return i;
if (items[i]->visible() && items[i]->position >= line) return i;
}
return items.size();
}
size_t TreeList::findLastItem(size_t start) const {
for (size_t i = min(items.size(), start) - 1 ; i + 1 > 0 ; --i) {
if (items[i].visible()) return i;
if (items[i]->visible()) return i;
}
return items.size();
}
size_t TreeList::findParent(size_t start) const {
int level = items[start].level;
int level = items[start]->level;
for (size_t i = start - 1 ; i + 1 > 0 ; --i) {
if (items[i].visible() && items[i].level < level) return i;
if (items[i]->visible() && items[i]->level < level) return i;
}
return items.size();
}
@@ -147,9 +155,13 @@ void TreeList::onPaint(wxPaintEvent& ev) {
size_t start = findItem(first_line);
size_t end = findItem(first_line + visible_lines);
for (size_t i = start ; i < end ; ++i) {
const Item& item = items[i];
const Item& item = *items[i];
if (!item.visible()) continue; // invisible
x = level_width * (item.level + 1);
// line below
dc.SetPen(lerp(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW),
wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT),0.2));
dc.DrawLine(x,y+item_height-1,cs.x,y+item_height-1);
// draw lines
dc.SetPen(lerp(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW),
wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT),0.4));
@@ -171,15 +183,12 @@ void TreeList::onPaint(wxPaintEvent& ev) {
if (selection == i) {
dc.SetPen(*wxTRANSPARENT_PEN);
dc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT));
dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT));
dc.DrawRectangle(x, y, cs.x-x, item_height);
dc.DrawRectangle(x, y, cs.x-x, item_height-1);
}
// draw text(s)
for (size_t j = 0 ; j < cols ; ++j) {
int w = columnWidth(j);
if (selection != i)
dc.SetTextForeground(itemColor(i,j));
dc.DrawText(itemText(i,j),x+1,y+1);
drawItem(dc, i, j, x+1, y, selection == i);
if (j == 0) x = 0;
x += w;
}
@@ -197,7 +206,7 @@ void TreeList::onChar(wxKeyEvent& ev) {
break;
} case WXK_LEFT: {
if (selection < items.size()) {
if (hasChildren(selection) && items[selection].expanded) {
if (hasChildren(selection) && items[selection]->expanded) {
expand(selection, false);
} else {
// select parent
@@ -207,7 +216,7 @@ void TreeList::onChar(wxKeyEvent& ev) {
break;
} case WXK_RIGHT: {
if (selection < items.size() && hasChildren(selection)) {
if (items[selection].expanded) {
if (items[selection]->expanded) {
// select first child
select(selection+1);
Refresh(false);
@@ -216,10 +225,10 @@ void TreeList::onChar(wxKeyEvent& ev) {
}
}
break;
} case WXK_PAGEUP: {
} case WXK_PAGEUP: case WXK_PRIOR: {
ScrollToLine(first_line > visible_lines_t ? first_line - visible_lines_t : 0);
break;
} case WXK_PAGEDOWN: {
} case WXK_PAGEDOWN: case WXK_NEXT: {
ScrollToLine(first_line + visible_lines_t);
break;
} case WXK_HOME: {
@@ -242,9 +251,9 @@ void TreeList::onChar(wxKeyEvent& ev) {
void TreeList::onLeftDown(wxMouseEvent& ev) {
size_t i = findItemByPos(ev.GetY());
if (i >= items.size()) return;
int left = items[i].level * level_width;
int left = items[i]->level * level_width;
if (hasChildren(i) && ev.GetX() >= left && ev.GetX() < left + level_width) {
expand(i, !items[i].expanded);
expand(i, !items[i]->expanded);
} else {
select(i);
}
@@ -255,7 +264,7 @@ void TreeList::onLeftDClick(wxMouseEvent& ev) {
size_t i = findItemByPos(ev.GetY());
if (i >= items.size()) return;
if (hasChildren(i)) {
expand(i, !items[i].expanded);
expand(i, !items[i]->expanded);
}
ev.Skip();
}
@@ -264,7 +273,8 @@ void TreeList::onLeftDClick(wxMouseEvent& ev) {
void TreeList::ScrollToLine(size_t line) {
// determine the real first line to scroll to: we shouldn't scroll beyond the end
line = (size_t)min((int)line, (int)(total_lines - visible_lines_t));
line = (size_t)max((int)line, 0);
line = (size_t)min((int)line, max(0, (int)(total_lines - visible_lines_t)));
// nothing to do?
if (line == first_line) return;
first_line = line;
@@ -314,12 +324,13 @@ void TreeList::onScroll(wxScrollWinEvent& ev) {
void TreeList::onSize(wxSizeEvent& ev) {
UpdateScrollbar();
Refresh(false);
ev.Skip();
}
void TreeList::onMouseWheel(wxMouseEvent& ev) {
ScrollLines(-ev.GetWheelRotation() * ev.GetLinesPerAction() / ev.GetWheelDelta());
Refresh(false);
int delta = -ev.GetWheelRotation() * ev.GetLinesPerAction() / ev.GetWheelDelta();
ScrollToLine(first_line + delta);
}
+14 -16
View File
@@ -12,8 +12,6 @@
#include <util/prec.hpp>
#include <wx/vscroll.h>
typedef intrusive_ptr<IntrusivePtrVirtualBase> VoidP;
// ----------------------------------------------------------------------------- : TreeList
/// A combination of a TreeCtrl and a ListCtrl. A tree with multiple columns.
@@ -24,7 +22,7 @@ class TreeList : public wxPanel {
/// Expand/collapse an item
void expand(size_t item, bool expand = true);
/// Select an item
void select(size_t item);
void select(size_t item, bool event = true);
/// (re)build the list
void rebuild(bool full = true);
@@ -32,24 +30,26 @@ class TreeList : public wxPanel {
public:
/// An item in the tree list
struct Item {
Item() {}
Item(int level, bool expanded = false, VoidP data = VoidP())
: level(level), expanded(expanded), data(data)
{}
class Item : public IntrusivePtrBase<Item> {
public:
Item() : level(0), expanded(false) {}
virtual ~Item() {}
int level;
bool expanded;
VoidP data;
inline bool visible() const { return position != NOTHING; }
private:
friend class TreeList;
size_t position; // NOTHING if invisible, otherwise the line the item is on
UInt lines; // lines in front of this item (bit set)
inline bool visible() const { return position != NOTHING; }
};
typedef intrusive_ptr<Item> ItemP;
protected:
/// The items in the tree list
vector<Item> items;
vector<ItemP> items;
static const size_t NOTHING = (size_t)-1;
size_t selection;
@@ -57,10 +57,8 @@ class TreeList : public wxPanel {
/// Initialize the items
virtual void initItems() = 0;
/// Get the text of an item
virtual String itemText(size_t item, size_t column) const = 0;
/// Get the color of an item
virtual Color itemColor(size_t item, size_t column) const = 0;
/// Draw the text of an item
virtual void drawItem(DC& dc, size_t index, size_t column, int x, int y, bool selected) const = 0;
/// The number of columns
virtual size_t columnCount() const = 0;
@@ -69,11 +67,11 @@ class TreeList : public wxPanel {
/// The width of a column in pixels
virtual int columnWidth(size_t column) const = 0;
private:
int item_height;
static const int header_height = 17;
static const int level_width = 17;
private:
size_t total_lines; // number of shown items
size_t first_line; // first visible line
size_t visible_lines; // number of (partially) visible lines
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/drop_down_list.hpp>
#include <gui/util.hpp>
#include <render/value/viewer.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/html_export_window.hpp>
#include <gui/control/package_list.hpp>
#include <gui/control/native_look_editor.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/icon_menu.hpp>
#include <gui/util.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/image_slice_window.hpp>
#include <gui/util.hpp>
#include <util/window_id.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/images_export_window.hpp>
#include <gui/control/select_card_list.hpp>
#include <data/settings.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/new_window.hpp>
#include <gui/control/gallery_list.hpp>
#include <gui/control/package_list.hpp>
+884
View File
@@ -0,0 +1,884 @@
//+----------------------------------------------------------------------------+
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
//| Copyright: (C) 2001 - 2007 Twan van Laarhoven |
//| License: GNU General Public License 2 or later (see file COPYING) |
//+----------------------------------------------------------------------------+
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/packages_window.hpp>
#include <gui/control/tree_list.hpp>
//%#include <gui/update_checker.hpp>
#include <gui/util.hpp>
#include <util/io/package_repository.hpp>
#include <util/io/package_manager.hpp>
#include <util/window_id.hpp>
#include <data/installer.hpp>
#include <data/settings.hpp>
#include <gfx/gfx.hpp>
//%#include <list>
//%#include <set>
#include <wx/wfstream.h>
#include <wx/html/htmlwin.h>
#include <wx/dialup.h>
#include <wx/url.h>
#include <wx/dcbuffer.h>
#include <wx/progdlg.h>
//%DECLARE_POINTER_TYPE(VersionData); //%% TODO
DECLARE_POINTER_TYPE(Installer);
//%DECLARE_POINTER_TYPE(PackageVersionData);
DECLARE_TYPEOF_COLLECTION(PackageVersionDataP);
DECLARE_TYPEOF_COLLECTION(PackageDependencyP);
DECLARE_TYPEOF_COLLECTION(InstallablePackageP);
DECLARE_TYPEOF_COLLECTION(TreeList::ItemP);
//%DECLARE_TYPEOF(list<PackageVersionDataP>);
//%DECLARE_TYPEOF(set<String>);
// ----------------------------------------------------------------------------- : 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
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() );
}
};
// ----------------------------------------------------------------------------- : 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()
*/
// ----------------------------------------------------------------------------- : 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)
, images(16,16)
{
item_height = max(item_height,17);
rebuild();
}
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;
mutable wxImageList images;
class TreeItem;
public:
typedef intrusive_ptr<TreeItem> TreeItemP;
private:
class TreeItem : public Item {
public:
String label;
vector<TreeItemP> children;
InstallablePackageP package;
void add(const InstallablePackageP& package, const String& path, int level = -1);
void toItems(vector<TreeList::ItemP>& items);
};
};
DECLARE_TYPEOF_COLLECTION(PackageUpdateList::TreeItemP);
void PackageUpdateList::TreeItem::add(const InstallablePackageP& package, const String& path, int level) {
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) {
if (ti->package) {
// two packages with the same path
TreeItemP ti2(new TreeItem);
ti2->level = level + 1;
ti2->label = name;
ti2->package = package;
children.insert(ti_IT.first, ti2);
} else {
ti->package = package;
}
} else {
ti->add(package, rest, level + 1);
}
return;
}
}
// don't have this child
TreeItemP ti(new TreeItem);
children.push_back(ti);
ti->level = level + 1;
ti->label = name;
if (pos == String::npos) {
ti->package = package;
} else {
ti->add(package, rest, level + 1);
}
}
bool compare_pos_hint(const PackageUpdateList::TreeItemP& a, const PackageUpdateList::TreeItemP& b) {
int pa = a->package ? a->package->description->position_hint : 0;
int pb = b->package ? b->package->description->position_hint : 0;
if (pa < pb) return true;
if (pa > pb) 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);
}
}
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");
//% group += _("/");
if (!group.empty()) group += _("/");
group += ip->description->short_name;
root.add(ip, group);
}
// tree to treelist items
items.clear();
root.toItems(items);
// init image list
images.RemoveAll();
Image resampled(16,16,false);
FOR_EACH(i,items) {
const TreeItem& ti = static_cast<const TreeItem&>(*i);
const InstallablePackageP& p = ti.package;
if (p && p->description->icon.Ok()) {
resample_preserve_aspect(p->description->icon, resampled);
images.Add(resampled);
} else if (p) {
images.Add(load_resource_image(_("installer_package")));
} else if (ti.label == _("locales")) {
images.Add(load_resource_image(_("installer_locales")));
} else {
images.Add(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
images.Draw((int)index, dc, x, y);
dc.SetTextForeground(color);
dc.DrawText(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.DrawText(_LABEL_("package conflicts"), x+1,y+2);
} else if ((stat & PACKAGE_MODIFIED) == PACKAGE_MODIFIED) {
dc.DrawText(_LABEL_("package modified"), x+1,y+2);
} else if ((stat & PACKAGE_UPDATES) == PACKAGE_UPDATES) {
dc.DrawText(_LABEL_("package updates"), x+1,y+2);
} else if ((stat & PACKAGE_INSTALLED) == PACKAGE_INSTALLED) {
dc.DrawText(_LABEL_("package installed"), x+1,y+2);
} else if ((stat & PACKAGE_INSTALLABLE) == PACKAGE_INSTALLABLE) {
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) {
dc.DrawText(_LABEL_("install package"), x+1,y+2);
} else if (act & PACKAGE_UPGRADE) {
dc.DrawText(_LABEL_("upgrade package"), x+1,y+2);
} else if (act & PACKAGE_REMOVE) {
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
class PackageInfoPanel : public wxPanel {
public:
PackageInfoPanel(Window* parent);
void setPackage(const InstallablePackageP& package);
virtual wxSize DoGetBestSize() const;
private:
InstallablePackageP package;
DECLARE_EVENT_TABLE();
void onPaint(wxPaintEvent&);
};
PackageInfoPanel::PackageInfoPanel(Window* parent)
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER)
{}
void PackageInfoPanel::setPackage(const InstallablePackageP& package) {
this->package = package;
Refresh(false);
}
void PackageInfoPanel::onPaint(wxPaintEvent&) {
wxBufferedPaintDC dc(this);
wxSize cs = GetClientSize();
dc.SetPen(*wxTRANSPARENT_PEN);
dc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
dc.DrawRectangle(0,0,cs.x,cs.y);
// draw package info
if (!package) return;
PackageDescription& d = *package->description;
int x = 5;
if (d.icon.Ok()) {
int h = d.icon.GetHeight();
int y = max(0,20-h)/2 + 5;
dc.DrawBitmap(d.icon, x,y);
x += d.icon.GetWidth();
}
dc.SetFont(wxFont(16, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, _("Arial")));
dc.DrawText(d.full_name, x + 5, 3);
}
wxSize PackageInfoPanel::DoGetBestSize() const {
return wxSize(200, 120);
}
BEGIN_EVENT_TABLE(PackageInfoPanel, wxPanel)
EVT_PAINT(PackageInfoPanel::onPaint)
END_EVENT_TABLE()
// ----------------------------------------------------------------------------- : PackagesWindow
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)
, where(is_install_local(settings.install_type) ? PACKAGE_LOCAL : PACKAGE_GLOBAL)
{
// get packages
wxBusyCursor busy;
packages.installedPackages(installable_packages);
FOR_EACH(p, installable_packages) p->determineStatus();
// ui elements
SetIcon(wxIcon());
package_list = new PackageUpdateList(this, ID_PACKAGE_LIST);
package_info = new PackageInfoPanel(this);
//wxToolbar* buttons = new wxToolbar
wxButton* install_button = new wxButton(this, ID_INSTALL, _BUTTON_("install package"));
wxButton* upgrade_button = new wxButton(this, ID_UPGRADE, _BUTTON_("upgrade 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
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);
v->Add(package_list, 1, wxEXPAND | wxALL & ~wxBOTTOM, 8);
v->AddSpacer(4);
wxBoxSizer* h = new wxBoxSizer(wxHORIZONTAL);
h->Add(package_info, 1, wxRIGHT, 4);
wxBoxSizer* v2 = new wxBoxSizer(wxVERTICAL);
v2->Add(install_button, 0, wxEXPAND | wxBOTTOM, 4);
v2->Add(upgrade_button, 0, wxEXPAND | wxBOTTOM, 4);
v2->Add(remove_button, 0, wxEXPAND | wxBOTTOM, 4);
v2->AddStretchSpacer();
h->Add(v2);
v->Add(h, 0, wxEXPAND | wxALL & ~wxTOP, 8);
v->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxEXPAND | wxALL & ~wxTOP, 8);
SetSizer(v);
UpdateWindowUI(wxUPDATE_UI_RECURSE);
}
PackagesWindow::~PackagesWindow() {
//(new WelcomeWindow)->Show();
}
/*
void PackagesWindow::onUpdateCheckFinished(wxCommandEvent&) {
setDefaultPackageStatus();
}*/
void PackagesWindow::onPackageSelect(wxCommandEvent& ev) {
// updateButtons(package_list->getSelection());
package_info->setPackage(package = package_list->getSelection());
UpdateWindowUI(wxUPDATE_UI_RECURSE);
}
void PackagesWindow::onActionChange(wxCommandEvent& ev) {
if (package) {
PackageAction act = ev.GetId() == ID_INSTALL ? PACKAGE_INSTALL
: ev.GetId() == ID_UPGRADE ? PACKAGE_UPGRADE
: ev.GetId() == ID_REMOVE ? PACKAGE_REMOVE
: PACKAGE_NOTHING;
act = (PackageAction)(act | where);
// toggle action
if (package->has(act)) {
set_package_action(installable_packages, package, (PackageAction)(PACKAGE_NOTHING | where));
} else {
set_package_action(installable_packages, package, act);
}
package_list->Refresh(false);
UpdateWindowUI(wxUPDATE_UI_RECURSE);
}
}
void PackagesWindow::onOk(wxCommandEvent& ev) {
// Do we need a new version of MSE first?
// progress dialog
int total = (int)installable_packages.size();
wxProgressDialog progress(
_TITLE_("installing updates"),
String::Format(_ERROR_("downloading updates"), 0, 2*total),
total,
this,
wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT | wxPD_SMOOTH
);
// Clear package list
packages.reset();
// Download installers
int n = 0;
FOR_EACH(ip, installable_packages) {
++n;
if (!progress.Update(n, String::Format(_ERROR_("downloading updates"), n, total))) {
return; // aborted
}
if ((ip->action & (PACKAGE_INSTALL | PACKAGE_UPGRADE)) && ip->installer && !ip->installer->installer) {
// download installer
wxURL url(ip->installer->installer_url);
wxInputStream* is = url.GetInputStream();
if (!is) {
throw Error(_ERROR_2_("can't download installer", ip->description->name, ip->installer->installer_url));
}
ip->installer->installer_file = wxFileName::CreateTempFileName(_("mse-installer"));
wxFileOutputStream os(ip->installer->installer_file);
os.Write(*is);
os.Close();
// open installer
ip->installer->installer = new_intrusive<Installer>();
ip->installer->installer->open(ip->installer->installer_file);
}
}
// Install stuff
int n2 = 0 ;
FOR_EACH(ip, installable_packages) {
++n; ++n2;
if (!progress.Update(n, String::Format(_ERROR_("installing updates"), n2, total))) {
// don't allow abort.
}
packages.install(*ip);
}
// Done
wxDialog::OnOK(ev);
}
void PackagesWindow::onUpdateUI(wxUpdateUIEvent& ev) {
switch (ev.GetId()) {
case ID_INSTALL:
case ID_UPGRADE:
case ID_REMOVE: {
PackageAction act = ev.GetId() == ID_INSTALL ? PACKAGE_INSTALL
: ev.GetId() == ID_UPGRADE ? PACKAGE_UPGRADE
: ev.GetId() == ID_REMOVE ? PACKAGE_REMOVE
: PACKAGE_NOTHING;
act = (PackageAction)(act | where);
ev.Check (package && package->has(act));
ev.Enable(package && package->can(act));
break;
}
}
}
/*
void PackagesWindow::onActionChange(wxCommandEvent& ev) {
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() {
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 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;
}
}
}
}
}
*/
BEGIN_EVENT_TABLE(PackagesWindow, wxDialog)
// EVT_COMMAND(wxID_ANY, UPDATE_CHECK_FINISHED_EVT, PackagesWindow::onUpdateCheckFinished)
EVT_LISTBOX(ID_PACKAGE_LIST, PackagesWindow::onPackageSelect)
EVT_BUTTON(ID_INSTALL, PackagesWindow::onActionChange)
EVT_BUTTON(ID_REMOVE, PackagesWindow::onActionChange)
EVT_BUTTON(ID_UPGRADE, PackagesWindow::onActionChange)
EVT_BUTTON(wxID_OK, PackagesWindow::onOk)
EVT_UPDATE_UI(wxID_ANY, PackagesWindow::onUpdateUI)
END_EVENT_TABLE()
+76
View File
@@ -0,0 +1,76 @@
//+----------------------------------------------------------------------------+
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
//| Copyright: (C) 2001 - 2007 Twan van Laarhoven |
//| License: GNU General Public License 2 or later (see file COPYING) |
//+----------------------------------------------------------------------------+
#ifndef HEADER_GUI_PACKAGES_WINDOW
#define HEADER_GUI_PACKAGES_WINDOW
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <data/installer.hpp>
// #include <gui/welcome_window.hpp> //???
class PackageUpdateList;
class PackageInfoPanel;
//class wxHtmlWindow;
//DECLARE_POINTER_TYPE(PackageVersionData);
//DECLARE_POINTER_TYPE(PackageVersion);
//DECLARE_POINTER_TYPE(PackageDescription);
//DECLARE_POINTER_TYPE(InstallableInstaller);
DECLARE_POINTER_TYPE(InstallablePackage);
// ----------------------------------------------------------------------------- : Available Packages
// ----------------------------------------------------------------------------- : Packages window
/// A window that displays the installed packages and updates to them
class PackagesWindow : public wxDialog {
public:
PackagesWindow(Window* parent, bool download_package_list = true);
~PackagesWindow();
InstallablePackages installable_packages;
private:
PackageUpdateList* package_list; ///< List of available packages
PackageInfoPanel* package_info; ///< Description of the selected package
InstallablePackageP package; ///< Selected package
PackageAction where; ///< Where to install? (PACKAGE_LOCAL or PACKAGE_GLOBAL)
DECLARE_EVENT_TABLE();
void onOk(wxCommandEvent&);
void onActionChange(wxCommandEvent&);
void onPackageSelect(wxCommandEvent&);
void onUpdateUI(wxUpdateUIEvent&);
/*
wxHtmlWindow* description_window;
wxButton *install_button, *upgrade_button, *remove_button, *cancel_button, *apply_button;
void onUpdateCheckFinished(wxCommandEvent&);
void onPackageSelect(wxCommandEvent&);
void onActionChange(wxCommandEvent&);
void onApplyChanges(wxCommandEvent&);
void SelectPackageDependencies (PackageVersionDataP);
void RemovePackageDependencies (PackageVersionDataP);
void DowngradePackageDependencies(PackageVersionDataP);
/// Update the buttons to indicate that this is selected.
void updateButtons(const PackageVersionDataP& pack);
void setDefaultPackageStatus();
*/
};
// ----------------------------------------------------------------------------- : EOF
#endif
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/preferences_window.hpp>
#include <gui/update_checker.hpp>
#include <data/settings.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/print_window.hpp>
#include <gui/card_select_window.hpp>
#include <gui/util.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/set/cards_panel.hpp>
#include <gui/control/image_card_list.hpp>
#include <gui/control/card_editor.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/set/keywords_panel.hpp>
#include <gui/control/keyword_list.hpp>
#include <gui/control/text_ctrl.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/set/panel.hpp>
#include <data/card.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/set/set_info_panel.hpp>
#include <gui/control/native_look_editor.hpp>
#include <gui/icon_menu.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/set/stats_panel.hpp>
#include <gui/control/graph.hpp>
#include <gui/control/gallery_list.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/set/style_panel.hpp>
#include <gui/control/package_list.hpp>
#include <gui/control/card_viewer.hpp>
+5 -3
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/set/window.hpp>
#include <gui/set/panel.hpp>
#include <gui/set/cards_panel.hpp>
@@ -18,6 +19,7 @@
#include <gui/control/gallery_list.hpp>
#include <gui/about_window.hpp>
#include <gui/update_checker.hpp>
#include <gui/packages_window.hpp>
#include <gui/new_window.hpp>
#include <gui/preferences_window.hpp>
#include <gui/print_window.hpp>
@@ -538,8 +540,8 @@ void SetWindow::onFileExportMWS(wxCommandEvent&) {
void SetWindow::onFileCheckUpdates(wxCommandEvent&) {
if (!askSaveAndContinue()) return;
(new UpdatesWindow)->Show();
Destroy();
(new PackagesWindow(this))->Show();
//Destroy();
}
void SetWindow::onFilePrint(wxCommandEvent&) {
@@ -562,7 +564,7 @@ void SetWindow::onFileReload(wxCommandEvent&) {
vector<CardP>::const_iterator card_it = find(set->cards.begin(), set->cards.end(), current_panel->selectedCard());
if (card_it != set->cards.end()) card_pos = card_it - set->cards.begin();
}
packages.destroy(); // unload all packages
packages.reset(); // unload all packages
settings.read(); // reload settings
setSet(import_set(filename));
// reselect card
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/symbol/basic_shape_editor.hpp>
#include <gui/util.hpp>
#include <util/window_id.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/symbol/control.hpp>
#include <gui/symbol/window.hpp>
#include <gui/symbol/editor.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/symbol/editor.hpp>
#include <gui/symbol/window.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/symbol/part_list.hpp>
#include <gui/symbol/selection.hpp>
#include <gui/util.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/symbol/point_editor.hpp>
#include <gui/symbol/window.hpp>
#include <gui/util.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/symbol/select_editor.hpp>
#include <gui/symbol/window.hpp>
#include <gui/util.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/symbol/selection.hpp>
#include <data/symbol.hpp>
#include <gfx/bezier.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/symbol/symmetry_editor.hpp>
#include <gui/util.hpp>
#include <util/window_id.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/symbol/window.hpp>
#include <gui/symbol/control.hpp>
#include <gui/symbol/part_list.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/thumbnail_thread.hpp>
#include <util/platform.hpp>
#include <util/error.hpp>
+57 -530
View File
@@ -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()
-58
View File
@@ -10,7 +10,6 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/welcome_window.hpp>
// ----------------------------------------------------------------------------- : Update checking
@@ -27,63 +26,6 @@ void check_updates_now(bool async = true);
* Call this function from an onIdle loop */
void show_update_dialog(Window* parent);
// ----------------------------------------------------------------------------- : Update window
class PackageUpdateList;
class wxHtmlWindow;
DECLARE_POINTER_TYPE(PackageVersionData);
/// A window that displays the updates and allows the user to select some.
/** NOTE: cannot be called 'UpdateWindow' because there is a Win32 function with that name
*/
class UpdatesWindow : public Frame {
public:
UpdatesWindow();
~UpdatesWindow();
void DrawTitles(wxPaintEvent&);
enum PackageStatus {
STATUS_INSTALLED,
STATUS_NOT_INSTALLED,
STATUS_UPGRADEABLE
};
enum PackageAction {
ACTION_INSTALL,
ACTION_UNINSTALL,
ACTION_UPGRADE,
ACTION_NOTHING,
ACTION_NEW_MSE // means that you need a new version of MSE to install/upgrade
};
typedef pair<PackageStatus, PackageAction> PackageData;
map<PackageVersionDataP, PackageData> package_data;
private:
DECLARE_EVENT_TABLE();
PackageUpdateList* package_list; ///< List of available packages
wxHtmlWindow* description_window;
wxStaticText *package_title, *type_title, *status_title, *new_title;
wxButton *install_button, *upgrade_button, *remove_button, *cancel_button, *apply_button;
void onUpdateCheckFinished(wxCommandEvent&);
void onPackageSelect(wxCommandEvent&);
void onActionChange(wxCommandEvent&);
void onApplyChanges(wxCommandEvent&);
void SelectPackageDependencies (PackageVersionDataP);
void RemovePackageDependencies (PackageVersionDataP);
void DowngradePackageDependencies(PackageVersionDataP);
/// Update the buttons to indicate that this is selected.
void updateButtons(int index);
void setDefaultPackageStatus();
};
/// Was update data found?
bool update_data_found();
/// Is there an update?
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/util.hpp>
#include <util/error.hpp>
#include <util/rotation.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/value/choice.hpp>
#include <gui/util.hpp>
#include <gui/thumbnail_thread.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/value/color.hpp>
#include <gui/drop_down_list.hpp>
#include <gui/util.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
//#include <gui/value/editor.hpp>
// ----------------------------------------------------------------------------- : ValueEditor
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/value/image.hpp>
#include <gui/image_slice_window.hpp>
#include <data/format/clipboard.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/value/information.hpp>
// ----------------------------------------------------------------------------- : InfoValueEditor
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/value/multiple_choice.hpp>
#include <gui/thumbnail_thread.hpp>
#include <gui/util.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/value/package_choice.hpp>
#include <gui/drop_down_list.hpp>
#include <gui/util.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/value/symbol.hpp>
#include <gui/symbol/window.hpp>
#include <gui/util.hpp>
+1
View File
@@ -6,6 +6,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/value/text.hpp>
#include <gui/icon_menu.hpp>
#include <gui/util.hpp>
+7 -5
View File
@@ -6,11 +6,13 @@
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <gui/welcome_window.hpp>
#include <gui/util.hpp>
#include <gui/new_window.hpp>
#include <gui/set/window.hpp>
#include <gui/update_checker.hpp>
#include <gui/packages_window.hpp>
#include <util/window_id.hpp>
#include <data/settings.hpp>
#include <data/format/formats.hpp>
@@ -23,7 +25,7 @@
// ----------------------------------------------------------------------------- : WelcomeWindow
WelcomeWindow::WelcomeWindow()
: Frame(nullptr, wxID_ANY, _TITLE_("magic set editor"), wxDefaultPosition, wxSize(480,340), wxDEFAULT_DIALOG_STYLE | wxTAB_TRAVERSAL | wxCLIP_CHILDREN )
: Frame(nullptr, wxID_ANY, _TITLE_("magic set editor"), wxDefaultPosition, wxSize(480,380), wxDEFAULT_DIALOG_STYLE | wxTAB_TRAVERSAL | wxCLIP_CHILDREN )
, logo (load_resource_image(_("about")))
, logo2(load_resource_image(_("two_beta")))
{
@@ -31,9 +33,9 @@ WelcomeWindow::WelcomeWindow()
// init controls
#ifdef USE_HOVERBUTTON
wxControl* new_set = new HoverButtonExt(this, ID_FILE_NEW, load_resource_image(_("welcome_new")), _BUTTON_("new set"), _HELP_("new set"));
wxControl* open_set = new HoverButtonExt(this, ID_FILE_OPEN, load_resource_image(_("welcome_open")), _BUTTON_("open set"), _HELP_("open set"));
wxControl* updates = new HoverButtonExt(this, ID_FILE_CHECK_UPDATES, wxImage(), _BUTTON_("check updates"), _HELP_("check updates"));
wxControl* new_set = new HoverButtonExt(this, ID_FILE_NEW, load_resource_image(_("welcome_new")), _BUTTON_("new set"), _HELP_("new set"));
wxControl* open_set = new HoverButtonExt(this, ID_FILE_OPEN, load_resource_image(_("welcome_open")), _BUTTON_("open set"), _HELP_("open set"));
wxControl* updates = new HoverButtonExt(this, ID_FILE_CHECK_UPDATES, load_resource_image(_("welcome_updates")), _BUTTON_("check updates"), _HELP_("check updates"));
#else
wxControl* new_set = new wxButton(this, ID_FILE_NEW, _BUTTON_("new set"));
wxControl* open_set = new wxButton(this, ID_FILE_OPEN, _BUTTON_("open set"));
@@ -106,7 +108,7 @@ void WelcomeWindow::onOpenLast(wxCommandEvent&) {
}
void WelcomeWindow::onCheckUpdates(wxCommandEvent&) {
(new UpdatesWindow)->Show();
(new PackagesWindow(nullptr))->Show();
Close();
}