Reworked field association

- Allow duplicate components to access same field data
This commit is contained in:
Oliver Walters 2017-04-18 22:43:40 +10:00 committed by Wayne Stambaugh
parent d792e36151
commit 47ee2773d2
2 changed files with 178 additions and 39 deletions

View File

@ -53,6 +53,86 @@ static BOM_TABLE_ROW const* ItemToRow( wxDataViewItem aItem )
} }
} }
BOM_FIELD_VALUES::BOM_FIELD_VALUES( wxString aRefDes ) : m_refDes( aRefDes )
{
}
/**
* Return the current value for the provided field ID
*/
bool BOM_FIELD_VALUES::GetFieldValue( unsigned int aFieldId, wxString& aValue ) const
{
auto search = m_currentValues.find( aFieldId );
if( search == m_currentValues.end() )
return false;
aValue = search->second;
return true;
}
/**
* Return the backup value for the provided field ID
*/
bool BOM_FIELD_VALUES::GetBackupValue( unsigned int aFieldId, wxString& aValue ) const
{
auto search = m_backupValues.find( aFieldId );
if( search == m_backupValues.end() )
return false;
aValue = search->second;
return true;
}
/**
* 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 BOM_FIELD_VALUES::SetFieldValue( unsigned int aFieldId, wxString aValue, bool aOverwrite )
{
if( aOverwrite || m_currentValues.count( aFieldId ) == 0 || m_currentValues[aFieldId].IsEmpty() )
{
m_currentValues[aFieldId] = aValue;
}
}
/**
* Set the backup value for the provided field ID
* If the backup value is already set, new value is ignored
*/
void BOM_FIELD_VALUES::SetBackupValue( unsigned int aFieldId, wxString aValue )
{
if( m_backupValues.count( aFieldId ) == 0 || m_backupValues[aFieldId].IsEmpty() )
{
m_backupValues[aFieldId] = aValue;
}
}
bool BOM_FIELD_VALUES::HasValueChanged( unsigned int aFieldId) const
{
wxString currentValue, backupValue;
GetFieldValue( aFieldId, currentValue );
GetBackupValue( aFieldId, backupValue );
return currentValue.Cmp( backupValue ) != 0;
}
void BOM_FIELD_VALUES::RevertChanges( unsigned int aFieldId )
{
wxString backupValue;
GetBackupValue( aFieldId, backupValue );
SetFieldValue( aFieldId, backupValue, true );
}
BOM_TABLE_ROW::BOM_TABLE_ROW() : m_columnList( nullptr ) BOM_TABLE_ROW::BOM_TABLE_ROW() : m_columnList( nullptr )
{ {
} }
@ -416,10 +496,12 @@ int BOM_TABLE_GROUP::SortValues( const wxString& aFirst, const wxString& aSecond
* Each COMPONENT row is associated with a single component item. * Each COMPONENT row is associated with a single component item.
*/ */
BOM_TABLE_COMPONENT::BOM_TABLE_COMPONENT( BOM_TABLE_GROUP* aParent, BOM_TABLE_COMPONENT::BOM_TABLE_COMPONENT( BOM_TABLE_GROUP* aParent,
BOM_COLUMN_LIST* aColumnList) BOM_COLUMN_LIST* aColumnList,
BOM_FIELD_VALUES* aFieldValues )
{ {
m_parent = aParent; m_parent = aParent;
m_columnList = aColumnList; m_columnList = aColumnList;
m_fieldValues = aFieldValues;
} }
/** /**
@ -471,10 +553,8 @@ bool BOM_TABLE_COMPONENT::AddUnit( SCH_REFERENCE aUnit )
break; break;
} }
SetFieldValue( column->Id(), value ); m_fieldValues->SetFieldValue( column->Id(), value );
m_fieldValues->SetBackupValue( column->Id(), value );
// Add the value to the fallback map
m_fallbackData[column->Id()] = value;
} }
return true; return true;
@ -489,16 +569,22 @@ bool BOM_TABLE_COMPONENT::AddUnit( SCH_REFERENCE aUnit )
*/ */
wxString BOM_TABLE_COMPONENT::GetFieldValue( unsigned int aFieldId ) const wxString BOM_TABLE_COMPONENT::GetFieldValue( unsigned int aFieldId ) const
{ {
auto search = m_fieldData.find( aFieldId ); wxString value;
if( search != m_fieldData.end() ) switch ( aFieldId )
{
return search->second;
}
else
{ {
case BOM_COL_ID_QUANTITY:
return wxEmptyString; return wxEmptyString;
case BOM_COL_ID_REFERENCE:
return GetReference();
default:
break;
} }
if( m_fieldValues )
m_fieldValues->GetFieldValue( aFieldId, value );
return value;
} }
/** /**
@ -509,9 +595,9 @@ wxString BOM_TABLE_COMPONENT::GetFieldValue( unsigned int aFieldId ) const
*/ */
bool BOM_TABLE_COMPONENT::SetFieldValue( unsigned int aFieldId, const wxString aValue, bool aOverwrite ) bool BOM_TABLE_COMPONENT::SetFieldValue( unsigned int aFieldId, const wxString aValue, bool aOverwrite )
{ {
if( aOverwrite || m_fieldData.count( aFieldId ) == 0 || m_fieldData[aFieldId].IsEmpty() ) if( m_fieldValues )
{ {
m_fieldData[aFieldId] = aValue; m_fieldValues->SetFieldValue( aFieldId, aValue, aOverwrite );
return true; return true;
} }
@ -550,13 +636,7 @@ bool BOM_TABLE_COMPONENT::HasValueChanged( BOM_COLUMN* aField ) const
return false; return false;
} }
auto value = m_fieldData.find( aField->Id() ); return m_fieldValues->HasValueChanged( aField->Id() );
auto backup = m_fallbackData.find( aField->Id() );
wxString currentValue = value == m_fieldData.end() ? wxString() : value->second;
wxString backupValue = backup == m_fallbackData.end() ? wxString() : backup->second;
return currentValue.Cmp( backupValue ) != 0;
} }
/** /**
@ -634,17 +714,7 @@ void BOM_TABLE_COMPONENT::RevertFieldChanges()
break; break;
} }
if( column && HasValueChanged( column ) ) m_fieldValues->RevertChanges( column->Id() );
{
if( m_fallbackData.count( column->Id() ) > 0 )
{
m_fieldData[column->Id()] = m_fallbackData[column->Id()];
}
else
{
m_fieldData[column->Id()] = wxEmptyString;
}
}
} }
} }
@ -931,6 +1001,7 @@ void BOM_TABLE_MODEL::SetComponents( SCH_REFERENCE_LIST aRefs )
// Group multi-unit components together // Group multi-unit components together
m_components.clear(); m_components.clear();
m_fieldValues.clear();
for( unsigned int ii=0; ii<aRefs.GetCount(); ii++ ) for( unsigned int ii=0; ii<aRefs.GetCount(); ii++ )
{ {
@ -949,7 +1020,30 @@ void BOM_TABLE_MODEL::SetComponents( SCH_REFERENCE_LIST aRefs )
if( !found ) if( !found )
{ {
auto* newComponent = new BOM_TABLE_COMPONENT( nullptr, &ColumnList ); // Find the field:value map associated with this component
wxString refDes = ref.GetComp()->GetField( REFERENCE )->GetText();
bool dataFound = false;
BOM_FIELD_VALUES* values;
for( auto& data : m_fieldValues )
{
// Look for a match based on RefDes
if( data->GetReference().Cmp( refDes ) == 0 )
{
dataFound = true;
values = &*data;
}
}
if( !dataFound )
{
values = new BOM_FIELD_VALUES( refDes );
m_fieldValues.push_back( std::unique_ptr<BOM_FIELD_VALUES>( values ) );
}
auto* newComponent = new BOM_TABLE_COMPONENT( nullptr, &ColumnList, values );
newComponent->AddUnit( ref ); newComponent->AddUnit( ref );
m_components.push_back( std::unique_ptr<BOM_TABLE_COMPONENT>( newComponent ) ); m_components.push_back( std::unique_ptr<BOM_TABLE_COMPONENT>( newComponent ) );
@ -1090,6 +1184,11 @@ bool BOM_TABLE_MODEL::SetValue(
} }
} }
if( m_widget )
{
m_widget->Update();
}
return result; return result;
} }

View File

@ -43,6 +43,46 @@ class BOM_TABLE_ROW; // Base-class for table row data model
class BOM_TABLE_GROUP; // Class for displaying a group of components class BOM_TABLE_GROUP; // Class for displaying a group of components
class BOM_TABLE_COMPONENT; // Class for displaying a single component class BOM_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 BOM_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 BOM_FIELD_VALUES
{
public:
BOM_FIELD_VALUES(wxString aRefDes);
bool GetFieldValue( unsigned int aFieldId, wxString& aValue ) const;
bool GetBackupValue( unsigned int aFieldId, wxString& aValue ) const;
void SetFieldValue( unsigned int aFieldId, wxString aValue, bool aOverwrite = false );
void SetBackupValue( unsigned int aFieldId, wxString aValue );
wxString GetReference() const { return m_refDes; }
bool HasValueChanged( unsigned int aFieldId ) const;
void RevertChanges( unsigned int aFieldId );
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;
};
/** /**
* Virtual base class determining how a row is displayed * Virtual base class determining how a row is displayed
* There are three types of rows: * There are three types of rows:
@ -144,7 +184,7 @@ public:
// List of units associated with this component // List of units associated with this component
std::vector<SCH_REFERENCE> Units; std::vector<SCH_REFERENCE> Units;
BOM_TABLE_COMPONENT( BOM_TABLE_GROUP* aParent, BOM_COLUMN_LIST* aColumnList ); BOM_TABLE_COMPONENT( BOM_TABLE_GROUP* aParent, BOM_COLUMN_LIST* aColumnList, BOM_FIELD_VALUES* aValues );
bool AddUnit( SCH_REFERENCE aUnit ); bool AddUnit( SCH_REFERENCE aUnit );
@ -168,13 +208,9 @@ public:
virtual BOM_TABLE_ROW* GetParent() const override { return m_parent; } virtual BOM_TABLE_ROW* GetParent() const override { return m_parent; }
protected: protected:
// Initial data for reverting component values
std::map<unsigned int, wxString> m_fallbackData;
// Data as it is updated
std::map<unsigned int, wxString> m_fieldData;
BOM_TABLE_GROUP* m_parent; BOM_TABLE_GROUP* m_parent;
BOM_FIELD_VALUES* m_fieldValues;
}; };
/** /**
@ -189,8 +225,12 @@ class BOM_TABLE_MODEL : public wxDataViewModel
protected: protected:
BOM_TABLE_MODEL(); BOM_TABLE_MODEL();
// Vector of unique component rows
std::vector<std::unique_ptr<BOM_TABLE_COMPONENT>> m_components; std::vector<std::unique_ptr<BOM_TABLE_COMPONENT>> m_components;
// Vector of field values mapped to field IDs
std::vector<std::unique_ptr<BOM_FIELD_VALUES>> m_fieldValues;
// BOM Preferences // BOM Preferences
//! Group components based on values //! Group components based on values
bool m_groupColumns = true; bool m_groupColumns = true;