2012-10-15 22:30:01 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
2013-10-23 18:56:03 +00:00
|
|
|
* Copyright (C) 2013 CERN
|
2016-10-28 13:11:23 +00:00
|
|
|
* Copyright (C) 2012-2016 KiCad Developers, see change_log.txt for contributors.
|
2012-10-15 22:30:01 +00:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2013-01-21 03:12:16 +00:00
|
|
|
/* TODO:
|
|
|
|
|
2013-10-13 21:33:58 +00:00
|
|
|
*) After any change to uri, reparse the environment variables.
|
2013-01-21 03:27:01 +00:00
|
|
|
|
2013-01-21 03:12:16 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <set>
|
2013-10-23 18:56:03 +00:00
|
|
|
#include <wx/regex.h>
|
2013-01-21 03:12:16 +00:00
|
|
|
|
2012-10-16 06:56:57 +00:00
|
|
|
#include <fctsys.h>
|
* KIWAY Milestone A): Make major modules into DLL/DSOs.
! The initial testing of this commit should be done using a Debug build so that
all the wxASSERT()s are enabled. Also, be sure and keep enabled the
USE_KIWAY_DLLs option. The tree won't likely build without it. Turning it
off is senseless anyways. If you want stable code, go back to a prior version,
the one tagged with "stable".
* Relocate all functionality out of the wxApp derivative into more finely
targeted purposes:
a) DLL/DSO specific
b) PROJECT specific
c) EXE or process specific
d) configuration file specific data
e) configuration file manipulations functions.
All of this functionality was blended into an extremely large wxApp derivative
and that was incompatible with the desire to support multiple concurrently
loaded DLL/DSO's ("KIFACE")s and multiple concurrently open projects.
An amazing amount of organization come from simply sorting each bit of
functionality into the proper box.
* Switch to wxConfigBase from wxConfig everywhere except instantiation.
* Add classes KIWAY, KIFACE, KIFACE_I, SEARCH_STACK, PGM_BASE, PGM_KICAD,
PGM_SINGLE_TOP,
* Remove "Return" prefix on many function names.
* Remove obvious comments from CMakeLists.txt files, and from else() and endif()s.
* Fix building boost for use in a DSO on linux.
* Remove some of the assumptions in the CMakeLists.txt files that windows had
to be the host platform when building windows binaries.
* Reduce the number of wxStrings being constructed at program load time via
static construction.
* Pass wxConfigBase* to all SaveSettings() and LoadSettings() functions so that
these functions are useful even when the wxConfigBase comes from another
source, as is the case in the KICAD_MANAGER_FRAME.
* Move the setting of the KIPRJMOD environment variable into class PROJECT,
so that it can be moved into a project variable soon, and out of FP_LIB_TABLE.
* Add the KIWAY_PLAYER which is associated with a particular PROJECT, and all
its child wxFrames and wxDialogs now have a Kiway() member function which
returns a KIWAY& that that window tree branch is in support of. This is like
wxWindows DNA in that child windows get this member with proper value at time
of construction.
* Anticipate some of the needs for milestones B) and C) and make code
adjustments now in an effort to reduce work in those milestones.
* No testing has been done for python scripting, since milestone C) has that
being largely reworked and re-thought-out.
2014-03-20 00:42:08 +00:00
|
|
|
#include <project.h>
|
2014-08-24 07:05:07 +00:00
|
|
|
#include <3d_viewer.h> // for KISYS3DMOD
|
2012-10-15 22:30:01 +00:00
|
|
|
#include <dialog_fp_lib_table_base.h>
|
|
|
|
#include <fp_lib_table.h>
|
2016-11-20 23:35:08 +00:00
|
|
|
#include <lib_table_lexer.h>
|
2013-10-13 21:33:58 +00:00
|
|
|
#include <invoke_pcb_dialog.h>
|
2013-10-23 18:56:03 +00:00
|
|
|
#include <grid_tricks.h>
|
2013-11-20 16:35:03 +00:00
|
|
|
#include <confirm.h>
|
2014-12-21 14:13:14 +00:00
|
|
|
#include <wizard_add_fplib.h>
|
|
|
|
|
2013-09-24 21:23:13 +00:00
|
|
|
|
|
|
|
/// grid column order is established by this sequence
|
|
|
|
enum COL_ORDER
|
|
|
|
{
|
|
|
|
COL_NICKNAME,
|
|
|
|
COL_URI,
|
|
|
|
COL_TYPE,
|
|
|
|
COL_OPTIONS,
|
|
|
|
COL_DESCR,
|
|
|
|
COL_COUNT // keep as last
|
|
|
|
};
|
|
|
|
|
2012-10-17 01:00:25 +00:00
|
|
|
|
2012-10-17 15:12:17 +00:00
|
|
|
/**
|
|
|
|
* Class FP_TBL_MODEL
|
2013-10-30 15:33:51 +00:00
|
|
|
* mixes in FP_LIB_TABLE into wxGridTableBase so the result can be used
|
2012-10-18 15:28:50 +00:00
|
|
|
* as a table within wxGrid.
|
2012-10-17 15:12:17 +00:00
|
|
|
*/
|
2012-10-17 01:00:25 +00:00
|
|
|
class FP_TBL_MODEL : public wxGridTableBase, public FP_LIB_TABLE
|
|
|
|
{
|
2013-10-23 18:56:03 +00:00
|
|
|
friend class FP_GRID_TRICKS;
|
2012-10-17 01:00:25 +00:00
|
|
|
|
|
|
|
public:
|
2012-12-09 20:51:42 +00:00
|
|
|
|
2012-10-17 01:00:25 +00:00
|
|
|
/**
|
|
|
|
* Constructor FP_TBL_MODEL
|
2012-10-18 15:28:50 +00:00
|
|
|
* is a copy constructor that builds a wxGridTableBase (table model) by wrapping
|
|
|
|
* an FP_LIB_TABLE.
|
2012-10-17 01:00:25 +00:00
|
|
|
*/
|
2016-11-19 22:15:34 +00:00
|
|
|
FP_TBL_MODEL( const FP_LIB_TABLE& aTableToEdit )
|
2012-10-17 01:00:25 +00:00
|
|
|
{
|
2016-11-19 22:15:34 +00:00
|
|
|
rows = aTableToEdit.rows;
|
2012-10-17 01:00:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//-----<wxGridTableBase overloads>-------------------------------------------
|
|
|
|
|
2016-09-25 17:06:49 +00:00
|
|
|
int GetNumberRows() override { return rows.size(); }
|
|
|
|
int GetNumberCols() override { return COL_COUNT; }
|
2012-10-17 01:00:25 +00:00
|
|
|
|
2016-09-25 17:06:49 +00:00
|
|
|
wxString GetValue( int aRow, int aCol ) override
|
2012-10-17 01:00:25 +00:00
|
|
|
{
|
|
|
|
if( unsigned( aRow ) < rows.size() )
|
|
|
|
{
|
2016-11-19 22:15:34 +00:00
|
|
|
const LIB_TABLE_ROW* r = &rows[aRow];
|
2012-10-17 01:00:25 +00:00
|
|
|
|
|
|
|
switch( aCol )
|
|
|
|
{
|
2016-11-19 22:15:34 +00:00
|
|
|
case COL_NICKNAME: return r->GetNickName();
|
|
|
|
case COL_URI: return r->GetFullURI();
|
|
|
|
case COL_TYPE: return r->GetType();
|
|
|
|
case COL_OPTIONS: return r->GetOptions();
|
|
|
|
case COL_DESCR: return r->GetDescr();
|
2012-10-17 01:00:25 +00:00
|
|
|
default:
|
|
|
|
; // fall thru to wxEmptyString
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return wxEmptyString;
|
|
|
|
}
|
|
|
|
|
2016-09-25 17:06:49 +00:00
|
|
|
void SetValue( int aRow, int aCol, const wxString &aValue ) override
|
2012-10-17 01:00:25 +00:00
|
|
|
{
|
|
|
|
if( unsigned( aRow ) < rows.size() )
|
|
|
|
{
|
2016-11-19 22:15:34 +00:00
|
|
|
LIB_TABLE_ROW* r = &rows[aRow];
|
2012-10-17 01:00:25 +00:00
|
|
|
|
|
|
|
switch( aCol )
|
|
|
|
{
|
2016-11-19 22:15:34 +00:00
|
|
|
case COL_NICKNAME: r->SetNickName( aValue ); break;
|
|
|
|
case COL_URI: r->SetFullURI( aValue ); break;
|
|
|
|
case COL_TYPE: r->SetType( aValue ); break;
|
|
|
|
case COL_OPTIONS: r->SetOptions( aValue ); break;
|
|
|
|
case COL_DESCR: r->SetDescr( aValue ); break;
|
2012-10-17 01:00:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-25 17:06:49 +00:00
|
|
|
bool IsEmptyCell( int aRow, int aCol ) override
|
2012-10-17 01:00:25 +00:00
|
|
|
{
|
2013-10-23 18:56:03 +00:00
|
|
|
return !GetValue( aRow, aCol );
|
2012-10-17 01:00:25 +00:00
|
|
|
}
|
|
|
|
|
2016-09-25 17:06:49 +00:00
|
|
|
bool InsertRows( size_t aPos = 0, size_t aNumRows = 1 ) override
|
2012-10-17 01:00:25 +00:00
|
|
|
{
|
|
|
|
if( aPos < rows.size() )
|
|
|
|
{
|
2016-11-19 22:15:34 +00:00
|
|
|
for( size_t i = 0; i < aNumRows; i++ )
|
|
|
|
{
|
|
|
|
rows.insert( rows.begin() + i,
|
|
|
|
dynamic_cast< LIB_TABLE_ROW* >( new FP_LIB_TABLE_ROW ) );
|
|
|
|
}
|
2012-10-18 15:28:50 +00:00
|
|
|
|
|
|
|
// use the (wxGridStringTable) source Luke.
|
|
|
|
if( GetView() )
|
|
|
|
{
|
|
|
|
wxGridTableMessage msg( this,
|
|
|
|
wxGRIDTABLE_NOTIFY_ROWS_INSERTED,
|
|
|
|
aPos,
|
|
|
|
aNumRows );
|
|
|
|
|
|
|
|
GetView()->ProcessTableMessage( msg );
|
|
|
|
}
|
|
|
|
|
2012-10-17 01:00:25 +00:00
|
|
|
return true;
|
|
|
|
}
|
2016-11-19 22:15:34 +00:00
|
|
|
|
2012-10-17 01:00:25 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-09-25 17:06:49 +00:00
|
|
|
bool AppendRows( size_t aNumRows = 1 ) override
|
2012-10-17 01:00:25 +00:00
|
|
|
{
|
2012-10-18 15:28:50 +00:00
|
|
|
// do not modify aNumRows, original value needed for wxGridTableMessage below
|
|
|
|
for( int i = aNumRows; i; --i )
|
2016-11-19 22:15:34 +00:00
|
|
|
rows.push_back( new FP_LIB_TABLE_ROW );
|
2012-10-18 15:28:50 +00:00
|
|
|
|
|
|
|
if( GetView() )
|
|
|
|
{
|
|
|
|
wxGridTableMessage msg( this,
|
|
|
|
wxGRIDTABLE_NOTIFY_ROWS_APPENDED,
|
|
|
|
aNumRows );
|
|
|
|
|
|
|
|
GetView()->ProcessTableMessage( msg );
|
|
|
|
}
|
|
|
|
|
2012-10-17 01:00:25 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-09-25 17:06:49 +00:00
|
|
|
bool DeleteRows( size_t aPos, size_t aNumRows ) override
|
2012-10-17 01:00:25 +00:00
|
|
|
{
|
2014-05-21 06:06:52 +00:00
|
|
|
// aPos may be a large positive, e.g. size_t(-1), and the sum of
|
|
|
|
// aPos+aNumRows may wrap here, so both ends of the range are tested.
|
|
|
|
if( aPos < rows.size() && aPos + aNumRows <= rows.size() )
|
2012-10-17 01:00:25 +00:00
|
|
|
{
|
2016-11-19 22:15:34 +00:00
|
|
|
LIB_TABLE_ROWS_ITER start = rows.begin() + aPos;
|
2012-10-17 01:00:25 +00:00
|
|
|
rows.erase( start, start + aNumRows );
|
2012-10-18 15:28:50 +00:00
|
|
|
|
|
|
|
if( GetView() )
|
|
|
|
{
|
|
|
|
wxGridTableMessage msg( this,
|
|
|
|
wxGRIDTABLE_NOTIFY_ROWS_DELETED,
|
|
|
|
aPos,
|
|
|
|
aNumRows );
|
|
|
|
|
|
|
|
GetView()->ProcessTableMessage( msg );
|
|
|
|
}
|
|
|
|
|
2012-10-17 01:00:25 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-11-19 22:15:34 +00:00
|
|
|
return false;
|
2012-10-17 01:00:25 +00:00
|
|
|
}
|
|
|
|
|
2016-09-25 17:06:49 +00:00
|
|
|
wxString GetColLabelValue( int aCol ) override
|
2012-10-17 01:00:25 +00:00
|
|
|
{
|
|
|
|
switch( aCol )
|
|
|
|
{
|
2012-12-09 20:51:42 +00:00
|
|
|
case COL_NICKNAME: return _( "Nickname" );
|
|
|
|
case COL_URI: return _( "Library Path" );
|
2013-01-21 03:12:16 +00:00
|
|
|
|
2013-11-12 00:17:27 +00:00
|
|
|
// keep this "Plugin Type" text fairly long so column is sized wide enough
|
2013-01-21 03:12:16 +00:00
|
|
|
case COL_TYPE: return _( "Plugin Type" );
|
2012-12-09 20:51:42 +00:00
|
|
|
case COL_OPTIONS: return _( "Options" );
|
|
|
|
case COL_DESCR: return _( "Description" );
|
|
|
|
default: return wxEmptyString;
|
2012-10-17 01:00:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----</wxGridTableBase overloads>------------------------------------------
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-10-23 18:56:03 +00:00
|
|
|
class FP_GRID_TRICKS : public GRID_TRICKS
|
2012-10-15 22:30:01 +00:00
|
|
|
{
|
2013-10-23 18:56:03 +00:00
|
|
|
public:
|
|
|
|
FP_GRID_TRICKS( wxGrid* aGrid ) :
|
|
|
|
GRID_TRICKS( aGrid )
|
2012-10-18 15:28:50 +00:00
|
|
|
{
|
2013-10-23 18:56:03 +00:00
|
|
|
}
|
2012-10-18 15:28:50 +00:00
|
|
|
|
2013-10-23 18:56:03 +00:00
|
|
|
protected:
|
2012-12-09 20:51:42 +00:00
|
|
|
|
2013-10-23 18:56:03 +00:00
|
|
|
/// handle specialized clipboard text, with leading "(fp_lib_table", OR
|
|
|
|
/// spreadsheet formatted text.
|
2016-09-25 17:06:49 +00:00
|
|
|
virtual void paste_text( const wxString& cb_text ) override
|
2013-10-23 18:56:03 +00:00
|
|
|
{
|
|
|
|
FP_TBL_MODEL* tbl = (FP_TBL_MODEL*) m_grid->GetTable();
|
2012-12-09 20:51:42 +00:00
|
|
|
|
2016-10-28 13:11:23 +00:00
|
|
|
size_t ndx = cb_text.find( "(fp_lib_table" );
|
2012-10-18 15:28:50 +00:00
|
|
|
|
2013-10-23 18:56:03 +00:00
|
|
|
if( ndx != std::string::npos )
|
2012-12-09 20:51:42 +00:00
|
|
|
{
|
2016-10-28 13:11:23 +00:00
|
|
|
// paste the FP_LIB_TABLE_ROWs of s-expression (fp_lib_table), starting
|
2013-10-23 18:56:03 +00:00
|
|
|
// at column 0 regardless of current cursor column.
|
2012-10-18 15:28:50 +00:00
|
|
|
|
2016-10-28 13:11:23 +00:00
|
|
|
STRING_LINE_READER slr( TO_UTF8( cb_text ), "Clipboard" );
|
2016-11-20 23:35:08 +00:00
|
|
|
LIB_TABLE_LEXER lexer( &slr );
|
2013-10-23 18:56:03 +00:00
|
|
|
FP_LIB_TABLE tmp_tbl;
|
|
|
|
bool parsed = true;
|
2012-12-09 20:51:42 +00:00
|
|
|
|
2013-10-23 18:56:03 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
tmp_tbl.Parse( &lexer );
|
|
|
|
}
|
|
|
|
catch( PARSE_ERROR& pe )
|
|
|
|
{
|
2016-09-14 22:36:45 +00:00
|
|
|
DisplayError( NULL, pe.What() );
|
2013-10-23 18:56:03 +00:00
|
|
|
parsed = false;
|
|
|
|
}
|
2012-12-09 20:51:42 +00:00
|
|
|
|
2013-10-23 18:56:03 +00:00
|
|
|
if( parsed )
|
|
|
|
{
|
|
|
|
const int cur_row = std::max( getCursorRow(), 0 );
|
2012-12-09 20:51:42 +00:00
|
|
|
|
2013-10-23 18:56:03 +00:00
|
|
|
// if clipboard rows would extend past end of current table size...
|
|
|
|
if( tmp_tbl.GetCount() > tbl->GetNumberRows() - cur_row )
|
|
|
|
{
|
|
|
|
int newRowsNeeded = tmp_tbl.GetCount() - ( tbl->GetNumberRows() - cur_row );
|
|
|
|
tbl->AppendRows( newRowsNeeded );
|
|
|
|
}
|
2012-12-09 20:51:42 +00:00
|
|
|
|
2013-10-23 18:56:03 +00:00
|
|
|
for( int i = 0; i < tmp_tbl.GetCount(); ++i )
|
|
|
|
{
|
2016-11-19 22:15:34 +00:00
|
|
|
tbl->rows.replace( cur_row+i, tmp_tbl.At( i ) );
|
2013-10-23 18:56:03 +00:00
|
|
|
}
|
|
|
|
}
|
2016-11-19 22:15:34 +00:00
|
|
|
|
2013-10-23 18:56:03 +00:00
|
|
|
m_grid->AutoSizeColumns( false );
|
|
|
|
}
|
|
|
|
else
|
2012-12-09 20:51:42 +00:00
|
|
|
{
|
2013-10-23 18:56:03 +00:00
|
|
|
// paste spreadsheet formatted text.
|
|
|
|
GRID_TRICKS::paste_text( cb_text );
|
2012-12-09 20:51:42 +00:00
|
|
|
}
|
2013-10-23 18:56:03 +00:00
|
|
|
}
|
|
|
|
};
|
2012-12-09 20:51:42 +00:00
|
|
|
|
|
|
|
|
2012-10-15 22:30:01 +00:00
|
|
|
/**
|
|
|
|
* Class DIALOG_FP_LIB_TABLE
|
|
|
|
* shows and edits the PCB library tables. Two tables are expected, one global
|
|
|
|
* and one project specific.
|
|
|
|
*/
|
|
|
|
class DIALOG_FP_LIB_TABLE : public DIALOG_FP_LIB_TABLE_BASE
|
|
|
|
{
|
2013-10-30 15:33:51 +00:00
|
|
|
|
|
|
|
public:
|
|
|
|
DIALOG_FP_LIB_TABLE( wxTopLevelWindow* aParent, FP_LIB_TABLE* aGlobal, FP_LIB_TABLE* aProject ) :
|
|
|
|
DIALOG_FP_LIB_TABLE_BASE( aParent ),
|
|
|
|
m_global( aGlobal ),
|
|
|
|
m_project( aProject )
|
|
|
|
{
|
2015-01-01 15:46:11 +00:00
|
|
|
// For user info, shows the table filenames:
|
|
|
|
m_PrjTableFilename->SetLabel( Prj().FootprintLibTblName() );
|
|
|
|
m_GblTableFilename->SetLabel( FP_LIB_TABLE::GetGlobalTableFileName() );
|
|
|
|
|
2013-10-30 15:33:51 +00:00
|
|
|
// wxGrid only supports user owned tables if they exist past end of ~wxGrid(),
|
|
|
|
// so make it a grid owned table.
|
|
|
|
m_global_grid->SetTable( new FP_TBL_MODEL( *aGlobal ), true );
|
|
|
|
m_project_grid->SetTable( new FP_TBL_MODEL( *aProject ), true );
|
|
|
|
|
|
|
|
// add Cut, Copy, and Paste to wxGrids
|
|
|
|
m_global_grid->PushEventHandler( new FP_GRID_TRICKS( m_global_grid ) );
|
|
|
|
m_project_grid->PushEventHandler( new FP_GRID_TRICKS( m_project_grid ) );
|
|
|
|
|
|
|
|
m_global_grid->AutoSizeColumns( false );
|
|
|
|
m_project_grid->AutoSizeColumns( false );
|
|
|
|
|
|
|
|
wxArrayString choices;
|
|
|
|
|
|
|
|
choices.Add( IO_MGR::ShowType( IO_MGR::KICAD ) );
|
|
|
|
choices.Add( IO_MGR::ShowType( IO_MGR::GITHUB ) );
|
|
|
|
choices.Add( IO_MGR::ShowType( IO_MGR::LEGACY ) );
|
|
|
|
choices.Add( IO_MGR::ShowType( IO_MGR::EAGLE ) );
|
|
|
|
choices.Add( IO_MGR::ShowType( IO_MGR::GEDA_PCB ) );
|
|
|
|
|
|
|
|
/* PCAD_PLUGIN does not support Footprint*() functions
|
|
|
|
choices.Add( IO_MGR::ShowType( IO_MGR::GITHUB ) );
|
|
|
|
*/
|
|
|
|
|
|
|
|
wxGridCellAttr* attr;
|
|
|
|
|
|
|
|
attr = new wxGridCellAttr;
|
|
|
|
attr->SetEditor( new wxGridCellChoiceEditor( choices ) );
|
|
|
|
m_project_grid->SetColAttr( COL_TYPE, attr );
|
|
|
|
|
|
|
|
attr = new wxGridCellAttr;
|
|
|
|
attr->SetEditor( new wxGridCellChoiceEditor( choices ) );
|
|
|
|
m_global_grid->SetColAttr( COL_TYPE, attr );
|
|
|
|
|
2013-11-12 20:49:17 +00:00
|
|
|
populateEnvironReadOnlyTable();
|
2013-10-30 15:33:51 +00:00
|
|
|
|
2013-11-12 20:49:17 +00:00
|
|
|
for( int i=0; i<2; ++i )
|
|
|
|
{
|
|
|
|
wxGrid* g = i==0 ? m_global_grid : m_project_grid;
|
2013-10-30 15:33:51 +00:00
|
|
|
|
2013-11-12 20:49:17 +00:00
|
|
|
// all but COL_OPTIONS, which is edited with Option Editor anyways.
|
2013-11-19 17:24:45 +00:00
|
|
|
g->AutoSizeColumn( COL_NICKNAME, false );
|
2013-11-12 20:49:17 +00:00
|
|
|
g->AutoSizeColumn( COL_TYPE, false );
|
|
|
|
g->AutoSizeColumn( COL_URI, false );
|
|
|
|
g->AutoSizeColumn( COL_DESCR, false );
|
2013-10-30 15:33:51 +00:00
|
|
|
|
2013-11-19 17:24:45 +00:00
|
|
|
// would set this to width of title, if it was easily known.
|
2013-11-12 20:49:17 +00:00
|
|
|
g->SetColSize( COL_OPTIONS, 80 );
|
|
|
|
}
|
|
|
|
|
|
|
|
// This scrunches the dialog hideously, probably due to wxAUI container.
|
|
|
|
// Fit();
|
|
|
|
// We derive from DIALOG_SHIM so prior size will be used anyways.
|
2013-10-30 15:33:51 +00:00
|
|
|
|
2014-09-22 07:51:06 +00:00
|
|
|
// select the last selected page
|
2014-09-22 09:37:22 +00:00
|
|
|
m_auinotebook->SetSelection( m_pageNdx );
|
2014-09-22 07:51:06 +00:00
|
|
|
|
2013-10-30 15:33:51 +00:00
|
|
|
// fire pageChangedHandler() so m_cur_grid gets set
|
2014-09-22 09:37:22 +00:00
|
|
|
// m_auinotebook->SetSelection will generate a pageChangedHandler()
|
|
|
|
// event call later, but too late.
|
2013-10-30 15:33:51 +00:00
|
|
|
wxAuiNotebookEvent uneventful;
|
|
|
|
pageChangedHandler( uneventful );
|
|
|
|
|
2014-12-21 14:13:14 +00:00
|
|
|
// Gives a selection for each grid, mainly for delete lib button.
|
|
|
|
// Without that, we do not see what lib will be deleted
|
2016-11-19 22:15:34 +00:00
|
|
|
m_global_grid->SelectRow( 0 );
|
|
|
|
m_project_grid->SelectRow( 0 );
|
2014-12-21 14:13:14 +00:00
|
|
|
|
2013-10-30 15:33:51 +00:00
|
|
|
// for ALT+A handling, we want the initial focus to be on the first selected grid.
|
|
|
|
m_cur_grid->SetFocus();
|
2015-03-14 16:47:25 +00:00
|
|
|
|
|
|
|
// On some windows manager (Unity, XFCE), this dialog is
|
|
|
|
// not always raised, depending on this dialog is run.
|
|
|
|
// Force it to be raised
|
|
|
|
Raise();
|
2013-10-30 15:33:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
~DIALOG_FP_LIB_TABLE()
|
|
|
|
{
|
|
|
|
// Delete the GRID_TRICKS.
|
|
|
|
// Any additional event handlers should be popped before the window is deleted.
|
|
|
|
m_global_grid->PopEventHandler( true );
|
|
|
|
m_project_grid->PopEventHandler( true );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
2016-10-28 13:11:23 +00:00
|
|
|
typedef FP_LIB_TABLE_ROW ROW;
|
2012-12-09 20:51:42 +00:00
|
|
|
|
2013-10-22 19:29:37 +00:00
|
|
|
/// If the cursor is not on a valid cell, because there are no rows at all, return -1,
|
|
|
|
/// else return a 0 based column index.
|
2013-10-22 14:29:48 +00:00
|
|
|
int getCursorCol() const
|
2013-10-05 10:34:55 +00:00
|
|
|
{
|
2013-10-22 14:29:48 +00:00
|
|
|
return m_cur_grid->GetGridCursorCol();
|
2012-12-09 20:51:42 +00:00
|
|
|
}
|
|
|
|
|
2013-10-22 19:29:37 +00:00
|
|
|
/// If the cursor is not on a valid cell, because there are no rows at all, return -1,
|
|
|
|
/// else return a 0 based row index.
|
2013-10-22 14:29:48 +00:00
|
|
|
int getCursorRow() const
|
2012-12-09 20:51:42 +00:00
|
|
|
{
|
2013-10-22 14:29:48 +00:00
|
|
|
return m_cur_grid->GetGridCursorRow();
|
2013-10-05 10:34:55 +00:00
|
|
|
}
|
2012-12-09 20:51:42 +00:00
|
|
|
|
2013-09-24 21:23:13 +00:00
|
|
|
/**
|
|
|
|
* Function verifyTables
|
|
|
|
* trims important fields, removes blank row entries, and checks for duplicates.
|
|
|
|
* @return bool - true if tables are OK, else false.
|
|
|
|
*/
|
|
|
|
bool verifyTables()
|
|
|
|
{
|
|
|
|
for( int t=0; t<2; ++t )
|
2012-12-09 20:51:42 +00:00
|
|
|
{
|
2013-10-30 15:33:51 +00:00
|
|
|
FP_TBL_MODEL& model = t==0 ? *global_model() : *project_model();
|
2013-09-24 21:23:13 +00:00
|
|
|
|
|
|
|
for( int r = 0; r < model.GetNumberRows(); )
|
2012-12-09 20:51:42 +00:00
|
|
|
{
|
2013-09-24 21:23:13 +00:00
|
|
|
wxString nick = model.GetValue( r, COL_NICKNAME ).Trim( false ).Trim();
|
|
|
|
wxString uri = model.GetValue( r, COL_URI ).Trim( false ).Trim();
|
2012-12-09 20:51:42 +00:00
|
|
|
|
2013-09-25 19:17:06 +00:00
|
|
|
if( !nick || !uri )
|
2012-12-09 20:51:42 +00:00
|
|
|
{
|
2013-09-25 19:17:06 +00:00
|
|
|
// Delete the "empty" row, where empty means missing nick or uri.
|
2013-09-24 21:23:13 +00:00
|
|
|
// This also updates the UI which could be slow, but there should only be a few
|
|
|
|
// rows to delete, unless the user fell asleep on the Add Row
|
|
|
|
// button.
|
|
|
|
model.DeleteRows( r, 1 );
|
|
|
|
}
|
|
|
|
else if( nick.find(':') != size_t(-1) )
|
|
|
|
{
|
|
|
|
wxString msg = wxString::Format(
|
|
|
|
_( "Illegal character '%s' found in Nickname: '%s' in row %d" ),
|
2016-10-28 13:11:23 +00:00
|
|
|
":", GetChars( nick ), r );
|
2012-12-09 20:51:42 +00:00
|
|
|
|
2013-09-24 21:23:13 +00:00
|
|
|
// show the tabbed panel holding the grid we have flunked:
|
2013-10-30 15:33:51 +00:00
|
|
|
if( &model != cur_model() )
|
2013-09-24 21:23:13 +00:00
|
|
|
{
|
2013-10-30 15:33:51 +00:00
|
|
|
m_auinotebook->SetSelection( &model == global_model() ? 0 : 1 );
|
2012-12-09 20:51:42 +00:00
|
|
|
}
|
|
|
|
|
2013-09-25 19:17:06 +00:00
|
|
|
// go to the problematic row
|
2013-10-13 21:33:58 +00:00
|
|
|
m_cur_grid->SetGridCursor( r, 0 );
|
2013-09-24 21:23:13 +00:00
|
|
|
m_cur_grid->SelectBlock( r, 0, r, 0 );
|
|
|
|
m_cur_grid->MakeCellVisible( r, 0 );
|
2012-12-09 20:51:42 +00:00
|
|
|
|
2013-09-24 21:23:13 +00:00
|
|
|
wxMessageDialog errdlg( this, msg, _( "No Colon in Nicknames" ) );
|
|
|
|
errdlg.ShowModal();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else
|
2012-12-09 20:51:42 +00:00
|
|
|
{
|
2013-09-24 21:23:13 +00:00
|
|
|
// set the trimmed values back into the table so they get saved to disk.
|
|
|
|
model.SetValue( r, COL_NICKNAME, nick );
|
|
|
|
model.SetValue( r, COL_URI, uri );
|
|
|
|
++r; // this row was OK.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-12-09 20:51:42 +00:00
|
|
|
|
2013-09-24 21:23:13 +00:00
|
|
|
// check for duplicate nickNames, separately in each table.
|
|
|
|
for( int t=0; t<2; ++t )
|
|
|
|
{
|
2013-10-30 15:33:51 +00:00
|
|
|
FP_TBL_MODEL& model = t==0 ? *global_model() : *project_model();
|
2012-12-09 20:51:42 +00:00
|
|
|
|
2013-09-24 21:23:13 +00:00
|
|
|
for( int r1 = 0; r1 < model.GetNumberRows() - 1; ++r1 )
|
|
|
|
{
|
2013-09-25 19:17:06 +00:00
|
|
|
wxString nick1 = model.GetValue( r1, COL_NICKNAME );
|
2012-12-09 20:51:42 +00:00
|
|
|
|
2013-09-24 21:23:13 +00:00
|
|
|
for( int r2=r1+1; r2 < model.GetNumberRows(); ++r2 )
|
|
|
|
{
|
|
|
|
wxString nick2 = model.GetValue( r2, COL_NICKNAME );
|
2012-12-21 05:29:40 +00:00
|
|
|
|
2013-09-24 21:23:13 +00:00
|
|
|
if( nick1 == nick2 )
|
2012-12-09 20:51:42 +00:00
|
|
|
{
|
2013-09-24 21:23:13 +00:00
|
|
|
wxString msg = wxString::Format(
|
|
|
|
_( "Duplicate Nickname: '%s' in rows %d and %d" ),
|
|
|
|
GetChars( nick1 ), r1+1, r2+1
|
|
|
|
);
|
2012-12-09 20:51:42 +00:00
|
|
|
|
2013-09-24 21:23:13 +00:00
|
|
|
// show the tabbed panel holding the grid we have flunked:
|
2013-10-30 15:33:51 +00:00
|
|
|
if( &model != cur_model() )
|
2012-12-09 20:51:42 +00:00
|
|
|
{
|
2013-10-30 15:33:51 +00:00
|
|
|
m_auinotebook->SetSelection( &model == global_model() ? 0 : 1 );
|
2012-12-09 20:51:42 +00:00
|
|
|
}
|
2013-09-24 21:23:13 +00:00
|
|
|
|
2013-09-25 19:17:06 +00:00
|
|
|
// go to the lower of the two rows, it is technically the duplicate:
|
2013-10-13 21:33:58 +00:00
|
|
|
m_cur_grid->SetGridCursor( r2, 0 );
|
2013-09-24 21:23:13 +00:00
|
|
|
m_cur_grid->SelectBlock( r2, 0, r2, 0 );
|
|
|
|
m_cur_grid->MakeCellVisible( r2, 0 );
|
|
|
|
|
|
|
|
wxMessageDialog errdlg( this, msg, _( "Please Delete or Modify One" ) );
|
|
|
|
errdlg.ShowModal();
|
|
|
|
return false;
|
2012-12-09 20:51:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-09-24 21:23:13 +00:00
|
|
|
|
|
|
|
return true;
|
2012-10-18 15:28:50 +00:00
|
|
|
}
|
2012-10-17 15:12:17 +00:00
|
|
|
|
2012-10-16 06:56:57 +00:00
|
|
|
//-----<event handlers>----------------------------------
|
|
|
|
|
2016-09-25 17:06:49 +00:00
|
|
|
void onKeyDown( wxKeyEvent& ev ) override
|
2013-10-04 22:23:53 +00:00
|
|
|
{
|
2013-10-23 18:56:03 +00:00
|
|
|
#if 0
|
|
|
|
// send the key to the current grid
|
|
|
|
((wxEvtHandler*)m_cur_grid)->ProcessEvent( ev );
|
|
|
|
#else
|
|
|
|
// or no:
|
|
|
|
// m_cur_grid has the focus most of the time anyways, so above not needed.
|
|
|
|
ev.Skip();
|
|
|
|
#endif
|
2013-10-04 22:23:53 +00:00
|
|
|
}
|
|
|
|
|
2016-09-25 17:06:49 +00:00
|
|
|
void pageChangedHandler( wxAuiNotebookEvent& event ) override
|
2012-10-16 06:56:57 +00:00
|
|
|
{
|
2014-09-22 07:51:06 +00:00
|
|
|
m_pageNdx = m_auinotebook->GetSelection();
|
|
|
|
m_cur_grid = ( m_pageNdx == 0 ) ? m_global_grid : m_project_grid;
|
2012-10-16 06:56:57 +00:00
|
|
|
}
|
|
|
|
|
2016-09-25 17:06:49 +00:00
|
|
|
void appendRowHandler( wxCommandEvent& event ) override
|
2012-10-16 06:56:57 +00:00
|
|
|
{
|
2013-09-24 21:23:13 +00:00
|
|
|
if( m_cur_grid->AppendRows( 1 ) )
|
|
|
|
{
|
|
|
|
int last_row = m_cur_grid->GetNumberRows() - 1;
|
|
|
|
|
2013-10-30 15:33:51 +00:00
|
|
|
// wx documentation is wrong, SetGridCursor does not make visible.
|
2013-09-24 21:23:13 +00:00
|
|
|
m_cur_grid->MakeCellVisible( last_row, 0 );
|
2013-10-13 21:33:58 +00:00
|
|
|
m_cur_grid->SetGridCursor( last_row, 0 );
|
2014-12-21 14:13:14 +00:00
|
|
|
m_cur_grid->SelectRow( m_cur_grid->GetGridCursorRow() );
|
2013-09-24 21:23:13 +00:00
|
|
|
}
|
2012-10-16 06:56:57 +00:00
|
|
|
}
|
|
|
|
|
2016-09-25 17:06:49 +00:00
|
|
|
void deleteRowHandler( wxCommandEvent& event ) override
|
2012-10-16 06:56:57 +00:00
|
|
|
{
|
2014-12-21 14:13:14 +00:00
|
|
|
int currRow = getCursorRow();
|
2017-03-14 19:31:44 +00:00
|
|
|
|
|
|
|
// In a wxGrid, collect rows that have a selected cell, or are selected
|
|
|
|
// is not so easy: it depend on the way the selection was made.
|
|
|
|
// Here, we collect row selected by clicking on a row label, and
|
|
|
|
// row that contain a cell previously selected.
|
|
|
|
// If no candidate, just delete the row with the grid cursor.
|
2014-12-21 14:13:14 +00:00
|
|
|
wxArrayInt selectedRows = m_cur_grid->GetSelectedRows();
|
2017-03-14 19:31:44 +00:00
|
|
|
wxGridCellCoordsArray cells = m_cur_grid->GetSelectedCells();
|
|
|
|
|
|
|
|
// Add all row having cell selected to list:
|
|
|
|
for( unsigned ii = 0; ii < cells.GetCount(); ii++ )
|
|
|
|
selectedRows.Add( cells[ii].GetRow() );
|
2014-12-21 14:13:14 +00:00
|
|
|
|
2017-03-14 19:31:44 +00:00
|
|
|
// Use the row having the grid cursor only if we have no candidate:
|
2014-12-21 14:13:14 +00:00
|
|
|
if( selectedRows.size() == 0 && getCursorRow() >= 0 )
|
|
|
|
selectedRows.Add( getCursorRow() );
|
|
|
|
|
|
|
|
std::sort( selectedRows.begin(), selectedRows.end() );
|
|
|
|
|
2017-03-14 19:31:44 +00:00
|
|
|
// Remove selected rows (note: a row can be stored more than once in list)
|
|
|
|
int last_row = -1;
|
2014-12-21 14:13:14 +00:00
|
|
|
for( int ii = selectedRows.GetCount()-1; ii >= 0; ii-- )
|
|
|
|
{
|
|
|
|
int row = selectedRows[ii];
|
2017-03-14 19:31:44 +00:00
|
|
|
|
|
|
|
if( row != last_row )
|
|
|
|
{
|
|
|
|
last_row = row;
|
|
|
|
m_cur_grid->DeleteRows( row, 1 );
|
|
|
|
}
|
2014-12-21 14:13:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if( currRow >= m_cur_grid->GetNumberRows() )
|
|
|
|
m_cur_grid->SetGridCursor(m_cur_grid->GetNumberRows()-1, getCursorCol() );
|
|
|
|
|
|
|
|
m_cur_grid->SelectRow( m_cur_grid->GetGridCursorRow() );
|
2012-10-16 06:56:57 +00:00
|
|
|
}
|
|
|
|
|
2016-09-25 17:06:49 +00:00
|
|
|
void moveUpHandler( wxCommandEvent& event ) override
|
2012-10-16 06:56:57 +00:00
|
|
|
{
|
2016-11-19 22:15:34 +00:00
|
|
|
wxArrayInt rowsSelected = m_cur_grid->GetSelectedRows();
|
|
|
|
|
|
|
|
if( rowsSelected.GetCount() == 0 )
|
|
|
|
return;
|
|
|
|
|
|
|
|
// @todo: add multiple selection moves.
|
|
|
|
int curRow = rowsSelected[0];
|
|
|
|
|
2012-10-18 15:28:50 +00:00
|
|
|
if( curRow >= 1 )
|
|
|
|
{
|
2013-10-05 10:34:55 +00:00
|
|
|
int curCol = getCursorCol();
|
2012-10-18 15:28:50 +00:00
|
|
|
|
2013-10-30 15:33:51 +00:00
|
|
|
FP_TBL_MODEL* tbl = cur_model();
|
2012-10-18 15:28:50 +00:00
|
|
|
|
2016-11-19 22:15:34 +00:00
|
|
|
boost::ptr_vector< LIB_TABLE_ROW >::auto_type move_me =
|
|
|
|
tbl->rows.release( tbl->rows.begin() + curRow );
|
2012-10-18 15:28:50 +00:00
|
|
|
|
2012-10-31 14:41:47 +00:00
|
|
|
--curRow;
|
2016-11-19 22:15:34 +00:00
|
|
|
tbl->rows.insert( tbl->rows.begin() + curRow, move_me.release() );
|
2012-10-18 15:28:50 +00:00
|
|
|
|
|
|
|
if( tbl->GetView() )
|
|
|
|
{
|
2012-10-31 14:41:47 +00:00
|
|
|
// fire a msg to cause redrawing
|
2012-10-18 15:28:50 +00:00
|
|
|
wxGridTableMessage msg( tbl,
|
|
|
|
wxGRIDTABLE_NOTIFY_ROWS_INSERTED,
|
|
|
|
curRow,
|
|
|
|
0 );
|
|
|
|
|
|
|
|
tbl->GetView()->ProcessTableMessage( msg );
|
|
|
|
}
|
2012-10-31 14:41:47 +00:00
|
|
|
|
2013-10-30 15:33:51 +00:00
|
|
|
m_cur_grid->MakeCellVisible( curRow, curCol );
|
2012-10-31 14:41:47 +00:00
|
|
|
m_cur_grid->SetGridCursor( curRow, curCol );
|
2014-12-21 14:13:14 +00:00
|
|
|
m_cur_grid->SelectRow( getCursorRow() );
|
2012-10-18 15:28:50 +00:00
|
|
|
}
|
2012-10-16 06:56:57 +00:00
|
|
|
}
|
|
|
|
|
2016-09-25 17:06:49 +00:00
|
|
|
void moveDownHandler( wxCommandEvent& event ) override
|
2012-10-16 06:56:57 +00:00
|
|
|
{
|
2016-11-19 22:15:34 +00:00
|
|
|
wxArrayInt rowsSelected = m_cur_grid->GetSelectedRows();
|
|
|
|
|
|
|
|
if( rowsSelected.GetCount() == 0 )
|
|
|
|
return;
|
|
|
|
|
2013-10-30 15:33:51 +00:00
|
|
|
FP_TBL_MODEL* tbl = cur_model();
|
2012-10-31 14:41:47 +00:00
|
|
|
|
2016-11-19 22:15:34 +00:00
|
|
|
// @todo: add multiple selection moves.
|
|
|
|
int curRow = rowsSelected[0];
|
|
|
|
|
2012-10-31 14:41:47 +00:00
|
|
|
if( unsigned( curRow + 1 ) < tbl->rows.size() )
|
|
|
|
{
|
2016-11-19 22:15:34 +00:00
|
|
|
int curCol = getCursorCol();
|
2012-10-31 14:41:47 +00:00
|
|
|
|
2016-11-19 22:15:34 +00:00
|
|
|
boost::ptr_vector< LIB_TABLE_ROW >::auto_type move_me =
|
|
|
|
tbl->rows.release( tbl->rows.begin() + curRow );
|
2012-10-31 14:41:47 +00:00
|
|
|
|
2016-11-19 22:15:34 +00:00
|
|
|
++curRow;
|
|
|
|
tbl->rows.insert( tbl->rows.begin() + curRow, move_me.release() );
|
2012-10-31 14:41:47 +00:00
|
|
|
|
|
|
|
if( tbl->GetView() )
|
|
|
|
{
|
|
|
|
// fire a msg to cause redrawing
|
|
|
|
wxGridTableMessage msg( tbl,
|
|
|
|
wxGRIDTABLE_NOTIFY_ROWS_INSERTED,
|
|
|
|
curRow - 1,
|
|
|
|
0 );
|
|
|
|
|
|
|
|
tbl->GetView()->ProcessTableMessage( msg );
|
|
|
|
}
|
|
|
|
|
2013-10-30 15:33:51 +00:00
|
|
|
m_cur_grid->MakeCellVisible( curRow, curCol );
|
2012-10-31 14:41:47 +00:00
|
|
|
m_cur_grid->SetGridCursor( curRow, curCol );
|
2014-12-21 14:13:14 +00:00
|
|
|
m_cur_grid->SelectRow( getCursorRow() );
|
2012-10-31 14:41:47 +00:00
|
|
|
}
|
2012-10-16 06:56:57 +00:00
|
|
|
}
|
|
|
|
|
2016-09-25 17:06:49 +00:00
|
|
|
void optionsEditor( wxCommandEvent& event ) override
|
2012-10-16 06:56:57 +00:00
|
|
|
{
|
2013-10-30 15:33:51 +00:00
|
|
|
FP_TBL_MODEL* tbl = cur_model();
|
2012-10-16 06:56:57 +00:00
|
|
|
|
2013-12-31 16:59:33 +00:00
|
|
|
if( tbl->GetNumberRows() )
|
|
|
|
{
|
2016-11-19 22:15:34 +00:00
|
|
|
int curRow = getCursorRow();
|
|
|
|
LIB_TABLE_ROW* row = &tbl->rows[curRow];
|
2012-10-17 01:00:25 +00:00
|
|
|
|
2013-12-31 16:59:33 +00:00
|
|
|
wxString result;
|
2016-11-19 22:15:34 +00:00
|
|
|
const wxString& options = row->GetOptions();
|
2012-10-17 01:00:25 +00:00
|
|
|
|
2016-11-19 22:15:34 +00:00
|
|
|
InvokePluginOptionsEditor( this, row->GetNickName(), row->GetType(), options, &result );
|
2012-10-16 06:56:57 +00:00
|
|
|
|
2013-12-31 16:59:33 +00:00
|
|
|
if( options != result )
|
|
|
|
{
|
2016-11-19 22:15:34 +00:00
|
|
|
row->SetOptions( result );
|
2013-11-12 00:17:27 +00:00
|
|
|
|
2013-12-31 16:59:33 +00:00
|
|
|
// all but options:
|
|
|
|
m_cur_grid->AutoSizeColumn( COL_NICKNAME, false );
|
|
|
|
m_cur_grid->AutoSizeColumn( COL_URI, false );
|
|
|
|
m_cur_grid->AutoSizeColumn( COL_TYPE, false );
|
2013-12-22 19:02:04 +00:00
|
|
|
|
2013-12-31 16:59:33 +00:00
|
|
|
// On Windows, the grid is not refresh,
|
|
|
|
// so force resfresh after a change
|
2013-12-22 19:02:04 +00:00
|
|
|
#ifdef __WINDOWS__
|
2013-12-31 16:59:33 +00:00
|
|
|
Refresh();
|
2013-12-22 19:02:04 +00:00
|
|
|
#endif
|
2013-12-31 16:59:33 +00:00
|
|
|
}
|
2012-10-18 15:28:50 +00:00
|
|
|
}
|
|
|
|
}
|
2012-10-16 06:56:57 +00:00
|
|
|
|
2016-09-24 18:53:15 +00:00
|
|
|
void OnClickLibraryWizard( wxCommandEvent& event ) override;
|
2014-12-21 14:13:14 +00:00
|
|
|
|
2016-09-25 17:06:49 +00:00
|
|
|
void onCancelButtonClick( wxCommandEvent& event ) override
|
2012-12-09 20:51:42 +00:00
|
|
|
{
|
2012-10-18 15:28:50 +00:00
|
|
|
EndModal( 0 );
|
2012-12-09 20:51:42 +00:00
|
|
|
}
|
|
|
|
|
2016-09-25 17:06:49 +00:00
|
|
|
void onCancelCaptionButtonClick( wxCloseEvent& event ) override
|
2012-12-09 20:51:42 +00:00
|
|
|
{
|
2013-10-13 21:33:58 +00:00
|
|
|
EndModal( 0 );
|
2012-12-09 20:51:42 +00:00
|
|
|
}
|
|
|
|
|
2016-09-25 17:06:49 +00:00
|
|
|
void onOKButtonClick( wxCommandEvent& event ) override
|
2012-12-09 20:51:42 +00:00
|
|
|
{
|
2012-10-18 15:28:50 +00:00
|
|
|
int dialogRet = 0;
|
2012-10-16 06:56:57 +00:00
|
|
|
|
2013-10-22 19:29:37 +00:00
|
|
|
// stuff any pending cell editor text into the table.
|
|
|
|
m_cur_grid->SaveEditControlValue();
|
|
|
|
|
2013-09-24 21:23:13 +00:00
|
|
|
if( verifyTables() )
|
2012-10-18 15:28:50 +00:00
|
|
|
{
|
2013-10-30 15:33:51 +00:00
|
|
|
if( *global_model() != *m_global )
|
2013-09-24 21:23:13 +00:00
|
|
|
{
|
|
|
|
dialogRet |= 1;
|
2012-12-09 20:51:42 +00:00
|
|
|
|
2016-11-19 22:15:34 +00:00
|
|
|
m_global->Clear();
|
|
|
|
m_global->rows.transfer( m_global->rows.end(), global_model()->rows.begin(),
|
|
|
|
global_model()->rows.end(), global_model()->rows );
|
2013-09-24 21:23:13 +00:00
|
|
|
m_global->reindex();
|
|
|
|
}
|
2012-10-16 06:56:57 +00:00
|
|
|
|
2013-10-30 15:33:51 +00:00
|
|
|
if( *project_model() != *m_project )
|
2013-09-24 21:23:13 +00:00
|
|
|
{
|
|
|
|
dialogRet |= 2;
|
2012-10-18 15:28:50 +00:00
|
|
|
|
2016-11-19 22:15:34 +00:00
|
|
|
m_project->Clear();
|
|
|
|
m_project->rows.transfer( m_project->rows.end(), project_model()->rows.begin(),
|
|
|
|
project_model()->rows.end(), project_model()->rows );
|
2013-09-24 21:23:13 +00:00
|
|
|
m_project->reindex();
|
|
|
|
}
|
2012-12-09 20:51:42 +00:00
|
|
|
|
2013-09-24 21:23:13 +00:00
|
|
|
EndModal( dialogRet );
|
|
|
|
}
|
2012-12-09 20:51:42 +00:00
|
|
|
}
|
|
|
|
|
2013-01-21 03:12:16 +00:00
|
|
|
/// Populate the readonly environment variable table with names and values
|
|
|
|
/// by examining all the full_uri columns.
|
|
|
|
void populateEnvironReadOnlyTable()
|
|
|
|
{
|
2016-10-28 13:11:23 +00:00
|
|
|
wxRegEx re( ".*?\\$\\{(.+?)\\}.*?", wxRE_ADVANCED );
|
2013-01-21 03:12:16 +00:00
|
|
|
wxASSERT( re.IsValid() ); // wxRE_ADVANCED is required.
|
|
|
|
|
|
|
|
std::set< wxString > unique;
|
|
|
|
typedef std::set<wxString>::const_iterator SET_CITER;
|
|
|
|
|
2013-10-23 18:56:03 +00:00
|
|
|
// clear the table
|
2013-01-21 03:12:16 +00:00
|
|
|
m_path_subs_grid->DeleteRows( 0, m_path_subs_grid->GetNumberRows() );
|
|
|
|
|
2013-10-30 15:33:51 +00:00
|
|
|
FP_TBL_MODEL* gbl = global_model();
|
|
|
|
FP_TBL_MODEL* prj = project_model();
|
|
|
|
|
|
|
|
int gblRowCount = gbl->GetNumberRows();
|
|
|
|
int prjRowCount = prj->GetNumberRows();
|
2013-01-21 03:12:16 +00:00
|
|
|
int row;
|
|
|
|
|
|
|
|
for( row = 0; row < gblRowCount; ++row )
|
|
|
|
{
|
2013-10-30 15:33:51 +00:00
|
|
|
wxString uri = gbl->GetValue( row, COL_URI );
|
2013-01-21 03:12:16 +00:00
|
|
|
|
|
|
|
while( re.Matches( uri ) )
|
|
|
|
{
|
|
|
|
wxString envvar = re.GetMatch( uri, 1 );
|
|
|
|
|
|
|
|
// ignore duplicates
|
|
|
|
unique.insert( envvar );
|
|
|
|
|
|
|
|
// delete the last match and search again
|
|
|
|
uri.Replace( re.GetMatch( uri, 0 ), wxEmptyString );
|
|
|
|
}
|
|
|
|
}
|
2012-10-16 06:56:57 +00:00
|
|
|
|
2013-01-21 03:12:16 +00:00
|
|
|
for( row = 0; row < prjRowCount; ++row )
|
|
|
|
{
|
2013-10-30 15:33:51 +00:00
|
|
|
wxString uri = prj->GetValue( row, COL_URI );
|
2013-01-21 03:12:16 +00:00
|
|
|
|
|
|
|
while( re.Matches( uri ) )
|
|
|
|
{
|
|
|
|
wxString envvar = re.GetMatch( uri, 1 );
|
|
|
|
|
|
|
|
// ignore duplicates
|
|
|
|
unique.insert( envvar );
|
|
|
|
|
|
|
|
// delete the last match and search again
|
|
|
|
uri.Replace( re.GetMatch( uri, 0 ), wxEmptyString );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-15 14:11:46 +00:00
|
|
|
// Make sure this special environment variable shows up even if it was
|
|
|
|
// not used yet. It is automatically set by KiCad to the directory holding
|
|
|
|
// the current project.
|
* KIWAY Milestone A): Make major modules into DLL/DSOs.
! The initial testing of this commit should be done using a Debug build so that
all the wxASSERT()s are enabled. Also, be sure and keep enabled the
USE_KIWAY_DLLs option. The tree won't likely build without it. Turning it
off is senseless anyways. If you want stable code, go back to a prior version,
the one tagged with "stable".
* Relocate all functionality out of the wxApp derivative into more finely
targeted purposes:
a) DLL/DSO specific
b) PROJECT specific
c) EXE or process specific
d) configuration file specific data
e) configuration file manipulations functions.
All of this functionality was blended into an extremely large wxApp derivative
and that was incompatible with the desire to support multiple concurrently
loaded DLL/DSO's ("KIFACE")s and multiple concurrently open projects.
An amazing amount of organization come from simply sorting each bit of
functionality into the proper box.
* Switch to wxConfigBase from wxConfig everywhere except instantiation.
* Add classes KIWAY, KIFACE, KIFACE_I, SEARCH_STACK, PGM_BASE, PGM_KICAD,
PGM_SINGLE_TOP,
* Remove "Return" prefix on many function names.
* Remove obvious comments from CMakeLists.txt files, and from else() and endif()s.
* Fix building boost for use in a DSO on linux.
* Remove some of the assumptions in the CMakeLists.txt files that windows had
to be the host platform when building windows binaries.
* Reduce the number of wxStrings being constructed at program load time via
static construction.
* Pass wxConfigBase* to all SaveSettings() and LoadSettings() functions so that
these functions are useful even when the wxConfigBase comes from another
source, as is the case in the KICAD_MANAGER_FRAME.
* Move the setting of the KIPRJMOD environment variable into class PROJECT,
so that it can be moved into a project variable soon, and out of FP_LIB_TABLE.
* Add the KIWAY_PLAYER which is associated with a particular PROJECT, and all
its child wxFrames and wxDialogs now have a Kiway() member function which
returns a KIWAY& that that window tree branch is in support of. This is like
wxWindows DNA in that child windows get this member with proper value at time
of construction.
* Anticipate some of the needs for milestones B) and C) and make code
adjustments now in an effort to reduce work in those milestones.
* No testing has been done for python scripting, since milestone C) has that
being largely reworked and re-thought-out.
2014-03-20 00:42:08 +00:00
|
|
|
unique.insert( PROJECT_VAR_NAME );
|
2013-11-15 14:36:11 +00:00
|
|
|
unique.insert( FP_LIB_TABLE::GlobalPathEnvVariableName() );
|
2014-12-21 14:13:14 +00:00
|
|
|
// This special environment variable is used to locate 3d shapes
|
2014-08-24 07:05:07 +00:00
|
|
|
unique.insert( KISYS3DMOD );
|
2013-11-15 14:11:46 +00:00
|
|
|
|
2013-01-21 03:12:16 +00:00
|
|
|
m_path_subs_grid->AppendRows( unique.size() );
|
|
|
|
|
|
|
|
row = 0;
|
2016-11-19 22:15:34 +00:00
|
|
|
|
2013-01-21 03:12:16 +00:00
|
|
|
for( SET_CITER it = unique.begin(); it != unique.end(); ++it, ++row )
|
|
|
|
{
|
|
|
|
wxString evName = *it;
|
|
|
|
wxString evValue;
|
|
|
|
|
|
|
|
m_path_subs_grid->SetCellValue( row, 0, evName );
|
|
|
|
|
|
|
|
if( wxGetEnv( evName, &evValue ) )
|
|
|
|
m_path_subs_grid->SetCellValue( row, 1, evValue );
|
|
|
|
}
|
|
|
|
|
|
|
|
m_path_subs_grid->AutoSizeColumns();
|
|
|
|
}
|
|
|
|
|
2012-12-09 20:51:42 +00:00
|
|
|
//-----</event handlers>---------------------------------
|
2012-10-16 06:56:57 +00:00
|
|
|
|
2013-10-30 15:33:51 +00:00
|
|
|
// caller's tables are modified only on OK button and successful verification.
|
2016-11-19 22:15:34 +00:00
|
|
|
FP_LIB_TABLE* m_global;
|
|
|
|
FP_LIB_TABLE* m_project;
|
2012-10-16 06:56:57 +00:00
|
|
|
|
2016-11-19 22:15:34 +00:00
|
|
|
FP_TBL_MODEL* global_model() const { return (FP_TBL_MODEL*) m_global_grid->GetTable(); }
|
|
|
|
FP_TBL_MODEL* project_model() const { return (FP_TBL_MODEL*) m_project_grid->GetTable(); }
|
|
|
|
FP_TBL_MODEL* cur_model() const { return (FP_TBL_MODEL*) m_cur_grid->GetTable(); }
|
2012-10-16 06:56:57 +00:00
|
|
|
|
2016-11-19 22:15:34 +00:00
|
|
|
wxGrid* m_cur_grid; ///< changed based on tab choice
|
|
|
|
static int m_pageNdx; ///< Remember the last notebook page selected during a session
|
2012-10-15 22:30:01 +00:00
|
|
|
};
|
|
|
|
|
2016-11-19 22:15:34 +00:00
|
|
|
|
2014-09-22 07:51:06 +00:00
|
|
|
int DIALOG_FP_LIB_TABLE::m_pageNdx = 0;
|
|
|
|
|
2012-10-15 22:30:01 +00:00
|
|
|
|
2014-12-21 14:13:14 +00:00
|
|
|
void DIALOG_FP_LIB_TABLE::OnClickLibraryWizard( wxCommandEvent& event )
|
|
|
|
{
|
2015-03-30 16:42:39 +00:00
|
|
|
WIZARD_FPLIB_TABLE dlg( this );
|
2014-12-21 14:13:14 +00:00
|
|
|
|
2015-03-30 16:42:39 +00:00
|
|
|
if( !dlg.RunWizard( dlg.GetFirstPage() ) )
|
2014-12-21 14:13:14 +00:00
|
|
|
return; // Aborted by user
|
|
|
|
|
2015-03-30 16:42:39 +00:00
|
|
|
const std::vector<WIZARD_FPLIB_TABLE::LIBRARY>& libs = dlg.GetLibraries();
|
|
|
|
bool global_scope = dlg.GetLibScope() == WIZARD_FPLIB_TABLE::GLOBAL;
|
|
|
|
wxGrid* libgrid = global_scope ? m_global_grid : m_project_grid;
|
|
|
|
FP_TBL_MODEL* tbl = (FP_TBL_MODEL*) libgrid->GetTable();
|
2014-12-21 14:13:14 +00:00
|
|
|
|
2015-03-30 16:42:39 +00:00
|
|
|
for( std::vector<WIZARD_FPLIB_TABLE::LIBRARY>::const_iterator it = libs.begin();
|
|
|
|
it != libs.end(); ++it )
|
2014-12-21 14:13:14 +00:00
|
|
|
{
|
2015-03-30 16:42:39 +00:00
|
|
|
if( it->GetStatus() == WIZARD_FPLIB_TABLE::LIBRARY::INVALID )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if( libgrid->AppendRows( 1 ) )
|
2014-12-21 14:13:14 +00:00
|
|
|
{
|
|
|
|
int last_row = libgrid->GetNumberRows() - 1;
|
|
|
|
|
|
|
|
// Add the nickname: currently make it from filename
|
2015-03-30 16:42:39 +00:00
|
|
|
tbl->SetValue( last_row, COL_NICKNAME, it->GetDescription() );
|
|
|
|
|
|
|
|
// Add the path:
|
|
|
|
tbl->SetValue( last_row, COL_URI, it->GetAutoPath( dlg.GetLibScope() ) );
|
|
|
|
|
2014-12-21 14:13:14 +00:00
|
|
|
// Add the plugin name:
|
2015-03-30 16:42:39 +00:00
|
|
|
tbl->SetValue( last_row, COL_TYPE, it->GetPluginName() );
|
2014-12-21 14:13:14 +00:00
|
|
|
|
|
|
|
libgrid->MakeCellVisible( last_row, 0 );
|
|
|
|
libgrid->SetGridCursor( last_row, 0 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-30 16:42:39 +00:00
|
|
|
// Switch to the current scope tab
|
|
|
|
if( global_scope )
|
|
|
|
m_auinotebook->SetSelection( 0 );
|
|
|
|
else
|
|
|
|
m_auinotebook->SetSelection( 1 );
|
|
|
|
|
2014-12-21 14:13:14 +00:00
|
|
|
libgrid->SelectRow( libgrid->GetGridCursorRow() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-11-19 22:15:34 +00:00
|
|
|
int InvokePcbLibTableEditor( wxTopLevelWindow* aParent, FP_LIB_TABLE* aGlobal,
|
|
|
|
FP_LIB_TABLE* aProject )
|
2012-10-15 22:30:01 +00:00
|
|
|
{
|
2012-10-18 15:28:50 +00:00
|
|
|
DIALOG_FP_LIB_TABLE dlg( aParent, aGlobal, aProject );
|
2012-10-15 22:30:01 +00:00
|
|
|
|
2012-10-18 15:28:50 +00:00
|
|
|
int dialogRet = dlg.ShowModal(); // returns value passed to EndModal() above
|
2012-10-15 22:30:01 +00:00
|
|
|
|
2012-10-18 15:28:50 +00:00
|
|
|
return dialogRet;
|
2012-10-15 22:30:01 +00:00
|
|
|
}
|
2015-03-30 16:42:39 +00:00
|
|
|
|
|
|
|
|
2016-11-19 22:15:34 +00:00
|
|
|
int InvokeFootprintWizard( wxTopLevelWindow* aParent, FP_LIB_TABLE* aGlobal,
|
|
|
|
FP_LIB_TABLE* aProject )
|
2015-03-30 16:42:39 +00:00
|
|
|
{
|
|
|
|
WIZARD_FPLIB_TABLE dlg( aParent );
|
|
|
|
|
|
|
|
if( !dlg.RunWizard( dlg.GetFirstPage() ) )
|
|
|
|
return 0; // Aborted by user
|
|
|
|
|
|
|
|
const std::vector<WIZARD_FPLIB_TABLE::LIBRARY>& libs = dlg.GetLibraries();
|
|
|
|
WIZARD_FPLIB_TABLE::LIB_SCOPE scope = dlg.GetLibScope();
|
|
|
|
FP_LIB_TABLE* fp_tbl = ( scope == WIZARD_FPLIB_TABLE::GLOBAL ? aGlobal : aProject );
|
|
|
|
|
|
|
|
if( fp_tbl )
|
|
|
|
{
|
|
|
|
for( std::vector<WIZARD_FPLIB_TABLE::LIBRARY>::const_iterator it = libs.begin();
|
|
|
|
it != libs.end(); ++it )
|
|
|
|
{
|
|
|
|
if( it->GetStatus() == WIZARD_FPLIB_TABLE::LIBRARY::INVALID )
|
|
|
|
continue;
|
|
|
|
|
2016-11-19 22:15:34 +00:00
|
|
|
FP_LIB_TABLE_ROW* row = new FP_LIB_TABLE_ROW( it->GetDescription(),
|
|
|
|
it->GetAutoPath( scope ),
|
|
|
|
it->GetPluginName(),
|
|
|
|
wxEmptyString ); // options
|
2015-03-30 16:42:39 +00:00
|
|
|
fp_tbl->InsertRow( row );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return scope;
|
|
|
|
}
|