2424from PyQt5 .QtCore import (Qt , pyqtSignal , QAbstractItemModel , QModelIndex , pyqtSlot )
2525from PyQt5 .QtWidgets import QTextEdit , QTabWidget , QWidget , QVBoxLayout , \
2626 QMenu , \
27- QAbstractItemView , QTableView
27+ QAbstractItemView , QTableView , QAction , QInputDialog , QMessageBox
2828
2929import pre_workbench .app
3030
31- from pre_workbench .configs import SettingsField
31+ from pre_workbench .configs import SettingsField , getIcon
3232from pre_workbench .guihelper import getMonospaceFont , setClipboardText , getClipboardText , APP
3333from pre_workbench .structinfo .expr import Expression
3434from pre_workbench .controls .genericwidgets import showSettingsDlg , showListSelectDialog
@@ -181,6 +181,7 @@ class PacketListWidget(QWidget):
181181
182182 def __init__ (self ):
183183 super ().__init__ ()
184+ self .lastFindExpression = ""
184185 self .initUI ()
185186
186187 def showData (self , data : List [ByteBuffer ]):
@@ -216,6 +217,25 @@ def initUI(self):
216217 self .packetlist .selectionModel ().currentChanged .connect (self .onPacketlistCurrentChanged )
217218 #tabs.addTab(self.packetlist, "Raw Frames")
218219 layout .addWidget (self .packetlist )
220+ self .actions = [
221+ QAction (getIcon ("magnifier-flag.png" ), "Find By Expression" , triggered = self ._findByExpression ),
222+ QAction (getIcon ("flag.png" ), "Mark/Unmark Selected Packets" , triggered = self ._markUnmarkSelection ),
223+ QAction (getIcon ("table-reset.png" ), "Reset Header" , triggered = lambda : self .packetlistmodel .autoCols ()),
224+ QAction (getIcon ("table-insert-column-tag.png" ), "Add Metadata Column" , triggered = lambda : self ._quickAddDialog ("Quick Add Metadata Column" , self ._getQuickAddMetadataElements (), None )),
225+ QAction (getIcon ("table-insert-column-bookmark.png" ), "Add Field Column" , triggered = lambda : self ._quickAddDialog ("Quick Add Field Column" , self ._getQuickAddFieldElements (), None )),
226+ ]
227+
228+ def _findByExpression (self ):
229+ expr_str = QInputDialog .getText (self , "Find By Expression" , "Please enter expression. All rows for which the expression is true will be marked, all others unmarked." , text = self .lastFindExpression )[0 ]
230+ if not expr_str : return
231+ self .lastFindExpression = expr_str
232+ expr = Expression (expr_str = expr_str )
233+ matches = 0
234+ for rowIndex , buf in enumerate (self .packetlistmodel .listObject .buffers ):
235+ match = buf .metadata ['marked' ] = bool (expr .evaluate_bbuf (buf ))
236+ if match : matches += 1
237+ self .packetlistmodel .headerDataChanged .emit (Qt .Vertical , rowIndex , rowIndex )
238+ QMessageBox .information (self , "Find By Expression" , f"Of { len (self .packetlistmodel .listObject .buffers )} buffers, { matches } matched the expression " + expr .serialize ())
219239
220240 def _rowHeaderClicked (self , rowIndex : int ):
221241 self .packetlistmodel .markPacket (rowIndex )
@@ -225,6 +245,7 @@ def setContents(self, lstObj: Optional[ByteBufferList]):
225245 logging .debug ("PacketListWidget::setContents %r %d" , lstObj , len (lstObj ))
226246 self .setWindowTitle (str (lstObj ))
227247 self .packetlistmodel .setList (self .listObject )
248+ self .meta_updated .emit ("actions" , self .actions )
228249
229250 def onPacketlistSelectionChanged (self , selected , deselected ):
230251 buffers = list ()
@@ -243,13 +264,16 @@ def onPacketlistContextMenu(self, point):
243264 ctx = QMenu ("Context menu" , self .packetlist )
244265 if index .isValid ():
245266 ctx .addAction ("Item Details" , lambda : self .showData (self .getSelectedBuffers ()))
246- ctx .addAction ("Mark/Unmark Packet" , lambda : [ self .packetlistmodel . markPacket ( index . row ()) for index in self . packetlist . selectionModel (). selectedRows ()] )
267+ ctx .addAction ("Mark/Unmark Packet" , self ._markUnmarkSelection )
247268 self ._buildRunMacroOnBufferSubmenu (ctx , "Run Macro On" + (" Selected Buffers" if len (self .packetlist .selectionModel ().selectedRows ()) > 1 else " Buffer" ))
248269 ctx .addSeparator ()
249270 ctx .addAction ("Select All" , lambda : self .packetlist .selectAll ())
250271
251272 ctx .exec (self .packetlist .viewport ().mapToGlobal (point ))
252273
274+ def _markUnmarkSelection (self ):
275+ [self .packetlistmodel .markPacket (index .row ()) for index in self .packetlist .selectionModel ().selectedRows ()]
276+
253277 def _buildRunMacroOnBufferSubmenu (self , ctx , title ):
254278 menu = ctx .addMenu (title )
255279 for container_id , container , macroName in APP ().find_macros_by_input_types (["BYTE_BUFFER" , "BYTE_BUFFER_LIST" ]):
@@ -266,17 +290,28 @@ def _runMacroOnSelectedBuffers(self, container, macroname):
266290 lst .add (self .listObject .buffers [index .row ()])
267291 macro .execute (lst )
268292
293+ def _quickAddDialog (self , title : str , elements : List [Tuple [str , str ]], addIdx : int ):
294+ def on_ok (keys ):
295+ for key in keys :
296+ self .packetlistmodel .addColumn (ColumnInfo (key , key ), addIdx )
297+ showListSelectDialog (elements , None , title , self , on_ok , multiselect = True )
298+
269299 def _generateQuickAddMenu (self , ctx : QMenu , title : str , elements : List [Tuple [str , str ]], addIdx : int ):
270300 if len (elements ) > 20 :
271- def on_ok (keys ):
272- for key in keys :
273- self .packetlistmodel .addColumn (ColumnInfo (key , key ), addIdx )
274- ctx .addAction (title + " ..." , lambda : showListSelectDialog (elements , None , title , self , on_ok , multiselect = True ))
301+ ctx .addAction (title + " ..." , lambda : self ._quickAddDialog (title , elements , addIdx ))
275302 else :
276303 quick = ctx .addMenu (title )
277304 for key , text in elements :
278305 quick .addAction (text , lambda key = key , text = text : self .packetlistmodel .addColumn (ColumnInfo (key , text ), addIdx ))
279306
307+ def _getQuickAddMetadataElements (self ):
308+ return [("${\" " + key + "\" }" , "$" + key ) for key in
309+ sorted (self .listObject .getAllKeys (metadataKeys = True , fieldKeys = False ))]
310+
311+ def _getQuickAddFieldElements (self ):
312+ return [("fields[\" " + key + "\" ]" , key ) for key in
313+ sorted (self .listObject .getAllKeys (metadataKeys = False , fieldKeys = True ))]
314+
280315 def onHeaderContextMenu (self , point ):
281316 index = self .packetlist .horizontalHeader ().logicalIndexAt (point )
282317
@@ -289,13 +324,9 @@ def onHeaderContextMenu(self, point):
289324 addIdx = None if index == - 1 else index
290325 ctx .addAction ("Add Column ..." , lambda : self .onAddColumn (addIdx ))
291326
292- elements = [("${\" " + key + "\" }" , "$" + key ) for key in
293- sorted (self .listObject .getAllKeys (metadataKeys = True , fieldKeys = False ))]
294- self ._generateQuickAddMenu (ctx , "Quick Add Metadata Column" , elements , addIdx )
327+ self ._generateQuickAddMenu (ctx , "Quick Add Metadata Column" , self ._getQuickAddMetadataElements (), addIdx )
295328
296- elements = [("fields[\" " + key + "\" ]" , key ) for key in
297- sorted (self .listObject .getAllKeys (metadataKeys = False , fieldKeys = True ))]
298- self ._generateQuickAddMenu (ctx , "Quick Add Field Column" , elements , addIdx )
329+ self ._generateQuickAddMenu (ctx , "Quick Add Field Column" , self ._getQuickAddFieldElements (), addIdx )
299330
300331 ctx .addSeparator ()
301332 magic = "!!pre_workbench/packetListHeaderState\n "
0 commit comments