oUc@s(ddlZddlZddlZddlmZddlmZddlZddlZddlZddl Z ddl Z ddl m Z ddl mZddl mZddl mZdZd Zeed Zeed Zd ad ad ZdZdadefdYZdS(iN(tctrl(tcopy(t DDUException(tddu_build_repo_list(tddu_package_lookup(tddu_install_packageiititjti s/usr/ddut InnerWindowcBs=eZdZeZeZeZeZdZdZ dZ dZ ddddddZ dZdZdZd Zd Zd d dd Zd d ddd ZdddZddZdZdZdZdZdZdZdZdZdZdZ dZ!dZ"RS(stWrapper around curses.windows objects providing common functions An InnerWindow wraps around a curses window, and represents an area of the screen. Each InnerWindow requires a parent window. The 'ultimate' parent of all InnerWindows is the sole instance of MainWindow. By default, InnerWindows have functions for adding text, processing input, and managing children InnerWindows. The following variables are used to indicate the status of ESC key navigations. begin_esc_sequence indicates that the next keystroke, if 0-9, should be translated to F# use_esc_sequence indicates that, at some point during program execution, ESC has been pressed, and the footer should, for the remainder of program execution, print Esc-#_ for navigation descriptions. Once set to True, it should never be set back to False. update_footer_text is a flag that indicates that Esc was just hit for the first time, and the managing window should immediately update the footer text. TODO: If we can call MainWindow.show_actions() directly, this flag won't be necessary cCs|jjdS(N(twindowt noutrefresh(tself((sinner_window.pyt no_ut_refreshUscCs'|jjtd||jdS(sSets the color attributes to 'color' This private method immediately updates the background color. Note that it doesn't reference self.colort N(R tbkgdtordR (R tcolor((sinner_window.pyt _set_colorXscCsNt|}t|tr.|j|jn|dk rJ|j|n|S(sRCreate a copy of area, and adjust its coordinates to be absolute if neededN(Rt isinstanceR trelative_to_absoluteR tNone(R R tarea((sinner_window.pyt _get_area`s   cCs+tj|j|j|j|j|_dS(sCreate a curses window over the given area If window is provided, use it to translate area to absolute coords If it's none, assume area is already in absolute coords N(tcursestnewwintlinestcolumnsty_loctx_locR (R R R((sinner_window.pyt _init_winjscCsP|j||}||_t|tr[|j|||jdkr[|j|_q[n|j|||dk r||_n|jj|_|dk r||_ n |j|_ |j |j|j j dg|_ g|_d|_|jd|_d|_d|_t|_d|_d|_d|_d|_g|_dS(s^ Build an InnerWindow area (required): Describes the area to use when building this window. Coordinates should be relative to window, if window is given. If window is not given, these must be absolute coordinates on the terminal window (optional): The parent window. If given, area is assumed to indicate a location within the parent. Additionally, if window is an InnerWindow, window.add_object(self) is called to register this new window with its parent color_theme (required if curses window): The color theme for this window. This property gets propagated to subwindows. If None, the parent window's color_theme is used. Unless this window requires unique coloring, the parent theme should be used. color (optional): The color attributes for this window. If None, color_theme.default is used. In general, this parameter is reserved for subclasses of InnerWindow. Other consumers should pass in an appropriate color_theme. highlight_color (optional): Color attributes for this window when 'selected' or 'highlighted.' Defaults to color (meaning no highlighting is used. In general, this parameter is reserved for subclasses of InnerWindow. Other consumers should pass in an appropriate color_theme iiN(Rt color_themeRR t add_objectRRRtdefaultthighlight_colorRR tkeypadtobjectst texts_fullt active_objectt_init_key_dicttdirectory_startt directory_endt start_pointt MAXLENGTHt end_pointt repo_indext super_objt super_wintInputWindow_FirstIndext objects_full(R RR RRR"tat_index((sinner_window.pyt__init__ss8                  cCsgg|_g|_g|_d|_d|_d|_t|_d|_ d|_ d|_ d|_ dS(Ni( R$R1R%RR&R0R*R+R,R-R(R)(R ((sinner_window.pytresets          cCs|j|jdS(N(RR"(R ((sinner_window.pyt make_activescCs|j|jdS(N(RR(R ((sinner_window.pyt make_inactivescCs||_|jjtd|j|j|jjtd||jj|jjtd||jj|jjtd||jjdS(sSpecial private version of _set_color for "footers" This version sets the color of the four windows that make up the footer / border RN( RR RRR tleftR trightttop(R R((sinner_window.pyt_set_footer_colors    cCs~t|tjs'|jj|}n|t|j}|jdk r`|j|jjn|j|j ||_dS(shSet a specific object to be the active object. This function accepts either an integer index, or an object reference. If an object reference is passed in, it must be an object in this InnerWindow.objects list Integers that are out of bounds of the size of the objects list are shifted to be in bounds. N( RttypestIntTypeR$tindextlenR&RR6R5(R R=((sinner_window.pytactivate_objects icCsL|dkr%|jj|||n|jj|||||jdS(sAdd a single line of text to the window 'text' must fit within the specified space, or a curses.error will be thrown by the underlying calls to addstr. N(RR taddstrtaddnstrR (R ttexttstart_ytstart_xt max_chars((sinner_window.pytadd_texts cCs|jj\}}|dkr.||}n|dkrC|}n||}|jdj} |} d} x| D] } t| |kr|j| | ||nd} d}x||t| krC|} | jd| | |}|dkr| |}n|j| | |!j| ||| d7} | |krPqqW|j| |j| ||| d7} | |kruPququW| |S(s!Add a block of text to the window This function will split a block of text at newline characters (\n) and at whitespace, and add it to the screen. Text that doesn't fit in the space indicated is not displayed. The number of lines used is returned iiRiiN( R tgetmaxyxRt expandtabst splitlinesR>RFtrfindtlstrip(R RBRCRDtmax_ytmax_xt win_size_yt win_size_xREt text_linesty_indext num_linestlinetstart_pttend_pt((sinner_window.pyt add_paragraphs<              cCsG|dkrt|j}n||jkrC|jj||ndS(sLAdd an object (usually an InnerWindow) to this window's object list N(RR>R$tinsert(R tobjecttmissing_driver_objectR2((sinner_window.pyR #s cCsG|dkrt|j}n||jkrC|jj||ndS(s> add text to this windows's object texts list N(RR>R%RW(R RBR2((sinner_window.pyt add_string+s cCsQx|jD]}|jq Wg|_d|_|jj|j|jdS(sRemove all objects from this window's list and clear the screen The background of this window will still be displayed; clear the parent if the window should be removed in entiretyN(R$tclearRR&R RR(R RX((sinner_window.pyR[4s    cCsddlm}ddlm}tjdd|jdk r|jd}|tkrt |j |j|st |j |j|r|j dt |j krg|jd7_|j d7_ d}xt|j|j dD]|}|dkrd}n(|t |j dkr!d}nd }|j |j||j |d d |d7}|jqWny0t |j |j|r|j |j anWqtk rqXnU|j|y4t |j |j|r|j |j|anWntk rnXdS|SdS( Ni(tToplist_Window(t Media_WindowisInnerWindow.on_key_downiis- s| REi2(ttoplist_windowR\t media_windowR]tloggingtlogR&RR+RR$R,R>R%R*trangetset_textR t media_patht IndexErrorR?(R tinputR\R]R=t object_indextloopt item_space((sinner_window.pyt on_key_down@sL             cCsddlm}ddlm}tjdd|jdk r|jd}|dkrt|j |j|st|j |j|r|j ddkr^|j d8_ |j d8_ d}xt |j |j dD]r}|dkrd}n(|t |jdkrd}nd }|j |j||j|d d |d7}qW|jny0t|j |j|r|j|j anWqtk rqXnU|j|y4t|j |j|r|j|j |anWntk rnXdS|SdS( Ni(R](R\isInnerWindow.on_key_upiis- s| REi2(R_R]R^R\R`RaR&RRR$R*R,RbR>R%RcR RdReR?(R RfR]R\R=RgRhRi((sinner_window.pyt on_key_uposL             cCs ddlm}ddlm}|jdkr3|St|j|j|rqg}|jdkr|j dkr|j|_|j|_ n|j|j |jkrd}x8||j|j kr|j |j ||d7}qW|j |j |j|j |d7}|}t jyt j|j |j|j }xf|D]^}tjd|dkrGtjj|j |j|j |} |j | |d7}qGqGWWntk rnX|d} |d8}|j|j d} xQ| |jkr9|j | |kr"|j |j | n|d7}| d7} qW|j d}x|t|j kr|j ||kr|j |j |n|d7}qJWns|j|j |j krd}x1||jkr|j |j ||d7}qW|j d} xB| |j|j kr>|j |j | |d7}| d7} qW|j |j |j|j |d7}|}t jyt j|j |j|j }xf|D]^}tjd|dkrtjj|j |j|j |} |j | |d7}qqWWntk rnX|d} |j|j d} x| t|j kr|j | |krx|j |j | n| d7} |d7}q9Wnzd}x1||jkr|j |j ||d7}qW|j |j |j|j |d7}|}t jyt j|j |j|j }xf|D]^}tjd|dkr/tjj|j |j|j |} |j | |d7}q/q/WWntk rnX|d} |j d}xM|t|j kr |j ||kr|j |j |n|d7}qW|jj||_| |_ t|tkrxtt|D]^} | dkrld} n%| t|dkrd} nd } |jj|j| || qQWn7x4tt|D] } |jj|j|| qW|jjj|jjj|j|j|j y||ja Wn,t!k rc|j|j|j dnX|j"nt|j|j|r |j#dk rt$j%d |j#j&d d}|j'n|j|j |jj(}yt)|g}WnLt*k r?|j#dk r@t$j%d |j#j&d d}|j'dSnX|j+dksd|j+dkr|jdj,|j-|jdj,|j.|jd|a/|j#dk r |j#jj0j1dSq |j#dk r t$j%d |j#j&d d}|j'dSn|S(Ni(R\(R]iis[^a-z0-9A-Z/_\- \.]s- s- s| ttargettargss$>>>Looking for driver information...tstatuss)>>>Looking for driver information failed!terrortPKGtSVR4i(s$>>>Looking for driver information...sstatus(s)>>>Looking for driver information failed!serror(s)>>>Looking for driver information failed!serror(2R^R\R_R]R&RRR$R(R)R*tappendR%tdircacheR4tlistdirtretsearchtostpathtjointOSErrorR>R.t object_resetR+Rbt object_inserttmain_wint show_actionst do_updateR?RdReR R/t threadingtThreadtinformation_dsptstartt query_tupleRRt get_pkg_typetset_repotget_pkg_locationt get_pkg_nametinstallation_packaget status_linet clear_err(R RfR\R]t text_full_bakt index_starttdirectory_start_baktdirlisttdiritemt displaynametdirectory_end_baktindex_start_tempR=Rittttdev_datat package_candi((sinner_window.pyt on_key_enters^                                                                       cCsddlm}ddlm}ddlm}t}t||r]|jj }|j}n|j }|}t j t krd}d} d} |j djjdkrdj|j dj}n|j djjdkrdj|j dj} n|j djjdkr5dj|j dj} n|j|j|dkr|j djt||jdn| dkr|j djt| |jdn| dkr|j djt| |jdntt _ dSy[|j djjdksR|j djjdksR|j djjdkrRnWntk rg|SXtdk r|dk rtjd |jd d} | jnyttd t }Wqotk rt}qoXnt j!dtt"dk rtt"} t#j$j%| } t#j$j&| }|dk r^tjd |jd d} | jnt'j(dt)| |f\}}|dkrt }qoy0t*dd}|j+t||j,Wnt-k rnXt}nt j!d|j djjdk rdj|j dj} g|j d_t#j$j%| } t#j$j&| }|dk rtjd |jd d} | jnt'j(dt)| |f\}}|dkrt }qoy0t*dd}|j+t||j,Wnt-k rnXt}n`t j!dtt.dk r/t j!d|j djjdk r/tt.a.|j djj}|dk rtjd |jd d} | jnt'j(dt)|t.f\}}|dkrt }qoy0t*dd}|j+t||j,Wnt-k r%nXt}n@t j!d|j djjdk rot j!d|j djjdk ro|j djjj/a.|j djjj/}|dk rtjd |jd d} | jnt'j(dt)|t.f\}}|dkr"t }qoy0t*dd}|j+t||j,Wnt-k renXt}ndada"|j|t krtjd |jd d} | jn%tjd |jd d} | jtjd |j0dd}|jdS( Ni(R\(t InputWindow(R]RiiiRlRms>>>Install driver...Rnt/s\ws&%s/scripts/file_check.sh UNK "%s" "%s"s/tmp/ddu_err.logtas&%s/scripts/file_check.sh IPS "%s" "%s"s0>>>Install driver successfully! rescan device...tsuccesss(>>>Install driver fail! rescan device...Rotnames rescan device(s>>>Install driver...sstatus(s>>>Install driver...sstatus(s>>>Install driver...sstatus(s>>>Install driver...sstatus(s>>>Install driver...sstatus(s0>>>Install driver successfully! rescan device...ssuccess(s(>>>Install driver fail! rescan device...serror(1R^R\t input_windowRR_R]tFalseRtwinR/R t just_reshowtTrueR$ttextboxtgatherRyt text_bufft setup_layoutt look_throughRtstrR?ReRRRRRRRRRuRvRdRwRxtbasenametdirnametcommandstgetstatusoutputtABSPATHtopentwritetclosetIOErrort repo_nametstriptreshow(R RfR\RR]t install_oktwindow_pointertinner_window_pttext0ttext1ttext2Rt package_pathtmediatlocationRntoutputtlogfilet package_namettdev((sinner_window.pyt on_key_f2_s6                              "         $"                                 cCstjdttdS(Ns F4 comming:%s(R`tdebugRRd(R Rf((sinner_window.pyt on_key_f4"scCs|S(N((R Rf((sinner_window.pyt no_action&scCsddlm}t|jts&dSt|j|j|r |j|j|jj dd}|j|j|jj dd}d|d|}t j d|\}}|dkr|j dd}t j d |\}}n|j j |j jnyt|j} t|jdkr|jdjt|j|j| jt|j|j| ja|jd7_nWntk rg} t j d t\}}|dkr|j} x;| D]0} | j d } | j| d| dfqWnt| |_t|j} t|jdkr|jdjt|j|j| jt|j|j| ja|jd7_qnX|jddS( Ni(R]Riis/usr/bin/eject -l| grep "%s"iRs/usr/bin/eject -f %ss!%s/scripts/pkg_relate.sh list alls (R_R]RR&tintRR$R%R*tsplitRRR.R{t items_resetR>t repo_candiRRR-RtAttributeErrorRRIRrRR?(R RfR]tmedia1tmedia2t eject_nameRnRt eject_mediatrepo_lent repo_listt output_linesRStrepo_name_candi((sinner_window.pyt on_key_f5)sb            cCsM|jdk r+|j|jj|}n|jj||j}||S(s,Process keyboard input Keyboard input is handled in a "bottom-up" manner. If this window has an active object, the input is passed down to it. If the input isn't handled by the object, we try to handle it. If we can't handle it, we pass it back up the chain. N(R&RR$tprocesstkey_dicttgetR(R Rfthandler((sinner_window.pyR_scCsli|_|j|jtj<|j|jtj<|j|jtj<|j|jtj <|j |jtj InnerWindow.on_key_down KEY_UP -> InnerWindow.on_key_up N( RRjRtKEY_DOWNRktKEY_UPRtKEY_F5RtKEY_F2Rt KEY_ENTER(R ((sinner_window.pyR'ls  cCsCtjddtj|d|tjrtjddtt_tjj|r~tjdd|t dtj StjddnG|t krtjddtj st t_ t t_nt t_dS|tkrtjdd |tj}n;|tjks|tkr?tjdd |tj}n|tjkrZtj}n|tjkrutj}n|tjkrd d lm}d d lm}t||rtj}|St||rdaq?dSn`|tjkrd d lm}d dlm}d d lm}t||st||r?q?t||rr|jj j!|jj j"dS|j j!|j j"dSn|t t#dkr?d d lm}d dlm}d d lm}t||st||r t t_$tjSt||r?|jj j!|jj j"dSn|S(sTranslate keyboard input codes This function will translate keyboard input. It's primary job is understanding Esc-# sequences and turning them into F# key codes. It also converts 127 to KEY_BACKSPACE, since curses does not seem to properly understand it, and converts TAB and ENTER to KEY_DOWN (TAB, ENTER, and DOWN all move to the next field) isGot char input %ss (char code %d)sEnding esc-sequences(Valid esc-sequence, converting to KEY_FNt0s)Invalid esc-sequence, returning raw inputsBeginning esc-sequences)Translating char code %d to KEY_BACKSPACEs%Translating char code %d to KEY_ENTERi(R\(R]R(RtLN(%R`RaRtkeynameR tbegin_esc_sequenceRtasciitisdigitRtKEY_F0tKEY_ESCtuse_esc_sequenceRtupdate_footer_textRtKEY_BSt KEY_BACKSPACERRRtKEY_F3R^R\R_R]RRdtKEY_F4RRRR.R{RRR(R RfR\R]R((sinner_window.pyttranslate_inputzs|                   cCsC|jdk r#|j|jjS|jj}|j|SdS(sTInnerWindow.getch() searches downward to find the active object. Once found, the active object's window.getch() function is called. This function is required to ensure that curses.window.getch() is called from the active object. Curses will update the console differently based on which window calls getch()N(R&RR$tgetchR R(R Rf((sinner_window.pyRsN(#t__name__t __module__t__doc__RRRRRR RRRRR3R4R5R6R:R?RFRVR RZR[RjRkRRRRRRR'RR(((sinner_window.pyR 4sB   ?      + / /   6  M(R`R;Rt curses.asciiRRRsRuRwRRtDDU.ddu_errorsRtDDU.ddu_functionRRRRRRtKEY_TABRRdRR+RRRRXR (((sinner_window.pyts.