-
Notifications
You must be signed in to change notification settings - Fork 5
/
ini-editor.ahk
581 lines (537 loc) · 23.7 KB
/
ini-editor.ahk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
;############# Edit ini file settings in a GUI #############################
; A function that can be used to edit settings in an ini file within it's own
; GUI. Just plug this function into your script.
;
; by Rajat, mod by toralf
; www.autohotkey.com/forum/viewtopic.php?p=69534#69534
;
; Tested OS: Windows XP Pro SP2
; AHK_version= 1.0.44.09 ;(http://www.autohotkey.com/download/)
; Language: English
; Date: 2006-08-23
;
; Version: 6
;
; changes since 5:
; - add key type "checkbox" with custom control name
; - added key field options (will only apply in Editor window)
; - whole sections can be set hidden
; - reorganized code in Editor and Creator
; - some fixes and adjustments
; changes since 1.4
; - Creator and Editor GUIs are resizeable (thanks Titan). The shortened Anchor function
; is added with a long name, to avoid nameing conflicts and avoid dependencies.
; - switched from 1.x version numbers to full integer version numbers
; - requires AHK version 1.0.44.09
; - fixed blinking of description field
; changes since 1.3:
; - added field option "Hidden" (thanks jballi)
; - simplified array naming
; - shorted the code
; changes since 1.2:
; - fixed a bug in the description (thanks jaballi and robiandi)
; changes since 1.1:
; - added statusbar (thanks rajat)
; - fixed a bug in Folder browsing
; changes since 1.0:
; - added default value (thanks rajat)
; - fixed error with DisableGui=1 but OwnedBy=0 (thanks kerry)
; - fixed some typos
;
; format:
; =======
; IniSettingsEditor(ProgName, IniFile[, OwnedBy = 0, DisableGui = 0, Help = 0])
;
; with
; ProgName - A string used in the GUI as text to describe the program
; IniFile - that ini file name (with path if not in script directory)
; OwnedBy - GUI ID of the calling GUI, will make the settings GUI owned
; DisableGui - 1=disables calling GUI during editing of settings
;
; example to call in script:
; IniSettingsEditor("Hello World", "Settings.ini", 0, 0)
;
; Include function with:
; #Include Func_IniSettingsEditor_v6.ahk
;
; No global variables needed.
;
; features:
; =========
; - the calling script will wait for the function to end, thus till the settings
; GUI gets closed.
; - Gui ID for the settings GUI is not hard coded, first free ID will be used
; - multiple description lines (comments) for each key and section possible
; - all characters are allowed in section and key names
; - when settings GUI is started first key in first section is pre-selected and
; first section is expanded
; - tree branches expand when items get selected and collapse when items get
; unselected
; - key types besides the default "Text" are supported
; + "File" and "Folder", will have a browse button and its functionality
; + "Float" and "Integer" with consistency check
; + "Hotkey" with its own hotkey control
; + "DateTime" with its own datetime control and custom format, default is
; "dddd MMMM d, yyyy HH:mm:ss tt"
; + "DropDown" with its own dropdown control, list of choices has to be given
; list is pipe "|" separated
; + "Checkbox" where the name of the checkbox can be customized
; - default value can be specified for each key
; - keys can be set invisible (hidden) in the tree
; - to each key control additional AHK specific options can be assigned
;
; format of ini file:
; ===================
; (optional) descriptions: to help the script's users to work with the settings
; add a description line to the ini file following the relevant 'key' or 'section'
; line, put a semi-colon (starts comment), then the name of the key or section
; just above it and a space, followed by any descriptive helpful comment you'd
; like users to see while editing that field.
;
; e.g.
; [SomeSection]
; ;somesection This can describe the section.
; Somekey=SomeValue
; ;somekey Now the descriptive comment can explain this item.
; ;somekey More then one line can be used. As many as you like.
; ;somekey [Type: key type] [format/list]
; ;somekey [Default: default key value]
; ;somekey [Hidden:]
; ;somekey [Options: AHK options that apply to the control]
; ;somekey [CheckboxName: Name of the checkbox control]
;
; (optional) key types: To limit the choice and get correct input a key type can
; be set or each key. Identical to the description start an extra line put a
; semi-colon (starts comment), then the name of the key with a space, then the
; string "Type:" with a space followed by the key type. See the above feature
; list for available key types. Some key types have custom formats or lists,
; they are written after the key type with a space in-between.
;
; (optional) default key value: To allow a easy and quick way back to a
; default value, you can specify a value as default. If no default is given,
; users can go back to the initial key value of that editing session.
; Format: Identical to the description start an extra line, put a semi-colon
; (starts comment line), then the name of the key with a space, then the
; string "Default:" with a space followed by the default value.
;
; (optional) hide key in tree: To hide a key from the user, a key can be set
; hidden.
; Format: Identical to the description start an extra line, put a semi-colon
; (starts comment line), then the name of the key with a space, then the
; string "Hidden:".
;
; (optional) add additional AHK options to key controls. To limit the input
; or enforce a special input into the key controls in the GUI, additional
; AHK options can be specified for each control.
; Format: Identical to the description start an extra line, put a semi-colon
; (starts comment line), then the name of the key with a space, then the
; string "Options" with a space followed by a list of AHK options for that
; AHK control (all separated with a space).
;
; (optional) custom checkbox name: To have a more relavant name then e.g.
; "status" a custom name for the checkbox key type can be specified.
; Format: Identical to the description start an extra line, put a semi-colon
; (starts comment line), then the name of the key with a space, then the
; string "CheckboxName:" with a space followed by the name of the checkbox.
;
;
; limitations:
; ============
; - ini file has to exist and created manually or with the IniFileCreator script
; - section lines have to start with [ and end with ]. No comments allowed on
; same line
; - ini file must only contain settings. Scripts can't be used to store setting,
; since the file is read and interpret as a whole.
; - code: can't use g-labels for tree or edit fields, since the arrays are not
; visible outside the function, hence inside the g-label subroutines.
; - code: can't make GUI resizable, since this is only possible with hard
; coded GUI ID, due to %GuiID%GuiSize label
IniSettingsEditor(ProgName,IniFile,OwnedBy = 0,DisableGui = 0, HelpText = "") {
DetectHiddenWindows, Off
static pos
;Find a GUI ID that does not exist yet
Loop, 99 {
Gui %A_Index%:+LastFoundExist
If not WinExist() {
SettingsGuiID = %A_Index%
break
}Else If (A_Index = 99){
MsgBox, 4112, Error in IniSettingsEditor function, Can't open settings dialog,`nsince no GUI ID was available.
Return 0
}
}
Gui, %SettingsGuiID%:Default
;apply options to settings GUI
If OwnedBy {
Gui, +ToolWindow +Owner%OwnedBy%
If DisableGui
Gui, %OwnedBy%:+Disabled
}Else
DisableGui := False
Gui, +Resize +LabelGuiIniSettingsEditor
IfNotEqual, OwnedBy, 0
Gui, %OwnedBy%:+OwnDialogs
;create GUI (order of the two edit controls is crucial, since ClassNN is order dependent)
Gui, Add, Statusbar
Gui, Add, TreeView, x16 y75 w180 h242 0x400
Gui, Add, Edit, x215 y114 w340 h20, ;ahk_class Edit1
Gui, Add, Edit, x215 y174 w340 h120 ReadOnly, ;ahk_class Edit2
Gui, Add, Button, x250 y335 w70 h30 gExitSettings , E&xit ;ahk_class Button1
Gui, Add, Button, x505 y88 gBtnBrowseKeyValue Hidden, B&rowse ;ahk_class Button2
Gui, Add, Button, x215 y294 gBtnDefaultValue, &Restore ;ahk_class Button3
Gui, Add, DateTime, x215 y114 w340 h20 Hidden, ;ahk_class SysDateTimePick321
Gui, Add, Hotkey, x215 y114 w340 h20 Hidden, ;ahk_class msctls_hotkey321
Gui, Add, DropDownList, x215 y114 w340 h120 Hidden, ;ahk_class ComboBox1
Gui, Add, CheckBox, x215 y114 w340 h20 Hidden, ;ahk_class Button4
Gui, Add, GroupBox, x4 y63 w560 h263 , ;ahk_class Button5
Gui, Font, Bold
Gui, Add, Text, x215 y93, Value ;ahk_class Static1
Gui, Add, Text, x215 y154, Description ;ahk_class Static2
HelpTip = ( All changes are Auto-Saved )
IfNotEqual, HelpText,
{
HelpTip = ( All changes are Auto-Saved - Press F1 for Help )
Hotkey, IfWinActive, %ProgName% Settings
Hotkey, F1, ShowHelp
Hotkey, F1, On
}
Gui, Add, Text, x45 y48 w480 h20 +Center, %HelpTip%
Gui, Font, S16 CDefault Bold, Verdana
Gui, Add, Text, x45 y13 w480 h35 +Center, Settings for %ProgName%
;read data from ini file, build tree and store values and description in arrays
Loop, Read, %IniFile%
{
CurrLine = %A_LoopReadLine%
CurrLineLength := StrLen(CurrLine)
;blank line
If CurrLine is space
Continue
;description (comment) line
If ( InStr(CurrLine,";") = 1 ){
StringLeft, chk2, CurrLine, % CurrLength + 2
StringTrimLeft, Des, CurrLine, % CurrLength + 2
;description of key
If ( %CurrID%Sec = False AND ";" CurrKey A_Space = chk2){
;handle key types
If ( InStr(Des,"Type: ") = 1 ){
StringTrimLeft, Typ, Des, 6
Typ = %Typ%
;the next line modded to hide the Type: from description
Des = ;`n%Des% ;add an extra line to the type definition in the description control
;handle format or list
If (InStr(Typ,"DropDown ") = 1) {
StringTrimLeft, Format, Typ, 9
%CurrID%For = %Format%
Typ = DropDown
Des =
}Else If (InStr(Typ,"DateTime") = 1) {
StringTrimLeft, Format, Typ, 9
If Format is space
Format = dddd MMMM d, yyyy HH:mm:ss tt
%CurrID%For = %Format%
Typ = DateTime
Des =
}
;set type
%CurrID%Typ := Typ
;remember default value
}Else If ( InStr(Des,"Default: ") = 1 ){
StringTrimLeft, Def, Des, 9
%CurrID%Def = %Def%
;remember custom options
}Else If ( InStr(Des,"Options: ") = 1 ){
StringTrimLeft, Opt, Des, 9
%CurrID%Opt = %Opt%
Des =
;remove hidden keys from tree
}Else If ( InStr(Des,"Hidden:") = 1 ){
TV_Delete(CurrID)
Des =
CurrID =
;handle checkbox name
}Else If ( InStr(Des,"CheckboxName: ") = 1 ){
StringTrimLeft, ChkN, Des, 14
%CurrID%ChkN = %ChkN%
Des =
}
%CurrID%Des := %CurrID%Des "`n" Des
;description of section
} Else If ( %CurrID%Sec = True AND ";" CurrSec A_Space = chk2 ){
;remove hidden section from tree
If ( InStr(Des,"Hidden:") = 1 ){
TV_Delete(CurrID)
Des =
CurrSecID =
}
;set description
%CurrID%Des := %CurrID%Des "`n" Des
}
;remove leading and trailing whitespaces and new lines
If ( InStr(%CurrID%Des, "`n") = 1 )
StringTrimLeft, %CurrID%Des, %CurrID%Des, 1
Continue
}
;section line
If ( InStr(CurrLine, "[") = 1 And InStr(CurrLine, "]", "", 0) = CurrLineLength) {
;extract section name
StringTrimLeft, CurrSec, CurrLine, 1
StringTrimRight, CurrSec, CurrSec, 1
CurrSec = %CurrSec%
CurrLength := StrLen(CurrSec) ;to easily trim name off of following comment lines
;add to tree
CurrSecID := TV_Add(CurrSec)
CurrID = %CurrSecID%
%CurrID%Sec := True
CurrKey =
Continue
}
;key line
Pos := InStr(CurrLine,"=")
If ( Pos AND CurrSecID ){
;extract key name and its value
StringLeft, CurrKey, CurrLine, % Pos - 1
StringTrimLeft, CurrVal, CurrLine, %Pos%
CurrKey = %CurrKey% ;remove whitespaces
CurrVal = %CurrVal%
CurrLength := StrLen(CurrKey)
;add to tree and store value
CurrID := TV_Add(CurrKey,CurrSecID)
%CurrID%Val := CurrVal
%CurrID%Sec := False
;store initial value as default for restore function
;will be overwritten if default is specified later on comment line
%CurrID%Def := CurrVal
}
}
;select first key of first section and expand section
TV_Modify(TV_GetChild(TV_GetNext()), "Select")
;show Gui and get UniqueID
Gui, Show, w570 h400, %ProgName% Settings
Gui, +LastFound
GuiID := WinExist()
;check for changes in GUI
Loop {
;get current tree selection
CurrID := TV_GetSelection()
If SetDefault {
%CurrID%Val := %CurrID%Def
LastID = 0
SetDefault := False
ValChanged := True
}
MouseGetPos,,, AWinID, ACtrl
If ( AWinID = GuiID){
If ( ACtrl = "Button3")
SB_SetText("Restores Value to default (if specified), else restores it to initial value before change")
} Else
SB_SetText("")
;change GUI content if tree selection changed
If (CurrID <> LastID) {
;remove custom options from last control
Loop, Parse, InvertedOptions, %A_Space%
GuiControl, %A_Loopfield%, %ControlUsed%
;hide/show browse button depending on key type
Typ := %CurrID%Typ
If Typ in File,Folder
GuiControl, Show , Button2,
Else
GuiControl, Hide , Button2,
;set the needed value control depending on key type
If (Typ = "DateTime")
ControlUsed = SysDateTimePick321
Else If ( Typ = "Hotkey" )
ControlUsed = msctls_hotkey321
Else If ( Typ = "DropDown")
ControlUsed = ComboBox1
Else If ( Typ = "CheckBox")
ControlUsed = Button4
Else ;e.g. Text,File,Folder,Float,Integer or No Tyo (e.g. Section)
ControlUsed = Edit1
;hide/show the value controls
Controls = SysDateTimePick321,msctls_hotkey321,ComboBox1,Button4,Edit1
Loop, Parse, Controls, `,
If ( ControlUsed = A_LoopField )
GuiControl, Show , %A_LoopField%,
Else
GuiControl, Hide , %A_LoopField%,
If ( ControlUsed = "Button4" )
GuiControl, , Button4, % %CurrID%ChkN
;get current options
CurrOpt := %CurrID%Opt
;apply current custom options to current control and memorize them inverted
InvertedOptions =
Loop, Parse, CurrOpt, %A_Space%
{
;get actual option name
StringLeft, chk, A_LoopField, 1
StringTrimLeft, chk2, A_LoopField, 1
If chk In +,-
{
GuiControl, %A_LoopField%, %ControlUsed%
If (chk = "+")
InvertedOptions = %InvertedOptions% -%chk2%
Else
InvertedOptions = %InvertedOptions% +%chk2%
}Else {
GuiControl, +%A_LoopField%, %ControlUsed%
InvertedOptions = %InvertedOptions% -%A_LoopField%
}
}
If %CurrID%Sec { ;section got selected
CurrVal =
GuiControl, , Edit1,
GuiControl, Disable , Edit1,
GuiControl, Disable , Button3,
}Else { ;new key got selected
CurrVal := %CurrID%Val ;get current value
GuiControl, , Edit1, %CurrVal% ;put current value in all value controls
GuiControl, Text, SysDateTimePick321, % %CurrID%For
GuiControl, , SysDateTimePick321, %CurrVal%
GuiControl, , msctls_hotkey321, %CurrVal%
GuiControl, , ComboBox1, % "|" %CurrID%For
GuiControl, ChooseString, ComboBox1, %CurrVal%
GuiControl, , Button4 , %CurrVal%
GuiControl, Enable , Edit1,
GuiControl, Enable , Button3,
}
GuiControl, , Edit2, % %CurrID%Des
}
LastID = %CurrID% ;remember last selection
;sleep to reduce CPU load
Sleep, 100
;exit endless loop, when settings GUI closes
If not WinExist("ahk_id" GuiID)
Break
;if key is selected, get value
If (%CurrID%Sec = False){
GuiControlGet, NewVal, , %ControlUsed%
;save key value when it has been changed
If ( NewVal <> CurrVal OR ValChanged ) {
ValChanged := False
;consistency check if type is integer or float
If (Typ = "Integer")
If NewVal is not space
If NewVal is not Integer
{
GuiControl, , Edit1, %CurrVal%
Continue
}
If (Typ = "Float")
If NewVal is not space
If NewVal is not Integer
If (NewVal <> ".")
If NewVal is not Float
{
GuiControl, , Edit1, %CurrVal%
Continue
}
;set new value and save it to INI
%CurrID%Val := NewVal
CurrVal = %NewVal%
PrntID := TV_GetParent(CurrID)
TV_GetText(SelSec, PrntID)
TV_GetText(SelKey, CurrID)
If (SelSec AND SelKey)
IniWrite, %NewVal%, %IniFile%, %SelSec%, %SelKey%
}
}
}
;Exit button got pressed
ExitSettings:
;re-enable calling GUI
If DisableGui {
Gui, %OwnedBy%:-Disabled
Gui, %OwnedBy%:,Show
}
Gui, Destroy
IfNotEqual, HelpText,
Hotkey, F1, Off
;exit function
Return 1
;browse button got pressed
BtnBrowseKeyValue:
;get current value
GuiControlGet, StartVal, , Edit1
Gui, +OwnDialogs
;Select file or folder depending on key type
If (Typ = "File"){
;get StartFolder
IfExist %A_ScriptDir%\%StartVal%
StartFolder = %A_ScriptDir%
Else IfExist %StartVal%
SplitPath, StartVal, , StartFolder
Else
StartFolder =
;select file
FileSelectFile, Selected,, %StartFolder%, Select file for %SelSec% - %SelKey%, Any file (*.*)
}Else If (Typ = "Folder"){
;get StartFolder
IfExist %A_ScriptDir%\%StartVal%
StartFolder = %A_ScriptDir%\%StartVal%
Else IfExist %StartVal%
StartFolder = %StartVal%
Else
StartFolder =
;select folder
FileSelectFolder, Selected, *%StartFolder% , 3, Select folder for %SelSec% - %SelKey%
;remove last backslash "\" if any
StringRight, LastChar, Selected, 1
If LastChar = \
StringTrimRight, Selected, Selected, 1
}
;If file or folder got selected, remove A_ScriptDir (since it's redundant) and set it into GUI
If Selected {
StringReplace, Selected, Selected, %A_ScriptDir%\
GuiControl, , Edit1, %Selected%
%CurrID%Val := Selected
}
Return ;end of browse button subroutine
;default button got pressed
BtnDefaultValue:
SetDefault := True
Return ;end of default button subroutine
;gui got resized, adjust control sizes
GuiIniSettingsEditorSize:
GuiIniSettingsEditorAnchor("SysTreeView321" , "wh")
GuiIniSettingsEditorAnchor("Edit1" , "x")
GuiIniSettingsEditorAnchor("Edit2" , "xh")
GuiIniSettingsEditorAnchor("Button1" , "xy",true)
GuiIniSettingsEditorAnchor("Button2" , "x",true)
GuiIniSettingsEditorAnchor("Button3" , "xy",true)
GuiIniSettingsEditorAnchor("Button4" , "x",true)
GuiIniSettingsEditorAnchor("Button5" , "wh",true)
GuiIniSettingsEditorAnchor("SysDateTimePick321" , "x")
GuiIniSettingsEditorAnchor("msctls_Hotkey321" , "x")
GuiIniSettingsEditorAnchor("ComboBox1" , "x")
GuiIniSettingsEditorAnchor("Static1" , "x")
GuiIniSettingsEditorAnchor("Static2" , "x")
GuiIniSettingsEditorAnchor("Static3" , "x")
GuiIniSettingsEditorAnchor("Static4" , "x")
Return
ShowHelp:
Gui, %SettingsGuiID%:+OwnDialogs
MsgBox, 64, %ProgName% Settings Help, %HelpText%
Return
} ;end of function
GuiIniSettingsEditorAnchor(ctrl, a, draw = false) { ; v3.2 by Titan (shortened)
static pos
sig = `n%ctrl%=
If !InStr(pos, sig) {
GuiControlGet, p, Pos, %ctrl%
pos := pos . sig . px - A_GuiWidth . "/" . pw - A_GuiWidth . "/"
. py - A_GuiHeight . "/" . ph - A_GuiHeight . "/"
}
StringTrimLeft, p, pos, InStr(pos, sig) - 1 + StrLen(sig)
StringSplit, p, p, /
c = xwyh
Loop, Parse, c
If InStr(a, A_LoopField) {
If A_Index < 3
e := p%A_Index% + A_GuiWidth
Else e := p%A_Index% + A_GuiHeight
m = %m%%A_LoopField%%e%
}
If draw
d = Draw
GuiControl, Move%d%, %ctrl%, %m%
}