Hi list,
I'm trying to build a working UltimateListCtrl using the demo as a base,
that seeks its data from a database and cache it.
When I launch it I've got a white window and only the columns headers text
are visible - and it throw a bunch of internal errors.
I traced both the example and my test (w/ eric) and found that it fails while
calling the "sizer.Layout()" function (see @ the end of code).
What I understand is the widget can't calculate its height, but why?
I think I'm close to the solution but I miss(understand?) something in the
Virtual chain that stuck me completely.
Here are the command line errors and code (errors are "complete" as I just
launched and immediately closed the window; but if I hover the widget, it
continues to throw such error lines):
========================================= ERRORS
$ python UltimateVirtualDemo_DB_2011-11-22_01_clean.py
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 12138, in OnSize
self._mainWin.RecalculatePositions()
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 9533, in RecalculatePositions
entireHeight = count*lineHeight + LINE_SPACING
TypeError: can only concatenate tuple (not "int") to tuple
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 12138, in OnSize
self._mainWin.RecalculatePositions()
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 9533, in RecalculatePositions
entireHeight = count*lineHeight + LINE_SPACING
TypeError: can only concatenate tuple (not "int") to tuple
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 12138, in OnSize
self._mainWin.RecalculatePositions()
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 9533, in RecalculatePositions
entireHeight = count*lineHeight + LINE_SPACING
TypeError: can only concatenate tuple (not "int") to tuple
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 12138, in OnSize
self._mainWin.RecalculatePositions()
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 9533, in RecalculatePositions
entireHeight = count*lineHeight + LINE_SPACING
TypeError: can only concatenate tuple (not "int") to tuple
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 12138, in OnSize
self._mainWin.RecalculatePositions()
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 9533, in RecalculatePositions
entireHeight = count*lineHeight + LINE_SPACING
TypeError: can only concatenate tuple (not "int") to tuple
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 7002, in OnPaint
self.RecalculatePositions(False)
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 9533, in RecalculatePositions
entireHeight = count*lineHeight + LINE_SPACING
TypeError: can only concatenate tuple (not "int") to tuple
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 12177, in OnInternalIdle
self._mainWin.RecalculatePositions()
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 9533, in RecalculatePositions
entireHeight = count*lineHeight + LINE_SPACING
TypeError: can only concatenate tuple (not "int") to tuple
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 12177, in OnInternalIdle
self._mainWin.RecalculatePositions()
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 9533, in RecalculatePositions
entireHeight = count*lineHeight + LINE_SPACING
TypeError: can only concatenate tuple (not "int") to tuple
========================================= /ERRORS
========================================= CODE
# -*- coding: utf-8 -*-
import wx
import images
import random
import os, sys
import psycopg2
try:
dirName = os.path.dirname(os.path.abspath(__file__))
except:
dirName = os.path.dirname(os.path.abspath(sys.argv[0]))
sys.path.append(os.path.split(dirName)[0])
from wx.lib.agw import ultimatelistctrl as ULC
#############################################################
# Size of a DB chunk (Nb of rows read in one SELECT)
DB_CHUNK_SIZE = 100L
# What range of rows is cached
DB_OFFSET = 1L
DB_LIMIT = 0L
DB_LIMIT = DB_LIMIT + DB_CHUNK_SIZE
#############################################################
class TestUltimateListCtrl(ULC.UltimateListCtrl):
def __init__(self, parent, DBcur=None, DBtab=None, DBcol=None, DBcolName=None):
ULC.UltimateListCtrl.__init__(self, parent, -1, agwStyle=wx.LC_REPORT
|wx.LC_VIRTUAL|wx.LC_HRULES|wx.LC_VRULES
|ULC.ULC_SHOW_TOOLTIPS)
if DBcur == None or DBtab == None or DBcol == None or DBcolName == None:
raise "Fn TestUltimateListCtrl - Bad call: DBcur, DBtab, DBcol |& DBcolName isn't set"
# Make parms ours
self.DBcur = DBcur
self.DBtab = DBtab
self.DBcol = DBcol
self.DBcolName = DBcolName
# Create data cache list (dict)
self.dataCache = None
# Create cache list (empty)
#self.listCache = ()
# Export a string from columns list and extract each list column name
self.DBcolListStr = ''
#for i in len(self.DBcol):
for i in range(len(DBcol)):
self.DBcolListStr += self.DBcol[i] + ","
self.InsertColumn(i, self.DBcolName[i])
# Strip last ','
self.DBcolListStr = self.DBcolListStr.rstrip(",")
self.SetColumnWidth(0, 100)
self.SetColumnWidth(1, 100)
self.SetColumnWidth(2, 100)
self.SetColumnToolTip(0,"First Column Tooltip!")
self.SetColumnToolTip(1,"Second Column Tooltip!")
self.SetColumnToolTip(2,"Third Column Tooltip!")
# Set last column to autosize
self.SetColumnWidth((len(DBcol)-1), ULC.ULC_AUTOSIZE_FILL)
# Set color of displayed lines
self.linColOdd = ULC.UltimateListItemAttr()
self.linColOdd.SetBackgroundColour(wx.NamedColour("light cyan"))
self.linColEve = ULC.UltimateListItemAttr()
self.linColEve.SetBackgroundColour(wx.NamedColour("light yellow"))
# Bind events to their methods
self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated)
self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.OnItemDeselected)
#
self.Bind(wx.EVT_LIST_CACHE_HINT, self.OnCacheHint)
# Now init global VARs & Virtual List
self.initData()
# Call: When click-L a line
def OnItemSelected(self, event):
self.currentItem = event.m_itemIndex
#print("OnItemSelected: %s, %s, %s, %s\n" % (self.currentItem,
# self.GetItemText(self.currentItem),
# self.getColumnText(self.currentItem, 1),
# self.getColumnText(self.currentItem, 2)))
# Call: When double-clicking on a line
def OnItemActivated(self, event):
self.currentItem = event.m_itemIndex
#print( "OnItemActivated: %s\n" % (self.GetItemText(self.currentItem)) )
# Position selected at the center (V) of the list
self.ScrollToItem(self.currentItem)
# Call: Seems to be only used by 'OnItemSelected(self, event)' log print
#def getColumnText(self, index, col):
# item = self.GetItem(index, col)
# return item.GetText()
def OnItemDeselected(self, event):
#self.log.write("OnItemDeselected: %s\n" % evt.m_itemIndex)
pass # MANDATORY: This Fn must exist
#---------------------------------------------------
# These methods are callbacks for implementing the
# "virtualness" of the list... Normally you would
# determine the text, attributes and/or image based
# on values from some external data source, but for
# this demo we'll just calculate them
# Call: Each time a cell (line/col) must be refreshed
def OnGetItemText(self, item, col):
#print "OnGetItemText: Item %d, column %d" % (item, col)
#return "Item %d, column %d" % (item, col)
return self.dataCache[item][col]
# Call: When staying too long on a line|col => Display a ToolTip (bof)
def OnGetItemToolTip(self, item, col):
if item == 0:
return "Tooltip: Item %d, column %d" % (item, col)
return None
# Colorise the 1st 3 cols of the 1st line (R, V & B)
#def OnGetItemTextColour(self, item, col):
# if item == 0 and col == 0:
# return wx.Colour(255,0,0)
# elif item == 0 and col == 1:
# return wx.Colour(0,255,0)
# elif item == 0 and col == 2:
# return wx.Colour(0,0,255)
# else:
# return None
#def OnGetItemTextColour(self, item, col):
# pass
# Call: When mouse hover a cell (line/col)
#def OnGetItemColumnImage(self, item, column):
#print ("OnGetItemColumnImage(self, item = %d, column = %d)" % (item, column) )
# return self.randomLists[item%5]
# Call: Seems to never be called (???)
#def OnGetItemImage(self, item):
# print ("OnGetItemImage(self, item = %d)" % item)
# return self.randomLists[item%5]
# Call: Seems d° as 'OnGetItemColumnImage(self, item, column)'
# BUT ONLY When mouse hover a LINE
# NB: Colorise lines background
def OnGetItemAttr(self, item):
if item % 2 == 1:
return self.linColEve
else:
return self.linColOdd
####################################################################
# Call: d° as 'OnGetItemColumnImage(self, item, column)'
# When mouse hover a cell (line/col)
def OnGetItemColumnCheck(self, item, column):
#print("OnGetItemColumnCheck(self, item = %d, column = %d)" % (item, column))
if item%3 == 0:
return True
return False
# Call: Seems to never be called (???)
#def OnGetItemCheck(self, item):
# print("OnGetItemCheck(self, item = %d)" % item)
# if item%3 == 1:
# return True
# return False
####################################################################
# Call: Many times for cells (line/col)
# Icon types for cells
#def OnGetItemColumnKind(self, item, column):
#print("OnGetItemColumnKind(self, item = %d, column = %d) CTR: %d" % (item, column, mabite) )
#if item%3 == 0:
# return 2
#elif item%3 == 1:
# return 1
#return 0
# ATTENTION: 'OnGetItemColumnCheck(self, item, column)' MUST be active for a correct icons render
############################################################## my tests
# NB: All interesting info @:
# /usr/share/pyshared/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py
# OR: http://xoomer.virgilio.it/infinity77/AGW_Docs/ultimatelistctrl_module.html#ultimatelistctrl
def initData(self):
# Set start order (we consider that 1st column is the pkey) - A REVOIR QD FONCTIONNEL => PLUTÔT 1 PARM
self.DB_ORDER = "id"
# Set sens or order
self.DB_ORDER_SENS = "ASC"
# Set ROW_COUNT
self.ROW_COUNT = -1L
self.ROW_COUNT = self.DBrowCount()
self.SetItemCount(self.ROW_COUNT)
# 1st fill of list
self.DoCacheHint(0L, 25L)
def DBrowCount(self):
qry = "SELECT count(*) FROM %s " % (DBtab)
DBcur.execute(qry)
row_count = DBcur.fetchone()
return row_count
# Call: Each time widget needs to refresh visible lines (+2: up & dwn)
def OnCacheHint(self, event):
DoCacheHint(event.GetCacheFrom(), event.GetCacheTo())
# Check if range of wanted lines is already cached, and query DB into cache if not
def DoCacheHint(self, cacheFrom, cacheTo):
global DB_OFFSET, DB_LIMIT
# Calc last row Nb returned by last query
DBlastRow = cacheFrom + DB_LIMIT
if cacheFrom >= (DB_OFFSET + 1L) and cacheTo <= DBlastRow:
pass # Data is cached, do nothing. Also take care of end of list
elif cacheFrom == 0L and DB_OFFSET == 0L: # Beginning of list
pass # Data is cached, do nothing
else:
# Data isn't cached, refill the list w/ the right query
# but 1st of all, reload row count in case another user
# added new rows(s)
self.ROW_COUNT = self.DBrowCount()
self.SetItemCount(self.ROW_COUNT)
halfList = ((cacheTo - cacheFrom) + 1L) / 2L
DB_OFFSET = cacheTo - (DB_LIMIT / 2L) + halfList
# Take care of list beginning
if DB_OFFSET < 0L:
DB_OFFSET = 0L
# Construct query
qry = "SELECT %s FROM %s ORDER BY %s %s LIMIT %s OFFSET %s " % (self.DBcolListStr, self.DBtab, self.DB_ORDER, self.DB_ORDER_SENS, DB_LIMIT, DB_OFFSET)
# Fill the cache
DBcur.execute(qry)
self.dataCache = DBcur.fetchall()
# Reposition the selected line at the middle (V) of the list
def ScrollToItem(self, index):
top_value = max([0, index - self.GetCountPerPage() / 2])
bottom_value = min([index + self.GetCountPerPage() / 2, self.GetItemCount() - 1])
self.EnsureVisible(top_value)
self.EnsureVisible(bottom_value)
############################################################################
class TestFrame(wx.Frame):
def __init__(self, parent, DBcur=None, DBtab=None, DBcol=None, DBcolName=None):
wx.Frame.__init__(self, parent, -1,
"UltimateListCtrl in wx.LC_VIRTUAL mode - WITH DB READING",
size=(700, 600))
panel = wx.Panel(self, -1)
sizer = wx.BoxSizer(wx.VERTICAL)
listCtrl = TestUltimateListCtrl(panel, DBcur, DBtab, DBcol, DBcolName)
sizer.Add(listCtrl, 1, wx.EXPAND)
panel.SetSizer(sizer)
# It is HERE (next line) that everything goes awry.
# In the example we go to the end of this class and jump to:
# __main__ -> frame.Show(True)
# however here we're stuck into Ultimate source, generating errors
# that are printed on command line :((
sizer.Layout()
self.SetIcon(images.Mondrian.GetIcon())
self.CenterOnScreen()
self.Show()
############################################################################
if __name__ == '__main__':
import sys
app = wx.PySimpleApp()
# Open a DB connection
DBcon = psycopg2.connect("host='anubis.defcon1' dbname='testulc' user='testulc' password='testulc'")
# Set transations to autocommit to avoid leaving an open transaction when leaving
# which would leave DB in an 'idle in transaction' (bad) state,
# isolation_level = REPEATABLE_READ (mean: use only written data out of any transaction)
# better than READ COMMITED because it forbids fail another transaction
# by stealing one of its element.
# readonly = True
# deferrable = True (might avoid concurrency row lock PB ?)
# autocommit = Commitotomatic:)
DBcon.set_session(psycopg2.extensions.ISOLATION_LEVEL_REPEATABLE_READ,
True, True, psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
# Surely a redundancy with above line ------------------------------------------------ CHECK LATER
DBcon.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
# Create DB cursor
DBcur = DBcon.cursor()
# Table name
DBtab = "public.tst1m"
# Also create column names lists (DB & Displayed)
DBcol = { 0: ("id"), 1: ("name"), 2: ("note"), }
DBcolName = { 0: ("Identité"), 1: ("Nom"), 2: ("Commentaire"), }
frame = TestFrame(None, DBcur, DBtab, DBcol, DBcolName)
frame.Show(True)
app.MainLoop()
# Close DB
DBcon.close()
========================================= /CODE
Test table is randomly filled w/ 1M rows:
CREATE TABLE tst1m(
id serial primary key,
name character varying(64) not null,
note character varying(64) not null
);
CREATE UNIQUE INDEX tst1m_name_ix ON tst1m(name);
CREATE INDEX tst1m_note_ix ON tst1m(note);
JY
--
The future is a myth created by insurance salesmen and high school counselors.
Have you tried the newest version of ULC from the source repository?
http://trac.wxwidgets.org/browser/wxPython/3rdParty/AGW
> What I understand is the widget can't calculate its height, but why?
>
> I think I'm close to the solution but I miss(understand?) something in the
> Virtual chain that stuck me completely.
>
> Here are the command line errors and code (errors are "complete" as I just
> launched and immediately closed the window; but if I hover the widget, it
> continues to throw such error lines):
>
> ========================================= ERRORS
> $ python UltimateVirtualDemo_DB_2011-11-22_01_clean.py
> Traceback (most recent call last):
> File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 12138, in OnSize
> self._mainWin.RecalculatePositions()
> File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 9533, in RecalculatePositions
> entireHeight = count*lineHeight + LINE_SPACING
> TypeError: can only concatenate tuple (not "int") to tuple
It looks like count or lineHeight is a tuple for some reason rather than
the expected number. Try adding some code there to verify that, and
then backtrack a little to see if you can figure out why.
> ========================================= CODE
> # -*- coding: utf-8 -*-
>
> import wx
> import images
> import random
> import os, sys
>
> import psycopg2
Next time please make a sample that is as simple as possible and does
not depend on any code or resources beyond wxPython and the Python
library. http://wiki.wxpython.org/MakingSampleApps
--
Robin Dunn
Software Craftsman
http://wxPython.org
> Have you tried the newest version of ULC from the source repository?
> http://trac.wxwidgets.org/browser/wxPython/3rdParty/AGW
No, I use the regular Debian package (I was about to tell you it might
break some dependencies, by just realised that ULC don't exist into
stable (squeeze), so I'll be obliged to do that).
Ok, I'll now see if I can just install the new ULC version or if I'm
obliged to get rid of package and launch a tarball installation.
...
> Try adding some code there to verify that, and
> then backtrack a little to see if you can figure out why.
Easy tiger! I'm much more a code assembler than a programmer,
so please develop what you mean exactly (and where).
My goal is to bring ideas into a working thing, whatever the
(clean) means.
...
> Next time please make a sample that is as simple as possible and does
> not depend on any code or resources beyond wxPython and the Python
> library. http://wiki.wxpython.org/MakingSampleApps
I don't think I would be able to do that rapidly for the above reason;
it would be very hard for me and would take a lot of time.
I tested the whole code I posted and found it usable (especially the
DB + caching one, that work exactly as expected and was my first
concern).
I also spent more than a week to (hardly) find docs & conversations
about Virtual lists and to adapt them to my case - at 1st sight code
seems "runable", so my understanding is the problem comes from the
widget code itself (as I'm lost when entering widget internal setup).
I try to install the ULC new version and keep you posted.
Oh, one more question: can I easily add the ULC code to Debian stable
wx (V. 2.8.11.0-0), or is it impossible mission for me?
Thanks Robin
--
Avert misunderstanding by calm, poise, and balance.
> I created a simple ULC widget demo based on the wxPython demo. It works for
> me on Windows 7, wxPython 2.8.10.1 with the latest ULC from SVN (I think).
Ok thanks, that good news:)
--
The secret of healthy hitchhiking is to eat junk food.
I removed the original ultimatelistctrl.py and pyc, and replace it
with the one from trac.
Still the same situation, just a tiny bit more verbose:
========================================= ERRORS
$ python UltimateVirtualDemo_DB_2011-11-22_01.py
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 12201, in OnSize
self.DoLayout()
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 13551, in DoLayout
self._mainWin.RecalculatePositions()
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 9598, in RecalculatePositions
entireHeight = count*lineHeight + LINE_SPACING
TypeError: can only concatenate tuple (not "int") to tuple
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 12201, in OnSize
self.DoLayout()
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 13551, in DoLayout
self._mainWin.RecalculatePositions()
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 9598, in RecalculatePositions
entireHeight = count*lineHeight + LINE_SPACING
TypeError: can only concatenate tuple (not "int") to tuple
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 12201, in OnSize
self.DoLayout()
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 13551, in DoLayout
self._mainWin.RecalculatePositions()
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 9598, in RecalculatePositions
entireHeight = count*lineHeight + LINE_SPACING
TypeError: can only concatenate tuple (not "int") to tuple
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 12201, in OnSize
self.DoLayout()
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 13551, in DoLayout
self._mainWin.RecalculatePositions()
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 9598, in RecalculatePositions
entireHeight = count*lineHeight + LINE_SPACING
TypeError: can only concatenate tuple (not "int") to tuple
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 12201, in OnSize
self.DoLayout()
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 13551, in DoLayout
self._mainWin.RecalculatePositions()
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 9598, in RecalculatePositions
entireHeight = count*lineHeight + LINE_SPACING
TypeError: can only concatenate tuple (not "int") to tuple
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 7067, in OnPaint
self.RecalculatePositions(False)
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 9598, in RecalculatePositions
entireHeight = count*lineHeight + LINE_SPACING
TypeError: can only concatenate tuple (not "int") to tuple
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 12233, in OnInternalIdle
self._mainWin.RecalculatePositions()
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 9598, in RecalculatePositions
entireHeight = count*lineHeight + LINE_SPACING
TypeError: can only concatenate tuple (not "int") to tuple
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 12233, in OnInternalIdle
self._mainWin.RecalculatePositions()
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 9598, in RecalculatePositions
entireHeight = count*lineHeight + LINE_SPACING
TypeError: can only concatenate tuple (not "int") to tuple
========================================= /ERRORS
--
When the only tool you have is a hammer, every problem starts to look
like a nail.
O_o: the error trace links to line #9598:
9594 if not self.HasAGWFlag(ULC_HAS_VARIABLE_ROW_HEIGHT):
9595 # all lines have the same height and we scroll one line per step
9596
9597 lineHeight = self.GetLineHeight()
9598 entireHeight = count*lineHeight + LINE_SPACING
so I made a test adding |ULC_HAS_VARIABLE_ROW_HEIGHT at the end of the ULC
__init__ string, and got this:
$ python UltimateVirtualDemo_DB_2011-11-22_01.py
Traceback (most recent call last):
File "UltimateVirtualDemo_DB_2011-11-22_01.py", line 499, in <module>
frame = TestFrame(None, DBcur, DBtab, DBcols, DBcolsNames)
File "UltimateVirtualDemo_DB_2011-11-22_01.py", line 448, in __init__
listCtrl = TestUltimateListCtrl(panel, DBcur, DBtab, DBcols, DBcolsNames)
File "UltimateVirtualDemo_DB_2011-11-22_01.py", line 61, in __init__
|ULC_HAS_VARIABLE_ROW_HEIGHT)
NameError: global name 'ULC_HAS_VARIABLE_ROW_HEIGHT' is not defined
Which seems quite weird (to me: remember I don't know very much about wx)
because it appears in the Window Style list from:
pydoc wx.lib.agw.ultimatelistctrl.
May be I should fold back to another base widget?!
Here are my basic needs:
* Read & cache data from very large tables,
* Sort data by column header click (some columns, not all) and
indicate what is the sorting direction,
* Change a whole line text color &| background
(based on a DB column criteria),
* Drag columns to be able to change their order,
* Display images in a column (if needed, directly from a DB column)
as it will be used for ie: an items' list (single) choice.
--
Les choses ne sont pas toujours ce que l'on voudrait
qu'elles soient qu'elles fussent -- P. Dac
On 23 November 2011 20:03, Jean-Yves F. Barbier wrote:
> On Wed, 23 Nov 2011 10:23:26 -0800
> Robin Dunn <ro...@alldunn.com> wrote:
>
>> Have you tried the newest version of ULC from the source repository?
>> http://trac.wxwidgets.org/browser/wxPython/3rdParty/AGW
>
> No, I use the regular Debian package (I was about to tell you it might
> break some dependencies, by just realised that ULC don't exist into
> stable (squeeze), so I'll be obliged to do that).
>
> Ok, I'll now see if I can just install the new ULC version or if I'm
> obliged to get rid of package and launch a tarball installation.
>
> ...
>> Try adding some code there to verify that, and
>> then backtrack a little to see if you can figure out why.
>
> Easy tiger! I'm much more a code assembler than a programmer,
> so please develop what you mean exactly (and where).
print count
print lineHeight
print LINE_SPACING
in the ULC code may be a good start.
>> Next time please make a sample that is as simple as possible and does
>> not depend on any code or resources beyond wxPython and the Python
>> library. http://wiki.wxpython.org/MakingSampleApps
>
> I don't think I would be able to do that rapidly for the above reason;
> it would be very hard for me and would take a lot of time.
This is the best way to find out where bugs are, and it takes far less
time than you think. If the ULC demos work OK for you, then I guess it
is either a deeper issue in ULC or a bug in your code.
> Oh, one more question: can I easily add the ULC code to Debian stable
> wx (V. 2.8.11.0-0), or is it impossible mission for me?
The whole of AGW is almost independent from the current wxPython
release, so you can try and grab the latest SVN version and see what
happens.
Andrea.
"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.alice.it/infinity77/
>>> import PyQt4.QtGui
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
ImportError: No module named PyQt4.QtGui
>>>
>>> import pygtk
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
ImportError: No module named pygtk
>>>
>>> import wx
>>>
>>>
On 23 November 2011 21:23, Jean-Yves F. Barbier wrote:
> On Wed, 23 Nov 2011 10:23:26 -0800
> Robin Dunn <ro...@alldunn.com> wrote:
>
>
> O_o: the error trace links to line #9598:
>
> 9594 if not self.HasAGWFlag(ULC_HAS_VARIABLE_ROW_HEIGHT):
> 9595 # all lines have the same height and we scroll one line per step
> 9596
> 9597 lineHeight = self.GetLineHeight()
> 9598 entireHeight = count*lineHeight + LINE_SPACING
>
> so I made a test adding |ULC_HAS_VARIABLE_ROW_HEIGHT at the end of the ULC
> __init__ string, and got this:
>
> $ python UltimateVirtualDemo_DB_2011-11-22_01.py
> Traceback (most recent call last):
> File "UltimateVirtualDemo_DB_2011-11-22_01.py", line 499, in <module>
> frame = TestFrame(None, DBcur, DBtab, DBcols, DBcolsNames)
> File "UltimateVirtualDemo_DB_2011-11-22_01.py", line 448, in __init__
> listCtrl = TestUltimateListCtrl(panel, DBcur, DBtab, DBcols, DBcolsNames)
> File "UltimateVirtualDemo_DB_2011-11-22_01.py", line 61, in __init__
> |ULC_HAS_VARIABLE_ROW_HEIGHT)
> NameError: global name 'ULC_HAS_VARIABLE_ROW_HEIGHT' is not defined
>
> Which seems quite weird (to me: remember I don't know very much about wx)
> because it appears in the Window Style list from:
> pydoc wx.lib.agw.ultimatelistctrl.
Of course you get a NameError, where does ULC_HAS_VARIABLE_ROW_HEIGHT
comes from? How do you import UltimateListCtrl? If you do this:
import wx.lib.agw.ultimatelistctrl as ULC
Then the window style is:
ULC.ULC_HAS_VARIABLE_ROW_HEIGHT
(Notice the "ULC." at the beginning). This is basic Python.
> Of course you get a NameError, where does ULC_HAS_VARIABLE_ROW_HEIGHT
> comes from? How do you import UltimateListCtrl? If you do this:
>
> import wx.lib.agw.ultimatelistctrl as ULC
Oops, yep (I missed that in the example:(
But still the same issue.
I try to add some "print" into the ULC code.
--
Most people would add a copy of the newer modules they need to their own
application's source tree, and then adjust the imports so that module is
loaded instead of the older one.
> ...
>> Try adding some code there to verify that, and
>> then backtrack a little to see if you can figure out why.
>
> Easy tiger! I'm much more a code assembler than a programmer,
> so please develop what you mean exactly (and where).
On the line before you can print the variables and see what you get.
> ...
>> Next time please make a sample that is as simple as possible and does
>> not depend on any code or resources beyond wxPython and the Python
>> library. http://wiki.wxpython.org/MakingSampleApps
>
> I don't think I would be able to do that rapidly for the above reason;
> it would be very hard for me and would take a lot of time.
Probably less time than figuring out the problem by yourself because
almost nobody is going to install a database and db modules and create a
million row table in order to experiment with your code. The whole
point of creating samples when asking for help is to isolate the problem
so as to not side-track or burden the helper with superfluous
information. Often when people go through the effort of making a
minimal sample they figure out on their own what they did wrong and they
learn a valuable lesson that may not have been learned if somebody else
just tells them what changes to make. It is also much easier for the
person providing the help if they can actually run the code instead of
just reading it in an email.
> print count
> print lineHeight
> print LINE_SPACING
> in the ULC code may be a good start.
Thanks, I wasn't sure it was here.
So I did and here's the result (count is a long int):
$ python UltimateVirtualDemo_DB_2011-11-22_01.py
count = 0
lineHeight = 26
LINE_SPACING = 0
count = 211158
lineHeight = 26
LINE_SPACING = 0
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 12144, in OnSize
self._mainWin.RecalculatePositions()
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 9539, in RecalculatePositions
entireHeight = count*lineHeight + LINE_SPACING
TypeError: can only concatenate tuple (not "int") to tuple
count = 211158
lineHeight = 26
LINE_SPACING = 0
etc.
--
A man who cannot seduce men cannot save them either.
-- Soren Kierkegaard
Oops, shaping print missed the point: in fact, 'count' is a tupple:
(211158L,)
may be it comes from there.
--
I'm not sure I've even got the brains to be President.
-- Barry Goldwater, in 1964
On 23 November 2011 21:59, Jean-Yves F. Barbier wrote:
> On Wed, 23 Nov 2011 21:27:02 +0100
> Andrea Gavana <andrea...@gmail.com> wrote:
>
> Oops, shaping print missed the point: in fact, 'count' is a tupple:
> (211158L,)
This is not possible. Unless, of course, you messed up your DB stuff:
self.ROW_COUNT = self.DBrowCount()
self.SetItemCount(self.ROW_COUNT)
def DBrowCount(self):
qry = "SELECT count(*) FROM %s " % (DBtab)
DBcur.execute(qry)
row_count = DBcur.fetchone()
return row_count
Nononononono, fetchone returns a tuple (from my limited understanding
of psycopg):
http://initd.org/psycopg/docs/cursor.html#cursor.fetchone
I may add a check to see if the call to SetItemCount receives an
integer or not, but that is irrelevant in this thread. The bug was not
in ULC.
> self.ROW_COUNT = self.DBrowCount()
> self.SetItemCount(self.ROW_COUNT)
>
> def DBrowCount(self):
> qry = "SELECT count(*) FROM %s " % (DBtab)
> DBcur.execute(qry)
> row_count = DBcur.fetchone()
> return row_count
>
> Nononononono, fetchone returns a tuple (from my limited understanding
> of psycopg):
Yep, you're absolutely right! And I should have seen that because
the eric debugger tells it is a tuple:(
So I change my return to make sure it returns an long integer:
myret = row_count[0]
return myret
and double checked in eric.
I also change the call from: DoCacheHint(.....) to: self.DoCacheHint(.....)
at the end of initData(self).
I modified: OnGetItemText(self, item, col) to have a visual too:
def OnGetItemText(self, item, col):
print ("self.dataCache[%d][%d]" % (item, col))
return self.dataCache[item][col]
Thanks to you, it progressed; here is the log between launch and CTRL-F4:
$ python UltimateVirtualDemo_DB_2011-11-22_01_clean.py
self.dataCache[0][0]
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 7105, in OnPaint
theLine = self.GetLine(line)
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 6416, in GetLine
self.CacheLineData(n)
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 6523, in CacheLineData
ld.SetColour(col, listctrl.OnGetItemTextColour(line, col))
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 12509, in OnGetItemTextColour
raise Exception("UltimateListCtrl.OnGetItemTextColour not supposed to be called")
Exception: UltimateListCtrl.OnGetItemTextColour not supposed to be called
self.dataCache[0][0]
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 7105, in OnPaint
theLine = self.GetLine(line)
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 6416, in GetLine
self.CacheLineData(n)
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 6523, in CacheLineData
ld.SetColour(col, listctrl.OnGetItemTextColour(line, col))
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 12509, in OnGetItemTextColour
raise Exception("UltimateListCtrl.OnGetItemTextColour not supposed to be called")
Exception: UltimateListCtrl.OnGetItemTextColour not supposed to be called
But my windows is still virgin of any line and throw a new exception:
$ python UltimateVirtualDemo_DB_2011-11-22_01_clean.py
self.dataCache[0][0]
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 7106, in OnPaint
theLine = self.GetLine(line)
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 6417, in GetLine
self.CacheLineData(n)
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 6524, in CacheLineData
ld.SetColour(col, listctrl.OnGetItemTextColour(line, col))
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 12510, in OnGetItemTextColour
raise Exception("UltimateListCtrl.OnGetItemTextColour not supposed to be called")
Exception: UltimateListCtrl.OnGetItemTextColour not supposed to be called
self.dataCache[0][0]
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 7106, in OnPaint
theLine = self.GetLine(line)
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 6417, in GetLine
self.CacheLineData(n)
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 6524, in CacheLineData
ld.SetColour(col, listctrl.OnGetItemTextColour(line, col))
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 12510, in OnGetItemTextColour
raise Exception("UltimateListCtrl.OnGetItemTextColour not supposed to be called")
Exception: UltimateListCtrl.OnGetItemTextColour not supposed to be called
So I reactivated this method (AND added: # -*- coding: utf-8 -*- at the
beginning of the new ULC file, which I formerly forgot):
def OnGetItemTextColour(self, item, col):
if item == 0 and col == 0:
return wx.Colour(255,0,0)
elif item == 0 and col == 1:
return wx.Colour(0,255,0)
elif item == 0 and col == 2:
return wx.Colour(0,0,255)
else:
return None
and got:
$ python UltimateVirtualDemo_DB_2011-11-22_01_clean.py
self.dataCache[0][0]
self.dataCache[0][1]
self.dataCache[0][2]
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 7112, in OnPaint
line==self._current, enabled, oldPN, oldBR)
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 4614, in DrawInReportMode
self.DrawTextFormatted(dc, item.GetText(), line, col, itemRect, overflow)
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 4673, in DrawTextFormatted
w, h, dummy = dc.GetMultiLineTextExtent(text)
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/_gdi.py", line 3774, in GetMultiLineTextExtent
return _gdi_.DC_GetMultiLineTextExtent(*args, **kwargs)
TypeError: String or Unicode type required
self.dataCache[0][0]
self.dataCache[0][1]
self.dataCache[0][2]
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 7112, in OnPaint
line==self._current, enabled, oldPN, oldBR)
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 4614, in DrawInReportMode
self.DrawTextFormatted(dc, item.GetText(), line, col, itemRect, overflow)
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 4673, in DrawTextFormatted
w, h, dummy = dc.GetMultiLineTextExtent(text)
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/_gdi.py", line 3774, in GetMultiLineTextExtent
return _gdi_.DC_GetMultiLineTextExtent(*args, **kwargs)
TypeError: String or Unicode type required
And here I'm again lost, sniff.
BUT there an improvement: the first data line is still empty but colored
in light cyan.
> Andrea.
>
> " Weapons Are The Only War Reality Against Imagination."
> http://xoomer.alice.it/infinity77/
--
For every complex problem, there is a solution that is simple, neat, and wrong.
-- H. L. Mencken
Hehe: it's aliiive!
You gave me the start hint that triggered it.
My last PB was the cache was returning the *real* type of the DB column
instead of a string; so I str()ed the return value and all is not working :)
Thanks to you & Robin.
JY
--
Tomorrow, you can be anywhere.
...
instead of a string; so I str()ed the return value and all is NOW working :)
...
--
Don't get stuck in a closet -- wear yourself out.
I modified some code (to correctly fit cache limits, etc) and it is now working
almost perfectly.
The last thing to fix is having the "END" key functional:
"HOME" is working from wherever I am,
"UP" & "DOWN" are also working,
but "END" throw a cryptic error msg (from any place in list):
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 8104, in OnChar
self.OnArrowChar(self.GetItemCount() - 1, event)
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 7970, in OnArrowChar
newCurrent = self.GetNextActiveItem(newCurrent, newCurrent > oldCurrent)
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 7954, in GetNextActiveItem
listItem = self.GetItem(listItem, 0)
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 8945, in GetItem
if item._itemId < 0 or item._itemId >= self.GetItemCount():
AttributeError: 'long' object has no attribute '_itemId'
BTW, is there a place to write it: I spent so many time on this one
that people might be interested in.
--
Obviously the only rational solution to your problem is suicide.
>
> Traceback (most recent call last):
> File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 8104, in OnChar
> self.OnArrowChar(self.GetItemCount() - 1, event)
> File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 7970, in OnArrowChar
> newCurrent = self.GetNextActiveItem(newCurrent, newCurrent > oldCurrent)
> File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 7954, in GetNextActiveItem
> listItem = self.GetItem(listItem, 0)
> File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/agw/ultimatelistctrl.py", line 8945, in GetItem
> if item._itemId < 0 or item._itemId >= self.GetItemCount():
> AttributeError: 'long' object has no attribute '_itemId'
In fact wx only takes an INTEGER for the list length, this error pops up
because I used a LONG and disappeared when using an INTEGER.
This is a terrible behaviour as I've got some tables with several billions
of rows in.
Is there any manner to flip it to use LONG instead of INTEGER?
--
Thanks, this was a bug in ULC, it should be fixed now in SVN.