mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 00:20:05 +00:00 
			
		
		
		
	Refactoring generic tree model behavior
This commit is contained in:
		
							parent
							
								
									1ba60f0da1
								
							
						
					
					
						commit
						98f8bab79a
					
				
					 7 changed files with 348 additions and 236 deletions
				
			
		|  | @ -11,241 +11,30 @@ namespace model | |||
| static const std::string logPrefix_ = "scwx::qt::model::radar_product_model"; | ||||
| static const auto        logger_    = scwx::util::Logger::Create(logPrefix_); | ||||
| 
 | ||||
| class RadarProductModelItem | ||||
| { | ||||
| public: | ||||
|    explicit RadarProductModelItem(const std::vector<QVariant>& data, | ||||
|                                   RadarProductModelItem* parent = nullptr); | ||||
|    ~RadarProductModelItem(); | ||||
| 
 | ||||
|    void AppendChild(RadarProductModelItem* child); | ||||
| 
 | ||||
|    const RadarProductModelItem* child(int row) const; | ||||
|    int                          child_count() const; | ||||
|    int                          column_count() const; | ||||
|    QVariant                     data(int column) const; | ||||
|    int                          row() const; | ||||
|    const RadarProductModelItem* parent_item() const; | ||||
| 
 | ||||
| private: | ||||
|    std::vector<RadarProductModelItem*> childItems_; | ||||
|    std::vector<QVariant>               itemData_; | ||||
|    RadarProductModelItem*              parentItem_; | ||||
| }; | ||||
| 
 | ||||
