KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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-2024 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>
31#include <tool/tool_manager.h>
33#include <widgets/ui_common.h>
34#include <wx/filedlg.h>
35#include <wx/sizer.h>
36#include <wx/srchctrl.h>
37#include <wx/txtstrm.h>
38#include <wx/wfstream.h>
39
40
49static wxSearchCtrl* CreateTextFilterBox( wxWindow* aParent, const wxString& aDescriptiveText )
50{
51 wxSearchCtrl* search_widget = new wxSearchCtrl( aParent, wxID_ANY );
52
53 search_widget->ShowSearchButton( false );
54 search_widget->ShowCancelButton( true );
55
56 search_widget->SetDescriptiveText( aDescriptiveText );
57
58#ifdef __WXGTK__
59 // wxSearchCtrl vertical height is not calculated correctly on some GTK setups
60 // See https://gitlab.com/kicad/code/kicad/-/issues/9019
61 search_widget->SetMinSize( wxSize( -1, aParent->GetTextExtent( wxT( "qb" ) ).y + 10 ) );
62#endif
63
64 return search_widget;
65}
66
67
69 bool aReadOnly ) :
70 RESETTABLE_PANEL( aWindow, wxID_ANY, wxDefaultPosition, wxDefaultSize ),
71 m_frame( aFrame ),
72 m_readOnly( aReadOnly ),
73 m_hotkeyStore()
74{
75 wxBoxSizer* mainSizer = new wxBoxSizer( wxVERTICAL );
76 wxBoxSizer* bMargins = new wxBoxSizer( wxVERTICAL );
77
78 m_filterSearch = CreateTextFilterBox( this, _( "Type filter text" ) );
79 bMargins->Add( m_filterSearch, 0, wxEXPAND, 0 );
80
82 bMargins->Add( m_hotkeyListCtrl, 1, wxEXPAND | wxTOP, 5 );
83
84 if( !m_readOnly )
85 installButtons( bMargins );
86
87 mainSizer->Add( bMargins, 1, wxEXPAND, 0 );
88
89#ifdef __WXGTK__
90
91 // It appears that this may have been fixed in wxWidgets 3.2.3.
92#if wxVERSION_NUMBER < 3203
93
94 // Work around a bug that clips the text vertically in the wxSearchCtrl on GTK
95 m_filterSearch->SetMinSize(
96 wxSize( m_filterSearch->GetSize().x, int( m_filterSearch->GetSize().y * 1.6 ) ) );
97#endif
98
99#endif
100
101 SetSizer( mainSizer );
102 Layout();
103 mainSizer->Fit( this );
104
105 // Connect Events
106 m_filterSearch->Bind( wxEVT_COMMAND_TEXT_UPDATED, &PANEL_HOTKEYS_EDITOR::OnFilterSearch, this );
107}
108
109
111{
112 m_filterSearch->Unbind( wxEVT_COMMAND_TEXT_UPDATED, &PANEL_HOTKEYS_EDITOR::OnFilterSearch,
113 this );
114}
115
116
118{
120}
121
122
124{
125 BUTTON_ROW_PANEL::BTN_DEF_LIST l_btn_defs = {
126 {
127 wxID_RESET,
128 _( "Undo All Changes" ),
129 _( "Undo all changes made so far in this dialog" ),
130 [this]( wxCommandEvent& )
131 {
133 }
134 },
135 {
136 wxID_ANY,
137 _( "Import Hotkeys..." ),
138 _( "Import hotkey definitions from an external file, replacing the current values" ),
139 [this]( wxCommandEvent& )
140 {
142 }
143 }
144 };
145
146 if( ADVANCED_CFG::GetCfg().m_HotkeysDumper )
147 {
148 // Add hotkeys dumper (does not need translation, it's a dev tool only)
149 l_btn_defs.push_back( {
150 wxID_ANY, wxT( "Dump Hotkeys" ), wxEmptyString,
151 [this]( wxCommandEvent& )
152 {
153 dumpHotkeys();
154 }
155 } );
156 }
157
158 const BUTTON_ROW_PANEL::BTN_DEF_LIST r_btn_defs = {
159 };
160
161 auto btnPanel = std::make_unique<BUTTON_ROW_PANEL>( this, l_btn_defs, r_btn_defs );
162
163 aSizer->Add( btnPanel.release(), 0, wxEXPAND | wxALL, KIUI::GetStdMargin() * 2 );
164}
165
166
168{
170
172 return false;
173
174 return true;
175}
176
177
179{
180 if( m_readOnly )
181 return true;
182
184 return false;
185
187
188 return true;
189}
190
191
192void PANEL_HOTKEYS_EDITOR::OnFilterSearch( wxCommandEvent& aEvent )
193{
194 const auto searchStr = aEvent.GetString();
196}
197
198
200{
201 wxString filename = wxFileSelector( _( "Import Hotkeys File:" ), m_frame->GetMruPath(),
202 wxEmptyString, FILEEXT::HotkeyFileExtension,
203 FILEEXT::HotkeyFileWildcard(), wxFD_OPEN,
204 wxGetTopLevelParent( this ) );
205
206 if( filename.IsEmpty() )
207 return;
208
209 std::map<std::string, std::pair<int, int>> importedHotKeys;
210 ReadHotKeyConfig( filename, importedHotKeys );
211 m_frame->SetMruPath( wxFileName( filename ).GetPath() );
212
213 // Overlay the imported hotkeys onto the hotkey store
214 for( HOTKEY_SECTION& section: m_hotkeyStore.GetSections() )
215 {
216 for( HOTKEY& hotkey: section.m_HotKeys )
217 {
218 if( importedHotKeys.count( hotkey.m_Actions[ 0 ]->GetName() ) )
219 {
220 hotkey.m_EditKeycode = importedHotKeys[ hotkey.m_Actions[ 0 ]->GetName() ].first;
221 hotkey.m_EditKeycodeAlt = importedHotKeys[ hotkey.m_Actions[ 0 ]->GetName() ].second;
222 }
223 }
224 }
225
227}
228
229
231{
232 wxString filename = wxFileSelector( wxT( "Hotkeys File" ), m_frame->GetMruPath(),
233 wxEmptyString, FILEEXT::TextFileExtension,
235 wxFD_SAVE, wxGetTopLevelParent( this ) );
236
237 if( filename.IsEmpty() )
238 return;
239
240 wxFileName fn( filename );
241
242 wxFFileOutputStream fileStream( fn.GetFullPath(), "w" );
243 wxTextOutputStream stream( fileStream );
244
245 if( !fn.IsDirWritable() || ( fn.Exists() && !fn.IsFileWritable() ) )
246 return;
247
248 for( HOTKEY_SECTION& section : m_hotkeyStore.GetSections() )
249 {
250 stream << wxT( "=== " ) << section.m_SectionName << endl << endl;
251
252 stream << wxT( "[width=\"100%\",options=\"header\",cols=\"20%,15%,65%\"]" ) << endl;
253 stream << wxT( "|===" ) << endl;
254 stream << _( "| Action | Default Hotkey | Description" ) << endl;
255
256 for( HOTKEY& hk : section.m_HotKeys )
257 {
258 stream << wxT( "| " ) << hk.m_Actions[0]->GetFriendlyName() << endl;
259
260 if( hk.m_EditKeycode > 0 )
261 {
262 stream << wxT( " | kbd:[" ) << KeyNameFromKeyCode( hk.m_EditKeycode ) << ']'
263 << endl;
264 }
265 else
266 {
267 stream << wxT( " |" ) << endl;
268 }
269
270 stream << wxT( " | " ) << hk.m_Actions[0]->GetDescription() << endl;
271 }
272
273 stream << wxT( "|===" ) << endl << endl;
274 }
275
276 stream.Flush();
277 fileStream.Close();
278}
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
std::vector< BTN_DEF > BTN_DEF_LIST
A list of BTN_DEFs, used to group buttons into the left/right groups.
The base frame for deriving all KiCad main window classes.
wxString GetMruPath() const
void SetMruPath(const wxString &aPath)
void Init(std::vector< TOOL_ACTION * > aActionsList, bool aIncludeReadOnlyCmds)
std::vector< HOTKEY_SECTION > & GetSections()
Get the list of sections managed by this store.
PANEL_HOTKEYS_EDITOR(EDA_BASE_FRAME *aFrame, wxWindow *aWindow, bool aReadOnly)
void OnFilterSearch(wxCommandEvent &aEvent)
Handle a change in the hotkey filter text.
void ResetPanel() override
Reset the contents of this panel.
std::vector< TOOL_ACTION * > m_actions
void installButtons(wxSizer *aSizer)
Install the button panel (global reset/default, import/export)
WIDGET_HOTKEY_LIST * m_hotkeyListCtrl
EDA_BASE_FRAME * m_frame
bool TransferDataToWindow() override
void ImportHotKeys()
Put up a dialog allowing the user to select a hotkeys file and then overlays those hotkeys onto the c...
void dumpHotkeys()
Dump all actions and their hotkeys to a text file for inclusion in documentation.
wxSearchCtrl * m_filterSearch
bool TransferDataFromWindow() override
A wxPanel that is designed to be reset in a standard manner.
void ResetAllHotkeys(bool aResetToDefault)
Set hotkeys in the control to default or original values.
bool TransferDataToControl()
Method TransferDataToControl Load the hotkey data from the store into the control.
bool TransferDataFromControl()
Method TransferDataFromControl Save the hotkey data from the control.
void ApplyFilterString(const wxString &aFilterStr)
Method ApplyFilterString Apply a filter string to the hotkey list, selecting which hotkeys to show.
#define _(s)
static const std::string TextFileExtension
static const std::string HotkeyFileExtension
static wxString HotkeyFileWildcard()
static wxString TextFileWildcard()
void ReadHotKeyConfig(const wxString &aFileName, std::map< std::string, std::pair< int, int > > &aHotKeys)
Reads a hotkey config file into a map.
wxString KeyNameFromKeyCode(int aKeycode, bool *aIsFound)
Return the key name from the key code.
int WriteHotKeyConfig(const std::vector< TOOL_ACTION * > &aActions)
Update the hotkeys config file with the hotkeys from the given actions map.
KICOMMON_API int GetStdMargin()
Get the standard margin around a widget in the KiCad UI.
Definition: ui_common.cpp:48
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.
int m_EditKeycodeAlt
Definition: hotkey_store.h:38
int m_EditKeycode
Definition: hotkey_store.h:37
std::vector< TOOL_ACTION * > m_Actions
Definition: hotkey_store.h:36
Functions to provide common constants and other functions to assist in making a consistent UI.
Definition of file extensions used in Kicad.