diff options
30 files changed, 948 insertions, 427 deletions
diff --git a/dist/changes-4.7.0 b/dist/changes-4.7.0 index 92f5244..3504763 100644 --- a/dist/changes-4.7.0 +++ b/dist/changes-4.7.0 @@ -24,6 +24,9 @@ General Improvements - Documentation and Examples +- Support for the GL_EXT_geometry_shader4, aka Geometry Shaders, was added + to QGLShaderProgram. + Third party components ---------------------- diff --git a/src/corelib/tools/qpoint.cpp b/src/corelib/tools/qpoint.cpp index d60087f..9850ee7 100644 --- a/src/corelib/tools/qpoint.cpp +++ b/src/corelib/tools/qpoint.cpp @@ -374,7 +374,7 @@ QDebug operator<<(QDebug dbg, const QPoint &p) { QDebug operator<<(QDebug d, const QPointF &p) { d.nospace() << "QPointF(" << p.x() << ", " << p.y() << ')'; - return d; + return d.space(); } #endif diff --git a/src/gui/dialogs/qdialog.cpp b/src/gui/dialogs/qdialog.cpp index 9ff2ad8..fb0dba4 100644 --- a/src/gui/dialogs/qdialog.cpp +++ b/src/gui/dialogs/qdialog.cpp @@ -648,13 +648,14 @@ void QDialog::contextMenuEvent(QContextMenuEvent *e) while (w && w->whatsThis().size() == 0 && !w->testAttribute(Qt::WA_CustomWhatsThis)) w = w->isWindow() ? 0 : w->parentWidget(); if (w) { - QMenu p(this); - QAction *wt = p.addAction(tr("What's This?")); - if (p.exec(e->globalPos()) == wt) { + QWeakPointer<QMenu> p = new QMenu(this); + QAction *wt = p.data()->addAction(tr("What's This?")); + if (p.data()->exec(e->globalPos()) == wt) { QHelpEvent e(QEvent::WhatsThis, w->rect().center(), w->mapToGlobal(w->rect().center())); QApplication::sendEvent(w, &e); } + delete p.data(); } #endif } diff --git a/src/gui/dialogs/qmessagebox.cpp b/src/gui/dialogs/qmessagebox.cpp index d1b2e3f..ed437ff 100644 --- a/src/gui/dialogs/qmessagebox.cpp +++ b/src/gui/dialogs/qmessagebox.cpp @@ -92,8 +92,8 @@ public: { #ifndef QT_NO_CONTEXTMENU QMenu *menu = createStandardContextMenu(); - menu->exec(e->globalPos()); - delete menu; + menu->setAttribute(Qt::WA_DeleteOnClose); + menu->popup(e->globalPos()); #else Q_UNUSED(e); #endif diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp index d5406cb..dd31834 100644 --- a/src/gui/image/qpnghandler.cpp +++ b/src/gui/image/qpnghandler.cpp @@ -50,8 +50,13 @@ #include <qvariant.h> #include <qvector.h> +#ifdef QT_USE_BUNDLED_LIBPNG +#include <../../3rdparty/libpng/png.h> +#include <../../3rdparty/libpng/pngconf.h> +#else #include <png.h> #include <pngconf.h> +#endif #ifdef Q_OS_WINCE #define CALLBACK_CALL_TYPE __cdecl @@ -162,11 +167,16 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, float scre png_uint_32 height; int bit_depth; int color_type; + png_bytep trans_alpha = 0; + png_color_16p trans_color_p = 0; + int num_trans; + png_colorp palette = 0; + int num_palette; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); if (color_type == PNG_COLOR_TYPE_GRAY) { // Black & White or 8-bit grayscale - if (bit_depth == 1 && info_ptr->channels == 1) { + if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) { png_set_invert_mono(png_ptr); png_read_update_info(png_ptr, info_ptr); if (image.size() != QSize(width, height) || image.format() != QImage::Format_Mono) { @@ -207,20 +217,16 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, float scre int c = i*255/(ncols-1); image.setColor(i, qRgba(c,c,c,0xff)); } - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { -#if PNG_LIBPNG_VER_MAJOR < 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR < 4) - const int g = info_ptr->trans_values.gray; -#else - const int g = info_ptr->trans_color.gray; -#endif + if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_color_p) { + const int g = trans_color_p->gray; if (g < ncols) { image.setColor(g, 0); } } } } else if (color_type == PNG_COLOR_TYPE_PALETTE - && png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE) - && info_ptr->num_palette <= 256) + && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette) + && num_palette <= 256) { // 1-bit and 8-bit color if (bit_depth != 1) @@ -233,29 +239,26 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, float scre if (image.isNull()) return; } - image.setColorCount(info_ptr->num_palette); + png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette); + image.setColorCount(num_palette); int i = 0; - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { - while (i < info_ptr->num_trans) { + if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_alpha) { + while (i < num_trans) { image.setColor(i, qRgba( - info_ptr->palette[i].red, - info_ptr->palette[i].green, - info_ptr->palette[i].blue, -#if PNG_LIBPNG_VER_MAJOR < 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR < 4) - info_ptr->trans[i] -#else - info_ptr->trans_alpha[i] -#endif + palette[i].red, + palette[i].green, + palette[i].blue, + trans_alpha[i] ) ); i++; } } - while (i < info_ptr->num_palette) { + while (i < num_palette) { image.setColor(i, qRgba( - info_ptr->palette[i].red, - info_ptr->palette[i].green, - info_ptr->palette[i].blue, + palette[i].red, + palette[i].green, + palette[i].blue, 0xff ) ); @@ -531,33 +534,36 @@ QImage::Format QPngHandlerPrivate::readImageFormat() QImage::Format format = QImage::Format_Invalid; png_uint_32 width, height; int bit_depth, color_type; - if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY) { + png_colorp palette; + int num_palette; + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); + if (color_type == PNG_COLOR_TYPE_GRAY) { // Black & White or 8-bit grayscale - if (info_ptr->bit_depth == 1 && info_ptr->channels == 1) { + if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) { format = QImage::Format_Mono; - } else if (info_ptr->bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { + } else if (bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { format = QImage::Format_ARGB32; } else { format = QImage::Format_Indexed8; } - } else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE - && png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE) - && info_ptr->num_palette <= 256) + } else if (color_type == PNG_COLOR_TYPE_PALETTE + && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette) + && num_palette <= 256) { // 1-bit and 8-bit color - if (info_ptr->bit_depth != 1) + if (bit_depth != 1) png_set_packing(png_ptr); png_read_update_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); format = bit_depth == 1 ? QImage::Format_Mono : QImage::Format_Indexed8; } else { // 32-bit - if (info_ptr->bit_depth == 16) + if (bit_depth == 16) png_set_strip_16(png_ptr); format = QImage::Format_ARGB32; // Only add filler if no alpha, or we can get 5 channel data. - if (!(info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + if (!(color_type & PNG_COLOR_MASK_ALPHA) && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { // We want 4 bytes, but it isn't an alpha channel format = QImage::Format_RGB32; @@ -648,7 +654,7 @@ static void set_text(const QImage &image, png_structp png_ptr, png_infop info_pt text_ptr[i].text = qstrdup(value.constData()); text_ptr[i].text_length = 0; text_ptr[i].itxt_length = value.size(); - text_ptr[i].lang = "UTF-8"; + text_ptr[i].lang = const_cast<char*>("UTF-8"); text_ptr[i].lang_key = qstrdup(it.key().toUtf8().constData()); #endif ++i; @@ -735,64 +741,51 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image_in, png_set_compression_level(png_ptr, quality); } - if (gamma != 0.0) { - png_set_gAMA(png_ptr, info_ptr, 1.0/gamma); - } - png_set_write_fn(png_ptr, (void*)this, qpiw_write_fn, qpiw_flush_fn); - info_ptr->channels = - (image.depth() == 32) - ? (image.format() == QImage::Format_RGB32 ? 3 : 4) - : 1; - png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(), image.depth() == 1 ? 1 : 8 /* per channel */, image.depth() == 32 ? image.format() == QImage::Format_RGB32 ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGB_ALPHA - : PNG_COLOR_TYPE_PALETTE, 0, 0, 0); + : PNG_COLOR_TYPE_PALETTE, 0, 0, 0); // also sets #channels + if (gamma != 0.0) { + png_set_gAMA(png_ptr, info_ptr, 1.0/gamma); + } - //png_set_sBIT(png_ptr, info_ptr, 8); - info_ptr->sig_bit.red = 8; - info_ptr->sig_bit.green = 8; - info_ptr->sig_bit.blue = 8; + png_color_8 sig_bit; + sig_bit.red = 8; + sig_bit.green = 8; + sig_bit.blue = 8; + sig_bit.alpha = image.hasAlphaChannel() ? 8 : 0; + png_set_sBIT(png_ptr, info_ptr, &sig_bit); if (image.format() == QImage::Format_MonoLSB) png_set_packswap(png_ptr); - png_colorp palette = 0; - png_bytep copy_trans = 0; if (image.colorCount()) { // Paletted - int num_palette = image.colorCount(); - palette = new png_color[num_palette]; - png_set_PLTE(png_ptr, info_ptr, palette, num_palette); - int* trans = new int[num_palette]; + int num_palette = qMin(256, image.colorCount()); + png_color palette[256]; + png_byte trans[256]; int num_trans = 0; for (int i=0; i<num_palette; i++) { - QRgb rgb=image.color(i); - info_ptr->palette[i].red = qRed(rgb); - info_ptr->palette[i].green = qGreen(rgb); - info_ptr->palette[i].blue = qBlue(rgb); - trans[i] = rgb >> 24; + QRgb rgba=image.color(i); + palette[i].red = qRed(rgba); + palette[i].green = qGreen(rgba); + palette[i].blue = qBlue(rgba); + trans[i] = qAlpha(rgba); if (trans[i] < 255) { num_trans = i+1; } } + png_set_PLTE(png_ptr, info_ptr, palette, num_palette); + if (num_trans) { - copy_trans = new png_byte[num_trans]; - for (int i=0; i<num_trans; i++) - copy_trans[i] = trans[i]; - png_set_tRNS(png_ptr, info_ptr, copy_trans, num_trans, 0); + png_set_tRNS(png_ptr, info_ptr, trans, num_trans, 0); } - delete [] trans; - } - - if (image.format() != QImage::Format_RGB32) { - info_ptr->sig_bit.alpha = 8; } // Swap ARGB to RGBA (normal PNG format) before saving on @@ -868,11 +861,6 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image_in, png_write_end(png_ptr, info_ptr); frames_written++; - if (palette) - delete [] palette; - if (copy_trans) - delete [] copy_trans; - png_destroy_write_struct(&png_ptr, &info_ptr); return true; @@ -958,7 +946,8 @@ QVariant QPngHandler::option(ImageOption option) const else if (option == Description) return d->description; else if (option == Size) - return QSize(d->info_ptr->width, d->info_ptr->height); + return QSize(png_get_image_width(d->png_ptr, d->info_ptr), + png_get_image_height(d->png_ptr, d->info_ptr)); else if (option == ImageFormat) return d->readImageFormat(); return 0; diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp index b42f95a..f345cd1 100644 --- a/src/gui/text/qtextcontrol.cpp +++ b/src/gui/text/qtextcontrol.cpp @@ -1764,8 +1764,8 @@ void QTextControlPrivate::contextMenuEvent(const QPoint &screenPos, const QPoint QMenu *menu = q->createStandardContextMenu(docPos, contextWidget); if (!menu) return; - menu->exec(screenPos); - delete menu; + menu->setAttribute(Qt::WA_DeleteOnClose); + menu->popup(screenPos); #endif } diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index b8c9b94..80931c9 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -436,6 +436,23 @@ void QTextDocument::redo(QTextCursor *cursor) } /*! + \since 4.7 + Clears the specified stacks. + + This method clears any commands on the undo stack, the redo stack, or both (the + default). If any commands got cleared, the appropriate signals + (\a QTextDocument::undoAvailable or \a QTextDocument::redoAvailable) get + emitted. + + \sa QTextDocument::undoAvailable QTextDocument::redoAvailable +*/ +void QTextDocument::clearUndoRedoStacks(Stacks stacksToClear) +{ + Q_D(QTextDocument); + d->clearUndoRedoStacks(stacksToClear, true); +} + +/*! \overload */ diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h index b5bcb41..0140772 100644 --- a/src/gui/text/qtextdocument.h +++ b/src/gui/text/qtextdocument.h @@ -256,6 +256,13 @@ public: void undo(QTextCursor *cursor); void redo(QTextCursor *cursor); + enum Stacks { + UndoStack = 0x01, + RedoStack = 0x02, + UndoAndRedoStacks = UndoStack | RedoStack + }; + void clearUndoRedoStacks(Stacks historyToClear = UndoAndRedoStacks); + int maximumBlockCount() const; void setMaximumBlockCount(int maximum); diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp index 372b9dc..e2fdf0e 100644 --- a/src/gui/text/qtextdocument_p.cpp +++ b/src/gui/text/qtextdocument_p.cpp @@ -260,7 +260,7 @@ void QTextDocumentPrivate::clear() title.clear(); undoState = 0; - truncateUndoStack(); + clearUndoRedoStacks(QTextDocument::RedoStack); text = QString(); unreachableCharacterCount = 0; modifiedState = 0; @@ -292,7 +292,7 @@ QTextDocumentPrivate::~QTextDocumentPrivate() cursors.clear(); undoState = 0; undoEnabled = true; - truncateUndoStack(); + clearUndoRedoStacks(QTextDocument::RedoStack); } void QTextDocumentPrivate::setLayout(QAbstractTextDocumentLayout *layout) @@ -1027,7 +1027,7 @@ void QTextDocumentPrivate::appendUndoItem(const QTextUndoCommand &c) if (!undoEnabled) return; if (undoState < undoStack.size()) - truncateUndoStack(); + clearUndoRedoStacks(QTextDocument::RedoStack); if (!undoStack.isEmpty() && modified) { QTextUndoCommand &last = undoStack[undoState - 1]; @@ -1050,26 +1050,46 @@ void QTextDocumentPrivate::appendUndoItem(const QTextUndoCommand &c) emit document()->undoCommandAdded(); } -void QTextDocumentPrivate::truncateUndoStack() +void QTextDocumentPrivate::clearUndoRedoStacks(QTextDocument::Stacks stacksToClear, + bool emitSignals) { - if (undoState == undoStack.size()) - return; - - for (int i = undoState; i < undoStack.size(); ++i) { - QTextUndoCommand c = undoStack[i]; - if (c.command & QTextUndoCommand::Removed) { - // ######## -// QTextFragment *f = c.fragment_list; -// while (f) { -// QTextFragment *n = f->right; -// delete f; -// f = n; -// } - } else if (c.command & QTextUndoCommand::Custom) { - delete c.custom; + bool undoCommandsAvailable = undoState != 0; + bool redoCommandsAvailable = undoState != undoStack.size(); + if (stacksToClear == QTextDocument::UndoStack && undoCommandsAvailable) { + for (int i = 0; i < undoState; ++i) { + QTextUndoCommand c = undoStack[undoState]; + if (c.command & QTextUndoCommand::Custom) + delete c.custom; + } + undoStack.remove(0, undoState); + undoStack.resize(undoStack.size() - undoState); + undoState = 0; + if (emitSignals) + emitUndoAvailable(false); + } else if (stacksToClear == QTextDocument::RedoStack + && redoCommandsAvailable) { + for (int i = undoState; i < undoStack.size(); ++i) { + QTextUndoCommand c = undoStack[i]; + if (c.command & QTextUndoCommand::Custom) + delete c.custom; + } + undoStack.resize(undoState); + if (emitSignals) + emitRedoAvailable(false); + } else if (stacksToClear == QTextDocument::UndoAndRedoStacks + && (undoCommandsAvailable || redoCommandsAvailable)) { + for (int i = 0; i < undoStack.size(); ++i) { + QTextUndoCommand c = undoStack[i]; + if (c.command & QTextUndoCommand::Custom) + delete c.custom; } + undoState = 0; + undoStack.resize(0); + if (emitSignals && undoCommandsAvailable) + emitUndoAvailable(false); + if (emitSignals && redoCommandsAvailable) + emitRedoAvailable(false); } - undoStack.resize(undoState); } void QTextDocumentPrivate::emitUndoAvailable(bool available) @@ -1097,7 +1117,7 @@ void QTextDocumentPrivate::enableUndoRedo(bool enable) if (!enable) { undoState = 0; - truncateUndoStack(); + clearUndoRedoStacks(QTextDocument::RedoStack); emitUndoAvailable(false); emitRedoAvailable(false); } diff --git a/src/gui/text/qtextdocument_p.h b/src/gui/text/qtextdocument_p.h index 4ecc2fa..ac5ed3c 100644 --- a/src/gui/text/qtextdocument_p.h +++ b/src/gui/text/qtextdocument_p.h @@ -252,10 +252,11 @@ public: inline QFont defaultFont() const { return formats.defaultFont(); } inline void setDefaultFont(const QFont &f) { formats.setDefaultFont(f); } + void clearUndoRedoStacks(QTextDocument::Stacks stacksToClear, bool emitSignals = false); + private: bool split(int pos); bool unite(uint f); - void truncateUndoStack(); void insert_string(int pos, uint strPos, uint length, int format, QTextUndoCommand::Operation op); int insert_block(int pos, uint strPos, int format, int blockformat, QTextUndoCommand::Operation op, int command); diff --git a/src/gui/widgets/qdockarealayout.cpp b/src/gui/widgets/qdockarealayout.cpp index d754800..13f31df 100644 --- a/src/gui/widgets/qdockarealayout.cpp +++ b/src/gui/widgets/qdockarealayout.cpp @@ -220,15 +220,17 @@ static quintptr tabId(const QDockAreaLayoutItem &item) } #endif +static const int zero = 0; + QDockAreaLayoutInfo::QDockAreaLayoutInfo() - : sep(0), dockPos(QInternal::LeftDock), o(Qt::Horizontal), mainWindow(0) + : sep(&zero), dockPos(QInternal::LeftDock), o(Qt::Horizontal), mainWindow(0) #ifndef QT_NO_TABBAR , tabbed(false), tabBar(0), tabBarShape(QTabBar::RoundedSouth), tabBarVisible(false) #endif { } -QDockAreaLayoutInfo::QDockAreaLayoutInfo(int _sep, QInternal::DockPosition _dockPos, +QDockAreaLayoutInfo::QDockAreaLayoutInfo(const int *_sep, QInternal::DockPosition _dockPos, Qt::Orientation _o, int tbshape, QMainWindow *window) : sep(_sep), dockPos(_dockPos), o(_o), mainWindow(window) @@ -281,7 +283,7 @@ QSize QDockAreaLayoutInfo::minimumSize() const #endif { if (!first) - a += sep; + a += *sep; a += pick(o, min_size); } b = qMax(b, perp(o, min_size)); @@ -349,7 +351,7 @@ QSize QDockAreaLayoutInfo::maximumSize() const #endif { if (!first) - a += sep; + a += *sep; a += pick(o, max_size); } b = qMin(b, perp(o, max_size)); @@ -415,7 +417,7 @@ QSize QDockAreaLayoutInfo::sizeHint() const { if (previous && !gap && !(previous->flags & QDockAreaLayoutItem::GapItem) && !previous->hasFixedSize(o)) { - a += sep; + a += *sep; } a += gap ? item.size : pick(o, size_hint); } @@ -491,7 +493,7 @@ static int realMinSize(const QDockAreaLayoutInfo &info) min = pick(info.o, item.minimumSize()); if (!first) - result += info.sep; + result += *info.sep; result += min; first = false; @@ -516,7 +518,7 @@ static int realMaxSize(const QDockAreaLayoutInfo &info) max = pick(info.o, item.maximumSize()); if (!first) - result += info.sep; + result += *info.sep; result += max; if (result >= QWIDGETSIZE_MAX) @@ -555,7 +557,7 @@ void QDockAreaLayoutInfo::fitItems() if (!(previous->flags & QDockAreaLayoutItem::GapItem)) { QLayoutStruct &ls = layout_struct_list[j++]; ls.init(); - ls.minimumSize = ls.maximumSize = ls.sizeHint = previous->hasFixedSize(o) ? 0 : sep; + ls.minimumSize = ls.maximumSize = ls.sizeHint = previous->hasFixedSize(o) ? 0 : *sep; ls.empty = false; } } @@ -938,7 +940,7 @@ int QDockAreaLayoutInfo::separatorMove(int index, int delta) if (item.skip()) { ls.empty = true; } else { - const int separatorSpace = item.hasFixedSize(o) ? 0 : sep; + const int separatorSpace = item.hasFixedSize(o) ? 0 : *sep; ls.empty = false; ls.pos = item.pos; ls.size = item.size + separatorSpace; @@ -956,7 +958,7 @@ int QDockAreaLayoutInfo::separatorMove(int index, int delta) if (item.skip()) continue; QLayoutStruct &ls = list[i]; - const int separatorSpace = item.hasFixedSize(o) ? 0 : sep; + const int separatorSpace = item.hasFixedSize(o) ? 0 : *sep; item.size = ls.size - separatorSpace; item.pos = ls.pos; if (item.subinfo != 0) { @@ -1041,11 +1043,11 @@ QLayoutItem *QDockAreaLayoutInfo::plug(const QList<int> &path) int next = this->next(index); if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) { - item.pos += sep; - item.size -= sep; + item.pos += *sep; + item.size -= *sep; } if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem)) - item.size -= sep; + item.size -= *sep; QPoint pos; rpick(o, pos) = item.pos; @@ -1083,11 +1085,11 @@ QLayoutItem *QDockAreaLayoutInfo::unplug(const QList<int> &path) #endif { if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) { - item.pos -= sep; - item.size += sep; + item.pos -= *sep; + item.size += *sep; } if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem)) - item.size += sep; + item.size += *sep; } return item.widgetItem; @@ -1255,9 +1257,9 @@ bool QDockAreaLayoutInfo::insertGap(const QList<int> &path, QLayoutItem *dockWid QRect r = dockedGeometry(dockWidgetItem->widget()); gap_size = pick(o, r.size()); if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) - sep_size += sep; + sep_size += *sep; if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem)) - sep_size += sep; + sep_size += *sep; } if (gap_size + sep_size > space) gap_size = pick(o, gap_item.minimumSize()); @@ -1364,7 +1366,7 @@ QRect QDockAreaLayoutInfo::separatorRect(int index) const QPoint pos = rect.topLeft(); rpick(o, pos) = item.pos + item.size; QSize s = rect.size(); - rpick(o, s) = sep; + rpick(o, s) = *sep; return QRect(pos, s); } @@ -1413,7 +1415,7 @@ QList<int> QDockAreaLayoutInfo::findSeparator(const QPoint &_pos) const continue; QRect sepRect = separatorRect(i); - if (!sepRect.isNull() && sep == 1) + if (!sepRect.isNull() && *sep == 1) sepRect.adjust(-2, -2, 2, 2); //we also make sure we don't find a separator that's not there if (sepRect.contains(_pos) && !item.hasFixedSize(o)) { @@ -1560,7 +1562,7 @@ void QDockAreaLayoutInfo::apply(bool animate) } } #ifndef QT_NO_TABBAR - if (sep == 1) + if (*sep == 1) updateSeparatorWidgets(); #endif //QT_NO_TABBAR } @@ -2010,7 +2012,7 @@ bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*> updateTabBar(); setCurrentTabId(tabId(item_list.at(index))); } - if (!testing && sep == 1) + if (!testing && *sep == 1) updateSeparatorWidgets(); #endif @@ -2273,13 +2275,13 @@ QDockAreaLayout::QDockAreaLayout(QMainWindow *win) : fallbackToSizeHints(true) const int tabShape = 0; #endif docks[QInternal::LeftDock] - = QDockAreaLayoutInfo(sep, QInternal::LeftDock, Qt::Vertical, tabShape, win); + = QDockAreaLayoutInfo(&sep, QInternal::LeftDock, Qt::Vertical, tabShape, win); docks[QInternal::RightDock] - = QDockAreaLayoutInfo(sep, QInternal::RightDock, Qt::Vertical, tabShape, win); + = QDockAreaLayoutInfo(&sep, QInternal::RightDock, Qt::Vertical, tabShape, win); docks[QInternal::TopDock] - = QDockAreaLayoutInfo(sep, QInternal::TopDock, Qt::Horizontal, tabShape, win); + = QDockAreaLayoutInfo(&sep, QInternal::TopDock, Qt::Horizontal, tabShape, win); docks[QInternal::BottomDock] - = QDockAreaLayoutInfo(sep, QInternal::BottomDock, Qt::Horizontal, tabShape, win); + = QDockAreaLayoutInfo(&sep, QInternal::BottomDock, Qt::Horizontal, tabShape, win); centralWidgetItem = 0; @@ -3028,7 +3030,7 @@ void QDockAreaLayout::addDockWidget(QInternal::DockPosition pos, QDockWidget *do #else int tbshape = 0; #endif - QDockAreaLayoutInfo new_info(sep, pos, orientation, tbshape, mainWindow); + QDockAreaLayoutInfo new_info(&sep, pos, orientation, tbshape, mainWindow); new_info.item_list.append(new QDockAreaLayoutInfo(info)); new_info.item_list.append(dockWidgetItem); info = new_info; @@ -3324,6 +3326,12 @@ void QDockAreaLayout::keepSize(QDockWidget *w) item.flags |= QDockAreaLayoutItem::KeepSize; } +void QDockAreaLayout::styleChangedEvent() +{ + sep = mainWindow->style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent, 0, mainWindow); + fitLayout(); +} + QT_END_NAMESPACE #endif // QT_NO_DOCKWIDGET diff --git a/src/gui/widgets/qdockarealayout_p.h b/src/gui/widgets/qdockarealayout_p.h index 0bc1aa9..0088f00 100644 --- a/src/gui/widgets/qdockarealayout_p.h +++ b/src/gui/widgets/qdockarealayout_p.h @@ -128,7 +128,7 @@ class Q_AUTOTEST_EXPORT QDockAreaLayoutInfo { public: QDockAreaLayoutInfo(); - QDockAreaLayoutInfo(int _sep, QInternal::DockPosition _dockPos, Qt::Orientation _o, + QDockAreaLayoutInfo(const int *_sep, QInternal::DockPosition _dockPos, Qt::Orientation _o, int tbhape, QMainWindow *window); QSize minimumSize() const; @@ -189,7 +189,7 @@ public: QMainWindowLayout *mainWindowLayout() const; - int sep; + const int *sep; mutable QVector<QWidget*> separatorWidgets; QInternal::DockPosition dockPos; Qt::Orientation o; @@ -300,6 +300,7 @@ public: QSet<QTabBar*> usedTabBars() const; QSet<QWidget*> usedSeparatorWidgets() const; #endif //QT_NO_TABBAR + void styleChangedEvent(); }; QT_END_NAMESPACE diff --git a/src/gui/widgets/qlabel.cpp b/src/gui/widgets/qlabel.cpp index c779312..b81f04f 100644 --- a/src/gui/widgets/qlabel.cpp +++ b/src/gui/widgets/qlabel.cpp @@ -951,8 +951,8 @@ void QLabel::contextMenuEvent(QContextMenuEvent *ev) return; } ev->accept(); - menu->exec(ev->globalPos()); - delete menu; + menu->setAttribute(Qt::WA_DeleteOnClose); + menu->popup(ev->globalPos()); #endif } diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index 2d2df92..141f844 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -2046,9 +2046,9 @@ void QLineEdit::dropEvent(QDropEvent* e) */ void QLineEdit::contextMenuEvent(QContextMenuEvent *event) { - QPointer<QMenu> menu = createStandardContextMenu(); - menu->exec(event->globalPos()); - delete menu; + QMenu *menu = createStandardContextMenu(); + menu->setAttribute(Qt::WA_DeleteOnClose); + menu->popup(event->globalPos()); } #if defined(Q_WS_WIN) diff --git a/src/gui/widgets/qmainwindow.cpp b/src/gui/widgets/qmainwindow.cpp index 269cd12..a63f3bf 100644 --- a/src/gui/widgets/qmainwindow.cpp +++ b/src/gui/widgets/qmainwindow.cpp @@ -1393,6 +1393,7 @@ bool QMainWindow::event(QEvent *event) #endif // QT_NO_STATUSTIP case QEvent::StyleChange: + d->layout->layoutState.dockAreaLayout.styleChangedEvent(); if (!d->explicitIconSize) setIconSize(QSize()); break; @@ -1554,11 +1555,15 @@ void QMainWindow::contextMenuEvent(QContextMenuEvent *event) #ifndef QT_NO_MENU QMenu *popup = createPopupMenu(); - if (popup && !popup->isEmpty()) { - popup->exec(event->globalPos()); - event->accept(); + if (popup) { + if (!popup->isEmpty()) { + popup->setAttribute(Qt::WA_DeleteOnClose); + popup->popup(event->globalPos()); + event->accept(); + } else { + delete popup; + } } - delete popup; #endif } #endif // QT_NO_CONTEXTMENU diff --git a/src/opengl/qglextensions.cpp b/src/opengl/qglextensions.cpp index 03fca39..02d5501 100644 --- a/src/opengl/qglextensions.cpp +++ b/src/opengl/qglextensions.cpp @@ -224,6 +224,12 @@ bool qt_resolve_buffer_extensions(QGLContext *ctx) bool qt_resolve_glsl_extensions(QGLContext *ctx) { + // Geometry shaders are optional... + glProgramParameteriEXT = (_glProgramParameteriEXT) ctx->getProcAddress(QLatin1String("glProgramParameteriEXT")); + glFramebufferTextureEXT = (_glFramebufferTextureEXT) ctx->getProcAddress(QLatin1String("glFramebufferTextureEXT")); + glFramebufferTextureLayerEXT = (_glFramebufferTextureLayerEXT) ctx->getProcAddress(QLatin1String("glFramebufferTextureLayerEXT")); + glFramebufferTextureFaceEXT = (_glFramebufferTextureFaceEXT) ctx->getProcAddress(QLatin1String("glFramebufferTextureFaceEXT")); + #if defined(QT_OPENGL_ES_2) // The GLSL shader functions are always present in OpenGL/ES 2.0. // The only exceptions are glGetProgramBinaryOES and glProgramBinaryOES. diff --git a/src/opengl/qglextensions_p.h b/src/opengl/qglextensions_p.h index 116dfa6..f6613fd 100644 --- a/src/opengl/qglextensions_p.h +++ b/src/opengl/qglextensions_p.h @@ -197,6 +197,15 @@ typedef void (APIENTRY *_glBlitFramebufferEXT) (int srcX0, int srcY0, int srcX1, typedef void (APIENTRY *_glRenderbufferStorageMultisampleEXT) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +// GL_EXT_geometry_shader4 +typedef void (APIENTRY *_glProgramParameteriEXT)(GLuint program, GLenum pname, GLint value); +typedef void (APIENTRY *_glFramebufferTextureEXT)(GLenum target, GLenum attachment, + GLuint texture, GLint level); +typedef void (APIENTRY *_glFramebufferTextureLayerEXT)(GLenum target, GLenum attachment, + GLuint texture, GLint level, GLint layer); +typedef void (APIENTRY *_glFramebufferTextureFaceEXT)(GLenum target, GLenum attachment, + GLuint texture, GLint level, GLenum face); + // ARB_texture_compression typedef void (APIENTRY *_glCompressedTexImage2DARB) (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *); @@ -310,6 +319,10 @@ struct QGLExtensionFuncs qt_glMapBufferARB = 0; qt_glUnmapBufferARB = 0; + qt_glProgramParameteriEXT = 0; + qt_glFramebufferTextureEXT = 0; + qt_glFramebufferTextureLayerEXT = 0; + qt_glFramebufferTextureFaceEXT = 0; #if !defined(QT_OPENGL_ES) // Texture compression qt_glCompressedTexImage2DARB = 0; @@ -425,6 +438,11 @@ struct QGLExtensionFuncs _glMapBufferARB qt_glMapBufferARB; _glUnmapBufferARB qt_glUnmapBufferARB; + // Geometry shaders... + _glProgramParameteriEXT qt_glProgramParameteriEXT; + _glFramebufferTextureEXT qt_glFramebufferTextureEXT; + _glFramebufferTextureLayerEXT qt_glFramebufferTextureLayerEXT; + _glFramebufferTextureFaceEXT qt_glFramebufferTextureFaceEXT; #if !defined(QT_OPENGL_ES) // Texture compression _glCompressedTexImage2DARB qt_glCompressedTexImage2DARB; @@ -661,6 +679,29 @@ struct QGLExtensionFuncs #define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A #endif +// Geometry shader defines +#ifndef GL_GEOMETRY_SHADER_EXT +# define GL_GEOMETRY_SHADER_EXT 0x8DD9 +# define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA +# define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB +# define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC +# define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29 +# define GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD +# define GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE +# define GL_MAX_VARYING_COMPONENTS_EXT 0x8B4B +# define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF +# define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0 +# define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1 +# define GL_LINES_ADJACENCY_EXT 0xA +# define GL_LINE_STRIP_ADJACENCY_EXT 0xB +# define GL_TRIANGLES_ADJACENCY_EXT 0xC +# define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0xD +# define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8 +# define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9 +# define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7 +# define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4 +# define GL_PROGRAM_POINT_SIZE_EXT 0x8642 +#endif #if !defined(QT_OPENGL_ES_2) #define glProgramStringARB QGLContextPrivate::extensionFuncs(ctx).qt_glProgramStringARB @@ -781,6 +822,11 @@ struct QGLExtensionFuncs #define glClearDepth glClearDepthf #endif +#define glProgramParameteriEXT QGLContextPrivate::extensionFuncs(ctx).qt_glProgramParameteriEXT +#define glFramebufferTextureEXT QGLContextPrivate::extensionFuncs(ctx).qt_glFramebufferTextureEXT +#define glFramebufferTextureLayerEXT QGLContextPrivate::extensionFuncs(ctx).qt_glFramebufferTextureLayerEXT +#define glFramebufferTextureFaceEXT QGLContextPrivate::extensionFuncs(ctx).qt_glFramebufferTextureFaceEXT + #if !defined(QT_OPENGL_ES) #define glCompressedTexImage2D QGLContextPrivate::extensionFuncs(ctx).qt_glCompressedTexImage2DARB #endif diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp index 8fd4acf..170b650 100644 --- a/src/opengl/qglshaderprogram.cpp +++ b/src/opengl/qglshaderprogram.cpp @@ -143,6 +143,8 @@ QT_BEGIN_NAMESPACE \value Vertex Vertex shader written in the OpenGL Shading Language (GLSL). \value Fragment Fragment shader written in the OpenGL Shading Language (GLSL). + \value Geometry Geometry shaders written in the OpenGL Shading + Language (GLSL), based on the GL_EXT_geometry_shader4 extension. */ #ifndef GL_FRAGMENT_SHADER @@ -226,6 +228,8 @@ bool QGLShaderPrivate::create() GLuint shader; if (shaderType == QGLShader::Vertex) shader = glCreateShader(GL_VERTEX_SHADER); + else if (shaderType == QGLShader::Geometry) + shader = glCreateShader(GL_GEOMETRY_SHADER_EXT); else shader = glCreateShader(GL_FRAGMENT_SHADER); if (!shader) { @@ -509,6 +513,10 @@ GLuint QGLShader::shaderId() const return d->shaderGuard.id(); } + + + + #undef ctx #define ctx programGuard.context() @@ -521,8 +529,9 @@ public: , linked(false) , inited(false) , removingShaders(false) - , vertexShader(0) - , fragmentShader(0) + , geometryVertexCount(64) + , geometryInputType(0) + , geometryOutputType(0) { } ~QGLShaderProgramPrivate(); @@ -531,11 +540,14 @@ public: bool linked; bool inited; bool removingShaders; + + int geometryVertexCount; + GLenum geometryInputType; + GLenum geometryOutputType; + QString log; QList<QGLShader *> shaders; QList<QGLShader *> anonShaders; - QGLShader *vertexShader; - QGLShader *fragmentShader; bool hasShader(QGLShader::ShaderType type) const; }; @@ -604,6 +616,7 @@ bool QGLShaderProgram::init() context = QGLContext::currentContext(); d->programGuard.setContext(context); } + if (!context) return false; if (qt_resolve_glsl_extensions(const_cast<QGLContext *>(context))) { @@ -831,6 +844,7 @@ bool QGLShaderProgram::link() GLuint program = d->programGuard.id(); if (!program) return false; + GLint value; if (d->shaders.isEmpty()) { // If there are no explicit shaders, then it is possible that the @@ -843,6 +857,22 @@ bool QGLShaderProgram::link() if (d->linked) return true; } + + // Set up the geometry shader parameters + if (glProgramParameteriEXT) { + foreach (QGLShader *shader, d->shaders) { + if (shader->shaderType() & QGLShader::Geometry) { + glProgramParameteriEXT(program, GL_GEOMETRY_INPUT_TYPE_EXT, + d->geometryInputType); + glProgramParameteriEXT(program, GL_GEOMETRY_OUTPUT_TYPE_EXT, + d->geometryOutputType); + glProgramParameteriEXT(program, GL_GEOMETRY_VERTICES_OUT_EXT, + d->geometryVertexCount); + break; + } + } + } + glLinkProgram(program); value = 0; glGetProgramiv(program, GL_LINK_STATUS, &value); @@ -3047,6 +3077,97 @@ void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x4 * #undef ctx /*! + Returns the hardware limit for how many vertices a geometry shader + can output. + + \sa setGeometryShaderOutputVertexCount +*/ +int QGLShaderProgram::maxGeometryOutputVertices() const +{ + int n; + glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT, &n); + return n; +} + + + +/*! + Sets the maximum number of vertices the current geometry shader + program will produce, if active. + + This parameter takes effect the next time the program is linked. +*/ +void QGLShaderProgram::setGeometryOutputVertexCount(int count) +{ +#ifndef QT_NO_DEBUG + int max = maxGeometryOutputVertices(); + if (count > max) { + qWarning("QGLShaderProgram::setGeometryOutputVertexCount: count: %d higher than maximum: %d", + count, max); + } +#endif + d_func()->geometryVertexCount = count; +} + + +/*! + Returns the maximum number of vertices the current geometry shader + program will produce, if active. + + This parameter takes effect the ntext time the program is linked. +*/ +int QGLShaderProgram::geometryOutputVertexCount() const +{ + return d_func()->geometryVertexCount; +} + + +/*! + Sets the output type from the geometry shader, if active. + + This parameter takes effect the next time the program is linked. +*/ +void QGLShaderProgram::setGeometryInputType(GLenum inputType) +{ + d_func()->geometryInputType = inputType; +} + + +/*! + Returns the geometry shader input type, if active. + + This parameter takes effect the next time the program is linked. + */ + +GLenum QGLShaderProgram::geometryInputType() const +{ + return d_func()->geometryInputType; +} + + +/*! + Sets the output type from the geometry shader, if active. + + This parameter takes effect the next time the program is linked. +*/ +void QGLShaderProgram::setGeometryOutputType(GLenum outputType) +{ + d_func()->geometryOutputType = outputType; +} + + +/*! + Returns the geometry shader output type, if active. + + This parameter takes effect the next time the program is linked. + */ +GLenum QGLShaderProgram::geometryOutputType() const +{ + return d_func()->geometryOutputType; +} + + +/*! Returns true if shader programs written in the OpenGL Shading Language (GLSL) are supported on this system; false otherwise. @@ -3078,6 +3199,39 @@ void QGLShaderProgram::shaderDestroyed() removeShader(shader); } + +#undef ctx +#undef context + +/*! + Returns true if shader programs of type \a type are supported on + this system; false otherwise. + + The \a context is used to resolve the GLSL extensions. + If \a context is null, then QGLContext::currentContext() is used. +*/ +bool QGLShader::hasOpenGLShaders(ShaderType type, const QGLContext *context) +{ + if (!context) + context = QGLContext::currentContext(); + if (!context) + return false; + + if ((type & ~(Geometry | Vertex | Fragment)) || type == 0) + return false; + + bool resolved = qt_resolve_glsl_extensions(const_cast<QGLContext *>(context)); + if (!resolved) + return false; + + if ((type & Geometry) && !QByteArray((const char *) glGetString(GL_EXTENSIONS)).contains("GL_EXT_geometry_shader4")) + return false; + + return true; +} + + + #ifdef Q_MAC_COMPAT_GL_FUNCTIONS /*! \internal */ void QGLShaderProgram::setAttributeArray diff --git a/src/opengl/qglshaderprogram.h b/src/opengl/qglshaderprogram.h index 19ce9f2..d612b05 100644 --- a/src/opengl/qglshaderprogram.h +++ b/src/opengl/qglshaderprogram.h @@ -66,7 +66,8 @@ public: enum ShaderTypeBit { Vertex = 0x0001, - Fragment = 0x0002 + Fragment = 0x0002, + Geometry = 0x0004 }; Q_DECLARE_FLAGS(ShaderType, ShaderTypeBit) @@ -88,6 +89,8 @@ public: GLuint shaderId() const; + static bool hasOpenGLShaders(ShaderType type, const QGLContext *context = 0); + private: friend class QGLShaderProgram; @@ -100,6 +103,14 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QGLShader::ShaderType) class QGLShaderProgramPrivate; +#ifndef GL_EXT_geometry_shader4 +# define GL_LINES_ADJACENCY_EXT 0xA +# define GL_LINE_STRIP_ADJACENCY_EXT 0xB +# define GL_TRIANGLES_ADJACENCY_EXT 0xC +# define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0xD +#endif + + class Q_OPENGL_EXPORT QGLShaderProgram : public QObject { Q_OBJECT @@ -128,6 +139,17 @@ public: GLuint programId() const; + int maxGeometryOutputVertices() const; + + void setGeometryOutputVertexCount(int count); + int geometryOutputVertexCount() const; + + void setGeometryInputType(GLenum inputType); + GLenum geometryInputType() const; + + void setGeometryOutputType(GLenum outputType); + GLenum geometryOutputType() const; + void bindAttributeLocation(const char *name, int location); void bindAttributeLocation(const QByteArray& name, int location); void bindAttributeLocation(const QString& name, int location); diff --git a/tests/auto/qdoublevalidator/tst_qdoublevalidator.cpp b/tests/auto/qdoublevalidator/tst_qdoublevalidator.cpp index 37dd6d8..26890b3 100644 --- a/tests/auto/qdoublevalidator/tst_qdoublevalidator.cpp +++ b/tests/auto/qdoublevalidator/tst_qdoublevalidator.cpp @@ -68,7 +68,7 @@ void tst_QDoubleValidator::validateThouSep_data() QTest::addColumn<QString>("value"); QTest::addColumn<QValidator::State>("result"); - QTest::newRow("1,000C") << "C" << QString("1,000") << INV; + QTest::newRow("1,000C") << "C" << QString("1,000") << ACC; QTest::newRow("1.000C") << "C" << QString("1.000") << ACC; QTest::newRow("1,000de") << "de" << QString("1,000") << ACC; @@ -160,9 +160,9 @@ void tst_QDoubleValidator::validate_data() QTest::newRow("data_de0") << "de" << 0.0 << 100.0 << 1 << QString("50,0") << ACC << ACC; QTest::newRow("data_de1") << "de" << 00.0 << 100.0 << 1 << QString("500,0") << ITM << ITM; QTest::newRow("data_de1a") << "de" << 00.0 << 100.0 << 1 << QString("5001,0") << ITM << INV; - QTest::newRow("data_de0C") << "de" << 0.0 << 100.0 << 1 << QString("50.0") << ACC << ACC; - QTest::newRow("data_de1C") << "de" << 00.0 << 100.0 << 1 << QString("500.0") << ITM << ITM; - QTest::newRow("data_de1aC") << "de" << 00.0 << 100.0 << 1 << QString("5001.0") << ITM << INV; + QTest::newRow("data_de0C") << "de" << 0.0 << 100.0 << 1 << QString("50,0") << ACC << ACC; + QTest::newRow("data_de1C") << "de" << 00.0 << 100.0 << 1 << QString("500,0") << ITM << ITM; + QTest::newRow("data_de1aC") << "de" << 00.0 << 100.0 << 1 << QString("5001,0") << ITM << INV; QTest::newRow("data_de2") << "de" << 00.0 << 100.0 << 1 << QString("-35,0") << INV << INV; QTest::newRow("data_de3") << "de" << 00.0 << 100.0 << 1 << QString("a") << INV << INV; QTest::newRow("data_de4") << "de" << 0.0 << 100.0 << 1 << QString("-") << INV << INV; @@ -172,7 +172,7 @@ void tst_QDoubleValidator::validate_data() QTest::newRow("data_de8") << "de" << -100.0 << 100.0 << 1 << QString("-100") << ACC << ACC; QTest::newRow("data_de9") << "de" << -100.0 << -10.0 << 1 << QString("10") << ITM << ITM; QTest::newRow("data_de10") << "de" << 0.3 << 0.5 << 5 << QString("0,34567") << ACC << ACC; - QTest::newRow("data_de11") << "de" << -0.3 << -0.5 << 5 << QString("-0,345678") << INV << INV; + QTest::newRow("data_de11") << "de" << -0.3 << -0.5 << 5 << QString("-0,345678") << ITM << INV; QTest::newRow("data_de12") << "de" << -0.32 << 0.32 << 1 << QString("0") << ACC << ACC; QTest::newRow("data_de13") << "de" << 0.0 << 100.0 << 1 << QString("3456a") << INV << INV; QTest::newRow("data_de14") << "de" << -100.0 << 100.0 << 1 << QString("-3456a") << INV << INV; diff --git a/tests/auto/qlabel/tst_qlabel.cpp b/tests/auto/qlabel/tst_qlabel.cpp index 7099917..153149e7 100644 --- a/tests/auto/qlabel/tst_qlabel.cpp +++ b/tests/auto/qlabel/tst_qlabel.cpp @@ -121,6 +121,10 @@ private slots: void mnemonic(); void selection(); +#ifndef QT_NO_CONTEXTMENU + void taskQTBUG_7902_contextMenuCrash(); +#endif + private: QLabel *testWidget; QPointer<Widget> test_box; @@ -582,5 +586,25 @@ void tst_QLabel::selection() QCOMPARE(label.selectionStart(), 6); } +#ifndef QT_NO_CONTEXTMENU +void tst_QLabel::taskQTBUG_7902_contextMenuCrash() +{ + QLabel *w = new QLabel("Test or crash?"); + w->setTextInteractionFlags(Qt::TextSelectableByMouse); + w->show(); + QTest::qWaitForWindowShown(w); + + QTimer ti; + w->connect(&ti, SIGNAL(timeout()), w, SLOT(deleteLater())); + ti.start(300); + + QContextMenuEvent *cme = new QContextMenuEvent(QContextMenuEvent::Mouse, w->rect().center()); + qApp->postEvent(w, cme); + + QTest::qWait(350); + // No crash, it's allright. +} +#endif + QTEST_MAIN(tst_QLabel) #include "tst_qlabel.moc" diff --git a/tests/auto/qlineedit/tst_qlineedit.cpp b/tests/auto/qlineedit/tst_qlineedit.cpp index 7283916..fcca58a 100644 --- a/tests/auto/qlineedit/tst_qlineedit.cpp +++ b/tests/auto/qlineedit/tst_qlineedit.cpp @@ -271,6 +271,9 @@ private slots: void taskQTBUG_4401_enterKeyClearsPassword(); void taskQTBUG_4679_moveToStartEndOfBlock(); void taskQTBUG_4679_selectToStartEndOfBlock(); +#ifndef QT_NO_CONTEXTMENU + void taskQTBUG_7902_contextMenuCrash(); +#endif protected slots: #ifdef QT3_SUPPORT @@ -3638,5 +3641,25 @@ void tst_QLineEdit::taskQTBUG_4679_selectToStartEndOfBlock() #endif // Q_OS_MAC } +#ifndef QT_NO_CONTEXTMENU +void tst_QLineEdit::taskQTBUG_7902_contextMenuCrash() +{ + // Would pass before the associated commit, but left as a guard. + QLineEdit *w = new QLineEdit; + w->show(); + QTest::qWaitForWindowShown(w); + + QTimer ti; + w->connect(&ti, SIGNAL(timeout()), w, SLOT(deleteLater())); + ti.start(200); + + QContextMenuEvent *cme = new QContextMenuEvent(QContextMenuEvent::Mouse, w->rect().center()); + qApp->postEvent(w, cme); + + QTest::qWait(300); + // No crash, it's allright. +} +#endif + QTEST_MAIN(tst_QLineEdit) #include "tst_qlineedit.moc" diff --git a/tests/auto/qmainwindow/tst_qmainwindow.cpp b/tests/auto/qmainwindow/tst_qmainwindow.cpp index b1c44be..1273e85 100644 --- a/tests/auto/qmainwindow/tst_qmainwindow.cpp +++ b/tests/auto/qmainwindow/tst_qmainwindow.cpp @@ -108,6 +108,7 @@ private slots: void addToolbarAfterShow(); void centralWidgetSize(); void dockWidgetSize(); + void QTBUG2774_stylechange(); }; // Testing get/set functions @@ -1709,6 +1710,45 @@ void tst_QMainWindow::dockWidgetSize() } } +void tst_QMainWindow::QTBUG2774_stylechange() +{ + + QMainWindow mw; + QDockWidget *dockw = new QDockWidget(); + mw.addDockWidget(Qt::LeftDockWidgetArea, dockw); + mw.addDockWidget(Qt::LeftDockWidgetArea, new QDockWidget()); + QTextEdit *central = new QTextEdit(&mw); + mw.setCentralWidget(central); + dockw->resize(10,10); + mw.show(); + QTest::qWaitForWindowShown(&mw); + int centralOriginalWidth = central->width(); + + QVERIFY(!mw.isSeparator(QPoint(4, dockw->pos().y() + dockw->size().height() - 3))); + QVERIFY( mw.isSeparator(QPoint(4, dockw->pos().y() + dockw->size().height()))); + QVERIFY(!mw.isSeparator(QPoint(4, dockw->pos().y() + dockw->size().height() + 30))); + + + { + QTest::qWait(1000); + mw.setStyleSheet("QMainWindow::separator { width: 50px; height:50px; }"); + QTest::qWait(5000); + QApplication::processEvents(); + QVERIFY(central->width() < centralOriginalWidth); + QVERIFY( mw.isSeparator(QPoint(4, dockw->pos().y() + dockw->size().height()))); + QVERIFY( mw.isSeparator(QPoint(4, dockw->pos().y() + dockw->size().height() + 49))); + } + + { + mw.setStyleSheet("QMainWindow::separator { width: 0px; height: 0px; }"); + QApplication::processEvents(); + QVERIFY(central->width() > centralOriginalWidth); + QVERIFY(!mw.isSeparator(QPoint(4, dockw->pos().y() + dockw->size().height()))); + QVERIFY(!mw.isSeparator(QPoint(4, dockw->pos().y() + dockw->size().height() + 1))); + } +} + + QTEST_MAIN(tst_QMainWindow) #include "tst_qmainwindow.moc" diff --git a/tests/auto/qtextedit/tst_qtextedit.cpp b/tests/auto/qtextedit/tst_qtextedit.cpp index deb9379..101baa5 100644 --- a/tests/auto/qtextedit/tst_qtextedit.cpp +++ b/tests/auto/qtextedit/tst_qtextedit.cpp @@ -201,6 +201,9 @@ private slots: void noWrapBackgrounds(); void preserveCharFormatAfterUnchangingSetPosition(); void twoSameInputMethodEvents(); +#ifndef QT_NO_CONTEXTMENU + void taskQTBUG_7902_contextMenuCrash(); +#endif private: void createSelection(); @@ -2202,5 +2205,24 @@ void tst_QTextEdit::twoSameInputMethodEvents() QCOMPARE(ed->document()->firstBlock().layout()->lineCount(), 1); } +#ifndef QT_NO_CONTEXTMENU +void tst_QTextEdit::taskQTBUG_7902_contextMenuCrash() +{ + QTextEdit *w = new QTextEdit; + w->show(); + QTest::qWaitForWindowShown(w); + + QTimer ti; + w->connect(&ti, SIGNAL(timeout()), w, SLOT(deleteLater())); + ti.start(200); + + QContextMenuEvent *cme = new QContextMenuEvent(QContextMenuEvent::Mouse, w->rect().center()); + qApp->postEvent(w->viewport(), cme); + + QTest::qWait(300); + // No crash, it's allright. +} +#endif + QTEST_MAIN(tst_QTextEdit) #include "tst_qtextedit.moc" diff --git a/tools/assistant/tools/assistant/assistant.pro b/tools/assistant/tools/assistant/assistant.pro index e62d30c..edaf076 100644 --- a/tools/assistant/tools/assistant/assistant.pro +++ b/tools/assistant/tools/assistant/assistant.pro @@ -25,6 +25,7 @@ HEADERS += aboutdialog.h \ centralwidget.h \ cmdlineparser.h \ contentwindow.h \ + findwidget.h \ filternamedialog.h \ helpenginewrapper.h \ helpviewer.h \ @@ -50,6 +51,7 @@ SOURCES += aboutdialog.cpp \ centralwidget.cpp \ cmdlineparser.cpp \ contentwindow.cpp \ + findwidget.cpp \ filternamedialog.cpp \ helpenginewrapper.cpp \ helpviewer.cpp \ diff --git a/tools/assistant/tools/assistant/centralwidget.cpp b/tools/assistant/tools/assistant/centralwidget.cpp index 8bb2ffe..03af06c 100644 --- a/tools/assistant/tools/assistant/centralwidget.cpp +++ b/tools/assistant/tools/assistant/centralwidget.cpp @@ -41,34 +41,26 @@ #include "tracer.h" #include "centralwidget.h" +#include "findwidget.h" #include "helpenginewrapper.h" #include "helpviewer.h" #include "searchwidget.h" #include "mainwindow.h" -#include "preferencesdialog.h" #include "../shared/collectionconfiguration.h" -#include <QtCore/QDir> -#include <QtCore/QEvent> #include <QtCore/QTimer> -#include <QtGui/QMenu> -#include <QtGui/QLabel> +#include <QtGui/QApplication> +#include <QtGui/QKeyEvent> #include <QtGui/QLayout> +#include <QtGui/QMenu> #include <QtGui/QPrinter> -#include <QtGui/QLineEdit> -#include <QtGui/QCheckBox> #include <QtGui/QTabBar> #include <QtGui/QTabWidget> #include <QtGui/QToolButton> -#include <QtGui/QMouseEvent> -#include <QtGui/QSpacerItem> -#include <QtGui/QTextCursor> +#include <QtGui/QPageSetupDialog> #include <QtGui/QPrintDialog> -#include <QtGui/QApplication> -#include <QtGui/QTextDocumentFragment> #include <QtGui/QPrintPreviewDialog> -#include <QtGui/QPageSetupDialog> #include <QtHelp/QHelpSearchEngine> @@ -88,135 +80,13 @@ namespace { CentralWidget *staticCentralWidget = 0; } -FindWidget::FindWidget(QWidget *parent) - : QWidget(parent) - , appPalette(qApp->palette()) -{ - TRACE_OBJ - QHBoxLayout *hboxLayout = new QHBoxLayout(this); - QString resourcePath = QLatin1String(":/trolltech/assistant/images/"); - -#ifndef Q_OS_MAC - hboxLayout->setMargin(0); - hboxLayout->setSpacing(6); - resourcePath.append(QLatin1String("win")); -#else - resourcePath.append(QLatin1String("mac")); -#endif - - toolClose = setupToolButton(QLatin1String(""), - resourcePath + QLatin1String("/closetab.png")); - hboxLayout->addWidget(toolClose); - - editFind = new QLineEdit(this); - hboxLayout->addWidget(editFind); - editFind->setMinimumSize(QSize(150, 0)); - connect(editFind, SIGNAL(textChanged(QString)), this, SLOT(updateButtons())); - toolPrevious = setupToolButton(tr("Previous"), - resourcePath + QLatin1String("/previous.png")); - hboxLayout->addWidget(toolPrevious); - - toolNext = setupToolButton(tr("Next"), - resourcePath + QLatin1String("/next.png")); - hboxLayout->addWidget(toolNext); - - checkCase = new QCheckBox(tr("Case Sensitive"), this); - hboxLayout->addWidget(checkCase); - - checkWholeWords = new QCheckBox(tr("Whole words"), this); - hboxLayout->addWidget(checkWholeWords); -#if !defined(QT_NO_WEBKIT) - checkWholeWords->hide(); -#endif - - labelWrapped = new QLabel(this); - labelWrapped->setScaledContents(true); - labelWrapped->setTextFormat(Qt::RichText); - labelWrapped->setMinimumSize(QSize(0, 20)); - labelWrapped->setMaximumSize(QSize(105, 20)); - labelWrapped->setAlignment(Qt::AlignLeading | Qt::AlignLeft | Qt::AlignVCenter); - labelWrapped->setText(tr("<img src=\":/trolltech/assistant/images/wrap.png\"" - "> Search wrapped")); - hboxLayout->addWidget(labelWrapped); - - QSpacerItem *spacerItem = new QSpacerItem(20, 20, QSizePolicy::Expanding, - QSizePolicy::Minimum); - hboxLayout->addItem(spacerItem); - setMinimumWidth(minimumSizeHint().width()); - labelWrapped->hide(); - - updateButtons(); -} - -FindWidget::~FindWidget() -{ - TRACE_OBJ -} - -void FindWidget::hideEvent(QHideEvent* event) -{ - TRACE_OBJ -#if !defined(QT_NO_WEBKIT) - // TODO: remove this once webkit supports setting the palette - if (!event->spontaneous()) - qApp->setPalette(appPalette); -#else - Q_UNUSED(event); -#endif -} - -void FindWidget::showEvent(QShowEvent* event) -{ - TRACE_OBJ -#if !defined(QT_NO_WEBKIT) - // TODO: remove this once webkit supports setting the palette - if (!event->spontaneous()) { - QPalette p = appPalette; - p.setColor(QPalette::Inactive, QPalette::Highlight, - p.color(QPalette::Active, QPalette::Highlight)); - p.setColor(QPalette::Inactive, QPalette::HighlightedText, - p.color(QPalette::Active, QPalette::HighlightedText)); - qApp->setPalette(p); - } -#else - Q_UNUSED(event); -#endif -} - -void FindWidget::updateButtons() -{ - TRACE_OBJ - if (editFind->text().isEmpty()) { - toolPrevious->setEnabled(false); - toolNext->setEnabled(false); - } else { - toolPrevious->setEnabled(true); - toolNext->setEnabled(true); - } -} - -QToolButton* FindWidget::setupToolButton(const QString &text, const QString &icon) -{ - TRACE_OBJ - QToolButton *toolButton = new QToolButton(this); - - toolButton->setText(text); - toolButton->setAutoRaise(true); - toolButton->setIcon(QIcon(icon)); - toolButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - - return toolButton; -} - - -// -- +// -- CentralWidget CentralWidget::CentralWidget(MainWindow *parent) : QWidget(parent) , lastTabPage(0) - , findBar(0) , tabWidget(0) , findWidget(0) , printer(0) @@ -260,20 +130,15 @@ CentralWidget::CentralWidget(MainWindow *parent) vboxLayout->addWidget(tabWidget); - findBar = new QWidget(this); - findWidget = new FindWidget(findBar); - findBar->setMinimumHeight(findWidget->minimumSizeHint().height()); - findWidget->move(0, 0); - vboxLayout->addWidget(findBar); - findBar->hide(); - findWidget->editFind->installEventFilter(this); - - connect(findWidget->toolClose, SIGNAL(clicked()), findBar, SLOT(hide())); - connect(findWidget->toolNext, SIGNAL(clicked()), this, SLOT(findNext())); - connect(findWidget->editFind, SIGNAL(returnPressed()), this, SLOT(findNext())); - connect(findWidget->editFind, SIGNAL(textChanged(QString)), this, - SLOT(findCurrentText(QString))); - connect(findWidget->toolPrevious, SIGNAL(clicked()), this, SLOT(findPrevious())); + findWidget = new FindWidget(this); + vboxLayout->addWidget(findWidget); + findWidget->hide(); + + connect(findWidget, SIGNAL(findNext()), this, SLOT(findNext())); + connect(findWidget, SIGNAL(findPrevious()), this, SLOT(findPrevious())); + connect(findWidget, SIGNAL(find(QString, bool)), this, + SLOT(find(QString, bool))); + connect(findWidget, SIGNAL(escapePressed()), this, SLOT(activateTab())); QTabBar *tabBar = qFindChild<QTabBar*>(tabWidget); if (tabBar) { @@ -360,12 +225,6 @@ void CentralWidget::zoomOut() m_searchWidget->zoomOut(); } -void CentralWidget::findNext() -{ - TRACE_OBJ - find(findWidget->editFind->text(), true); -} - void CentralWidget::nextPage() { TRACE_OBJ @@ -395,12 +254,6 @@ void CentralWidget::previousPage() tabWidget->setCurrentIndex(index); } -void CentralWidget::findPrevious() -{ - TRACE_OBJ - find(findWidget->editFind->text(), false); -} - void CentralWidget::closeTab() { TRACE_OBJ @@ -527,9 +380,7 @@ void CentralWidget::copySelection() void CentralWidget::showTextSearch() { TRACE_OBJ - findBar->show(); - findWidget->editFind->selectAll(); - findWidget->editFind->setFocus(Qt::ShortcutFocusReason); + findWidget->show(); } void CentralWidget::initPrinter() @@ -708,12 +559,6 @@ HelpViewer *CentralWidget::newEmptyTab() return viewer; } -void CentralWidget::findCurrentText(const QString &text) -{ - TRACE_OBJ - find(text, true); -} - void CentralWidget::connectSignals() { TRACE_OBJ @@ -855,14 +700,6 @@ bool CentralWidget::eventFilter(QObject *object, QEvent *e) return QWidget::eventFilter(object, e); } break; - case Qt::Key_Escape: { - if (findWidget->editFind == object) { - findBar->hide(); - if (HelpViewer *viewer = currentHelpViewer()) - viewer->setFocus(); - } - } break; - case Qt::Key_Backspace: { HelpViewer *viewer = currentHelpViewer(); if (viewer == object) { @@ -906,38 +743,43 @@ void CentralWidget::keyPressEvent(QKeyEvent *e) TRACE_OBJ const QString &text = e->text(); if (text.startsWith(QLatin1Char('/'))) { - if (!findBar->isVisible()) { - findBar->show(); - findWidget->editFind->clear(); + if (!findWidget->isVisible()) { + findWidget->showAndClear(); } else { - findWidget->editFind->selectAll(); + findWidget->show(); } - findWidget->editFind->setFocus(); - return; + } else { + QWidget::keyPressEvent(e); } - QWidget::keyPressEvent(e); } -void CentralWidget::find(const QString &ttf, bool forward) +void CentralWidget::findNext() +{ + find(findWidget->text(), true); +} + +void CentralWidget::findPrevious() { TRACE_OBJ - QPalette p = findWidget->editFind->palette(); - p.setColor(QPalette::Active, QPalette::Base, Qt::white); + find(findWidget->text(), false); +} +void CentralWidget::find(const QString &ttf, bool forward) +{ + TRACE_OBJ bool found = false; - #if defined(QT_NO_WEBKIT) found = findInTextBrowser(ttf, forward); #else found = findInWebPage(ttf, forward); #endif - if (!found && !ttf.isEmpty()) - p.setColor(QPalette::Active, QPalette::Base, QColor(255, 102, 102)); + if (!found && ttf.isEmpty()) + found = true; // the line edit is empty, no need to mark it red... if (!findWidget->isVisible()) findWidget->show(); - findWidget->editFind->setPalette(p); + findWidget->setPalette(found); } bool CentralWidget::findInWebPage(const QString &ttf, bool forward) @@ -951,21 +793,23 @@ bool CentralWidget::findInWebPage(const QString &ttf, bool forward) if (!forward) options |= QWebPage::FindBackward; - if (findWidget->checkCase->isChecked()) + if (findWidget->caseSensitive()) options |= QWebPage::FindCaseSensitively; found = viewer->findText(ttf, options); - findWidget->labelWrapped->hide(); + findWidget->setTextWrappedVisible(false); if (!found) { options |= QWebPage::FindWrapsAroundDocument; found = viewer->findText(ttf, options); if (found) - findWidget->labelWrapped->show(); + findWidget->setTextWrappedVisible(true); } } // force highlighting of all other matches, also when empty (clear) options = QWebPage::HighlightAllOccurrences; + if (findWidget->caseSensitive()) + options |= QWebPage::FindCaseSensitively; viewer->findText(QLatin1String(""), options); viewer->findText(ttf, options); return found; @@ -1006,13 +850,10 @@ bool CentralWidget::findInTextBrowser(const QString &ttf, bool forward) if (!forward) options |= QTextDocument::FindBackward; - if (findWidget->checkCase->isChecked()) + if (findWidget->caseSensitive()) options |= QTextDocument::FindCaseSensitively; - if (findWidget->checkWholeWords->isChecked()) - options |= QTextDocument::FindWholeWords; - - findWidget->labelWrapped->hide(); + findWidget->setTextWrappedVisible(false); bool found = true; QTextCursor newCursor = doc->find(ttf, cursor, options); @@ -1025,7 +866,7 @@ bool CentralWidget::findInTextBrowser(const QString &ttf, bool forward) found = false; newCursor = cursor; } else { - findWidget->labelWrapped->show(); + findWidget->setTextWrappedVisible(true); } } browser->setTextCursor(newCursor); @@ -1048,6 +889,11 @@ void CentralWidget::updateBrowserFont() setBrowserFontFor(tabWidget->widget(i), font); } +bool CentralWidget::searchWidgetAttached() const +{ + return m_searchWidget && m_searchWidget->isAttached(); +} + void CentralWidget::createSearchWidget(QHelpSearchEngine *searchEngine) { TRACE_OBJ diff --git a/tools/assistant/tools/assistant/centralwidget.h b/tools/assistant/tools/assistant/centralwidget.h index a7c0d6f..6c3e93c 100644 --- a/tools/assistant/tools/assistant/centralwidget.h +++ b/tools/assistant/tools/assistant/centralwidget.h @@ -38,72 +38,20 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ - #ifndef CENTRALWIDGET_H #define CENTRALWIDGET_H -#include <QtCore/QList> #include <QtCore/QUrl> -#include <QtCore/QPoint> -#include <QtCore/QObject> - #include <QtGui/QWidget> -#include "searchwidget.h" - QT_BEGIN_NAMESPACE -class QEvent; -class QLabel; -class QAction; -class QCheckBox; -class QLineEdit; -class QTextBrowser; -class QToolButton; - +class FindWidget; class HelpViewer; -class QTabWidget; -class QHelpEngine; -class CentralWidget; -class PrintHelper; class MainWindow; - class QHelpSearchEngine; - -class FindWidget : public QWidget -{ - Q_OBJECT - -public: - FindWidget(QWidget *parent = 0); - ~FindWidget(); - -signals: - void findNext(); - void findPrevious(); - -protected: - void hideEvent(QHideEvent* event); - void showEvent(QShowEvent * event); - -private slots: - void updateButtons(); - -private: - QToolButton* setupToolButton(const QString &text, const QString &icon); - -private: - QLineEdit *editFind; - QCheckBox *checkCase; - QLabel *labelWrapped; - QToolButton *toolNext; - QToolButton *toolClose; - QToolButton *toolPrevious; - QCheckBox *checkWholeWords; - - QPalette appPalette; - friend class CentralWidget; -}; +class QTabWidget; +class SearchWidget; class CentralWidget : public QWidget { @@ -123,11 +71,8 @@ public: QList<QAction*> globalActions() const; void setGlobalActions(const QList<QAction*> &actions); HelpViewer *currentHelpViewer() const; - void activateTab(bool onlyHelpViewer = false); - bool searchWidgetAttached() const { - return m_searchWidget && m_searchWidget->isAttached(); - } + bool searchWidgetAttached() const; void createSearchWidget(QHelpSearchEngine *searchEngine); void activateSearchWidget(bool updateLastTabPage = false); void removeSearchWidget(); @@ -144,11 +89,9 @@ public: public slots: void zoomIn(); void zoomOut(); - void findNext(); void nextPage(); void resetZoom(); void previousPage(); - void findPrevious(); void copySelection(); void showTextSearch(); void print(); @@ -157,12 +100,17 @@ public slots: void updateBrowserFont(); void setSource(const QUrl &url); void setSourceInNewTab(const QUrl &url, qreal zoom = 0.0); - void findCurrentText(const QString &text); HelpViewer *newEmptyTab(); void home(); void forward(); void backward(); + void activateTab(bool onlyHelpViewer = false); + + void findNext(); + void findPrevious(); + void find(const QString &text, bool forward); + signals: void currentViewerChanged(); void copyAvailable(bool yes); @@ -189,7 +137,6 @@ private slots: private: void connectSignals(); bool eventFilter(QObject *object, QEvent *e); - void find(const QString &ttf, bool forward); bool findInWebPage(const QString &ttf, bool forward); bool findInTextBrowser(const QString &ttf, bool forward); void initPrinter(); @@ -203,7 +150,6 @@ private: int lastTabPage; QList<QAction*> globalActionList; - QWidget *findBar; QTabWidget *tabWidget; FindWidget *findWidget; QPrinter *printer; diff --git a/tools/assistant/tools/assistant/findwidget.cpp b/tools/assistant/tools/assistant/findwidget.cpp new file mode 100644 index 0000000..2e40ab0 --- /dev/null +++ b/tools/assistant/tools/assistant/findwidget.cpp @@ -0,0 +1,233 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "tracer.h" +#include "findwidget.h" + +#include <QtGui/QApplication> +#include <QtGui/QCheckBox> +#include <QtGui/QHideEvent> +#include <QtGui/QKeyEvent> +#include <QtGui/QLabel> +#include <QtGui/QLayout> +#include <QtGui/QLineEdit> +#include <QtGui/QToolButton> + +QT_BEGIN_NAMESPACE + +FindWidget::FindWidget(QWidget *parent) + : QWidget(parent) + , appPalette(qApp->palette()) +{ + TRACE_OBJ + installEventFilter(this); + QHBoxLayout *hboxLayout = new QHBoxLayout(this); + QString resourcePath = QLatin1String(":/trolltech/assistant/images/"); + +#ifndef Q_OS_MAC + hboxLayout->setMargin(0); + hboxLayout->setSpacing(6); + resourcePath.append(QLatin1String("win")); +#else + resourcePath.append(QLatin1String("mac")); +#endif + + toolClose = setupToolButton(QLatin1String(""), + resourcePath + QLatin1String("/closetab.png")); + hboxLayout->addWidget(toolClose); + + editFind = new QLineEdit(this); + hboxLayout->addWidget(editFind); + editFind->setMinimumSize(QSize(150, 0)); + connect(editFind, SIGNAL(textChanged(QString)), this, + SLOT(textChanged(QString))); + connect(editFind, SIGNAL(returnPressed()), this, SIGNAL(findNext())); + connect(editFind, SIGNAL(textChanged(QString)), this, SLOT(updateButtons())); + + toolPrevious = setupToolButton(tr("Previous"), + resourcePath + QLatin1String("/previous.png")); + connect(toolPrevious, SIGNAL(clicked()), this, SIGNAL(findPrevious())); + + hboxLayout->addWidget(toolPrevious); + + toolNext = setupToolButton(tr("Next"), + resourcePath + QLatin1String("/next.png")); + hboxLayout->addWidget(toolNext); + connect(toolNext, SIGNAL(clicked()), this, SIGNAL(findNext())); + + checkCase = new QCheckBox(tr("Case Sensitive"), this); + hboxLayout->addWidget(checkCase); + + labelWrapped = new QLabel(this); + labelWrapped->setScaledContents(true); + labelWrapped->setTextFormat(Qt::RichText); + labelWrapped->setMinimumSize(QSize(0, 20)); + labelWrapped->setMaximumSize(QSize(105, 20)); + labelWrapped->setAlignment(Qt::AlignLeading | Qt::AlignLeft | Qt::AlignVCenter); + labelWrapped->setText(tr("<img src=\":/trolltech/assistant/images/wrap.png\"" + "> Search wrapped")); + hboxLayout->addWidget(labelWrapped); + + QSpacerItem *spacerItem = new QSpacerItem(20, 20, QSizePolicy::Expanding, + QSizePolicy::Minimum); + hboxLayout->addItem(spacerItem); + setMinimumWidth(minimumSizeHint().width()); + labelWrapped->hide(); + + updateButtons(); +} + +FindWidget::~FindWidget() +{ + TRACE_OBJ +} + +void FindWidget::show() +{ + TRACE_OBJ + QWidget::show(); + editFind->selectAll(); + editFind->setFocus(Qt::ShortcutFocusReason); +} + +void FindWidget::showAndClear() +{ + TRACE_OBJ + show(); + editFind->clear(); +} + +QString FindWidget::text() const +{ + TRACE_OBJ + return editFind->text(); +} + +bool FindWidget::caseSensitive() const +{ + TRACE_OBJ + return checkCase->isChecked(); +} + +void FindWidget::setPalette(bool found) +{ + TRACE_OBJ + QPalette palette = editFind->palette(); + palette.setColor(QPalette::Active, QPalette::Base, found ? Qt::white + : QColor(255, 102, 102)); + editFind->setPalette(palette); +} + +void FindWidget::setTextWrappedVisible(bool visible) +{ + TRACE_OBJ + labelWrapped->setVisible(visible); +} + +void FindWidget::hideEvent(QHideEvent* event) +{ + TRACE_OBJ +#if !defined(QT_NO_WEBKIT) + // TODO: remove this once webkit supports setting the palette + if (!event->spontaneous()) + qApp->setPalette(appPalette); +#else + Q_UNUSED(event); +#endif +} + +void FindWidget::showEvent(QShowEvent* event) +{ + TRACE_OBJ +#if !defined(QT_NO_WEBKIT) + // TODO: remove this once webkit supports setting the palette + if (!event->spontaneous()) { + QPalette p = appPalette; + p.setColor(QPalette::Inactive, QPalette::Highlight, + p.color(QPalette::Active, QPalette::Highlight)); + p.setColor(QPalette::Inactive, QPalette::HighlightedText, + p.color(QPalette::Active, QPalette::HighlightedText)); + qApp->setPalette(p); + } +#else + Q_UNUSED(event); +#endif +} + +void FindWidget::updateButtons() +{ + TRACE_OBJ + const bool enable = !editFind->text().isEmpty(); + toolNext->setEnabled(enable); + toolPrevious->setEnabled(enable); +} + +void FindWidget::textChanged(const QString &text) +{ + TRACE_OBJ + emit find(text, true); +} + +bool FindWidget::eventFilter(QObject *object, QEvent *e) +{ + TRACE_OBJ + if (e->type() == QEvent::KeyPress) { + if ((static_cast<QKeyEvent*>(e))->key() == Qt::Key_Escape) { + hide(); + emit escapePressed(); + } + } + return QWidget::eventFilter(object, e); +} + +QToolButton* FindWidget::setupToolButton(const QString &text, const QString &icon) +{ + TRACE_OBJ + QToolButton *toolButton = new QToolButton(this); + + toolButton->setText(text); + toolButton->setAutoRaise(true); + toolButton->setIcon(QIcon(icon)); + toolButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + + return toolButton; +} + +QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/findwidget.h b/tools/assistant/tools/assistant/findwidget.h new file mode 100644 index 0000000..cf78003 --- /dev/null +++ b/tools/assistant/tools/assistant/findwidget.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef FINDWIDGET_H +#define FINDWIDGET_H + +#include <QtGui/QWidget> + +QT_BEGIN_NAMESPACE + +class QCheckBox; +class QLabel; +class QLineEdit; +class QToolButton; + +class FindWidget : public QWidget +{ + Q_OBJECT +public: + FindWidget(QWidget *parent = 0); + ~FindWidget(); + + void show(); + void showAndClear(); + + QString text() const; + bool caseSensitive() const; + + void setPalette(bool found); + void setTextWrappedVisible(bool visible); + +signals: + void escapePressed(); + + void findNext(); + void findPrevious(); + void find(const QString &text, bool forward); + +protected: + void hideEvent(QHideEvent* event); + void showEvent(QShowEvent * event); + +private slots: + void updateButtons(); + void textChanged(const QString &text); + +private: + bool eventFilter(QObject *object, QEvent *e); + QToolButton* setupToolButton(const QString &text, const QString &icon); + +private: + QPalette appPalette; + + QLineEdit *editFind; + QCheckBox *checkCase; + QLabel *labelWrapped; + QToolButton *toolNext; + QToolButton *toolClose; + QToolButton *toolPrevious; +}; + +QT_END_NAMESPACE + +#endif // FINDWIDGET_H diff --git a/tools/assistant/tools/assistant/helpenginewrapper.cpp b/tools/assistant/tools/assistant/helpenginewrapper.cpp index ddc056a..76211c5 100644 --- a/tools/assistant/tools/assistant/helpenginewrapper.cpp +++ b/tools/assistant/tools/assistant/helpenginewrapper.cpp @@ -103,7 +103,7 @@ private: HelpEngineWrapperPrivate(const QString &collectionFile); void initFileSystemWatchers(); - void assertDocFilesWatched(); + void checkDocFilesWatched(); void qchFileChanged(const QString &fileName, bool fromTimeout); static const int UpdateGracePeriod = 2000; @@ -202,23 +202,23 @@ const QString HelpEngineWrapper::collectionFile() const bool HelpEngineWrapper::registerDocumentation(const QString &docFile) { TRACE_OBJ - d->assertDocFilesWatched(); + d->checkDocFilesWatched(); if (!d->m_helpEngine->registerDocumentation(docFile)) return false; d->m_qchWatcher->addPath(docFile); - d->assertDocFilesWatched(); + d->checkDocFilesWatched(); return true; } bool HelpEngineWrapper::unregisterDocumentation(const QString &namespaceName) { TRACE_OBJ - d->assertDocFilesWatched(); + d->checkDocFilesWatched(); const QString &file = d->m_helpEngine->documentationFileName(namespaceName); if (!d->m_helpEngine->unregisterDocumentation(namespaceName)) return false; d->m_qchWatcher->removePath(file); - d->assertDocFilesWatched(); + d->checkDocFilesWatched(); return true; } @@ -715,7 +715,7 @@ void HelpEngineWrapperPrivate::initFileSystemWatchers() connect(m_qchWatcher, SIGNAL(fileChanged(QString)), this, SLOT(qchFileChanged(QString))); } - assertDocFilesWatched(); + checkDocFilesWatched(); } void HelpEngineWrapperPrivate::qchFileChanged(const QString &fileName) @@ -724,11 +724,15 @@ void HelpEngineWrapperPrivate::qchFileChanged(const QString &fileName) qchFileChanged(fileName, false); } -void HelpEngineWrapperPrivate::assertDocFilesWatched() +void HelpEngineWrapperPrivate::checkDocFilesWatched() { TRACE_OBJ - Q_ASSERT(m_qchWatcher->files().count() - == m_helpEngine->registeredDocumentations().count()); + const int watchedFilesCount = m_qchWatcher->files().count(); + const int docFilesCount = m_helpEngine->registeredDocumentations().count(); + if (watchedFilesCount != docFilesCount) { + qWarning("Strange: Have %d docs, but %d are being watched", + watchedFilesCount, docFilesCount); + } } void HelpEngineWrapperPrivate::qchFileChanged(const QString &fileName, |