1 // This may look like C code, but it's really -*- C++ -*- 2 /* 3 * Copyright (C) 2008 Emweb bv, Herent, Belgium. 4 * 5 * See the LICENSE file for terms of use. 6 */ 7 #ifndef WABSTRACT_PROXY_MODEL_H_ 8 #define WABSTRACT_PROXY_MODEL_H_ 9 10 #include <Wt/WAbstractItemModel.h> 11 12 namespace Wt { 13 14 /*! \class WAbstractProxyModel Wt/WAbstractProxyModel.h Wt/WAbstractProxyModel.h 15 * \brief An abstract proxy model for %Wt's item models. 16 * 17 * A proxy model does not store data, but presents data from a source 18 * model in another way. It may provide filtering, sorting, or other 19 * computed changes to the source model. A proxy model may be a fully 20 * functional model, that also allows modification of the underlying 21 * model. 22 * 23 * This abstract proxy model may be used as a starting point for 24 * implementing a custom proxy model, when WSortFilterProxyModel is 25 * not adequate. It implements data access and manipulation using the 26 * a virtual mapping method (mapToSource()) to access and manipulate 27 * the underlying sourceModel(). 28 * 29 * \ingroup modelview 30 */ 31 class WT_API WAbstractProxyModel : public WAbstractItemModel 32 { 33 public: 34 /*! \brief Constructor. 35 */ 36 WAbstractProxyModel(); 37 38 /*! \brief Maps a source model index to the proxy model. 39 * 40 * This method returns a model index in the proxy model that 41 * corresponds to the model index \p sourceIndex in the source 42 * model. This method must only be implemented for source model 43 * indexes that are mapped and thus are the result of mapToSource(). 44 * 45 * \sa mapToSource() 46 */ 47 virtual WModelIndex mapFromSource(const WModelIndex& sourceIndex) const = 0; 48 49 /*! \brief Maps a proxy model index to the source model. 50 * 51 * This method returns a model index in the source model that 52 * corresponds to the proxy model index \p proxyIndex. 53 * 54 * \sa mapFromSource() 55 */ 56 virtual WModelIndex mapToSource(const WModelIndex& proxyIndex) const = 0; 57 58 /*! \brief Sets the source model. 59 * 60 * The source model provides the actual data for the proxy 61 * model. 62 * 63 * Ownership of the source model is <i>not</i> transferred. 64 * 65 * Note that the source model's signals are not forwarded to 66 * the proxy model by default, but some specializations, 67 * like WBatchEditProxyModel and WSortFilterProxyModel do. 68 * If you want to reimplement data() with no changes to row 69 * or column indices, consider the use of WIdentityProxyModel. 70 */ 71 virtual void setSourceModel(const std::shared_ptr<WAbstractItemModel>& 72 sourceModel); 73 74 /*! \brief Returns the source model. 75 * 76 * \sa setSourceModel() 77 */ sourceModel()78 std::shared_ptr<WAbstractItemModel> sourceModel() const { 79 return sourceModel_; 80 } 81 82 using WAbstractItemModel::setData; 83 using WAbstractItemModel::data; 84 using WAbstractItemModel::setHeaderData; 85 86 /*! \brief Returns the data at a specific model index. 87 * 88 * The default proxy implementation translates the index to the 89 * source model, and calls sourceModel()->data() with this index. 90 */ 91 virtual cpp17::any data(const WModelIndex& index, 92 ItemDataRole role = ItemDataRole::Display) const override; 93 94 /*! \brief Returns the row or column header data. 95 * 96 * The default proxy implementation constructs a dummy 97 * WModelIndex with the row set to 0 and column set to \c section 98 * if the orientation is Wt::Orientation::Horizontal, or with the 99 * row set to \c section and the column set to 0 if the orientation 100 * is Wt::Orientation::Vertical. 101 * 102 * The resulting section that is forwarded to sourceModel()->headerData() 103 * depends on how the WModelIndex is transformed with mapToSource(). 104 */ 105 virtual cpp17::any headerData(int section, 106 Orientation orientation = Orientation::Horizontal, 107 ItemDataRole role = ItemDataRole::Display) 108 const override; 109 110 /*! \brief Sets the data at the given model index. 111 * 112 * The default proxy implementation calls sourceModel()->setData(mapToSource(index), value, role) 113 */ 114 virtual bool setData(const WModelIndex& index, const cpp17::any& value, 115 ItemDataRole role = ItemDataRole::Edit) override; 116 117 /*! \brief Sets the data at the given model index. 118 * 119 * The default proxy implementation calls sourceModel()->setData(mapToSource(index), values) 120 */ 121 virtual bool setItemData(const WModelIndex& index, const DataMap& values) 122 override; 123 124 /*! \brief Returns the flags for an item. 125 * 126 * The default proxy implementation calls sourceModel()->flags(mapToSource(index)) 127 */ 128 virtual WFlags<ItemFlag> flags(const WModelIndex& index) const override; 129 130 /*! \brief Returns the flags for a header. 131 * 132 * The default proxy implementation constructs a dummy 133 * WModelIndex with the row set to 0 and column set to \c section 134 * if the orientation is Wt::Orientation::Horizontal, or with the 135 * row set to \c section and the column set to 0 if the orientation 136 * is Wt::Orientation::Vertical. 137 * 138 * The resulting section that is forwarded to sourceModel()->headerFlags() 139 * depends on how the WModelIndex is transformed with mapToSource(). 140 */ 141 virtual WFlags<HeaderFlag> headerFlags 142 (int section, Orientation orientation = Orientation::Horizontal) 143 const override; 144 145 /*! \brief Inserts one or more columns. 146 * 147 * The default proxy implementation calls sourceModel()->insertColumns(column, count, parent) 148 */ 149 virtual bool insertColumns(int column, int count, 150 const WModelIndex& parent = WModelIndex()) 151 override; 152 153 /*! \brief Removes columns. 154 * 155 * The default proxy implementation calls sourceModel()->removeColumns(column, count, parent) 156 */ 157 virtual bool removeColumns(int column, int count, 158 const WModelIndex& parent = WModelIndex()) 159 override; 160 161 /*! \brief Returns a mime-type for dragging a set of indexes. 162 * 163 * The default proxy implementation calls sourceModel()->mimeType() 164 */ 165 virtual std::string mimeType() const override; 166 167 /*! \brief Returns a list of mime-types that could be accepted for a 168 * drop event. 169 * 170 * The default proxy implementation calls sourceModel()->acceptDropMimeTypes() 171 */ 172 virtual std::vector<std::string> acceptDropMimeTypes() const override; 173 174 /*! \brief Handles a drop event. 175 * 176 * The default proxy implementation maps the given row and parent 177 * to the row and parent in the source model, and forwards the 178 * dropEvent call to the source model. 179 */ 180 virtual void dropEvent(const WDropEvent& e, DropAction action, 181 int row, int column, const WModelIndex& parent) 182 override; 183 184 /*! \brief Converts a model index to a raw pointer that remains valid 185 * while the model's layout is changed. 186 * 187 * The default proxy implementation calls sourceModel()->toRawIndex(mapToSource(index)) 188 */ 189 virtual void *toRawIndex(const WModelIndex& index) const override; 190 191 /*! \brief Converts a raw pointer to a model index. 192 * 193 * The default proxy implementation calls mapFromSource(sourceModel()->fromRawIndex(rawIndex)) 194 */ 195 virtual WModelIndex fromRawIndex(void *rawIndex) const override; 196 197 protected: 198 /*! \brief Create a source model index. 199 * 200 * This is a utility function that allows you to create indexes in 201 * the source model. In this way, you can reuse the internal pointers of 202 * the source model in proxy model indexes, and convert a proxy model index 203 * back to the source model index using this method. 204 */ 205 WModelIndex createSourceIndex(int row, int column, void *ptr) const; 206 207 /*! \brief A base class for an item modeling a source index parent. 208 * 209 * Many mplementations of a proxy model will need to maintain a data 210 * structure per source model indexes, where they relate source rows or 211 * columns to proxy rows or columns, per hierarchical parent. 212 * 213 * It may be convenient to start from this item class as a base 214 * class so that shiftModelIndexes() can be used to update this data 215 * structure when the source model adds or removes rows. 216 * 217 * You will typically use your derived class of this item as the 218 * internal pointer for proxy model indexes: a proxy model index 219 * will have an item as internal pointer whose sourceIndex_ corresponds 220 * to the source equivalent of the proxy model index parent. 221 * 222 * \sa createIndex() 223 */ 224 struct WT_API BaseItem { 225 /*! \brief The source model index. 226 * 227 * The source model index for this item. 228 */ 229 WModelIndex sourceIndex_; 230 231 /*! \brief Create a BaseItem. 232 */ BaseItemBaseItem233 BaseItem(const WModelIndex& sourceIndex) : sourceIndex_(sourceIndex) { } 234 virtual ~BaseItem(); 235 }; 236 237 /*! \brief A map for items. 238 * 239 * \sa BaseItem 240 */ 241 #ifndef WT_TARGET_JAVA 242 typedef std::map<WModelIndex, BaseItem *> ItemMap; 243 #else 244 typedef std::treemap<WModelIndex, BaseItem *> ItemMap; 245 #endif // WT_TARGET_JAVA 246 247 /*! \brief Utility methods to shift items in an item map. 248 * 249 * You can use this method to adjust an item map after the source 250 * model has inserted or removed rows. When removing rows (count < 0), 251 * items may possibly be removed and deleted. 252 */ 253 void startShiftModelIndexes(const WModelIndex& sourceParent, int start, int count, 254 ItemMap& items); 255 void endShiftModelIndexes(const WModelIndex& sourceParent, int start, int count, 256 ItemMap& items); 257 258 private: 259 std::vector<BaseItem *> itemsToShift_; 260 std::shared_ptr<WAbstractItemModel> sourceModel_; 261 }; 262 263 } 264 265 #endif // WABSTRACT_PROXY_MODEL_H_ 266