From ee379340fcc5ebf8625906f42540c0fb3577f9ac Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Wed, 17 Mar 2010 13:35:16 +0100 Subject: Fix a sizing issue of message box on windows Vista/7 The problem is that the font changes after the creation of the buttons and we were setting a fixed size to the datails button. Task-number: QTBUG-8381 Reviewed-by: gabi --- src/gui/dialogs/qmessagebox.cpp | 49 ++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/src/gui/dialogs/qmessagebox.cpp b/src/gui/dialogs/qmessagebox.cpp index 121ba62..df8b525 100644 --- a/src/gui/dialogs/qmessagebox.cpp +++ b/src/gui/dialogs/qmessagebox.cpp @@ -118,14 +118,44 @@ public: } void setText(const QString &text) { textEdit->setPlainText(text); } QString text() const { return textEdit->toPlainText(); } - QString label(DetailButtonLabel label) - { return label == ShowLabel ? QMessageBox::tr("Show Details...") - : QMessageBox::tr("Hide Details..."); } private: TextEdit *textEdit; }; #endif // QT_NO_TEXTEDIT +class DetailButton : public QPushButton +{ +public: + DetailButton(QWidget *parent) : QPushButton(label(ShowLabel), parent) + { + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + } + + QString label(DetailButtonLabel label) const + { return label == ShowLabel ? QMessageBox::tr("Show Details...") : QMessageBox::tr("Hide Details..."); } + + void setLabel(DetailButtonLabel lbl) + { setText(label(lbl)); } + + QSize sizeHint() const + { + ensurePolished(); + QStyleOptionButton opt; + initStyleOption(&opt); + const QFontMetrics fm = fontMetrics(); + opt.text = label(ShowLabel); + QSize sz = fm.size(Qt::TextShowMnemonic, opt.text); + QSize ret = style()->sizeFromContents(QStyle::CT_PushButton, &opt, sz, this). + expandedTo(QApplication::globalStrut()); + opt.text = label(HideLabel); + sz = fm.size(Qt::TextShowMnemonic, opt.text); + ret.expandedTo(style()->sizeFromContents(QStyle::CT_PushButton, &opt, sz, this). + expandedTo(QApplication::globalStrut())); + return ret; + } +}; + + class QMessageBoxPrivate : public QDialogPrivate { Q_DECLARE_PUBLIC(QMessageBox) @@ -181,7 +211,7 @@ public: QAbstractButton *escapeButton; QPushButton *defaultButton; QAbstractButton *clickedButton; - QPushButton *detailsButton; + DetailButton *detailsButton; #ifndef QT_NO_TEXTEDIT QMessageBoxDetailsText *detailsText; #endif @@ -421,7 +451,7 @@ void QMessageBoxPrivate::_q_buttonClicked(QAbstractButton *button) Q_Q(QMessageBox); #ifndef QT_NO_TEXTEDIT if (detailsButton && detailsText && button == detailsButton) { - detailsButton->setText(detailsText->isHidden() ? detailsText->label(HideLabel) : detailsText->label(ShowLabel)); + detailsButton->setLabel(detailsText->isHidden() ? HideLabel : ShowLabel); detailsText->setHidden(!detailsText->isHidden()); updateSize(); } else @@ -1891,7 +1921,7 @@ void QMessageBoxPrivate::retranslateStrings() { #ifndef QT_NO_TEXTEDIT if (detailsButton) - detailsButton->setText(detailsText->isHidden() ? detailsText->label(HideLabel) : detailsText->label(ShowLabel)); + detailsButton->setLabel(detailsText->isHidden() ? HideLabel : ShowLabel); #endif } @@ -2399,11 +2429,8 @@ void QMessageBox::setDetailedText(const QString &text) grid->addWidget(d->detailsText, grid->rowCount(), 0, 1, grid->columnCount()); d->detailsText->hide(); } - if (!d->detailsButton) { - d->detailsButton = new QPushButton(d->detailsText->label(ShowLabel), this); - QPushButton hideDetails(d->detailsText->label(HideLabel)); - d->detailsButton->setFixedSize(d->detailsButton->sizeHint().expandedTo(hideDetails.sizeHint())); - } + if (!d->detailsButton) + d->detailsButton = new DetailButton(this); d->detailsText->setText(text); } #endif // QT_NO_TEXTEDIT -- cgit v0.12 From f9b0efc17962df74a67d81daca5814af93a5fb97 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Wed, 17 Mar 2010 14:12:49 +0100 Subject: Fixed a potential crash in headerview when inserting a section This could happen if a section was moved andthen hidden Task-number: QTBUG-8650 Reviewed-by: Andy Shaw --- src/gui/itemviews/qheaderview.cpp | 9 +++------ tests/auto/qheaderview/tst_qheaderview.cpp | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/gui/itemviews/qheaderview.cpp b/src/gui/itemviews/qheaderview.cpp index eb3db21..586e5d4 100644 --- a/src/gui/itemviews/qheaderview.cpp +++ b/src/gui/itemviews/qheaderview.cpp @@ -1698,13 +1698,10 @@ void QHeaderView::sectionsInserted(const QModelIndex &parent, if (!d->sectionHidden.isEmpty()) { QBitArray sectionHidden(d->sectionHidden); sectionHidden.resize(sectionHidden.count() + insertCount); - //sectionHidden.fill(false, logicalFirst, logicalLast + 1); - for (int i = logicalFirst; i <= logicalLast; ++i) - // visual == logical in this range (see previous block) - sectionHidden.setBit(i, false); + sectionHidden.fill(false, logicalFirst, logicalLast + 1); for (int j = logicalLast + 1; j < sectionHidden.count(); ++j) - sectionHidden.setBit(d->visualIndex(j), - d->sectionHidden.testBit(d->visualIndex(j - insertCount))); + //here we simply copy the old sectionHidden + sectionHidden.setBit(j, d->sectionHidden.testBit(j - insertCount)); d->sectionHidden = sectionHidden; } diff --git a/tests/auto/qheaderview/tst_qheaderview.cpp b/tests/auto/qheaderview/tst_qheaderview.cpp index 4642830..f6cd4e3 100644 --- a/tests/auto/qheaderview/tst_qheaderview.cpp +++ b/tests/auto/qheaderview/tst_qheaderview.cpp @@ -192,6 +192,7 @@ private slots: void task248050_hideRow(); void QTBUG6058_reset(); void QTBUG7833_sectionClicked(); + void QTBUG8650_crashOnInsertSections(); protected: QHeaderView *view; @@ -2056,6 +2057,19 @@ void tst_QHeaderView::QTBUG7833_sectionClicked() QCOMPARE(pressedSpy.at(2).at(0).toInt(), 0); } +void tst_QHeaderView::QTBUG8650_crashOnInsertSections() +{ + QStringList headerLabels; + QHeaderView view(Qt::Horizontal); + QStandardItemModel model(2,2); + view.setModel(&model); + view.moveSection(1, 0); + view.hideSection(0); + + QList items; + items << new QStandardItem("c"); + model.insertColumn(0, items); +} QTEST_MAIN(tst_QHeaderView) #include "tst_qheaderview.moc" -- cgit v0.12 From a45cec6a22c70f0b0d7e066822a74b2172d5f397 Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Mon, 15 Mar 2010 10:10:19 +0100 Subject: Add ultra-paranoid synchronization to QX11GLPixmapData This is completely over the top and many of these synchronisation points should be removed before doing any serious benchmarking. However, it makes sure any remaining bugs are not due to GPU & CPU being out of sync. Reviewed-By: TrustMe --- src/opengl/qpixmapdata_x11gl_egl.cpp | 66 ++++++++++++++++++++++++++++++++---- src/opengl/qpixmapdata_x11gl_p.h | 5 +++ 2 files changed, 65 insertions(+), 6 deletions(-) diff --git a/src/opengl/qpixmapdata_x11gl_egl.cpp b/src/opengl/qpixmapdata_x11gl_egl.cpp index a01eec4..2bdfe5c 100644 --- a/src/opengl/qpixmapdata_x11gl_egl.cpp +++ b/src/opengl/qpixmapdata_x11gl_egl.cpp @@ -41,19 +41,21 @@ #include -#include -#include -#include -#include +#include +#include +#include +#include #if !defined(QT_OPENGL_ES_1) -#include +#include #endif #ifndef QT_OPENGL_ES_2 -#include +#include #endif +#include + #include "qpixmapdata_x11gl_p.h" QT_BEGIN_NAMESPACE @@ -185,6 +187,58 @@ QX11GLPixmapData::~QX11GLPixmapData() delete ctx; } + +void QX11GLPixmapData::fill(const QColor &color) +{ + if (ctx) { + ctx->makeCurrent(); + glFinish(); + eglWaitClient(); + } + + QX11PixmapData::fill(color); + XSync(X11->display, False); + + if (ctx) { + ctx->makeCurrent(); + eglWaitNative(EGL_CORE_NATIVE_ENGINE); + } +} + +void QX11GLPixmapData::copy(const QPixmapData *data, const QRect &rect) +{ + if (ctx) { + ctx->makeCurrent(); + glFinish(); + eglWaitClient(); + } + + QX11PixmapData::copy(data, rect); + XSync(X11->display, False); + + if (ctx) { + ctx->makeCurrent(); + eglWaitNative(EGL_CORE_NATIVE_ENGINE); + } +} + +bool QX11GLPixmapData::scroll(int dx, int dy, const QRect &rect) +{ + if (ctx) { + ctx->makeCurrent(); + glFinish(); + eglWaitClient(); + } + + QX11PixmapData::scroll(dx, dy, rect); + XSync(X11->display, False); + + if (ctx) { + ctx->makeCurrent(); + eglWaitNative(EGL_CORE_NATIVE_ENGINE); + } +} + #if !defined(QT_OPENGL_ES_1) Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_gl_pixmap_2_engine) #endif diff --git a/src/opengl/qpixmapdata_x11gl_p.h b/src/opengl/qpixmapdata_x11gl_p.h index 83cd780..8681336 100644 --- a/src/opengl/qpixmapdata_x11gl_p.h +++ b/src/opengl/qpixmapdata_x11gl_p.h @@ -71,6 +71,11 @@ public: QX11GLPixmapData(); virtual ~QX11GLPixmapData(); + // Re-implemented from QX11PixmapData: + void fill(const QColor &color); + void copy(const QPixmapData *data, const QRect &rect); + bool scroll(int dx, int dy, const QRect &rect); + // Re-implemented from QGLPaintDevice QPaintEngine* paintEngine() const; // Also re-implements QX11PixmapData::paintEngine void beginPaint(); -- cgit v0.12 From 65313ab37780191c5aacd88f246aec6f8d839543 Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Wed, 17 Mar 2010 10:57:57 +0100 Subject: Make WA_TranslucentBackground work with QX11GLWindowSurface Reviewed-By: TrustMe --- src/opengl/qwindowsurface_x11gl.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/opengl/qwindowsurface_x11gl.cpp b/src/opengl/qwindowsurface_x11gl.cpp index 27b91ba..c6897d5 100644 --- a/src/opengl/qwindowsurface_x11gl.cpp +++ b/src/opengl/qwindowsurface_x11gl.cpp @@ -113,6 +113,8 @@ void QX11GLWindowSurface::setGeometry(const QRect &rect) QX11GLPixmapData *pd = new QX11GLPixmapData; pd->resize(newSize.width(), newSize.height()); m_backBuffer = QPixmap(pd); + if (window()->testAttribute(Qt::WA_TranslucentBackground)) + m_backBuffer.fill(Qt::transparent); } // if (gc) -- cgit v0.12 From cb06b04338545ee3f0227faaa26d0f97addb5cdd Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Wed, 17 Mar 2010 11:01:01 +0100 Subject: Implement scrolling in QX11GLWindowSurface Seems to have some artifacts when scrolling by 1 pixel, but apart from that works pretty well. Reviewed-By: TrustMe --- src/opengl/qwindowsurface_x11gl.cpp | 46 +++++++++++++++++++++++++++---------- src/opengl/qwindowsurface_x11gl_p.h | 3 ++- 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/opengl/qwindowsurface_x11gl.cpp b/src/opengl/qwindowsurface_x11gl.cpp index c6897d5..1061008 100644 --- a/src/opengl/qwindowsurface_x11gl.cpp +++ b/src/opengl/qwindowsurface_x11gl.cpp @@ -51,14 +51,16 @@ QT_BEGIN_NAMESPACE QX11GLWindowSurface::QX11GLWindowSurface(QWidget* window) - : QWindowSurface(window), m_GC(0), m_window(window) + : QWindowSurface(window), m_windowGC(0), m_pixmapGC(0), m_window(window) { } QX11GLWindowSurface::~QX11GLWindowSurface() { - if (m_GC) - XFree(m_GC); + if (m_windowGC) + XFree(m_windowGC); + if (m_pixmapGC) + XFree(m_pixmapGC); } QPaintDevice *QX11GLWindowSurface::paintDevice() @@ -92,13 +94,13 @@ void QX11GLWindowSurface::flush(QWidget *widget, const QRegion &widgetRegion, co // for (int i = 0; i < num; ++i) // qDebug() << ' ' << i << rects[i].x << rects[i].x << rects[i].y << rects[i].width << rects[i].height; - if (m_GC == 0) { - m_GC = XCreateGC(X11->display, m_window->handle(), 0, 0); - XSetGraphicsExposures(X11->display, m_GC, False); + if (m_windowGC == 0) { + m_windowGC = XCreateGC(X11->display, m_window->handle(), 0, 0); + XSetGraphicsExposures(X11->display, m_windowGC, False); } - XSetClipRectangles(X11->display, m_GC, 0, 0, rects, rectCount, YXBanded); - XCopyArea(X11->display, m_backBuffer.handle(), m_window->handle(), m_GC, + XSetClipRectangles(X11->display, m_windowGC, 0, 0, rects, rectCount, YXBanded); + XCopyArea(X11->display, m_backBuffer.handle(), m_window->handle(), m_windowGC, boundingRect.x() + offset.x(), boundingRect.y() + offset.y(), boundingRect.width(), boundingRect.height(), windowBoundingRect.x(), windowBoundingRect.y()); @@ -126,10 +128,30 @@ void QX11GLWindowSurface::setGeometry(const QRect &rect) bool QX11GLWindowSurface::scroll(const QRegion &area, int dx, int dy) { - Q_UNUSED(area); - Q_UNUSED(dx); - Q_UNUSED(dy); - return false; + if (m_backBuffer.isNull()) + return false; + + Q_ASSERT(m_backBuffer.data_ptr()->classId() == QPixmapData::X11Class); + + QX11GLPixmapData* pmd = static_cast(m_backBuffer.data_ptr().data()); + Q_ASSERT(pmd->context()); + pmd->context()->makeCurrent(); + glFinish(); + eglWaitClient(); + + if (!m_pixmapGC) + m_pixmapGC = XCreateGC(X11->display, m_backBuffer.handle(), 0, 0); + + foreach (const QRect& rect, area.rects()) { + XCopyArea(X11->display, m_backBuffer.handle(), m_backBuffer.handle(), m_pixmapGC, + rect.x(), rect.y(), rect.width(), rect.height(), + rect.x()+dx, rect.y()+dy); + } + + XSync(X11->display, False); + eglWaitNative(EGL_CORE_NATIVE_ENGINE); + + return true; } /* diff --git a/src/opengl/qwindowsurface_x11gl_p.h b/src/opengl/qwindowsurface_x11gl_p.h index 90f3ad5..3a952e8 100644 --- a/src/opengl/qwindowsurface_x11gl_p.h +++ b/src/opengl/qwindowsurface_x11gl_p.h @@ -70,7 +70,8 @@ public: bool scroll(const QRegion &area, int dx, int dy); private: - GC m_GC; + GC m_windowGC; + GC m_pixmapGC; QPixmap m_backBuffer; QWidget *m_window; }; -- cgit v0.12 From e8a80a4eac6d0c1802d6e06e51c7ad5427f00ac8 Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Wed, 17 Mar 2010 12:30:52 +0100 Subject: Fix some rendering/scrolling artifacts with QX11GLWindowSurface The GL2 paint engine sometimes adds a 0.49,0.49 offset when rendering into a multi-sampled QGLPaintDevice. The problem was that we weren't updating the QGLContext's QGLFormat with the EGLConfig so the paint engine thought it was rendering into an surface without multisampling and thus added the offset. Reviewed-By: TrustMe --- src/opengl/qpixmapdata_x11gl_egl.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/opengl/qpixmapdata_x11gl_egl.cpp b/src/opengl/qpixmapdata_x11gl_egl.cpp index 2bdfe5c..d3af60f 100644 --- a/src/opengl/qpixmapdata_x11gl_egl.cpp +++ b/src/opengl/qpixmapdata_x11gl_egl.cpp @@ -55,6 +55,7 @@ #endif #include +#include #include "qpixmapdata_x11gl_p.h" @@ -255,6 +256,8 @@ QPaintEngine* QX11GLPixmapData::paintEngine() const ctx = new QGLContext(glFormat()); Q_ASSERT(ctx->d_func()->eglContext == 0); ctx->d_func()->eglContext = hasAlphaChannel() ? argbContext : rgbContext; + // Update the glFormat for the QGLContext: + qt_glformat_from_eglconfig(ctx->d_func()->glFormat, ctx->d_func()->eglContext->config()); } QPaintEngine* engine; @@ -303,6 +306,7 @@ void QX11GLPixmapData::beginPaint() EGLConfig cfg = ctx->d_func()->eglContext->config(); Q_ASSERT(cfg != QEGL_NO_CONFIG); +// qDebug("QX11GLPixmapData - using EGL Config ID %d", ctx->d_func()->eglContext->configAttrib(EGL_CONFIG_ID)); EGLSurface surface = QEgl::createSurface(&tmpPixmap, cfg); if (surface == EGL_NO_SURFACE) { qWarning() << "Error creating EGL surface for pixmap:" << QEgl::errorString(); -- cgit v0.12 From bd8e35f2e0a572d7c98b9c72eacfdeda435b0980 Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Wed, 17 Mar 2010 12:36:15 +0100 Subject: Make QX11GLPixmapData::scroll() return a value Reviewed-By: TrustMe --- src/opengl/qpixmapdata_x11gl_egl.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/opengl/qpixmapdata_x11gl_egl.cpp b/src/opengl/qpixmapdata_x11gl_egl.cpp index d3af60f..3ab385a 100644 --- a/src/opengl/qpixmapdata_x11gl_egl.cpp +++ b/src/opengl/qpixmapdata_x11gl_egl.cpp @@ -231,13 +231,15 @@ bool QX11GLPixmapData::scroll(int dx, int dy, const QRect &rect) eglWaitClient(); } - QX11PixmapData::scroll(dx, dy, rect); + bool success = QX11PixmapData::scroll(dx, dy, rect); XSync(X11->display, False); if (ctx) { ctx->makeCurrent(); eglWaitNative(EGL_CORE_NATIVE_ENGINE); } + + return success; } #if !defined(QT_OPENGL_ES_1) -- cgit v0.12 From e309914b0481201ed46f79f115548ebb22c19018 Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Wed, 17 Mar 2010 13:03:33 +0100 Subject: Make sure XCopyArea has completed before resuming rendering Reviewed-By: TrustMe --- src/opengl/qwindowsurface_x11gl.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/opengl/qwindowsurface_x11gl.cpp b/src/opengl/qwindowsurface_x11gl.cpp index 1061008..7befe03 100644 --- a/src/opengl/qwindowsurface_x11gl.cpp +++ b/src/opengl/qwindowsurface_x11gl.cpp @@ -104,6 +104,12 @@ void QX11GLWindowSurface::flush(QWidget *widget, const QRegion &widgetRegion, co boundingRect.x() + offset.x(), boundingRect.y() + offset.y(), boundingRect.width(), boundingRect.height(), windowBoundingRect.x(), windowBoundingRect.y()); + + QX11GLPixmapData* pmd = static_cast(m_backBuffer.data_ptr().data()); + Q_ASSERT(pmd->context()); + pmd->context()->makeCurrent(); + XSync(X11->display, False); + eglWaitNative(EGL_CORE_NATIVE_ENGINE); } void QX11GLWindowSurface::setGeometry(const QRect &rect) -- cgit v0.12 From b72a2bcf8d813ec6b76eb6cc986408c75a1c96bf Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 17 Mar 2010 15:53:33 +0100 Subject: QTreeView: Remove a lot of useless and slow code. Since commit cd2afafbc9c29393a80d415145c49eb5f439da55, we are always doing full relayout when adding or removing rows. So there is no point of doing the expensive incremental update of the viewItems. This has also the nice side effect to fix QTCREATORBUG-886 (see comment in the task) Reviewed-by: Thierry --- src/gui/itemviews/qtreeview.cpp | 234 ++++----------------------------- src/gui/itemviews/qtreeview_p.h | 7 +- tests/auto/qtreeview/tst_qtreeview.cpp | 2 +- 3 files changed, 29 insertions(+), 214 deletions(-) diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index 4135ba0..ada3936 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -1997,6 +1997,24 @@ QModelIndex QTreeView::indexBelow(const QModelIndex &index) const void QTreeView::doItemsLayout() { Q_D(QTreeView); + if (d->hasRemovedItems) { + //clean the QSet that may contains old (and this invalid) indexes + d->hasRemovedItems = false; + QSet::iterator it = d->expandedIndexes.begin(); + while (it != d->expandedIndexes.constEnd()) { + if (!it->isValid()) + it = d->expandedIndexes.erase(it); + else + ++it; + } + it = d->hiddenIndexes.begin(); + while (it != d->hiddenIndexes.constEnd()) { + if (!it->isValid()) + it = d->hiddenIndexes.erase(it); + else + ++it; + } + } d->viewItems.clear(); // prepare for new layout QModelIndex parent = d->root; if (d->model->hasChildren(parent)) { @@ -2406,24 +2424,6 @@ void QTreeView::reexpand() } /*! - \internal - This function assume that left is a (grand-)child of the parent of left. -*/ -static bool treeViewItemLessThanInInsert(const QTreeViewItem &left, const QTreeViewItem &right) -{ - if (left.level != right.level) { - Q_ASSERT(left.level > right.level); - QModelIndex leftParent = left.index.parent(); - QModelIndex rightParent = right.index.parent(); - // computer parent, don't get - while (leftParent.isValid() && leftParent.parent() != rightParent) - leftParent = leftParent.parent(); - return (leftParent.row() < right.index.row()); - } - return (left.index.row() < right.index.row()); -} - -/*! Informs the view that the rows from the \a start row to the \a end row inclusive have been inserted into the \a parent model item. */ @@ -2452,83 +2452,6 @@ void QTreeView::rowsInserted(const QModelIndex &parent, int start, int end) const int parentItem = d->viewIndex(parent); if (((parentItem != -1) && d->viewItems.at(parentItem).expanded && updatesEnabled()) || (parent == d->root)) { - const uint childLevel = (parentItem == -1) - ? uint(0) : d->viewItems.at(parentItem).level + 1; - const int firstChildItem = parentItem + 1; - const int lastChildItem = firstChildItem + ((parentItem == -1) - ? d->viewItems.count() - : d->viewItems.at(parentItem).total) - 1; - - if (parentRowCount == end + 1 && start > 0) { - //need to Update hasMoreSiblings - int previousRow = start - 1; - QModelIndex previousSibilingModelIndex = d->model->index(previousRow, 0, parent); - bool isHidden = d->isRowHidden(previousSibilingModelIndex); - while (isHidden && previousRow > 0) { - previousRow--; - previousSibilingModelIndex = d->model->index(previousRow, 0, parent); - isHidden = d->isRowHidden(previousSibilingModelIndex); - } - if (!isHidden) { - const int previousSibilling = d->viewIndex(previousSibilingModelIndex); - if(previousSibilling != -1) - d->viewItems[previousSibilling].hasMoreSiblings = true; - } - } - - QVector insertedItems(delta); - for (int i = 0; i < delta; ++i) { - QTreeViewItem &item = insertedItems[i]; - item.index = d->model->index(i + start, 0, parent); - item.parentItem = parentItem; - item.level = childLevel; - item.hasChildren = d->hasVisibleChildren(item.index); - item.hasMoreSiblings = !((i == delta - 1) && (parentRowCount == end +1)); - } - if (d->viewItems.isEmpty()) - d->defaultItemHeight = indexRowSizeHint(insertedItems[0].index); - - int insertPos; - if (lastChildItem < firstChildItem) { // no children - insertPos = firstChildItem; - } else { - // do a binary search to figure out where to insert - QVector::iterator it; - it = qLowerBound(d->viewItems.begin() + firstChildItem, - d->viewItems.begin() + lastChildItem + 1, - insertedItems.at(0), treeViewItemLessThanInInsert); - insertPos = it - d->viewItems.begin(); - - // update stale model indexes of siblings - for (int item = insertPos; item <= lastChildItem; ) { - Q_ASSERT(d->viewItems.at(item).level == childLevel); - const QModelIndex modelIndex = d->viewItems.at(item).index; - //Q_ASSERT(modelIndex.parent() == parent); - d->viewItems[item].index = d->model->index( - modelIndex.row() + delta, modelIndex.column(), parent); - - if (!d->viewItems[item].index.isValid()) { - // Something really bad is happening, a bad model is - // often the cause. We can't optimize in this case :( - qWarning() << "QTreeView::rowsInserted internal representation of the model has been corrupted, resetting."; - doItemsLayout(); - return; - } - - item += d->viewItems.at(item).total + 1; - } - } - - d->insertViewItems(insertPos, delta, insertedItems.at(0)); - if (delta > 1) { - qCopy(insertedItems.begin() + 1, insertedItems.end(), - d->viewItems.begin() + insertPos + 1); - } - - if (parentItem != -1) - d->viewItems[parentItem].hasChildren = true; - d->updateChildCount(parentItem, delta); - d->doDelayedItemsLayout(); } else if ((parentItem != -1) && d->viewItems.at(parentItem).expanded) { d->doDelayedItemsLayout(); @@ -2547,8 +2470,8 @@ void QTreeView::rowsInserted(const QModelIndex &parent, int start, int end) void QTreeView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) { Q_D(QTreeView); - d->rowsRemoved(parent, start, end, false); QAbstractItemView::rowsAboutToBeRemoved(parent, start, end); + d->viewItems.clear(); } /*! @@ -2560,7 +2483,10 @@ void QTreeView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int e void QTreeView::rowsRemoved(const QModelIndex &parent, int start, int end) { Q_D(QTreeView); - d->rowsRemoved(parent, start, end, true); + d->viewItems.clear(); + d->doDelayedItemsLayout(); + d->hasRemovedItems = true; + d->_q_rowsRemoved(parent, start, end); } /*! @@ -3398,7 +3324,7 @@ int QTreeViewPrivate::viewIndex(const QModelIndex &_index) const const int totalCount = viewItems.count(); const QModelIndex index = _index.sibling(_index.row(), 0); const int row = index.row(); - const quint64 internalId = index.internalId(); + const qint64 internalId = index.internalId(); // We start nearest to the lastViewedItem int localCount = qMin(lastViewedItem - 1, totalCount - lastViewedItem); @@ -3751,118 +3677,6 @@ bool QTreeViewPrivate::hasVisibleChildren(const QModelIndex& parent) const return false; } -void QTreeViewPrivate::rowsRemoved(const QModelIndex &parent, - int start, int end, bool after) -{ - // if we are going to do a complete relayout anyway, there is no need to update - if (delayedPendingLayout) { - _q_rowsRemoved(parent, start, end); - return; - } - - const int parentItem = viewIndex(parent); - if ((parentItem != -1) || (parent == root)) { - - const uint childLevel = (parentItem == -1) - ? uint(0) : viewItems.at(parentItem).level + 1; - Q_UNUSED(childLevel); // unused in release mode, used in assert below - - const int firstChildItem = parentItem + 1; - int lastChildItem = firstChildItem + ((parentItem == -1) - ? viewItems.count() - : viewItems.at(parentItem).total) - 1; - - const int delta = end - start + 1; - - int previousSibiling = -1; - int removedCount = 0; - for (int item = firstChildItem; item <= lastChildItem; ) { - Q_ASSERT(viewItems.at(item).level == childLevel); - const QModelIndex modelIndex = viewItems.at(item).index; - //Q_ASSERT(modelIndex.parent() == parent); - const int count = viewItems.at(item).total + 1; - if (modelIndex.row() < start) { - previousSibiling = item; - // not affected by the removal - item += count; - } else if (modelIndex.row() <= end) { - // removed - removeViewItems(item, count); - removedCount += count; - lastChildItem -= count; - } else { - if (after) { - // moved; update the model index - viewItems[item].index = model->index( - modelIndex.row() - delta, modelIndex.column(), parent); - } - item += count; - } - } - - if (previousSibiling != -1 && after && model->rowCount(parent) == start) - viewItems[previousSibiling].hasMoreSiblings = false; - - if (parentItem != -1) { - if (viewItems.at(parentItem).expanded) { - updateChildCount(parentItem, -removedCount); - if (viewItems.at(parentItem).total == 0) - viewItems[parentItem].hasChildren = false; //every children have been removed; - } else if (viewItems[parentItem].hasChildren && !hasVisibleChildren(parent)) { - viewItems[parentItem].hasChildren = false; - } - } - if (after) { - doDelayedItemsLayout(); - } else { - //we have removed items: we should at least update the scroll bar values. - // They are used to determine the item geometry. - updateScrollBars(); - } - } else { - // If an ancestor of root is removed then relayout - QModelIndex idx = root; - while (idx.isValid()) { - idx = idx.parent(); - if (idx == parent) { - doDelayedItemsLayout(); - break; - } - } - } - _q_rowsRemoved(parent, start, end); - - QSet::iterator it = expandedIndexes.begin(); - while (it != expandedIndexes.constEnd()) { - if (!it->isValid()) - it = expandedIndexes.erase(it); - else - ++it; - } - it = hiddenIndexes.begin(); - while (it != hiddenIndexes.constEnd()) { - if (!it->isValid()) - it = hiddenIndexes.erase(it); - else - ++it; - } -} - -void QTreeViewPrivate::updateChildCount(const int parentItem, const int delta) -{ - if ((parentItem != -1) && delta) { - int level = viewItems.at(parentItem).level; - int item = parentItem; - do { - Q_ASSERT(item >= 0); - for ( ; int(viewItems.at(item).level) != level; --item) ; - viewItems[item].total += delta; - --level; - } while (level >= 0); - } -} - - void QTreeViewPrivate::_q_sortIndicatorChanged(int column, Qt::SortOrder order) { model->sort(column, order); diff --git a/src/gui/itemviews/qtreeview_p.h b/src/gui/itemviews/qtreeview_p.h index 48997b7..261af31 100644 --- a/src/gui/itemviews/qtreeview_p.h +++ b/src/gui/itemviews/qtreeview_p.h @@ -91,7 +91,7 @@ public: expandsOnDoubleClick(true), allColumnsShowFocus(false), current(0), spanning(false), animationsEnabled(false), columnResizeTimerID(0), - autoExpandDelay(-1), hoverBranch(-1), geometryRecursionBlock(false) {} + autoExpandDelay(-1), hoverBranch(-1), geometryRecursionBlock(false), hasRemovedItems(false) {} ~QTreeViewPrivate() {} void initialize(); @@ -165,8 +165,6 @@ public: QPair startAndEndColumns(const QRect &rect) const; void updateChildCount(const int parentItem, const int delta); - void rowsRemoved(const QModelIndex &parent, - int start, int end, bool before); void paintAlternatingRowColors(QPainter *painter, QStyleOptionViewItemV4 *option, int y, int bottom) const; @@ -242,6 +240,9 @@ public: // used for blocking recursion when calling setViewportMargins from updateGeometries bool geometryRecursionBlock; + + // If we should clean the set + bool hasRemovedItems; }; QT_END_NAMESPACE diff --git a/tests/auto/qtreeview/tst_qtreeview.cpp b/tests/auto/qtreeview/tst_qtreeview.cpp index e39cf6c..bdc0a0c 100644 --- a/tests/auto/qtreeview/tst_qtreeview.cpp +++ b/tests/auto/qtreeview/tst_qtreeview.cpp @@ -246,7 +246,7 @@ public: fetched(false), rows(0), cols(0), levels(INT_MAX), wrongIndex(false) { init(); } QtTestModel(int _rows, int _cols, QObject *parent = 0): QAbstractItemModel(parent), - rows(_rows), cols(_cols), levels(INT_MAX), wrongIndex(false) { init(); } + fetched(false), rows(_rows), cols(_cols), levels(INT_MAX), wrongIndex(false) { init(); } void init() { decorationsEnabled = false; -- cgit v0.12 From b1fe3626c2406e917b6c858c84e45f12368e969a Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Thu, 18 Mar 2010 14:28:35 +1000 Subject: Add a raw bind() function to QGLBuffer. It is awkward for a Qt application to do the equivalent of glBindBuffer(GL_ARRAY_BUFFER, 0) without knowing the QGLBuffer that was previously bound, or to bind a raw id obtained elsewhere. Resolving the extension is annoying. This change provides a raw low-level version of bind() for directly resolving and calling glBindBuffer() to assist such applications. Reviewed-by: Sarah Smith --- src/opengl/qglbuffer.cpp | 32 ++++++++++++++++++++++++++++++++ src/opengl/qglbuffer.h | 2 ++ 2 files changed, 34 insertions(+) diff --git a/src/opengl/qglbuffer.cpp b/src/opengl/qglbuffer.cpp index 7022a53..2ab7c32 100644 --- a/src/opengl/qglbuffer.cpp +++ b/src/opengl/qglbuffer.cpp @@ -369,6 +369,38 @@ void QGLBuffer::release() const glBindBuffer(d->type, 0); } +#undef ctx + +/*! + Binds a raw \a bufferId to the specified buffer \a type + in the current QGLContext. Returns false if there is + no context current or the GL buffer extension could + not be resolved. + + This function is a direct call to \c{glBindBuffer()} for + use when the caller does not have a QGLBuffer but does + have a raw \a bufferId. It can also be used to release + the current buffer when the caller does not know which + QGLBuffer object is currently bound: + + \code + QGLBuffer::bind(QGLBuffer::VertexBuffer, 0); + \endcode +*/ +bool QGLBuffer::bind(QGLBuffer::Type type, uint bufferId) +{ + const QGLContext *ctx = QGLContext::currentContext(); + if (ctx) { + if (qt_resolve_buffer_extensions(const_cast(ctx))) { + glBindBuffer(GLenum(type), GLuint(bufferId)); + return true; + } + } + return false; +} + +#define ctx d->guard.context() + /*! Returns the GL identifier associated with this buffer; zero if the buffer has not been created. diff --git a/src/opengl/qglbuffer.h b/src/opengl/qglbuffer.h index ecb86e2..a060733 100644 --- a/src/opengl/qglbuffer.h +++ b/src/opengl/qglbuffer.h @@ -97,6 +97,8 @@ public: bool bind() const; void release() const; + static bool bind(QGLBuffer::Type type, uint bufferId); + uint bufferId() const; int size() const; -- cgit v0.12