Skip to content

Commit

Permalink
wx GUI: Disable the native GTK "live" search on logs
Browse files Browse the repository at this point in the history
Addresses #351
  • Loading branch information
kynikos committed Sep 30, 2014
1 parent 2a0ef6c commit 4e51919
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 68 deletions.
70 changes: 53 additions & 17 deletions src/outspline/interfaces/wxgui/logs.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,37 @@ def reverse_selection(self):
self.select_log(newsel)


class DatabaseHistoryModel(wx.dataview.PyDataViewIndexListModel):
def __init__(self, data):
# Using a model is necessary to disable the native "live" search
# See bugs #349 and #351
super(DatabaseHistoryModel, self).__init__()
self.data = data

# The wxPython demo uses weak references for the item objects: see if
# it can be used also in this case (bug #348)
#self.objmapper.UseWeakRefs(True)

def GetValueByRow(self, row, col):
return self.data[row][col]

def GetColumnCount(self):
return 4

def GetCount(self):
return len(self.data)

'''def GetColumnType(self, col):
# It seems not needed to override this method, it's not done in the
# demos either
# Besides, returning "string" here would activate the "live" search
# feature that belongs to the native GTK widget used by DataViewCtrl
# See also bug #349
# https://groups.google.com/d/msg/wxpython-users/QvSesrnD38E/31l8f6AzIhAJ
# https://groups.google.com/d/msg/wxpython-users/4nsv7x1DE-s/ljQHl9RTnuEJ
return None'''


class DatabaseHistory(object):
def __init__(self, logspanel, parent, filename, bgcolor):
self.logspanel = logspanel
Expand All @@ -137,17 +168,25 @@ def __init__(self, logspanel, parent, filename, bgcolor):
statusflags = 0 if self.config('History').get_bool('debug') else \
wx.dataview.DATAVIEW_COL_HIDDEN

