KiCad PCB EDA Suite
panel_hotkeys_editor.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KICAD, a free EDA CAD application.
3  *
4  * Copyright (C) 1992-2020 Kicad Developers, see AUTHORS.txt for contributors.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #include <advanced_config.h>
25 #include <gestfich.h>
26 #include <hotkeys_basic.h>
27 #include <kiway_player.h>
28 #include <locale_io.h>
29 #include <panel_hotkeys_editor.h>
30 #include <tool/tool_manager.h>
32 #include <widgets/ui_common.h>
33 #include <wx/filedlg.h>
34 #include <wx/panel.h>
35 #include <wx/sizer.h>
36 #include <wx/srchctrl.h>
37 #include <wx/tokenzr.h>
38 #include <wx/txtstrm.h>
39 #include <wx/wfstream.h>
40 
41 static const wxSize default_dialog_size { 500, 350 };
42 
51 static wxSearchCtrl* CreateTextFilterBox( wxWindow* aParent, const wxString& aDescriptiveText )
52 {
53  wxSearchCtrl* search_widget = new wxSearchCtrl( aParent, wxID_ANY );
54 
55  search_widget->ShowSearchButton( false );
56  search_widget->ShowCancelButton( true );
57 
58  search_widget->SetDescriptiveText( aDescriptiveText );
59 
60  return search_widget;
61 }
62 
63 
65  bool aReadOnly ) :
66  RESETTABLE_PANEL( aWindow, wxID_ANY, wxDefaultPosition, default_dialog_size ),
67  m_frame( aFrame ),
68  m_readOnly( aReadOnly ),
69  m_hotkeyStore()
70 {
71  const auto margin = KIUI::GetStdMargin();
72  wxBoxSizer* mainSizer = new wxBoxSizer( wxVERTICAL );
73 
74  const int side_margins = margin * 2;
75  wxBoxSizer* bMargins = new wxBoxSizer( wxVERTICAL );
76 
77  wxSearchCtrl* filterSearch = CreateTextFilterBox( this, _( "Type filter text" ) );
78  bMargins->Add( filterSearch, 0, wxALL | wxEXPAND, margin );
79 
81  bMargins->Add( m_hotkeyListCtrl, 1, wxALL | wxEXPAND, margin );
82 
83  if( !m_readOnly )
84  installButtons( bMargins );
85 
86  mainSizer->Add( bMargins, 1, wxEXPAND | wxRIGHT | wxLEFT, side_margins );
87 
88 #ifdef __WXGTK__
89  // Work around a bug that clips the text vertically in the wxSearchCtrl on GTK
90  filterSearch->SetMinSize( wxSize( filterSearch->GetSize().x,
91  int( filterSearch->GetSize().y * 1.6 ) ) );
92 #endif
93 
94  SetSizer( mainSizer );
95  Layout();
96 
97  // Connect Events
98  filterSearch->Bind( wxEVT_COMMAND_TEXT_UPDATED, &PANEL_HOTKEYS_EDITOR::OnFilterSearch, this );
99 }
100 
101 
103 {
104  m_toolManagers.push_back( aToolMgr );
105 }
106 
107 
109 {
111 }
112 
113 
115 {
116  BUTTON_ROW_PANEL::BTN_DEF_LIST l_btn_defs = {
117  {
118  wxID_RESET,
119  _( "Undo All Changes" ),
120  _( "Undo all changes made so far in this dialog" ),
121  [this]( wxCommandEvent& )
122  {
124  }
125  },
126  {
127  wxID_ANY,
128  _( "Import Hotkeys..." ),
129  _( "Import hotkey definitions from an external file, replacing the current values" ),
130  [this]( wxCommandEvent& )
131  {
132  ImportHotKeys();
133  }
134  }
135  };
136 
137 
138  if( ADVANCED_CFG::GetCfg().m_HotkeysDumper )
139  {
140  // Add hotkeys dumper (does not need translation, it's a dev tool only)
141  l_btn_defs.push_back( {
142  wxID_ANY, wxT( "Dump Hotkeys" ), wxEmptyString,
143  [this]( wxCommandEvent& )
144  {
145  dumpHotkeys();
146  }
147  } );
148  }
149 
150  const BUTTON_ROW_PANEL::BTN_DEF_LIST r_btn_defs = {
151  };
152 
153  auto btnPanel = std::make_unique<BUTTON_ROW_PANEL>( this, l_btn_defs, r_btn_defs );
154 
155  aSizer->Add( btnPanel.release(), 0, wxEXPAND | wxTOP, KIUI::GetStdMargin() );
156 }
157 
158 
160 {
163 }
164 
165 
167 {
169  return false;
170 
171  if( m_readOnly )
172  return true;
173 
174  // save the hotkeys
175  for( TOOL_MANAGER* toolMgr : m_toolManagers )
176  WriteHotKeyConfig( toolMgr->GetActions() );
177 
178  return true;
179 }
180 
181 
182 void PANEL_HOTKEYS_EDITOR::OnFilterSearch( wxCommandEvent& aEvent )
183 {
184  const auto searchStr = aEvent.GetString();
185  m_hotkeyListCtrl->ApplyFilterString( searchStr );
186 }
187 
188 
190 {
191  wxString ext = DEFAULT_HOTKEY_FILENAME_EXT;
192  wxString mask = wxT( "*." ) + ext;
193  wxString filename = EDA_FILE_SELECTOR( _( "Import Hotkeys File:" ), m_frame->GetMruPath(),
194  wxEmptyString, ext, mask, this, wxFD_OPEN, true );
195 
196  if( filename.IsEmpty() )
197  return;
198 
199  std::map<std::string, int> importedHotKeys;
200  ReadHotKeyConfig( filename, importedHotKeys );
201  m_frame->SetMruPath( wxFileName( filename ).GetPath() );
202 
203  // Overlay the imported hotkeys onto the hotkey store
204  for( HOTKEY_SECTION& section: m_hotkeyStore.GetSections() )
205  {
206  for( HOTKEY& hotkey: section.m_HotKeys )
207  {
208  if( importedHotKeys.count( hotkey.m_Actions[ 0 ]->GetName() ) )
209  hotkey.m_EditKeycode = importedHotKeys[ hotkey.m_Actions[ 0 ]->GetName() ];
210  }
211  }
212 
214 }
215 
216 
218 {
219  wxString filename = EDA_FILE_SELECTOR( wxT( "Dump Hotkeys File:" ), m_frame->GetMruPath(),
220  wxEmptyString, wxT( "txt" ), wxT( "*.txt" ), this,
221  wxFD_SAVE, true );
222 
223  if( filename.IsEmpty() )
224  return;
225 
226  wxFileName fn( filename );
227 
228  wxFFileOutputStream fileStream( fn.GetFullPath(), "w" );
229  wxTextOutputStream stream( fileStream );
230 
231  if( !fn.IsDirWritable() || ( fn.Exists() && !fn.IsFileWritable() ) )
232  return;
233 
234  for( HOTKEY_SECTION& section : m_hotkeyStore.GetSections() )
235  {
236  stream << wxT( "=== " ) << section.m_SectionName << endl << endl;
237 
238  stream << wxT( "[width=\"100%\",options=\"header\",cols=\"20%,15%,65%\"]" ) << endl;
239  stream << wxT( "|===" ) << endl;
240  stream << _( "| Action | Default Hotkey | Description" ) << endl;
241 
242  for( HOTKEY& hk : section.m_HotKeys )
243  {
244  stream << wxT( "| " ) << hk.m_Actions[0]->GetLabel() << endl;
245 
246  if( hk.m_EditKeycode > 0 )
247  {
248  stream << wxT( " | kbd:[" ) << KeyNameFromKeyCode( hk.m_EditKeycode ) << ']'
249  << endl;
250  }
251  else
252  {
253  stream << wxT( " |" ) << endl;
254  }
255 
256  stream << wxT( " | " ) << hk.m_Actions[0]->GetDescription( false ) << endl;
257  }
258 
259  stream << wxT( "|===" ) << endl << endl;
260  }
261 
262  stream.Flush();
263  fileStream.Close();
264 }
void OnFilterSearch(wxCommandEvent &aEvent)
Handle a change in the hotkey filter text.
static wxSearchCtrl * CreateTextFilterBox(wxWindow *aParent, const wxString &aDescriptiveText)
Helper function to add a filter box to a panel, with some sensible defaults for that purpose.
void SetMruPath(const wxString &aPath)
static const wxSize default_dialog_size
This file is part of the common library TODO brief description.
void ImportHotKeys()
Put up a dialog allowing the user to select a hotkeys file and then overlays those hotkeys onto the c...
void ResetPanel() override
Reset the contents of this panel.
bool TransferDataToControl()
Method TransferDataToControl Load the hotkey data from the store into the control.
void ReadHotKeyConfig(const wxString &aFileName, std::map< std::string, int > &aHotKeys)
Reads a hotkey config file into a map.
void AddHotKeys(TOOL_MANAGER *aToolMgr)
int GetStdMargin()
Get the standard margin around a widget in the KiCad UI.
Definition: ui_common.cpp:30
std::vector< TOOL_MANAGER * > m_toolManagers
EDA_BASE_FRAME * m_frame
Master controller class:
Definition: tool_manager.h:54
wxString GetMruPath() const
void installButtons(wxSizer *aSizer)
Install the button panel (global reset/default, import/export)
wxString EDA_FILE_SELECTOR(const wxString &aTitle, const wxString &aPath, const wxString &aFileName, const wxString &aExtension, const wxString &aWildcard, wxWindow *aParent, int aStyle, const bool aKeepWorkingDirectory, const wxPoint &aPosition, wxString *aMruPath)
A helper function that wraps a call to wxFileSelector.
Definition: gestfich.cpp:52
Functions to provide common constants and other functions to assist in making a consistent UI.
#define _(s)
void ApplyFilterString(const wxString &aFilterStr)
Method ApplyFilterString Apply a filter string to the hotkey list, selecting which hotkeys to show.
void dumpHotkeys()
Dumps all actions and their hotkeys to a text file for inclusion in documentation.
bool TransferDataFromWindow() override
std::vector< TOOL_ACTION * > m_Actions
Definition: hotkey_store.h:36
bool TransferDataToWindow() override
std::vector< HOTKEY_SECTION > & GetSections()
Get the list of sections managed by this store.
The base frame for deriving all KiCad main window classes.
std::vector< BTN_DEF > BTN_DEF_LIST
A list of BTN_DEFs, used to group buttons into the left/right groups.
wxString KeyNameFromKeyCode(int aKeycode, bool *aIsFound)
Return the key name from the key code.
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
void Init(std::vector< TOOL_MANAGER * > aToolManagerList, bool aIncludeReadOnlyCmds)
PANEL_HOTKEYS_EDITOR(EDA_BASE_FRAME *aFrame, wxWindow *aWindow, bool aReadOnly)
WIDGET_HOTKEY_LIST * m_hotkeyListCtrl
#define DEFAULT_HOTKEY_FILENAME_EXT
Definition: hotkeys_basic.h:30
int m_EditKeycode
Definition: hotkey_store.h:37
A wxPanel that is designed to be reset in a standard manner.
int WriteHotKeyConfig(const std::map< std::string, TOOL_ACTION * > &aActionMap)
Update the hotkeys config file with the hotkeys from the given actions map.
void ResetAllHotkeys(bool aResetToDefault)
Set hotkeys in the control to default or original values.
bool TransferDataFromControl()
Method TransferDataFromControl Save the hotkey data from the control.