1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
#pragma once
#include <queue>
#include <mutex>
#include <stack>
#include <map>
#include "DataCell.hh"
#include "tree.hh"
namespace cadabra {
class ActionBase;
class ActionAddCell;
class ActionPositionCursor;
class ActionRemoveCell;
class ActionSetRunStatus;
class ActionSplitCell;
class ActionInsertText;
class ActionCompleteText;
class ActionEraseText;
class ComputeThread;
class GUIBase;
/// \ingroup clientserver
///
/// A base class with all the logic to manipulate a Cadabra
/// notebook document. Relies on the various objects derived from
/// ActionBase in order to get actual work done. All methods here
/// will always run on the GUI thread.
///
/// In order to implement a GUI, derive from both DocumentThread
/// and GUIBase and then implement the virtual functions of the
/// latter (those implement basic insertion/removal of notebook
/// cells; the logic to figure out which ones and to implement the
/// undo/redo stack is all in the GUI-agnostic DocumentThread).
class DocumentThread {
public:
DocumentThread(GUIBase *);
/// It is not possible to copy-construct a DocumentThread as
/// it holds on to resources which are not easily copied
/// (such as GUI elements).
DocumentThread(const DocumentThread&)=delete;
/// Let the notebook know about the ComputeThread so that it
/// can send cells for evaluation. Notebook does NOT own this
/// pointer.
virtual void set_compute_thread(ComputeThread *);
/// Ensure that the gui has an up-to-date representation of the
/// dtree. Traverses the entire tree so is expensive to run and
/// should only be used when loading new documents or creating
/// a new canvas view.
void build_visual_representation();
/// All changes to the document should be made by submitting
/// ActionBase derived objects to the 'queue_action' function,
/// so that an undo stack can be kept. They are then processed
/// by calling the 'process_action_queue' method (only
/// available from this thread).
void queue_action(std::shared_ptr<ActionBase>);
/// Setup an empty new document with a single Python input cell.
void new_document();
/// Load a new notebook from a JSON string. Should only be called
/// from the GUI thread. Will cancel any pending operations on the
/// existing notebook (if present) first.
void load_from_string(const std::string&);
virtual void on_interactive_output(const nlohmann::json& msg);
virtual void set_progress(const std::string& msg, int cur_step, int total_steps);
/// One undo step.
void undo();
/// Find string, return match, or a (doc.end(), std::string::npos).
std::pair<DTree::iterator, size_t> find_string(DTree::iterator start_it, size_t start_pos, const std::string& f, bool case_ins) const;
friend ActionBase;
friend ActionAddCell;
friend ActionPositionCursor;
friend ActionRemoveCell;
friend ActionSplitCell;
friend ActionSetRunStatus;
friend ActionInsertText;
friend ActionCompleteText;
friend ActionEraseText;
class Prefs {
public:
using ColorMap = std::map<std::string, std::string>;
Prefs(bool use_defaults = false);
void save();
int font_step;
bool highlight;
bool is_registered;
bool is_anonymous;
std::map<std::string, ColorMap> colours;
std::string git_path;
std::string python_path;
bool move_into_new_cell;
bool tab_completion;
private:
nlohmann::json data;
std::string config_path;
};
Prefs prefs;
/// Set user details which will be sent to the Cadabra log
/// server.
void set_user_details(const std::string& name, const std::string& email, const std::string& affiliation);
protected:
GUIBase *gui;
ComputeThread *compute;
/// The actual document tree. This object is only modified on
/// the GUI thread, either directly by code in
/// DocumentThread, or by code in the various objects derived
/// from ActionBase. In particular, ComputeThread cannot
/// access this tree directly.
DTree doc;
/// The action undo/redo/todo stacks and logic to execute
/// them. These stacks can be accessed from both the
/// DocumentThread as well as the ComputeThread (the latter
/// does it through the DocumentThread::queue_action method),
/// so they need a mutex to access them.
std::mutex stack_mutex;
typedef std::stack<std::shared_ptr<ActionBase> > ActionStack;
ActionStack undo_stack, redo_stack;
std::queue<std::shared_ptr<ActionBase> > pending_actions;
bool disable_stacks;
/// Process the action queue. It is allowed to call queue_action() above
/// while this is running. So a running action can add more actions.
void process_action_queue();
virtual bool on_unhandled_error(const std::exception& err);
/// Help system
enum class help_t { algorithm, property, latex, none };
bool help_type_and_topic(const std::string& before, const std::string& after,
help_t& help_type, std::string& help_topic) const;
};
}
|