Gunnar Sletta schrieb:
> Tom Schindl wrote:
>> Hi Gunnar,
>>
>> The first thing I found out is that it looks like a problem in QList and
>> Event-Listeners.
>>
>>> Thread 0 Crashed:
>>> 0   <<00000000>>     0x26594a85 0 + 643385989
>>> 1   libqtjambi.jnilib     0x0275367e qtjambi_event_notify(void**) + 80
>>> 2   libQtCore.4.dylib     0x0896fd53
>>> QInternal::activateCallbacks(QInternal::Callback, void**) + 115
>>> 3   libQtCore.4.dylib     0x08a60b11
>>> QCoreApplication::notifyInternal(QObject*, QEvent*) + 49
>>> 4   libQtCore.4.dylib     0x08a63de1
>>> QCoreApplicationPrivate::sendPostedEvents(QObject*, int,
>>> QThreadData*) + 689
>>> 5   libQtGui.4.dylib      0x08d4d68b
>>> QEventDispatcherMac::processEvents(QFlags<QEventLoop::ProcessEventsFlag>)
>>> + 107
>>> 6   libQtCore.4.dylib     0x08a60231
>>> QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 65
>>> 7   libQtCore.4.dylib     0x08a602fd
>>> QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) + 157
>>> 8   libQtCore.4.dylib     0x08a64021 QCoreApplication::exec() + 161
> 
> I'm afraid not ;)
> 
> This only states that the problem occured while an event was being
> delivered, most likely it was a DeleteLater event, caused by a GUI
> object being collected on the GC thread and the deletion being delegated
> back to the GUI thread. We spent a lot of effort ironing out these
> issues back in may, and I was rather confident that we had caught these
> problems, but alas..
> 
> Places to look:
>  * Do you have any disposeLater() or dispose() in your code?

No dispose() / disposeLater() at all :-(

>  * Start looking at the parts of the app where you use temporary GUI
> objects: QFonts, QPixmaps, QRegions, QGraphicsItems, QBrushes, QPens, etc.
> 

None of the above is used :-(

Another stacktrace I just got:
> Thread 0 Crashed:
> 0   libcom_trolltech_qt_gui.jnilib    0x0982eedc qtjambi_destructor(void*) + 
> 12
> 1   libqtjambi.jnilib                 0x027547ef 
> QtJambiDestructorEvent::callDestructor() + 57
> 2   libqtjambi.jnilib                 0x0275367e qtjambi_event_notify(void**) 
> + 80
> 3   libQtCore.4.dylib                 0x0896fd53 
> QInternal::activateCallbacks(QInternal::Callback, void**) + 115
> 4   libQtCore.4.dylib                 0x08a60b11 
> QCoreApplication::notifyInternal(QObject*, QEvent*) + 49
> 5   libQtCore.4.dylib                 0x08a63de1 
> QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) + 689
> 6   libQtGui.4.dylib                  0x08d4d68b 
> QEventDispatcherMac::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 
> 107
> 7   libQtCore.4.dylib                 0x08a60231 
> QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 65
> 8   libQtCore.4.dylib                 0x08a602fd 
> QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) + 157
> 9   libQtCore.4.dylib                 0x08a64021 QCoreApplication::exec() + 
> 161

The problem occurs with some of my ListWidget-code because when I
comment certain parts the crash is not happening any more.

E.g. when I comment the remove-code or the selection-update-code I don't
get a crash.

The call order is like this:
a) insert x items
b) remove x old items
c) clear the widget
d) set a new selection

I tried to extract the call order but naturally then it doesn't crash.


Tom
/*******************************************************************************
 * Copyright (c) 2008, Original authors.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Tom Schindl <[EMAIL PROTECTED]>
 
*******************************************************************************/
package org.ufacekit.ui.qt.jface;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.ufacekit.ui.viewers.IElementComparer;
import org.ufacekit.ui.viewers.IListViewer;
import org.ufacekit.ui.viewers.LabelConverter;

import com.trolltech.qt.gui.QListWidget;
import com.trolltech.qt.gui.QListWidgetItem;
import com.trolltech.qt.gui.QItemSelectionModel.SelectionFlag;

public class ListViewer<ModelElement, Input> extends Viewer<ModelElement, 
Input> implements IListViewer<ModelElement, Input> {
        private QListWidget listWidget;
        private LabelConverter<ModelElement> labelProvider = new 
LabelConverter<ModelElement>();
        private boolean blockevent = false;

        private class QListWidgetItemImpl extends QListWidgetItem {
                private ModelElement data;
        }

        public ListViewer(QListWidget listWidget) {
                this.listWidget = listWidget;
                this.listWidget.itemSelectionChanged.connect(this, 
"selectionChanged()");
        }

        private void selectionChanged() {
                if( blockevent ) {
                        return;
                }
                fireSelectionChangeListener();
        }

        public LabelConverter<ModelElement> getLabelProvider() {
                return labelProvider;
        }

        public void setLabelProvider(LabelConverter<ModelElement> 
labelProvider) {
                this.labelProvider = labelProvider;
        }

        public void add(ModelElement element) {
                System.err.println("Adding: " + element);
                QListWidgetItem item = createItem(getLabelProvider(), element);
                listWidget.addItem(item);
        }

        public void insert(ModelElement element, int index) {
                System.err.println("Inserting: " + element + " => " + index);
                QListWidgetItem item = createItem(getLabelProvider(), element);
                listWidget.insertItem(index, item);
        }

        public void remove(ModelElement element) {
                System.err.println("Removing: " + element);
                QListWidgetItem item = findItem(element);
                if( item != null ) {
                        listWidget.removeItemWidget(item);
                }
        }

        private QListWidgetItem findItem(ModelElement element) {
                int size = listWidget.count();
                IElementComparer<ModelElement> c = getComparer();

                for( int i = 0; i < size; i++ ) {
                        QListWidgetItemImpl item = (QListWidgetItemImpl) 
listWidget.item(i);
                        if( item.data == element || item.data.equals(element) 
|| ( c != null && c.equals(item.data, element) )) {
                                return item;
                        }
                }
                return null;
        }

        private QListWidgetItemImpl createItem(LabelConverter<ModelElement> cp, 
ModelElement element) {
                QListWidgetItemImpl item = new QListWidgetItemImpl();
                item.data = element;
                item.setText(cp.getText(element));
                return item;
        }

        @Override
        void doRefreshAll() {
                System.err.println("Refresh");
                listWidget.clear();
                LabelConverter<ModelElement> cp = getLabelProvider();
                Collection<ModelElement> elements = 
getFilteredAndSortedElements();

                int i = 0;
                for( ModelElement element: elements ) {
                        listWidget.insertItem(i++,createItem(cp, element));
                }
        }

        @Override
        List<ModelElement> doGetSelectedElements() {
                List<QListWidgetItem> items = listWidget.selectedItems();
                List<ModelElement> rv = new 
ArrayList<ModelElement>(items.size());

                for( QListWidgetItem item: items ) {
                        rv.add(((QListWidgetItemImpl)item).data);
                }

                return rv;
        }

        @Override
        void doSetSelectedElements(List<ModelElement> elements) {
                blockevent = true;
                System.err.println("SELECTION: " + elements);
                listWidget.clearSelection();
                for( ModelElement element: elements ) {
                        QListWidgetItem item = findItem(element);
                        if( item != null ) {
                                
listWidget.setCurrentItem(item,SelectionFlag.Select);
                        }
                }
                System.err.println("SELECTION DONE: " + elements);
                blockevent = false;
//              fireSelectionChangeListener();

        }
}
package org.ufacekit.ui.qt.jface.examples;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.ufacekit.ui.viewers.IElementComparer;
import org.ufacekit.ui.viewers.LabelConverter;

import com.trolltech.qt.gui.QApplication;
import com.trolltech.qt.gui.QDialog;
import com.trolltech.qt.gui.QGridLayout;
import com.trolltech.qt.gui.QListWidget;
import com.trolltech.qt.gui.QListWidgetItem;
import com.trolltech.qt.gui.QPushButton;
import com.trolltech.qt.gui.QItemSelectionModel.SelectionFlag;

public class QTListBug extends QDialog {
        private QListWidget widget;
        private static ArrayList<String> VALUES_1 = new ArrayList<String>();
        
        {
                VALUES_1.add("Tyrol");
                VALUES_1.add("Vorarlberg");
                VALUES_1.add("Salzburg");
                VALUES_1.add("Upper Austria");
                VALUES_1.add("Carinthia");
                VALUES_1.add("Styria");
                VALUES_1.add("Lower Austria");
                VALUES_1.add("Vienna");
                VALUES_1.add("Burgenland");
        }
        
        private static ArrayList<String> VALUES_2 = new ArrayList<String>();
        
        {
                VALUES_2.add("London");
                VALUES_2.add("West Yorkshire");
                VALUES_2.add("South Yorkshire");
                VALUES_2.add("Upper Austria");
                VALUES_2.add("North Yorkshire");
                VALUES_2.add("Somerset");
        }
        
        private static boolean flag = true;
        
        private class QListWidgetItemImpl extends QListWidgetItem {
                private Object data;
        }
        
        public QTListBug() {
                QGridLayout layout = new QGridLayout();
                widget = new QListWidget();
                widget.itemSelectionChanged.connect(this, "modify2()");
        
                QListWidget selectionWidget = new QListWidget();
                selectionWidget.itemSelectionChanged.connect(this, "modify()");
                selectionWidget.addItems(Arrays.asList("A","B","C","D"));
                
                doRefreshAll(VALUES_1);
                
doSetSelectedElements(Collections.singletonList(VALUES_1.get(0)));
                
                layout.addWidget(widget);
                layout.addWidget(selectionWidget);

                setLayout(layout);
        }
        
        public void modify2() {
                System.err.println("SELECTION CHANGED FIRED");
        }
        
        public void modify() {
                ArrayList<String> insert;
                ArrayList<String> remove;
                
                if( flag ) {
                        insert = VALUES_2;
                        remove = VALUES_1;
                } else {
                        insert = VALUES_1;
                        remove = VALUES_2;
                }
                
                int i = 0;
                for( String s: insert ) {
                        insert(s,i++);
                }
                
                for( String s: remove ) {
                        remove(s);
                }
                
                doRefreshAll(insert);
                doSetSelectedElements(Collections.singletonList(insert.get(0)));
                
                flag = !flag;
        }
        
        private void doRefreshAll(ArrayList<String> elements) {
                System.err.println("Refresh");
                widget.clear();

                int i = 0;
                for( String element: elements ) {
                        widget.insertItem(i++,createItem(element));
                }
        }
        
        private QListWidgetItem findItem(String element) {
                int size = widget.count();

                for( int i = 0; i < size; i++ ) {
                        QListWidgetItemImpl item = (QListWidgetItemImpl) 
widget.item(i);
                        if( item.data == element || item.data.equals(element) ) 
{
                                return item;
                        }
                }
                return null;
        }

        private QListWidgetItemImpl createItem(String element) {
                QListWidgetItemImpl item = new QListWidgetItemImpl();
                item.data = element;
                item.setText(element);
                return item;
        }
        
        public void add(String element) {
                System.err.println("Adding: " + element);
                QListWidgetItem item = createItem(element);
                widget.addItem(item);
        }

        public void insert(String element, int index) {
                System.err.println("Inserting: " + element);
                QListWidgetItem item = createItem(element);
                widget.insertItem(index, item);
        }

        public void remove(String element) {
                System.err.println("Removing: " + element);
                QListWidgetItem item = findItem(element);
                if( item != null ) {
                        widget.removeItemWidget(item);
                }
        }
        
        /**
         * @param args
         */
        public static void main(final String[] args) {
                QApplication.initialize(args);
                new QTListBug().show();
                QApplication.exec();

        }
        
        void doSetSelectedElements(List<String> elements) {
                System.err.println("SELECTION: " + elements);
                widget.clearSelection();
                for( String element: elements ) {
                        QListWidgetItem item = findItem(element);
                        if( item != null ) {
                                
widget.setCurrentItem(item,SelectionFlag.Select);
                        }
                }
                System.err.println("SELECTION DONE: " + elements);
//              fireSelectionChangeListener();

        }
}
_______________________________________________
Qt-jambi-interest mailing list
[email protected]
http://lists.trolltech.com/mailman/listinfo/qt-jambi-interest

Reply via email to