KiCad PCB EDA Suite
hotkey_store.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-2019 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 <hotkey_store.h>
25 #include <eda_base_frame.h>
26 #include <tool/tool_manager.h>
27 #include <tool/action_manager.h>
28 #include <tool/tool_event.h>
29 #include <tool/tool_action.h>
30 #include <advanced_config.h>
31 
32 class PSEUDO_ACTION : public TOOL_ACTION
33 {
34 public:
35  PSEUDO_ACTION( const wxString& aLabel, int aHotKey )
36  {
37  m_label = aLabel;
38  m_hotKey = aHotKey;
39  }
40 };
41 
43  new PSEUDO_ACTION( _( "Pan Left/Right" ), MD_CTRL + PSEUDO_WXK_WHEEL ),
44  new PSEUDO_ACTION( _( "Pan Up/Down" ), MD_SHIFT + PSEUDO_WXK_WHEEL ),
45  new PSEUDO_ACTION( _( "Finish Drawing" ), PSEUDO_WXK_DBLCLICK ),
46  new PSEUDO_ACTION( _( "Add to Selection" ), MD_SHIFT + PSEUDO_WXK_CLICK ),
47  new PSEUDO_ACTION( _( "Highlight Net" ), MD_ALT + PSEUDO_WXK_CLICK ),
48  new PSEUDO_ACTION( _( "Remove from Selection" ), MD_SHIFT + MD_ALT + PSEUDO_WXK_CLICK ),
49  new PSEUDO_ACTION( _( "Ignore Grid Snaps" ), MD_CTRL ),
50  new PSEUDO_ACTION( _( "Ignore Other Snaps" ), MD_SHIFT ),
51 };
52 
54 #ifndef __WINDOWS__
55  new PSEUDO_ACTION( _( "Close" ), MD_CTRL + 'W' ),
56 #endif
57  new PSEUDO_ACTION( _( "Quit" ), MD_CTRL + 'Q' )
58 };
59 
60 
62 {
63  wxString name( aAction->GetName() );
64  return name.BeforeFirst( '.' );
65 }
66 
67 
69 {
70  std::map<wxString, wxString> s_AppNames = {
71  { wxT( "common" ), _( "Common" ) },
72  { wxT( "kicad" ), _( "Project Manager" ) },
73  { wxT( "eeschema" ), _( "Schematic Editor" ) },
74  { wxT( "pcbnew" ), _( "PCB Editor" ) },
75  { wxT( "plEditor" ), _( "Drawing Sheet Editor" ), },
76  { wxT( "3DViewer" ), _( "3D Viewer" ) }
77  };
78 
79  wxString appName = GetAppName( aAction );
80 
81  if( s_AppNames.count( appName ) )
82  return s_AppNames[ appName ];
83  else
84  return appName;
85 }
86 
87 
89 {
90 }
91 
92 
93 void HOTKEY_STORE::Init( std::vector<TOOL_MANAGER*> aToolManagerList, bool aIncludeReadOnlyCmds )
94 {
95  m_toolManagers = std::move( aToolManagerList );
96 
97  // Collect all action maps into a single master map. This will re-group everything
98  // and collect duplicates together
99  std::map<std::string, HOTKEY> masterMap;
100 
101  for( TOOL_MANAGER* toolMgr : m_toolManagers )
102  {
103  for( const std::pair<const std::string, TOOL_ACTION*>& entry : toolMgr->GetActions() )
104  {
105  // Internal actions probably shouldn't be allowed hotkeys
106  if( entry.second->GetLabel().IsEmpty() )
107  continue;
108 
110  {
111  if( entry.second->GetName() == "pcbnew.Control.zoneDisplayOutlines"
112  || entry.second->GetName() == "pcbnew.Control.zoneDisplayTesselation" )
113  {
114  continue;
115  }
116  }
117 
118  HOTKEY& hotkey = masterMap[ entry.first ];
119  hotkey.m_Actions.push_back( entry.second );
120  hotkey.m_EditKeycode = entry.second->GetHotKey();
121  }
122  }
123 
124  wxString currentApp;
125  HOTKEY_SECTION* currentSection = nullptr;
126 
127  // If a previous list was built, ensure this previous list is cleared:
128  m_hk_sections.clear();
129 
130  for( const std::pair<const std::string, HOTKEY>& entry : masterMap )
131  {
132  TOOL_ACTION* entryAction = entry.second.m_Actions[ 0 ];
133  wxString entryApp = GetAppName( entryAction );
134 
135  if( !currentSection || entryApp != currentApp )
136  {
137  m_hk_sections.emplace_back( HOTKEY_SECTION() );
138  currentApp = entryApp;
139  currentSection = &m_hk_sections.back();
140  currentSection->m_SectionName = GetSectionName( entryAction );
141 
142  if( aIncludeReadOnlyCmds && currentApp == "common" )
143  {
144  for( TOOL_ACTION* command : g_standardPlatformCommands )
145  currentSection->m_HotKeys.emplace_back( HOTKEY( command ) );
146  }
147  }
148 
149  currentSection->m_HotKeys.emplace_back( HOTKEY( entry.second ) );
150  }
151 
152  if( aIncludeReadOnlyCmds )
153  {
154  m_hk_sections.emplace_back( HOTKEY_SECTION() );
155  currentSection = &m_hk_sections.back();
156  currentSection->m_SectionName = _( "Gestures" );
157 
158  for( TOOL_ACTION* gesture : g_gesturePseudoActions )
159  currentSection->m_HotKeys.emplace_back( HOTKEY( gesture ) );
160  }
161 }
162 
163 
164 std::vector<HOTKEY_SECTION>& HOTKEY_STORE::GetSections()
165 {
166  return m_hk_sections;
167 }
168 
169 
171 {
172  for( HOTKEY_SECTION& section : m_hk_sections )
173  {
174  for( HOTKEY& hotkey : section.m_HotKeys )
175  {
176  for( TOOL_ACTION* action : hotkey.m_Actions )
177  action->SetHotKey( hotkey.m_EditKeycode );
178  }
179  }
180 }
181 
182 
184 {
185  for( HOTKEY_SECTION& section : m_hk_sections )
186  {
187  for( HOTKEY& hotkey : section.m_HotKeys )
188  hotkey.m_EditKeycode = hotkey.m_Actions[ 0 ]->GetDefaultHotKey();
189  }
190 }
191 
192 
194 {
195  for( HOTKEY_SECTION& section : m_hk_sections )
196  {
197  for( HOTKEY& hotkey : section.m_HotKeys )
198  hotkey.m_EditKeycode = hotkey.m_Actions[ 0 ]->GetHotKey();
199  }
200 }
201 
202 
203 bool HOTKEY_STORE::CheckKeyConflicts( TOOL_ACTION* aAction, long aKey, HOTKEY** aConflict )
204 {
205  wxString sectionName = GetSectionName( aAction );
206 
207  // Create a fake "TOOL_ACTION" so we can get the section name for "Common" through the API.
208  // Simply declaring a wxString with the value "Common" works, but the goal is to futureproof
209  // the code here as much as possible.
210  TOOL_ACTION commonAction( "common.Control.Fake", AS_GLOBAL, 0, "", "", "" );
211  wxString commonName = GetSectionName( &commonAction );
212 
213  for( HOTKEY_SECTION& section : m_hk_sections )
214  {
215  // We can have the same hotkey in multiple sections (i.e. Kicad programs), but if a hotkey
216  // is in "Common" it can't be in any other section and vice versa.
217 
218  if( !( section.m_SectionName == sectionName || section.m_SectionName == commonName ) )
219  continue;
220 
221  for( HOTKEY& hotkey : section.m_HotKeys )
222  {
223  if( hotkey.m_Actions[0] == aAction )
224  continue;
225 
226  if( hotkey.m_EditKeycode == aKey )
227  {
228  // We can use the same key for a different action if both actions are contextual and
229  // for different tools.
230  if( hotkey.m_Actions[0]->GetScope() == AS_CONTEXT &&
231  aAction->GetScope() == AS_CONTEXT &&
232  hotkey.m_Actions[0]->GetToolName() != aAction->GetToolName() )
233  {
234  continue;
235  }
236 
237  *aConflict = &hotkey;
238  return true;
239  }
240  }
241  }
242 
243  return false;
244 }
wxString m_label
Definition: tool_action.h:200
#define PSEUDO_WXK_WHEEL
Definition: hotkeys_basic.h:51
void SaveAllHotkeys()
Persist all changes to hotkeys in the store to the underlying data structures.
std::vector< HOTKEY > m_HotKeys
Definition: hotkey_store.h:54
Master controller class:
Definition: tool_manager.h:54
HOTKEY_STORE()
Construct a HOTKEY_STORE from a list of hotkey sections.
bool m_ExtraZoneDisplayModes
When true, adds zone-diaplay-modes for stroking the zone fracture boundaries and the zone triangulati...
TOOL_ACTION_SCOPE GetScope() const
Definition: tool_action.h:147
std::vector< TOOL_MANAGER * > m_toolManagers
Definition: hotkey_store.h:110
static PSEUDO_ACTION * g_gesturePseudoActions[]
static wxString GetAppName(TOOL_ACTION *aAction)
#define PSEUDO_WXK_CLICK
Definition: hotkeys_basic.h:49
void ResetAllHotkeysToDefault()
Reset every hotkey in the store to the default values.
Base window classes and related definitions.
Action belongs to a particular tool (i.e. a part of a pop-up menu)
#define _(s)
void SetHotKey(int aKeycode)
bool CheckKeyConflicts(TOOL_ACTION *aAction, long aKey, HOTKEY **aConflict)
Check whether the given key conflicts with anything in this store.
std::string GetToolName() const
Return name of the tool associated with the action.
std::vector< TOOL_ACTION * > m_Actions
Definition: hotkey_store.h:36
static PSEUDO_ACTION * g_standardPlatformCommands[]
std::vector< HOTKEY_SECTION > & GetSections()
Get the list of sections managed by this store.
const char * name
Definition: DXF_plotter.cpp:56
Global action (toolbar/main menu event, global shortcut)
std::vector< HOTKEY_SECTION > m_hk_sections
Definition: hotkey_store.h:111
Represent a single user action.
Definition: tool_action.h:67
void ResetAllHotkeysToOriginal()
Resets every hotkey to the original values.
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)
#define PSEUDO_WXK_DBLCLICK
Definition: hotkeys_basic.h:50
int m_EditKeycode
Definition: hotkey_store.h:37
wxString m_SectionName
Definition: hotkey_store.h:53
const std::string & GetName() const
Return name of the action.
Definition: tool_action.h:101
PSEUDO_ACTION(const wxString &aLabel, int aHotKey)
static wxString GetSectionName(TOOL_ACTION *aAction)