1- from PySide6 .QtWidgets import QDockWidget , QVBoxLayout , QTableView , QWidget ,\
2- QCompleter , QLineEdit , QStyledItemDelegate , QComboBox
3- from PySide6 .QtCore import Qt
4- from PySide6 .QtGui import QGuiApplication
1+ from PySide6 .QtWidgets import (QDockWidget , QHeaderView , QTableView ,
2+ QCompleter , QLineEdit , QStyledItemDelegate ,
3+ QComboBox )
4+ from PySide6 .QtCore import Qt , QPropertyAnimation , QRect
5+ from PySide6 .QtGui import QGuiApplication , QColor
56
67from ..utils import get_selected , get_selected_rectangles
78from ..C import INDEX
@@ -15,13 +16,9 @@ def __init__(self, title, parent=None):
1516 self .setAllowedAreas (
1617 Qt .AllDockWidgetAreas
1718 )
18- widget = QWidget ()
19- self .setWidget (widget )
20- layout = QVBoxLayout (widget )
21-
2219 # Create the QTableView for the table content
23- self .table_view = QTableView ()
24- layout . addWidget (self .table_view )
20+ self .table_view = CustomTableView ()
21+ self . setWidget (self .table_view )
2522 # Dictionary to store column-specific completers
2623 self .completers = {}
2724 self .table_view .setAlternatingRowColors (True )
@@ -48,7 +45,8 @@ def paste_from_clipboard(self):
4845 model = self .table_view .model ()
4946 row_start , col_start = start_index .row (), start_index .column ()
5047 # identify which invalid cells are being pasted into
51- pasted_data = [line .split ("\t " ) for line in text .split ("\n " ) if line .strip ()]
48+ pasted_data = [line .split ("\t " ) for line in text .split ("\n " ) if
49+ line .strip ()]
5250 num_rows = len (pasted_data )
5351 num_cols = max ([len (line ) for line in pasted_data ])
5452 overridden_cells = {
@@ -85,6 +83,7 @@ def createEditor(self, parent, option, index):
8583class SingleSuggestionDelegate (QStyledItemDelegate ):
8684 """Suggest a single option based the current row and the value in
8785 `column_name`."""
86+
8887 def __init__ (self , model , suggestions_column , afix = None , parent = None ):
8988 super ().__init__ (parent )
9089 self .model = model # The main model to retrieve data from
@@ -110,6 +109,7 @@ def createEditor(self, parent, option, index):
110109
111110 return editor
112111
112+
113113class ColumnSuggestionDelegate (QStyledItemDelegate ):
114114 """Suggest options based on all unique values in the specified column."""
115115 def __init__ (
@@ -171,3 +171,95 @@ def createEditor(self, parent, option, index):
171171 editor .setCompleter (completer )
172172
173173 return editor
174+
175+
176+ class CustomTableView (QTableView ):
177+ """Custom Table View to Handle Copy Paste events, resizing policies etc."""
178+
179+ def __init__ (self , parent = None ):
180+ super ().__init__ (parent )
181+ self .setSizeAdjustPolicy (QTableView .AdjustToContents )
182+ self .horizontalHeader ().setSectionResizeMode (
183+ QHeaderView .ResizeToContents
184+ )
185+ self .horizontalHeader ().setStretchLastSection (
186+ False
187+ ) # Prevent last column from stretching
188+
189+ self .horizontalHeader ().sectionDoubleClicked .connect (
190+ self .autofit_column
191+ )
192+
193+ def setModel (self , model ):
194+ """Ensures selection model exists before connecting signals"""
195+ super ().setModel (model )
196+ if self .selectionModel ():
197+ self .selectionModel ().currentColumnChanged .connect (self .highlight_active_column )
198+
199+ def reset_column_sizes (self ):
200+ """Resets column sizes with refinements"""
201+ header = self .horizontalHeader ()
202+ total_width = self .viewport ().width ()
203+ max_width = total_width // 4 # 1/4th of total table width
204+
205+ header .setSectionResizeMode (QHeaderView .ResizeToContents )
206+ self .resizeColumnsToContents ()
207+ header .setSectionResizeMode (QHeaderView .Interactive )
208+
209+ # Enforce max width but allow expanding into empty neighbors
210+ for col in range (self .model ().columnCount ()):
211+ optimal_width = self .columnWidth (col )
212+ if optimal_width > max_width :
213+ self .setColumnWidth (col , max_width )
214+ else :
215+ self .setColumnWidth (col , optimal_width )
216+
217+ # self.adjust_for_empty_neighbors()
218+ self .collapse_empty_columns ()
219+ self .updateGeometry ()
220+
221+ def adjust_for_empty_neighbors (self ):
222+ """Expands column if adjacent columns are empty"""
223+ model = self .model ()
224+ for col in range (model .columnCount ()):
225+ if self .columnWidth (col ) == self .viewport ().width () // 4 : # If maxed out
226+ next_col = col + 1
227+ if next_col < model .columnCount ():
228+ if all (model .index (row , next_col ).data () in [None , "" ] for row in range (model .rowCount ())):
229+ new_width = self .columnWidth (
230+ col ) + self .columnWidth (next_col )
231+ self .setColumnWidth (col , new_width )
232+ self .setColumnWidth (next_col , 0 ) # Hide empty column
233+
234+ def collapse_empty_columns (self ):
235+ """Collapses columns that only contain empty values"""
236+ model = self .model ()
237+ for col in range (model .columnCount ()):
238+ if all (model .index (row , col ).data () in [None , "" , " " ] for row in
239+ range (model .rowCount ())):
240+ self .setColumnWidth (col , 10 ) # Minimal width
241+
242+ def autofit_column (self , col ):
243+ """Expands column width on double-click"""
244+ self .horizontalHeader ().setSectionResizeMode (col ,
245+ QHeaderView .ResizeToContents )
246+ self .resizeColumnToContents (col )
247+ self .horizontalHeader ().setSectionResizeMode (col ,
248+ QHeaderView .Interactive )
249+
250+ def highlight_active_column (self , index ):
251+ """Highlights the active column"""
252+ for row in range (self .model ().rowCount ()):
253+ self .model ().setData (self .model ().index (row , index .column ()),
254+ QColor ("#cce6ff" ), Qt .BackgroundRole )
255+
256+ def animate_column_resize (self , col , new_width ):
257+ """Smoothly animates column resizing"""
258+ anim = QPropertyAnimation (self , b"geometry" )
259+ anim .setDuration (200 )
260+ anim .setStartValue (QRect (self .columnViewportPosition (col ), 0 ,
261+ self .columnWidth (col ), self .height ()))
262+ anim .setEndValue (
263+ QRect (self .columnViewportPosition (col ), 0 , new_width ,
264+ self .height ()))
265+ anim .start ()
0 commit comments