123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331 |
- """
- Overview
- ========
- A Tkinter-based menuconfig implementation, based around a treeview control and
- a help display. The interface should feel familiar to people used to qconf
- ('make xconfig'). Compatible with both Python 2 and Python 3.
- The display can be toggled between showing the full tree and showing just a
- single menu (like menuconfig.py). Only single-menu mode distinguishes between
- symbols defined with 'config' and symbols defined with 'menuconfig'.
- A show-all mode is available that shows invisible items in red.
- Supports both mouse and keyboard controls. The following keyboard shortcuts are
- available:
- Ctrl-S : Save configuration
- Ctrl-O : Open configuration
- Ctrl-A : Toggle show-all mode
- Ctrl-N : Toggle show-name mode
- Ctrl-M : Toggle single-menu mode
- Ctrl-F, /: Open jump-to dialog
- ESC : Close
- Running
- =======
- guiconfig.py can be run either as a standalone executable or by calling the
- menuconfig() function with an existing Kconfig instance. The second option is a
- bit inflexible in that it will still load and save .config, etc.
- When run in standalone mode, the top-level Kconfig file to load can be passed
- as a command-line argument. With no argument, it defaults to "Kconfig".
- The KCONFIG_CONFIG environment variable specifies the .config file to load (if
- it exists) and save. If KCONFIG_CONFIG is unset, ".config" is used.
- When overwriting a configuration file, the old version is saved to
- <filename>.old (e.g. .config.old).
- $srctree is supported through Kconfiglib.
- """
- import errno
- import os
- import re
- import sys
- _PY2 = sys.version_info[0] < 3
- if _PY2:
-
- from Tkinter import *
- import ttk
- import tkFont as font
- import tkFileDialog as filedialog
- import tkMessageBox as messagebox
- else:
-
- from tkinter import *
- import tkinter.ttk as ttk
- import tkinter.font as font
- from tkinter import filedialog, messagebox
- from kconfiglib import Symbol, Choice, MENU, COMMENT, MenuNode, \
- BOOL, TRISTATE, STRING, INT, HEX, \
- AND, OR, \
- expr_str, expr_value, split_expr, \
- standard_sc_expr_str, \
- TRI_TO_STR, TYPE_TO_STR, \
- standard_kconfig, standard_config_filename
- _USE_EMBEDDED_IMAGES = True
- _JUMP_TO_HELP = """\
- Type one or more strings/regexes and press Enter to list items that match all
- of them. Python's regex flavor is used (see the 're' module). Double-clicking
- an item will jump to it. Item values can be toggled directly within the dialog.\
- """
- def _main():
- menuconfig(standard_kconfig(__doc__))
- def menuconfig(kconf):
- """
- Launches the configuration interface, returning after the user exits.
- kconf:
- Kconfig instance to be configured
- """
- global _kconf
- global _conf_filename
- global _minconf_filename
- global _jump_to_tree
- global _cur_menu
- _kconf = kconf
- _jump_to_tree = None
- _create_id_to_node()
- _create_ui()
-
- _conf_filename = standard_config_filename()
-
- _set_conf_changed(_load_config())
-
- _minconf_filename = "defconfig"
-
- _cur_menu = _kconf.top_node
-
- if not _shown_menu_nodes(kconf.top_node):
-
- _show_all_var.set(True)
- if not _shown_menu_nodes(kconf.top_node):
-
-
- _root.wait_visibility()
- messagebox.showerror(
- "Error",
- "Empty configuration -- nothing to configure.\n\n"
- "Check that environment variables are set properly.")
- _root.destroy()
- return
-
- _update_tree()
-
-
- _select(_tree, _tree.get_children()[0])
- _tree.focus_set()
-
-
-
- _root.withdraw()
- _root.update_idletasks()
-
- _root.geometry("+{}+{}".format(
- (_root.winfo_screenwidth() - _root.winfo_reqwidth())//2,
- (_root.winfo_screenheight() - _root.winfo_reqheight())//2))
-
- _root.deiconify()
-
-
-
- _root.geometry(_root.geometry())
- _root.mainloop()
- def _load_config():
-
-
-
-
- print(_kconf.load_config())
- if not os.path.exists(_conf_filename):
-
- return True
- return _needs_save()
- def _needs_save():
-
-
- if _kconf.missing_syms:
-
- return True
- for sym in _kconf.unique_defined_syms:
- if sym.user_value is None:
- if sym.config_string:
-
- return True
- elif sym.orig_type in (BOOL, TRISTATE):
- if sym.tri_value != sym.user_value:
-
- return True
- elif sym.str_value != sym.user_value:
-
- return True
-
- return False
- def _create_id_to_node():
- global _id_to_node
- _id_to_node = {str(id(node)): node for node in _kconf.node_iter()}
- def _create_ui():
-
- global _root
- global _tree
-
-
- _root = Tk()
- _load_images()
- _init_misc_ui()
- _fix_treeview_issues()
- _create_top_widgets()
-
- panedwindow, _tree = _create_kconfig_tree_and_desc(_root)
- panedwindow.grid(column=0, row=1, sticky="nsew")
- _create_status_bar()
- _root.columnconfigure(0, weight=1)
-
- _root.rowconfigure(1, weight=1)
-
- _do_showname()
- _tree.bind("<Left>", _tree_left_key)
- _tree.bind("<Right>", _tree_right_key)
-
-
- _tree.bind("<<TreeviewOpen>>", _tree_open)
-
- _tree.bind("<<TreeviewSelect>>", _update_menu_path, add=True)
- _root.bind("<Control-s>", _save)
- _root.bind("<Control-o>", _open)
- _root.bind("<Control-a>", _toggle_showall)
- _root.bind("<Control-n>", _toggle_showname)
- _root.bind("<Control-m>", _toggle_tree_mode)
- _root.bind("<Control-f>", _jump_to_dialog)
- _root.bind("/", _jump_to_dialog)
- _root.bind("<Escape>", _on_quit)
- def _load_images():
-
-
-
-
-
-
-
-
- def load_image(name, data):
- var_name = "_{}_img".format(name)
- if _USE_EMBEDDED_IMAGES:
- globals()[var_name] = PhotoImage(data=data, format="gif")
- else:
- globals()[var_name] = PhotoImage(
- file=os.path.join(os.path.dirname(__file__), name + ".gif"),
- format="gif")
-
-
- load_image("icon", "R0lGODlhMAAwAPEDAAAAAADQAO7u7v///yH5BAUKAAMALAAAAAAwADAAAAL/nI+gy+2Pokyv2jazuZxryQjiSJZmyXxHeLbumH6sEATvW8OLNtf5bfLZRLFITzgEipDJ4mYxYv6A0ubuqYhWk66tVTE4enHer7jcKvt0LLUw6P45lvEprT6c0+v7OBuqhYdHohcoqIbSAHc4ljhDwrh1UlgSydRCWWlp5wiYZvmSuSh4IzrqV6p4cwhkCsmY+nhK6uJ6t1mrOhuJqfu6+WYiCiwl7HtLjNSZZZis/MeM7NY3TaRKS40ooDeoiVqIultsrav92bi9c3a5KkkOsOJZpSS99m4k/0zPng4Gks9JSbB+8DIcoQfnjwpZCHv5W+ip4aQrKrB0uOikYhiMCBw1/uPoQUMBADs=")
- load_image("n_bool", "R0lGODdhEAAQAPAAAAgICP///ywAAAAAEAAQAAACIISPacHtvp5kcb5qG85hZ2+BkyiRF8BBaEqtrKkqslEAADs=")
- load_image("y_bool", "R0lGODdhEAAQAPEAAAgICADQAP///wAAACwAAAAAEAAQAAACMoSPacLtvlh4YrIYsst2cV19AvaVF9CUXBNJJoum7ymrsKuCnhiupIWjSSjAFuWhSCIKADs=")
- load_image("n_tri", "R0lGODlhEAAQAPD/AAEBAf///yH5BAUKAAIALAAAAAAQABAAAAInlI+pBrAKQnCPSUlXvFhznlkfeGwjKZhnJ65h6nrfi6h0st2QXikFADs=")
- load_image("m_tri", "R0lGODlhEAAQAPEDAAEBAeQMuv///wAAACH5BAUKAAMALAAAAAAQABAAAAI5nI+pBrAWAhPCjYhiAJQCnWmdoElHGVBoiK5M21ofXFpXRIrgiecqxkuNciZIhNOZFRNI24PhfEoLADs=")
- load_image("y_tri", "R0lGODlhEAAQAPEDAAICAgDQAP///wAAACH5BAUKAAMALAAAAAAQABAAAAI0nI+pBrAYBhDCRRUypfmergmgZ4xjMpmaw2zmxk7cCB+pWiVqp4MzDwn9FhGZ5WFjIZeGAgA7")
- load_image("m_my", "R0lGODlhEAAQAPEDAAAAAOQMuv///wAAACH5BAUKAAMALAAAAAAQABAAAAI5nIGpxiAPI2ghxFinq/ZygQhc94zgZopmOLYf67anGr+oZdp02emfV5n9MEHN5QhqICETxkABbQ4KADs=")
- load_image("y_my", "R0lGODlhEAAQAPH/AAAAAADQAAPRA////yH5BAUKAAQALAAAAAAQABAAAAM+SArcrhCMSSuIM9Q8rxxBWIXawIBkmWonupLd565Um9G1PIs59fKmzw8WnAlusBYR2SEIN6DmAmqBLBxYSAIAOw==")
- load_image("n_locked", "R0lGODlhEAAQAPABAAAAAP///yH5BAUKAAEALAAAAAAQABAAAAIgjB8AyKwN04pu0vMutpqqz4Hih4ydlnUpyl2r23pxUAAAOw==")
- load_image("m_locked", "R0lGODlhEAAQAPD/AAAAAOQMuiH5BAUKAAIALAAAAAAQABAAAAIylC8AyKwN04ohnGcqqlZmfXDWI26iInZoyiore05walolV39ftxsYHgL9QBBMBGFEFAAAOw==")
- load_image("y_locked", "R0lGODlhEAAQAPD/AAAAAADQACH5BAUKAAIALAAAAAAQABAAAAIylC8AyKzNgnlCtoDTwvZwrHydIYpQmR3KWq4uK74IOnp0HQPmnD3cOVlUIAgKsShkFAAAOw==")
- load_image("not_selected", "R0lGODlhEAAQAPD/AAAAAP///yH5BAUKAAIALAAAAAAQABAAAAIrlA2px6IBw2IpWglOvTYhzmUbGD3kNZ5QqrKn2YrqigCxZoMelU6No9gdCgA7")
- load_image("selected", "R0lGODlhEAAQAPD/AAAAAP///yH5BAUKAAIALAAAAAAQABAAAAIzlA2px6IBw2IpWglOvTah/kTZhimASJomiqonlLov1qptHTsgKSEzh9H8QI0QzNPwmRoFADs=")
- load_image("edit", "R0lGODlhEAAQAPIFAAAAAKOLAMuuEPvXCvrxvgAAAAAAAAAAACH5BAUKAAUALAAAAAAQABAAAANCWLqw/gqMBp8cszJxcwVC2FEOEIAi5kVBi3IqWZhuCGMyfdpj2e4pnK+WAshmvxeAcETWlsxPkkBtsqBMa8TIBSQAADs=")
- def _fix_treeview_issues():
-
- global _treeview_rowheight
- style = ttk.Style()
-
-
-
- _treeview_rowheight = font.Font(font=style.lookup("Treeview", "font")) \
- .metrics("linespace") + 2
- style.configure("Treeview", rowheight=_treeview_rowheight)
-
-
- for option in "foreground", "background":
-
-
-
- style.map(
- "Treeview",
- **{option: [elm for elm in style.map("Treeview", query_opt=option)
- if elm[:2] != ("!disabled", "!selected")]})
- def _init_misc_ui():
-
- _root.title(_kconf.mainmenu_text)
-
- _root.tk.call("wm", "iconphoto", _root._w, "-default", _icon_img)
-
-
- _root.minsize(128, 128)
- _root.protocol("WM_DELETE_WINDOW", _on_quit)
-
-
- if _root.tk.call("tk", "windowingsystem") == "x11":
- style = ttk.Style()
- if "clam" in style.theme_names():
- style.theme_use("clam")
- def _create_top_widgets():
-
- global _show_all_var
- global _show_name_var
- global _single_menu_var
- global _menupath
- global _backbutton
- topframe = ttk.Frame(_root)
- topframe.grid(column=0, row=0, sticky="ew")
- ttk.Button(topframe, text="Save", command=_save) \
- .grid(column=0, row=0, sticky="ew", padx=".05c", pady=".05c")
- ttk.Button(topframe, text="Save as...", command=_save_as) \
- .grid(column=1, row=0, sticky="ew")
- ttk.Button(topframe, text="Save minimal (advanced)...",
- command=_save_minimal) \
- .grid(column=2, row=0, sticky="ew", padx=".05c")
- ttk.Button(topframe, text="Open...", command=_open) \
- .grid(column=3, row=0)
- ttk.Button(topframe, text="Jump to...", command=_jump_to_dialog) \
- .grid(column=4, row=0, padx=".05c")
- _show_name_var = BooleanVar()
- ttk.Checkbutton(topframe, text="Show name", command=_do_showname,
- variable=_show_name_var) \
- .grid(column=0, row=1, sticky="nsew", padx=".05c", pady="0 .05c",
- ipady=".2c")
- _show_all_var = BooleanVar()
- ttk.Checkbutton(topframe, text="Show all", command=_do_showall,
- variable=_show_all_var) \
- .grid(column=1, row=1, sticky="nsew", pady="0 .05c")
-
-
- def show_all_updated(*_):
- global _show_all
- _show_all = _show_all_var.get()
- _trace_write(_show_all_var, show_all_updated)
- _show_all_var.set(False)
- _single_menu_var = BooleanVar()
- ttk.Checkbutton(topframe, text="Single-menu mode", command=_do_tree_mode,
- variable=_single_menu_var) \
- .grid(column=2, row=1, sticky="nsew", padx=".05c", pady="0 .05c")
- _backbutton = ttk.Button(topframe, text="<--", command=_leave_menu,
- state="disabled")
- _backbutton.grid(column=0, row=4, sticky="nsew", padx=".05c", pady="0 .05c")
- def tree_mode_updated(*_):
- global _single_menu
- _single_menu = _single_menu_var.get()
- if _single_menu:
- _backbutton.grid()
- else:
- _backbutton.grid_remove()
- _trace_write(_single_menu_var, tree_mode_updated)
- _single_menu_var.set(False)
-
-
- topframe.columnconfigure(5, weight=1)
- _menupath = ttk.Label(topframe)
- _menupath.grid(column=0, row=3, columnspan=6, sticky="w", padx="0.05c",
- pady="0 .05c")
- def _create_kconfig_tree_and_desc(parent):
-
-
-
-
- panedwindow = ttk.Panedwindow(parent, orient=VERTICAL)
- tree_frame, tree = _create_kconfig_tree(panedwindow)
- desc_frame, desc = _create_kconfig_desc(panedwindow)
- panedwindow.add(tree_frame, weight=1)
- panedwindow.add(desc_frame)
- def tree_select(_):
-
-
- desc["state"] = "normal"
- sel = tree.selection()
- if not sel:
- desc.delete("1.0", "end")
- desc["state"] = "disabled"
- return
-
- desc.delete("1.0", "end")
- desc.insert("end", _info_str(_id_to_node[sel[0]]))
- desc["state"] = "disabled"
- tree.bind("<<TreeviewSelect>>", tree_select)
- tree.bind("<1>", _tree_click)
- tree.bind("<Double-1>", _tree_double_click)
- tree.bind("<Return>", _tree_enter)
- tree.bind("<KP_Enter>", _tree_enter)
- tree.bind("<space>", _tree_toggle)
- tree.bind("n", _tree_set_val(0))
- tree.bind("m", _tree_set_val(1))
- tree.bind("y", _tree_set_val(2))
- return panedwindow, tree
- def _create_kconfig_tree(parent):
-
- frame = ttk.Frame(parent)
- tree = ttk.Treeview(frame, selectmode="browse", height=20,
- columns=("name",))
- tree.heading("#0", text="Option", anchor="w")
- tree.heading("name", text="Name", anchor="w")
- tree.tag_configure("n-bool", image=_n_bool_img)
- tree.tag_configure("y-bool", image=_y_bool_img)
- tree.tag_configure("m-tri", image=_m_tri_img)
- tree.tag_configure("n-tri", image=_n_tri_img)
- tree.tag_configure("m-tri", image=_m_tri_img)
- tree.tag_configure("y-tri", image=_y_tri_img)
- tree.tag_configure("m-my", image=_m_my_img)
- tree.tag_configure("y-my", image=_y_my_img)
- tree.tag_configure("n-locked", image=_n_locked_img)
- tree.tag_configure("m-locked", image=_m_locked_img)
- tree.tag_configure("y-locked", image=_y_locked_img)
- tree.tag_configure("not-selected", image=_not_selected_img)
- tree.tag_configure("selected", image=_selected_img)
- tree.tag_configure("edit", image=_edit_img)
- tree.tag_configure("invisible", foreground="red")
- tree.grid(column=0, row=0, sticky="nsew")
- _add_vscrollbar(frame, tree)
- frame.columnconfigure(0, weight=1)
- frame.rowconfigure(0, weight=1)
-
-
- insert = tree.insert
- id_ = id
- Symbol_ = Symbol
- for node in _kconf.node_iter():
- item = node.item
- insert("", "end", iid=id_(node),
- values=item.name if item.__class__ is Symbol_ else "")
- return frame, tree
- def _create_kconfig_desc(parent):
-
- frame = ttk.Frame(parent)
- desc = Text(frame, height=12, wrap="none", borderwidth=0,
- state="disabled")
- desc.grid(column=0, row=0, sticky="nsew")
-
-
- desc.bind("<1>", lambda _: desc.focus_set())
- _add_vscrollbar(frame, desc)
- frame.columnconfigure(0, weight=1)
- frame.rowconfigure(0, weight=1)
- return frame, desc
- def _add_vscrollbar(parent, widget):
-
- vscrollbar = ttk.Scrollbar(parent, orient="vertical",
- command=widget.yview)
- vscrollbar.grid(column=1, row=0, sticky="ns")
- def yscrollcommand(first, last):
-
-
- if float(first) <= 0.0 and float(last) >= 1.0:
- vscrollbar.grid_remove()
- else:
- vscrollbar.grid()
- vscrollbar.set(first, last)
- widget["yscrollcommand"] = yscrollcommand
- def _create_status_bar():
-
- global _status_label
- _status_label = ttk.Label(_root, anchor="e", padding="0 0 0.4c 0")
- _status_label.grid(column=0, row=3, sticky="ew")
- def _set_status(s):
-
- _status_label["text"] = s
- def _set_conf_changed(changed):
-
- global _conf_changed
- _conf_changed = changed
- if changed:
- _set_status("Modified")
- def _update_tree():
-
-
-
-
-
-
-
- old_selection = _tree.selection()
- old_focus = _tree.focus()
-
-
- _tree.detach(*_id_to_node.keys())
- if _single_menu:
- _build_menu_tree()
- else:
- _build_full_tree(_kconf.top_node)
- _tree.selection_set(old_selection)
- _tree.focus(old_focus)
- def _build_full_tree(menu):
-
-
-
-
- for node in _shown_full_nodes(menu):
- _add_to_tree(node, _kconf.top_node)
-
-
- if node.list and not isinstance(node.item, Symbol):
- if _tree.item(id(node), "open"):
- _build_full_tree(node)
- else:
-
-
- shown = _shown_menu_nodes(node)
- if shown:
-
- _tree.move(id(shown[0]), id(shown[0].parent), "end")
- def _shown_full_nodes(menu):
-
-
-
- def rec(node):
- res = []
- while node:
- if _visible(node) or _show_all:
- res.append(node)
- if node.list and isinstance(node.item, Symbol):
-
- res += rec(node.list)
- elif node.list and isinstance(node.item, Symbol):
-
-
-
-
- shown_children = rec(node.list)
- if shown_children:
- res.append(node)
- res += shown_children
- node = node.next
- return res
- return rec(menu.list)
- def _build_menu_tree():
-
- for node in _shown_menu_nodes(_cur_menu):
- _add_to_tree(node, _cur_menu)
- def _shown_menu_nodes(menu):
-
-
- def rec(node):
- res = []
- while node:
- if _visible(node) or _show_all:
- res.append(node)
- if node.list and not node.is_menuconfig:
- res += rec(node.list)
- elif node.list and isinstance(node.item, Symbol):
- shown_children = rec(node.list)
- if shown_children:
-
- res.append(node)
- if not node.is_menuconfig:
- res += shown_children
- node = node.next
- return res
- return rec(menu.list)
- def _visible(node):
-
-
- return node.prompt and expr_value(node.prompt[1]) and not \
- (node.item == MENU and not expr_value(node.visibility))
- def _add_to_tree(node, top):
-
-
-
- parent = node.parent
- _tree.move(id(node), "" if parent is top else id(parent), "end")
- _tree.item(
- id(node),
- text=_node_str(node),
-
-
-
-
- tags=_img_tag(node) if _visible(node) or not _show_all else
- _img_tag(node) + " invisible")
- def _node_str(node):
-
- if node.prompt:
- if node.item == COMMENT:
- s = "*** {} ***".format(node.prompt[0])
- else:
- s = node.prompt[0]
- if isinstance(node.item, Symbol):
- sym = node.item
-
-
-
- if sym.user_value is None and sym.type and not \
- (sym.choice and sym.choice.tri_value == 2):
- s += " (NEW)"
- elif isinstance(node.item, Symbol):
-
- s = "<{}>".format(node.item.name)
- else:
-
-
- s = standard_sc_expr_str(node.item)
- if isinstance(node.item, Symbol):
- sym = node.item
- if sym.orig_type == STRING:
- s += ": " + sym.str_value
- elif sym.orig_type in (INT, HEX):
- s = "({}) {}".format(sym.str_value, s)
- elif isinstance(node.item, Choice) and node.item.tri_value == 2:
-
-
- sym = node.item.selection
- if sym:
- for sym_node in sym.nodes:
-
-
- if sym_node.parent is node and sym_node.prompt:
- s += " ({})".format(sym_node.prompt[0])
- break
- else:
-
-
- for sym_node in sym.nodes:
- if sym_node.prompt:
- s += " ({})".format(sym_node.prompt[0])
- break
-
-
-
- if _single_menu and node.is_menuconfig:
- s += " --->" if _shown_menu_nodes(node) else " ----"
- return s
- def _img_tag(node):
-
-
- item = node.item
- if item in (MENU, COMMENT) or not item.orig_type:
- return ""
- if item.orig_type in (STRING, INT, HEX):
- return "edit"
-
- if _is_y_mode_choice_sym(item):
-
- return "selected" if item.choice.selection is item else "not-selected"
- if len(item.assignable) <= 1:
-
- return "" if isinstance(item, Choice) else item.str_value + "-locked"
- if item.type == BOOL:
- return item.str_value + "-bool"
-
- if item.assignable == (1, 2):
- return item.str_value + "-my"
- return item.str_value + "-tri"
- def _is_y_mode_choice_sym(item):
-
-
-
- return isinstance(item, Symbol) and item.choice and item.visibility == 2
- def _tree_click(event):
-
- tree = event.widget
- if tree.identify_element(event.x, event.y) == "image":
- item = tree.identify_row(event.y)
-
-
- _select(tree, item)
- _change_node(_id_to_node[item], tree.winfo_toplevel())
- return "break"
- def _tree_double_click(event):
-
-
-
- if not _in_heading(event):
- return _tree_enter(event)
- def _in_heading(event):
-
- tree = event.widget
- return hasattr(tree, "identify_region") and \
- tree.identify_region(event.x, event.y) in ("heading", "separator")
- def _tree_enter(event):
-
-
- tree = event.widget
- sel = tree.focus()
- if sel:
- node = _id_to_node[sel]
- if tree.get_children(sel):
- _tree_toggle_open(sel)
- elif _single_menu_mode_menu(node, tree):
- _enter_menu_and_select_first(node)
- else:
- _change_node(node, tree.winfo_toplevel())
- return "break"
- def _tree_toggle(event):
-
-
- tree = event.widget
- sel = tree.focus()
- if sel:
- node = _id_to_node[sel]
- if _changeable(node):
- _change_node(node, tree.winfo_toplevel())
- elif _single_menu_mode_menu(node, tree):
- _enter_menu_and_select_first(node)
- elif tree.get_children(sel):
- _tree_toggle_open(sel)
- return "break"
- def _tree_left_key(_):
-
- if _single_menu:
-
- _leave_menu()
- return "break"
-
- def _tree_right_key(_):
-
- sel = _tree.focus()
- if sel:
- node = _id_to_node[sel]
-
- if _single_menu_mode_menu(node, _tree):
- _enter_menu_and_select_first(node)
- return "break"
-
- def _single_menu_mode_menu(node, tree):
-
-
- return _single_menu and tree is _tree and node.is_menuconfig and \
- _shown_menu_nodes(node)
- def _changeable(node):
-
- sc = node.item
- if not isinstance(sc, (Symbol, Choice)):
- return False
-
-
-
- if not (node.prompt and expr_value(node.prompt[1])):
- return False
- return sc.orig_type in (STRING, INT, HEX) or len(sc.assignable) > 1 \
- or _is_y_mode_choice_sym(sc)
- def _tree_toggle_open(item):
-
- if _tree.item(item, "open"):
- _tree.item(item, open=False)
- else:
- node = _id_to_node[item]
- if not isinstance(node.item, Symbol):
-
- _build_full_tree(node)
- _tree.item(item, open=True)
- def _tree_set_val(tri_val):
- def tree_set_val(event):
-
-
-
- sel = event.widget.focus()
- if sel:
- sc = _id_to_node[sel].item
- if isinstance(sc, (Symbol, Choice)) and tri_val in sc.assignable:
- _set_val(sc, tri_val)
- return tree_set_val
- def _tree_open(_):
-
- if _single_menu:
-
-
-
-
- return
- node = _id_to_node[_tree.focus()]
-
-
- if not isinstance(node.item, Symbol):
- _build_full_tree(node)
- def _update_menu_path(_):
-
-
- sel = _tree.selection()
- _menupath["text"] = _menu_path_info(_id_to_node[sel[0]]) if sel else ""
- def _item_row(item):
-
-
-
-
-
- row = 0
- while True:
- prev = _tree.prev(item)
- if prev:
- item = prev
- row += _n_rows(item)
- else:
- item = _tree.parent(item)
- if not item:
- return row
- row += 1
- def _n_rows(item):
-
-
- rows = 1
- if _tree.item(item, "open"):
- for child in _tree.get_children(item):
- rows += _n_rows(child)
- return rows
- def _attached(item):
-
-
-
- return bool(_tree.next(item) or _tree.prev(item) or _tree.parent(item))
- def _change_node(node, parent):
-
-
-
- if not _changeable(node):
- return
-
- sc = node.item
- if sc.type in (INT, HEX, STRING):
- s = _set_val_dialog(node, parent)
-
-
- if _PY2 and isinstance(s, unicode):
- s = s.encode("utf-8", "ignore")
- if s is not None:
- _set_val(sc, s)
- elif len(sc.assignable) == 1:
-
-
- _set_val(sc, sc.assignable[0])
- else:
-
-
- val_index = sc.assignable.index(sc.tri_value)
- _set_val(sc, sc.assignable[(val_index + 1) % len(sc.assignable)])
- def _set_val(sc, val):
-
-
-
-
- if val in TRI_TO_STR:
- val = TRI_TO_STR[val]
- if val != sc.str_value:
- sc.set_value(val)
- _set_conf_changed(True)
-
-
-
- stayput = _loc_ref_item()
- old_row = _item_row(stayput)
- _update_tree()
-
-
-
- if _attached(stayput):
- _tree.yview_scroll(_item_row(stayput) - old_row, "units")
- if _jump_to_tree:
- _update_jump_to_display()
- def _set_val_dialog(node, parent):
-
-
- def ok(_=None):
-
- global _entry_res
- s = entry.get()
- if sym.type == HEX and not s.startswith(("0x", "0X")):
- s = "0x" + s
- if _check_valid(dialog, entry, sym, s):
- _entry_res = s
- dialog.destroy()
- def cancel(_=None):
- global _entry_res
- _entry_res = None
- dialog.destroy()
- sym = node.item
- dialog = Toplevel(parent)
- dialog.title("Enter {} value".format(TYPE_TO_STR[sym.type]))
- dialog.resizable(False, False)
- dialog.transient(parent)
- dialog.protocol("WM_DELETE_WINDOW", cancel)
- ttk.Label(dialog, text=node.prompt[0] + ":") \
- .grid(column=0, row=0, columnspan=2, sticky="w", padx=".3c",
- pady=".2c .05c")
- entry = ttk.Entry(dialog, width=30)
-
- entry.insert(0, sym.str_value)
- entry.selection_range(0, "end")
- entry.grid(column=0, row=1, columnspan=2, sticky="ew", padx=".3c")
- entry.focus_set()
- range_info = _range_info(sym)
- if range_info:
- ttk.Label(dialog, text=range_info) \
- .grid(column=0, row=2, columnspan=2, sticky="w", padx=".3c",
- pady=".2c 0")
- ttk.Button(dialog, text="OK", command=ok) \
- .grid(column=0, row=4 if range_info else 3, sticky="e", padx=".3c",
- pady=".4c")
- ttk.Button(dialog, text="Cancel", command=cancel) \
- .grid(column=1, row=4 if range_info else 3, padx="0 .3c")
-
-
- dialog.columnconfigure(0, weight=1)
- _center_on_root(dialog)
-
-
-
- def scroll_entry(_):
- _root.update_idletasks()
- entry.unbind("<Expose>")
- entry.xview_moveto(1)
- entry.bind("<Expose>", scroll_entry)
-
- dialog.wait_visibility()
- dialog.grab_set()
- dialog.bind("<Return>", ok)
- dialog.bind("<KP_Enter>", ok)
- dialog.bind("<Escape>", cancel)
-
- parent.wait_window(dialog)
-
- parent.grab_set()
- return _entry_res
- def _center_on_root(dialog):
-
-
-
- dialog.withdraw()
- _root.update_idletasks()
- dialog_width = dialog.winfo_reqwidth()
- dialog_height = dialog.winfo_reqheight()
- screen_width = _root.winfo_screenwidth()
- screen_height = _root.winfo_screenheight()
- x = _root.winfo_rootx() + (_root.winfo_width() - dialog_width)//2
- y = _root.winfo_rooty() + (_root.winfo_height() - dialog_height)//2
-
- if x + dialog_width > screen_width:
- x = screen_width - dialog_width
- elif x < 0:
- x = 0
- if y + dialog_height > screen_height:
- y = screen_height - dialog_height
- elif y < 0:
- y = 0
- dialog.geometry("+{}+{}".format(x, y))
- dialog.deiconify()
- def _check_valid(dialog, entry, sym, s):
-
-
- if sym.type not in (INT, HEX):
-
- return True
- base = 10 if sym.type == INT else 16
- try:
- int(s, base)
- except ValueError:
- messagebox.showerror(
- "Bad value",
- "'{}' is a malformed {} value".format(
- s, TYPE_TO_STR[sym.type]),
- parent=dialog)
- entry.focus_set()
- return False
- for low_sym, high_sym, cond in sym.ranges:
- if expr_value(cond):
- low_s = low_sym.str_value
- high_s = high_sym.str_value
- if not int(low_s, base) <= int(s, base) <= int(high_s, base):
- messagebox.showerror(
- "Value out of range",
- "{} is outside the range {}-{}".format(s, low_s, high_s),
- parent=dialog)
- entry.focus_set()
- return False
- break
- return True
- def _range_info(sym):
-
-
- if sym.type in (INT, HEX):
- for low, high, cond in sym.ranges:
- if expr_value(cond):
- return "Range: {}-{}".format(low.str_value, high.str_value)
- return None
- def _save(_=None):
-
- if _try_save(_kconf.write_config, _conf_filename, "configuration"):
- _set_conf_changed(False)
- _tree.focus_set()
- def _save_as():
-
- global _conf_filename
- filename = _conf_filename
- while True:
- filename = filedialog.asksaveasfilename(
- title="Save configuration as",
- initialdir=os.path.dirname(filename),
- initialfile=os.path.basename(filename),
- parent=_root)
- if not filename:
- break
- if _try_save(_kconf.write_config, filename, "configuration"):
- _conf_filename = filename
- break
- _tree.focus_set()
- def _save_minimal():
-
-
- global _minconf_filename
- filename = _minconf_filename
- while True:
- filename = filedialog.asksaveasfilename(
- title="Save minimal configuration as",
- initialdir=os.path.dirname(filename),
- initialfile=os.path.basename(filename),
- parent=_root)
- if not filename:
- break
- if _try_save(_kconf.write_min_config, filename,
- "minimal configuration"):
- _minconf_filename = filename
- break
- _tree.focus_set()
- def _open(_=None):
-
- global _conf_filename
- if _conf_changed and \
- not messagebox.askokcancel(
- "Unsaved changes",
- "You have unsaved changes. Load new configuration anyway?"):
- return
- filename = _conf_filename
- while True:
- filename = filedialog.askopenfilename(
- title="Open configuration",
- initialdir=os.path.dirname(filename),
- initialfile=os.path.basename(filename),
- parent=_root)
- if not filename:
- break
- if _try_load(filename):
-
-
- _conf_filename = filename
- _set_conf_changed(_needs_save())
- if _single_menu and not _shown_menu_nodes(_cur_menu):
-
-
- _show_all_var.set(True)
- _update_tree()
- break
- _tree.focus_set()
- def _toggle_showname(_):
-
- _show_name_var.set(not _show_name_var.get())
- _do_showname()
- def _do_showname():
-
-
-
- tree_width = _tree.winfo_width()
- if _show_name_var.get():
- _tree["displaycolumns"] = ("name",)
- _tree["show"] = "tree headings"
- name_width = tree_width//3
- _tree.column("#0", width=max(tree_width - name_width, 1))
- _tree.column("name", width=name_width)
- else:
- _tree["displaycolumns"] = ()
- _tree["show"] = "tree"
- _tree.column("#0", width=tree_width)
- _tree.focus_set()
- def _toggle_showall(_):
-
- _show_all_var.set(not _show_all)
- _do_showall()
- def _do_showall():
-
-
- if _nothing_shown():
- _show_all_var.set(True)
- return
-
-
-
- stayput = _vis_loc_ref_item()
-
-
- old_scroll = _item_row(stayput) - \
- _item_row(_tree.identify_row(_treeview_rowheight//2))
- _update_tree()
- if _show_all:
-
-
-
-
-
-
-
-
-
-
- _root.update_idletasks()
-
- _tree.yview(_item_row(stayput) - old_scroll)
- _tree.focus_set()
- def _nothing_shown():
-
-
-
-
-
- return not _shown_menu_nodes(
- _cur_menu if _single_menu else _kconf.top_node)
- def _toggle_tree_mode(_):
-
- _single_menu_var.set(not _single_menu)
- _do_tree_mode()
- def _do_tree_mode():
-
- loc_ref_node = _id_to_node[_loc_ref_item()]
- if not _single_menu:
-
-
-
- _update_tree()
- _jump_to(loc_ref_node)
- _tree.focus_set()
- def _enter_menu_and_select_first(menu):
-
-
- _enter_menu(menu)
- _select(_tree, _tree.get_children()[0])
- def _enter_menu(menu):
-
- global _cur_menu
- _cur_menu = menu
- _update_tree()
- _backbutton["state"] = "disabled" if menu is _kconf.top_node else "normal"
- def _leave_menu():
-
- global _cur_menu
- if _cur_menu is not _kconf.top_node:
- old_menu = _cur_menu
- _cur_menu = _parent_menu(_cur_menu)
- _update_tree()
- _select(_tree, id(old_menu))
- if _cur_menu is _kconf.top_node:
- _backbutton["state"] = "disabled"
- _tree.focus_set()
- def _select(tree, item):
-
- tree.selection_set(item)
- tree.focus(item)
- tree.see(item)
- def _loc_ref_item():
-
-
-
-
- sel = _tree.selection()
- if sel and _tree.bbox(sel[0]):
- return sel[0]
-
-
- return _tree.identify_row(_tree.winfo_height()//2) or \
- _tree.get_children()[0]
- def _vis_loc_ref_item():
-
-
-
- item = _loc_ref_item()
- vis_before = _vis_before(item)
- if vis_before and _tree.bbox(vis_before):
- return vis_before
- vis_after = _vis_after(item)
- if vis_after and _tree.bbox(vis_after):
- return vis_after
- return vis_before or vis_after
- def _vis_before(item):
-
-
- while item:
- if not _tree.tag_has("invisible", item):
- return item
- prev = _tree.prev(item)
- item = prev if prev else _tree.parent(item)
- return None
- def _vis_after(item):
-
-
- while item:
- if not _tree.tag_has("invisible", item):
- return item
- next = _tree.next(item)
- if next:
- item = next
- else:
- item = _tree.parent(item)
- if not item:
- break
- item = _tree.next(item)
- return None
- def _on_quit(_=None):
-
- if not _conf_changed:
- _quit("No changes to save (for '{}')".format(_conf_filename))
- return
- while True:
- ync = messagebox.askyesnocancel("Quit", "Save changes?")
- if ync is None:
- return
- if not ync:
- _quit("Configuration ({}) was not saved".format(_conf_filename))
- return
- if _try_save(_kconf.write_config, _conf_filename, "configuration"):
-
-
- _quit()
- return
- def _quit(msg=None):
-
-
- _root.destroy()
- if msg:
- print(msg)
- def _try_save(save_fn, filename, description):
-
-
-
-
-
-
-
-
- try:
-
- msg = save_fn(filename)
- _set_status(msg)
- print(msg)
- return True
- except EnvironmentError as e:
- messagebox.showerror(
- "Error saving " + description,
- "Error saving {} to '{}': {} (errno: {})"
- .format(description, e.filename, e.strerror,
- errno.errorcode[e.errno]))
- return False
- def _try_load(filename):
-
-
-
-
-
- try:
- msg = _kconf.load_config(filename)
- _set_status(msg)
- print(msg)
- return True
- except EnvironmentError as e:
- messagebox.showerror(
- "Error loading configuration",
- "Error loading '{}': {} (errno: {})"
- .format(filename, e.strerror, errno.errorcode[e.errno]))
- return False
- def _jump_to_dialog(_=None):
-
-
-
-
-
-
-
-
- global _jump_to_tree
- def search(_=None):
- _update_jump_to_matches(msglabel, entry.get())
- def jump_to_selected(event=None):
-
-
- if event and (tree.identify_element(event.x, event.y) == "image" or
- _in_heading(event)):
- return
- sel = tree.selection()
- if not sel:
- return
- node = _id_to_node[sel[0]]
- if node not in _shown_menu_nodes(_parent_menu(node)):
- _show_all_var.set(True)
- if not _single_menu:
-
- _update_tree()
- _jump_to(node)
- dialog.destroy()
- def tree_select(_):
- jumpto_button["state"] = "normal" if tree.selection() else "disabled"
- dialog = Toplevel(_root)
- dialog.geometry("+{}+{}".format(
- _root.winfo_rootx() + 50, _root.winfo_rooty() + 50))
- dialog.title("Jump to symbol/choice/menu/comment")
- dialog.minsize(128, 128)
- dialog.transient(_root)
- ttk.Label(dialog, text=_JUMP_TO_HELP) \
- .grid(column=0, row=0, columnspan=2, sticky="w", padx=".1c",
- pady=".1c")
- entry = ttk.Entry(dialog)
- entry.grid(column=0, row=1, sticky="ew", padx=".1c", pady=".1c")
- entry.focus_set()
- entry.bind("<Return>", search)
- entry.bind("<KP_Enter>", search)
- ttk.Button(dialog, text="Search", command=search) \
- .grid(column=1, row=1, padx="0 .1c", pady="0 .1c")
- msglabel = ttk.Label(dialog)
- msglabel.grid(column=0, row=2, sticky="w", pady="0 .1c")
- panedwindow, tree = _create_kconfig_tree_and_desc(dialog)
- panedwindow.grid(column=0, row=3, columnspan=2, sticky="nsew")
-
- tree.set_children("")
- _jump_to_tree = tree
- jumpto_button = ttk.Button(dialog, text="Jump to selected item",
- state="disabled", command=jump_to_selected)
- jumpto_button.grid(column=0, row=4, columnspan=2, sticky="ns", pady=".1c")
- dialog.columnconfigure(0, weight=1)
-
- dialog.rowconfigure(3, weight=1)
-
- _root.update_idletasks()
- dialog.geometry(dialog.geometry())
-
- dialog.wait_visibility()
- dialog.grab_set()
- tree.bind("<Double-1>", jump_to_selected)
- tree.bind("<Return>", jump_to_selected)
- tree.bind("<KP_Enter>", jump_to_selected)
-
- tree.bind("<<TreeviewSelect>>", tree_select, add=True)
- dialog.bind("<Escape>", lambda _: dialog.destroy())
-
- _root.wait_window(dialog)
- _jump_to_tree = None
- _tree.focus_set()
- def _update_jump_to_matches(msglabel, search_string):
-
-
-
- global _jump_to_matches
- _jump_to_tree.selection_set(())
- try:
-
-
-
-
- regex_searches = [re.compile(regex).search
- for regex in search_string.lower().split()]
- except re.error as e:
- msg = "Bad regular expression"
-
- if hasattr(e, "msg"):
- msg += ": " + e.msg
- msglabel["text"] = msg
-
- _jump_to_tree.set_children("")
- return
- _jump_to_matches = []
- add_match = _jump_to_matches.append
- for node in _sorted_sc_nodes():
-
- sc = node.item
- for search in regex_searches:
-
-
-
-
- if not (sc.name and search(sc.name.lower()) or
- node.prompt and search(node.prompt[0].lower())):
-
-
-
- break
- else:
- add_match(node)
-
- for node in _sorted_menu_comment_nodes():
- for search in regex_searches:
- if not search(node.prompt[0].lower()):
- break
- else:
- add_match(node)
- msglabel["text"] = "" if _jump_to_matches else "No matches"
- _update_jump_to_display()
- if _jump_to_matches:
- item = id(_jump_to_matches[0])
- _jump_to_tree.selection_set(item)
- _jump_to_tree.focus(item)
- def _update_jump_to_display():
-
-
-
- item = _jump_to_tree.item
- id_ = id
- node_str = _node_str
- img_tag = _img_tag
- visible = _visible
- for node in _jump_to_matches:
- item(id_(node),
- text=node_str(node),
- tags=img_tag(node) if visible(node) else
- img_tag(node) + " invisible")
- _jump_to_tree.set_children("", *map(id, _jump_to_matches))
- def _jump_to(node):
-
- if _single_menu:
- _enter_menu(_parent_menu(node))
- else:
- _load_parents(node)
- _select(_tree, id(node))
- def _sorted_sc_nodes(cached_nodes=[]):
-
-
-
- if not cached_nodes:
-
- for sym in sorted(_kconf.unique_defined_syms,
- key=lambda sym: sym.name):
-
- cached_nodes += sym.nodes
-
- choices = sorted(_kconf.unique_choices,
- key=lambda choice: choice.name or "")
- cached_nodes += sorted(
- [node for choice in choices for node in choice.nodes],
- key=lambda node: node.prompt[0] if node.prompt else "")
- return cached_nodes
- def _sorted_menu_comment_nodes(cached_nodes=[]):
-
-
- if not cached_nodes:
- def prompt_text(mc):
- return mc.prompt[0]
- cached_nodes += sorted(_kconf.menus, key=prompt_text)
- cached_nodes += sorted(_kconf.comments, key=prompt_text)
- return cached_nodes
- def _load_parents(node):
-
-
-
-
- parents = []
- cur = node.parent
- while cur is not _kconf.top_node:
- parents.append(cur)
- cur = cur.parent
- parents.reverse()
- for i, parent in enumerate(parents):
- if not _tree.item(id(parent), "open"):
-
-
- for parent in parents[i:]:
-
-
- if not isinstance(parent.item, Symbol):
- _build_full_tree(parent)
- return
- def _parent_menu(node):
-
-
-
- menu = node.parent
- while not menu.is_menuconfig:
- menu = menu.parent
- return menu
- def _trace_write(var, fn):
-
-
-
- if hasattr(var, "trace_add"):
- var.trace_add("write", fn)
- else:
- var.trace_variable("w", fn)
- def _info_str(node):
-
-
-
-
- if isinstance(node.item, Symbol):
- sym = node.item
- return (
- _name_info(sym) +
- _help_info(sym) +
- _direct_dep_info(sym) +
- _defaults_info(sym) +
- _select_imply_info(sym) +
- _kconfig_def_info(sym)
- )
- if isinstance(node.item, Choice):
- choice = node.item
- return (
- _name_info(choice) +
- _help_info(choice) +
- 'Mode: {}\n\n'.format(choice.str_value) +
- _choice_syms_info(choice) +
- _direct_dep_info(choice) +
- _defaults_info(choice) +
- _kconfig_def_info(choice)
- )
-
- return _kconfig_def_info(node)
- def _name_info(sc):
-
-
- return (sc.name if sc.name else standard_sc_expr_str(sc)) + "\n\n"
- def _value_info(sym):
-
-
- return "Value: {}\n".format(
- '"{}"'.format(sym.str_value)
- if sym.orig_type == STRING
- else sym.str_value)
- def _choice_syms_info(choice):
-
-
- s = "Choice symbols:\n"
- for sym in choice.syms:
- s += " - " + sym.name
- if sym is choice.selection:
- s += " (selected)"
- s += "\n"
- return s + "\n"
- def _help_info(sc):
-
-
-
- s = ""
- for node in sc.nodes:
- if node.help is not None:
- s += node.help + "\n\n"
- return s
- def _direct_dep_info(sc):
-
-
-
-
- return "" if sc.direct_dep is _kconf.y else \
- 'Direct dependencies (={}):\n{}\n' \
- .format(TRI_TO_STR[expr_value(sc.direct_dep)],
- _split_expr_info(sc.direct_dep, 2))
- def _defaults_info(sc):
-
- if not sc.defaults:
- return ""
- s = "Default"
- if len(sc.defaults) > 1:
- s += "s"
- s += ":\n"
- for val, cond in sc.orig_defaults:
- s += " - "
- if isinstance(sc, Symbol):
- s += _expr_str(val)
-
-
-
-
-
- if isinstance(val, tuple):
- s += ' (={})'.format(TRI_TO_STR[expr_value(val)])
- else:
-
-
- s += val.name
- s += "\n"
- if cond is not _kconf.y:
- s += " Condition (={}):\n{}" \
- .format(TRI_TO_STR[expr_value(cond)],
- _split_expr_info(cond, 4))
- return s + "\n"
- def _split_expr_info(expr, indent):
-
-
-
-
-
-
-
- if len(split_expr(expr, AND)) > 1:
- split_op = AND
- op_str = "&&"
- else:
- split_op = OR
- op_str = "||"
- s = ""
- for i, term in enumerate(split_expr(expr, split_op)):
- s += "{}{} {}".format(indent*" ",
- " " if i == 0 else op_str,
- _expr_str(term))
-
-
- if isinstance(term, tuple):
- s += " (={})".format(TRI_TO_STR[expr_value(term)])
- s += "\n"
- return s
- def _select_imply_info(sym):
-
-
-
- def sis(expr, val, title):
-
- sis = [si for si in split_expr(expr, OR) if expr_value(si) == val]
- if not sis:
- return ""
- res = title
- for si in sis:
- res += " - {}\n".format(split_expr(si, AND)[0].name)
- return res + "\n"
- s = ""
- if sym.rev_dep is not _kconf.n:
- s += sis(sym.rev_dep, 2,
- "Symbols currently y-selecting this symbol:\n")
- s += sis(sym.rev_dep, 1,
- "Symbols currently m-selecting this symbol:\n")
- s += sis(sym.rev_dep, 0,
- "Symbols currently n-selecting this symbol (no effect):\n")
- if sym.weak_rev_dep is not _kconf.n:
- s += sis(sym.weak_rev_dep, 2,
- "Symbols currently y-implying this symbol:\n")
- s += sis(sym.weak_rev_dep, 1,
- "Symbols currently m-implying this symbol:\n")
- s += sis(sym.weak_rev_dep, 0,
- "Symbols currently n-implying this symbol (no effect):\n")
- return s
- def _kconfig_def_info(item):
-
-
- nodes = [item] if isinstance(item, MenuNode) else item.nodes
- s = "Kconfig definition{}, with parent deps. propagated to 'depends on'\n" \
- .format("s" if len(nodes) > 1 else "")
- s += (len(s) - 1)*"="
- for node in nodes:
- s += "\n\n" \
- "At {}:{}\n" \
- "{}" \
- "Menu path: {}\n\n" \
- "{}" \
- .format(node.filename, node.linenr,
- _include_path_info(node),
- _menu_path_info(node),
- node.custom_str(_name_and_val_str))
- return s
- def _include_path_info(node):
- if not node.include_path:
-
- return ""
- return "Included via {}\n".format(
- " -> ".join("{}:{}".format(filename, linenr)
- for filename, linenr in node.include_path))
- def _menu_path_info(node):
-
- path = ""
- while node.parent is not _kconf.top_node:
- node = node.parent
-
-
-
- path = " -> " + (node.prompt[0] if node.prompt else
- standard_sc_expr_str(node.item)) + path
- return "(Top)" + path
- def _name_and_val_str(sc):
-
-
-
-
-
- if isinstance(sc, Symbol) and not sc.is_constant and not _is_num(sc.name):
- if not sc.nodes:
-
- return "{}(undefined/n)".format(sc.name)
- return '{}(={})'.format(sc.name, sc.str_value)
-
- return standard_sc_expr_str(sc)
- def _expr_str(expr):
-
- return expr_str(expr, _name_and_val_str)
- def _is_num(name):
-
-
-
- try:
- int(name)
- except ValueError:
- if not name.startswith(("0x", "0X")):
- return False
- try:
- int(name, 16)
- except ValueError:
- return False
- return True
- if __name__ == "__main__":
- _main()
|