1 /***************************************************************************
2                           rkvareditmodel  -  description
3                              -------------------
4     begin                : Mon Nov 05 2007
5     copyright            : (C) 2007, 2010, 2011 by Thomas Friedrichsmeier
6     email                : thomas.friedrichsmeier@kdemail.net
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #ifndef RKVAREDITMODEL
19 #define RKVAREDITMODEL
20 
21 #include <QAbstractTableModel>
22 #include <QItemSelectionRange>
23 #include <QList>
24 
25 #include "rktextmatrix.h"
26 #include "../core/rkvariable.h"
27 #include "../core/rkmodificationtracker.h"
28 
29 class RKVarEditMetaModel;
30 class RCommandChain;
31 class RKEditor;
32 class RKRowNames;
33 
34 /** Base class for RKVarEditModel and RKVarEditMetaModel. Defines a common interface for copy and paste operations. Models might reimplement these functions for more efficiency.
35 @author Thomas Friedrichsmeier */
36 class RKVarEditModelBase : public QAbstractTableModel {
37 public:
RKVarEditModelBase(QObject * parent)38 	explicit RKVarEditModelBase (QObject *parent) : QAbstractTableModel (parent) {};
~RKVarEditModelBase()39 	virtual ~RKVarEditModelBase () {};
40 
41 	virtual RKTextMatrix getTextMatrix (const QItemSelectionRange& range) const = 0;
42 	virtual void blankRange (const QItemSelectionRange& range) = 0;
43 	virtual void setTextMatrix (const QModelIndex& offset, const RKTextMatrix& text, const QItemSelectionRange& confine_to = QItemSelectionRange ()) = 0;
44 
45 	virtual int trueRows () const = 0;
46 	virtual int trueCols () const = 0;
firstRealColumn()47 	int firstRealColumn () const { return var_col_offset; };
48 
49 	int var_col_offset;
50 };
51 
52 /** This class represents a collection of RKVariables of uniform length (typically a data.frame) suitable for editing in a model/view editor such as QTableView. Probably it will only ever support editing a single RKVariable, though, as it is not possible to ensure uniform length outside of a data.frame. For a data.frame use RKVarEditDataFrameModel . Since the real data storage is in RKVariable, it is ok (and recommended) to create separate models for separate editors/viewers, even if the objects in question are the same. */
53 class RKVarEditModel : public RKVarEditModelBase, public RObjectListener {
54 	Q_OBJECT
55 public:
56 	explicit RKVarEditModel (QObject *parent);
57 	~RKVarEditModel ();
58 
59 	/** set the editor that is using this model. This is useful to find out, e.g. which window should be raised, when calling "Edit" on an object represented in this data-model. Also, the editor will be notified, if all objects in the model have been removed. */
setEditor(RKEditor * editor)60 	void setEditor (RKEditor* editor) { myeditor = editor; };
61 	/** see setEditor () */
getEditor()62 	RKEditor* getEditor () const { return myeditor; };
63 
64 	/** Add an object to the model at the given index. Calls this only once, unless from an RKVarEditDataFrameModel. You should add at least one object, **before** you add this model to any view.
65 	@param index position to insert at, or -1 to append the item
66 	@param object the objects to insert */
67 	void addObject (int index, RKVariable* object);
68 	/** Return a pointer to the meta model. The meta model is created the first time this function is called. */
69 	RKVarEditMetaModel* getMetaModel ();
70 
71 	// QAbstractTableModel implementations
72 	bool insertRows (int row, int count, const QModelIndex& parent = QModelIndex()) override;
73 	bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex()) override;
74 	int rowCount (const QModelIndex& parent = QModelIndex()) const override;
75 	int columnCount (const QModelIndex& parent = QModelIndex()) const override;
76 	QVariant data (const QModelIndex& index, int role = Qt::DisplayRole) const override;
77 	Qt::ItemFlags flags (const QModelIndex& index) const override;
78 	bool setData (const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;
79 	QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
80 
81 	RKTextMatrix getTextMatrix (const QItemSelectionRange& range) const override;
82 	void blankRange (const QItemSelectionRange& range) override;
83 	void setTextMatrix (const QModelIndex& offset, const RKTextMatrix& text, const QItemSelectionRange& confine_to = QItemSelectionRange ()) override;
84 
trueCols()85 	int trueCols () const override { return objects.size (); };
trueRows()86 	int trueRows () const override { return (objects.isEmpty () ? 0 : objects[0]->getLength ()); };
lockHeader(bool lock)87 	void lockHeader (bool lock) { header_locked = lock; };
88 
89 	virtual void restoreObject (RObject* object, RCommandChain* chain);
90 
91 	void objectMetaChanged (RObject* changed) override;
92 	void objectDataChanged (RObject* object, const RObject::ChangeSet *changes) override;
93 
94 	RKVariable* getObject (int index) const;
95 signals:
96 	void modelDepleted ();
97 	void hasDuplicates (const QStringList& dupes);
98 private slots:
99 	void checkDuplicatesNow ();
100 	void doResetNow ();
101 private:
102 	bool reset_scheduled;
103 	void scheduleReset ();
104 protected:
105 friend class RKVarEditMetaModel;
106 	QList<RKVariable*> objects;
107 	RKRowNames *rownames;
108 
109 	/** very simple convenience function to return the number of true cols + trailing cols */
apparentCols()110 	int apparentCols () const { return (trueCols () + trailing_cols); };
111 	/** very simple convenience function to return the number of true rows + trailing rows */
apparentRows()112 	int apparentRows () const { return (trueRows () + trailing_rows); };
113 
114 	/** Receives notifications of object removals. Takes care of removing the object from the list. */
115 	void objectRemoved (RObject* object) override;
116 
117 	/** insert new columns at index. Default implementation does nothing. To be implemented in subclasses */
118 	virtual void doInsertColumns (int index, int count);
119 
120 	virtual void doInsertRowsInBackend (int row, int count);
121 	virtual void doRemoveRowsInBackend (int row, int count);
122 
123 	/** Check whether there are any duplicate names in the model. Actual check is delayed until the next iteration of the event loop. If a duplicate is found, hasDuplicates(const QStringList&) is emitted. */
124 	void checkDuplicates ();
125 	bool duplicate_check_triggered;
126 
127 	int trailing_rows;
128 	int trailing_cols;
129 
130 	int edit_blocks;
131 	bool header_locked;
132 
133 	RKVarEditMetaModel* meta_model;
134 	RKEditor* myeditor;
135 };
136 
137 /** Represents the meta information portion belonging to an RKVarEditModel. Implemented in a separate class for technical reasons, only (so this info can be displayed in a separate QTableView). This model mostly acts as a slave of an RKVarEditModel. You will not need to call any functions directly except from the RKVarEditModel, or an item view. */
138 class RKVarEditMetaModel : public RKVarEditModelBase {
139 	Q_OBJECT
140 public:
141 	enum Rows {
142 		NameRow=0,
143 		LabelRow,
144 		TypeRow,
145 		FormatRow,
146 		LevelsRow,
147 		RowCount = LevelsRow + 1
148 	};
149 
150 	// QAbstractTableModel implementations
151 	int rowCount (const QModelIndex& parent = QModelIndex()) const override;
152 	int columnCount (const QModelIndex& parent = QModelIndex()) const override;
153 	QVariant data (const QModelIndex& index, int role = Qt::DisplayRole) const override;
154 	Qt::ItemFlags flags (const QModelIndex& index) const override;
155 	bool setData (const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;
156 	QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
157 
158 	RKTextMatrix getTextMatrix (const QItemSelectionRange& range) const override;
159 	void blankRange (const QItemSelectionRange& range) override;
160 	void setTextMatrix (const QModelIndex& offset, const RKTextMatrix& text, const QItemSelectionRange& confine_to = QItemSelectionRange ()) override;
161 
trueCols()162 	int trueCols () const override { return data_model->trueCols (); };
trueRows()163 	int trueRows () const override { return RowCount; };
164 
165 	RObject::ValueLabels getValueLabels (int column) const;
166 	void setValueLabels (int column, const RObject::ValueLabels& labels);
167 
getObject(int index)168 	RKVariable* getObject (int index) const { return data_model->getObject (index); };
getDataModel()169 	RKVarEditModel* getDataModel () const { return data_model; };
170 protected:
171 friend class RKVarEditModel;
172 	RKVarEditMetaModel (RKVarEditModel* data_model);
173 	~RKVarEditMetaModel ();
174 
175 	void beginAddDataObject (int index);
176 	void endAddDataObject ();
177 	void beginRemoveDataObject (int index);
178 	void endRemoveDataObject ();
179 	void objectMetaChanged (int atcolumn);
180 
181 	RKVarEditModel* data_model;
182 };
183 
184 
185 class RKVarEditDataFrameModel : public RKVarEditModel {
186 	Q_OBJECT
187 public:
188 	RKVarEditDataFrameModel (RContainerObject* dataframe, QObject* parent);
189 /** ctor that constructs a new empty data frame */
190 	RKVarEditDataFrameModel (const QString& validized_name, RContainerObject* parent_object, RCommandChain* chain, int initial_cols, QObject* parent);
191 	~RKVarEditDataFrameModel ();
192 
193 	bool insertColumns (int column, int count, const QModelIndex& parent = QModelIndex()) override;
194 	bool removeColumns (int column, int count, const QModelIndex& parent = QModelIndex()) override;
195 
getObject()196 	RContainerObject* getObject () const { return dataframe; };
197 
198 	void restoreObject (RObject* object, RCommandChain* chain) override;
199 signals:
200 	void modelObjectDestroyed ();
201 protected:
202 	void doInsertColumns (int index, int count) override;
203 	/** reimplemented from RKVarEditModel to listen for the dataframe object as well */
204 	void objectRemoved (RObject* object) override;
205 	/** receives notifications of new objects added to this data.frame */
206 	void childAdded (int index, RObject* parent) override;
207 	/** receives notifications of object position changes inside this data.frame */
208 	void childMoved (int old_index, int new_index, RObject* parent) override;
209 
210 	void doInsertRowsInBackend (int row, int count) override;
211 	void doRemoveRowsInBackend (int row, int count) override;
212 
213 	RContainerObject* dataframe;
214 
215 	void init (RContainerObject* dataframe);
216 	void pushTable (RCommandChain* sync_chain);
217 };
218 
219 #endif
220