[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-bugs-dist
Subject:    Bug#1504: KTabListBox displaying stale information after being cleared.
From:       Bill Slemer <bill-slemco () mediaone ! net>
Date:       1999-07-02 4:48:55
[Download RAW message or body]

Package: kdelibs
Version: 1.1

KTabListBox will display stale information in a column of a row after
being clear() 'ed.  The following  code snippet exhibits the problem.
It is a piece of code to fill in a tabbed list box with four columns.
The last column is a "comment" field which may or may not have a
comment.  If no comment is present, the comment field is set to null
string which results in KTabListBox putting any previous stale data for
that column of that row from a previous insertItem() call.

<<< begin snippet >>>

KTabListBox  voiceListBox;
     :
  voiceListBox->clear();   // <<<<===== NOTE THE clear();
     :
  for(i=0;i<voiceDir.count();i++)
  {
    voiceIndex->setGroup("status");
    QString message=voiceDir[i];
    if( (flag = voiceIndex->readEntry(message))  == 0)
      flag = "new";
    message = voiceDir.path();
    message += "/";
    message += voiceDir[i];

       :

    //
    // If there is no valid comment, set "comment" to a null string.
    //
    voiceIndex->setGroup("comments");
    if((comment = voiceIndex->readEntry(voiceDir[i]))  == 0)
      comment = "";    // <<<==== NOTE: the null string.
<<<<============<<<<<<

       :

    message.sprintf("%s\n%s\n%d %s\n%s",(const char *)flag,
                    (const char *)mydate,
                    length, (const char *)i18n("secs"),
                    (const char *)comment);
    //debug( "    ----> %s",(const char *) message );
    voiceListBox->insertItem(message);   // <<<<==== NOTE: the last
field of "message" will be null.
  }
}

<<< end snippet >>>

Examining the KTabListBox::clear() code (ktablistbox.cpp  - revision
1.52) shows that clear() will mark any items in the list box with a "-2"
(apparently to denote that it's been deleted?), but doesn't appear to
delete the items.

Examining the KTabListBox::insertItem() code (ktablistbox.cpp  -
revision 1.52) shows that it calls KTabListBox::changeItem(), which
contains the following code:

void KTabListBox::changeItem(const QString& aStr, int row)
{
    char  sepStr[2];

  if (row < 0 || row >= numRows()) return;

  char *str = qstrdup(aStr.local8Bit()); // TODO: make it really QString
using

  sepStr[0] = sepChar;
  sepStr[1] = '\0';

  KTabListBoxItem* item = itemList[row];
  char *pos = strtok(str, sepStr);
//
// key line follows ---||||
//                     VVVV
  for (int i=0; pos && *pos && i<numCols(); i++)
  {
    item->setText(i, QString::fromLocal8Bit(pos));
    pos = strtok(0L, sepStr);
  }
  item->setForeground(black);

  if (needsUpdate(row)) lbox.repaint();
  delete [] str;
}


The "*pos" of the for-loop will terminate without setting the "comment"
field (last column of row) since it was parsed out of aStr using
strtok() which returned a pointer to a null string.  That is, the body
of the for-loop was not executed.

A work around for me is to set the "comment" variable to " " (single
space) rather than the null string "".  However, this is not desireable.

POSSIBLE FIXES:
===============
(1) remove "*pos" from conditional check of for-loop.  However, will
passing a null string to setText() cause a problem?
(2) change KTabListBox::clear() to set the string in the "item" to a
null string rather than just marking it as a "-2".
(3) catch the null string in the body of the for-loop and do something
special to free the memory for the column.

[Attachment #3 (text/html)]

<HTML>
<TT>Package: kdelibs</TT>
<BR><TT>Version:&nbsp;1.1</TT><TT></TT>

<P><TT>KTabListBox will display stale information in a column of a row
after being clear() 'ed.&nbsp; The following&nbsp; code snippet exhibits
the problem.&nbsp; It is a piece of code to fill in a tabbed list box with
four columns.&nbsp; The last column is a "comment" field which may or may
not have a comment.&nbsp; If no comment is present, the comment field is
set to null string which results in KTabListBox putting any previous stale
data for that column of that row from a previous insertItem() call.</TT><TT></TT>

<P><TT>&lt;&lt;&lt; begin snippet >>></TT><TT></TT>

<P><TT>KTabListBox&nbsp; voiceListBox;</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp; :</TT>
<BR><TT>&nbsp; voiceListBox->clear();&nbsp;&nbsp; // &lt;&lt;&lt;&lt;=====
NOTE&nbsp;THE&nbsp;clear();</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp; :</TT>
<BR><TT>&nbsp; for(i=0;i&lt;voiceDir.count();i++)</TT>
<BR><TT>&nbsp; {</TT>
<BR><TT>&nbsp;&nbsp;&nbsp; voiceIndex->setGroup("status");</TT>
<BR><TT>&nbsp;&nbsp;&nbsp; QString message=voiceDir[i];</TT>
<BR><TT>&nbsp;&nbsp;&nbsp; if( (flag = voiceIndex->readEntry(message))&nbsp;
== 0)</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flag = "new";</TT>
<BR><TT>&nbsp;&nbsp;&nbsp; message = voiceDir.path();</TT>
<BR><TT>&nbsp;&nbsp;&nbsp; message += "/";</TT>
<BR><TT>&nbsp;&nbsp;&nbsp; message += voiceDir[i];</TT><TT></TT>

<P><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :</TT><TT></TT>

<P><TT>&nbsp;&nbsp;&nbsp; //</TT>
<BR><TT>&nbsp;&nbsp;&nbsp; // If there is no valid comment, set "comment"
to a null string.</TT>
<BR><TT>&nbsp;&nbsp;&nbsp; //</TT>
<BR><TT>&nbsp;&nbsp;&nbsp; voiceIndex->setGroup("comments");</TT>
<BR><TT>&nbsp;&nbsp;&nbsp; if((comment = voiceIndex->readEntry(voiceDir[i]))&nbsp;
== 0)</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; comment = "";&nbsp;&nbsp;&nbsp;
// &lt;&lt;&lt;==== NOTE: the null string.&nbsp; \
&lt;&lt;&lt;&lt;============&lt;&lt;&lt;&lt;&lt;&lt;</TT><TT></TT>

<P><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :</TT><TT></TT>

<P><TT>&nbsp;&nbsp;&nbsp; message.sprintf("%s\n%s\n%d %s\n%s",(const char
*)flag,</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 (const char *)mydate,</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 length, (const char *)i18n("secs"),</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 (const char *)comment);</TT>
<BR><TT>&nbsp;&nbsp;&nbsp; //debug( "&nbsp;&nbsp;&nbsp; ----> %s",(const
char *) message );</TT>
<BR><TT>&nbsp;&nbsp;&nbsp; voiceListBox->insertItem(message);&nbsp;&nbsp;
// &lt;&lt;&lt;&lt;==== NOTE: the last field of "message" will be null.</TT>
<BR><TT>&nbsp; }</TT>
<BR><TT>}</TT><TT></TT>

<P><TT>&lt;&lt;&lt;&nbsp;end snippet >>></TT><TT></TT>

<P><TT>Examining the KTabListBox::clear() code (ktablistbox.cpp&nbsp; -
revision 1.52) shows that clear() will mark any items in the list box with
a "-2" (apparently to denote that it's been deleted?), but doesn't appear
to delete the items.</TT><TT></TT>

<P><TT>Examining the KTabListBox::insertItem() code (ktablistbox.cpp&nbsp;
- revision 1.52) shows that it calls KTabListBox::changeItem(), which contains
the following code:</TT><TT></TT>

<P><TT>void KTabListBox::changeItem(const QString&amp; aStr, int row)</TT>
<BR><TT>{</TT>
<BR><TT>&nbsp;&nbsp;&nbsp; char&nbsp; sepStr[2];</TT><TT></TT>

<P><TT>&nbsp; if (row &lt; 0 || row >= numRows()) return;</TT><TT></TT>

<P><TT>&nbsp; char *str = qstrdup(aStr.local8Bit()); // TODO: make it really
QString using</TT><TT></TT>

<P><TT>&nbsp; sepStr[0] = sepChar;</TT>
<BR><TT>&nbsp; sepStr[1] = '\0';</TT><TT></TT>

<P><TT>&nbsp; KTabListBoxItem* item = itemList[row];</TT>
<BR><TT>&nbsp; char *pos = strtok(str, sepStr);</TT>
<BR><TT>//</TT>
<BR><TT>// key line follows ---||||</TT>
<BR><TT>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 VVVV</TT>
<BR><TT>&nbsp; for (int i=0; pos &amp;&amp; *pos &amp;&amp; i&lt;numCols();
i++)</TT>
<BR><TT>&nbsp; {</TT>
<BR><TT>&nbsp;&nbsp;&nbsp; item->setText(i, QString::fromLocal8Bit(pos));</TT>
<BR><TT>&nbsp;&nbsp;&nbsp; pos = strtok(0L, sepStr);</TT>
<BR><TT>&nbsp; }</TT>
<BR><TT>&nbsp; item->setForeground(black);</TT><TT></TT>

<P><TT>&nbsp; if (needsUpdate(row)) lbox.repaint();</TT>
<BR><TT>&nbsp; delete [] str;</TT>
<BR><TT>}</TT>
<BR><TT></TT>&nbsp;<TT></TT>

<P><TT>The "*pos" of the for-loop will terminate without setting the "comment"
field (last column of row) since it was parsed out of aStr using strtok()
which returned a pointer to a null string.&nbsp; That is, the body of the
for-loop was not executed.</TT><TT></TT>

<P><TT>A work around for me is to set the "comment" variable to " " (single
space) rather than the null string "".&nbsp; However, this is not \
desireable.</TT><TT></TT>

<P><TT>POSSIBLE FIXES:</TT>
<BR><TT>===============</TT>
<BR><TT>(1) remove "*pos" from conditional check of for-loop.&nbsp; However,
will passing a null string to setText() cause a problem?</TT>
<BR><TT>(2) change KTabListBox::clear() to set the string in the "item"
to a null string rather than just marking it as a "-2".</TT>
<BR><TT>(3) catch the null string in the body of the for-loop and do something
special to free the memory for the column.</TT></HTML>



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic