ADDED: Implement Drag and Drop

dropping files to Kicad manager :
  *.kicad_pro, *.pro -> open project;
  gerber and job files -> open in Gerbview editor;
  Eagle and Cadstar files -> open project.
dropping file to schematic editor -> append schematic;
dropping library file to Symbol editor -> add library;
dropping board file to PCB editor -> append board;
dropping library or footprint file to Footprint editor -> add library or import footprint;
dropping ZIP file or gerber files to Gerbview editor -> open files;
dropping sheet file to Drawing Sheet editor -> open sheet.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/11638
This commit is contained in:
lulu731 2022-09-14 22:28:09 +00:00 committed by Seth Hillbrand
parent 78acb4f07f
commit 0180bcf90a
48 changed files with 962 additions and 167 deletions

View File

@ -313,6 +313,7 @@ set( COMMON_SRCS
eda_pattern_match.cpp
eda_shape.cpp
eda_text.cpp
eda_tools.cpp
eda_units.cpp
env_paths.cpp
env_vars.cpp
@ -713,4 +714,3 @@ make_lexer(
# to build it, first enable #define STAND_ALONE at top of dsnlexer.cpp
add_executable( dsntest EXCLUDE_FROM_ALL dsnlexer.cpp )
target_link_libraries( dsntest common ${wxWidgets_LIBRARIES} rt )

View File

@ -1123,6 +1123,36 @@ void EDA_BASE_FRAME::OnPreferences( wxCommandEvent& event )
}
void EDA_BASE_FRAME::OnDropFiles( wxDropFilesEvent& aEvent )
{
wxString* files = aEvent.GetFiles();
for( int nb = 0; nb < aEvent.GetNumberOfFiles(); nb++ )
{
const wxFileName fn = wxFileName( files[nb] );
for( const auto& [ext, tool] : m_acceptedExts )
{
if( IsExtensionAccepted( fn.GetExt(), { ext.ToStdString() } ) )
{
m_AcceptedFiles.emplace( m_AcceptedFiles.end(), fn );
break;
}
}
}
DoWithAcceptedFiles();
m_AcceptedFiles.clear();
}
void EDA_BASE_FRAME::DoWithAcceptedFiles()
{
for( auto file : m_AcceptedFiles )
{
wxString fn = file.GetFullPath();
m_toolManager->RunAction( *m_acceptedExts.at( file.GetExt() ), true, &fn );
}
}
bool EDA_BASE_FRAME::IsWritable( const wxFileName& aFileName, bool aVerbose )
{
wxString msg;

53
common/eda_tools.cpp Normal file
View File

@ -0,0 +1,53 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2013 CERN (www.cern.ch)
* Copyright (C) 2004-2021 KiCad Developers, see change_log.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
*/
#include <eda_tools.h>
#include <wx/textfile.h>
bool IsFileFromEDATool( const wxFileName& aFileName, const EDA_TOOLS aTool )
{
wxTextFile textFile;
if( textFile.Open( aFileName.GetFullPath() ) )
{
switch( aTool )
{
case EAGLE:
if( textFile.GetLineCount() > 2
&& textFile[1].StartsWith( wxT( "<!DOCTYPE eagle SYSTEM" ) )
&& textFile[2].StartsWith( wxT( "<eagle version" ) ) )
{
textFile.Close();
return true;
}
break;
default: break;
}
textFile.Close();
}
return false;
}

View File

@ -671,6 +671,9 @@ TOOL_ACTION ACTIONS::reportBug( "common.SuiteControl.reportBug",
_( "Report a problem with KiCad" ),
BITMAPS::bug );
TOOL_ACTION ACTIONS::ddAddLibrary( "common.Control.ddaddLibrary",
AS_GLOBAL );
// System-wide selection Events
const TOOL_EVENT EVENTS::PointSelectedEvent( TC_MESSAGE, TA_ACTION, "common.Interactive.pointSelected" );
@ -684,4 +687,3 @@ const TOOL_EVENT EVENTS::InhibitSelectionEditing( TC_MESSAGE, TA_ACTION, "common
const TOOL_EVENT EVENTS::UninhibitSelectionEditing( TC_MESSAGE, TA_ACTION, "common.Interactive.uninhibit" );
const TOOL_EVENT EVENTS::DisambiguatePoint( TC_MESSAGE, TA_ACTION, "common.Interactive.disambiguate" );

View File

@ -32,6 +32,7 @@
#include <wx/filedlg.h>
#include <wx/regex.h>
#include <wx/translation.h>
#include <regex>
bool compareFileExtensions( const std::string& aExtension,
const std::vector<std::string>& aReference, bool aCaseSensitive )
@ -131,6 +132,8 @@ const std::string ProjectFileExtension( "kicad_pro" );
const std::string LegacyProjectFileExtension( "pro" );
const std::string ProjectLocalSettingsFileExtension( "kicad_prl" );
const std::string LegacySchematicFileExtension( "sch" );
const std::string EagleSchematicFileExtension( "sch" );
const std::string CadstarSchematicFileExtension( "csa" );
const std::string KiCadSchematicFileExtension( "kicad_sch" );
const std::string OrCadPcb2NetlistFileExtension( "net" );
const std::string NetlistFileExtension( "net" );
@ -145,6 +148,8 @@ const std::string DatabaseLibraryFileExtension( "kicad_dbl" );
const std::string ArchiveFileExtension( "zip" );
const std::string LegacyPcbFileExtension( "brd" );
const std::string EaglePcbFileExtension( "brd" );
const std::string CadstarPcbFileExtension( "cpa" );
const std::string KiCadPcbFileExtension( "kicad_pcb" );
const std::string DrawingSheetFileExtension( "kicad_wks" );
const std::string DesignRulesFileExtension( "kicad_dru" );
@ -174,6 +179,31 @@ const std::string TextFileExtension( "txt" );
const std::string MarkdownFileExtension( "md" );
const std::string CsvFileExtension( "csv" );
/**
* Gerber files extensions Kicad is to open
*/
const std::vector<std::string> GerberFileExtensions =
{
GerberFileExtension, GerberJobFileExtension,
"gbl", "gbo", "gbp", "gbs", "gko",
"gm1", "gm2", "gm3", "gm4", "gm5", "gm6", "gm7", "gm8", "gm9",
"g1", "g3",
"gpt", "gpb", "gtl", "gto", "gtp", "gts", "pho", "pos"
};
const wxString GerberFileExtensionWildCard( ".((gbr|gbrjob|(gb|gt)[alops])|pho)" );
bool IsExtensionAccepted( const wxString& aExt, const std::vector<std::string> acceptedExts )
{
for( auto extPtr = acceptedExts.begin(); extPtr != acceptedExts.end(); extPtr++ )
{
if( aExt.ToStdString() == *extPtr )
return true;
}
return false;
}
bool IsProtelExtension( const wxString& ext )
{

View File

@ -524,7 +524,6 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
bool SCH_EDIT_FRAME::AppendSchematic()
{
wxString fullFileName;
SCH_SCREEN* screen = GetScreen();
if( !screen )
@ -542,9 +541,13 @@ bool SCH_EDIT_FRAME::AppendSchematic()
if( dlg.ShowModal() == wxID_CANCEL )
return false;
fullFileName = dlg.GetPath();
return AddSheetAndUpdateDisplay( dlg.GetPath() );
}
if( !LoadSheetFromFile( GetCurrentSheet().Last(), &GetCurrentSheet(), fullFileName ) )
bool SCH_EDIT_FRAME::AddSheetAndUpdateDisplay( const wxString aFullFileName )
{
if( !LoadSheetFromFile( GetCurrentSheet().Last(), &GetCurrentSheet(), aFullFileName ) )
return false;
initScreenZoom();
@ -1502,4 +1505,3 @@ const wxString& SCH_EDIT_FRAME::getAutoSaveFileName() const
return autoSaveFileName;
}

View File

@ -106,6 +106,9 @@ BEGIN_EVENT_TABLE( SCH_EDIT_FRAME, EDA_DRAW_FRAME )
EVT_MENU( wxID_CLOSE, SCH_EDIT_FRAME::OnExit )
EVT_MENU( ID_GRID_SETTINGS, SCH_BASE_FRAME::OnGridSettings )
// Drop files event
EVT_DROP_FILES( SCH_EDIT_FRAME::OnDropFiles )
END_EVENT_TABLE()
@ -265,6 +268,10 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
// Default shutdown reason until a file is loaded
KIPLATFORM::APP::SetShutdownBlockReason( this, _( "New schematic file is unsaved" ) );
// Init for dropping files
m_acceptedExts.emplace( KiCadSchematicFileExtension, &EE_ACTIONS::ddAppendFile );
DragAcceptFiles( true );
// Ensure the window is on top
Raise();

View File

@ -464,6 +464,16 @@ public:
*/
bool AppendSchematic();
/**
* Add a sheet file into the current sheet and updates display
*
* @note Used in AppendSchematic() and SCH_EDIT_TOOL::ddAppendFile() (so it is public)
*
* @param aFullFileName Path and name of sheet
* @return True if the sheet was properly added
*/
bool AddSheetAndUpdateDisplay( const wxString aFullFileName );
/**
* Check if any of the screens has unsaved changes and asks the user whether to save or
* drop them.

View File

@ -91,6 +91,9 @@ BEGIN_EVENT_TABLE( SYMBOL_EDIT_FRAME, EDA_DRAW_FRAME )
// Update user interface elements.
EVT_UPDATE_UI( ID_LIBEDIT_SELECT_UNIT_NUMBER, SYMBOL_EDIT_FRAME::OnUpdateUnitNumber )
// Drop files event
EVT_DROP_FILES( SYMBOL_EDIT_FRAME::OnDropFiles )
END_EVENT_TABLE()
@ -239,6 +242,9 @@ SYMBOL_EDIT_FRAME::SYMBOL_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
m_toolManager->RunAction( ACTIONS::zoomFitScreen, true );
m_acceptedExts.emplace( KiCadSymbolLibFileExtension, &ACTIONS::ddAddLibrary );
DragAcceptFiles( true );
KIPLATFORM::APP::SetShutdownBlockReason( this, _( "Library changes are unsaved" ) );
// Catch unhandled accelerator command characters that were no handled by the library tree
@ -900,6 +906,41 @@ wxString SYMBOL_EDIT_FRAME::AddLibraryFile( bool aCreateNew )
}
void SYMBOL_EDIT_FRAME::DdAddLibrary( wxString aLibFile )
{
// Select the target library table (global/project)
SYMBOL_LIB_TABLE* libTable = selectSymLibTable();
if( !libTable )
return;
wxFileName fn = wxFileName( aLibFile );
wxString libName = fn.GetName();
if( libName.IsEmpty() )
return;
if( m_libMgr->LibraryExists( libName ) )
{
DisplayError( this, wxString::Format( _( "Library '%s' already exists." ), libName ) );
return;
}
if( !m_libMgr->AddLibrary( fn.GetFullPath(), libTable ) )
{
DisplayError( this, _( "Could not open the library file." ) );
return;
}
bool globalTable = ( libTable == &SYMBOL_LIB_TABLE::GetGlobalLibTable() );
saveSymbolLibTables( globalTable, !globalTable );
std::string packet = fn.GetFullPath().ToStdString();
this->Kiway().ExpressMail( FRAME_SCH_SYMBOL_EDITOR, MAIL_LIB_EDIT, packet );
}
LIB_ID SYMBOL_EDIT_FRAME::GetTreeLIBID( int* aUnit ) const
{
return m_treePane->GetLibTree()->GetSelectedLibId( aUnit );

View File

@ -124,6 +124,11 @@ public:
*/
wxString AddLibraryFile( bool aCreateNew );
/**
* Add a library dropped file to the symbol library table.
*/
void DdAddLibrary( wxString aLibFile );
/**
* Create a new symbol in the selected library.
*/

View File

@ -901,3 +901,7 @@ TOOL_ACTION EE_ACTIONS::saveCurrSheetCopyAs( "eeschema.EditorControl.saveCurrShe
0, "",
_( "Save Current Sheet Copy As..." ), _( "Save a copy of the current sheet to another location or name" ),
BITMAPS::save_as );
// Drag and drop
TOOL_ACTION EE_ACTIONS::ddAppendFile( "eeschema.EditorControl.ddAppendFile",
AS_GLOBAL );

View File

@ -251,6 +251,9 @@ public:
static TOOL_ACTION clearHighlight;
static TOOL_ACTION updateNetHighlighting;
static TOOL_ACTION highlightNetTool;
// Drag and drop
static TOOL_ACTION ddAppendFile;
};
#endif

View File

@ -2285,6 +2285,13 @@ int SCH_EDIT_TOOL::EditPageNumber( const TOOL_EVENT& aEvent )
}
int SCH_EDIT_TOOL::DdAppendFile( const TOOL_EVENT& aEvent )
{
wxString aFileName = *aEvent.Parameter<wxString*>();
return ( m_frame->AddSheetAndUpdateDisplay( aFileName ) ? 0 : 1 );
}
void SCH_EDIT_TOOL::setTransitions()
{
Go( &SCH_EDIT_TOOL::RepeatDrawItem, EE_ACTIONS::repeatDrawItem.MakeEvent() );
@ -2321,4 +2328,6 @@ void SCH_EDIT_TOOL::setTransitions()
Go( &SCH_EDIT_TOOL::CleanupSheetPins, EE_ACTIONS::cleanupSheetPins.MakeEvent() );
Go( &SCH_EDIT_TOOL::GlobalEdit, EE_ACTIONS::editTextAndGraphics.MakeEvent() );
Go( &SCH_EDIT_TOOL::EditPageNumber, EE_ACTIONS::editPageNumber.MakeEvent() );
Go( &SCH_EDIT_TOOL::DdAppendFile, EE_ACTIONS::ddAppendFile.MakeEvent() );
}

View File

@ -78,6 +78,9 @@ public:
///< Run the deletion tool.
int DeleteItemCursor( const TOOL_EVENT& aEvent );
/// Drag and drop
int DdAppendFile( const TOOL_EVENT& aEvent );
private:
void editFieldText( SCH_FIELD* aField );

View File

@ -139,6 +139,16 @@ int SYMBOL_EDITOR_CONTROL::AddLibrary( const TOOL_EVENT& aEvent )
}
int SYMBOL_EDITOR_CONTROL::DdAddLibrary( const TOOL_EVENT& aEvent )
{
wxString libFile = *aEvent.Parameter<wxString*>();
if( m_frame->IsType( FRAME_SCH_SYMBOL_EDITOR ) )
static_cast<SYMBOL_EDIT_FRAME*>( m_frame )->DdAddLibrary( libFile );
return 0;
}
int SYMBOL_EDITOR_CONTROL::EditSymbol( const TOOL_EVENT& aEvent )
{
if( m_frame->IsType( FRAME_SCH_SYMBOL_EDITOR ) )
@ -679,6 +689,8 @@ void SYMBOL_EDITOR_CONTROL::setTransitions()
Go( &SYMBOL_EDITOR_CONTROL::AddSymbol, EE_ACTIONS::importSymbol.MakeEvent() );
Go( &SYMBOL_EDITOR_CONTROL::EditSymbol, EE_ACTIONS::editSymbol.MakeEvent() );
Go( &SYMBOL_EDITOR_CONTROL::DdAddLibrary, ACTIONS::ddAddLibrary.MakeEvent() );
Go( &SYMBOL_EDITOR_CONTROL::Save, ACTIONS::save.MakeEvent() );
Go( &SYMBOL_EDITOR_CONTROL::Save, EE_ACTIONS::saveLibraryAs.MakeEvent() );
Go( &SYMBOL_EDITOR_CONTROL::Save, EE_ACTIONS::saveSymbolAs.MakeEvent() );

View File

@ -70,6 +70,8 @@ public:
int ToggleSymbolTree( const TOOL_EVENT& aEvent );
int ToggleSyncedPinsMode( const TOOL_EVENT& aEvent );
int DdAddLibrary( const TOOL_EVENT& aEvent );
private:
///< Set up handlers for various events.
void setTransitions() override;

View File

@ -85,6 +85,9 @@ BEGIN_EVENT_TABLE( GERBVIEW_FRAME, EDA_DRAW_FRAME )
EVT_UPDATE_UI_RANGE( ID_TB_OPTIONS_SHOW_GBR_MODE_0, ID_TB_OPTIONS_SHOW_GBR_MODE_2,
GERBVIEW_FRAME::OnUpdateDrawMode )
// Drop files event
EVT_DROP_FILES( GERBVIEW_FRAME::OnDropFiles )
END_EVENT_TABLE()

View File

@ -37,6 +37,7 @@
#include <view/view.h>
#include <widgets/wx_progress_reporters.h>
#include "widgets/gerbview_layer_widget.h"
#include <tool/tool_manager.h>
// HTML Messages used more than one time:
#define MSG_NO_MORE_LAYER _( "<b>No more available layers</b> in GerbView to load files" )
@ -672,3 +673,27 @@ bool GERBVIEW_FRAME::LoadZipArchiveFile( const wxString& aFullFileName )
return true;
}
void GERBVIEW_FRAME::DoWithAcceptedFiles()
{
wxString gerbFn; // param to be sent with action event.
for( auto file : m_AcceptedFiles )
{
if( IsExtensionAccepted( file.GetExt(), { ArchiveFileExtension } ) )
{
wxString fn = file.GetFullPath();
// Open zip archive in editor
m_toolManager->RunAction( *m_acceptedExts.at( ArchiveFileExtension ), true, &fn );
}
else
{
// Store FileName in variable to open later
gerbFn += '"' + file.GetFullPath() + '"';
}
}
// Open files in editor
if( !gerbFn.IsEmpty() )
m_toolManager->RunAction( *m_acceptedExts.at( DrillFileExtension ), true, &gerbFn );
}

View File

@ -177,6 +177,13 @@ GERBVIEW_FRAME::GERBVIEW_FRAME( KIWAY* aKiway, wxWindow* aParent )
m_LayersManager->ReFill();
m_LayersManager->ReFillRender(); // Update colors in Render after the config is read
// Drag and drop
m_acceptedExts.emplace( ArchiveFileExtension, &GERBVIEW_ACTIONS::loadZipFile );
for( const auto& ext : GerberFileExtensions )
m_acceptedExts.emplace( ext, &GERBVIEW_ACTIONS::loadGerbFiles );
m_acceptedExts.emplace( DrillFileExtension, &GERBVIEW_ACTIONS::loadGerbFiles );
DragAcceptFiles( true );
GetToolManager()->RunAction( ACTIONS::zoomFitScreen, true );
// Ensure the window is on top

View File

@ -496,6 +496,8 @@ private:
void OnClearDrlFileHistory( wxCommandEvent& aEvent );
void OnClearGbrFileHistory( wxCommandEvent& aEvent );
void DoWithAcceptedFiles() override;
/**
* Loads the file provided or shows a dialog to get the file(s) from the user.
*

View File

@ -214,3 +214,10 @@ TOOL_ACTION GERBVIEW_ACTIONS::selectionClear( "gerbview.InteractiveSelection.Cle
AS_GLOBAL );
// Drag and drop
//
TOOL_ACTION GERBVIEW_ACTIONS::loadZipFile( "gerbview.Control.loadZipFile",
AS_GLOBAL );
TOOL_ACTION GERBVIEW_ACTIONS::loadGerbFiles( "gerbview.Control.loadGerbFiles",
AS_GLOBAL );

View File

@ -93,6 +93,10 @@ public:
static TOOL_ACTION highlightComponent;
static TOOL_ACTION highlightAttribute;
static TOOL_ACTION highlightDCode;
// Drag and drop
static TOOL_ACTION loadZipFile;
static TOOL_ACTION loadGerbFiles;
};
#endif // __GERBVIEW_ACTIONS_H

View File

@ -460,6 +460,46 @@ int GERBVIEW_CONTROL::UpdateMessagePanel( const TOOL_EVENT& aEvent )
}
int GERBVIEW_CONTROL::LoadZipfile( const TOOL_EVENT& aEvent )
{
m_frame->LoadZipArchiveFile( *aEvent.Parameter<wxString*>() );
canvas()->Refresh();
return 0;
}
int GERBVIEW_CONTROL::LoadGerbFiles( const TOOL_EVENT& aEvent )
{
// The event parameter is a string containing names of dropped files.
// Each file name has been enclosed with "", so file names with space character are allowed.
wxString files = *aEvent.Parameter<wxString*>();
// ie : files = "file1""another file""file3"...
std::vector<wxString> aFileNameList;
// Isolate each file name, deletting ""
files = files.AfterFirst( '"' );
// Gerber files are enclosed with "".
// Load files names in array.
while( !files.empty() )
{
wxString fileName = files.BeforeFirst( '"' );
// Check if file exists. If not, keep on and ignore fileName
if( wxFileName( fileName ).Exists() )
aFileNameList.push_back( fileName );
files = files.AfterFirst( '"' );
files = files.AfterFirst( '"' );
}
if( !aFileNameList.empty() )
m_frame->OpenProjectFiles( aFileNameList, KICTL_CREATE );
return 0;
}
void GERBVIEW_CONTROL::setTransitions()
{
Go( &GERBVIEW_CONTROL::OpenAutodetected, GERBVIEW_ACTIONS::openAutodetected.MakeEvent() );
@ -499,4 +539,7 @@ void GERBVIEW_CONTROL::setTransitions()
Go( &GERBVIEW_CONTROL::UpdateMessagePanel, EVENTS::UnselectedEvent );
Go( &GERBVIEW_CONTROL::UpdateMessagePanel, EVENTS::ClearedEvent );
Go( &GERBVIEW_CONTROL::UpdateMessagePanel, ACTIONS::updateUnits.MakeEvent() );
Go( &GERBVIEW_CONTROL::LoadZipfile, GERBVIEW_ACTIONS::loadZipFile.MakeEvent() );
Go( &GERBVIEW_CONTROL::LoadGerbFiles, GERBVIEW_ACTIONS::loadGerbFiles.MakeEvent() );
}

View File

@ -68,6 +68,10 @@ public:
int UpdateMessagePanel( const TOOL_EVENT& aEvent );
int Print( const TOOL_EVENT& aEvent );
// Drag and drop
int LoadZipfile( const TOOL_EVENT& aEvent );
int LoadGerbFiles( const TOOL_EVENT& aEvent );
///< Set up handlers for various events.
void setTransitions() override;

View File

@ -33,6 +33,7 @@
#include <vector>
#include <map>
#include <wx/aui/aui.h>
#include <layer_ids.h>
@ -608,7 +609,7 @@ protected:
/**
* Handle a window iconize event.
*
*
* @param aEvent is the data for the event.
*/
virtual void handleIconizeEvent( wxIconizeEvent& aEvent ) {}
@ -657,6 +658,21 @@ protected:
void ensureWindowIsOnScreen();
/**
* Handles event fired when a file is dropped to the window.
* In this base class, stores the path of files accepted.
* Calls DoWithAcceptedFiles() to execute actions on files.
*/
virtual void OnDropFiles( wxDropFilesEvent& aEvent );
/**
* Execute action on accepted dropped file.
* Called in OnDropFiles and should be populated with
* the action to execute in inherited classes.
*/
virtual void DoWithAcceptedFiles();
std::vector<wxFileName> m_AcceptedFiles;
DECLARE_EVENT_TABLE()
private:
@ -743,6 +759,11 @@ private:
///< Set by #NonUserClose() to indicate that the user did not request the current close.
bool m_isNonUserClose;
/**
* Associates files extensions with action to execute.
*/
std::map<const wxString, TOOL_ACTION*> m_acceptedExts;
};

55
include/eda_tools.h Normal file
View File

@ -0,0 +1,55 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 2004-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2018 CERN
*
* 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
*/
/**
* @file eda_tools.h
* @brief Enums and utilities for different EDA tools.
*/
#ifndef EDA_TOOLS_H
#define EDA_TOOLS_H
#include <wx/filename.h>
/**
* Enumeration of tools
*/
enum EDA_TOOLS
{
EAGLE
};
/**
* Check if aFileName is a aTool file
* As an example, can be used to check if a .sch file is an EAGLE file
* (may be a legacy KICAD file)
* @param aFileName name of file to check. Must be given with full path
* @param aTool EDA tool
* @return true if the file is an EDA_TOOL file type, false if not or file does not exist
*/
bool IsFileFromEDATool( const wxFileName& aFileName, const EDA_TOOLS aTool );
#endif

View File

@ -57,6 +57,7 @@ public:
static TOOL_ACTION print;
static TOOL_ACTION plot;
static TOOL_ACTION quit;
static TOOL_ACTION ddAddLibrary; // for drag and drop lib
// Generic edit actions
static TOOL_ACTION cancelInteractive;
@ -219,5 +220,3 @@ public:
};
#endif // __ACTIONS_H

View File

@ -120,6 +120,8 @@ extern const std::string ProjectFileExtension;
extern const std::string LegacyProjectFileExtension;
extern const std::string ProjectLocalSettingsFileExtension;
extern const std::string LegacySchematicFileExtension;
extern const std::string EagleSchematicFileExtension;
extern const std::string CadstarSchematicFileExtension;
extern const std::string KiCadSchematicFileExtension;
extern const std::string OrCadPcb2NetlistFileExtension;
extern const std::string NetlistFileExtension;
@ -133,6 +135,8 @@ extern const std::string DatabaseLibraryFileExtension;
extern const std::string ArchiveFileExtension;
extern const std::string LegacyPcbFileExtension;
extern const std::string EaglePcbFileExtension;
extern const std::string CadstarPcbFileExtension;
extern const std::string KiCadPcbFileExtension;
#define PcbFileExtension KiCadPcbFileExtension // symlink choice
extern const std::string KiCadSymbolLibFileExtension;
@ -164,6 +168,17 @@ extern const std::string TextFileExtension;
extern const std::string MarkdownFileExtension;
extern const std::string CsvFileExtension;
extern const std::vector<std::string> GerberFileExtensions;
extern const wxString GerberFileExtensionWildCard;
/**
* Checks if the file extension is in accepted extensions
* @param aExt is the extension to test
* @param acceptedExts Array with extensions to test against
*
* @return true if the extension is in array
*/
bool IsExtensionAccepted( const wxString& aExt, const std::vector<std::string> acceptedExts );
bool IsProtelExtension( const wxString& ext );

View File

@ -21,6 +21,7 @@ set( KICAD_SRCS
dialogs/panel_kicad_launcher_base.cpp
dialogs/panel_kicad_launcher.cpp
files-io.cpp
import_proj.cpp
import_project.cpp
kicad.cpp
kicad_manager_frame.cpp

207
kicad/import_proj.cpp Normal file
View File

@ -0,0 +1,207 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019 CERN
* Copyright (C) 2019-2022 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "import_proj.h"
#include <kiway.h>
#include <kiway_player.h>
#include <wildcards_and_files_ext.h>
#include <macros.h>
#include <richio.h>
#include <wx/msgdlg.h>
IMPORT_PROJ_HELPER::IMPORT_PROJ_HELPER( KICAD_MANAGER_FRAME* aFrame,
const wxString& aFile,
const wxString& aSchFileExtension,
const wxString& aPcbFileExtension ) :
m_frame( aFrame ),
m_sch( aFile ), m_pcb( m_sch ), m_pro( m_sch )
{
m_sch.SetExt( aSchFileExtension );
m_pcb.SetExt( aPcbFileExtension );
m_pro.SetExt( ProjectFileExtension );
}
const wxFileName& IMPORT_PROJ_HELPER::GetProj()
{
return m_pro;
}
wxString IMPORT_PROJ_HELPER::GetProjPath()
{
return m_pro.GetPath();
}
void IMPORT_PROJ_HELPER::SetProjPath( const wxString aPath )
{
m_pro.SetPath( aPath );
}
wxString IMPORT_PROJ_HELPER::GetProjFullPath()
{
return m_pro.GetFullPath();
}
wxString IMPORT_PROJ_HELPER::GetProjName()
{
return m_pro.GetName();
}
void IMPORT_PROJ_HELPER::CreateEmptyDirForProject()
{
// Append a new directory with the same name of the project file
// Keep iterating until we find an empty directory
wxString newDir = m_pro.GetName();
int attempt = 0;
m_pro.AppendDir( newDir );
while( m_pro.DirExists() )
{
m_pro.RemoveLastDir();
wxString suffix = wxString::Format( "_%d", ++attempt );
m_pro.AppendDir( newDir + suffix );
}
}
void IMPORT_PROJ_HELPER::SetProjAbsolutePath()
{
m_pro.SetExt( ProjectFileExtension );
if( !m_pro.IsAbsolute() )
m_pro.MakeAbsolute();
}
bool IMPORT_PROJ_HELPER::CopyImportedFile( KICAD_T aFT, bool displayError )
{
wxASSERT( m_pro.GetExt() == ProjectFileExtension );
wxFileName fileCopy( m_pro );
wxFileName src, dest;
switch( aFT )
{
case SCHEMATIC_T: src = m_sch; break;
case PCB_T: src = m_pcb; break;
default: break;
}
fileCopy.SetExt( src.GetExt() );
if( src.Exists() && !fileCopy.SameAs( src ) )
{
if( !wxCopyFile( src.GetFullPath(), fileCopy.GetFullPath(), true ) )
{
if( displayError )
OutputCopyError( src, fileCopy );
return false;
}
}
switch( aFT )
{
case SCHEMATIC_T: m_shCopy = fileCopy; break;
case PCB_T: m_pcbCopy = fileCopy; break;
default: break;
}
return true;
}
bool IMPORT_PROJ_HELPER::CopyImportedFiles( bool displayError )
{
return CopyImportedFile( SCHEMATIC_T, displayError ) && CopyImportedFile( PCB_T, displayError );
}
void IMPORT_PROJ_HELPER::OutputCopyError( const wxFileName& aSrc, const wxFileName& aFileCopy )
{
wxString msg;
msg.Printf( _( "Cannot copy file '%s'\n"
"to '%s'\n"
"The project cannot be imported." ),
aSrc.GetFullPath(), aFileCopy.GetFullPath() );
wxMessageDialog fileCopyErrorDlg( m_frame, msg, _( "Error" ), wxOK_DEFAULT | wxICON_ERROR );
fileCopyErrorDlg.ShowModal();
}
void IMPORT_PROJ_HELPER::AssociateFileWithProj( KICAD_T aFT, int aImportedFileType )
{
wxFileName fileCopy, importedFile;
FRAME_T frame_type;
switch( aFT )
{
case SCHEMATIC_T:
importedFile = m_sch;
fileCopy = m_shCopy;
frame_type = FRAME_SCH;
break;
case PCB_T:
importedFile = m_pcb;
fileCopy = m_pcbCopy;
frame_type = FRAME_PCB_EDITOR;
break;
default: return;
}
if( fileCopy.FileExists() )
{
KIWAY_PLAYER* frame = m_frame->Kiway().Player( frame_type, true );
std::string packet =
StrPrintf( "%d\n%s", aImportedFileType, TO_UTF8( fileCopy.GetFullPath() ) );
frame->Kiway().ExpressMail( frame_type, MAIL_IMPORT_FILE, packet, m_frame );
if( !frame->IsShown() )
frame->Show( true );
// On Windows, Raise() does not bring the window on screen, when iconized
if( frame->IsIconized() )
frame->Iconize( false );
frame->Raise();
if( !fileCopy.SameAs( importedFile ) ) // Do not delete the original file!
wxRemoveFile( fileCopy.GetFullPath() );
}
}
void IMPORT_PROJ_HELPER::AssociateFilesWithProj( int aImportedSchFileType,
int aImportedPcbFileType )
{
AssociateFileWithProj( SCHEMATIC_T, aImportedSchFileType );
AssociateFileWithProj( PCB_T, aImportedPcbFileType );
}

56
kicad/import_proj.h Normal file
View File

@ -0,0 +1,56 @@
#ifndef IMPORT_PROJ_H
#define IMPORT_PROJ_H
#include "kicad_manager_frame.h"
#include <wx/filename.h>
#include <core/typeinfo.h>
/**
* A helper class to import non Kicad project.
* */
class IMPORT_PROJ_HELPER
{
public:
IMPORT_PROJ_HELPER( KICAD_MANAGER_FRAME* aframe, const wxString& aFile,
const wxString& aSchFileExtension, const wxString& aPcbFileExtension );
const wxFileName& GetProj();
wxString GetProjPath();
void SetProjPath( const wxString aPath );
wxString GetProjFullPath();
wxString GetProjName();
/**
* @brief Appends a new directory with the name of the project file
* Keep iterating until an empty directory is found
*/
void CreateEmptyDirForProject();
void SetProjAbsolutePath();
/**
* @brief Copies project files to the destination directory
* @param displayError calls OutputCopyError() if true
*/
bool CopyImportedFiles( bool displayError = true );
/**
* @brief Converts imported files to kicad type files.
* Types of imported files are needed for conversion
* @param aImportedSchFileType type of the imported schematic
* @param aImportedPcbFileType type of the imported PCB
*/
void AssociateFilesWithProj( int aImportedSchFileType, int aImportedPcbFileType );
private:
KICAD_MANAGER_FRAME* m_frame;
wxFileName m_sch;
wxFileName m_shCopy;
wxFileName m_pcb;
wxFileName m_pcbCopy;
wxFileName m_pro;
bool CopyImportedFile( KICAD_T aKicad_T, bool displayError = true );
void OutputCopyError( const wxFileName& aSrc, const wxFileName& aFileCopy );
void AssociateFileWithProj( KICAD_T aKicad_T, int aImportedFileType );
};
#endif

View File

@ -28,27 +28,18 @@
* @brief routines for importing a non-KiCad project
*/
#include <wx/filefn.h>
#include <wx/filename.h>
#include <wx/dir.h>
#include <wx/filedlg.h>
#include <wx/dirdlg.h>
#include <common.h>
#include <confirm.h>
#include <kiway.h>
#include <macros.h>
#include <richio.h>
#include <wildcards_and_files_ext.h>
#include <kiway_player.h>
#include <stdexcept>
#include "pgm_kicad.h"
#include <io_mgr.h>
#include <sch_io_mgr.h>
#include "kicad_manager_frame.h"
#include <import_proj.h>
void KICAD_MANAGER_FRAME::ImportNonKiCadProject( const wxString& aWindowTitle,
@ -71,28 +62,21 @@ void KICAD_MANAGER_FRAME::ImportNonKiCadProject( const wxString& aWindowTitle,
// disjoint.
CloseProject( true );
wxFileName sch( schdlg.GetPath() );
sch.SetExt( aSchFileExtension );
wxFileName pcb( sch );
pcb.SetExt( aPcbFileExtension );
wxFileName pro( sch );
pro.SetExt( ProjectFileExtension );
IMPORT_PROJ_HELPER importProj( this, schdlg.GetPath(), aSchFileExtension, aPcbFileExtension );
wxString protitle = _( "KiCad Project Destination" );
// Don't use wxFileDialog here. On GTK builds, the default path is returned unless a
// file is actually selected.
wxDirDialog prodlg( this, protitle, pro.GetPath(), wxDD_DEFAULT_STYLE );
wxDirDialog prodlg( this, protitle, importProj.GetProjPath(), wxDD_DEFAULT_STYLE );
if( prodlg.ShowModal() == wxID_CANCEL )
return;
pro.SetPath( prodlg.GetPath() );
importProj.SetProjPath( prodlg.GetPath() );
// Check if the project directory is empty
wxDir directory( pro.GetPath() );
wxDir directory( importProj.GetProjPath() );
if( directory.HasFiles() )
{
@ -107,19 +91,9 @@ void KICAD_MANAGER_FRAME::ImportNonKiCadProject( const wxString& aWindowTitle,
{
// Append a new directory with the same name of the project file
// Keep iterating until we find an empty directory
wxString newDir = pro.GetName();
int attempt = 0;
importProj.CreateEmptyDirForProject();
pro.AppendDir( newDir );
while( pro.DirExists() )
{
pro.RemoveLastDir();
wxString suffix = wxString::Format( "_%d", ++attempt );
pro.AppendDir( newDir + suffix );
}
if( !wxMkdir( pro.GetPath() ) )
if( !wxMkdir( importProj.GetProjPath() ) )
{
msg = _( "Error creating new directory. Please try a different path. The "
"project cannot be imported." );
@ -133,101 +107,15 @@ void KICAD_MANAGER_FRAME::ImportNonKiCadProject( const wxString& aWindowTitle,
std::string packet;
pro.SetExt( ProjectFileExtension );
importProj.SetProjAbsolutePath();
if( !pro.IsAbsolute() )
pro.MakeAbsolute();
if( !importProj.CopyImportedFiles() )
return;
wxFileName schCopy( pro );
schCopy.SetExt( aSchFileExtension );
CreateNewProject( importProj.GetProjFullPath(), false /* Don't create stub files */ );
LoadProject( importProj.GetProj() );
if( sch.Exists() && !schCopy.SameAs( sch ) )
{
if( !wxCopyFile( sch.GetFullPath(), schCopy.GetFullPath(), true ) )
{
///< @todo Should we remove the newly created folder?
msg.Printf( _( "Cannot copy file '%s'\n"
"to '%s'\n"
"The project cannot be imported." ),
sch.GetFullPath(), schCopy.GetFullPath() );
wxMessageDialog schCopyErrorDlg( this, msg, _( "Error" ), wxOK_DEFAULT | wxICON_ERROR );
schCopyErrorDlg.ShowModal();
return;
}
}
wxFileName pcbCopy( pro );
pcbCopy.SetExt( aPcbFileExtension );
if( pcb.Exists() && !pcbCopy.SameAs( pcb ) )
{
if( !wxCopyFile( pcb.GetFullPath(), pcbCopy.GetFullPath(), true ) )
{
///< @todo Should we remove copied schematic file and the newly created folder?
msg.Printf( _( "Cannot copy file '%s'\n"
"to '%s'\n"
"The project cannot be imported." ),
pcb.GetFullPath(), pcbCopy.GetFullPath() );
wxMessageDialog brdCopyErrorDlg( this, msg, _( "Error" ), wxOK_DEFAULT | wxICON_ERROR );
brdCopyErrorDlg.ShowModal();
return;
}
}
CreateNewProject( pro.GetFullPath(), false /* Don't create stub files */ );
LoadProject( pro );
if( schCopy.FileExists() )
{
KIWAY_PLAYER* schframe = Kiway().Player( FRAME_SCH, true );
wxWindow* blocking_dialog = schframe->Kiway().GetBlockingDialog();
if( blocking_dialog )
blocking_dialog->Close( true );
packet = StrPrintf( "%d\n%s", aSchFileType, TO_UTF8( schCopy.GetFullPath() ) );
schframe->Kiway().ExpressMail( FRAME_SCH, MAIL_IMPORT_FILE, packet, this );
if( !schframe->IsShown() )
schframe->Show( true );
// On Windows, Raise() does not bring the window on screen, when iconized
if( schframe->IsIconized() )
schframe->Iconize( false );
schframe->Raise();
if( !schCopy.SameAs( sch ) ) // Do not delete the original file!
wxRemoveFile( schCopy.GetFullPath() );
}
if( pcbCopy.FileExists() )
{
KIWAY_PLAYER* pcbframe = Kiway().Player( FRAME_PCB_EDITOR, true );
wxWindow* blocking_dialog = pcbframe->Kiway().GetBlockingDialog();
if( blocking_dialog )
blocking_dialog->Close( true );
if( !pcbframe->IsVisible() )
pcbframe->Show( true );
packet = StrPrintf( "%d\n%s", aPcbFileType, TO_UTF8( pcbCopy.GetFullPath() ) );
pcbframe->Kiway().ExpressMail( FRAME_PCB_EDITOR, MAIL_IMPORT_FILE, packet, this );
// On Windows, Raise() does not bring the window on screen, when iconized
if( pcbframe->IsIconized() )
pcbframe->Iconize( false );
pcbframe->Raise();
if( !pcbCopy.SameAs( pcb ) ) // Do not delete the original file!
wxRemoveFile( pcbCopy.GetFullPath() );
}
importProj.AssociateFilesWithProj( aSchFileType, aPcbFileType );
ReCreateTreePrj();
m_active_project = true;

View File

@ -31,8 +31,10 @@
#include <build_version.h>
#include <dialogs/panel_kicad_launcher.h>
#include <eda_base_frame.h>
#include <executable_names.h>
#include <filehistory.h>
#include <policy_keys.h>
#include <gestfich.h>
#include <kiplatform/app.h>
#include <kiplatform/policy.h>
#include <kicad_build_version.h>
@ -226,6 +228,20 @@ KICAD_MANAGER_FRAME::KICAD_MANAGER_FRAME( wxWindow* parent, const wxString& titl
// Do not let the messages window have initial focus
m_leftWin->SetFocus();
// Init for dropping files
m_acceptedExts.emplace( ProjectFileExtension, &KICAD_MANAGER_ACTIONS::loadProject );
m_acceptedExts.emplace( LegacyProjectFileExtension, &KICAD_MANAGER_ACTIONS::loadProject );
for( const auto& ext : GerberFileExtensions )
m_acceptedExts.emplace( ext, &KICAD_MANAGER_ACTIONS::viewDroppedGerbers );
m_acceptedExts.emplace( DrillFileExtension, &KICAD_MANAGER_ACTIONS::viewDroppedGerbers );
// Eagle files import
m_acceptedExts.emplace( EagleSchematicFileExtension,
&KICAD_MANAGER_ACTIONS::importNonKicadProj );
m_acceptedExts.emplace( EaglePcbFileExtension, &KICAD_MANAGER_ACTIONS::importNonKicadProj );
// Cadstar files import
m_acceptedExts.emplace( CadstarSchematicFileExtension,
&KICAD_MANAGER_ACTIONS::importNonKicadProj );
m_acceptedExts.emplace( CadstarPcbFileExtension, &KICAD_MANAGER_ACTIONS::importNonKicadProj );
DragAcceptFiles( true );
// Ensure the window is on top
@ -397,20 +413,60 @@ void KICAD_MANAGER_FRAME::OnSize( wxSizeEvent& event )
event.Skip();
}
void KICAD_MANAGER_FRAME::OnDropFiles( wxDropFilesEvent& aEvent )
void KICAD_MANAGER_FRAME::DoWithAcceptedFiles()
{
wxString* files = aEvent.GetFiles();
for( int nb = 0; nb < aEvent.GetNumberOfFiles(); nb++ )
// All fileNames are now in m_AcceptedFiles vector.
// Check if contains a project file name and load project.
// If not, open files in dedicated app.
for( auto fileName : m_AcceptedFiles )
{
const wxFileName fn = wxFileName( files[nb] );
if( fn.GetExt() == "kicad_pro" || fn.GetExt() == "pro" )
if( IsExtensionAccepted( fileName.GetExt(),
{ ProjectFileExtension, LegacyProjectFileExtension } ) )
{
LoadProject( fn );
break;
wxString fn = fileName.GetFullPath();
m_toolManager->RunAction( *m_acceptedExts.at( fileName.GetExt() ), true, &fn );
return;
}
}
// Then stock gerber files in gerberFiles and run action for other files.
wxString gerberFiles;
// Gerbview editor should be able to open Gerber and drill files
std::vector<std::string> gerberExts( GerberFileExtensions );
gerberExts.push_back( DrillFileExtension );
for( auto fileName : m_AcceptedFiles )
{
if( IsExtensionAccepted( fileName.GetExt(), gerberExts ) )
{
gerberFiles += wxT( '\"' );
gerberFiles += fileName.GetFullPath() + wxT( '\"' );
gerberFiles = gerberFiles.Pad( 1 );
}
else
{
wxString fn = fileName.GetFullPath();
m_toolManager->RunAction( *m_acceptedExts.at( fileName.GetExt() ), true, &fn );
}
}
// Execute Gerbviewer
if( !gerberFiles.IsEmpty() )
{
wxString fullEditorName = FindKicadFile( GERBVIEW_EXE );
if( wxFileExists( fullEditorName ) )
{
wxString command = fullEditorName + " " + gerberFiles;
m_toolManager->RunAction( *m_acceptedExts.at( GerberFileExtension ),
true, &command );
}
}
}
bool KICAD_MANAGER_FRAME::canCloseWindow( wxCloseEvent& aEvent )
{
KICAD_SETTINGS* settings = kicadSettings();

View File

@ -166,11 +166,7 @@ private:
void setupTools();
void setupActions();
/**
* Handles event fired when a file is dropped to window.
* Opens project file. Does nothing if it is not a kicad project file.
*/
void OnDropFiles( wxDropFilesEvent& aEvent );
void DoWithAcceptedFiles() override;
APP_SETTINGS_BASE* config() const override;

View File

@ -107,15 +107,6 @@ static const wxChar* s_allowedExtensionsToList[] = {
};
/* TODO: Check if these file extension and wildcard definitions are used
* in any of the other KiCad programs and move them into the common
* library as required.
*/
// Gerber file extension wildcard.
const wxString GerberFileExtensionWildCard( ".((gbr|gbrjob|(gb|gt)[alops])|pho)" );
/**
* The frame that shows the tree list of files and subdirectories inside the working directory.
*
@ -1288,5 +1279,3 @@ void KICAD_MANAGER_FRAME::OnChangeWatchedPaths( wxCommandEvent& aEvent )
{
m_leftWin->FileWatcherReset();
}

View File

@ -65,6 +65,15 @@ TOOL_ACTION KICAD_MANAGER_ACTIONS::closeProject( "kicad.Control.closeProject",
_( "Close Project" ), _( "Close the current project" ),
BITMAPS::project_close );
TOOL_ACTION KICAD_MANAGER_ACTIONS::loadProject( "kicad.Control.loadProject",
AS_GLOBAL);
TOOL_ACTION KICAD_MANAGER_ACTIONS::importNonKicadProj( "kicad.Control.importNonKicadProj",
AS_GLOBAL );
TOOL_ACTION KICAD_MANAGER_ACTIONS::viewDroppedGerbers( "kicad.Control.viewDroppedGerbers",
AS_GLOBAL );
TOOL_ACTION KICAD_MANAGER_ACTIONS::editSchematic( "kicad.Control.editSchematic",
AS_GLOBAL,
MD_CTRL + 'E', LEGACY_HK_NAME( "Run Eeschema" ),
@ -129,5 +138,3 @@ TOOL_ACTION KICAD_MANAGER_ACTIONS::editOtherSch( "kicad.Control.editOtherSch",
TOOL_ACTION KICAD_MANAGER_ACTIONS::editOtherPCB( "kicad.Control.editOtherPCB",
AS_GLOBAL );

View File

@ -36,6 +36,9 @@ public:
static TOOL_ACTION openDemoProject;
static TOOL_ACTION openProject;
static TOOL_ACTION closeProject;
static TOOL_ACTION loadProject;
static TOOL_ACTION importNonKicadProj;
static TOOL_ACTION viewDroppedGerbers;
static TOOL_ACTION editSchematic;
static TOOL_ACTION editSymbols;

View File

@ -26,6 +26,7 @@
#include <kicad_manager_frame.h>
#include <kiplatform/policy.h>
#include <confirm.h>
#include <eda_tools.h>
#include <project/project_file.h>
#include <project/project_local_settings.h>
#include <settings/settings_manager.h>
@ -40,6 +41,10 @@
#include <wx/dir.h>
#include <wx/filedlg.h>
#include "dialog_pcm.h"
#include <macros.h>
#include <sch_io_mgr.h>
#include <io_mgr.h>
#include <import_proj.h>
#if wxCHECK_VERSION( 3, 1, 7 )
#include "widgets/filedlg_new_project.h"
@ -337,6 +342,95 @@ int KICAD_MANAGER_CONTROL::CloseProject( const TOOL_EVENT& aEvent )
}
int KICAD_MANAGER_CONTROL::ImportNonKicadProj( const TOOL_EVENT& aEvent )
{
if( !aEvent.Parameter<wxString*>() )
return -1;
wxFileName droppedFileName( *aEvent.Parameter<wxString*>() );
wxString schFileExtension, pcbFileExtension;
int schFileType, pcbFileType;
// Define extensions to use according to dropped file.
// Eagle project.
if( droppedFileName.GetExt() == EagleSchematicFileExtension
|| droppedFileName.GetExt() == EaglePcbFileExtension )
{
// Check if droppedFile is an eagle file.
// If not, return and do not import files.
if( !IsFileFromEDATool( droppedFileName, EAGLE ) )
return -1;
schFileExtension = EagleSchematicFileExtension;
pcbFileExtension = EaglePcbFileExtension;
schFileType = SCH_IO_MGR::SCH_EAGLE;
pcbFileType = IO_MGR::EAGLE;
}
else
{
// Cadstar project.
if( droppedFileName.GetExt() == CadstarSchematicFileExtension
|| droppedFileName.GetExt() == CadstarPcbFileExtension )
{
schFileExtension = CadstarSchematicFileExtension;
pcbFileExtension = CadstarPcbFileExtension;
schFileType = SCH_IO_MGR::SCH_CADSTAR_ARCHIVE;
pcbFileType = IO_MGR::CADSTAR_PCB_ARCHIVE;
}
else
return -1;
}
IMPORT_PROJ_HELPER importProj( m_frame, droppedFileName.GetFullPath(), schFileExtension,
pcbFileExtension );
// Check if the project directory is empty
wxDir directory( importProj.GetProjPath() );
if( directory.HasFiles() )
{
// Append a new directory with the same name of the project file
// Keep iterating until we find an empty directory
importProj.CreateEmptyDirForProject();
if( !wxMkdir( importProj.GetProjPath() ) )
return -1;
}
importProj.SetProjAbsolutePath();
if( !importProj.CopyImportedFiles( false ) )
{
wxRmdir( importProj.GetProjPath() ); // Remove the previous created directory, before leaving.
return -1;
}
m_frame->CloseProject( true );
m_frame->CreateNewProject( importProj.GetProjFullPath(), false /* Don't create stub files */ );
m_frame->LoadProject( importProj.GetProj() );
importProj.AssociateFilesWithProj( schFileType, pcbFileType );
m_frame->ReCreateTreePrj();
m_frame->LoadProject( importProj.GetProj() );
return 0;
}
int KICAD_MANAGER_CONTROL::LoadProject( const TOOL_EVENT& aEvent )
{
if( aEvent.Parameter<wxString*>() )
m_frame->LoadProject( wxFileName( *aEvent.Parameter<wxString*>() ) );
return 0;
}
int KICAD_MANAGER_CONTROL::ViewDroppedViewers( const TOOL_EVENT& aEvent )
{
if( aEvent.Parameter<wxString*>() )
wxExecute( *aEvent.Parameter<wxString*>(), wxEXEC_ASYNC );
return 0;
}
class SAVE_AS_TRAVERSER : public wxDirTraverser
{
public:
@ -815,12 +909,15 @@ int KICAD_MANAGER_CONTROL::ShowPluginManager( const TOOL_EVENT& aEvent )
void KICAD_MANAGER_CONTROL::setTransitions()
{
Go( &KICAD_MANAGER_CONTROL::NewProject, KICAD_MANAGER_ACTIONS::newProject.MakeEvent() );
Go( &KICAD_MANAGER_CONTROL::NewFromTemplate, KICAD_MANAGER_ACTIONS::newFromTemplate.MakeEvent() );
Go( &KICAD_MANAGER_CONTROL::OpenDemoProject, KICAD_MANAGER_ACTIONS::openDemoProject.MakeEvent() );
Go( &KICAD_MANAGER_CONTROL::OpenProject, KICAD_MANAGER_ACTIONS::openProject.MakeEvent() );
Go( &KICAD_MANAGER_CONTROL::CloseProject, KICAD_MANAGER_ACTIONS::closeProject.MakeEvent() );
Go( &KICAD_MANAGER_CONTROL::SaveProjectAs, ACTIONS::saveAs.MakeEvent() );
Go( &KICAD_MANAGER_CONTROL::NewProject, KICAD_MANAGER_ACTIONS::newProject.MakeEvent() );
Go( &KICAD_MANAGER_CONTROL::NewFromTemplate, KICAD_MANAGER_ACTIONS::newFromTemplate.MakeEvent() );
Go( &KICAD_MANAGER_CONTROL::OpenDemoProject, KICAD_MANAGER_ACTIONS::openDemoProject.MakeEvent() );
Go( &KICAD_MANAGER_CONTROL::OpenProject, KICAD_MANAGER_ACTIONS::openProject.MakeEvent() );
Go( &KICAD_MANAGER_CONTROL::CloseProject, KICAD_MANAGER_ACTIONS::closeProject.MakeEvent() );
Go( &KICAD_MANAGER_CONTROL::SaveProjectAs, ACTIONS::saveAs.MakeEvent() );
Go( &KICAD_MANAGER_CONTROL::LoadProject, KICAD_MANAGER_ACTIONS::loadProject.MakeEvent() );
Go( &KICAD_MANAGER_CONTROL::ImportNonKicadProj, KICAD_MANAGER_ACTIONS::importNonKicadProj.MakeEvent() );
Go( &KICAD_MANAGER_CONTROL::ViewDroppedViewers, KICAD_MANAGER_ACTIONS::viewDroppedGerbers.MakeEvent() );
Go( &KICAD_MANAGER_CONTROL::Refresh, ACTIONS::zoomRedraw.MakeEvent() );
Go( &KICAD_MANAGER_CONTROL::UpdateMenu, ACTIONS::updateMenu.MakeEvent() );

View File

@ -50,6 +50,15 @@ public:
int OpenDemoProject( const TOOL_EVENT& aEvent );
int CloseProject( const TOOL_EVENT& aEvent );
int SaveProjectAs( const TOOL_EVENT& aEvent );
int LoadProject( const TOOL_EVENT& aEvent );
/**
* @brief Imports a non kicad project from a sch/pcb dropped file.
* No error is displayed if the project can not be imported.
*/
int ImportNonKicadProj( const TOOL_EVENT& aEvent );
int ViewDroppedViewers( const TOOL_EVENT& aEvent );
int Refresh( const TOOL_EVENT& aEvent );
int UpdateMenu( const TOOL_EVENT& aEvent );

View File

@ -321,3 +321,9 @@ bool PL_EDITOR_FRAME::SaveDrawingSheetFile( const wxString& aFullFileName )
return false;
}
void PL_EDITOR_FRAME::DoWithAcceptedFiles()
{
for( wxFileName file : m_AcceptedFiles )
OpenProjectFiles( { file.GetFullPath() }, KICTL_CREATE );
}

View File

@ -33,6 +33,7 @@
#include <confirm.h>
#include <kiplatform/app.h>
#include <painter.h>
#include <wildcards_and_files_ext.h>
#include <tool/selection.h>
#include <tool/action_toolbar.h>
#include <tool/editor_conditions.h>
@ -72,6 +73,9 @@ BEGIN_EVENT_TABLE( PL_EDITOR_FRAME, EDA_DRAW_FRAME )
EVT_CHOICE( ID_SELECT_COORDINATE_ORIGIN, PL_EDITOR_FRAME::OnSelectCoordOriginCorner )
EVT_CHOICE( ID_SELECT_PAGE_NUMBER, PL_EDITOR_FRAME::OnSelectPage )
// Drop files event
EVT_DROP_FILES( PL_EDITOR_FRAME::OnDropFiles )
END_EVENT_TABLE()
@ -114,6 +118,9 @@ PL_EDITOR_FRAME::PL_EDITOR_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
LoadSettings( config() );
m_acceptedExts.emplace( DrawingSheetFileExtension, nullptr );
DragAcceptFiles( true );
wxSize pageSizeIU = GetPageLayout().GetPageSettings().GetSizeIU( IU_PER_MILS );
SetScreen( new BASE_SCREEN( pageSizeIU ) );

View File

@ -291,6 +291,8 @@ private:
wxString m_mruImagePath; // Most recently used path for placing a new image
// only on page 1, not on page 1
VECTOR2I m_grid_origin;
void DoWithAcceptedFiles() override;
};
#endif /* _PL_EDITOR_FRAME_H */

View File

@ -97,6 +97,10 @@ BEGIN_EVENT_TABLE( FOOTPRINT_EDIT_FRAME, PCB_BASE_FRAME )
EVT_UPDATE_UI( ID_ADD_FOOTPRINT_TO_BOARD,
FOOTPRINT_EDIT_FRAME::OnUpdateSaveFootprintToBoard )
EVT_UPDATE_UI( ID_TOOLBARH_PCB_SELECT_LAYER, FOOTPRINT_EDIT_FRAME::OnUpdateLayerSelectBox )
// Drop files event
EVT_DROP_FILES( FOOTPRINT_EDIT_FRAME::OnDropFiles )
END_EVENT_TABLE()
@ -237,6 +241,10 @@ FOOTPRINT_EDIT_FRAME::FOOTPRINT_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
// The selection filter doesn't need to grow in the vertical direction when docked
m_auimgr.GetPane( "SelectionFilter" ).dock_proportion = 0;
m_acceptedExts.emplace( KiCadFootprintLibPathExtension, &ACTIONS::ddAddLibrary );
m_acceptedExts.emplace( KiCadFootprintFileExtension, &PCB_ACTIONS::ddImportFootprint );
DragAcceptFiles( true );
ActivateGalCanvas();
FinishAUIInitialization();
@ -1260,4 +1268,4 @@ void FOOTPRINT_EDIT_FRAME::OnSaveFootprintAsPng( wxCommandEvent& event )
// to refresh the screen before creating the PNG or JPEG image from screen
wxYield();
SaveCanvasImageToFile( this, dlg.GetPath() );
}
}

View File

@ -175,6 +175,8 @@ BEGIN_EVENT_TABLE( PCB_EDIT_FRAME, PCB_BASE_FRAME )
PCB_EDIT_FRAME::OnUpdateSelectTrackWidth )
EVT_UPDATE_UI_RANGE( ID_POPUP_PCB_SELECT_VIASIZE1, ID_POPUP_PCB_SELECT_VIASIZE8,
PCB_EDIT_FRAME::OnUpdateSelectViaSize )
// Drop files event
EVT_DROP_FILES( PCB_EDIT_FRAME::OnDropFiles )
END_EVENT_TABLE()
@ -443,6 +445,10 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
m_eventCounterTimer->Start( 1000 );
}
m_acceptedExts.emplace( KiCadPcbFileExtension, &PCB_ACTIONS::ddAppendBoard );
m_acceptedExts.emplace( LegacyPcbFileExtension, &PCB_ACTIONS::ddAppendBoard );
DragAcceptFiles( true );
}
@ -2006,4 +2012,4 @@ void PCB_EDIT_FRAME::onSize( wxSizeEvent& aEvent )
// Skip() is called in the base class.
EDA_DRAW_FRAME::OnSize( aEvent );
}
}

