diff --git a/resource/tool/card_modify_multiple.png b/resource/tool/card_modify_multiple.png new file mode 100644 index 00000000..eb3d9b22 Binary files /dev/null and b/resource/tool/card_modify_multiple.png differ diff --git a/resource/win32_res.rc b/resource/win32_res.rc index 4d052b5c..21d8b6bd 100644 --- a/resource/win32_res.rc +++ b/resource/win32_res.rc @@ -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" diff --git a/src/data/action/set.cpp b/src/data/action/set.cpp index 8f445e87..a5470368 100644 --- a/src/data/action/set.cpp +++ b/src/data/action/set.cpp @@ -212,7 +212,34 @@ String ChangeCardHasStylingAction::getName(bool to_undo) const { void ChangeCardHasStylingAction::perform(bool to_undo) { card->has_styling = !card->has_styling; 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 diff --git a/src/data/action/set.hpp b/src/data/action/set.hpp index 9e43864c..d8156466 100644 --- a/src/data/action/set.hpp +++ b/src/data/action/set.hpp @@ -147,8 +147,38 @@ public: Set& set; ///< The set to copy styling from CardP card; ///< The affected card IndexMap 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 diff --git a/src/data/action/value.cpp b/src/data/action/value.cpp index 2cd5bb55..888bdf5a 100644 --- a/src/data/action/value.cpp +++ b/src/data/action/value.cpp @@ -36,7 +36,10 @@ void ValueAction::setCard(CardP const& card) { } // ----------------------------------------------------------------------------- : Simple - + +unique_ptr value_action(const TextValueP& value, const Defaultable& new_value) { + return make_unique>(value, new_value); +} unique_ptr value_action(const ChoiceValueP& value, const Defaultable& new_value) { return make_unique>(value, new_value); } @@ -205,7 +208,34 @@ String ScriptStyleEvent::getName(bool) const { } void ScriptStyleEvent::perform(bool) { assert(false); // this action is just an event, it should not be performed +} + +// ----------------------------------------------------------------------------- : Bulk action + +BulkAction::BulkAction(const vector>& 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 diff --git a/src/data/action/value.hpp b/src/data/action/value.hpp index 3a5c736f..f7ba1606 100644 --- a/src/data/action/value.hpp +++ b/src/data/action/value.hpp @@ -23,6 +23,7 @@ #include #include #include +#include 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 value_action(const TextValueP& value, const Defaultable& new_value); +unique_ptr value_action(const ChoiceValueP& value, const Defaultable& new_value); +unique_ptr value_action(const MultipleChoiceValueP& value, const Defaultable& new_value, const String& last_change); +unique_ptr value_action(const ColorValueP& value, const Defaultable& new_value); +unique_ptr value_action(const ImageValueP& value, const LocalFileName& new_value); +unique_ptr value_action(const SymbolValueP& value, const LocalFileName& new_value); +unique_ptr value_action(const PackageChoiceValueP& value, const String& new_value); + /// A ValueAction that swaps between old and new values template class SimpleValueAction : public ValueAction { @@ -79,13 +82,13 @@ public: inline SimpleValueAction(const intrusive_ptr& value, const typename T::ValueType& new_value) : ValueAction(value), new_value(new_value) {} - + void perform(bool to_undo) override { ValueAction::perform(to_undo); swap_value(static_cast(*valueP), new_value); valueP->onAction(*this, to_undo); // notify value } - + bool merge(const Action& action) override { if (!ALLOW_MERGE) return false; TYPE_CASE(action, SimpleValueAction) { @@ -97,18 +100,10 @@ public: } return false; } - + typename T::ValueType new_value; }; -/// Action that updates a Value to a new value -unique_ptr value_action(const ChoiceValueP& value, const Defaultable& new_value); -unique_ptr value_action(const MultipleChoiceValueP& value, const Defaultable& new_value, const String& last_change); -unique_ptr value_action(const ColorValueP& value, const Defaultable& new_value); -unique_ptr value_action(const ImageValueP& value, const LocalFileName& new_value); -unique_ptr value_action(const SymbolValueP& value, const LocalFileName& new_value); -unique_ptr 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>& 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> actions; + SetP set; + CardListBase* card_list_window; +}; // ----------------------------------------------------------------------------- : Action performer diff --git a/src/gui/bulk_modification_window.cpp b/src/gui/bulk_modification_window.cpp new file mode 100644 index 00000000..edeb71d4 --- /dev/null +++ b/src/gui/bulk_modification_window.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include