# The native "live" search is still enabled here, see bug #351
self.view = wx.dataview.DataViewListCtrl(parent,
self.view = wx.dataview.DataViewCtrl(parent,
style=wx.dataview.DV_SINGLE |
wx.dataview.DV_ROW_LINES | wx.dataview.DV_NO_HEADER)
# Note how AppendBitmapColumn requires a second argument, while
# AppendTextColumn doesn't

self.data = []
self.dvmodel = DatabaseHistoryModel(self.data)
self.view.AssociateModel(self.dvmodel)
# According to DataViewModel's documentation (as of September 2014)
# its reference count must be decreased explicitly to avoid memory
# leaks; the wxPython demo, however, doesn't do it, and if done here,
# the application crashes with a segfault when closing all databases
# See also bug #104
#self.dvmodel.DecRef()

self.view.AppendBitmapColumn('Icon', 0, width=wx.COL_WIDTH_AUTOSIZE)
self.view.AppendTextColumn('Status', width=wx.COL_WIDTH_AUTOSIZE,
self.view.AppendTextColumn('Status', 1, width=wx.COL_WIDTH_AUTOSIZE,
flags=statusflags)
self.view.AppendTextColumn('Timestamp', width=wx.COL_WIDTH_AUTOSIZE)
self.view.AppendTextColumn('Description')
self.view.AppendTextColumn('Timestamp', 2, width=wx.COL_WIDTH_AUTOSIZE)
self.view.AppendTextColumn('Description', 3)

self._make_icons(bgcolor)

Expand All @@ -161,8 +200,6 @@ def __init__(self, logspanel, parent, filename, bgcolor):
self.view.Bind(wx.dataview.EVT_DATAVIEW_ITEM_CONTEXT_MENU, popup_cmenu)
self.view.Bind(wx.dataview.EVT_DATAVIEW_SELECTION_CHANGED,
self._handle_selection)
self.view.Bind(wx.dataview.EVT_DATAVIEW_ITEM_START_EDITING,
self._handle_item_editing)

self.refresh()

Expand Down Expand Up @@ -235,21 +272,19 @@ def _store_context_menu_items(self, items):
def _handle_selection(self, event):
self.view.UnselectAll()

def _handle_item_editing(self, event):
event.Veto()

def refresh(self):
self.view.DeleteAllItems()

del self.data[:]
descriptions = core_api.get_history_descriptions(self.filename)

for row in descriptions:
tstamp = time_.strftime('%Y-%m-%d %H:%M', time_.localtime(
row['H_tstamp']))
item = self.view.AppendItem((self.icons[row['H_status']],
self.data.append((self.icons[row['H_status']],
"".join(("[", str(row['H_status']), "]")),
tstamp, row['H_description']))

self.dvmodel.Reset(len(self.data))

def select(self):
self.logspanel.select_log(self.tool_id)

Expand Down Expand Up @@ -279,8 +314,9 @@ def _popup(self, event):
self._update()
self.view.PopupMenu(self)

# Skipping the event lets right clicks behave correctly
event.Skip()
# Skipping the event would change the current selection after the
# click and only select the item under the cursor
#event.Skip()

def get_items_and_popup(self):
return (self.added_items, self._popup)
135 changes: 84 additions & 51 deletions src/outspline/plugins/wxalarmslog/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,28 +71,67 @@ def get_selected_log(self):
return (False, False)


class AlarmsLogModel(wx.dataview.PyDataViewIndexListModel):
def __init__(self, data):
# Using a model is necessary to disable the native "live" search
# See bugs #349 and #351
super(AlarmsLogModel, self).__init__()
self.data = data

# The wxPython demo uses weak references for the item objects: see if
# it can be used also in this case (bug #348)
#self.objmapper.UseWeakRefs(True)

def GetValueByRow(self, row, col):
return self.data[row][col]

def GetColumnCount(self):
return 3

def GetCount(self):
return len(self.data)

'''def GetColumnType(self, col):
# It seems not needed to override this method, it's not done in the
# demos either
# Besides, returning "string" here would activate the "live" search
# feature that belongs to the native GTK widget used by DataViewCtrl
# See also bug #349
# https://groups.google.com/d/msg/wxpython-users/QvSesrnD38E/31l8f6AzIhAJ
# https://groups.google.com/d/msg/wxpython-users/4nsv7x1DE-s/ljQHl9RTnuEJ
return None'''


class AlarmsLog(object):
def __init__(self, parent, filename, mainmenu):
self.filename = filename

# The native "live" search is still enabled here, see bug #351
self.view = wx.dataview.DataViewListCtrl(parent,
self.view = wx.dataview.DataViewCtrl(parent,
style=wx.dataview.DV_MULTIPLE |
wx.dataview.DV_ROW_LINES | wx.dataview.DV_NO_HEADER)

self.data = []
self.dvmodel = AlarmsLogModel(self.data)
self.view.AssociateModel(self.dvmodel)
# According to DataViewModel's documentation (as of September 2014)
# its reference count must be decreased explicitly to avoid memory
# leaks; the wxPython demo, however, doesn't do it, and if done here,
# the application crashes with a segfault when closing all databases
# See also bug #104
#self.dvmodel.DecRef()

# Temporary workaround for bug #279
# Note how AppendDateColumn requires a second argument, while
# AppendTextColumn doesn't
#self.view.AppendDateColumn('Timestamp', 0,
# width=wx.COL_WIDTH_AUTOSIZE, align=wx.ALIGN_CENTER_VERTICAL)
self.view.AppendTextColumn('Timestamp', width=wx.COL_WIDTH_AUTOSIZE)
self.view.AppendTextColumn('Action', width=wx.COL_WIDTH_AUTOSIZE)
self.view.AppendTextColumn('Item')
self.view.AppendTextColumn('Timestamp', 0, width=wx.COL_WIDTH_AUTOSIZE)
self.view.AppendTextColumn('Action', 1, width=wx.COL_WIDTH_AUTOSIZE)
self.view.AppendTextColumn('Item', 2)

self.reasons = {0: '[snoozed]',
1: '[dismissed]',
2: '[deleted]'}

cmenu = ContextMenu(mainmenu, self.view)
cmenu = ContextMenu(mainmenu, self)

self.tool_id, menu_items, popup_cmenu = wxgui_api.add_log(filename,
self.view, "Alarms",
Expand All @@ -102,37 +141,41 @@ def __init__(self, parent, filename, mainmenu):

self.view.Bind(wx.dataview.EVT_DATAVIEW_ITEM_CONTEXT_MENU,
popup_cmenu)

self.view.Bind(wx.dataview.EVT_DATAVIEW_ITEM_START_EDITING,
self._handle_item_editing)
organism_alarms_api.bind_to_alarm_off(self._handle_alarm_off)
wxgui_api.bind_to_close_database(self._handle_close_database)

self._refresh()

def _handle_item_editing(self, event):
event.Veto()

def _handle_alarm_off(self, kwargs):
self._refresh()

def _handle_close_database(self, kwargs):
organism_alarms_api.bind_to_alarm_off(self._handle_alarm_off, False)

def get_view(self):
return self.view
def is_shown(self):
return self.view.IsShown()

def has_selection(self):
return self.view.HasSelection()

def get_selections(self):
return self.view.GetSelections()

def get_item_id(self, item):
return self.data[self.dvmodel.GetRow(item)][3]

def get_tool_id(self):
return self.tool_id

def _refresh(self):
self.view.DeleteAllItems()

del self.data[:]
cursor = organism_alarms_api.get_alarms_log(self.filename)

for row in cursor:
self.view.AppendItem(self._format_values(row),
data=row['AOL_item'])
# 4 values are stored per row, but only the first 3 must be shown
self.data.append(self._format_values(row))

self.dvmodel.Reset(len(self.data))

def _format_values(self, row):
# Temporary workaround for bug #279
Expand All @@ -141,7 +184,8 @@ def _format_values(self, row):
row['AOL_tstamp']))
reason = self.reasons[row['AOL_reason']]
text = row['AOL_text']
return (tstamp, reason, text)
id_ = row['AOL_item']
return (tstamp, reason, text, id_)

def set_log_limit(self, data, value):
if core_api.block_databases():
Expand Down Expand Up @@ -191,14 +235,8 @@ def _update_items(self, kwargs):

log, filename = self.plugin.get_selected_log()

if log:
view = log.get_view()

if view.IsShown():
sel = view.GetSelectedItemsCount()

if sel > 0:
self.find.Enable()
if log and log.is_shown() and log.has_selection():
self.find.Enable()

def _disable_items(self, kwargs):
self.alarms.Enable(False)
Expand All @@ -218,29 +256,26 @@ def _select(self, event):
def _find_in_tree(self, event):
log, filename = self.plugin.get_selected_log()

if log:
view = log.get_view()

if view.IsShown():
sel = view.GetSelections()
if log and log.is_shown():
sel = log.get_selections()

if len(sel) > 0:
wxgui_api.unselect_all_items(filename)
if len(sel) > 0:
wxgui_api.unselect_all_items(filename)

# Do not loop directly on view.GetSelections(), e.g.
# for s in view.GetSelections():
# because it doesn't work as expected!
for item in sel:
id_ = view.GetItemData(item)
# Do not loop directly on view.GetSelections(), e.g.
# for s in view.GetSelections():
# because it doesn't work as expected!
for item in sel:
id_ = log.get_item_id(item)

# The logged item may not exist anymore
if core_api.is_item(filename, id_):
wxgui_api.add_item_to_selection(filename, id_)
# The logged item may not exist anymore
if core_api.is_item(filename, id_):
wxgui_api.add_item_to_selection(filename, id_)


class ContextMenu(object):
def __init__(self, mainmenu, logview):
self.logview = logview
def __init__(self, mainmenu, log):
self.log = log

self.find_paramaters = (mainmenu.ID_FIND, "&Find in database",
wx.ArtProvider.GetBitmap('@find', wx.ART_MENU))
Expand All @@ -252,12 +287,10 @@ def store_items(self, items):
self.find = items[0]

def update(self):
self.find.Enable(False)

sel = self.logview.GetSelectedItemsCount()

if sel > 0:
if self.log.has_selection():
self.find.Enable()
else:
self.find.Enable(False)


def main():
Expand Down

0 comments on commit 4e51919

Please sign in to comment.