View File

@ -1510,3 +1510,10 @@ TOOL_ACTION PCB_ACTIONS::lengthTunerSettingsDialog( "pcbnew.LengthTuner.Settings
_( "Length Tuning Settings..." ),
_( "Sets the length tuning parameters for currently routed item." ),
BITMAPS::router_len_tuner_setup );
TOOL_ACTION PCB_ACTIONS::ddAppendBoard( "pcbnew.Control.DdAppendBoard",
AS_GLOBAL );
TOOL_ACTION PCB_ACTIONS::ddImportFootprint( "pcbnew.Control.ddImportFootprint",
AS_GLOBAL );

View File

@ -500,6 +500,10 @@ public:
static TOOL_ACTION convertToLines;
static TOOL_ACTION convertToArc;
static TOOL_ACTION convertToTracks;
/// Drag and drop
static TOOL_ACTION ddAppendBoard;
static TOOL_ACTION ddImportFootprint;
};
#endif

View File

@ -43,6 +43,7 @@
#include <pcb_group.h>
#include <pcb_textbox.h>
#include <pcb_track.h>
#include <wildcards_and_files_ext.h>
#include <zone.h>
#include <fp_shape.h>
#include <fp_textbox.h>
@ -56,6 +57,7 @@
#include <properties.h>
#include <settings/color_settings.h>
#include <tool/tool_manager.h>
#include <footprint_edit_frame.h>
#include <widgets/wx_progress_reporters.h>
#include <widgets/infobar.h>
#include <wx/hyperlink.h>
@ -111,6 +113,23 @@ int PCB_CONTROL::AddLibrary( const TOOL_EVENT& aEvent )
}
int PCB_CONTROL::DdAddLibrary( const TOOL_EVENT& aEvent )
{
const wxString fn = *aEvent.Parameter<wxString*>();
static_cast<PCB_BASE_EDIT_FRAME*>( m_frame )->AddLibrary( fn );
return 0;
}
int PCB_CONTROL::DdImportFootprint( const TOOL_EVENT& aEvent )
{
const wxString fn = *aEvent.Parameter<wxString*>();
static_cast<FOOTPRINT_EDIT_FRAME*>( m_frame )->ImportFootprint( fn );
m_frame->Zoom_Automatique( false );
return 0;
}
int PCB_CONTROL::Quit( const TOOL_EVENT& aEvent )
{
m_frame->Close( false );
@ -1465,6 +1484,25 @@ int PCB_CONTROL::UpdateMessagePanel( const TOOL_EVENT& aEvent )
}
int PCB_CONTROL::DdAppendBoard( const TOOL_EVENT& aEvent )
{
wxFileName fileName = wxFileName( *aEvent.Parameter<wxString*>() );
int open_ctl = fileName.GetExt() == KiCadPcbFileExtension ? 0 : KICTL_EAGLE_BRD;
PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame );
if( !editFrame )
return 1;
wxString filePath = fileName.GetFullPath();
IO_MGR::PCB_FILE_T pluginType = plugin_type( filePath, open_ctl );
PLUGIN::RELEASER pi( IO_MGR::PluginFind( pluginType ) );
return AppendBoard( *pi, filePath );
}
int PCB_CONTROL::FlipPcbView( const TOOL_EVENT& aEvent )
{
view()->SetMirror( !view()->IsMirroredX(), false );
@ -1549,6 +1587,7 @@ void PCB_CONTROL::setTransitions()
// Append control
Go( &PCB_CONTROL::AppendBoardFromFile, PCB_ACTIONS::appendBoard.MakeEvent() );
Go( &PCB_CONTROL::DdAppendBoard, PCB_ACTIONS::ddAppendBoard.MakeEvent() );
Go( &PCB_CONTROL::Paste, ACTIONS::paste.MakeEvent() );
Go( &PCB_CONTROL::Paste, ACTIONS::pasteSpecial.MakeEvent() );
@ -1558,4 +1597,8 @@ void PCB_CONTROL::setTransitions()
Go( &PCB_CONTROL::UpdateMessagePanel, EVENTS::UnselectedEvent );
Go( &PCB_CONTROL::UpdateMessagePanel, EVENTS::ClearedEvent );
Go( &PCB_CONTROL::UpdateMessagePanel, EVENTS::SelectedItemsModified );
// Add library by dropping file
Go( &PCB_CONTROL::DdAddLibrary, ACTIONS::ddAddLibrary.MakeEvent() );
Go( &PCB_CONTROL::DdImportFootprint, PCB_ACTIONS::ddImportFootprint.MakeEvent() );
}

View File

@ -98,6 +98,11 @@ public:
int FlipPcbView( const TOOL_EVENT& aEvent );
// Drag and drop
int DdAppendBoard( const TOOL_EVENT& aEvent );
int DdAddLibrary( const TOOL_EVENT& aEvent );
int DdImportFootprint( const TOOL_EVENT& aEvent );
private:
///< Sets up handlers for various events.
void setTransitions() override;