3i-7dZddlZddlmZmZmZmZmZmZm Z m Z m Z m Z m Z ddlmZmZddlmZmZddlmZddlmZmZmZddlmZej8eZGd d eZy) z Snapshot Tab - Portfolio Overview. Displays current holdings with P&L, weights, and current prices. Includes Update Prices and Add Holding functionality. N) QWidget QVBoxLayout QHBoxLayout QPushButton QTableWidgetQTableWidgetItemQLabel QHeaderView QMessageBoxQProgressDialogQMenu)QtpyqtSlot)QColorQBrush)PriceFetcherThread)format_currencyformat_percentage color_for_pnl)AddHoldingDialogceZdZdZfdZdZdZdZdZddZ dZ e e e d Z e ed Ze ed Zd Zd ZdZxZS) SnapshotTabz+Portfolio snapshot tab with holdings table.c~t|||_d|_|j |j y)za Initialize snapshot tab. Args: parent: MainWindow instance N)super__init__parent price_threadinit_ui load_data)selfr __class__s B/mnt/ssd/data/python-lab/portfolio-manager/src/gui/snapshot_tab.pyrzSnapshotTab.__init__s2     cF t|}t}td|_|jj dtd|_|j j dtd|_|j j dtd|_|jj d|j|j|j|j |j|j|j |j|j|j|t}td|_ |jjj|jtd|_|j jj|j"|j|j|j|j |j|j|t%|_|j&j)d |j&j+gd |j&j-d |j&j/t$j0j2|j&j5t$j6j8|j&j;d |j&j=}|j?d t@jBjD|j?d t@jBjD|j?dt@jBjD|j?dt@jBjD|j?dt@jBjD|j?dt@jBjF|j?dt@jBjD|j?dt@jBjD|j?dt@jBjD|j&jItJjLjN|j&jPj|jR|j|j&y)zInitialize user interface.uTotal Value: €0.00z#font-size: 16px; font-weight: bold;uP&L: €0.00 (0.0%)uInvested: €0.00zfont-size: 14px;uCash: €0.00 (0.0%)u🔄 Update Pricesz + Add Holding ) TickerTypeQtyu Avg Price €uCurrent Price €uCurrent Value €uP&L €zP&L %zWeight %TrN)*rrr lbl_total_value setStyleSheetlbl_pnl lbl_investedlbl_cash addWidget addStretch addLayoutrbtn_update_pricesclickedconnect update_pricesbtn_add_holding add_holdingrtablesetColumnCountsetHorizontalHeaderLabelssetAlternatingRowColorssetSelectionBehaviorSelectionBehavior SelectRowssetSelectionMode SelectionModeSingleSelectionsetSortingEnabledhorizontalHeadersetSectionResizeModer ResizeModeResizeToContentsStretchsetContextMenuPolicyrContextMenuPolicyCustomContextMenucustomContextMenuRequestedshow_context_menu)r layoutsummary_layout btn_layoutheaders r"rzSnapshotTab.init_ui(sT"%%&<= **+PQ34  ""#HI"#67 ''(:;56  ##$67  !5!56  .!!#  !2!23  /(!] !,-A!B &&..t/A/AB*?; $$,,T-=-=>T334T112$"^  !!!$ ,,.   **40 '' (F(F(Q(QR ##L$>$>$N$NO $$T*,,.##A{'='='N'NO##A{'='='N'NO##A{'='='N'NO##A{'='='N'NO##A{'='='N'NO##A{'='='E'EF##A{'='='N'NO##A{'='='N'NO##A{'='='N'NO ''(<(<(N(NO --55d6L6LM$r#c tjd |jjj |j |j tjdy#t$rG}tjd|dtj|ddt|Yd}~yd}~wwxYw) z Load and display portfolio data.zLoading snapshot data...z!Snapshot data loaded successfullyzError loading snapshot data: Texc_infoErrorzFailed to load snapshot data: N) loggerdebugr portfolio load_holdingsupdate_summary update_tableinfo Exceptionerrorr criticalstr)r es r"rzSnapshotTab.load_datass /0  KK ! ! / / 1    !     KK; <  LL8s*CEH  % %b&6&6&A&ABDTDTDaDa&a b JJ  sAx 0.1Ec0JLN  + +B,<,<,G,G"JZJZJgJg,g h JJ  sA~ 6$O4M"2mC5H"J"23"7  , ,R-=-=-H-H2K[K[KhKh-h i JJ  sA 7*/'/:R*STJ  ' '(8(8(C(CbFVFVFcFc(c d JJ  sAz 2!.J.z/JKO  , ,R-=-=-H-H2K[K[KhKh-h i  ) )& j8Q1R*S T JJ  sA 7"-0K/0A+0NO   - -b.>.>.I.IBL\L\LiLi.i j  * *6&{9S2T+U V JJ  sA'7 8+gl.CC-H+JKK  ( ()9)9)D)DrGWGWGdGd)d e JJ  sA{ 3a0 4d $$T*r#c|jjj}|s|stj|ddyt j dt|d|jjdtddd t|||_ |jjtjj|jj!d |jj"j%|j&t)|jj*|| |_|j,j.j%|j0|j,j2j%|j4|j,j6j%|j8|j,j;y) z Update prices from yfinance. Args: auto_refresh: True if triggered by auto-refresh timer z No Tickersz!No holdings to update prices for.NzUpdating prices for z tickers...FzUpdating prices...Cancelr) force_refresh)r db_managerget_all_tickersr informationr\rbrr9 setEnabledr progress_dialogsetWindowModalityrWindowModality WindowModalsetMinimumDurationcanceledr;cancel_price_updater price_fetcherrprogresson_price_progressfinishedon_prices_updatedrdon_price_errorstart)r auto_refreshtickerss r"r<zSnapshotTab.update_pricessy++((88:''l<_`  *3w<. DE ))%0 /  L    ..r/@/@/L/LM //2 %%--d.F.FG/ KK % % **  ""**4+A+AB ""**4+A+AB ''(;(;< !r#c||jr0|jjtjdyy)zCancel price update operation.zPrice update cancelled by userN)rstopr\rb)r s r"rzSnapshotTab.cancel_price_update s/       " " $ KK8 9 r#ct|dr=|jj||jjd|d|yy)z Update progress dialog. Args: current: Current ticker index total: Total tickers rzUpdating prices... /N)hasattrrsetValue setLabelText)r currenttotals r"rzSnapshotTab.on_price_progresssJ 4* +  ) )' 2  - -0CG9AeW.U V ,r#ctjdt|dt|dr|jj |j jj||j|j|j jjdt|dd|jjdy) zr Handle price update completion. Args: prices: Dictionary of ticker -> price zPrice update completed: z prices fetchedrzPrices updated: z tickersiTN)r\rbrrrcloserr^r<r`ra status_bar showMessager9r)r pricess r"rzSnapshotTab.on_prices_updateds  .s6{m?KL 4* +  & & ( ++F3   **s6{m8 4  ))$/r#ctjd|t|dr|jj t j |d||jjdy)z_ Handle price fetch error. Args: error_msg: Error message zPrice fetch error: rzPrice Update ErrorTN) r\rdrrrr rer9r)r error_msgs r"rzSnapshotTab.on_price_error:sb  *9+67 4* +  & & ( T#7C ))$/r#ct|j}|jr[|j|jjj|jj j ddyy)zOpen Add Holding dialog.zHolding added successfully N)rrexecr analytics_tabrr)r dialogs r"r>zSnapshotTab.add_holdingNs]!$++. ;;= NN  KK % % / / 1 KK " " . ./KT R r#cjjj}|sy|dj}jj |dj t }|jd}|jjfd|jjjj|y)z] Show context menu for table. Args: pos: Click position NrzDelete Holdingc&jS)N)delete_holding)r rzsr"z/SnapshotTab.show_context_menu..os0C0CF0Kr#) r?selectionModel selectedRowsritemtextr addAction triggeredr;rviewport mapToGlobal)r pos selected_rowsrmenu delete_actionrzs` @r"rSzSnapshotTab.show_context_menu\s 113@@B  A""$a(--/T{'78 ''(KL $**%%'33C89r#c ttj|dd|dtjjtjjz}|tjjk(ry |j j j||j|j jjd|ddtjd|y y #t$rG}tjd|d tj|d d t!|Yd }~y d }~wwxYw)zW Delete a holding. Args: ticker: Ticker to delete zConfirm DeletezDelete holding z=? This will remove the holding but keep transaction history.zHolding z deletedrzHolding deleted: zError deleting holding: TrYr[zFailed to delete holding: N)r questionStandardButtonYesNorrrrrrr\rbrcrdrerf)r rzreplyrgs r"rzSnapshotTab.delete_holdingss$$  fX%d e  & & * *[-G-G-J-J J   K..22 2  &&55f=  &&22XfXX3NPTU /x89 3  7s;d K$$1#a&: s.A7C'' D70=D22D7)F)__name__ __module__ __qualname____doc__rrrr`rar<rrintrdictrrfrr>rSr __classcell__)r!s@r"rrs5 I%V0R29+v("T: c3 W Wd^00:c]00& S:.r#r) rloggingPyQt6.QtWidgetsrrrrrrr r r r r PyQt6.QtCorerr PyQt6.QtGuirrsrc.data.price_fetcherrsrc.utils.formattersrrrsrc.gui.dialogsr getLoggerrr\rr#r"rsW &&5RR,   8 $w'wr#