KiCad PCB EDA Suite
panel_common_settings.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) 2018-2022 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
25
26#include <advanced_config.h>
27#include <bitmaps.h>
28#include <dialog_shim.h>
29#include <gal/dpi_scaling.h>
30#include <kiface_base.h>
31#include <kiplatform/ui.h>
32#include <pgm_base.h>
33#include <id.h>
38#include <wx/filedlg.h>
39
40/*
41 * What follows is a whole lot of ugly to handle various platform GUI deficiences with respect
42 * to light/dark mode, DPI scaling, and other foibles.
43 *
44 * Ugly as it all is, it does improve our usability on various platforms.
45 */
46
48 : PANEL_COMMON_SETTINGS_BASE( aParent ),
49 m_dialog( aDialog ),
50 m_iconScaleLabel( nullptr ),
51 m_iconScaleSlider( nullptr ),
52 m_iconScaleAuto( nullptr ),
53 m_last_scale( -1 )
54{
55 /*
56 * Cairo canvas doesn't work on Mac, so no need for fallback anti-aliasing options
57 */
58#ifdef __WXMAC__
59 m_antialiasingFallback->Show( false );
60 m_antialiasingFallbackLabel->Show( false );
61#endif
62
65
66 /*
67 * Automatic dark mode detection works fine on Mac, so no need for the explicit options.
68 */
69#ifdef __WXMAC__
70 m_stIconTheme->Show( false );
71 m_rbIconThemeLight->Show( false );
72 m_rbIconThemeDark->Show( false );
73 m_rbIconThemeAuto->Show( false );
74#endif
75
76 /*
77 * Automatic icon scaling works fine on Mac. It works mostly fine on MSW, but perhaps not
78 * uniformly enough to exclude the explicit controls there.
79 */
80#if defined( __WXGTK__ ) || defined( __WXMSW__ )
81 // Sadly wxSlider is poorly implemented and adds its legends as sibling windows (so that
82 // showing/hiding the control doesn't work). So we have to create it conditionally.
83 wxGridBagSizer* gb = m_gbUserInterface;
84
85 const int row_num = 0;
86 m_iconScaleLabel = new wxStaticText( this, wxID_ANY, _( "Icon scale:" ) );
87 m_iconScaleLabel->Wrap( -1 );
88 gb->Add( m_iconScaleLabel, wxGBPosition( row_num, 0 ),
89 wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 );
90
91 m_iconScaleSlider = new STEPPED_SLIDER( this, wxID_ANY, 100, 50, 275, wxDefaultPosition,
92 wxDefaultSize, wxSL_HORIZONTAL|wxSL_VALUE_LABEL );
94 gb->Add( m_iconScaleSlider, wxGBPosition( row_num, 1 ), wxGBSpan( 1, 1 ), wxEXPAND|wxBOTTOM, 5 );
95
96 m_iconScaleAuto = new wxCheckBox( this, wxID_ANY, _( "Automatic" ) );
97 gb->Add( m_iconScaleAuto, wxGBPosition( row_num, 2 ),
98 wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxLEFT, 15 );
99#endif
100
101 /*
102 * Automatic canvas scaling works fine on all supported platforms, so manual scaling is disabled
103 */
104 if( ADVANCED_CFG::GetCfg().m_AllowManualCanvasScale )
105 {
106 static constexpr int dpi_scaling_precision = 1;
107 static constexpr double dpi_scaling_increment = 0.5;
108
111 m_canvasScaleCtrl->SetDigits( dpi_scaling_precision );
112 m_canvasScaleCtrl->SetIncrement( dpi_scaling_increment );
114
115 m_canvasScaleCtrl->SetToolTip(
116 _( "Set the scale for the canvas."
117 "\n\n"
118 "On high-DPI displays on some platforms, KiCad cannot determine the "
119 "scaling factor. In this case you may need to set this to a value to "
120 "match your system's DPI scaling. 2.0 is a common value. "
121 "\n\n"
122 "If this does not match the system DPI scaling, the canvas will "
123 "not match the window size and cursor position." ) );
124
125 m_canvasScaleAuto->SetToolTip(
126 _( "Use an automatic value for the canvas scale."
127 "\n\n"
128 "On some platforms, the automatic value is incorrect and should be "
129 "set manually." ) );
130 }
131 else
132 {
133 m_staticTextCanvasScale->Show( false );
134 m_canvasScaleCtrl->Show( false );
135 m_canvasScaleCtrl = nullptr;
136 m_canvasScaleAuto->Show( false );
137 }
138
139 // Hide the option of icons in menus for platforms that do not support them
141
142 /*
143 * Font scaling hacks are only needed on GTK under wxWidgets 3.0.
144 */
145#if defined( __WXGTK__ ) && !wxCHECK_VERSION( 3, 1, 0 )
146 m_fontScalingHelp->SetFont( KIUI::GetInfoFont( this ).Italic() );
147#else
148 m_scaleFonts->Show( false );
149 m_fontScalingHelp->Show( false );
150#endif
151
153 {
154 m_iconScaleSlider->Connect( wxEVT_SCROLL_TOP,
155 wxScrollEventHandler( PANEL_COMMON_SETTINGS::OnScaleSlider ),
156 nullptr, this );
157 m_iconScaleSlider->Connect( wxEVT_SCROLL_BOTTOM,
158 wxScrollEventHandler( PANEL_COMMON_SETTINGS::OnScaleSlider ),
159 nullptr, this );
160 m_iconScaleSlider->Connect( wxEVT_SCROLL_LINEUP,
161 wxScrollEventHandler( PANEL_COMMON_SETTINGS::OnScaleSlider ),
162 nullptr, this );
163 m_iconScaleSlider->Connect( wxEVT_SCROLL_LINEDOWN,
164 wxScrollEventHandler( PANEL_COMMON_SETTINGS::OnScaleSlider ),
165 nullptr, this );
166 m_iconScaleSlider->Connect( wxEVT_SCROLL_PAGEUP,
167 wxScrollEventHandler( PANEL_COMMON_SETTINGS::OnScaleSlider ),
168 nullptr, this );
169 m_iconScaleSlider->Connect( wxEVT_SCROLL_PAGEDOWN,
170 wxScrollEventHandler( PANEL_COMMON_SETTINGS::OnScaleSlider ),
171 nullptr, this );
172 m_iconScaleSlider->Connect( wxEVT_SCROLL_THUMBTRACK,
173 wxScrollEventHandler( PANEL_COMMON_SETTINGS::OnScaleSlider ),
174 nullptr, this );
175 m_iconScaleSlider->Connect( wxEVT_SCROLL_THUMBRELEASE,
176 wxScrollEventHandler( PANEL_COMMON_SETTINGS::OnScaleSlider ),
177 nullptr, this );
178 m_iconScaleSlider->Connect( wxEVT_SCROLL_CHANGED,
179 wxScrollEventHandler( PANEL_COMMON_SETTINGS::OnScaleSlider ),
180 nullptr, this );
181 m_iconScaleAuto->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED,
182 wxCommandEventHandler( PANEL_COMMON_SETTINGS::OnIconScaleAuto ),
183 nullptr, this );
184 }
185
187 {
188 m_canvasScaleCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED,
189 wxCommandEventHandler( PANEL_COMMON_SETTINGS::OnCanvasScaleChange ),
190 nullptr, this );
191 }
192
193 wxSize minSize = m_highContrastCtrl->GetMinSize();
194 int minWidth = m_highContrastCtrl->GetTextExtent( wxT( "XXX.XXX" ) ).GetWidth();
195
196 m_highContrastCtrl->SetMinSize( wxSize( minWidth, minSize.GetHeight() ) );
197}
198
199
201{
203 {
204 m_iconScaleSlider->Disconnect( wxEVT_SCROLL_TOP,
205 wxScrollEventHandler( PANEL_COMMON_SETTINGS::OnScaleSlider ),
206 nullptr, this );
207 m_iconScaleSlider->Disconnect( wxEVT_SCROLL_BOTTOM,
208 wxScrollEventHandler( PANEL_COMMON_SETTINGS::OnScaleSlider ),
209 nullptr, this );
210 m_iconScaleSlider->Disconnect( wxEVT_SCROLL_LINEUP,
211 wxScrollEventHandler( PANEL_COMMON_SETTINGS::OnScaleSlider ),
212 nullptr, this );
213 m_iconScaleSlider->Disconnect( wxEVT_SCROLL_LINEDOWN,
214 wxScrollEventHandler( PANEL_COMMON_SETTINGS::OnScaleSlider ),
215 nullptr, this );
216 m_iconScaleSlider->Disconnect( wxEVT_SCROLL_PAGEUP,
217 wxScrollEventHandler( PANEL_COMMON_SETTINGS::OnScaleSlider ),
218 nullptr, this );
219 m_iconScaleSlider->Disconnect( wxEVT_SCROLL_PAGEDOWN,
220 wxScrollEventHandler( PANEL_COMMON_SETTINGS::OnScaleSlider ),
221 nullptr, this );
222 m_iconScaleSlider->Disconnect( wxEVT_SCROLL_THUMBTRACK,
223 wxScrollEventHandler( PANEL_COMMON_SETTINGS::OnScaleSlider ),
224 nullptr, this );
225 m_iconScaleSlider->Disconnect( wxEVT_SCROLL_THUMBRELEASE,
226 wxScrollEventHandler( PANEL_COMMON_SETTINGS::OnScaleSlider ),
227 nullptr, this );
228 m_iconScaleSlider->Disconnect( wxEVT_SCROLL_CHANGED,
229 wxScrollEventHandler( PANEL_COMMON_SETTINGS::OnScaleSlider ),
230 nullptr, this );
231 m_iconScaleAuto->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED,
232 wxCommandEventHandler( PANEL_COMMON_SETTINGS::OnIconScaleAuto ),
233 nullptr, this );
234 }
235
237 {
238 m_canvasScaleCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED,
239 wxCommandEventHandler( PANEL_COMMON_SETTINGS::OnCanvasScaleChange ),
240 nullptr, this );
241 }
242}
243
244
246{
247 COMMON_SETTINGS* commonSettings = Pgm().GetCommonSettings();
248
249 applySettingsToPanel( *commonSettings );
250
251 // TODO(JE) Move these into COMMON_SETTINGS probably
252 m_textEditorPath->SetValue( Pgm().GetTextEditor( false ) );
253 m_defaultPDFViewer->SetValue( Pgm().UseSystemPdfBrowser() );
254 m_otherPDFViewer->SetValue( !Pgm().UseSystemPdfBrowser() );
255 m_PDFViewerPath->SetValue( Pgm().GetPdfBrowserName() );
257
258 return true;
259}
260
261
263{
264 COMMON_SETTINGS* commonSettings = Pgm().GetCommonSettings();
265
266 commonSettings->m_System.autosave_interval = m_SaveTime->GetValue() * 60;
267 commonSettings->m_System.file_history_size = m_fileHistorySize->GetValue();
268 commonSettings->m_System.clear_3d_cache_interval = m_Clear3DCacheFilesOlder->GetValue();
269
270 commonSettings->m_Graphics.opengl_aa_mode = m_antialiasing->GetSelection();
271 commonSettings->m_Graphics.cairo_aa_mode = m_antialiasingFallback->GetSelection();
272
274 {
275 int scale_fourths = m_iconScaleAuto->GetValue() ? -1 : m_iconScaleSlider->GetValue() / 25;
276 commonSettings->m_Appearance.icon_scale = scale_fourths;
277 }
278
280 {
281 DPI_SCALING dpi( commonSettings, this );
282 dpi.SetDpiConfig( m_canvasScaleAuto->GetValue(), m_canvasScaleCtrl->GetValue() );
283 }
284
285 if( m_rbIconThemeLight->GetValue() )
286 commonSettings->m_Appearance.icon_theme = ICON_THEME::LIGHT;
287 else if( m_rbIconThemeDark->GetValue() )
288 commonSettings->m_Appearance.icon_theme = ICON_THEME::DARK;
289 else if( m_rbIconThemeAuto->GetValue() )
290 commonSettings->m_Appearance.icon_theme = ICON_THEME::AUTO;
291
292 commonSettings->m_Appearance.use_icons_in_menus = m_checkBoxIconsInMenus->GetValue();
293 commonSettings->m_Appearance.apply_icon_scale_to_fonts = m_scaleFonts->GetValue();
294
295 commonSettings->m_Appearance.show_scrollbars = m_showScrollbars->GetValue();
296
297 double dimmingPercent = 80;
298 m_highContrastCtrl->GetValue().ToDouble( &dimmingPercent );
299 commonSettings->m_Appearance.hicontrast_dimming_factor = dimmingPercent / 100.0f;
300
301 commonSettings->m_Input.focus_follow_sch_pcb = m_focusFollowSchPcb->GetValue();
302 commonSettings->m_Input.immediate_actions = !m_NonImmediateActions->GetValue();
303 commonSettings->m_Input.warp_mouse_on_move = m_warpMouseOnMove->GetValue();
304
305 commonSettings->m_Backup.enabled = m_cbBackupEnabled->GetValue();
306 commonSettings->m_Backup.backup_on_autosave = m_cbBackupAutosave->GetValue();
307 commonSettings->m_Backup.limit_total_files = m_backupLimitTotalFiles->GetValue();
308 commonSettings->m_Backup.limit_daily_files = m_backupLimitDailyFiles->GetValue();
309 commonSettings->m_Backup.min_interval = m_backupMinInterval->GetValue() * 60;
310 commonSettings->m_Backup.limit_total_size = m_backupLimitTotalSize->GetValue() * 1024 * 1024;
311
312 commonSettings->m_Session.remember_open_files = m_cbRememberOpenFiles->GetValue();
313
314 Pgm().SetTextEditor( m_textEditorPath->GetValue());
315
316 Pgm().SetPdfBrowserName( m_PDFViewerPath->GetValue() );
317 Pgm().ForceSystemPdfBrowser( m_defaultPDFViewer->GetValue() );
318 Pgm().WritePdfBrowserInfos();
319
320 Pgm().GetSettingsManager().Save( commonSettings );
321
322 return true;
323}
324
325
327{
328 COMMON_SETTINGS defaultSettings;
329
330 defaultSettings.ResetToDefaults();
331
332 applySettingsToPanel( defaultSettings );
333
334 // TODO(JE) Move these into COMMON_SETTINGS probably
335 m_textEditorPath->SetValue( defaultSettings.m_System.text_editor );
336 m_defaultPDFViewer->SetValue( defaultSettings.m_System.use_system_pdf_viewer );
337 m_otherPDFViewer->SetValue( !defaultSettings.m_System.use_system_pdf_viewer );
338 m_PDFViewerPath->SetValue( defaultSettings.m_System.pdf_viewer_name );
340}
341
342
344{
345 int timevalue = aSettings.m_System.autosave_interval;
346 wxString msg;
347
348 msg << timevalue / 60;
349 m_SaveTime->SetValue( msg );
350
351 m_fileHistorySize->SetValue( aSettings.m_System.file_history_size );
352
353 m_antialiasing->SetSelection( aSettings.m_Graphics.opengl_aa_mode );
354 m_antialiasingFallback->SetSelection( aSettings.m_Graphics.cairo_aa_mode );
355
357
359 {
360 int icon_scale_fourths = aSettings.m_Appearance.icon_scale;
361
362 if( icon_scale_fourths <= 0 )
363 {
364 m_iconScaleAuto->SetValue( true );
365 m_iconScaleSlider->SetValue( 25 * KiIconScale( GetParent() ) );
366 }
367 else
368 {
369 m_iconScaleAuto->SetValue( false );
370 m_iconScaleSlider->SetValue( icon_scale_fourths * 25 );
371 }
372 }
373
375 {
376 const DPI_SCALING dpi( &aSettings, this );
377 m_canvasScaleCtrl->SetValue( dpi.GetScaleFactor() );
378 m_canvasScaleAuto->SetValue( dpi.GetCanvasIsAutoScaled() );
379 }
380
381 switch( aSettings.m_Appearance.icon_theme )
382 {
383 case ICON_THEME::LIGHT: m_rbIconThemeLight->SetValue( true ); break;
384 case ICON_THEME::DARK: m_rbIconThemeDark->SetValue( true ); break;
385 case ICON_THEME::AUTO: m_rbIconThemeAuto->SetValue( true ); break;
386 }
387
390
391 double dimmingPercent = aSettings.m_Appearance.hicontrast_dimming_factor * 100.0f;
392 m_highContrastCtrl->SetValue( wxString::Format( "%.0f", dimmingPercent ) );
393
394 m_focusFollowSchPcb->SetValue( aSettings.m_Input.focus_follow_sch_pcb );
395 m_warpMouseOnMove->SetValue( aSettings.m_Input.warp_mouse_on_move );
396 m_NonImmediateActions->SetValue( !aSettings.m_Input.immediate_actions );
397
399
400 m_cbBackupEnabled->SetValue( aSettings.m_Backup.enabled );
401 m_cbBackupAutosave->SetValue( aSettings.m_Backup.backup_on_autosave );
404 m_backupMinInterval->SetValue( aSettings.m_Backup.min_interval / 60 );
405 m_backupLimitTotalSize->SetValue( aSettings.m_Backup.limit_total_size / ( 1024 * 1024 ) );
406
407 m_showScrollbars->SetValue( aSettings.m_Appearance.show_scrollbars );
408}
409
410
411void PANEL_COMMON_SETTINGS::OnScaleSlider( wxScrollEvent& aEvent )
412{
413 m_iconScaleAuto->SetValue( false );
414 aEvent.Skip();
415}
416
417
418void PANEL_COMMON_SETTINGS::OnIconScaleAuto( wxCommandEvent& aEvent )
419{
421 {
422 if( m_iconScaleAuto->GetValue() )
423 {
424 m_last_scale = m_iconScaleAuto->GetValue();
425 m_iconScaleSlider->SetValue( 25 * KiIconScale( GetParent() ) );
426 }
427 else
428 {
429 if( m_last_scale >= 0 )
430 m_iconScaleSlider->SetValue( m_last_scale );
431 }
432 }
433}
434
435
436void PANEL_COMMON_SETTINGS::OnCanvasScaleChange( wxCommandEvent& aEvent )
437{
438 m_canvasScaleAuto->SetValue( false );
439}
440
441
442void PANEL_COMMON_SETTINGS::OnCanvasScaleAuto( wxCommandEvent& aEvent )
443{
444 const bool automatic = m_canvasScaleAuto->GetValue();
445
446 if( automatic && m_canvasScaleCtrl )
447 {
448 // set the scale to the auto value, without consulting the config
449 DPI_SCALING dpi( nullptr, this );
450
451 // update the field (no events sent)
452 m_canvasScaleCtrl->SetValue( dpi.GetScaleFactor() );
453 }
454}
455
456
457void PANEL_COMMON_SETTINGS::OnTextEditorClick( wxCommandEvent& event )
458{
459 // Ask the user to select a new editor, but suggest the current one as the default.
460 wxString editorname = Pgm().AskUserForPreferredEditor( m_textEditorPath->GetValue() );
461
462 // If we have a new editor name request it to be copied to m_text_editor and saved
463 // to the preferences file. If the user cancelled the dialog then the previous
464 // value will be retained.
465 if( !editorname.IsEmpty() )
466 m_textEditorPath->SetValue( editorname );
467}
468
469
470void PANEL_COMMON_SETTINGS::OnPDFViewerClick( wxCommandEvent& event )
471{
472 wxString mask( wxT( "*" ) );
473
474#ifdef __WINDOWS__
475 mask += wxT( ".exe" );
476#endif
477
478 wxString wildcard = _( "Executable files (" ) + mask + wxT( ")|" ) + mask;
479
480 Pgm().ReadPdfBrowserInfos();
481 wxFileName fn = Pgm().GetPdfBrowserName();
482
483 wxFileDialog dlg( this, _( "Select Preferred PDF Viewer" ), fn.GetPath(), fn.GetFullPath(),
484 wildcard, wxFD_OPEN | wxFD_FILE_MUST_EXIST );
485
486 if( dlg.ShowModal() == wxID_CANCEL )
487 return;
488
489 m_otherPDFViewer->SetValue( true );
490 m_PDFViewerPath->SetValue( dlg.GetPath() );
491}
492
493
495{
497}
498
499
501{
502 m_PDFViewerPath->Enable( m_otherPDFViewer->GetValue() );
503 m_pdfViewerBtn->Enable( m_otherPDFViewer->GetValue() );
504}
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:106
int KiIconScale(wxWindow *aWindow)
Return the automatic scale factor that would be used for a given window by KiScaledBitmap and KiScale...
Definition: bitmap.cpp:123
@ small_folder
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
APPEARANCE m_Appearance
AUTO_BACKUP m_Backup
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Definition: dialog_shim.h:83
Class to handle configuration and automatic determination of the DPI scale to use for canvases.
Definition: dpi_scaling.h:37
double GetScaleFactor() const
Get the DPI scale from all known sources in order:
Definition: dpi_scaling.cpp:91
void SetDpiConfig(bool aAuto, double aValue)
Set the common DPI config in a given config object.
static double GetDefaultScaleFactor()
Get the "default" scaling factor to use if not other config is available.
static double GetMaxScaleFactor()
bool GetCanvasIsAutoScaled() const
Is the current value auto scaled, or is it user-set in the config.
static double GetMinScaleFactor()
void ResetToDefaults()
Resets all parameters to default values.
Class PANEL_COMMON_SETTINGS_BASE.
STEPPED_SLIDER * m_iconScaleSlider
void OnTextEditorClick(wxCommandEvent &event) override
bool TransferDataFromWindow() override
bool TransferDataToWindow() override
void OnCanvasScaleChange(wxCommandEvent &aEvent)
Event fired when the canvas scale field is modified.
void applySettingsToPanel(COMMON_SETTINGS &aSettings)
void OnScaleSlider(wxScrollEvent &aEvent)
PANEL_COMMON_SETTINGS(DIALOG_SHIM *aDialog, wxWindow *aParent)
int m_last_scale
saved icon scale when Auto selected
void OnPDFViewerClick(wxCommandEvent &event) override
void OnIconScaleAuto(wxCommandEvent &aEvent)
void OnCanvasScaleAuto(wxCommandEvent &aEvent) override
Event fired when the canvas auto-scale option is changed.
void ResetPanel() override
Reset the contents of this panel.
void OnRadioButtonPdfViewer(wxCommandEvent &event) override
void SetBitmap(const wxBitmap &aBmp)
bool Enable(bool aEnable=true) override
Customized wxSlider with forced stepping.
void SetStep(int aSize)
Set the step size.
const int minSize
Push and Shove router track width and via size dialog.
#define _(s)
bool AllowIconsInMenus()
If the user has disabled icons system-wide, we check that here.
Definition: gtk/ui.cpp:147
wxFont GetInfoFont(wxWindow *aWindow)
Definition: ui_common.cpp:156
see class PGM_BASE
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:111
int min_interval
Minimum time, in seconds, between subsequent backups.
bool backup_on_autosave
Trigger a backup on autosave.
unsigned long long limit_total_size
Maximum total size of backups (bytes), 0 for unlimited.
int limit_total_files
Maximum number of backup archives to retain.
int limit_daily_files
Maximum files to keep per day, 0 for unlimited.
bool enabled
Automatically back up the project when files are saved.