Commit bf2f650e authored by jean-pierre charras's avatar jean-pierre charras

Cvpcb: fix a typo which prevents cvpcb to be compiled with webkit suppport....

Cvpcb: fix a typo which prevents cvpcb to be compiled with webkit suppport. Equ files support enhancements.
parent 0b6d1bbc
...@@ -8,7 +8,7 @@ endif() ...@@ -8,7 +8,7 @@ endif()
add_definitions( -DCVPCB ) add_definitions( -DCVPCB )
if( KICAD_USE_WEBKITT AND BUILD_GITHUB_PLUGIN ) if( KICAD_USE_WEBKIT AND BUILD_GITHUB_PLUGIN )
set( WEBVIEWER_WXLIB "webviewer" ) set( WEBVIEWER_WXLIB "webviewer" )
add_definitions( -DKICAD_USE_WEBKIT ) add_definitions( -DKICAD_USE_WEBKIT )
endif() endif()
......
...@@ -25,7 +25,11 @@ ...@@ -25,7 +25,11 @@
* @file autosel.cpp * @file autosel.cpp
*/ */
// Routines for automatic selection of modules. // This file handle automatic selection of footprints, from .equ files which give
// a footprint FPID associated to a component value.
// Thse assiciations have this form:
// 'FT232BL' 'QFP:LQFP-32_7x7mm_Pitch0.8mm'
#include <fctsys.h> #include <fctsys.h>
#include <common.h> #include <common.h>
...@@ -39,24 +43,10 @@ ...@@ -39,24 +43,10 @@
#include <cvpcb.h> #include <cvpcb.h>
#include <cvpcb_mainframe.h> #include <cvpcb_mainframe.h>
#include <cvstruct.h> #include <cvstruct.h>
#include <autosel.h>
#define QUOTE '\'' #define QUOTE '\''
#define FMT_TITLE_LIB_LOAD_ERROR _( "Library Load Error" )
class FOOTPRINT_ALIAS
{
public:
int m_Type;
wxString m_Name;
wxString m_FootprintName;
FOOTPRINT_ALIAS() { m_Type = 0; }
};
typedef boost::ptr_vector< FOOTPRINT_ALIAS > FOOTPRINT_ALIAS_LIST;
/* /*
* read the string between quotes and put it in aTarget * read the string between quotes and put it in aTarget
...@@ -81,38 +71,48 @@ wxString GetQuotedText( wxString & text ) ...@@ -81,38 +71,48 @@ wxString GetQuotedText( wxString & text )
} }
void CVPCB_MAINFRAME::AssocieModule( wxCommandEvent& event ) // A sort compare function, used to sort a FOOTPRINT_EQUIVALENCE_LIST by cmp values
// (m_ComponentValue member)
bool sortListbyCmpValue( const FOOTPRINT_EQUIVALENCE& ref, const FOOTPRINT_EQUIVALENCE& test )
{ {
FOOTPRINT_ALIAS_LIST aliases; return ref.m_ComponentValue.Cmp( test.m_ComponentValue ) >= 0;
FOOTPRINT_ALIAS* alias; }
COMPONENT* component;
wxFileName fn;
wxString msg, tmp;
char Line[1024];
FILE* file;
size_t ii;
SEARCH_STACK& search = Kiface().KifaceSearch(); // read the .equ files and populate the list of equvalents
int CVPCB_MAINFRAME::buildEquivalenceList( FOOTPRINT_EQUIVALENCE_LIST& aList, wxString * aErrorMessages )
{
char Line[1024];
int error_count = 0;
FILE* file;
wxFileName fn;
wxString tmp, error_msg;
if( m_netlist.IsEmpty() ) SEARCH_STACK& search = Kiface().KifaceSearch();
return;
// Find equivalents in all available files. // Find equivalences in all available files, and populates the
for( ii = 0; ii < m_EquFilesNames.GetCount(); ii++ ) // equiv_List with all equivalences found in .equ files
for( unsigned ii = 0; ii < m_EquFilesNames.GetCount(); ii++ )
{ {
if( m_EquFilesNames[ii].StartsWith( wxT("${") ) ) fn = wxExpandEnvVars( m_EquFilesNames[ii] );
fn = wxExpandEnvVars( m_EquFilesNames[ii] );
else
fn = m_EquFilesNames[ii];
tmp = search.FindValidPath( fn.GetFullPath() ); tmp = search.FindValidPath( fn.GetFullPath() );
if( !tmp ) if( !tmp )
{ {
msg.Printf( _( "Footprint equ file '%s' could not be found in the " error_count++;
"default search paths." ),
GetChars( fn.GetFullName() ) ); if( aErrorMessages )
wxMessageBox( msg, FMT_TITLE_LIB_LOAD_ERROR, wxOK | wxICON_ERROR ); {
error_msg.Printf( _( "Equ file '%s' could not be found in the "
"default search paths." ),
GetChars( fn.GetFullName() ) );
if( ! aErrorMessages->IsEmpty() )
*aErrorMessages << wxT("\n\n");
*aErrorMessages += error_msg;
}
continue; continue;
} }
...@@ -120,8 +120,18 @@ void CVPCB_MAINFRAME::AssocieModule( wxCommandEvent& event ) ...@@ -120,8 +120,18 @@ void CVPCB_MAINFRAME::AssocieModule( wxCommandEvent& event )
if( file == NULL ) if( file == NULL )
{ {
msg.Printf( _( "Error opening equ file '%s'." ), GetChars( tmp ) ); error_count++;
wxMessageBox( msg, FMT_TITLE_LIB_LOAD_ERROR, wxOK | wxICON_ERROR );
if( aErrorMessages )
{
error_msg.Printf( _( "Error opening equ file '%s'." ), GetChars( tmp ) );
if( ! aErrorMessages->IsEmpty() )
*aErrorMessages << wxT("\n\n");
*aErrorMessages += error_msg;
}
continue; continue;
} }
...@@ -142,21 +152,46 @@ void CVPCB_MAINFRAME::AssocieModule( wxCommandEvent& event ) ...@@ -142,21 +152,46 @@ void CVPCB_MAINFRAME::AssocieModule( wxCommandEvent& event )
value.Replace( wxT( " " ), wxT( "_" ) ); value.Replace( wxT( " " ), wxT( "_" ) );
alias = new FOOTPRINT_ALIAS(); FOOTPRINT_EQUIVALENCE* equivItem = new FOOTPRINT_EQUIVALENCE();
alias->m_Name = value; equivItem->m_ComponentValue = value;
alias->m_FootprintName = footprint; equivItem->m_FootprintFPID = footprint;
aliases.push_back( alias ); aList.push_back( equivItem );
} }
fclose( file ); fclose( file );
} }
// Display the number of footprint aliases. return error_count;
msg.Printf( _( "%d footprint/cmp equivalences found." ), aliases.size() ); }
void CVPCB_MAINFRAME::AutomaticFootprintMatching( wxCommandEvent& event )
{
FOOTPRINT_EQUIVALENCE_LIST equiv_List;
COMPONENT* component;
wxString msg, error_msg;
size_t ii;
if( m_netlist.IsEmpty() )
return;
if( buildEquivalenceList( equiv_List, &error_msg ) )
wxMessageBox( error_msg, _( "Equ files Load Error" ), wxOK | wxICON_WARNING, this );
// Sort the association list by component value.
// When sorted, find duplicate definitions (i.e. 2 or more items
// having the same component value) is more easy.
std::sort( equiv_List.begin(), equiv_List.end(), sortListbyCmpValue );
// Display the number of footprint/component equivalences.
msg.Printf( _( "%d footprint/cmp equivalences found." ), equiv_List.size() );
SetStatusText( msg, 0 ); SetStatusText( msg, 0 );
// Now, associe each free component with a footprint, when the association
// is found in list
m_skipComponentSelect = true; m_skipComponentSelect = true;
ii = 0; ii = 0;
error_msg.Empty();
for( unsigned kk = 0; kk < m_netlist.GetCount(); kk++ ) for( unsigned kk = 0; kk < m_netlist.GetCount(); kk++ )
{ {
...@@ -165,19 +200,41 @@ void CVPCB_MAINFRAME::AssocieModule( wxCommandEvent& event ) ...@@ -165,19 +200,41 @@ void CVPCB_MAINFRAME::AssocieModule( wxCommandEvent& event )
bool found = false; bool found = false;
m_compListBox->SetSelection( ii++, true ); m_compListBox->SetSelection( ii++, true );
if( !component->GetFPID().empty() ) if( !component->GetFPID().empty() ) // the component has already a footprint
continue; continue;
BOOST_FOREACH( FOOTPRINT_ALIAS& alias, aliases ) // Here a first attempt is made. We can have multiple equivItem of the same value.
// When happens, using the footprint filter of components can remove the ambiguity by
// filtering equivItem so one can use multiple equiv_List (for polar and
// nonpolar caps for example)
for( unsigned idx = 0; idx < equiv_List.size(); idx++ )
{ {
FOOTPRINT_EQUIVALENCE& equivItem = equiv_List[idx];
if( alias.m_Name.CmpNoCase( component->GetValue() ) != 0 ) if( equivItem.m_ComponentValue.CmpNoCase( component->GetValue() ) != 0 )
continue; continue;
// filter alias so one can use multiple aliases (for polar and const FOOTPRINT_INFO *module = m_footprints.GetModuleInfo( equivItem.m_FootprintFPID );
// nonpolar caps for example)
const FOOTPRINT_INFO *module = m_footprints.GetModuleInfo( alias.m_FootprintName ); bool equ_is_unique = true;
unsigned next = idx+1;
unsigned previous = idx-1;
if( next < equiv_List.size() && previous >= 0 &&
( equivItem.m_ComponentValue == equiv_List[next].m_ComponentValue ||
equivItem.m_ComponentValue == equiv_List[previous].m_ComponentValue ) )
equ_is_unique = false;
// If the equivalence is unique, no ambiguity: use the association
if( module && equ_is_unique )
{
SetNewPkg( equivItem.m_FootprintFPID );
found = true;
break;
}
// The equivalence is not unique: use the footprint filter to try to remove
// ambiguity
if( module ) if( module )
{ {
size_t filtercount = component->GetFootprintFilters().GetCount(); size_t filtercount = component->GetFootprintFilters().GetCount();
...@@ -193,31 +250,38 @@ void CVPCB_MAINFRAME::AssocieModule( wxCommandEvent& event ) ...@@ -193,31 +250,38 @@ void CVPCB_MAINFRAME::AssocieModule( wxCommandEvent& event )
msg.Printf( _( "Component %s: footprint %s not found in any of the project " msg.Printf( _( "Component %s: footprint %s not found in any of the project "
"footprint libraries." ), "footprint libraries." ),
GetChars( component->GetReference() ), GetChars( component->GetReference() ),
GetChars( alias.m_FootprintName ) ); GetChars( equivItem.m_FootprintFPID ) );
wxMessageBox( msg, _( "CvPcb Error" ), wxOK | wxICON_ERROR, this );
if( ! error_msg.IsEmpty() )
error_msg << wxT("\n\n");
error_msg += msg;
} }
if( found ) if( found )
{ {
SetNewPkg( alias.m_FootprintName ); SetNewPkg( equivItem.m_FootprintFPID );
break; break;
} }
} }
if( found )
continue;
// obviously the last chance: there's only one filter matching one footprint // obviously the last chance: there's only one filter matching one footprint
if( !found && 1 == component->GetFootprintFilters().GetCount() ) if( 1 == component->GetFootprintFilters().GetCount() )
{ {
// we do not need to analyse wildcards: single footprint do not // we do not need to analyse wildcards: single footprint do not
// contain them and if there are wildcards it just will not match any // contain them and if there are wildcards it just will not match any
const FOOTPRINT_INFO* module = m_footprints.GetModuleInfo( component->GetFootprintFilters()[0] ); const FOOTPRINT_INFO* module = m_footprints.GetModuleInfo( component->GetFootprintFilters()[0] );
if( module ) if( module )
{
SetNewPkg( component->GetFootprintFilters()[0] ); SetNewPkg( component->GetFootprintFilters()[0] );
}
} }
} }
if( !error_msg.IsEmpty() )
wxMessageBox( error_msg, _( "CvPcb Warning" ), wxOK | wxICON_WARNING, this );
m_skipComponentSelect = false; m_skipComponentSelect = false;
} }
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 1992-2015 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 AUTOSEL_H
#define AUTOSEL_H
// A helper class to handle info read in .equ files, which gives a footprint FPID
// corresponding to a component value.
// Each line is something like:
// 'FT232BL' 'QFP:LQFP-32_7x7mm_Pitch0.8mm'
//
class FOOTPRINT_EQUIVALENCE
{
public:
wxString m_ComponentValue; // The value of a component
wxString m_FootprintFPID; // the footprint FPID corresponding to this value
FOOTPRINT_EQUIVALENCE() {}
};
typedef boost::ptr_vector< FOOTPRINT_EQUIVALENCE > FOOTPRINT_EQUIVALENCE_LIST;
#endif // ifndef AUTOSEL_H
...@@ -80,7 +80,7 @@ BEGIN_EVENT_TABLE( CVPCB_MAINFRAME, EDA_BASE_FRAME ) ...@@ -80,7 +80,7 @@ BEGIN_EVENT_TABLE( CVPCB_MAINFRAME, EDA_BASE_FRAME )
EVT_TOOL( ID_CVPCB_GOTO_FIRSTNA, CVPCB_MAINFRAME::ToFirstNA ) EVT_TOOL( ID_CVPCB_GOTO_FIRSTNA, CVPCB_MAINFRAME::ToFirstNA )
EVT_TOOL( ID_CVPCB_GOTO_PREVIOUSNA, CVPCB_MAINFRAME::ToPreviousNA ) EVT_TOOL( ID_CVPCB_GOTO_PREVIOUSNA, CVPCB_MAINFRAME::ToPreviousNA )
EVT_TOOL( ID_CVPCB_DEL_ASSOCIATIONS, CVPCB_MAINFRAME::DelAssociations ) EVT_TOOL( ID_CVPCB_DEL_ASSOCIATIONS, CVPCB_MAINFRAME::DelAssociations )
EVT_TOOL( ID_CVPCB_AUTO_ASSOCIE, CVPCB_MAINFRAME::AssocieModule ) EVT_TOOL( ID_CVPCB_AUTO_ASSOCIE, CVPCB_MAINFRAME::AutomaticFootprintMatching )
EVT_TOOL( ID_PCB_DISPLAY_FOOTPRINT_DOC, CVPCB_MAINFRAME::DisplayDocFile ) EVT_TOOL( ID_PCB_DISPLAY_FOOTPRINT_DOC, CVPCB_MAINFRAME::DisplayDocFile )
EVT_TOOL( ID_CVPCB_FOOTPRINT_DISPLAY_FILTERED_LIST, EVT_TOOL( ID_CVPCB_FOOTPRINT_DISPLAY_FILTERED_LIST,
CVPCB_MAINFRAME::OnSelectFilteringFootprint ) CVPCB_MAINFRAME::OnSelectFilteringFootprint )
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <wxBasePcbFrame.h> #include <wxBasePcbFrame.h>
#include <config_params.h> #include <config_params.h>
#include <autosel.h>
/* Forward declarations of all top-level window classes. */ /* Forward declarations of all top-level window classes. */
...@@ -158,7 +159,7 @@ public: ...@@ -158,7 +159,7 @@ public:
* format of a line: * format of a line:
* 'cmp_ref' 'footprint_name' * 'cmp_ref' 'footprint_name'
*/ */
void AssocieModule( wxCommandEvent& event ); void AutomaticFootprintMatching( wxCommandEvent& event );
void DisplayDocFile( wxCommandEvent& event ); void DisplayDocFile( wxCommandEvent& event );
...@@ -177,6 +178,7 @@ public: ...@@ -177,6 +178,7 @@ public:
* @param aFootprintName = the selected footprint * @param aFootprintName = the selected footprint
*/ */
void SetNewPkg( const wxString& aFootprintName ); void SetNewPkg( const wxString& aFootprintName );
void BuildCmpListBox(); void BuildCmpListBox();
void BuildFOOTPRINTS_LISTBOX(); void BuildFOOTPRINTS_LISTBOX();
void BuildLIBRARY_LISTBOX(); void BuildLIBRARY_LISTBOX();
...@@ -292,6 +294,17 @@ public: ...@@ -292,6 +294,17 @@ public:
COMPONENT* GetSelectedComponent(); COMPONENT* GetSelectedComponent();
private:
/**
* read the .equ files and populate the list of equvalents
* @param aList the list to populate
* @param aErrorMessages is a pointer to a wxString to store error messages
* (can be NULL)
* @return the error count ( 0 = no error)
*/
int buildEquivalenceList( FOOTPRINT_EQUIVALENCE_LIST& aList, wxString * aErrorMessages = NULL );
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
}; };
......
...@@ -247,7 +247,7 @@ PCB_CALCULATOR_FRAME_BASE::PCB_CALCULATOR_FRAME_BASE( wxWindow* parent, wxWindow ...@@ -247,7 +247,7 @@ PCB_CALCULATOR_FRAME_BASE::PCB_CALCULATOR_FRAME_BASE( wxWindow* parent, wxWindow
m_panelRegulators->SetSizer( bSizerMainReg ); m_panelRegulators->SetSizer( bSizerMainReg );
m_panelRegulators->Layout(); m_panelRegulators->Layout();
bSizerMainReg->Fit( m_panelRegulators ); bSizerMainReg->Fit( m_panelRegulators );
m_Notebook->AddPage( m_panelRegulators, _("Regulators"), true ); m_Notebook->AddPage( m_panelRegulators, _("Regulators"), false );
m_panelTrackWidth = new wxPanel( m_Notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); m_panelTrackWidth = new wxPanel( m_Notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bSizerTrackWidth; wxBoxSizer* bSizerTrackWidth;
bSizerTrackWidth = new wxBoxSizer( wxHORIZONTAL ); bSizerTrackWidth = new wxBoxSizer( wxHORIZONTAL );
...@@ -593,7 +593,7 @@ PCB_CALCULATOR_FRAME_BASE::PCB_CALCULATOR_FRAME_BASE( wxWindow* parent, wxWindow ...@@ -593,7 +593,7 @@ PCB_CALCULATOR_FRAME_BASE::PCB_CALCULATOR_FRAME_BASE( wxWindow* parent, wxWindow
wxBoxSizer* bLeftSizer; wxBoxSizer* bLeftSizer;
bLeftSizer = new wxBoxSizer( wxVERTICAL ); bLeftSizer = new wxBoxSizer( wxVERTICAL );
wxString m_TranslineSelectionChoices[] = { _("Microstrip Line"), _("Coplanar wave guide"), _("Grounded Coplanar wave guide"), _("Rectangular Waveguide"), _("Coaxial Line"), _("Coupled Microstrip Line"), _("Stripline"), _("Twisted Pair") }; wxString m_TranslineSelectionChoices[] = { _("Microstrip Line"), _("Coplanar wave guide"), _("Coplanar wave guide with ground plane"), _("Rectangular Waveguide"), _("Coaxial Line"), _("Coupled Microstrip Line"), _("Stripline"), _("Twisted Pair") };
int m_TranslineSelectionNChoices = sizeof( m_TranslineSelectionChoices ) / sizeof( wxString ); int m_TranslineSelectionNChoices = sizeof( m_TranslineSelectionChoices ) / sizeof( wxString );
m_TranslineSelection = new wxRadioBox( m_panelTransline, wxID_ANY, _("Transmission Line Type:"), wxDefaultPosition, wxDefaultSize, m_TranslineSelectionNChoices, m_TranslineSelectionChoices, 1, wxRA_SPECIFY_COLS ); m_TranslineSelection = new wxRadioBox( m_panelTransline, wxID_ANY, _("Transmission Line Type:"), wxDefaultPosition, wxDefaultSize, m_TranslineSelectionNChoices, m_TranslineSelectionChoices, 1, wxRA_SPECIFY_COLS );
m_TranslineSelection->SetSelection( 0 ); m_TranslineSelection->SetSelection( 0 );
...@@ -998,7 +998,7 @@ PCB_CALCULATOR_FRAME_BASE::PCB_CALCULATOR_FRAME_BASE( wxWindow* parent, wxWindow ...@@ -998,7 +998,7 @@ PCB_CALCULATOR_FRAME_BASE::PCB_CALCULATOR_FRAME_BASE( wxWindow* parent, wxWindow
m_panelTransline->SetSizer( bSizeTransline ); m_panelTransline->SetSizer( bSizeTransline );
m_panelTransline->Layout(); m_panelTransline->Layout();
bSizeTransline->Fit( m_panelTransline ); bSizeTransline->Fit( m_panelTransline );
m_Notebook->AddPage( m_panelTransline, _("TransLine"), false ); m_Notebook->AddPage( m_panelTransline, _("TransLine"), true );
m_panelAttenuators = new wxPanel( m_Notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); m_panelAttenuators = new wxPanel( m_Notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxStaticBoxSizer* sbSizerAtt; wxStaticBoxSizer* sbSizerAtt;
sbSizerAtt = new wxStaticBoxSizer( new wxStaticBox( m_panelAttenuators, wxID_ANY, _("label") ), wxHORIZONTAL ); sbSizerAtt = new wxStaticBoxSizer( new wxStaticBox( m_panelAttenuators, wxID_ANY, _("label") ), wxHORIZONTAL );
......
...@@ -270,7 +270,7 @@ ...@@ -270,7 +270,7 @@
<object class="notebookpage" expanded="1"> <object class="notebookpage" expanded="1">
<property name="bitmap"></property> <property name="bitmap"></property>
<property name="label">Regulators</property> <property name="label">Regulators</property>
<property name="select">1</property> <property name="select">0</property>
<object class="wxPanel" expanded="1"> <object class="wxPanel" expanded="1">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
<property name="LeftDockable">1</property> <property name="LeftDockable">1</property>
...@@ -8181,7 +8181,7 @@ ...@@ -8181,7 +8181,7 @@
<object class="notebookpage" expanded="1"> <object class="notebookpage" expanded="1">
<property name="bitmap"></property> <property name="bitmap"></property>
<property name="label">TransLine</property> <property name="label">TransLine</property>
<property name="select">0</property> <property name="select">1</property>
<object class="wxPanel" expanded="1"> <object class="wxPanel" expanded="1">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
<property name="LeftDockable">1</property> <property name="LeftDockable">1</property>
...@@ -8288,7 +8288,7 @@ ...@@ -8288,7 +8288,7 @@
<property name="caption"></property> <property name="caption"></property>
<property name="caption_visible">1</property> <property name="caption_visible">1</property>
<property name="center_pane">0</property> <property name="center_pane">0</property>
<property name="choices">&quot;Microstrip Line&quot; &quot;Coplanar wave guide&quot; &quot;Grounded Coplanar wave guide&quot; &quot;Rectangular Waveguide&quot; &quot;Coaxial Line&quot; &quot;Coupled Microstrip Line&quot; &quot;Stripline&quot; &quot;Twisted Pair&quot;</property> <property name="choices">&quot;Microstrip Line&quot; &quot;Coplanar wave guide&quot; &quot;Coplanar wave guide with ground plane&quot; &quot;Rectangular Waveguide&quot; &quot;Coaxial Line&quot; &quot;Coupled Microstrip Line&quot; &quot;Stripline&quot; &quot;Twisted Pair&quot;</property>
<property name="close_button">1</property> <property name="close_button">1</property>
<property name="context_help"></property> <property name="context_help"></property>
<property name="context_menu">1</property> <property name="context_menu">1</property>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment