kicad/eeschema/fields_editor_table_model.h

363 lines
12 KiB
C++

/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2017 Oliver Walters
* Copyright (C) 2017 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef FIELDS_EDITOR_TABLE_MODEL_H
#define FIELDS_EDITOR_TABLE_MODEL_H
#include <wx/dataview.h>
#include <wx/regex.h>
#include <vector>
#include <map>
#include <sch_component.h>
#include <sch_reference_list.h>
#include <netlist_object.h>
#include <template_fieldnames.h>
#include "fields_editor_table_column.h"
// Forward-declare classes
class FIELDS_EDITOR_TABLE_ROW; // Base-class for table row data model
class FIELDS_EDITOR_TABLE_GROUP; // Class for displaying a group of components
class FIELDS_EDITOR_TABLE_COMPONENT; // Class for displaying a single component
// Map column IDs to field values (for quick lookup)
typedef std::map<unsigned int, wxString> FIELD_VALUE_MAP;
/**
* The FIELDS_EDITOR_FIELD_VALUES class provides quick lookup of component values
* (based on Field ID)
* This is done for the following reasons:
* - Increase lookup speed for table values
* - Allow field values to be reverted to original values
* - Allow duplicate components to reference the same data
*/
class FIELDS_EDITOR_FIELD_VALUES
{
public:
FIELDS_EDITOR_FIELD_VALUES( const wxString& aRefDes, FIELD_VALUE_MAP* aTemplate );
/**
* Return the current value for the provided field ID
* @return true if the field exists
* @param aFieldId = the field index
* @param aValue = a string to return the field value
*/
bool GetFieldValue( unsigned int aFieldId, wxString& aValue ) const;
/**
* Return the backup value for the provided field ID
* @return true if the field exists
* @param aFieldId = the field index
* @param aValue = a string to return the field backup value
*/
bool GetBackupValue( unsigned int aFieldId, wxString& aValue ) const;
/**
* Return the template value for a provided field ID (if it exists)
* @return true if the field exists
* @param aFieldId = the field index
* @param aValue = a string to return the field template value
*/
bool GetTemplateValue( unsigned int aFieldId, wxString& aValue ) const;
/**
* Set the value for the provided field ID
* Field value is set under any of the following conditions:
* - param aOverwrite is true
* - There is no current value
* - The current value is empty
*/
void SetFieldValue( unsigned int aFieldId, const wxString& aValue, bool aOverwrite = false );
wxString GetReference() const { return m_refDes; }
bool HasValueChanged( unsigned int aFieldId ) const;
void RevertChanges( unsigned int aFieldId );
void SetBackupPoint();
protected:
//! The RefDes to which these values correspond
wxString m_refDes;
//! Current values for each column
FIELD_VALUE_MAP m_currentValues;
//! Backup values for each column
FIELD_VALUE_MAP m_backupValues;
//! Template values for each column
FIELD_VALUE_MAP* m_templateValues;
};
/**
* Virtual base class determining how a row is displayed
* There are three types of rows:
* GROUP - Displays a group of (one or more) components
* COMPONENT - Displays a single component
* UNIT - Child of COMPONENT for multi-unit components
*/
class FIELDS_EDITOR_TABLE_ROW
{
public:
FIELDS_EDITOR_TABLE_ROW();
virtual ~FIELDS_EDITOR_TABLE_ROW() {}
/// Set display properties for a cell
virtual bool GetAttr( unsigned int aFieldId, wxDataViewItemAttr& aAttr ) const;
/// Get the row value associated with provided field ID
virtual wxString GetFieldValue( unsigned int aFieldId ) const = 0;
/// Set the field value associated with the provided field ID
virtual bool SetFieldValue( unsigned int aFieldId, const wxString aValue, bool aOverwrite = false ) = 0;
/// Return parent item
virtual FIELDS_EDITOR_TABLE_ROW* GetParent() const { return nullptr; }
/// Test if row has any child rows
virtual bool HasChildren() const { return false; }
/// Return any child rows
virtual unsigned int GetChildren( wxDataViewItemArray& aChildren ) const { return 0; }
/// Determine if a value has changed
virtual bool HasValueChanged( FIELDS_EDITOR_COLUMN* aField ) const { return false; }
/// Determine if any values have changed
bool HasChanged() const;
protected:
/// Pointer to list of columns
FIELDS_EDITOR_COLUMN_LIST* m_columnList;
};
/**
* FIELDS_EDITOR_TABLE_GROUP class displays a group of similar components
* If the group contains more than one component,
* they are each displayed as child items of the group
*/
class FIELDS_EDITOR_TABLE_GROUP : public FIELDS_EDITOR_TABLE_ROW
{
public:
/// List of components stored in this group
std::vector<FIELDS_EDITOR_TABLE_COMPONENT*> Components;
FIELDS_EDITOR_TABLE_GROUP( FIELDS_EDITOR_COLUMN_LIST* aColumnList );
virtual ~FIELDS_EDITOR_TABLE_GROUP() {}
/// Set display properties for a group row
virtual bool GetAttr( unsigned int aFieldId, wxDataViewItemAttr& aAttr ) const override;
/// Get group row value
virtual wxString GetFieldValue( unsigned int aFieldId ) const override;
/// Set group row value
virtual bool SetFieldValue( unsigned int aFieldId, const wxString aValue, bool aOverwrite = false ) override;
/// Attempt to add a new component to the group
bool AddComponent( FIELDS_EDITOR_TABLE_COMPONENT* aComponent );
/// Test if this group should display children
virtual bool HasChildren() const override { return Components.size() > 1; }
/// Return a list of children items of this group
virtual unsigned int GetChildren( wxDataViewItemArray& aChildren ) const override;
/// Test if any children have changed
virtual bool HasValueChanged( FIELDS_EDITOR_COLUMN* aField ) const override;
/// Return the number of child items in this group
unsigned int GroupSize( void ) const { return Components.size(); }
/// Return a sorted, concatenated list of references
wxArrayString GetReferences( bool aSort = true ) const;
/// Function for sorting two reference strings
static int SortReferences( const wxString& aFirst, const wxString& aSecond );
/// Function for sorting two value strings
static int SortValues( const wxString& aFirst, const wxString& aSecond );
protected:
/// Test if a particular field matches against another component
bool TestField( FIELDS_EDITOR_COLUMN* aField, FIELDS_EDITOR_TABLE_COMPONENT* aComponent ) const;
};
class FIELDS_EDITOR_TABLE_COMPONENT : public FIELDS_EDITOR_TABLE_ROW
{
public:
// List of units associated with this component
std::vector<SCH_REFERENCE> Units;
FIELDS_EDITOR_TABLE_COMPONENT( FIELDS_EDITOR_TABLE_GROUP* aParent, FIELDS_EDITOR_COLUMN_LIST* aColumnList, FIELDS_EDITOR_FIELD_VALUES* aValues );
bool AddUnit( const SCH_REFERENCE& aUnit );
virtual wxString GetFieldValue( unsigned int aFieldId ) const override;
virtual bool SetFieldValue( unsigned int aFieldId, const wxString aValue, bool aOverwrite = false ) override;
virtual bool HasValueChanged( FIELDS_EDITOR_COLUMN* aField ) const override;
/// Return the reference of the first unit (all units must be the same
wxString GetReference() const;
/**
* @return the prefix of a component e.g. "R23" returns "R"
*/
wxString GetPrefix() const;
void ApplyFieldChanges();
void RevertFieldChanges();
void SetParent( FIELDS_EDITOR_TABLE_GROUP* aParent ) { m_parent = aParent; }
virtual FIELDS_EDITOR_TABLE_ROW* GetParent() const override { return m_parent; }
protected:
FIELDS_EDITOR_TABLE_GROUP* m_parent;
FIELDS_EDITOR_FIELD_VALUES* m_fieldValues;
};
/**
* FIELDS_EDITOR_TABLE_MODEL class
*
* Contains complete BOM information:
* a) List of columns (fields) to display
* b) List of groups of consolidated components
*/
class FIELDS_EDITOR_TABLE_MODEL : public wxDataViewModel
{
protected:
FIELDS_EDITOR_TABLE_MODEL();
// Vector of unique component rows
std::vector<std::unique_ptr<FIELDS_EDITOR_TABLE_COMPONENT>> m_components;
// Vector of field values mapped to field IDs
std::vector<std::unique_ptr<FIELDS_EDITOR_FIELD_VALUES>> m_fieldValues;
// Template field values
FIELD_VALUE_MAP m_fieldTemplates;
// BOM Preferences
//! Group components based on values
bool m_groupColumns = true;
//! Filter components
bool m_filterColumns = false;
//! Allow blank fields to be merged with otherwise matching groups
bool m_mergeBlankFields = false;
wxDataViewCtrl* m_widget;
//! ID of column to sort by
unsigned int m_sortingColumn;
bool m_sortingOrder;
void AddDefaultColumns();
void ClearColumns();
virtual bool HasContainerColumns( const wxDataViewItem& aItem ) const override { return true; }
virtual bool IsContainer( const wxDataViewItem& aItem ) const override;
virtual wxDataViewItem GetParent( const wxDataViewItem& aItem ) const override;
virtual unsigned int GetChildren( const wxDataViewItem& aItem, wxDataViewItemArray& aChildren ) const override;
virtual unsigned int GetColumnCount() const override { return ColumnList.ColumnCount( false ); }
virtual wxString GetColumnType( unsigned int aFieldId ) const override { return wxString( "string" ); }
virtual void GetValue( wxVariant& aVariant, const wxDataViewItem& aItem, unsigned int aFieldId ) const override;
virtual bool SetValue( const wxVariant& aVariant, const wxDataViewItem& item, unsigned int aFieldId ) override;
public:
virtual ~FIELDS_EDITOR_TABLE_MODEL();
FIELDS_EDITOR_COLUMN_LIST ColumnList;
/// List of component groups
std::vector<std::unique_ptr<FIELDS_EDITOR_TABLE_GROUP>> Groups;
typedef wxObjectDataPtr<FIELDS_EDITOR_TABLE_MODEL> MODEL_PTR;
static MODEL_PTR Create();
void AttachTo( wxDataViewCtrl* aView );
wxDataViewColumn* AddColumn( FIELDS_EDITOR_COLUMN* aColumn, int aPosition = -1 );
bool RemoveColumn( FIELDS_EDITOR_COLUMN* aColumn );
// wxDataViewModel functions
virtual bool GetAttr( const wxDataViewItem& aItem, unsigned int aFieldId, wxDataViewItemAttr& aAttr ) const override;
virtual bool HasDefaultCompare() const override { return false; }
virtual int Compare( const wxDataViewItem& aItem1,
const wxDataViewItem& aItem2,
unsigned int aColumnId,
bool aAscending ) const override;
void ReloadTable();
unsigned int ColumnCount() const { return ColumnList.ColumnCount(); }
unsigned int GroupCount() const { return (unsigned int) Groups.size(); }
unsigned int ComponentCount() const;
void SetColumnGrouping( const bool aGroup = true ) { m_groupColumns = aGroup; }
bool GetColumnGrouping() const { return m_groupColumns; }
void SetColumnFiltering( const bool aFilter = true ) { m_filterColumns = aFilter; }
bool GetColumnFiltering() const { return m_filterColumns; }
void SetBlankMerging( const bool aMerge = true ) { m_mergeBlankFields = aMerge; }
bool GetBlankMerging() const { return m_mergeBlankFields; }
wxArrayString GetRowData( unsigned int aRow, std::vector<FIELDS_EDITOR_COLUMN*> aColumns ) const;
void SetComponents( SCH_REFERENCE_LIST aRefs, const TEMPLATE_FIELDNAMES& aTemplateFields );
void AddComponentFields( SCH_COMPONENT* aCmp );
void RevertFieldChanges();
void ApplyFieldChanges();
bool HaveFieldsChanged() const;
void SetBackupPoint();
std::vector<SCH_REFERENCE> GetChangedComponents();
unsigned int CountChangedComponents();
};
#endif // FIELDS_EDITOR_TABLE_MODEL_H