| class RadarProductModelImpl | ||||
| { | ||||
| public: | ||||
|    explicit RadarProductModelImpl() : | ||||
|        rootItem_ {std::make_shared<RadarProductModelItem>( | ||||
|        rootItem_ {std::make_shared<TreeItem>( | ||||
|           std::vector<QVariant> {QObject::tr("Name"), QObject::tr("Info")})} | ||||
|    { | ||||
|       rootItem_->AppendChild(new RadarProductModelItem( | ||||
|       rootItem_->AppendChild(new TreeItem( | ||||
|          std::vector<QVariant> {QObject::tr("MyItem"), QObject::tr("Data")})); | ||||
|    } | ||||
|    ~RadarProductModelImpl() = default; | ||||
| 
 | ||||
|    std::shared_ptr<RadarProductModelItem> rootItem_; | ||||
|    std::shared_ptr<TreeItem> rootItem_; | ||||
| }; | ||||
| 
 | ||||
| RadarProductModel::RadarProductModel(QObject* parent) : | ||||
|     QAbstractTableModel(parent), p(std::make_unique<RadarProductModelImpl>()) | ||||
|     TreeModel(parent), p(std::make_unique<RadarProductModelImpl>()) | ||||
| { | ||||
| } | ||||
| RadarProductModel::~RadarProductModel() = default; | ||||
| 
 | ||||
| int RadarProductModel::rowCount(const QModelIndex& parent) const | ||||
| const std::shared_ptr<TreeItem> RadarProductModel::root_item() const | ||||
| { | ||||
|    const RadarProductModelItem* parentItem; | ||||
| 
 | ||||
|    if (parent.isValid()) | ||||
|    { | ||||
|       parentItem = static_cast<const RadarProductModelItem*>( | ||||
|          parent.constInternalPointer()); | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       parentItem = p->rootItem_.get(); | ||||
|    } | ||||
| 
 | ||||
|    return parentItem->child_count(); | ||||
| } | ||||
| 
 | ||||
| int RadarProductModel::columnCount(const QModelIndex& parent) const | ||||
| { | ||||
|    const RadarProductModelItem* parentItem; | ||||
| 
 | ||||
|    if (parent.isValid()) | ||||
|    { | ||||
|       parentItem = static_cast<const RadarProductModelItem*>( | ||||
|          parent.constInternalPointer()); | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       parentItem = p->rootItem_.get(); | ||||
|    } | ||||
| 
 | ||||
|    return parentItem->column_count(); | ||||
| } | ||||
| 
 | ||||
| QVariant RadarProductModel::data(const QModelIndex& index, int role) const | ||||
| { | ||||
|    if (!index.isValid() || role != Qt::DisplayRole) | ||||
|    { | ||||
|       return QVariant(); | ||||
|    } | ||||
| 
 | ||||
|    const RadarProductModelItem* item = | ||||
|       static_cast<const RadarProductModelItem*>(index.internalPointer()); | ||||
| 
 | ||||
|    return item->data(index.column()); | ||||
| } | ||||
| 
 | ||||
| Qt::ItemFlags RadarProductModel::flags(const QModelIndex& index) const | ||||
| { | ||||
|    Qt::ItemFlags flags; | ||||
| 
 | ||||
|    if (!index.isValid()) | ||||
|    { | ||||
|       flags = Qt::NoItemFlags; | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       flags = QAbstractItemModel::flags(index); | ||||
|    } | ||||
| 
 | ||||
|    return flags; | ||||
| } | ||||
| 
 | ||||
| QVariant RadarProductModel::headerData(int             section, | ||||
|                                        Qt::Orientation orientation, | ||||
|                                        int             role) const | ||||
| { | ||||
|    if (orientation == Qt::Horizontal && role == Qt::DisplayRole) | ||||
|    { | ||||
|       return p->rootItem_->data(section); | ||||
|    } | ||||
| 
 | ||||
|    return QVariant(); | ||||
| } | ||||
| 
 | ||||
| QModelIndex | ||||
| RadarProductModel::index(int row, int column, const QModelIndex& parent) const | ||||
| { | ||||
|    if (!hasIndex(row, column, parent)) | ||||
|    { | ||||
|       return QModelIndex(); | ||||
|    } | ||||
| 
 | ||||
|    const RadarProductModelItem* parentItem; | ||||
| 
 | ||||
|    if (!parent.isValid()) | ||||
|    { | ||||
|       parentItem = p->rootItem_.get(); | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       parentItem = static_cast<const RadarProductModelItem*>( | ||||
|          parent.constInternalPointer()); | ||||
|    } | ||||
| 
 | ||||
|    const RadarProductModelItem* childItem = parentItem->child(row); | ||||
|    if (childItem) | ||||
|    { | ||||
|       return createIndex(row, column, childItem); | ||||
|    } | ||||
| 
 | ||||
|    return QModelIndex(); | ||||
| } | ||||
| 
 | ||||
| QModelIndex RadarProductModel::parent(const QModelIndex& index) const | ||||
| { | ||||
|    if (!index.isValid()) | ||||
|    { | ||||
|       return QModelIndex(); | ||||
|    } | ||||
| 
 | ||||
|    const RadarProductModelItem* childItem = | ||||
|       static_cast<const RadarProductModelItem*>(index.constInternalPointer()); | ||||
|    const RadarProductModelItem* parentItem = childItem->parent_item(); | ||||
| 
 | ||||
|    if (parentItem == p->rootItem_.get()) | ||||
|    { | ||||
|       return QModelIndex(); | ||||
|    } | ||||
| 
 | ||||
|    return createIndex(parentItem->row(), 0, parentItem); | ||||
| } | ||||
| 
 | ||||
| RadarProductModelItem::RadarProductModelItem(const std::vector<QVariant>& data, | ||||
|                                              RadarProductModelItem* parent) : | ||||
|     childItems_ {}, itemData_ {data}, parentItem_ {parent} | ||||
| { | ||||
| } | ||||
| 
 | ||||
| RadarProductModelItem::~RadarProductModelItem() | ||||
| { | ||||
|    qDeleteAll(childItems_); | ||||
| } | ||||
| 
 | ||||
| void RadarProductModelItem::AppendChild(RadarProductModelItem* item) | ||||
| { | ||||
|    item->parentItem_ = this; | ||||
|    childItems_.push_back(item); | ||||
| } | ||||
| 
 | ||||
| const RadarProductModelItem* RadarProductModelItem::child(int row) const | ||||
| { | ||||
|    const RadarProductModelItem* item = nullptr; | ||||
| 
 | ||||
|    if (0 <= row && row < childItems_.size()) | ||||
|    { | ||||
|       item = childItems_[row]; | ||||
|    } | ||||
| 
 | ||||
|    return item; | ||||
| } | ||||
| 
 | ||||
| int RadarProductModelItem::child_count() const | ||||
| { | ||||
|    return static_cast<int>(childItems_.size()); | ||||
| } | ||||
| 
 | ||||
| int RadarProductModelItem::column_count() const | ||||
| { | ||||
|    return static_cast<int>(itemData_.size()); | ||||
| } | ||||
| 
 | ||||
| QVariant RadarProductModelItem::data(int column) const | ||||
| { | ||||
|    if (0 <= column && column < itemData_.size()) | ||||
|    { | ||||
|       return itemData_[column]; | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       return QVariant("Hello world"); | ||||
|    } | ||||
| } | ||||
| 
 | ||||
| int RadarProductModelItem::row() const | ||||
| { | ||||
|    int row = 0; | ||||
| 
 | ||||
|    if (parentItem_ != nullptr) | ||||
|    { | ||||
|       const auto& childItems = parentItem_->childItems_; | ||||
|       row = | ||||
|          std::distance(childItems.cbegin(), | ||||
|                        std::find(childItems.cbegin(), childItems.cend(), this)); | ||||
|    } | ||||
| 
 | ||||
|    return row; | ||||
| } | ||||
| 
 | ||||
| const RadarProductModelItem* RadarProductModelItem::parent_item() const | ||||
| { | ||||
|    return parentItem_; | ||||
|    return p->rootItem_; | ||||
| } | ||||
| 
 | ||||
| } // namespace model
 | ||||
|  |  | |||
|  | @ -1,8 +1,6 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <memory> | ||||
| 
 | ||||
| #include <QAbstractTableModel> | ||||
| #include <scwx/qt/model/tree_model.hpp> | ||||
| 
 | ||||
| namespace scwx | ||||
| { | ||||
|  | @ -13,25 +11,14 @@ namespace model | |||
| 
 | ||||
| class RadarProductModelImpl; | ||||
| 
 | ||||
| class RadarProductModel : public QAbstractTableModel | ||||
| class RadarProductModel : public TreeModel | ||||
| { | ||||
| public: | ||||
|    explicit RadarProductModel(QObject* parent = nullptr); | ||||
|    ~RadarProductModel(); | ||||
| 
 | ||||
|    int rowCount(const QModelIndex& parent = QModelIndex()) const override; | ||||
|    int columnCount(const QModelIndex& parent = QModelIndex()) const override; | ||||
| 
 | ||||
|    QVariant      data(const QModelIndex& index, | ||||
|                       int                role = Qt::DisplayRole) const override; | ||||
|    Qt::ItemFlags flags(const QModelIndex& index) const override; | ||||
|    QVariant      headerData(int             section, | ||||
|                             Qt::Orientation orientation, | ||||
|                             int             role = Qt::DisplayRole) const override; | ||||
|    QModelIndex   index(int                row, | ||||
|                        int                column, | ||||
|                        const QModelIndex& parent = QModelIndex()) const override; | ||||
|    QModelIndex   parent(const QModelIndex& index) const override; | ||||
| protected: | ||||
|    const std::shared_ptr<TreeItem> root_item() const override; | ||||
| 
 | ||||
| private: | ||||
|    std::unique_ptr<RadarProductModelImpl> p; | ||||
|  |  | |||
							
								
								
									
										98
									
								
								scwx-qt/source/scwx/qt/model/tree_item.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								scwx-qt/source/scwx/qt/model/tree_item.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,98 @@ | |||
| #include <scwx/qt/model/tree_item.hpp> | ||||
| 
 | ||||
| namespace scwx | ||||
| { | ||||
| namespace qt | ||||
| { | ||||
| namespace model | ||||
| { | ||||
| 
 | ||||
| static const std::string logPrefix_ = "scwx::qt::model::tree_item"; | ||||
| 
 | ||||
| class TreeItem::Impl | ||||
| { | ||||
| public: | ||||
|    explicit Impl(const std::vector<QVariant>& data, TreeItem* parent) : | ||||
|        childItems_ {}, itemData_ {data}, parentItem_ {parent} | ||||
|    { | ||||
|    } | ||||
|    ~Impl() { qDeleteAll(childItems_); } | ||||
| 
 | ||||
|    std::vector<TreeItem*> childItems_; | ||||
|    std::vector<QVariant>  itemData_; | ||||
|    TreeItem*              parentItem_; | ||||
| }; | ||||
| 
 | ||||
| TreeItem::TreeItem(const std::vector<QVariant>& data, TreeItem* parent) : | ||||
|     p {std::make_unique<Impl>(data, parent)} | ||||
| { | ||||
| } | ||||
| 
 | ||||
| TreeItem::~TreeItem() {} | ||||
| 
 | ||||
| TreeItem::TreeItem(TreeItem&&) noexcept            = default; | ||||
| TreeItem& TreeItem::operator=(TreeItem&&) noexcept = default; | ||||
| 
 | ||||
| void TreeItem::AppendChild(TreeItem* item) | ||||
| { | ||||
|    item->p->parentItem_ = this; | ||||
|    p->childItems_.push_back(item); | ||||
| } | ||||
| 
 | ||||
| const TreeItem* TreeItem::child(int row) const | ||||
| { | ||||
|    const TreeItem* item = nullptr; | ||||
| 
 | ||||
|    if (0 <= row && row < p->childItems_.size()) | ||||
|    { | ||||
|       item = p->childItems_[row]; | ||||
|    } | ||||
| 
 | ||||
|    return item; | ||||
| } | ||||
| 
 | ||||
| int TreeItem::child_count() const | ||||
| { | ||||
|    return static_cast<int>(p->childItems_.size()); | ||||
| } | ||||
| 
 | ||||
| int TreeItem::column_count() const | ||||
| { | ||||
|    return static_cast<int>(p->itemData_.size()); | ||||
| } | ||||
| 
 | ||||
| QVariant TreeItem::data(int column) const | ||||
| { | ||||
|    if (0 <= column && column < p->itemData_.size()) | ||||
|    { | ||||
|       return p->itemData_[column]; | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       return QVariant(); | ||||
|    } | ||||
| } | ||||
| 
 | ||||
| int TreeItem::row() const | ||||
| { | ||||
|    int row = 0; | ||||
| 
 | ||||
|    if (p->parentItem_ != nullptr) | ||||
|    { | ||||
|       const auto& childItems = p->parentItem_->p->childItems_; | ||||
|       row = | ||||
|          std::distance(childItems.cbegin(), | ||||
|                        std::find(childItems.cbegin(), childItems.cend(), this)); | ||||
|    } | ||||
| 
 | ||||
|    return row; | ||||
| } | ||||
| 
 | ||||
| const TreeItem* TreeItem::parent_item() const | ||||
| { | ||||
|    return p->parentItem_; | ||||
| } | ||||
| 
 | ||||
| } // namespace model
 | ||||
| } // namespace qt
 | ||||
| } // namespace scwx
 | ||||
							
								
								
									
										44
									
								
								scwx-qt/source/scwx/qt/model/tree_item.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								scwx-qt/source/scwx/qt/model/tree_item.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,44 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <vector> | ||||
| 
 | ||||
| #include <QVariant> | ||||
| 
 | ||||
| namespace scwx | ||||
| { | ||||
| namespace qt | ||||
| { | ||||
| namespace model | ||||
| { | ||||
| 
 | ||||
| class TreeItem | ||||
| { | ||||
| public: | ||||
|    explicit TreeItem(const std::vector<QVariant>& data, | ||||
|                      TreeItem*                    parent = nullptr); | ||||
|    virtual ~TreeItem(); | ||||
| 
 | ||||
|    TreeItem(const TreeItem&)            = delete; | ||||
|    TreeItem& operator=(const TreeItem&) = delete; | ||||
| 
 | ||||
|    TreeItem(TreeItem&&) noexcept; | ||||
|    TreeItem& operator=(TreeItem&&) noexcept; | ||||
| 
 | ||||
|    void AppendChild(TreeItem* child); | ||||
| 
 | ||||
|    const TreeItem* child(int row) const; | ||||
|    int             child_count() const; | ||||
|    int             column_count() const; | ||||
|    QVariant        data(int column) const; | ||||
|    int             row() const; | ||||
|    const TreeItem* parent_item() const; | ||||
| 
 | ||||
| private: | ||||
|    class Impl; | ||||
|    std::unique_ptr<Impl> p; | ||||
| }; | ||||
| 
 | ||||
| } // namespace model
 | ||||
| } // namespace qt
 | ||||
| } // namespace scwx
 | ||||
							
								
								
									
										145
									
								
								scwx-qt/source/scwx/qt/model/tree_model.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								scwx-qt/source/scwx/qt/model/tree_model.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,145 @@ | |||
| #include <scwx/qt/model/tree_model.hpp> | ||||
| 
 | ||||
| namespace scwx | ||||
| { | ||||
| namespace qt | ||||
| { | ||||
| namespace model | ||||
| { | ||||
| 
 | ||||
| static const std::string logPrefix_ = "scwx::qt::model::tree_model"; | ||||
| 
 | ||||
| class TreeModelImpl | ||||
| { | ||||
| public: | ||||
|    explicit TreeModelImpl() = default; | ||||
|    ~TreeModelImpl()         = default; | ||||
| }; | ||||
| 
 | ||||
| TreeModel::TreeModel(QObject* parent) : | ||||
|     QAbstractTableModel(parent), p(std::make_unique<TreeModelImpl>()) | ||||
| { | ||||
| } | ||||
| TreeModel::~TreeModel() = default; | ||||
| 
 | ||||
| int TreeModel::rowCount(const QModelIndex& parent) const | ||||
| { | ||||
|    const TreeItem* parentItem; | ||||
| 
 | ||||
|    if (parent.isValid()) | ||||
|    { | ||||
|       parentItem = static_cast<const TreeItem*>(parent.constInternalPointer()); | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       parentItem = root_item().get(); | ||||
|    } | ||||
| 
 | ||||
|    return parentItem->child_count(); | ||||
| } | ||||
| 
 | ||||
| int TreeModel::columnCount(const QModelIndex& parent) const | ||||
| { | ||||
|    const TreeItem* parentItem; | ||||
| 
 | ||||
|    if (parent.isValid()) | ||||
|    { | ||||
|       parentItem = static_cast<const TreeItem*>(parent.constInternalPointer()); | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       parentItem = root_item().get(); | ||||
|    } | ||||
| 
 | ||||
|    return parentItem->column_count(); | ||||
| } | ||||
| 
 | ||||
| QVariant TreeModel::data(const QModelIndex& index, int role) const | ||||
| { | ||||
|    if (!index.isValid() || role != Qt::DisplayRole) | ||||
|    { | ||||
|       return QVariant(); | ||||
|    } | ||||
| 
 | ||||
|    const TreeItem* item = static_cast<const TreeItem*>(index.internalPointer()); | ||||
| 
 | ||||
|    return item->data(index.column()); | ||||
| } | ||||
| 
 | ||||
| Qt::ItemFlags TreeModel::flags(const QModelIndex& index) const | ||||
| { | ||||
|    Qt::ItemFlags flags; | ||||
| 
 | ||||
|    if (!index.isValid()) | ||||
|    { | ||||
|       flags = Qt::NoItemFlags; | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       flags = QAbstractItemModel::flags(index); | ||||
|    } | ||||
| 
 | ||||
|    return flags; | ||||
| } | ||||
| 
 | ||||
| QVariant | ||||
| TreeModel::headerData(int section, Qt::Orientation orientation, int role) const | ||||
| { | ||||
|    if (orientation == Qt::Horizontal && role == Qt::DisplayRole) | ||||
|    { | ||||
|       return root_item()->data(section); | ||||
|    } | ||||
| 
 | ||||
|    return QVariant(); | ||||
| } | ||||
| 
 | ||||
| QModelIndex | ||||
| TreeModel::index(int row, int column, const QModelIndex& parent) const | ||||
| { | ||||
|    if (!hasIndex(row, column, parent)) | ||||
|    { | ||||
|       return QModelIndex(); | ||||
|    } | ||||
| 
 | ||||
|    const TreeItem* parentItem; | ||||
| 
 | ||||
|    if (!parent.isValid()) | ||||
|    { | ||||
|       parentItem = root_item().get(); | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       parentItem = static_cast<const TreeItem*>(parent.constInternalPointer()); | ||||
|    } | ||||
| 
 | ||||
|    const TreeItem* childItem = parentItem->child(row); | ||||
|    if (childItem) | ||||
|    { | ||||
|       return createIndex(row, column, childItem); | ||||
|    } | ||||
| 
 | ||||
|    return QModelIndex(); | ||||
| } | ||||
| 
 | ||||
| QModelIndex TreeModel::parent(const QModelIndex& index) const | ||||
| { | ||||
|    if (!index.isValid()) | ||||
|    { | ||||
|       return QModelIndex(); | ||||
|    } | ||||
| 
 | ||||
|    const TreeItem* childItem = | ||||
|       static_cast<const TreeItem*>(index.constInternalPointer()); | ||||
|    const TreeItem* parentItem = childItem->parent_item(); | ||||
| 
 | ||||
|    if (parentItem == root_item().get()) | ||||
|    { | ||||
|       return QModelIndex(); | ||||
|    } | ||||
| 
 | ||||
|    return createIndex(parentItem->row(), 0, parentItem); | ||||
| } | ||||
| 
 | ||||
| } // namespace model
 | ||||
| } // namespace qt
 | ||||
| } // namespace scwx
 | ||||
							
								
								
									
										45
									
								
								scwx-qt/source/scwx/qt/model/tree_model.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								scwx-qt/source/scwx/qt/model/tree_model.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,45 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <scwx/qt/model/tree_item.hpp> | ||||
| 
 | ||||
| #include <QAbstractTableModel> | ||||
| 
 | ||||
| namespace scwx | ||||
| { | ||||
| namespace qt | ||||
| { | ||||
| namespace model | ||||
| { | ||||
| 
 | ||||
| class TreeModelImpl; | ||||
| 
 | ||||
| class TreeModel : public QAbstractTableModel | ||||
| { | ||||
| public: | ||||
|    explicit TreeModel(QObject* parent = nullptr); | ||||
|    virtual ~TreeModel(); | ||||
| 
 | ||||
|    int rowCount(const QModelIndex& parent = QModelIndex()) const override; | ||||
|    int columnCount(const QModelIndex& parent = QModelIndex()) const override; | ||||
| 
 | ||||
|    QVariant      data(const QModelIndex& index, | ||||
|                       int                role = Qt::DisplayRole) const override; | ||||
|    Qt::ItemFlags flags(const QModelIndex& index) const override; | ||||
|    QVariant      headerData(int             section, | ||||
|                             Qt::Orientation orientation, | ||||
|                             int             role = Qt::DisplayRole) const override; | ||||
|    QModelIndex   index(int                row, | ||||
|                        int                column, | ||||
|                        const QModelIndex& parent = QModelIndex()) const override; | ||||
|    QModelIndex   parent(const QModelIndex& index) const override; | ||||
| 
 | ||||
| protected: | ||||
|    virtual const std::shared_ptr<TreeItem> root_item() const = 0; | ||||
| 
 | ||||
| private: | ||||
|    std::unique_ptr<TreeModelImpl> p; | ||||
| }; | ||||
| 
 | ||||
| } // namespace model
 | ||||
| } // namespace qt
 | ||||
| } // namespace scwx
 | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat