mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 04:57:00 -04:00
Bulk card modification
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 4.5 KiB |
@@ -55,6 +55,7 @@ tool/no_auto IMAGE "tool/no_auto.png"
|
||||
|
||||
tool/card_add IMAGE "tool/card_add.png"
|
||||
tool/card_add_multiple IMAGE "tool/card_add_multiple.png"
|
||||
tool/card_modify_multiple IMAGE "tool/card_modify_multiple.png"
|
||||
tool/card_del IMAGE "tool/card_del.png"
|
||||
tool/card_link IMAGE "tool/card_link.png"
|
||||
tool/card_copy IMAGE "tool/card_copy.png"
|
||||
|
||||
@@ -214,6 +214,33 @@ void ChangeCardHasStylingAction::perform(bool to_undo) {
|
||||
swap(card->styling_data, styling_data);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Change notes
|
||||
|
||||
ChangeCardNotesAction::ChangeCardNotesAction(const CardP& card, const String& notes)
|
||||
: card(card), notes(notes)
|
||||
{}
|
||||
String ChangeCardNotesAction::getName(bool to_undo) const {
|
||||
return _("Change notes");
|
||||
}
|
||||
void ChangeCardNotesAction::perform(bool to_undo) {
|
||||
swap(card->notes, notes);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Change uid
|
||||
|
||||
ChangeCardUIDAction::ChangeCardUIDAction(Set& set, const CardP& card, const String& uid)
|
||||
: CardListAction(set), card(card), uid(uid)
|
||||
{}
|
||||
String ChangeCardUIDAction::getName(bool to_undo) const {
|
||||
return _("Change ID");
|
||||
}
|
||||
void ChangeCardUIDAction::perform(bool to_undo) {
|
||||
FOR_EACH(c, set.cards) {
|
||||
c->updateLink(card->uid, uid);
|
||||
}
|
||||
swap(card->uid, uid);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Pack types
|
||||
|
||||
AddPackAction::AddPackAction(AddingOrRemoving ar, Set& set, const PackTypeP& pack)
|
||||
|
||||
@@ -149,6 +149,36 @@ public:
|
||||
IndexMap<FieldP,ValueP> styling_data; ///< The old styling of the card
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : Change notes
|
||||
|
||||
/// Changing the notes of a card
|
||||
class ChangeCardNotesAction : public Action {
|
||||
public:
|
||||
ChangeCardNotesAction(const CardP& card, const String& notes);
|
||||
|
||||
String getName(bool to_undo) const override;
|
||||
void perform(bool to_undo) override;
|
||||
|
||||
//private:
|
||||
CardP card; ///< The affected card
|
||||
String notes; ///< Its old notes
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : Change uid
|
||||
|
||||
/// Changing the uid of a card
|
||||
class ChangeCardUIDAction : public CardListAction {
|
||||
public:
|
||||
ChangeCardUIDAction(Set& set, const CardP& card, const String& id);
|
||||
|
||||
String getName(bool to_undo) const override;
|
||||
void perform(bool to_undo) override;
|
||||
|
||||
//private:
|
||||
CardP card; ///< The affected card
|
||||
String uid; ///< Its old uid
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : Pack types
|
||||
|
||||
/// An Action the changes the pack types of a set
|
||||
|
||||
@@ -37,6 +37,9 @@ void ValueAction::setCard(CardP const& card) {
|
||||
|
||||
// ----------------------------------------------------------------------------- : Simple
|
||||
|
||||
unique_ptr<ValueAction> value_action(const TextValueP& value, const Defaultable<String>& new_value) {
|
||||
return make_unique<SimpleValueAction<TextValue, false>>(value, new_value);
|
||||
}
|
||||
unique_ptr<ValueAction> value_action(const ChoiceValueP& value, const Defaultable<String>& new_value) {
|
||||
return make_unique<SimpleValueAction<ChoiceValue, true>>(value, new_value);
|
||||
}
|
||||
@@ -207,6 +210,33 @@ void ScriptStyleEvent::perform(bool) {
|
||||
assert(false); // this action is just an event, it should not be performed
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Bulk action
|
||||
|
||||
BulkAction::BulkAction(const vector<shared_ptr<Action>>& actions, const SetP& set, CardListBase* card_list_window)
|
||||
: actions(actions), set(set), card_list_window(card_list_window)
|
||||
{
|
||||
if (actions.empty()) throw InternalError(_("BulkAction created with no actions"));
|
||||
name_do = actions.front()->getName(false) + _(" ") + _ACTION_("bulk");
|
||||
name_undo = actions.front()->getName(true) + _(" ") + _ACTION_("bulk");
|
||||
}
|
||||
BulkAction::~BulkAction() {}
|
||||
|
||||
String BulkAction::getName(bool to_undo) const {
|
||||
return to_undo ? name_undo : name_do;
|
||||
}
|
||||
|
||||
void BulkAction::perform(bool to_undo) {
|
||||
FOR_EACH(action, actions) {
|
||||
action->perform(to_undo);
|
||||
set->actions.tellListeners(*action, to_undo);
|
||||
}
|
||||
card_list_window->Refresh();
|
||||
}
|
||||
|
||||
bool BulkAction::merge(const Action& action) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Action performer
|
||||
|
||||
ValueActionPerformer::ValueActionPerformer(const ValueP& value, CardP const& card, const SetP& set)
|
||||
|
||||
+30
-16
@@ -23,6 +23,7 @@
|
||||
#include <data/field/image.hpp>
|
||||
#include <data/field/symbol.hpp>
|
||||
#include <data/field/package_choice.hpp>
|
||||
#include <gui/control/card_list.hpp>
|
||||
|
||||
class StyleSheet;
|
||||
class LocalFileName;
|
||||
@@ -30,15 +31,8 @@ DECLARE_POINTER_TYPE(Card);
|
||||
DECLARE_POINTER_TYPE(Set);
|
||||
DECLARE_POINTER_TYPE(Value);
|
||||
DECLARE_POINTER_TYPE(Style);
|
||||
DECLARE_POINTER_TYPE(TextValue);
|
||||
DECLARE_POINTER_TYPE(ChoiceValue);
|
||||
DECLARE_POINTER_TYPE(MultipleChoiceValue);
|
||||
DECLARE_POINTER_TYPE(ColorValue);
|
||||
DECLARE_POINTER_TYPE(ImageValue);
|
||||
DECLARE_POINTER_TYPE(SymbolValue);
|
||||
DECLARE_POINTER_TYPE(PackageChoiceValue);
|
||||
|
||||
// ----------------------------------------------------------------------------- : ValueAction (based class)
|
||||
// ----------------------------------------------------------------------------- : ValueAction (base class)
|
||||
|
||||
/// An Action the changes a Value
|
||||
class ValueAction : public Action {
|
||||
@@ -72,6 +66,15 @@ inline void swap_value(MultipleChoiceValue& a, MultipleChoiceValue::ValueType& b
|
||||
swap(a.last_change, b.last_change);
|
||||
}
|
||||
|
||||
/// Action that updates a Value to a new value
|
||||
unique_ptr<ValueAction> value_action(const TextValueP& value, const Defaultable<String>& new_value);
|
||||
unique_ptr<ValueAction> value_action(const ChoiceValueP& value, const Defaultable<String>& new_value);
|
||||
unique_ptr<ValueAction> value_action(const MultipleChoiceValueP& value, const Defaultable<String>& new_value, const String& last_change);
|
||||
unique_ptr<ValueAction> value_action(const ColorValueP& value, const Defaultable<Color>& new_value);
|
||||
unique_ptr<ValueAction> value_action(const ImageValueP& value, const LocalFileName& new_value);
|
||||
unique_ptr<ValueAction> value_action(const SymbolValueP& value, const LocalFileName& new_value);
|
||||
unique_ptr<ValueAction> value_action(const PackageChoiceValueP& value, const String& new_value);
|
||||
|
||||
/// A ValueAction that swaps between old and new values
|
||||
template <typename T, bool ALLOW_MERGE>
|
||||
class SimpleValueAction : public ValueAction {
|
||||
@@ -101,14 +104,6 @@ public:
|
||||
typename T::ValueType new_value;
|
||||
};
|
||||
|
||||
/// Action that updates a Value to a new value
|
||||
unique_ptr<ValueAction> value_action(const ChoiceValueP& value, const Defaultable<String>& new_value);
|
||||
unique_ptr<ValueAction> value_action(const MultipleChoiceValueP& value, const Defaultable<String>& new_value, const String& last_change);
|
||||
unique_ptr<ValueAction> value_action(const ColorValueP& value, const Defaultable<Color>& new_value);
|
||||
unique_ptr<ValueAction> value_action(const ImageValueP& value, const LocalFileName& new_value);
|
||||
unique_ptr<ValueAction> value_action(const SymbolValueP& value, const LocalFileName& new_value);
|
||||
unique_ptr<ValueAction> value_action(const PackageChoiceValueP& value, const String& new_value);
|
||||
|
||||
// ----------------------------------------------------------------------------- : Text
|
||||
|
||||
/// An action that changes a TextValue
|
||||
@@ -206,6 +201,25 @@ public:
|
||||
const Style* style; ///< The modified style
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : Bulk action
|
||||
|
||||
// An action that's just a list of other actions
|
||||
class BulkAction : public Action {
|
||||
public:
|
||||
BulkAction(const vector<shared_ptr<Action>>& actions, const SetP& set, CardListBase* card_list_window);
|
||||
~BulkAction() override;
|
||||
|
||||
String getName(bool to_undo) const override;
|
||||
void perform(bool to_undo) override;
|
||||
bool merge(const Action& action) override;
|
||||
|
||||
private:
|
||||
String name_do;
|
||||
String name_undo;
|
||||
vector<shared_ptr<Action>> actions;
|
||||
SetP set;
|
||||
CardListBase* card_list_window;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : Action performer
|
||||
|
||||
|
||||
@@ -0,0 +1,330 @@
|
||||
//+----------------------------------------------------------------------------+
|
||||
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
|
||||
//| Copyright: (C) Twan van Laarhoven and the other MSE developers |
|
||||
//| License: GNU General Public License 2 or later (see file COPYING) |
|
||||
//+----------------------------------------------------------------------------+
|
||||
|
||||
// ----------------------------------------------------------------------------- : Includes
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <regex>
|
||||
#include <util/prec.hpp>
|
||||
#include <data/game.hpp>
|
||||
#include <data/set.hpp>
|
||||
#include <data/card.hpp>
|
||||
#include <data/stylesheet.hpp>
|
||||
#include <data/field/multiple_choice.hpp>
|
||||
#include <data/field/symbol.hpp>
|
||||
#include <data/action/set.hpp>
|
||||
#include <data/action/value.hpp>
|
||||
#include <script/functions/construction_helper.hpp>
|
||||
#include <gui/bulk_modification_window.hpp>
|
||||
#include <gui/control/card_list.hpp>
|
||||
#include <util/window_id.hpp>
|
||||
#include <wx/statline.h>
|
||||
|
||||
// ----------------------------------------------------------------------------- : AddCSV
|
||||
|
||||
BulkModificationWindow::BulkModificationWindow(Window* parent, const SetP& set, bool sizer)
|
||||
: wxDialog(parent, wxID_ANY, _TITLE_("bulk modify"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
, set(set), parent(parent)
|
||||
{
|
||||
// init controls
|
||||
ok_button = new wxButton(this, wxID_OK);
|
||||
predicate_description = new wxStaticText(this, -1, _LABEL_("bulk modify predicate description"));
|
||||
predicate = new wxTextCtrl(this, ID_CARD_BULK_PREDICATE, wxEmptyString, wxDefaultPosition, wxSize(400, 70), wxTE_MULTILINE);
|
||||
predicate->SetHint(_LABEL_("bulk modify predicate example") + _("\ncard.cmc <= 3 and contains(card.type, match:\"Creature\")"));
|
||||
predicate_errors = new wxStaticText(this, wxID_ANY, _(""));
|
||||
predicate_errors->SetForegroundColour(*wxRED);
|
||||
modification_description = new wxStaticText(this, -1, _LABEL_("bulk modify mod description"));
|
||||
modification = new wxTextCtrl(this, ID_CARD_BULK_MODIFICATION, wxEmptyString, wxDefaultPosition, wxSize(400, 70), wxTE_MULTILINE);
|
||||
modification_errors = new wxStaticText(this, wxID_ANY, _(""));
|
||||
modification_errors->SetForegroundColour(*wxRED);
|
||||
modification_parsed = true;
|
||||
modification_selection = new wxChoice(this, ID_CARD_BULK_TYPE, wxDefaultPosition, wxDefaultSize, 0, nullptr);
|
||||
modification_selection->Clear();
|
||||
modification_selection->Append(_LABEL_("bulk modify all"));
|
||||
modification_selection->Append(_LABEL_("bulk modify filtered"));
|
||||
modification_selection->Append(_LABEL_("bulk modify selected"));
|
||||
modification_selection->Append(_LABEL_("bulk modify predicate"));
|
||||
modification_selection->SetSelection(0);
|
||||
changeSelection();
|
||||
parseModification();
|
||||
field_type = new wxChoice(this, ID_CARD_BULK_FIELD, wxDefaultPosition, wxDefaultSize, 0, nullptr, wxCB_SORT);
|
||||
field_type->Clear();
|
||||
String default_selection = _("");
|
||||
field_type->Append(_("id"));
|
||||
field_type->Append(_("stylesheet"));
|
||||
field_type->Append(_("notes"));
|
||||
FOR_EACH(field, set->game->card_fields) {
|
||||
field_type->Append(field->name);
|
||||
if (field->identifying) default_selection = field->name;
|
||||
}
|
||||
int default_index = field_type->FindString(default_selection);
|
||||
if (default_index == wxNOT_FOUND) default_index = 0;
|
||||
field_type->SetSelection(default_index);
|
||||
// init sizers
|
||||
if (sizer) {
|
||||
wxSizer* s = new wxBoxSizer(wxVERTICAL);
|
||||
s->Add(new wxStaticText(this, -1, _LABEL_("bulk modify selection")), 0, wxALL, 8);
|
||||
s->Add(modification_selection, 0, wxEXPAND | (wxALL & ~wxTOP), 8);
|
||||
s->Add(predicate_description, 0, wxEXPAND | wxALL, 8);
|
||||
s->Add(predicate, 0, wxEXPAND | (wxALL & ~wxTOP), 8);
|
||||
s->Add(predicate_errors, 0, wxALL & ~wxTOP, 8);
|
||||
s->AddSpacer(20);
|
||||
s->Add(new wxStaticText(this, -1, _LABEL_("bulk modify field")), 0, wxALL, 8);
|
||||
s->Add(field_type, 0, wxEXPAND | (wxALL & ~wxTOP), 8);
|
||||
s->Add(modification_description, 0, wxEXPAND | wxALL, 8);
|
||||
s->Add(modification, 0, wxEXPAND | (wxALL & ~wxTOP), 8);
|
||||
s->Add(modification_errors, 0, wxALL & ~wxTOP, 8);
|
||||
s->AddStretchSpacer(1);
|
||||
wxStdDialogButtonSizer* s1 = new wxStdDialogButtonSizer();
|
||||
s1->AddStretchSpacer(1);
|
||||
s1->AddButton(ok_button);
|
||||
s1->AddButton(new wxButton(this, wxID_CANCEL));
|
||||
s1->Realize();
|
||||
s->Add(s1, 1, wxEXPAND | wxALL, 12);
|
||||
s->SetSizeHints(this);
|
||||
SetSizer(s);
|
||||
SetSize(600, 400);
|
||||
Layout();
|
||||
}
|
||||
}
|
||||
|
||||
void BulkModificationWindow::updateOkButton() {
|
||||
if (predicate_parsed && modification_parsed) {
|
||||
ok_button->Enable(true);
|
||||
}
|
||||
else {
|
||||
ok_button->Enable(false);
|
||||
}
|
||||
}
|
||||
|
||||
void BulkModificationWindow::changeSelection() {
|
||||
if (modification_selection->GetSelection() <= 2) {
|
||||
predicate_description->Hide();
|
||||
predicate->Hide();
|
||||
predicate_errors->Hide();
|
||||
predicate_parsed = true;
|
||||
SetSize(600, 400);
|
||||
} else {
|
||||
predicate_description->Show();
|
||||
predicate->Show();
|
||||
predicate_errors->Show();
|
||||
parsePredicate();
|
||||
SetSize(600, 560);
|
||||
}
|
||||
updateOkButton();
|
||||
Layout();
|
||||
}
|
||||
|
||||
void BulkModificationWindow::onSelectionChange(wxCommandEvent&) {
|
||||
changeSelection();
|
||||
}
|
||||
|
||||
void BulkModificationWindow::parsePredicate() {
|
||||
vector<ScriptParseError> parse_errors;
|
||||
String value = predicate->GetValue();
|
||||
if (value.StartsWith("{") && value.EndsWith("}")) value = value.substr(1, value.length()-2);
|
||||
predicate_script = parse(value, nullptr, false, parse_errors);
|
||||
if (parse_errors.empty()) {
|
||||
predicate_errors->SetLabel(_(""));
|
||||
predicate_parsed = true;
|
||||
}
|
||||
else {
|
||||
predicate_errors->SetLabel(ScriptParseErrors(parse_errors).what());
|
||||
predicate_parsed = false;
|
||||
}
|
||||
updateOkButton();
|
||||
}
|
||||
|
||||
void BulkModificationWindow::onPredicateChange(wxCommandEvent&) {
|
||||
parsePredicate();
|
||||
}
|
||||
|
||||
void BulkModificationWindow::parseModification() {
|
||||
vector<ScriptParseError> parse_errors;
|
||||
modification_script = parse(modification->GetValue(), nullptr, true, parse_errors);
|
||||
if (parse_errors.empty()) {
|
||||
modification_errors->SetLabel(_(""));
|
||||
modification_parsed = true;
|
||||
}
|
||||
else {
|
||||
modification_errors->SetLabel(ScriptParseErrors(parse_errors).what());
|
||||
modification_parsed = false;
|
||||
}
|
||||
updateOkButton();
|
||||
}
|
||||
|
||||
void BulkModificationWindow::onModificationChange(wxCommandEvent&) {
|
||||
parseModification();
|
||||
}
|
||||
|
||||
void BulkModificationWindow::onOk(wxCommandEvent&) {
|
||||
wxBusyCursor wait;
|
||||
// get the context
|
||||
CardListBase* card_list_window = dynamic_cast<CardListBase*>(parent);
|
||||
if (!card_list_window) {
|
||||
queue_message(MESSAGE_ERROR, _("Bulk modification must be called from a card list window!"));
|
||||
EndModal(wxID_ABORT);
|
||||
return;
|
||||
}
|
||||
// get the cards
|
||||
vector<CardP> cards;
|
||||
int selection_type = modification_selection->GetSelection();
|
||||
if (selection_type == 0) { // all
|
||||
for (int i = 0; i < set->cards.size(); ++i) {
|
||||
cards.push_back(set->cards[i]);
|
||||
}
|
||||
} else if (selection_type == 1) { // currently filtered
|
||||
for (int i = 0; i < card_list_window->GetItemCount(); ++i) {
|
||||
cards.push_back(card_list_window->getCard(i));
|
||||
}
|
||||
} else if (selection_type == 2) { // currently selected
|
||||
card_list_window->getSelection(cards);
|
||||
} else { // predicate
|
||||
FOR_EACH(card, set->cards) {
|
||||
Context& ctx = set->getContext(card);
|
||||
ScriptValueP result = predicate_script->eval(ctx, false);
|
||||
if (result->type() != SCRIPT_BOOL) {
|
||||
queue_message(MESSAGE_ERROR, _ERROR_("bulk modify predicate is not bool"));
|
||||
EndModal(wxID_ABORT);
|
||||
return;
|
||||
}
|
||||
if (result->toBool()) {
|
||||
cards.push_back(card);
|
||||
}
|
||||
}
|
||||
}
|
||||
int count = cards.size();
|
||||
if (count == 0) {
|
||||
queue_message(MESSAGE_ERROR, _ERROR_("bulk modify no cards"));
|
||||
EndModal(wxID_ABORT);
|
||||
return;
|
||||
}
|
||||
// get the new script values
|
||||
vector<shared_ptr<Action>> actions;
|
||||
String& field_name = field_type->GetString(field_type->GetSelection());
|
||||
// stylesheet, notes or id change
|
||||
if (field_name == _("stylesheet") || field_name == _("notes") || field_name == _("id")) {
|
||||
vector<String> new_values;
|
||||
FOR_EACH(card, cards) {
|
||||
Context& ctx = set->getContext(card);
|
||||
ScriptValueP new_value = modification_script->eval(ctx, false);
|
||||
if (new_value->type() != SCRIPT_STRING) {
|
||||
queue_message(MESSAGE_ERROR, _ERROR_("bulk modify mod is not string"));
|
||||
EndModal(wxID_ABORT);
|
||||
return;
|
||||
}
|
||||
new_values.push_back(new_value->toString());
|
||||
}
|
||||
assert(count == new_values.size());
|
||||
if (field_name == _("stylesheet")) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
StyleSheetP stylesheet = StyleSheet::byGameAndName(*set->game, new_values[i]);
|
||||
actions.push_back(make_shared<ChangeCardStyleAction>(cards[i], stylesheet));
|
||||
}
|
||||
} else if (field_name == _("notes")) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
actions.push_back(make_shared<ChangeCardNotesAction>(cards[i], new_values[i]));
|
||||
}
|
||||
} else if (field_name == _("id")) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
actions.push_back(make_shared<ChangeCardUIDAction>(*set, cards[i], new_values[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
// card field value change
|
||||
else {
|
||||
vector<Value*> values;
|
||||
vector<ScriptValueP> new_values;
|
||||
FOR_EACH(card, cards) {
|
||||
Value* value = get_card_field_container(*set->game, card->data, field_name, false);
|
||||
values.push_back(value);
|
||||
Context& ctx = set->getContext(card);
|
||||
ScriptValueP new_value = modification_script->eval(ctx, false);
|
||||
new_values.push_back(new_value);
|
||||
}
|
||||
assert(count == values.size());
|
||||
assert(count == new_values.size());
|
||||
// make the modifications (I have lost my battle with c++ templates)
|
||||
if (dynamic_cast<TextValue*>(values.front())) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
TextValue* value = dynamic_cast<TextValue*>(values[i]);
|
||||
TextValue::ValueType new_value = new_values[i]->toString();
|
||||
shared_ptr<SimpleValueAction<TextValue, false>> action = make_shared<SimpleValueAction<TextValue, false>>(value, new_value);
|
||||
action->setCard(cards[i]);
|
||||
actions.push_back(action);
|
||||
}
|
||||
}
|
||||
else if (dynamic_cast<MultipleChoiceValue*>(values.front())) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
MultipleChoiceValue* value = dynamic_cast<MultipleChoiceValue*>(values[i]);
|
||||
MultipleChoiceValue::ValueType new_value = { new_values[i]->toString(), _("") };
|
||||
shared_ptr<SimpleValueAction<MultipleChoiceValue, false>> action = make_shared<SimpleValueAction<MultipleChoiceValue, false>>(value, new_value);
|
||||
action->setCard(cards[i]);
|
||||
actions.push_back(action);
|
||||
}
|
||||
}
|
||||
else if (dynamic_cast<ChoiceValue*>(values.front())) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
ChoiceValue* value = dynamic_cast<ChoiceValue*>(values[i]);
|
||||
ChoiceValue::ValueType new_value = new_values[i]->toString();
|
||||
shared_ptr<SimpleValueAction<ChoiceValue, false>> action = make_shared<SimpleValueAction<ChoiceValue, false>>(value, new_value);
|
||||
action->setCard(cards[i]);
|
||||
actions.push_back(action);
|
||||
}
|
||||
}
|
||||
else if (dynamic_cast<PackageChoiceValue*>(values.front())) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
PackageChoiceValue* value = dynamic_cast<PackageChoiceValue*>(values[i]);
|
||||
PackageChoiceValue::ValueType new_value = new_values[i]->toString();
|
||||
shared_ptr<SimpleValueAction<PackageChoiceValue, false>> action = make_shared<SimpleValueAction<PackageChoiceValue, false>>(value, new_value);
|
||||
action->setCard(cards[i]);
|
||||
actions.push_back(action);
|
||||
}
|
||||
}
|
||||
else if (dynamic_cast<ColorValue*>(values.front())) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
ColorValue* value = dynamic_cast<ColorValue*>(values[i]);
|
||||
ColorValue::ValueType new_value = new_values[i]->toColor();
|
||||
shared_ptr<SimpleValueAction<ColorValue, false>> action = make_shared<SimpleValueAction<ColorValue, false>>(value, new_value);
|
||||
action->setCard(cards[i]);
|
||||
actions.push_back(action);
|
||||
}
|
||||
}
|
||||
else if (dynamic_cast<ImageValue*>(values.front())) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
ImageValue* value = dynamic_cast<ImageValue*>(values[i]);
|
||||
wxFileName fname(static_cast<ExternalImage*>(new_values[i].get())->toString());
|
||||
ImageValue::ValueType new_value = LocalFileName::fromReadString(fname.GetName(), "");
|
||||
shared_ptr<SimpleValueAction<ImageValue, false>> action = make_shared<SimpleValueAction<ImageValue, false>>(value, new_value);
|
||||
action->setCard(cards[i]);
|
||||
actions.push_back(action);
|
||||
}
|
||||
}
|
||||
else if (dynamic_cast<SymbolValue*>(values.front())) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
SymbolValue* value = dynamic_cast<SymbolValue*>(values[i]);
|
||||
wxFileName fname(static_cast<ExternalImage*>(new_values[i].get())->toString());
|
||||
SymbolValue::ValueType new_value = LocalFileName::fromReadString(fname.GetName(), "");
|
||||
shared_ptr<SimpleValueAction<SymbolValue, false>> action = make_shared<SimpleValueAction<SymbolValue, false>>(value, new_value);
|
||||
action->setCard(cards[i]);
|
||||
actions.push_back(action);
|
||||
}
|
||||
}
|
||||
else {
|
||||
queue_message(MESSAGE_ERROR, _ERROR_("bulk modify script type unknown"));
|
||||
}
|
||||
}
|
||||
set->actions.addAction(make_unique<BulkAction>(actions, set, card_list_window), false);
|
||||
EndModal(wxID_OK);
|
||||
}
|
||||
|
||||
BEGIN_EVENT_TABLE(BulkModificationWindow, wxDialog)
|
||||
EVT_BUTTON (wxID_OK, BulkModificationWindow::onOk)
|
||||
EVT_CHOICE (ID_CARD_BULK_TYPE, BulkModificationWindow::onSelectionChange)
|
||||
EVT_TEXT (ID_CARD_BULK_PREDICATE, BulkModificationWindow::onPredicateChange)
|
||||
EVT_TEXT (ID_CARD_BULK_MODIFICATION, BulkModificationWindow::onModificationChange)
|
||||
END_EVENT_TABLE()
|
||||
@@ -0,0 +1,48 @@
|
||||
//+----------------------------------------------------------------------------+
|
||||
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
|
||||
//| Copyright: (C) Twan van Laarhoven and the other MSE developers |
|
||||
//| License: GNU General Public License 2 or later (see file COPYING) |
|
||||
//+----------------------------------------------------------------------------+
|
||||
|
||||
#pragma once
|
||||
|
||||
// ----------------------------------------------------------------------------- : Includes
|
||||
|
||||
#include <util/prec.hpp>
|
||||
|
||||
DECLARE_POINTER_TYPE(Game);
|
||||
DECLARE_POINTER_TYPE(Set);
|
||||
|
||||
// ----------------------------------------------------------------------------- : BulkModificationWindow
|
||||
|
||||
/// A window for modifying multiple cards at once.
|
||||
class BulkModificationWindow : public wxDialog {
|
||||
public:
|
||||
BulkModificationWindow(Window* parent, const SetP& set, bool sizer);
|
||||
|
||||
protected:
|
||||
DECLARE_EVENT_TABLE();
|
||||
|
||||
wxChoice* modification_selection, *field_type;
|
||||
wxStaticText* modification_description, *modification_errors, *predicate_description, *predicate_errors;
|
||||
wxTextCtrl* modification, *predicate;
|
||||
bool modification_parsed, predicate_parsed;
|
||||
wxButton* ok_button;
|
||||
SetP set;
|
||||
Window* parent;
|
||||
ScriptP modification_script, predicate_script;
|
||||
|
||||
void onSelectionChange(wxCommandEvent&);
|
||||
void changeSelection();
|
||||
|
||||
void onPredicateChange(wxCommandEvent&);
|
||||
void parsePredicate();
|
||||
|
||||
void onModificationChange(wxCommandEvent&);
|
||||
void parseModification();
|
||||
|
||||
void updateOkButton();
|
||||
|
||||
void onOk(wxCommandEvent&);
|
||||
|
||||
};
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <gui/util.hpp>
|
||||
#include <gui/add_csv_window.hpp>
|
||||
#include <gui/add_json_window.hpp>
|
||||
#include <gui/bulk_modification_window.hpp>
|
||||
#include <data/game.hpp>
|
||||
#include <data/field.hpp>
|
||||
#include <data/field/choice.hpp>
|
||||
@@ -232,6 +233,15 @@ bool CardListBase::doAddJSON() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CardListBase::doBulkModification() {
|
||||
BulkModificationWindow wnd(this, set, true);
|
||||
if (wnd.ShowModal() == wxID_OK) {
|
||||
// The actual modifying is done in this window's onOk function
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CardListBase::parseUrl(String& url, vector<CardP>& out) {
|
||||
size_t j = out.size();
|
||||
size_t pos = url.find("URL=");
|
||||
|
||||
@@ -82,9 +82,13 @@ public:
|
||||
bool doCopyCardAndLinkedCards();
|
||||
bool doPaste() override;
|
||||
bool doDelete() override;
|
||||
|
||||
// Try to perform a bulk operation, return success
|
||||
bool doAddCSV();
|
||||
bool doAddJSON();
|
||||
|
||||
bool doBulkModification();
|
||||
|
||||
// Look for cards inside some given data
|
||||
bool parseData(bool ignore_cards_from_own_card_list);
|
||||
bool parseUrl (String& url, vector<CardP>& out);
|
||||
|
||||
@@ -138,6 +138,7 @@ CardsPanel::CardsPanel(Window* parent, int id)
|
||||
add_menu_item(menuCard, ID_CARD_REMOVE, "card_del", _MENU_("remove card")+_(" "), _HELP_("remove card"));
|
||||
add_menu_item(menuCard, ID_CARD_LINK, "card_link", _MENU_("link card") + _(" "), _HELP_("link card"));
|
||||
add_menu_item(menuCard, ID_CARD_AND_LINK_COPY, "card_copy", _MENU_("copy card and links") + _(" "), _HELP_("copy card and links"));
|
||||
add_menu_item(menuCard, ID_CARD_BULK, "card_modify_multiple", _MENU_("bulk modify") + _(" "), _HELP_("bulk modify"));
|
||||
menuCard->AppendSeparator();
|
||||
auto menuRotate = new wxMenu();
|
||||
add_menu_item_tr(menuRotate, ID_CARD_ROTATE_0, "card_rotate_0", "rotate_0", wxITEM_CHECK);
|
||||
@@ -452,6 +453,9 @@ void CardsPanel::onCommand(int id) {
|
||||
case ID_CARD_AND_LINK_COPY:
|
||||
card_list->doCopyCardAndLinkedCards();
|
||||
break;
|
||||
case ID_CARD_BULK:
|
||||
card_list->doBulkModification();
|
||||
break;
|
||||
case ID_CARD_ROTATE:
|
||||
case ID_CARD_ROTATE_0: case ID_CARD_ROTATE_90: case ID_CARD_ROTATE_180: case ID_CARD_ROTATE_270: {
|
||||
StyleSheetSettings& ss = settings.stylesheetSettingsFor(set->stylesheetFor(card_list->getCard()));
|
||||
|
||||
@@ -116,6 +116,11 @@ enum ChildMenuID {
|
||||
ID_CARD_ADD_JSON,
|
||||
ID_CARD_ADD_JSON_ARRAY,
|
||||
ID_CARD_ADD_JSON_BROWSE,
|
||||
ID_CARD_BULK,
|
||||
ID_CARD_BULK_TYPE,
|
||||
ID_CARD_BULK_FIELD,
|
||||
ID_CARD_BULK_MODIFICATION,
|
||||
ID_CARD_BULK_PREDICATE,
|
||||
|
||||
// Keyword menu
|
||||
ID_KEYWORD_ADD = 6101,
|
||||
|
||||
Reference in New Issue
Block a user