diff --git a/src/blackgui/models/listmodelbase.cpp b/src/blackgui/models/listmodelbase.cpp index ee8f91f74..54040c070 100644 --- a/src/blackgui/models/listmodelbase.cpp +++ b/src/blackgui/models/listmodelbase.cpp @@ -10,25 +10,16 @@ // Drag and drop docu: // http://doc.qt.io/qt-5/model-view-programming.html#using-drag-and-drop-with-item-views -#include "blackgui/models/columnformatters.h" #include "blackgui/models/listmodelbase.h" #include "blackgui/models/allmodelcontainers.h" #include "blackgui/guiutility.h" -#include "blackmisc/compare.h" -#include "blackmisc/predicates.h" -#include "blackmisc/propertyindex.h" -#include "blackmisc/fileutils.h" -#include "blackmisc/sequence.h" #include "blackmisc/variant.h" -#include "blackmisc/verify.h" #include "blackmisc/worker.h" #include #include #include #include -#include -#include using namespace BlackMisc; using namespace BlackMisc::Aviation; @@ -37,172 +28,6 @@ namespace BlackGui { namespace Models { - int CListModelBaseNonTemplate::columnCount(const QModelIndex &modelIndex) const - { - Q_UNUSED(modelIndex); - int c = m_columns.size(); - return c; - } - - QVariant CListModelBaseNonTemplate::headerData(int section, Qt::Orientation orientation, int role) const - { - if (orientation != Qt::Horizontal) { return QVariant(); } - const bool handled = (role == Qt::DisplayRole || role == Qt::ToolTipRole || role == Qt::InitialSortOrderRole); - if (!handled) { return QVariant(); } - if (section < 0 || section >= m_columns.size()) { return QVariant(); } - - if (role == Qt::DisplayRole) - { - const QString header = m_columns.at(section).getColumnName(false); - return QVariant(header); - } - if (role == Qt::ToolTipRole) - { - const QString header = m_columns.at(section).getColumnToolTip(false); - return header.isEmpty() ? QVariant() : QVariant(header); - } - return QVariant(); - } - - QModelIndex CListModelBaseNonTemplate::index(int row, int column, const QModelIndex &parent) const - { - Q_UNUSED(parent); - return QStandardItemModel::createIndex(row, column); - } - - QModelIndex CListModelBaseNonTemplate::parent(const QModelIndex &child) const - { - Q_UNUSED(child); - return QModelIndex(); - } - - CPropertyIndex CListModelBaseNonTemplate::columnToPropertyIndex(int column) const - { - return m_columns.columnToPropertyIndex(column); - } - - int CListModelBaseNonTemplate::propertyIndexToColumn(const CPropertyIndex &propertyIndex) const - { - return m_columns.propertyIndexToColumn(propertyIndex); - } - - CPropertyIndex CListModelBaseNonTemplate::modelIndexToPropertyIndex(const QModelIndex &index) const - { - return this->columnToPropertyIndex(index.column()); - } - - void CListModelBaseNonTemplate::sortByPropertyIndex(const CPropertyIndex &propertyIndex, Qt::SortOrder order) - { - const int column = this->propertyIndexToColumn(propertyIndex); - this->sort(column, order); - } - - bool CListModelBaseNonTemplate::setSortColumnByPropertyIndex(const CPropertyIndex &propertyIndex) - { - const int column = m_columns.propertyIndexToColumn(propertyIndex); - if (m_sortColumn == column) { return false; } // not changed - m_sortColumn = column; - return true; // changed - } - - bool CListModelBaseNonTemplate::setSorting(const CPropertyIndex &propertyIndex, Qt::SortOrder order) - { - const bool changedColumn = this->setSortColumnByPropertyIndex(propertyIndex); - const bool changedOrder = (m_sortOrder == order); - m_sortOrder = order; - return changedColumn || changedOrder; - } - - bool CListModelBaseNonTemplate::hasValidSortColumn() const - { - - if (!(m_sortColumn >= 0 && m_sortColumn < m_columns.size())) { return false; } - return m_columns.isSortable(m_sortColumn); - } - - Qt::ItemFlags CListModelBaseNonTemplate::flags(const QModelIndex &index) const - { - Qt::ItemFlags f = QStandardItemModel::flags(index); - if (!index.isValid()) { return f; } - const bool editable = m_columns.isEditable(index); - f = editable ? (f | Qt::ItemIsEditable) : (f & ~Qt::ItemIsEditable); - - // flags from formatter - const CDefaultFormatter *formatter = m_columns.getFormatter(index); - if (formatter) { f = formatter->flags(f, editable); } - - // drag and drop - f = f | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; - return f; - } - - const QString &CListModelBaseNonTemplate::getTranslationContext() const - { - return m_columns.getTranslationContext(); - } - - Qt::DropActions CListModelBaseNonTemplate::supportedDragActions() const - { - return isOrderable() ? Qt::CopyAction | Qt::MoveAction : Qt::CopyAction; - } - - Qt::DropActions CListModelBaseNonTemplate::supportedDropActions() const - { - return m_dropActions; - } - - QStringList CListModelBaseNonTemplate::mimeTypes() const - { - static const QStringList mimes({ "application/swift.container.json" }); - return mimes; - } - - void CListModelBaseNonTemplate::markDestroyed() - { - m_modelDestroyed = true; - } - - bool CListModelBaseNonTemplate::isModelDestroyed() - { - return m_modelDestroyed; - } - - void CListModelBaseNonTemplate::clearHighlighting() - { - // can be overridden to delete highlighting - } - - bool CListModelBaseNonTemplate::hasHighlightedRows() const - { - return false; - // can be overridden to enable highlighting based operations - } - - void CListModelBaseNonTemplate::emitDataChanged(int startRowIndex, int endRowIndex) - { - BLACK_VERIFY_X(startRowIndex <= endRowIndex, Q_FUNC_INFO, "check rows"); - BLACK_VERIFY_X(startRowIndex >= 0 && endRowIndex >= 0, Q_FUNC_INFO, "check rows"); - - const int columns = columnCount(); - const int rows = rowCount(); - if (columns < 1) { return; } - if (startRowIndex < 0) { startRowIndex = 0; } - if (endRowIndex >= rows) { endRowIndex = rows - 1; } - const QModelIndex topLeft(createIndex(startRowIndex, 0)); - const QModelIndex bottomRight(createIndex(endRowIndex, columns - 1)); - emit this->dataChanged(topLeft, bottomRight); - } - - CListModelBaseNonTemplate::CListModelBaseNonTemplate(const QString &translationContext, QObject *parent) - : QStandardItemModel(parent), m_columns(translationContext), m_sortColumn(-1), m_sortOrder(Qt::AscendingOrder) - { - // non unique default name, set translation context as default - this->setObjectName(translationContext); - - // connect - connect(this, &CListModelBaseNonTemplate::dataChanged, this, &CListModelBaseNonTemplate::onDataChanged); - } - template CListModelBase::CListModelBase(const QString &translationContext, QObject *parent) : CListModelBaseNonTemplate(translationContext, parent) @@ -770,33 +595,5 @@ namespace BlackGui return false; } - // see here for the reason of thess forward instantiations - // https://isocpp.org/wiki/faq/templates#separate-template-fn-defn-from-decl - template class CListModelBase; - template class CListModelBase; - template class CListModelBase; - template class CListModelBase; - template class CListModelBase; - template class CListModelBase; - template class CListModelBase; - template class CListModelBase; - template class CListModelBase; - template class CListModelBase; - template class CListModelBase; - template class CListModelBase; - template class CListModelBase; - template class CListModelBase; - template class CListModelBase; - template class CListModelBase; - template class CListModelBase; - template class CListModelBase; - template class CListModelBase; - template class CListModelBase; - template class CListModelBase; - template class CListModelBase; - template class CListModelBase; - template class CListModelBase; - template class CListModelBase; - } // namespace } // namespace diff --git a/src/blackgui/models/listmodelbase.h b/src/blackgui/models/listmodelbase.h index 69e815b2c..233d3a982 100644 --- a/src/blackgui/models/listmodelbase.h +++ b/src/blackgui/models/listmodelbase.h @@ -12,27 +12,23 @@ #ifndef BLACKGUI_LISTMODELBASE_H #define BLACKGUI_LISTMODELBASE_H -#include "blackgui/models/columns.h" +#include "blackgui/models/listmodelbasenontemplate.h" +//#include "blackgui/models/columns.h" #include "blackgui/models/modelfilter.h" #include "blackgui/models/selectionmodel.h" -#include "blackgui/dropbase.h" -#include "blackgui/blackguiexport.h" -#include "blackmisc/digestsignal.h" -#include "blackmisc/variant.h" +//#include "blackgui/dropbase.h" +//#include "blackgui/blackguiexport.h" +//#include "blackmisc/digestsignal.h" +//#include "blackmisc/variant.h" #include #include #include #include -#include -#include #include -#include #include #include -#include #include -#include class QMimeData; class QModelIndex; @@ -42,141 +38,6 @@ namespace BlackGui { namespace Models { - //! Non templated base class, allows Q_OBJECT and signals to be used - class BLACKGUI_EXPORT CListModelBaseNonTemplate : - public QStandardItemModel, - public CDropBase - { - Q_OBJECT - - public: - //! Number of elements when to use asynchronous updates - static constexpr int asyncThreshold = 50; - - //! Destructor - virtual ~CListModelBaseNonTemplate() override {} - - //! \name Functions from QStandardItemModel - //! @{ - virtual int columnCount(const QModelIndex &modelIndex = QModelIndex()) const final override; - virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const final override; - virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const final override; - virtual QModelIndex parent(const QModelIndex &child) const final override; - virtual Qt::ItemFlags flags(const QModelIndex &index) const final override; - virtual Qt::DropActions supportedDragActions() const final override; - virtual Qt::DropActions supportedDropActions() const final override; - virtual QStringList mimeTypes() const final override; - //! @} - - //! Column to property index - virtual BlackMisc::CPropertyIndex columnToPropertyIndex(int column) const; - - //! Property index to column number - virtual int propertyIndexToColumn(const BlackMisc::CPropertyIndex &propertyIndex) const; - - //! Index to property index - virtual BlackMisc::CPropertyIndex modelIndexToPropertyIndex(const QModelIndex &index) const; - - //! Set sort column - virtual void setSortColumn(int column) { m_sortColumn = column; } - - //! Sort by index - void sortByPropertyIndex(const BlackMisc::CPropertyIndex &propertyIndex, Qt::SortOrder order = Qt::AscendingOrder); - - //! Set column for sorting - //! \param propertyIndex index of column to be sorted - virtual bool setSortColumnByPropertyIndex(const BlackMisc::CPropertyIndex &propertyIndex); - - //! Sorting - virtual bool setSorting(const BlackMisc::CPropertyIndex &propertyIndex, Qt::SortOrder order = Qt::AscendingOrder); - - //! Get sort column property index - virtual int getSortColumn() const { return m_sortColumn; } - - //! Has valid sort column? - virtual bool hasValidSortColumn() const; - - //! Get sort order - virtual Qt::SortOrder getSortOrder() const { return m_sortOrder; } - - //! Translation context - virtual const QString &getTranslationContext() const; - - //! Orderable, normally use a container BlackMisc::IOrderableList - virtual bool isOrderable() const = 0; - - //! Mark as about to be destroyed, normally marked from view - void markDestroyed(); - - //! Model about to be destroyed? - bool isModelDestroyed(); - - //! Remove all highlighting - virtual void clearHighlighting(); - - //! Has highlighted rows? - virtual bool hasHighlightedRows() const; - - //! Drop actions - void setDropActions(Qt::DropActions dropActions) { m_dropActions = dropActions; } - - //! Send signal that data have been changed. - //! \note Meant for scenarios where the container is directly updated and a subsequent signal is required - void emitDataChanged(int startRowIndex, int endRowIndex); - - //! Convert to JSON - virtual QJsonObject toJson(bool selectedOnly = false) const = 0; - - //! Convert to JSON string - virtual QString toJsonString(QJsonDocument::JsonFormat format = QJsonDocument::Indented, bool selectedOnly = false) const = 0; - - //! The columns - const CColumns &getColumns() const { return m_columns; } - - signals: - //! Asynchronous update finished - void asyncUpdateFinished(); - - //! Data changed - //! \remark passing back selected objects so they can be reselected - //! \remark condsider modelDataChangedDigest for performance reasons - void modelDataChanged(int count, bool withFilter); - - //! Data changed, digest version - void modelDataChangedDigest(int count, bool withFilter); - - //! Model has been changed - //! Triggered with each change, for performance consider using changedDigest - void changed(); - - //! Model has been changed, digest signal - void changedDigest(); - - //! Template free information, that object changed - void objectChanged(const BlackMisc::CVariant &object, const BlackMisc::CPropertyIndex &changedIndex); - - protected: - //! Feedback when QStandardItemModel::dataChanged was called - virtual void onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles) = 0; - - //! Digest signal - virtual void onChangedDigest() = 0; - - //! Constructor - //! \param translationContext I18N context - //! \param parent - CListModelBaseNonTemplate(const QString &translationContext, QObject *parent = nullptr); - - CColumns m_columns; //!< columns metadata - int m_sortColumn; //!< currently sorted column - bool m_modelDestroyed = false; //!< model is about to be destroyed - Qt::SortOrder m_sortOrder; //!< sort order (asc/desc) - Qt::DropActions m_dropActions = Qt::IgnoreAction; //!< drop actions - - private: - BlackMisc::CDigestSignal m_dsModelsChanged { this, &CListModelBaseNonTemplate::changed, &CListModelBaseNonTemplate::onChangedDigest, 500, 10 }; - }; - //! List model template class CListModelBase : public CListModelBaseNonTemplate { diff --git a/src/blackgui/models/listmodelbaseaviation.cpp b/src/blackgui/models/listmodelbaseaviation.cpp new file mode 100644 index 000000000..4a0016fa6 --- /dev/null +++ b/src/blackgui/models/listmodelbaseaviation.cpp @@ -0,0 +1,27 @@ +/* Copyright (C) 2018 + * swift project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +#include "listmodelbase.cpp" + +namespace BlackGui +{ + namespace Models + { + // see here for the reason of thess forward instantiations + // https://isocpp.org/wiki/faq/templates#separate-template-fn-defn-from-decl + template class CListModelBase; + template class CListModelBase; + template class CListModelBase; + template class CListModelBase; + template class CListModelBase; + template class CListModelBase; + template class CListModelBase; + template class CListModelBase; + } // namespace +} // namespace diff --git a/src/blackgui/models/listmodelbasemisc.cpp b/src/blackgui/models/listmodelbasemisc.cpp new file mode 100644 index 000000000..50089ffed --- /dev/null +++ b/src/blackgui/models/listmodelbasemisc.cpp @@ -0,0 +1,25 @@ +/* Copyright (C) 2018 + * swift project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +#include "listmodelbase.cpp" + +namespace BlackGui +{ + namespace Models + { + // see here for the reason of thess forward instantiations + // https://isocpp.org/wiki/faq/templates#separate-template-fn-defn-from-decl + template class CListModelBase; + template class CListModelBase; + template class CListModelBase; + template class CListModelBase; + template class CListModelBase; + + } // namespace +} // namespace diff --git a/src/blackgui/models/listmodelbasenetwork.cpp b/src/blackgui/models/listmodelbasenetwork.cpp new file mode 100644 index 000000000..34ec3ceb8 --- /dev/null +++ b/src/blackgui/models/listmodelbasenetwork.cpp @@ -0,0 +1,24 @@ +/* Copyright (C) 2018 + * swift project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +#include "listmodelbase.cpp" + +namespace BlackGui +{ + namespace Models + { + // see here for the reason of thess forward instantiations + // https://isocpp.org/wiki/faq/templates#separate-template-fn-defn-from-decl + template class CListModelBase; + template class CListModelBase; + template class CListModelBase; + template class CListModelBase; + + } // namespace +} // namespace diff --git a/src/blackgui/models/listmodelbasenontemplate.cpp b/src/blackgui/models/listmodelbasenontemplate.cpp new file mode 100644 index 000000000..5cde2034b --- /dev/null +++ b/src/blackgui/models/listmodelbasenontemplate.cpp @@ -0,0 +1,206 @@ +/* Copyright (C) 2018 + * swift project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +// Drag and drop docu: +// http://doc.qt.io/qt-5/model-view-programming.html#using-drag-and-drop-with-item-views + +//#include "blackgui/models/columnformatters.h" +#include "blackgui/models/listmodelbasenontemplate.h" +//#include "blackgui/models/allmodelcontainers.h" +//#include "blackgui/guiutility.h" +//#include "blackmisc/compare.h" +//#include "blackmisc/predicates.h" +//#include "blackmisc/propertyindex.h" +//#include "blackmisc/fileutils.h" +//#include "blackmisc/sequence.h" +//#include "blackmisc/variant.h" +#include "blackmisc/verify.h" +//#include "blackmisc/worker.h" + +//#include +//#include +//#include +//#include +//#include +//#include + +using namespace BlackMisc; + +namespace BlackGui +{ + namespace Models + { + int CListModelBaseNonTemplate::columnCount(const QModelIndex &modelIndex) const + { + Q_UNUSED(modelIndex); + int c = m_columns.size(); + return c; + } + + QVariant CListModelBaseNonTemplate::headerData(int section, Qt::Orientation orientation, int role) const + { + if (orientation != Qt::Horizontal) { return QVariant(); } + const bool handled = (role == Qt::DisplayRole || role == Qt::ToolTipRole || role == Qt::InitialSortOrderRole); + if (!handled) { return QVariant(); } + if (section < 0 || section >= m_columns.size()) { return QVariant(); } + + if (role == Qt::DisplayRole) + { + const QString header = m_columns.at(section).getColumnName(false); + return QVariant(header); + } + if (role == Qt::ToolTipRole) + { + const QString header = m_columns.at(section).getColumnToolTip(false); + return header.isEmpty() ? QVariant() : QVariant(header); + } + return QVariant(); + } + + QModelIndex CListModelBaseNonTemplate::index(int row, int column, const QModelIndex &parent) const + { + Q_UNUSED(parent); + return QStandardItemModel::createIndex(row, column); + } + + QModelIndex CListModelBaseNonTemplate::parent(const QModelIndex &child) const + { + Q_UNUSED(child); + return QModelIndex(); + } + + CPropertyIndex CListModelBaseNonTemplate::columnToPropertyIndex(int column) const + { + return m_columns.columnToPropertyIndex(column); + } + + int CListModelBaseNonTemplate::propertyIndexToColumn(const CPropertyIndex &propertyIndex) const + { + return m_columns.propertyIndexToColumn(propertyIndex); + } + + CPropertyIndex CListModelBaseNonTemplate::modelIndexToPropertyIndex(const QModelIndex &index) const + { + return this->columnToPropertyIndex(index.column()); + } + + void CListModelBaseNonTemplate::sortByPropertyIndex(const CPropertyIndex &propertyIndex, Qt::SortOrder order) + { + const int column = this->propertyIndexToColumn(propertyIndex); + this->sort(column, order); + } + + bool CListModelBaseNonTemplate::setSortColumnByPropertyIndex(const CPropertyIndex &propertyIndex) + { + const int column = m_columns.propertyIndexToColumn(propertyIndex); + if (m_sortColumn == column) { return false; } // not changed + m_sortColumn = column; + return true; // changed + } + + bool CListModelBaseNonTemplate::setSorting(const CPropertyIndex &propertyIndex, Qt::SortOrder order) + { + const bool changedColumn = this->setSortColumnByPropertyIndex(propertyIndex); + const bool changedOrder = (m_sortOrder == order); + m_sortOrder = order; + return changedColumn || changedOrder; + } + + bool CListModelBaseNonTemplate::hasValidSortColumn() const + { + + if (!(m_sortColumn >= 0 && m_sortColumn < m_columns.size())) { return false; } + return m_columns.isSortable(m_sortColumn); + } + + Qt::ItemFlags CListModelBaseNonTemplate::flags(const QModelIndex &index) const + { + Qt::ItemFlags f = QStandardItemModel::flags(index); + if (!index.isValid()) { return f; } + const bool editable = m_columns.isEditable(index); + f = editable ? (f | Qt::ItemIsEditable) : (f & ~Qt::ItemIsEditable); + + // flags from formatter + const CDefaultFormatter *formatter = m_columns.getFormatter(index); + if (formatter) { f = formatter->flags(f, editable); } + + // drag and drop + f = f | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; + return f; + } + + const QString &CListModelBaseNonTemplate::getTranslationContext() const + { + return m_columns.getTranslationContext(); + } + + Qt::DropActions CListModelBaseNonTemplate::supportedDragActions() const + { + return isOrderable() ? Qt::CopyAction | Qt::MoveAction : Qt::CopyAction; + } + + Qt::DropActions CListModelBaseNonTemplate::supportedDropActions() const + { + return m_dropActions; + } + + QStringList CListModelBaseNonTemplate::mimeTypes() const + { + static const QStringList mimes({ "application/swift.container.json" }); + return mimes; + } + + void CListModelBaseNonTemplate::markDestroyed() + { + m_modelDestroyed = true; + } + + bool CListModelBaseNonTemplate::isModelDestroyed() + { + return m_modelDestroyed; + } + + void CListModelBaseNonTemplate::clearHighlighting() + { + // can be overridden to delete highlighting + } + + bool CListModelBaseNonTemplate::hasHighlightedRows() const + { + return false; + // can be overridden to enable highlighting based operations + } + + void CListModelBaseNonTemplate::emitDataChanged(int startRowIndex, int endRowIndex) + { + BLACK_VERIFY_X(startRowIndex <= endRowIndex, Q_FUNC_INFO, "check rows"); + BLACK_VERIFY_X(startRowIndex >= 0 && endRowIndex >= 0, Q_FUNC_INFO, "check rows"); + + const int columns = columnCount(); + const int rows = rowCount(); + if (columns < 1) { return; } + if (startRowIndex < 0) { startRowIndex = 0; } + if (endRowIndex >= rows) { endRowIndex = rows - 1; } + const QModelIndex topLeft(createIndex(startRowIndex, 0)); + const QModelIndex bottomRight(createIndex(endRowIndex, columns - 1)); + emit this->dataChanged(topLeft, bottomRight); + } + + CListModelBaseNonTemplate::CListModelBaseNonTemplate(const QString &translationContext, QObject *parent) + : QStandardItemModel(parent), m_columns(translationContext), m_sortColumn(-1), m_sortOrder(Qt::AscendingOrder) + { + // non unique default name, set translation context as default + this->setObjectName(translationContext); + + // connect + connect(this, &CListModelBaseNonTemplate::dataChanged, this, &CListModelBaseNonTemplate::onDataChanged); + } + + } // namespace +} // namespace diff --git a/src/blackgui/models/listmodelbasenontemplate.h b/src/blackgui/models/listmodelbasenontemplate.h new file mode 100644 index 000000000..a40c26945 --- /dev/null +++ b/src/blackgui/models/listmodelbasenontemplate.h @@ -0,0 +1,176 @@ +/* Copyright (C) 2018 + * swift project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +//! \file + +#ifndef BLACKGUI_LISTMODELBASENONTEMPLATE_H +#define BLACKGUI_LISTMODELBASENONTEMPLATE_H + +#include "blackgui/models/columns.h" +#include "blackgui/dropbase.h" +#include "blackgui/blackguiexport.h" +#include "blackmisc/digestsignal.h" +#include "blackmisc/variant.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class QMimeData; +class QModelIndex; + +namespace BlackMisc { class CWorker; } +namespace BlackGui +{ + namespace Models + { + //! Non templated base class, allows Q_OBJECT and signals to be used + class BLACKGUI_EXPORT CListModelBaseNonTemplate : + public QStandardItemModel, + public CDropBase + { + Q_OBJECT + + public: + //! Number of elements when to use asynchronous updates + static constexpr int asyncThreshold = 50; + + //! Destructor + virtual ~CListModelBaseNonTemplate() override {} + + //! \name Functions from QStandardItemModel + //! @{ + virtual int columnCount(const QModelIndex &modelIndex = QModelIndex()) const final override; + virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const final override; + virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const final override; + virtual QModelIndex parent(const QModelIndex &child) const final override; + virtual Qt::ItemFlags flags(const QModelIndex &index) const final override; + virtual Qt::DropActions supportedDragActions() const final override; + virtual Qt::DropActions supportedDropActions() const final override; + virtual QStringList mimeTypes() const final override; + //! @} + + //! Column to property index + virtual BlackMisc::CPropertyIndex columnToPropertyIndex(int column) const; + + //! Property index to column number + virtual int propertyIndexToColumn(const BlackMisc::CPropertyIndex &propertyIndex) const; + + //! Index to property index + virtual BlackMisc::CPropertyIndex modelIndexToPropertyIndex(const QModelIndex &index) const; + + //! Set sort column + virtual void setSortColumn(int column) { m_sortColumn = column; } + + //! Sort by index + void sortByPropertyIndex(const BlackMisc::CPropertyIndex &propertyIndex, Qt::SortOrder order = Qt::AscendingOrder); + + //! Set column for sorting + //! \param propertyIndex index of column to be sorted + virtual bool setSortColumnByPropertyIndex(const BlackMisc::CPropertyIndex &propertyIndex); + + //! Sorting + virtual bool setSorting(const BlackMisc::CPropertyIndex &propertyIndex, Qt::SortOrder order = Qt::AscendingOrder); + + //! Get sort column property index + virtual int getSortColumn() const { return m_sortColumn; } + + //! Has valid sort column? + virtual bool hasValidSortColumn() const; + + //! Get sort order + virtual Qt::SortOrder getSortOrder() const { return m_sortOrder; } + + //! Translation context + virtual const QString &getTranslationContext() const; + + //! Orderable, normally use a container BlackMisc::IOrderableList + virtual bool isOrderable() const = 0; + + //! Mark as about to be destroyed, normally marked from view + void markDestroyed(); + + //! Model about to be destroyed? + bool isModelDestroyed(); + + //! Remove all highlighting + virtual void clearHighlighting(); + + //! Has highlighted rows? + virtual bool hasHighlightedRows() const; + + //! Drop actions + void setDropActions(Qt::DropActions dropActions) { m_dropActions = dropActions; } + + //! Send signal that data have been changed. + //! \note Meant for scenarios where the container is directly updated and a subsequent signal is required + void emitDataChanged(int startRowIndex, int endRowIndex); + + //! Convert to JSON + virtual QJsonObject toJson(bool selectedOnly = false) const = 0; + + //! Convert to JSON string + virtual QString toJsonString(QJsonDocument::JsonFormat format = QJsonDocument::Indented, bool selectedOnly = false) const = 0; + + //! The columns + const CColumns &getColumns() const { return m_columns; } + + signals: + //! Asynchronous update finished + void asyncUpdateFinished(); + + //! Data changed + //! \remark passing back selected objects so they can be reselected + //! \remark condsider modelDataChangedDigest for performance reasons + void modelDataChanged(int count, bool withFilter); + + //! Data changed, digest version + void modelDataChangedDigest(int count, bool withFilter); + + //! Model has been changed + //! Triggered with each change, for performance consider using changedDigest + void changed(); + + //! Model has been changed, digest signal + void changedDigest(); + + //! Template free information, that object changed + void objectChanged(const BlackMisc::CVariant &object, const BlackMisc::CPropertyIndex &changedIndex); + + protected: + //! Feedback when QStandardItemModel::dataChanged was called + virtual void onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles) = 0; + + //! Digest signal + virtual void onChangedDigest() = 0; + + //! Constructor + //! \param translationContext I18N context + //! \param parent + CListModelBaseNonTemplate(const QString &translationContext, QObject *parent = nullptr); + + CColumns m_columns; //!< columns metadata + int m_sortColumn; //!< currently sorted column + bool m_modelDestroyed = false; //!< model is about to be destroyed + Qt::SortOrder m_sortOrder; //!< sort order (asc/desc) + Qt::DropActions m_dropActions = Qt::IgnoreAction; //!< drop actions + + private: + BlackMisc::CDigestSignal m_dsModelsChanged { this, &CListModelBaseNonTemplate::changed, &CListModelBaseNonTemplate::onChangedDigest, 500, 10 }; + }; + + } // namespace +} // namespace +#endif // guard diff --git a/src/blackgui/models/listmodelbasesimulation.cpp b/src/blackgui/models/listmodelbasesimulation.cpp new file mode 100644 index 000000000..c25c8ec1f --- /dev/null +++ b/src/blackgui/models/listmodelbasesimulation.cpp @@ -0,0 +1,25 @@ +/* Copyright (C) 2018 + * swift project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +#include "listmodelbase.cpp" + +namespace BlackGui +{ + namespace Models + { + // see here for the reason of thess forward instantiations + // https://isocpp.org/wiki/faq/templates#separate-template-fn-defn-from-decl + template class CListModelBase; + template class CListModelBase; + template class CListModelBase; + template class CListModelBase; + template class CListModelBase; + + } // namespace +} // namespace diff --git a/src/blackgui/models/listmodelbaseweather.cpp b/src/blackgui/models/listmodelbaseweather.cpp new file mode 100644 index 000000000..c2e7ec49f --- /dev/null +++ b/src/blackgui/models/listmodelbaseweather.cpp @@ -0,0 +1,24 @@ +/* Copyright (C) 2018 + * swift project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +#include "listmodelbase.cpp" + + +namespace BlackGui +{ + namespace Models + { + // see here for the reason of thess forward instantiations + // https://isocpp.org/wiki/faq/templates#separate-template-fn-defn-from-decl + template class CListModelBase; + template class CListModelBase; + template class CListModelBase; + + } // namespace +} // namespace