KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_template_selector.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) 2012 Brian Sidebotham <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
26#include <bitmaps.h>
28#include <widgets/ui_common.h>
29#include <algorithm>
30#include <wx_filename.h>
31#include <wx/dir.h>
32#include <wx/dirdlg.h>
33#include <wx/settings.h>
34#include <wx/bitmap.h>
35#include <wx/image.h>
36#include <wx/math.h>
37#include <wx/menu.h>
38#include <wx/textdlg.h>
39#include <wx/textfile.h>
40#include <confirm.h>
43
44// Welcome / fallback HTML now provided by template_default_html.h
45
47 const wxString& aPath ) :
49{
50 m_parent = aParent;
51 m_templatesPath = aPath;
52 m_isUserTemplates = false;
53}
54
55
57{
58 m_SizerChoice->Add( aTemplateWidget );
59 Layout();
60}
61
62
63// Sort the widgets alphabetically, leaving Default at the top
65{
66 std::vector<TEMPLATE_WIDGET*> sortedList;
67 TEMPLATE_WIDGET* default_temp = nullptr;
68 size_t count = m_SizerChoice->GetItemCount();
69
70 if( count <= 1 )
71 return;
72
73 for( size_t idx = 0; idx < count; idx++ )
74 {
75 wxSizerItem* item = m_SizerChoice->GetItem( idx );
76 if( item && item->IsWindow() )
77 {
78 TEMPLATE_WIDGET* temp = static_cast<TEMPLATE_WIDGET*>( item->GetWindow() );
79
80 const wxString title = *temp->GetTemplate()->GetTitle();
81
82 if( default_temp == nullptr && title.CmpNoCase( "default" ) == 0 )
83 default_temp = temp;
84 else
85 sortedList.push_back( temp );
86 }
87 }
88
89 std::sort(
90 sortedList.begin(), sortedList.end(),
91 []( TEMPLATE_WIDGET* aWidgetA, TEMPLATE_WIDGET* aWidgetB ) -> bool
92 {
93 const wxString* a = aWidgetA->GetTemplate()->GetTitle();
94 const wxString* b = aWidgetB->GetTemplate()->GetTitle();
95
96 return ( *a ).CmpNoCase( *b ) < 0;
97 });
98
99 m_SizerChoice->Clear( false );
100
101 if( default_temp != nullptr )
102 m_SizerChoice->Add( default_temp );
103
104 for (TEMPLATE_WIDGET* temp : sortedList)
105 {
106 m_SizerChoice->Add( temp );
107 }
108
109 Layout();
110}
111
112
114 TEMPLATE_WIDGET_BASE( aParent )
115{
116 m_parent = aParent;
117 m_dialog = aDialog;
118 m_isUserTemplate = false;
119
120 // wxWidgets_3.xx way of doing the same...
121 // Bind(wxEVT_LEFT_DOWN, &TEMPLATE_WIDGET::OnMouse, this );
122
123 m_bitmapIcon->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( TEMPLATE_WIDGET::OnMouse ),
124 nullptr, this );
125 m_staticTitle->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( TEMPLATE_WIDGET::OnMouse ),
126 nullptr, this );
127
128 // Add right-click handler
129 m_bitmapIcon->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( TEMPLATE_WIDGET::onRightClick ),
130 nullptr, this );
131 m_staticTitle->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( TEMPLATE_WIDGET::onRightClick ),
132 nullptr, this );
133 Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( TEMPLATE_WIDGET::onRightClick ),
134 nullptr, this );
135
136 // Add double-click handler to activate the template (like OK button)
137 m_bitmapIcon->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( TEMPLATE_WIDGET::OnDoubleClick ),
138 nullptr, this );
139 m_staticTitle->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( TEMPLATE_WIDGET::OnDoubleClick ),
140 nullptr, this );
141 Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( TEMPLATE_WIDGET::OnDoubleClick ),
142 nullptr, this );
143
144 // We're not selected until we're clicked
145 Unselect();
146
147 // Start with template being NULL
148 m_currTemplate = nullptr;
149}
150
151
153{
154 m_dialog->SetWidget( this );
155 SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
156 m_staticTitle->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHTTEXT ) );
157 m_selected = true;
158 Refresh();
159}
160
161
163{
164 SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
165 m_staticTitle->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNTEXT ) );
166 m_selected = false;
167 Refresh();
168}
169
170
172{
173 m_currTemplate = aTemplate;
174 m_staticTitle->SetFont( KIUI::GetInfoFont( this ) );
175 m_staticTitle->SetLabel( *aTemplate->GetTitle() );
176 m_staticTitle->Wrap( 100 );
177 wxBitmap* icon = aTemplate->GetIcon();
178
179 if( icon && icon->IsOk() )
180 {
181 wxSize maxSize = m_bitmapIcon->GetSize();
182
183 if( icon->GetWidth() > maxSize.x || icon->GetHeight() > maxSize.y )
184 {
185 double scale = std::min( (double) maxSize.x / icon->GetWidth(),
186 (double) maxSize.y / icon->GetHeight() );
187 wxImage image = icon->ConvertToImage();
188 int w = wxRound( icon->GetWidth() * scale );
189 int h = wxRound( icon->GetHeight() * scale );
190 image.Rescale( w, h, wxIMAGE_QUALITY_HIGH );
191 m_bitmapIcon->SetBitmap( wxBitmap( image ) );
192 }
193 else
194 {
195 m_bitmapIcon->SetBitmap( *icon );
196 }
197 }
198 else
200}
201
202
203void TEMPLATE_WIDGET::OnMouse( wxMouseEvent& event )
204{
205 // Toggle selection here
206 Select();
207 event.Skip();
208}
209
210
211void TEMPLATE_WIDGET::OnDoubleClick( wxMouseEvent& event )
212{
213 // Double-click acts like pressing OK button
214 Select();
215 m_dialog->EndModal( wxID_OK );
216 event.Skip();
217}
218
219
220void TEMPLATE_WIDGET::onRightClick( wxMouseEvent& event )
221{
222 // Only show context menu for user templates
224 {
225 event.Skip();
226 return;
227 }
228
229 wxMenu menu;
230 menu.Append( wxID_EDIT, _( "Edit Template" ) );
231 menu.Append( wxID_COPY, _( "Duplicate Template" ) );
232
233 menu.Bind( wxEVT_COMMAND_MENU_SELECTED,
234 [this]( wxCommandEvent& evt )
235 {
236 if( evt.GetId() == wxID_EDIT )
237 onEditTemplate( evt );
238 else if( evt.GetId() == wxID_COPY )
239 onDuplicateTemplate( evt );
240 } );
241
242 PopupMenu( &menu );
243}
244
245
246void TEMPLATE_WIDGET::onEditTemplate( wxCommandEvent& event )
247{
248 if( !m_currTemplate )
249 return;
250
251 // Get the template's base path
252 wxFileName templatePath = m_currTemplate->GetHtmlFile();
253 templatePath.RemoveLastDir(); // Remove "meta" dir
254
255 // Find a .kicad_pro file in the template directory
256 wxDir dir( templatePath.GetPath() );
257
258 if( !dir.IsOpened() )
259 {
261 _( "Could not open template directory." ) );
262 return;
263 }
264
265 wxString filename;
266 bool found = dir.GetFirst( &filename, "*.kicad_pro", wxDIR_FILES );
267
268 if( !found )
269 {
271 _( "No project file found in template directory." ) );
272 return;
273 }
274
275 wxFileName projectFile( templatePath.GetPath(), filename );
276
277 // Store the project path in the dialog so the caller can handle it
278 m_dialog->SetProjectToEdit( projectFile.GetFullPath() );
279
280 // Close with wxID_APPLY to indicate we want to edit, not create
281 m_dialog->EndModal( wxID_APPLY );
282}
283
284
285
286void TEMPLATE_WIDGET::onDuplicateTemplate( wxCommandEvent& event )
287{
288 if( !m_currTemplate )
289 return;
290
291 // Get the template's base path
292 wxFileName templatePath = m_currTemplate->GetHtmlFile();
293 templatePath.RemoveLastDir(); // Remove "meta" dir
294 wxString srcTemplatePath = templatePath.GetPath();
295 wxString srcTemplateName = m_currTemplate->GetPrjDirName();
296
297 // Ask for new template name
298 wxTextEntryDialog nameDlg( m_dialog,
299 _( "Enter name for the new template:" ),
300 _( "Duplicate Template" ),
301 srcTemplateName + _( "_copy" ) );
302
303 if( nameDlg.ShowModal() != wxID_OK )
304 return;
305
306 wxString newTemplateName = nameDlg.GetValue();
307
308 if( newTemplateName.IsEmpty() )
309 {
310 DisplayErrorMessage( m_dialog, _( "Template name cannot be empty." ) );
311 return;
312 }
313
314 // Get the user templates directory from the dialog
315 wxString userTemplatesPath = m_dialog->GetUserTemplatesPath();
316
317 if( userTemplatesPath.IsEmpty() )
318 {
319 DisplayErrorMessage( m_dialog, _( "Could not find user templates directory." ) );
320 return;
321 }
322
323 // Create destination directory in user templates folder
324 wxFileName destPath( userTemplatesPath, wxEmptyString );
325 destPath.AppendDir( newTemplateName );
326 wxString newTemplatePath = destPath.GetPath();
327
328 if( destPath.DirExists() )
329 {
331 wxString::Format( _( "Directory '%s' already exists." ),
332 newTemplatePath ) );
333 return;
334 }
335
336 if( !destPath.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
337 {
339 wxString::Format( _( "Could not create directory '%s'." ),
340 newTemplatePath ) );
341 return;
342 }
343
344 // Use shared traverser to copy all files with proper renaming
345 // Pass nullptr for frame to enable simple copy mode (no KIFACE handling)
346 wxDir sourceDir( srcTemplatePath );
347
348 if( !sourceDir.IsOpened() )
349 {
350 DisplayErrorMessage( m_dialog, _( "Could not open source template directory." ) );
351 return;
352 }
353
354 PROJECT_TREE_TRAVERSER traverser( nullptr, srcTemplatePath, srcTemplateName,
355 newTemplatePath, newTemplateName );
356
357 sourceDir.Traverse( traverser );
358
359 if( !traverser.GetErrors().empty() )
360 {
361 DisplayErrorMessage( m_dialog, traverser.GetErrors() );
362 return;
363 }
364
365 // Update the title in meta/info.html if it exists
366 wxFileName metaHtmlFile( newTemplatePath, "info.html" );
367 metaHtmlFile.AppendDir( "meta" );
368
369 if( metaHtmlFile.FileExists() )
370 {
371 wxTextFile htmlFile( metaHtmlFile.GetFullPath() );
372
373 if( htmlFile.Open() )
374 {
375 bool modified = false;
376
377 for( size_t i = 0; i < htmlFile.GetLineCount(); i++ )
378 {
379 wxString line = htmlFile.GetLine( i );
380
381 // Update the title tag - replace content between <title> and </title>
382 if( line.Contains( wxT( "<title>" ) ) && line.Contains( wxT( "</title>" ) ) )
383 {
384 int titleStart = line.Find( wxT( "<title>" ) );
385 int titleEnd = line.Find( wxT( "</title>" ) );
386
387 if( titleStart != wxNOT_FOUND && titleEnd != wxNOT_FOUND && titleEnd > titleStart )
388 {
389 wxString before = line.Left( titleStart + 7 ); // Include "<title>"
390 wxString after = line.Mid( titleEnd ); // Include "</title>" onwards
391 line = before + newTemplateName + after;
392 htmlFile[i] = line;
393 modified = true;
394 }
395 }
396 }
397
398 if( modified )
399 htmlFile.Write();
400
401 htmlFile.Close();
402 }
403 }
404
406 wxString::Format( _( "Template duplicated successfully to '%s'." ),
407 newTemplatePath ) );
408
409 // Refresh the widget list to show the new template
410 m_dialog->replaceCurrentPage();
411}
412
413
414
415void DIALOG_TEMPLATE_SELECTOR::OnPageChange( wxNotebookEvent& event )
416{
417 int newPage = event.GetSelection();
418 int oldPage = event.GetOldSelection();
419
420 // Move webview panel from old page to new page
421 if( oldPage != wxNOT_FOUND && (unsigned)oldPage < m_panels.size() )
422 {
423 // Detach webview from old panel
424 m_panels[oldPage]->m_SizerBase->Detach( m_webviewPanel );
425 m_panels[oldPage]->Layout();
426 }
427
428 if( newPage != wxNOT_FOUND && (unsigned)newPage < m_panels.size() )
429 {
430 // Reparent the webview to the new panel
431 m_webviewPanel->Reparent( m_panels[newPage] );
432
433 // Attach webview to new panel
434 m_panels[newPage]->m_SizerBase->Add( m_webviewPanel, 1, wxEXPAND | wxALL, 5 );
435 m_panels[newPage]->Layout();
436
437 // Update template path
438 m_tcTemplatePath->SetValue( m_panels[newPage]->GetPath() );
439
440 // Reset to welcome page when switching tabs if no template selected
441 m_webviewPanel->SetPage( GetWelcomeHtml() );
442 }
443
444 event.Skip();
445}
446
447
448DIALOG_TEMPLATE_SELECTOR::DIALOG_TEMPLATE_SELECTOR( wxWindow* aParent, const wxPoint& aPos,
449 const wxSize& aSize,
450 std::vector<std::pair<wxString, wxFileName>> aTitleDirList,
451 const wxFileName& aDefaultTemplate ) :
452 DIALOG_TEMPLATE_SELECTOR_BASE( aParent, wxID_ANY, _( "Project Template Selector" ), aPos,
453 aSize )
454{
457
458 m_selectedWidget = nullptr;
459 m_defaultTemplatePath = aDefaultTemplate;
460 m_defaultWidget = nullptr;
461
462 for( auto& [title, pathFname] : aTitleDirList )
463 {
464 pathFname.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS );
465 wxString path = pathFname.GetFullPath(); // caller ensures this ends with file separator.
466
468
469 // Mark the first panel as "User Templates" if the title matches
470 if( title == _( "User Templates" ) )
471 tpanel->SetIsUserTemplates( true );
472
473 m_panels.push_back( tpanel );
474
475 m_notebook->AddPage( tpanel, title );
476
477 if( m_notebook->GetPageCount() == 1 )
478 m_tcTemplatePath->SetValue( path );
479
480 buildPageContent( path, m_notebook->GetPageCount() - 1 );
481 }
482
483 // Move webview panel from dialog to first template selection panel
484 if( !m_panels.empty() )
485 {
486 // Find the sizer containing the webview and detach it
487 wxSizer* parentSizer = m_webviewPanel->GetContainingSizer();
488
489 if( parentSizer )
490 {
491 parentSizer->Detach( m_webviewPanel );
492 }
493
494 // Reparent the webview to the first panel
495 m_webviewPanel->Reparent( m_panels[0] );
496
497 // Add webview to first panel
498 m_panels[0]->m_SizerBase->Add( m_webviewPanel, 1, wxEXPAND | wxALL, 5 );
499 m_panels[0]->Layout();
500 }
501
502 if( m_defaultWidget )
503 m_defaultWidget->Select();
504
505 // Set welcome HTML after dialog is fully constructed
506 CallAfter( [this]()
507 {
508 #if defined (_WIN32)
509 wxSafeYield();
510 m_tcTemplatePath->SelectNone();
511 #endif
512
513 if( m_selectedWidget )
514 {
515 wxFileName htmlFile = m_selectedWidget->GetTemplate()->GetHtmlFile();
516
517 if( htmlFile.FileExists() && htmlFile.IsFileReadable() && htmlFile.GetSize() > 100 /* Basic HTML */ )
518 m_webviewPanel->LoadURL( wxFileName::FileNameToURL( htmlFile ) );
519 else
520 m_webviewPanel->SetPage( GetWelcomeHtml() );
521 }
522 else
523 {
524 m_webviewPanel->SetPage( GetWelcomeHtml() );
525 }
526 });
527
528 // When all widgets have the size fixed, call finishDialogSettings to update sizers
529 finishDialogSettings();
530}
531
532
534{
535 if( m_selectedWidget != nullptr )
536 m_selectedWidget->Unselect();
537
538 m_selectedWidget = aWidget;
539 wxFileName htmlFile = aWidget->GetTemplate()->GetHtmlFile();
540
541 if( htmlFile.FileExists() && htmlFile.IsFileReadable() )
542 {
543 m_webviewPanel->LoadURL( wxFileName::FileNameToURL( htmlFile ) );
544 }
545 else
546 {
547 m_webviewPanel->SetPage( GetTemplateInfoHtml( *aWidget->GetTemplate()->GetTitle() ) );
548 }
549}
550
551
553{
554 TEMPLATE_WIDGET* w = new TEMPLATE_WIDGET( m_panels[aPage]->m_scrolledWindow, this );
555 w->SetTemplate( aTemplate );
556 w->SetIsUserTemplate( m_panels[aPage]->IsUserTemplates() );
557 m_panels[aPage]->AddTemplateWidget( w );
558 m_allWidgets.push_back( w );
559
560 wxFileName base = aTemplate->GetHtmlFile();
561 base.RemoveLastDir();
562
564 m_defaultWidget = w;
565
566 wxString dirName = base.GetDirs().IsEmpty() ? wxString() : base.GetDirs().back();
567
568 if( dirName.CmpNoCase( "default" ) == 0 )
569 {
570 // Prefer a directory literally named 'default'
571 m_defaultWidget = w;
572 }
573}
574
575
580
585
586
588{
589 // Find the first panel marked as user templates
590 for( const TEMPLATE_SELECTION_PANEL* panel : m_panels )
591 {
592 if( panel->IsUserTemplates() )
593 return panel->GetPath();
594 }
595
596 // If no user templates panel found, return empty string
597 return wxEmptyString;
598}
599
600
601void DIALOG_TEMPLATE_SELECTOR::buildPageContent( const wxString& aPath, int aPage )
602{
603 // Track initial template count to detect if any templates were added
604 size_t initialTemplateCount = m_panels[aPage]->m_SizerChoice->GetItemCount();
605
606 // Get a list of files under the template path to include as choices...
607 wxDir dir;
608
609 if( dir.Open( aPath ) )
610 {
611 if( dir.HasSubDirs( "meta" ) )
612 {
613 AddTemplate( aPage, new PROJECT_TEMPLATE( aPath ) );
614 }
615 else
616 {
617 wxString sub_name;
618 wxArrayString subdirs;
619
620 bool cont = dir.GetFirst( &sub_name, wxEmptyString, wxDIR_DIRS );
621
622 while( cont )
623 {
624 subdirs.Add( wxString( sub_name ) );
625 cont = dir.GetNext( &sub_name );
626 }
627
628 if( !subdirs.IsEmpty() )
629 subdirs.Sort();
630
631 for( const wxString& dir_name : subdirs )
632 {
633 wxDir sub_dir;
634 wxString sub_full = aPath + dir_name;
635
636 if( sub_dir.Open( sub_full ) )
637 AddTemplate( aPage, new PROJECT_TEMPLATE( sub_full ) );
638 }
639 }
640 }
641
642 m_panels[aPage]->SortAlphabetically();
643
644 // Check if any templates were added; if not, display "No templates found" message
645 size_t finalTemplateCount = m_panels[aPage]->m_SizerChoice->GetItemCount();
646
647 if( finalTemplateCount == initialTemplateCount )
648 {
649 // No templates found in this directory - show message in webview
650 if( (unsigned)aPage < m_panels.size() )
651 {
652 // Get the panel's webview if it exists (it may not be directly accessible)
653 // Instead, we'll set the message on the main webview if it's associated with this panel
654 if( m_selectedWidget == nullptr && aPage == m_notebook->GetSelection() )
655 {
657 }
658 }
659 }
660
661 Layout();
662}
663
664
665
667{
668 wxFileName fn;
669 fn.AssignDir( m_tcTemplatePath->GetValue() );
670 fn.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS );
671 wxString currPath = fn.GetFullPath();
672
673 wxDirDialog dirDialog( this, _( "Select Templates Directory" ), currPath,
674 wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST );
675
676 if( dirDialog.ShowModal() != wxID_OK )
677 return;
678
679 wxFileName dirName = wxFileName::DirName( dirDialog.GetPath() );
680
681 m_tcTemplatePath->SetValue( dirName.GetFullPath() );
682
683 // Rebuild the page from the new templates path:
685}
686
687
688void DIALOG_TEMPLATE_SELECTOR::onReload( wxCommandEvent& event )
689{
690 int page = m_notebook->GetSelection();
691
692 if( page < 0 )
693 return; // Should not happen
694
695 wxString currPath = m_tcTemplatePath->GetValue();
696
697 wxFileName fn;
698 fn.AssignDir( m_tcTemplatePath->GetValue() );
699 fn.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS );
700 currPath = fn.GetFullPath();
701 m_tcTemplatePath->SetValue( currPath );
702
704}
705
706
708{
709 // Rebuild the page from the new templates path:
710 int page = m_notebook->GetSelection();
711
712 if( page < 0 )
713 return; // Should not happen
714
715 wxString title = m_notebook->GetPageText( page );
716 wxString currPath = m_tcTemplatePath->GetValue();
717
718 // Save the user template flag before deleting
719 bool wasUserTemplates = false;
720 if( (unsigned)page < m_panels.size() )
721 wasUserTemplates = m_panels[page]->IsUserTemplates();
722
723 // Block all events to the notebook and its children
724 wxEventBlocker blocker( m_notebook );
725
726 // Detach webview from current panel before deleting it
727 if( (unsigned)page < m_panels.size() )
728 {
729 m_panels[page]->m_SizerBase->Detach( m_webviewPanel );
730 m_webviewPanel->Reparent( this ); // Reparent to dialog
731 m_webviewPanel->Hide(); // Hide webview panel temporarily
732 }
733
734 m_notebook->DeletePage( page );
735
737 tpanel->SetIsUserTemplates( wasUserTemplates ); // Restore the flag
738 m_panels[page] = tpanel;
739 m_notebook->InsertPage( page, tpanel, title, true );
740
741 // Reparent and add webview back to the new panel
742 m_webviewPanel->Reparent( tpanel );
743 m_webviewPanel->Show();
744 tpanel->m_SizerBase->Add( m_webviewPanel, 1, wxEXPAND | wxALL, 5 );
745
746 buildPageContent( m_tcTemplatePath->GetValue(), page );
747
748 m_selectedWidget = nullptr;
749 // Reset to welcome page after rebuilding
750 m_webviewPanel->SetPage( GetWelcomeHtml() );
751
752 Layout();
753}
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition bitmap.cpp:104
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:110
DIALOG_TEMPLATE_SELECTOR_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Project Template Selector"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(513, 523), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
void AddTemplate(int aPage, PROJECT_TEMPLATE *aTemplate)
void OnPageChange(wxNotebookEvent &event) override
void onReload(wxCommandEvent &event) override
DIALOG_TEMPLATE_SELECTOR(wxWindow *aParent, const wxPoint &aPos, const wxSize &aSize, std::vector< std::pair< wxString, wxFileName > > aTitleDirList, const wxFileName &aDefaultTemplate)
void onDirectoryBrowseClicked(wxCommandEvent &event) override
void replaceCurrentPage()
Refresh the current page to show updated template list.
std::vector< TEMPLATE_WIDGET * > m_allWidgets
void SetWidget(TEMPLATE_WIDGET *aWidget)
void buildPageContent(const wxString &aPath, int aPage)
wxString GetUserTemplatesPath() const
Get the path to the user templates directory (first panel marked as user templates)
std::vector< TEMPLATE_SELECTION_PANEL * > m_panels
A class which provides project template functionality.
wxBitmap * GetIcon()
Get the 64px^2 icon for the project template.
wxFileName GetHtmlFile()
Get the full Html filename for the project template.
wxString * GetTitle()
Get the title of the project (extracted from the html title tag)
Traverser class to duplicate/copy project or template files with proper renaming.
TEMPLATE_SELECTION_PANEL_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxTAB_TRAVERSAL|wxBORDER_NONE, const wxString &name=wxEmptyString)
TEMPLATE_SELECTION_PANEL(wxNotebookPage *aParent, const wxString &aPath)
wxString m_templatesPath
the path to access to the folder containing the templates (which are also folders)
void AddTemplateWidget(TEMPLATE_WIDGET *aTemplateWidget)
bool m_isUserTemplates
true if this panel contains user templates
void SetIsUserTemplates(bool aIsUser)
Set whether templates in this panel are user templates (can be edited/duplicated)
TEMPLATE_WIDGET_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxTAB_TRAVERSAL, const wxString &name=wxEmptyString)
void SetIsUserTemplate(bool aIsUser)
Set whether this template widget represents a user template.
PROJECT_TEMPLATE * GetTemplate()
void OnMouse(wxMouseEvent &event)
void SetTemplate(PROJECT_TEMPLATE *aTemplate)
Set the project template for this widget, which will determine the icon and title associated with thi...
DIALOG_TEMPLATE_SELECTOR * m_dialog
void onEditTemplate(wxCommandEvent &event)
void OnDoubleClick(wxMouseEvent &event)
void onDuplicateTemplate(wxCommandEvent &event)
void onRightClick(wxMouseEvent &event)
TEMPLATE_WIDGET(wxWindow *aParent, DIALOG_TEMPLATE_SELECTOR *aDialog)
PROJECT_TEMPLATE * m_currTemplate
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition confirm.cpp:230
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:202
This file is part of the common library.
#define _(s)
KICOMMON_API wxFont GetInfoFont(wxWindow *aWindow)
void Refresh()
Update the board display after modifying it by a python script (note: it is automatically called by a...
const int scale
wxString GetWelcomeHtml()
wxString GetNoTemplatesHtml()
wxString GetTemplateInfoHtml(const wxString &aTemplateName)
Functions to provide common constants and other functions to assist in making a consistent UI.
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().
Definition wx_filename.h:39