summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/dialogs/qabstractprintdialog.cpp7
-rw-r--r--src/gui/dialogs/qabstractprintdialog.h6
-rw-r--r--src/gui/dialogs/qcolordialog.cpp69
-rw-r--r--src/gui/dialogs/qdialog.cpp35
-rw-r--r--src/gui/dialogs/qerrormessage.cpp2
-rw-r--r--src/gui/dialogs/qfiledialog.cpp9
-rw-r--r--src/gui/dialogs/qfiledialog.ui36
-rw-r--r--src/gui/dialogs/qfiledialog_mac.mm27
-rw-r--r--src/gui/dialogs/qfiledialog_win.cpp62
-rw-r--r--src/gui/dialogs/qfiledialog_win_p.h2
-rw-r--r--src/gui/dialogs/qfileinfogatherer.cpp39
-rw-r--r--src/gui/dialogs/qfileinfogatherer_p.h13
-rw-r--r--src/gui/dialogs/qfilesystemmodel.cpp17
-rw-r--r--src/gui/dialogs/qfontdialog.cpp27
-rw-r--r--src/gui/dialogs/qfontdialog_mac.mm395
-rw-r--r--src/gui/dialogs/qfontdialog_p.h12
-rw-r--r--src/gui/dialogs/qmessagebox.cpp65
-rw-r--r--src/gui/dialogs/qprintdialog.h2
-rw-r--r--src/gui/dialogs/qprintdialog_qws.cpp11
-rw-r--r--src/gui/dialogs/qprintdialog_unix.cpp53
-rw-r--r--src/gui/dialogs/qprintdialog_win.cpp18
-rw-r--r--src/gui/dialogs/qprintpreviewdialog.cpp13
-rw-r--r--src/gui/dialogs/qprintsettingsoutput.ui246
-rw-r--r--src/gui/dialogs/qprogressdialog.cpp4
-rw-r--r--src/gui/dialogs/qwizard.cpp205
-rw-r--r--src/gui/dialogs/qwizard.h5
-rw-r--r--src/gui/dialogs/qwizard_win_p.h1
-rw-r--r--src/gui/egl/egl.pri1
-rw-r--r--src/gui/egl/qegl.cpp339
-rw-r--r--src/gui/egl/qegl_p.h179
-rw-r--r--src/gui/egl/qegl_qws.cpp30
-rw-r--r--src/gui/egl/qegl_symbian.cpp48
-rw-r--r--src/gui/egl/qegl_wince.cpp56
-rw-r--r--src/gui/egl/qegl_x11.cpp349
-rw-r--r--src/gui/egl/qeglcontext_p.h119
-rw-r--r--src/gui/egl/qeglproperties.cpp35
-rw-r--r--src/gui/egl/qeglproperties_p.h46
-rw-r--r--src/gui/embedded/directfb.pri2
-rw-r--r--src/gui/embedded/qscreen_qws.cpp2
-rw-r--r--src/gui/embedded/qwsmanager_qws.cpp6
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp441
-rw-r--r--src/gui/graphicsview/qgraphicsitem.h27
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h72
-rw-r--r--src/gui/graphicsview/qgraphicslinearlayout.cpp2
-rw-r--r--src/gui/graphicsview/qgraphicsproxywidget.cpp7
-rw-r--r--src/gui/graphicsview/qgraphicsproxywidget_p.h1
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp67
-rw-r--r--src/gui/graphicsview/qgraphicsscene_p.h4
-rw-r--r--src/gui/graphicsview/qgraphicssceneevent.h10
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp6
-rw-r--r--src/gui/graphicsview/qgraphicswidget.cpp35
-rw-r--r--src/gui/graphicsview/qgraphicswidget.h10
-rw-r--r--src/gui/graphicsview/qgraphicswidget_p.cpp51
-rw-r--r--src/gui/graphicsview/qgraphicswidget_p.h9
-rw-r--r--src/gui/gui.pro14
-rw-r--r--src/gui/image/qicon.cpp4
-rw-r--r--src/gui/image/qiconloader.cpp32
-rw-r--r--src/gui/image/qiconloader_p.h2
-rw-r--r--src/gui/image/qimage.cpp67
-rw-r--r--src/gui/image/qimage.h1
-rw-r--r--src/gui/image/qimagepixmapcleanuphooks.cpp10
-rw-r--r--src/gui/image/qimagereader.cpp2
-rw-r--r--src/gui/image/qimagewriter.cpp1
-rw-r--r--src/gui/image/qpicture.cpp9
-rw-r--r--src/gui/image/qpixmap.cpp25
-rw-r--r--src/gui/image/qpixmap_raster.cpp4
-rw-r--r--src/gui/image/qpixmap_s60.cpp4
-rw-r--r--src/gui/image/qpixmap_x11.cpp4
-rw-r--r--src/gui/image/qpixmap_x11_p.h10
-rw-r--r--src/gui/image/qpixmapfilter.cpp9
-rw-r--r--src/gui/inputmethod/inputmethod.pri2
-rw-r--r--src/gui/inputmethod/qcoefepinputcontext_s60.cpp15
-rw-r--r--src/gui/inputmethod/qinputcontextfactory.cpp47
-rw-r--r--src/gui/inputmethod/qximinputcontext_x11.cpp54
-rw-r--r--src/gui/itemviews/qabstractitemview.cpp31
-rw-r--r--src/gui/itemviews/qabstractitemview_p.h5
-rw-r--r--src/gui/itemviews/qdirmodel.cpp6
-rw-r--r--src/gui/itemviews/qfileiconprovider.cpp6
-rw-r--r--src/gui/itemviews/qheaderview.cpp37
-rw-r--r--src/gui/itemviews/qitemdelegate.cpp14
-rw-r--r--src/gui/itemviews/qitemselectionmodel.cpp88
-rw-r--r--src/gui/itemviews/qitemselectionmodel_p.h2
-rw-r--r--src/gui/itemviews/qlistview.cpp14
-rw-r--r--src/gui/itemviews/qproxymodel.h25
-rw-r--r--src/gui/itemviews/qsortfilterproxymodel.cpp54
-rw-r--r--src/gui/itemviews/qstyleditemdelegate.cpp7
-rw-r--r--src/gui/itemviews/qtableview.cpp68
-rw-r--r--src/gui/itemviews/qtreeview.cpp457
-rw-r--r--src/gui/itemviews/qtreeview_p.h21
-rw-r--r--src/gui/kernel/qapplication.cpp47
-rw-r--r--src/gui/kernel/qapplication.h1
-rw-r--r--src/gui/kernel/qapplication_mac.mm32
-rw-r--r--src/gui/kernel/qapplication_p.h3
-rw-r--r--src/gui/kernel/qapplication_s60.cpp89
-rw-r--r--src/gui/kernel/qapplication_win.cpp48
-rw-r--r--src/gui/kernel/qapplication_x11.cpp90
-rw-r--r--src/gui/kernel/qclipboard.cpp6
-rw-r--r--src/gui/kernel/qclipboard_x11.cpp15
-rw-r--r--src/gui/kernel/qcocoaapplicationdelegate_mac.mm13
-rw-r--r--src/gui/kernel/qcocoamenuloader_mac.mm23
-rw-r--r--src/gui/kernel/qcocoamenuloader_mac_p.h4
-rw-r--r--src/gui/kernel/qcocoasharedwindowmethods_mac_p.h20
-rw-r--r--src/gui/kernel/qcocoaview_mac.mm102
-rw-r--r--src/gui/kernel/qcursor.cpp3
-rw-r--r--src/gui/kernel/qcursor_mac.mm33
-rw-r--r--src/gui/kernel/qcursor_s60.cpp2
-rw-r--r--src/gui/kernel/qcursor_x11.cpp68
-rw-r--r--src/gui/kernel/qdesktopwidget_s60.cpp1
-rw-r--r--src/gui/kernel/qdesktopwidget_win.cpp4
-rw-r--r--src/gui/kernel/qdnd_win.cpp16
-rw-r--r--src/gui/kernel/qdnd_x11.cpp12
-rw-r--r--src/gui/kernel/qeventdispatcher_mac.mm17
-rw-r--r--src/gui/kernel/qeventdispatcher_mac_p.h1
-rw-r--r--src/gui/kernel/qgesture_p.h4
-rw-r--r--src/gui/kernel/qgesturemanager.cpp4
-rw-r--r--src/gui/kernel/qgesturerecognizer.cpp2
-rw-r--r--src/gui/kernel/qgridlayout.cpp2
-rw-r--r--src/gui/kernel/qguifunctions_wince.cpp9
-rw-r--r--src/gui/kernel/qkeymapper_mac.cpp54
-rw-r--r--src/gui/kernel/qkeymapper_p.h2
-rw-r--r--src/gui/kernel/qkeymapper_win.cpp2
-rw-r--r--src/gui/kernel/qkeymapper_x11.cpp47
-rw-r--r--src/gui/kernel/qkeysequence.cpp36
-rw-r--r--src/gui/kernel/qmime_win.cpp12
-rw-r--r--src/gui/kernel/qsoftkeymanager.cpp61
-rw-r--r--src/gui/kernel/qsoftkeymanager_common_p.h3
-rw-r--r--src/gui/kernel/qsoftkeymanager_p.h5
-rw-r--r--src/gui/kernel/qsoftkeymanager_s60.cpp77
-rw-r--r--src/gui/kernel/qsoftkeymanager_s60_p.h3
-rw-r--r--src/gui/kernel/qsound.cpp3
-rw-r--r--src/gui/kernel/qsound_mac.mm1
-rw-r--r--src/gui/kernel/qstandardgestures.cpp7
-rw-r--r--src/gui/kernel/qt_cocoa_helpers_mac.mm60
-rw-r--r--src/gui/kernel/qt_cocoa_helpers_mac_p.h2
-rw-r--r--src/gui/kernel/qt_s60_p.h6
-rw-r--r--src/gui/kernel/qt_x11_p.h11
-rw-r--r--src/gui/kernel/qtooltip.cpp11
-rw-r--r--src/gui/kernel/qwidget.cpp143
-rw-r--r--src/gui/kernel/qwidget.h1
-rw-r--r--src/gui/kernel/qwidget_mac.mm100
-rw-r--r--src/gui/kernel/qwidget_p.h24
-rw-r--r--src/gui/kernel/qwidget_s60.cpp69
-rw-r--r--src/gui/kernel/qwidget_win.cpp6
-rw-r--r--src/gui/kernel/qwidget_wince.cpp4
-rw-r--r--src/gui/kernel/qwidget_x11.cpp90
-rw-r--r--src/gui/kernel/qwinnativepangesturerecognizer_win_p.h32
-rw-r--r--src/gui/kernel/qx11embed_x11.cpp4
-rw-r--r--src/gui/painting/painting.pri16
-rw-r--r--src/gui/painting/qbackingstore.cpp11
-rw-r--r--src/gui/painting/qblendfunctions.cpp446
-rw-r--r--src/gui/painting/qblendfunctions_p.h497
-rw-r--r--src/gui/painting/qbrush.cpp3
-rw-r--r--src/gui/painting/qcolor.cpp21
-rw-r--r--src/gui/painting/qcolormap.qdoc10
-rw-r--r--src/gui/painting/qcups.cpp3
-rw-r--r--src/gui/painting/qdrawhelper.cpp112
-rw-r--r--src/gui/painting/qdrawhelper_neon.cpp409
-rw-r--r--src/gui/painting/qdrawhelper_neon_asm.S192
-rw-r--r--src/gui/painting/qdrawhelper_neon_p.h58
-rw-r--r--src/gui/painting/qdrawhelper_sse2.cpp211
-rw-r--r--src/gui/painting/qdrawhelper_x86_p.h8
-rw-r--r--src/gui/painting/qdrawutil.cpp4
-rw-r--r--src/gui/painting/qgraphicssystem_raster.cpp13
-rw-r--r--src/gui/painting/qmemrotate_p.h3
-rw-r--r--src/gui/painting/qpaintbuffer.cpp326
-rw-r--r--src/gui/painting/qpaintbuffer_p.h8
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp13
-rw-r--r--src/gui/painting/qpaintengineex.cpp23
-rw-r--r--src/gui/painting/qpaintengineex_p.h3
-rw-r--r--src/gui/painting/qpainter.cpp137
-rw-r--r--src/gui/painting/qpainter.h18
-rw-r--r--src/gui/painting/qpainterpath.h2
-rw-r--r--src/gui/painting/qprinter.cpp3
-rw-r--r--src/gui/painting/qprinter.h2
-rw-r--r--src/gui/painting/qregion.cpp40
-rw-r--r--src/gui/painting/qstroker.cpp116
-rw-r--r--src/gui/painting/qtextureglyphcache.cpp32
-rw-r--r--src/gui/painting/qtextureglyphcache_p.h3
-rw-r--r--src/gui/painting/qtransform.cpp15
-rw-r--r--src/gui/painting/qtransform.h7
-rw-r--r--src/gui/painting/qwindowsurface_qws.cpp17
-rw-r--r--src/gui/painting/qwindowsurface_qws_p.h2
-rw-r--r--src/gui/painting/qwindowsurface_s60.cpp29
-rw-r--r--src/gui/s60framework/qs60mainapplication.cpp7
-rw-r--r--src/gui/s60framework/qs60mainappui.cpp10
-rw-r--r--src/gui/s60framework/qs60maindocument.h2
-rw-r--r--src/gui/s60framework/s60framework.pri7
-rw-r--r--src/gui/styles/qcommonstyle.cpp2
-rw-r--r--src/gui/styles/qgtkpainter.cpp2
-rw-r--r--src/gui/styles/qgtkstyle.cpp208
-rw-r--r--src/gui/styles/qgtkstyle_p.cpp122
-rw-r--r--src/gui/styles/qgtkstyle_p.h91
-rw-r--r--src/gui/styles/qmacstyle_mac.mm14
-rw-r--r--src/gui/styles/qplastiquestyle.cpp5
-rw-r--r--src/gui/styles/qs60style.cpp250
-rw-r--r--src/gui/styles/qs60style.h10
-rw-r--r--src/gui/styles/qs60style_p.h15
-rw-r--r--src/gui/styles/qs60style_s60.cpp46
-rw-r--r--src/gui/styles/qstylehelper.cpp65
-rw-r--r--src/gui/styles/qstylesheetstyle.cpp17
-rw-r--r--src/gui/styles/qwindowsmobilestyle.cpp54
-rw-r--r--src/gui/styles/qwindowsstyle.cpp10
-rw-r--r--src/gui/styles/qwindowsstyle_p.h4
-rw-r--r--src/gui/styles/qwindowsvistastyle_p.h1
-rw-r--r--src/gui/styles/styles.pri24
-rw-r--r--src/gui/text/qfont.cpp8
-rw-r--r--src/gui/text/qfont.h23
-rw-r--r--src/gui/text/qfont_s60.cpp4
-rw-r--r--src/gui/text/qfontdatabase_qws.cpp7
-rw-r--r--src/gui/text/qfontdatabase_s60.cpp9
-rw-r--r--src/gui/text/qfontdatabase_x11.cpp8
-rw-r--r--src/gui/text/qfontengine.cpp15
-rw-r--r--src/gui/text/qfontengine_ft.cpp72
-rw-r--r--src/gui/text/qfontengine_ft_p.h16
-rw-r--r--src/gui/text/qfontengine_mac.mm102
-rw-r--r--src/gui/text/qfontengine_p.h3
-rw-r--r--src/gui/text/qfontengine_qpf.cpp14
-rw-r--r--src/gui/text/qfontengine_s60.cpp30
-rw-r--r--src/gui/text/qfontengine_s60_p.h2
-rw-r--r--src/gui/text/qfontengine_win.cpp31
-rw-r--r--src/gui/text/qfontengine_win_p.h4
-rw-r--r--src/gui/text/qfontmetrics.cpp39
-rw-r--r--src/gui/text/qstatictext.cpp178
-rw-r--r--src/gui/text/qstatictext.h8
-rw-r--r--src/gui/text/qstatictext_p.h13
-rw-r--r--src/gui/text/qsyntaxhighlighter.cpp95
-rw-r--r--src/gui/text/qtextcontrol.cpp21
-rw-r--r--src/gui/text/qtextcontrol_p.h3
-rw-r--r--src/gui/text/qtextdocument_p.cpp2
-rw-r--r--src/gui/text/qtextengine.cpp22
-rw-r--r--src/gui/text/qtextengine_p.h1
-rw-r--r--src/gui/text/qtextformat.cpp3
-rw-r--r--src/gui/text/qtextlayout.cpp137
-rw-r--r--src/gui/text/qtextlayout.h1
-rw-r--r--src/gui/text/qzip.cpp44
-rw-r--r--src/gui/text/qzipreader_p.h5
-rw-r--r--src/gui/text/qzipwriter_p.h2
-rw-r--r--src/gui/util/qcompleter.cpp4
-rw-r--r--src/gui/util/qdesktopservices_s60.cpp4
-rw-r--r--src/gui/util/qsystemtrayicon_mac.mm4
-rw-r--r--src/gui/util/util.pri9
-rw-r--r--src/gui/widgets/qabstractslider.cpp18
-rw-r--r--src/gui/widgets/qabstractslider_p.h3
-rw-r--r--src/gui/widgets/qabstractspinbox.cpp5
-rw-r--r--src/gui/widgets/qcheckbox.cpp2
-rw-r--r--src/gui/widgets/qcombobox.cpp60
-rw-r--r--src/gui/widgets/qcombobox.h4
-rw-r--r--src/gui/widgets/qcombobox_p.h2
-rw-r--r--src/gui/widgets/qdockarealayout.cpp22
-rw-r--r--src/gui/widgets/qeffects.cpp6
-rw-r--r--src/gui/widgets/qlabel.cpp5
-rw-r--r--src/gui/widgets/qlabel_p.h2
-rw-r--r--src/gui/widgets/qlinecontrol.cpp21
-rw-r--r--src/gui/widgets/qlinecontrol_p.h615
-rw-r--r--src/gui/widgets/qlineedit.cpp21
-rw-r--r--src/gui/widgets/qlineedit.h6
-rw-r--r--src/gui/widgets/qlineedit_p.cpp2
-rw-r--r--src/gui/widgets/qmainwindow.cpp29
-rw-r--r--src/gui/widgets/qmainwindowlayout_mac.mm2
-rw-r--r--src/gui/widgets/qmenu.cpp61
-rw-r--r--src/gui/widgets/qmenu_mac.mm52
-rw-r--r--src/gui/widgets/qmenu_p.h8
-rw-r--r--src/gui/widgets/qmenu_symbian.cpp18
-rw-r--r--src/gui/widgets/qmenu_wince.cpp25
-rw-r--r--src/gui/widgets/qmenubar.cpp50
-rw-r--r--src/gui/widgets/qmenubar_p.h5
-rw-r--r--src/gui/widgets/qradiobutton.cpp2
-rw-r--r--src/gui/widgets/qscrollbar.cpp5
-rw-r--r--src/gui/widgets/qspinbox.cpp15
-rw-r--r--src/gui/widgets/qsplitter.cpp69
-rw-r--r--src/gui/widgets/qsplitter.h1
-rw-r--r--src/gui/widgets/qtoolbarlayout.cpp4
-rw-r--r--src/gui/widgets/qvalidator.cpp2
-rw-r--r--src/gui/widgets/qworkspace.cpp10
-rw-r--r--src/gui/widgets/widgets.pri2
275 files changed, 8020 insertions, 3889 deletions
diff --git a/src/gui/dialogs/qabstractprintdialog.cpp b/src/gui/dialogs/qabstractprintdialog.cpp
index 4523433..25d9ebb 100644
--- a/src/gui/dialogs/qabstractprintdialog.cpp
+++ b/src/gui/dialogs/qabstractprintdialog.cpp
@@ -76,6 +76,7 @@ class QPrintDialogPrivate : public QAbstractPrintDialogPrivate
\value AllPages All pages should be printed.
\value Selection Only the selection should be printed.
\value PageRange The specified page range should be printed.
+ \value CurrentPage Only the currently visible page should be printed.
\sa QPrinter::PrintRange
*/
@@ -89,7 +90,9 @@ class QPrintDialogPrivate : public QAbstractPrintDialogPrivate
\value PrintToFile The print to file option is enabled.
\value PrintSelection The print selection option is enabled.
\value PrintPageRange The page range selection option is enabled.
- \value PrintCollateCopies
+ \value PrintShowPageSize Show the page size + margins page only if this is enabled.
+ \value PrintCollateCopies The collate copies option is enabled
+ \value PrintCurrentPage The print current page option is enabled
This value is obsolete and does nothing since Qt 4.5:
@@ -97,8 +100,6 @@ class QPrintDialogPrivate : public QAbstractPrintDialogPrivate
would create a sheet by default the dialog was given a parent.
This is no longer supported in Qt 4.5. If you want to use sheets, use
QPrintDialog::open() instead.
-
- \value PrintShowPageSize Show the page size + margins page only if this is enabled.
*/
/*!
diff --git a/src/gui/dialogs/qabstractprintdialog.h b/src/gui/dialogs/qabstractprintdialog.h
index 4d867f6..82e3df8 100644
--- a/src/gui/dialogs/qabstractprintdialog.h
+++ b/src/gui/dialogs/qabstractprintdialog.h
@@ -65,7 +65,8 @@ public:
enum PrintRange {
AllPages,
Selection,
- PageRange
+ PageRange,
+ CurrentPage
};
enum PrintDialogOption {
@@ -75,7 +76,8 @@ public:
PrintPageRange = 0x0004,
PrintShowPageSize = 0x0008,
PrintCollateCopies = 0x0010,
- DontUseSheet = 0x0020
+ DontUseSheet = 0x0020,
+ PrintCurrentPage = 0x0040
};
Q_DECLARE_FLAGS(PrintDialogOptions, PrintDialogOption)
diff --git a/src/gui/dialogs/qcolordialog.cpp b/src/gui/dialogs/qcolordialog.cpp
index e6abf7f..e9b5720 100644
--- a/src/gui/dialogs/qcolordialog.cpp
+++ b/src/gui/dialogs/qcolordialog.cpp
@@ -644,6 +644,7 @@ protected:
void paintEvent(QPaintEvent*);
void mouseMoveEvent(QMouseEvent *);
void mousePressEvent(QMouseEvent *);
+ void resizeEvent(QResizeEvent *);
private:
int hue;
@@ -654,7 +655,7 @@ private:
int satPt(const QPoint &pt);
void setCol(const QPoint &pt);
- QPixmap *pix;
+ QPixmap pix;
};
static int pWidth = 220;
@@ -790,13 +791,27 @@ void QColorLuminancePicker::setCol(int h, int s , int v)
}
QPoint QColorPicker::colPt()
-{ return QPoint((360-hue)*(pWidth-1)/360, (255-sat)*(pHeight-1)/255); }
+{
+ QRect r = contentsRect();
+ return QPoint((360 - hue) * (r.width() - 1) / 360, (255 - sat) * (r.height() - 1) / 255);
+}
+
int QColorPicker::huePt(const QPoint &pt)
-{ return 360 - pt.x()*360/(pWidth-1); }
+{
+ QRect r = contentsRect();
+ return 360 - pt.x() * 360 / (r.width() - 1);
+}
+
int QColorPicker::satPt(const QPoint &pt)
-{ return 255 - pt.y()*255/(pHeight-1) ; }
+{
+ QRect r = contentsRect();
+ return 255 - pt.y() * 255 / (r.height() - 1);
+}
+
void QColorPicker::setCol(const QPoint &pt)
-{ setCol(huePt(pt), satPt(pt)); }
+{
+ setCol(huePt(pt), satPt(pt));
+}
QColorPicker::QColorPicker(QWidget* parent)
: QFrame(parent)
@@ -804,29 +819,12 @@ QColorPicker::QColorPicker(QWidget* parent)
hue = 0; sat = 0;
setCol(150, 255);
- QImage img(pWidth, pHeight, QImage::Format_RGB32);
- int x, y;
- uint *pixel = (uint *) img.scanLine(0);
- for (y = 0; y < pHeight; y++) {
- const uint *end = pixel + pWidth;
- x = 0;
- while (pixel < end) {
- QPoint p(x, y);
- QColor c;
- c.setHsv(huePt(p), satPt(p), 200);
- *pixel = c.rgb();
- ++pixel;
- ++x;
- }
- }
- pix = new QPixmap(QPixmap::fromImage(img));
setAttribute(Qt::WA_NoSystemBackground);
setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed) );
}
QColorPicker::~QColorPicker()
{
- delete pix;
}
QSize QColorPicker::sizeHint() const
@@ -869,7 +867,7 @@ void QColorPicker::paintEvent(QPaintEvent* )
drawFrame(&p);
QRect r = contentsRect();
- p.drawPixmap(r.topLeft(), *pix);
+ p.drawPixmap(r.topLeft(), pix);
QPoint pt = colPt() + r.topLeft();
p.setPen(Qt::black);
@@ -878,6 +876,31 @@ void QColorPicker::paintEvent(QPaintEvent* )
}
+void QColorPicker::resizeEvent(QResizeEvent *ev)
+{
+ QFrame::resizeEvent(ev);
+
+ int w = width() - frameWidth() * 2;
+ int h = height() - frameWidth() * 2;
+ QImage img(w, h, QImage::Format_RGB32);
+ int x, y;
+ uint *pixel = (uint *) img.scanLine(0);
+ for (y = 0; y < h; y++) {
+ const uint *end = pixel + w;
+ x = 0;
+ while (pixel < end) {
+ QPoint p(x, y);
+ QColor c;
+ c.setHsv(huePt(p), satPt(p), 200);
+ *pixel = c.rgb();
+ ++pixel;
+ ++x;
+ }
+ }
+ pix = QPixmap::fromImage(img);
+}
+
+
class QColSpinBox : public QSpinBox
{
public:
diff --git a/src/gui/dialogs/qdialog.cpp b/src/gui/dialogs/qdialog.cpp
index fb0dba4..c9129c1 100644
--- a/src/gui/dialogs/qdialog.cpp
+++ b/src/gui/dialogs/qdialog.cpp
@@ -69,7 +69,6 @@ extern bool qt_wince_is_smartphone(); //is defined in qguifunctions_wce.cpp
# include "qfontdialog.h"
# include "qcolordialog.h"
# include "qwizard.h"
-# include "qmenubar.h"
#endif
#if defined(Q_WS_S60)
@@ -259,7 +258,7 @@ QT_BEGIN_NAMESPACE
QDialog::QDialog(QWidget *parent, Qt::WindowFlags f)
: QWidget(*new QDialogPrivate, parent,
- f | QFlag((f & Qt::WindowType_Mask) == 0 ? Qt::Dialog : 0))
+ f | ((f & Qt::WindowType_Mask) == 0 ? Qt::Dialog : Qt::WindowType(0)))
{
#ifdef Q_WS_WINCE
if (!qt_wince_is_smartphone())
@@ -296,7 +295,7 @@ QDialog::QDialog(QWidget *parent, const char *name, bool modal, Qt::WindowFlags
\internal
*/
QDialog::QDialog(QDialogPrivate &dd, QWidget *parent, Qt::WindowFlags f)
- : QWidget(dd, parent, f | QFlag((f & Qt::WindowType_Mask) == 0 ? Qt::Dialog : 0))
+ : QWidget(dd, parent, f | ((f & Qt::WindowType_Mask) == 0 ? Qt::Dialog : Qt::WindowType(0)))
{
#ifdef Q_WS_WINCE
if (!qt_wince_is_smartphone())
@@ -415,8 +414,15 @@ bool QDialog::event(QEvent *e)
result = true;
}
#else
- if ((e->type() == QEvent::StyleChange) || (e->type() == QEvent::Resize ))
- adjustPosition(parentWidget());
+ if ((e->type() == QEvent::StyleChange) || (e->type() == QEvent::Resize )) {
+ if (!testAttribute(Qt::WA_Moved)) {
+ Qt::WindowStates state = windowState();
+ adjustPosition(parentWidget());
+ setAttribute(Qt::WA_Moved, false); // not really an explicit position
+ if (state != windowState())
+ setWindowState(state);
+ }
+ }
#endif
return result;
}
@@ -522,12 +528,6 @@ int QDialog::exec()
#endif //Q_WS_WINCE_WM
#ifdef Q_OS_SYMBIAN
-#ifndef QT_NO_MENUBAR
- QMenuBar *menuBar = 0;
- if (!findChild<QMenuBar *>())
- menuBar = new QMenuBar(this);
-#endif
-
if (qobject_cast<QFileDialog *>(this) || qobject_cast<QFontDialog *>(this) ||
qobject_cast<QColorDialog *>(this) || qobject_cast<QWizard *>(this))
showMaximized();
@@ -559,13 +559,6 @@ int QDialog::exec()
delete menuBar;
#endif //QT_NO_MENUBAR
#endif //Q_WS_WINCE_WM
-#ifdef Q_OS_SYMBIAN
-#ifndef QT_NO_MENUBAR
- else if (menuBar)
- delete menuBar;
-#endif //QT_NO_MENUBAR
-#endif //Q_OS_SYMBIAN
-
return res;
}
@@ -808,11 +801,11 @@ void QDialog::setVisible(bool visible)
void QDialog::showEvent(QShowEvent *event)
{
if (!event->spontaneous() && !testAttribute(Qt::WA_Moved)) {
- Qt::WindowStates state = windowState();
+ Qt::WindowStates state = windowState();
adjustPosition(parentWidget());
setAttribute(Qt::WA_Moved, false); // not really an explicit position
- if (state != windowState())
- setWindowState(state);
+ if (state != windowState())
+ setWindowState(state);
}
}
diff --git a/src/gui/dialogs/qerrormessage.cpp b/src/gui/dialogs/qerrormessage.cpp
index 0bca811..7be7481 100644
--- a/src/gui/dialogs/qerrormessage.cpp
+++ b/src/gui/dialogs/qerrormessage.cpp
@@ -70,10 +70,10 @@ extern bool qt_wince_is_high_dpi(); //defined in qguifunctions_wince.cpp
#if defined(QT_SOFTKEYS_ENABLED)
#include <qaction.h>
+#endif
#ifdef Q_WS_S60
#include "private/qt_s60_p.h"
#endif
-#endif
QT_BEGIN_NAMESPACE
diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp
index 089e04a..3b5fb9f 100644
--- a/src/gui/dialogs/qfiledialog.cpp
+++ b/src/gui/dialogs/qfiledialog.cpp
@@ -228,7 +228,8 @@ Q_GUI_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook
\value ReadOnly Indicates that the model is readonly.
- \value HideNameFilterDetails Indicates if the is hidden or not.
+ \value HideNameFilterDetails Indicates if the file name filter details are
+ hidden or not.
\value DontUseSheet In previous versions of Qt, the static
functions would create a sheet by default if the static function
@@ -722,9 +723,15 @@ void QFileDialog::setVisible(bool visible)
// Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below
// updates the state correctly, but skips showing the non-native version:
setAttribute(Qt::WA_DontShowOnScreen);
+ //So the completer don't try to complete and therefore to show a popup
+ d->completer->setModel(0);
} else {
d->nativeDialogInUse = false;
setAttribute(Qt::WA_DontShowOnScreen, false);
+ if (d->proxyModel != 0)
+ d->completer->setModel(d->proxyModel);
+ else
+ d->completer->setModel(d->model);
}
}
diff --git a/src/gui/dialogs/qfiledialog.ui b/src/gui/dialogs/qfiledialog.ui
index b52bd8a..1f35abb 100644
--- a/src/gui/dialogs/qfiledialog.ui
+++ b/src/gui/dialogs/qfiledialog.ui
@@ -83,6 +83,12 @@
<property name="toolTip" >
<string>Back</string>
</property>
+ <property name="accessibleName">
+ <string>Back</string>
+ </property>
+ <property name="accessibleDescription">
+ <string>Go back</string>
+ </property>
</widget>
</item>
<item>
@@ -90,6 +96,12 @@
<property name="toolTip" >
<string>Forward</string>
</property>
+ <property name="accessibleName">
+ <string>Forward</string>
+ </property>
+ <property name="accessibleDescription">
+ <string>Go forward</string>
+ </property>
</widget>
</item>
<item>
@@ -97,6 +109,12 @@
<property name="toolTip" >
<string>Parent Directory</string>
</property>
+ <property name="accessibleName">
+ <string>Parent Directory</string>
+ </property>
+ <property name="accessibleDescription">
+ <string>Go to the parent directory</string>
+ </property>
</widget>
</item>
<item>
@@ -104,6 +122,12 @@
<property name="toolTip" >
<string>Create New Folder</string>
</property>
+ <property name="accessibleName">
+ <string>Create New Folder</string>
+ </property>
+ <property name="accessibleDescription">
+ <string>Create a New Folder</string>
+ </property>
</widget>
</item>
<item>
@@ -111,6 +135,12 @@
<property name="toolTip" >
<string>List View</string>
</property>
+ <property name="accessibleName">
+ <string>List View</string>
+ </property>
+ <property name="accessibleDescription">
+ <string>Change to list view mode</string>
+ </property>
</widget>
</item>
<item>
@@ -118,6 +148,12 @@
<property name="toolTip" >
<string>Detail View</string>
</property>
+ <property name="accessibleName">
+ <string>Detail View</string>
+ </property>
+ <property name="accessibleDescription">
+ <string>Change to detail view mode</string>
+ </property>
</widget>
</item>
</layout>
diff --git a/src/gui/dialogs/qfiledialog_mac.mm b/src/gui/dialogs/qfiledialog_mac.mm
index 67daced..14a5f15 100644
--- a/src/gui/dialogs/qfiledialog_mac.mm
+++ b/src/gui/dialogs/qfiledialog_mac.mm
@@ -295,10 +295,14 @@ QT_USE_NAMESPACE
if (!mQDirFilterEntryList->contains(info.fileName()))
return NO;
- // Always accept directories regardless of their names:
+ // Always accept directories regardless of their names (unless it is a bundle):
BOOL isDir;
- if ([[NSFileManager defaultManager] fileExistsAtPath:filename isDirectory:&isDir] && isDir)
- return YES;
+ if ([[NSFileManager defaultManager] fileExistsAtPath:filename isDirectory:&isDir] && isDir) {
+ if ([mSavePanel treatsFilePackagesAsDirectories] == NO) {
+ if ([[NSWorkspace sharedWorkspace] isFilePackageAtPath:filename] == NO)
+ return YES;
+ }
+ }
// No filter means accept everything
if (mSelectedNameFilter->isEmpty())
@@ -725,6 +729,7 @@ Boolean QFileDialogPrivate::qt_mac_filedialog_filter_proc(AEDesc *theItem, void
NavFileOrFolderInfo *theInfo = static_cast<NavFileOrFolderInfo *>(info);
QString file;
+ QString path;
const QtMacFilterName &fn
= fileDialogPrivate->filterInfo.filters.at(fileDialogPrivate->filterInfo.currentSelection);
if (theItem->descriptorType == typeFSRef) {
@@ -732,10 +737,12 @@ Boolean QFileDialogPrivate::qt_mac_filedialog_filter_proc(AEDesc *theItem, void
AEGetDescData(theItem, &ref, sizeof(ref));
UInt8 str_buffer[1024];
FSRefMakePath(&ref, str_buffer, 1024);
- file = QString::fromUtf8(reinterpret_cast<const char *>(str_buffer));
- int slsh = file.lastIndexOf(QLatin1Char('/'));
+ path = QString::fromUtf8(reinterpret_cast<const char *>(str_buffer));
+ int slsh = path.lastIndexOf(QLatin1Char('/'));
if (slsh != -1)
- file = file.right(file.length() - slsh - 1);
+ file = path.right(path.length() - slsh - 1);
+ else
+ file = path;
}
QStringList reg = fn.regexp.split(QLatin1String(";"));
for (QStringList::const_iterator it = reg.constBegin(); it != reg.constEnd(); ++it) {
@@ -747,7 +754,13 @@ Boolean QFileDialogPrivate::qt_mac_filedialog_filter_proc(AEDesc *theItem, void
if (rg.exactMatch(file))
return true;
}
- return (theInfo->isFolder && !file.endsWith(QLatin1String(".app")));
+
+ if (theInfo->isFolder) {
+ if ([[NSWorkspace sharedWorkspace] isFilePackageAtPath:qt_mac_QStringToNSString(path)])
+ return false;
+ return true;
+ }
+ return false;
}
void QFileDialogPrivate::qt_mac_filedialog_event_proc(const NavEventCallbackMessage msg,
diff --git a/src/gui/dialogs/qfiledialog_win.cpp b/src/gui/dialogs/qfiledialog_win.cpp
index 3120938..afeed8e 100644
--- a/src/gui/dialogs/qfiledialog_win.cpp
+++ b/src/gui/dialogs/qfiledialog_win.cpp
@@ -583,6 +583,63 @@ static QStringList qt_win_CID_get_open_file_names(const QFileDialogArgs &args,
return result;
}
+QString qt_win_CID_get_existing_directory(const QFileDialogArgs &args)
+{
+ QString result;
+ QDialog modal_widget;
+ modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true);
+ modal_widget.setParent(args.parent, Qt::Window);
+ QApplicationPrivate::enterModal(&modal_widget);
+
+ IFileOpenDialog *pfd = 0;
+ HRESULT hr = CoCreateInstance(QT_CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER,
+ QT_IID_IFileOpenDialog, reinterpret_cast<void**>(&pfd));
+
+ if (SUCCEEDED(hr)) {
+ qt_win_set_IFileDialogOptions(pfd, args.selection,
+ args.directory, args.caption,
+ QStringList(), QFileDialog::ExistingFiles,
+ args.options);
+
+ // Set the FOS_PICKFOLDERS flag
+ DWORD newOptions;
+ hr = pfd->GetOptions(&newOptions);
+ newOptions |= FOS_PICKFOLDERS;
+ if (SUCCEEDED(hr) && SUCCEEDED((hr = pfd->SetOptions(newOptions)))) {
+ QWidget *parentWindow = args.parent;
+ if (parentWindow)
+ parentWindow = parentWindow->window();
+ else
+ parentWindow = QApplication::activeWindow();
+
+ // Show the file dialog.
+ hr = pfd->Show(parentWindow ? parentWindow->winId() : 0);
+ if (SUCCEEDED(hr)) {
+ // Retrieve the result
+ IShellItem *psi = 0;
+ hr = pfd->GetResult(&psi);
+ if (SUCCEEDED(hr)) {
+ // Retrieve the file name from shell item.
+ wchar_t *pszPath;
+ hr = psi->GetDisplayName(SIGDN_FILESYSPATH, &pszPath);
+ if (SUCCEEDED(hr)) {
+ result = QString::fromWCharArray(pszPath);
+ CoTaskMemFree(pszPath);
+ }
+ psi->Release(); // Free the current item.
+ }
+ }
+ }
+ }
+ QApplicationPrivate::leaveModal(&modal_widget);
+
+ qt_win_eatMouseMove();
+
+ if (pfd)
+ pfd->Release();
+ return result;
+}
+
#endif
QStringList qt_win_get_open_file_names(const QFileDialogArgs &args,
@@ -701,6 +758,11 @@ static int __stdcall winGetExistDirCallbackProc(HWND hwnd,
QString qt_win_get_existing_directory(const QFileDialogArgs &args)
{
+#ifndef Q_WS_WINCE
+ if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)
+ return qt_win_CID_get_existing_directory(args);
+#endif
+
QString currentDir = QDir::currentPath();
QString result;
QWidget *parent = args.parent;
diff --git a/src/gui/dialogs/qfiledialog_win_p.h b/src/gui/dialogs/qfiledialog_win_p.h
index 44b7e43..7079925 100644
--- a/src/gui/dialogs/qfiledialog_win_p.h
+++ b/src/gui/dialogs/qfiledialog_win_p.h
@@ -82,7 +82,7 @@ typedef int GETPROPERTYSTOREFLAGS;
#define GPS_BESTEFFORT 0x00000040
#define GPS_MASK_VALID 0x0000007F
-typedef int (CALLBACK* BFFCALLBACK)(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData);
+typedef int (QT_WIN_CALLBACK* BFFCALLBACK)(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData);
// message from browser
#define BFFM_INITIALIZED 1
#define BFFM_SELCHANGED 2
diff --git a/src/gui/dialogs/qfileinfogatherer.cpp b/src/gui/dialogs/qfileinfogatherer.cpp
index c75cdfd..3b279ae 100644
--- a/src/gui/dialogs/qfileinfogatherer.cpp
+++ b/src/gui/dialogs/qfileinfogatherer.cpp
@@ -216,41 +216,10 @@ void QFileInfoGatherer::run()
}
}
-/*
- QFileInfo::permissions is different depending upon your platform.
-
- "normalize this" so they can mean the same to us.
-*/
-QFile::Permissions QFileInfoGatherer::translatePermissions(const QFileInfo &fileInfo) const {
- QFile::Permissions permissions = fileInfo.permissions();
-#ifdef Q_OS_WIN
- return permissions;
-#else
- QFile::Permissions p = permissions;
- p &= ~(QFile::ReadUser|QFile::WriteUser|QFile::ExeUser);
- if ( permissions & QFile::ReadOther
- || (fileInfo.ownerId() == userId && permissions & QFile::ReadOwner)
- || (fileInfo.groupId() == groupId && permissions & QFile::ReadGroup))
- p |= QFile::ReadUser;
-
- if ( permissions & QFile::WriteOther
- || (fileInfo.ownerId() == userId && permissions & QFile::WriteOwner)
- || (fileInfo.groupId() == groupId && permissions & QFile::WriteGroup))
- p |= QFile::WriteUser;
-
- if ( permissions & QFile::ExeOther
- || (fileInfo.ownerId() == userId && permissions & QFile::ExeOwner)
- || (fileInfo.groupId() == groupId && permissions & QFile::ExeGroup))
- p |= QFile::ExeUser;
- return p;
-#endif
-}
-
QExtendedInformation QFileInfoGatherer::getInfo(const QFileInfo &fileInfo) const
{
QExtendedInformation info(fileInfo);
info.icon = m_iconProvider->icon(fileInfo);
- info.setPermissions(translatePermissions(fileInfo));
info.displayType = m_iconProvider->type(fileInfo);
#ifndef QT_NO_FILESYSTEMWATCHER
// ### Not ready to listen all modifications
@@ -328,7 +297,8 @@ void QFileInfoGatherer::getFileInfos(const QString &path, const QStringList &fil
return;
}
- QTime base = QTime::currentTime();
+ QElapsedTimer base;
+ base.start();
QFileInfo fileInfo;
bool firstTime = true;
QList<QPair<QString, QFileInfo> > updatedFiles;
@@ -357,9 +327,10 @@ void QFileInfoGatherer::getFileInfos(const QString &path, const QStringList &fil
emit directoryLoaded(path);
}
-void QFileInfoGatherer::fetch(const QFileInfo &fileInfo, QTime &base, bool &firstTime, QList<QPair<QString, QFileInfo> > &updatedFiles, const QString &path) {
+void QFileInfoGatherer::fetch(const QFileInfo &fileInfo, QElapsedTimer &base, bool &firstTime, QList<QPair<QString, QFileInfo> > &updatedFiles, const QString &path) {
updatedFiles.append(QPair<QString, QFileInfo>(fileInfo.fileName(), fileInfo));
- QTime current = QTime::currentTime();
+ QElapsedTimer current;
+ current.start();
if ((firstTime && updatedFiles.count() > 100) || base.msecsTo(current) > 1000) {
emit updates(path, updatedFiles);
updatedFiles.clear();
diff --git a/src/gui/dialogs/qfileinfogatherer_p.h b/src/gui/dialogs/qfileinfogatherer_p.h
index b8b58a2..5abcd94 100644
--- a/src/gui/dialogs/qfileinfogatherer_p.h
+++ b/src/gui/dialogs/qfileinfogatherer_p.h
@@ -60,9 +60,10 @@
#include <qfileiconprovider.h>
#include <qfsfileengine.h>
#include <qpair.h>
-#include <qdatetime.h>
#include <qstack.h>
+#include <qdatetime.h>
#include <qdir.h>
+#include <qelapsedtimer.h>
QT_BEGIN_NAMESPACE
@@ -88,11 +89,7 @@ public:
return fe.caseSensitive();
}
QFile::Permissions permissions() const {
- return mPermissions;
- }
-
- void setPermissions (QFile::Permissions permissions) {
- mPermissions = permissions;
+ return mFileInfo.permissions();
}
Type type() const {
@@ -140,7 +137,6 @@ public:
private :
QFileInfo mFileInfo;
- QFile::Permissions mPermissions;
};
class QFileIconProvider;
@@ -179,9 +175,8 @@ protected:
void getFileInfos(const QString &path, const QStringList &files);
private:
- void fetch(const QFileInfo &info, QTime &base, bool &firstTime, QList<QPair<QString, QFileInfo> > &updatedFiles, const QString &path);
+ void fetch(const QFileInfo &info, QElapsedTimer &base, bool &firstTime, QList<QPair<QString, QFileInfo> > &updatedFiles, const QString &path);
QString translateDriveName(const QFileInfo &drive) const;
- QFile::Permissions translatePermissions(const QFileInfo &fileInfo) const;
QMutex mutex;
QWaitCondition condition;
diff --git a/src/gui/dialogs/qfilesystemmodel.cpp b/src/gui/dialogs/qfilesystemmodel.cpp
index ba0a560..8a6190f 100644
--- a/src/gui/dialogs/qfilesystemmodel.cpp
+++ b/src/gui/dialogs/qfilesystemmodel.cpp
@@ -1373,6 +1373,16 @@ QModelIndex QFileSystemModel::setRootPath(const QString &newPath)
if (!showDrives && !newPathDir.exists())
return d->index(rootPath());
+ //We remove the watcher on the previous path
+ if (!rootPath().isEmpty() && rootPath() != QLatin1String(".")) {
+ //This remove the watcher for the old rootPath
+ d->fileInfoGatherer.removePath(rootPath());
+ //This line "marks" the node as dirty, so the next fetchMore
+ //call on the path will ask the gatherer to install a watcher again
+ //But it doesn't re-fetch everything
+ d->node(rootPath())->populatedChildren = false;
+ }
+
// We have a new valid root path
d->rootDir = newPathDir;
QModelIndex newRootIndex;
@@ -1896,6 +1906,13 @@ void QFileSystemModelPrivate::init()
q->connect(&fileInfoGatherer, SIGNAL(directoryLoaded(QString)),
q, SIGNAL(directoryLoaded(QString)));
q->connect(&delayedSortTimer, SIGNAL(timeout()), q, SLOT(_q_performDelayedSort()), Qt::QueuedConnection);
+
+ QHash<int, QByteArray> roles = q->roleNames();
+ roles.insertMulti(QFileSystemModel::FileIconRole, "fileIcon"); // == Qt::decoration
+ roles.insert(QFileSystemModel::FilePathRole, "filePath");
+ roles.insert(QFileSystemModel::FileNameRole, "fileName");
+ roles.insert(QFileSystemModel::FilePermissions, "filePermissions");
+ q->setRoleNames(roles);
}
/*!
diff --git a/src/gui/dialogs/qfontdialog.cpp b/src/gui/dialogs/qfontdialog.cpp
index a4bf15d..b159fa7 100644
--- a/src/gui/dialogs/qfontdialog.cpp
+++ b/src/gui/dialogs/qfontdialog.cpp
@@ -174,6 +174,11 @@ void QFontDialogPrivate::init()
{
Q_Q(QFontDialog);
+#ifdef Q_WS_MAC
+ nativeDialogInUse = false;
+ delegate = 0;
+#endif
+
q->setSizeGripEnabled(true);
q->setWindowTitle(QFontDialog::tr("Select Font"));
@@ -329,10 +334,6 @@ void QFontDialogPrivate::init()
familyList->setFocus();
retranslateStrings();
-
-#ifdef Q_WS_MAC
- delegate = 0;
-#endif
}
/*!
@@ -345,8 +346,7 @@ QFontDialog::~QFontDialog()
#ifdef Q_WS_MAC
Q_D(QFontDialog);
if (d->delegate) {
- QFontDialogPrivate::closeCocoaFontPanel(d->delegate);
- QFontDialogPrivate::sharedFontPanelAvailable = true;
+ d->closeCocoaFontPanel();
return;
}
#endif
@@ -428,14 +428,6 @@ QFont QFontDialog::getFont(bool *ok, QWidget *parent)
QFont QFontDialogPrivate::getFont(bool *ok, const QFont &initial, QWidget *parent,
const QString &title, QFontDialog::FontDialogOptions options)
{
-#ifdef Q_WS_MAC
- if (!(options & QFontDialog::DontUseNativeDialog)
- && QFontDialogPrivate::sharedFontPanelAvailable) {
- return QFontDialogPrivate::execCocoaFontPanel(ok, initial, parent,
- title.isEmpty() ? QFontDialog::tr("Select Font") : title, options);
- }
-#endif
-
QFontDialog dlg(parent);
dlg.setOptions(options);
dlg.setCurrentFont(initial);
@@ -988,13 +980,10 @@ void QFontDialog::open(QObject *receiver, const char *member)
*/
void QFontDialog::setVisible(bool visible)
{
- Q_D(QFontDialog);
- if (visible) {
- if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden))
- return;
- } else if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden))
+ if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden) != visible)
return;
#ifdef Q_WS_MAC
+ Q_D(QFontDialog);
if (d->canBeNativeDialog()){
if (d->setVisible_sys(visible)){
d->nativeDialogInUse = true;
diff --git a/src/gui/dialogs/qfontdialog_mac.mm b/src/gui/dialogs/qfontdialog_mac.mm
index 67d32b8..919790b 100644
--- a/src/gui/dialogs/qfontdialog_mac.mm
+++ b/src/gui/dialogs/qfontdialog_mac.mm
@@ -58,6 +58,14 @@
typedef float CGFloat; // Should only not be defined on 32-bit platforms
#endif
+QT_BEGIN_NAMESPACE
+
+extern void macStartInterceptNSPanelCtor();
+extern void macStopInterceptNSPanelCtor();
+extern NSButton *macCreateButton(const char *text, NSView *superview);
+extern bool qt_mac_is_macsheet(const QWidget *w); // qwidget_mac.mm
+
+QT_END_NAMESPACE
QT_USE_NAMESPACE
// should a priori be kept in sync with qcolordialog_mac.mm
@@ -95,7 +103,8 @@ const int StyleMask = NSTitledWindowMask | NSClosableWindowMask | NSResizableWin
BOOL mPanelHackedWithButtons;
CGFloat mDialogExtraWidth;
CGFloat mDialogExtraHeight;
- NSModalSession mModalSession;
+ int mReturnCode;
+ BOOL mAppModal;
}
- (id)initWithFontPanel:(NSFontPanel *)panel
stolenContentView:(NSView *)stolenContentView
@@ -104,9 +113,11 @@ const int StyleMask = NSTitledWindowMask | NSClosableWindowMask | NSResizableWin
priv:(QFontDialogPrivate *)priv
extraWidth:(CGFloat)extraWidth
extraHeight:(CGFloat)extraHeight;
+- (void)showModelessPanel;
+- (void)showWindowModalSheet:(QWidget *)docWidget;
+- (void)runApplicationModalPanel;
- (void)changeFont:(id)sender;
- (void)changeAttributes:(id)sender;
-- (void)setModalSession:(NSModalSession)session;
- (BOOL)windowShouldClose:(id)window;
- (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize;
- (void)relayout;
@@ -163,7 +174,8 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont)
mPanelHackedWithButtons = (okButton != 0);
mDialogExtraWidth = extraWidth;
mDialogExtraHeight = extraHeight;
- mModalSession = 0;
+ mReturnCode = -1;
+ mAppModal = false;
if (mPanelHackedWithButtons) {
[self relayout];
@@ -174,6 +186,20 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont)
[cancelButton setAction:@selector(onCancelClicked)];
[cancelButton setTarget:self];
}
+
+#ifdef QT_MAC_USE_COCOA
+ // Stack the native dialog in front of its parent, if any:
+ QFontDialog *q = mPriv->fontDialog();
+ if (!qt_mac_is_macsheet(q)) {
+ if (QWidget *parent = q->parentWidget()) {
+ if (parent->isWindow()) {
+ [qt_mac_window_for(parent)
+ addChildWindow:[mStolenContentView window] ordered:NSWindowAbove];
+ }
+ }
+ }
+#endif
+
mQtFont = new QFont();
return self;
}
@@ -184,6 +210,50 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont)
[super dealloc];
}
+- (void)showModelessPanel
+{
+ mAppModal = false;
+ NSWindow *ourPanel = [mStolenContentView window];
+ [ourPanel makeKeyAndOrderFront:self];
+}
+
+- (void)runApplicationModalPanel
+{
+ QBoolBlocker nativeDialogOnTop(QApplicationPrivate::native_modal_dialog_active);
+ mAppModal = true;
+ NSWindow *ourPanel = [mStolenContentView window];
+ [NSApp runModalForWindow:ourPanel];
+ QAbstractEventDispatcher::instance()->interrupt();
+
+ if (mReturnCode == NSOKButton)
+ mPriv->fontDialog()->accept();
+ else
+ mPriv->fontDialog()->reject();
+}
+
+- (void)showWindowModalSheet:(QWidget *)docWidget
+{
+#ifdef QT_MAC_USE_COCOA
+ NSWindow *window = qt_mac_window_for(docWidget);
+#else
+ WindowRef hiwindowRef = qt_mac_window_for(docWidget);
+ NSWindow *window = [[NSWindow alloc] initWithWindowRef:hiwindowRef];
+ CFRetain(hiwindowRef);
+#endif
+
+ mAppModal = false;
+ NSWindow *ourPanel = [mStolenContentView window];
+ [NSApp beginSheet:ourPanel
+ modalForWindow:window
+ modalDelegate:0
+ didEndSelector:0
+ contextInfo:0 ];
+
+#ifndef QT_MAC_USE_COCOA
+ CFRelease(hiwindowRef);
+#endif
+}
+
- (void)changeFont:(id)sender
{
NSFont *dummyFont = [NSFont userFontOfSize:12.0];
@@ -216,12 +286,6 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont)
mPriv->updateSampleFont(*mQtFont);
}
-- (void)setModalSession:(NSModalSession)session
-{
- Q_ASSERT(!mModalSession);
- mModalSession = session;
-}
-
- (BOOL)windowShouldClose:(id)window
{
Q_UNUSED(window);
@@ -282,9 +346,8 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont)
NSSize cancelSizeHint = [mCancelButton frame].size;
const CGFloat ButtonWidth = qMin(qMax(ButtonMinWidth,
- qMax(okSizeHint.width, cancelSizeHint.width)),
- CGFloat((frameSize.width - 2.0 * ButtonSideMargin
- - ButtonSpacing) * 0.5));
+ qMax(okSizeHint.width, cancelSizeHint.width)),
+ CGFloat((frameSize.width - 2.0 * ButtonSideMargin - ButtonSpacing) * 0.5));
const CGFloat ButtonHeight = qMax(ButtonMinHeight,
qMax(okSizeHint.height, cancelSizeHint.height));
@@ -317,14 +380,12 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont)
NSFontManager *fontManager = [NSFontManager sharedFontManager];
[self setQtFont:qfontForCocoaFont([fontManager convertFont:[fontManager selectedFont]],
*mQtFont)];
- [[mStolenContentView window] close];
[self finishOffWithCode:NSOKButton];
}
- (void)onCancelClicked
{
Q_ASSERT(mPanelHackedWithButtons);
- [[mStolenContentView window] close];
[self finishOffWithCode:NSCancelButton];
}
@@ -368,20 +429,26 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont)
- (void)finishOffWithCode:(NSInteger)code
{
- if (mPriv) {
- if (mModalSession) {
- [NSApp endModalSession:mModalSession];
- mModalSession = 0;
+#ifdef QT_MAC_USE_COCOA
+ QFontDialog *q = mPriv->fontDialog();
+ if (QWidget *parent = q->parentWidget()) {
+ if (parent->isWindow()) {
+ [qt_mac_window_for(parent) removeChildWindow:[mStolenContentView window]];
}
- // Hack alert!
- // Since this code path was never intended to be followed when starting from exec
- // we need to force the dialog to communicate the new font, otherwise the signal
- // won't get emitted.
- if(code == NSOKButton)
- mPriv->sampleEdit->setFont([self qtFont]);
- mPriv->done((code == NSOKButton) ? QDialog::Accepted : QDialog::Rejected);
- } else {
+ }
+#endif
+
+ if(code == NSOKButton)
+ mPriv->sampleEdit->setFont([self qtFont]);
+
+ if (mAppModal) {
+ mReturnCode = code;
[NSApp stopModalWithCode:code];
+ } else {
+ if (code == NSOKButton)
+ mPriv->fontDialog()->accept();
+ else
+ mPriv->fontDialog()->reject();
}
}
@@ -408,206 +475,16 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont)
QT_BEGIN_NAMESPACE
-extern void macStartInterceptNSPanelCtor();
-extern void macStopInterceptNSPanelCtor();
-extern NSButton *macCreateButton(const char *text, NSView *superview);
-
-void *QFontDialogPrivate::openCocoaFontPanel(const QFont &initial,
- QWidget *parent, const QString &title, QFontDialog::FontDialogOptions options,
- QFontDialogPrivate *priv)
-{
- Q_UNUSED(parent); // we would use the parent if only NSFontPanel could be a sheet
- QMacCocoaAutoReleasePool pool;
-
- /*
- The standard Cocoa font panel has no OK or Cancel button and
- is created as a utility window. For strange reasons (which seem
- to stem from the fact that the font panel is based on a NIB
- file), the approach we use for the color panel doesn't work for
- the font panel (and, inversely, the approach we use here doesn't
- quite work for color panel, and crashed last time I tried). So
- instead, we take the following steps:
-
- 1. Constructs a plain NSPanel that looks the way we want it
- to look. Specifically, if the NoButtons option is off, we
- construct a panel without the NSUtilityWindowMask flag
- and with buttons (OK and Cancel).
-
- 2. Steal the content view from the shared NSFontPanel and
- put it inside our new NSPanel's content view, together
- with the OK and Cancel buttons.
-
- 3. Lay out the original content view and the buttons when
- the font panel is shown and whenever it is resized.
-
- 4. Clean up after ourselves.
-
- PS. Some customization is also done in QCocoaApplication
- validModesForFontPanel:.
- */
-
- Qt::WindowModality modality = Qt::ApplicationModal;
- if (priv)
- modality = priv->fontDialog()->windowModality();
-
- bool needButtons = !(options & QFontDialog::NoButtons);
- // don't need our own panel if the title bar isn't visible anyway (in a sheet)
- bool needOwnPanel = (needButtons && modality != Qt::WindowModal);
-
- bool sharedFontPanelExisted = [NSFontPanel sharedFontPanelExists];
- NSFontPanel *sharedFontPanel = [NSFontPanel sharedFontPanel];
- [sharedFontPanel setHidesOnDeactivate:false];
-
- // hack to ensure that QCocoaApplication's validModesForFontPanel:
- // implementation is honored
- if (!sharedFontPanelExisted && needOwnPanel) {
- [sharedFontPanel makeKeyAndOrderFront:sharedFontPanel];
- [sharedFontPanel close];
- }
-
- NSPanel *ourPanel = 0;
- NSView *stolenContentView = 0;
- NSButton *okButton = 0;
- NSButton *cancelButton = 0;
-
- CGFloat dialogExtraWidth = 0.0;
- CGFloat dialogExtraHeight = 0.0;
-
- if (!needOwnPanel) {
- // we can reuse the NSFontPanel unchanged
- ourPanel = sharedFontPanel;
- } else {
- // compute dialogExtra{Width,Height}
- dialogExtraWidth = 2.0 * DialogSideMargin;
- dialogExtraHeight = DialogTopMargin + ButtonTopMargin + ButtonMinHeight
- + ButtonBottomMargin;
-
- // compute initial contents rectangle
- NSRect contentRect = [sharedFontPanel contentRectForFrameRect:[sharedFontPanel frame]];
- contentRect.size.width += dialogExtraWidth;
- contentRect.size.height += dialogExtraHeight;
-
- // create the new panel
- ourPanel = [[NSPanel alloc] initWithContentRect:contentRect
- styleMask:StyleMask
- backing:NSBackingStoreBuffered
- defer:YES];
- [ourPanel setReleasedWhenClosed:YES];
- }
-
- stolenContentView = [sharedFontPanel contentView];
-
- if (needButtons) {
- // steal the font panel's contents view
- [stolenContentView retain];
- [sharedFontPanel setContentView:0];
-
- // create a new content view and add the stolen one as a subview
- NSRect frameRect = { { 0.0, 0.0 }, { 0.0, 0.0 } };
- NSView *ourContentView = [[NSView alloc] initWithFrame:frameRect];
- [ourContentView addSubview:stolenContentView];
-
- // create OK and Cancel buttons and add these as subviews
- okButton = macCreateButton("&OK", ourContentView);
- cancelButton = macCreateButton("Cancel", ourContentView);
-
- [ourPanel setContentView:ourContentView];
- [ourPanel setDefaultButtonCell:[okButton cell]];
- }
-
- // create a delegate and set it
- QCocoaFontPanelDelegate *delegate =
- [[QCocoaFontPanelDelegate alloc] initWithFontPanel:sharedFontPanel
- stolenContentView:stolenContentView
- okButton:okButton
- cancelButton:cancelButton
- priv:priv
- extraWidth:dialogExtraWidth
- extraHeight:dialogExtraHeight];
- [ourPanel setDelegate:delegate];
- [[NSFontManager sharedFontManager] setDelegate:delegate];
-#ifdef QT_MAC_USE_COCOA
- [[NSFontManager sharedFontManager] setTarget:delegate];
-#endif
- setFont(delegate, initial);
-
- // hack to get correct initial layout
- NSRect frameRect = [ourPanel frame];
- frameRect.size.width += 1.0;
- [ourPanel setFrame:frameRect display:NO];
- frameRect.size.width -= 1.0;
- frameRect.size = [delegate windowWillResize:ourPanel toSize:frameRect.size];
- [ourPanel setFrame:frameRect display:NO];
- [ourPanel center];
-
- [ourPanel setTitle:(NSString*)(CFStringRef)QCFString(title)];
-
- if (priv) {
- switch (modality) {
- case Qt::WindowModal:
- if (parent) {
-#ifndef QT_MAC_USE_COCOA
- WindowRef hiwindowRef = qt_mac_window_for(parent);
- NSWindow *window =
- [[NSWindow alloc] initWithWindowRef:hiwindowRef];
- // Cocoa docs say I should retain the Carbon ref.
- CFRetain(hiwindowRef);
-#else
- NSWindow *window = qt_mac_window_for(parent);
-#endif
- [NSApp beginSheet:ourPanel
- modalForWindow:window
- modalDelegate:0
- didEndSelector:0
- contextInfo:0];
-#ifndef QT_MAC_USE_COCOA
- [window release];
-#endif
- break;
- }
- // fallthrough
- case Qt::ApplicationModal:
- [delegate setModalSession:[NSApp beginModalSessionForWindow:ourPanel]];
- break;
- default:
- [ourPanel makeKeyAndOrderFront:ourPanel];
- }
- }
- return delegate;
-}
-
-void QFontDialogPrivate::closeCocoaFontPanel(void *delegate)
+void QFontDialogPrivate::closeCocoaFontPanel()
{
QMacCocoaAutoReleasePool pool;
QCocoaFontPanelDelegate *theDelegate = static_cast<QCocoaFontPanelDelegate *>(delegate);
NSWindow *ourPanel = [theDelegate actualPanel];
[ourPanel close];
[theDelegate cleanUpAfterMyself];
- [theDelegate autorelease];
-}
-
-QFont QFontDialogPrivate::execCocoaFontPanel(bool *ok, const QFont &initial,
- QWidget *parent, const QString &title, QFontDialog::FontDialogOptions options)
-{
- QMacCocoaAutoReleasePool pool;
- QCocoaFontPanelDelegate *delegate =
- static_cast<QCocoaFontPanelDelegate *>(
- openCocoaFontPanel(initial, parent, title, options));
- NSWindow *ourPanel = [delegate actualPanel];
- [ourPanel retain];
- int rval = [NSApp runModalForWindow:ourPanel];
- QFont font([delegate qtFont]);
- [ourPanel release];
- [delegate cleanUpAfterMyself];
- [delegate release];
- bool isOk = ((options & QFontDialog::NoButtons) || rval == NSOKButton);
- if (ok)
- *ok = isOk;
- if (isOk) {
- return font;
- } else {
- return initial;
- }
+ [theDelegate release];
+ this->delegate = 0;
+ sharedFontPanelAvailable = true;
}
void QFontDialogPrivate::setFont(void *delegate, const QFont &font)
@@ -645,10 +522,13 @@ void QFontDialogPrivate::setFont(void *delegate, const QFont &font)
[static_cast<QCocoaFontPanelDelegate *>(delegate) setQtFont:font];
}
-void *QFontDialogPrivate::_q_constructNativePanel()
+void QFontDialogPrivate::createNSFontPanelDelegate()
{
- QMacCocoaAutoReleasePool pool;
+ if (delegate)
+ return;
+ sharedFontPanelAvailable = false;
+ QMacCocoaAutoReleasePool pool;
bool sharedFontPanelExisted = [NSFontPanel sharedFontPanelExists];
NSFontPanel *sharedFontPanel = [NSFontPanel sharedFontPanel];
[sharedFontPanel setHidesOnDeactivate:false];
@@ -670,8 +550,7 @@ void *QFontDialogPrivate::_q_constructNativePanel()
// compute dialogExtra{Width,Height}
dialogExtraWidth = 2.0 * DialogSideMargin;
- dialogExtraHeight = DialogTopMargin + ButtonTopMargin + ButtonMinHeight
- + ButtonBottomMargin;
+ dialogExtraHeight = DialogTopMargin + ButtonTopMargin + ButtonMinHeight + ButtonBottomMargin;
// compute initial contents rectangle
NSRect contentRect = [sharedFontPanel contentRectForFrameRect:[sharedFontPanel frame]];
@@ -684,7 +563,6 @@ void *QFontDialogPrivate::_q_constructNativePanel()
backing:NSBackingStoreBuffered
defer:YES];
[ourPanel setReleasedWhenClosed:YES];
-
stolenContentView = [sharedFontPanel contentView];
// steal the font panel's contents view
@@ -704,21 +582,23 @@ void *QFontDialogPrivate::_q_constructNativePanel()
[ourPanel setContentView:ourContentView];
[ourPanel setDefaultButtonCell:[okButton cell]];
}
- // create a delegate and set it
- QCocoaFontPanelDelegate *delegate =
- [[QCocoaFontPanelDelegate alloc] initWithFontPanel:sharedFontPanel
+
+ // create the delegate and set it
+ QCocoaFontPanelDelegate *del = [[QCocoaFontPanelDelegate alloc] initWithFontPanel:sharedFontPanel
stolenContentView:stolenContentView
okButton:okButton
cancelButton:cancelButton
priv:this
extraWidth:dialogExtraWidth
extraHeight:dialogExtraHeight];
- [ourPanel setDelegate:delegate];
- [[NSFontManager sharedFontManager] setDelegate:delegate];
+ delegate = del;
+ [ourPanel setDelegate:del];
+
+ [[NSFontManager sharedFontManager] setDelegate:del];
#ifdef QT_MAC_USE_COCOA
- [[NSFontManager sharedFontManager] setTarget:delegate];
+ [[NSFontManager sharedFontManager] setTarget:del];
#endif
- setFont(delegate, QApplication::font());
+ setFont(del, q_func()->currentFont());
{
// hack to get correct initial layout
@@ -726,15 +606,12 @@ void *QFontDialogPrivate::_q_constructNativePanel()
frameRect.size.width += 1.0;
[ourPanel setFrame:frameRect display:NO];
frameRect.size.width -= 1.0;
- frameRect.size = [delegate windowWillResize:ourPanel toSize:frameRect.size];
+ frameRect.size = [del windowWillResize:ourPanel toSize:frameRect.size];
[ourPanel setFrame:frameRect display:NO];
[ourPanel center];
}
NSString *title = @"Select font";
[ourPanel setTitle:title];
-
- [delegate setModalSession:[NSApp beginModalSessionForWindow:ourPanel]];
- return delegate;
}
void QFontDialogPrivate::mac_nativeDialogModalHelp()
@@ -759,29 +636,47 @@ void QFontDialogPrivate::mac_nativeDialogModalHelp()
// and "adding" the buttons.
void QFontDialogPrivate::_q_macRunNativeAppModalPanel()
{
- QBoolBlocker nativeDialogOnTop(QApplicationPrivate::native_modal_dialog_active);
+ createNSFontPanelDelegate();
+ QCocoaFontPanelDelegate *del = static_cast<QCocoaFontPanelDelegate *>(delegate);
+ [del runApplicationModalPanel];
+}
+
+bool QFontDialogPrivate::showCocoaFontPanel()
+{
+ if (!sharedFontPanelAvailable)
+ return false;
+
Q_Q(QFontDialog);
- QCocoaFontPanelDelegate *delegate = (QCocoaFontPanelDelegate *)_q_constructNativePanel();
- NSWindow *ourPanel = [delegate actualPanel];
- [ourPanel retain];
- int rval = [NSApp runModalForWindow:ourPanel];
- QAbstractEventDispatcher::instance()->interrupt();
- [ourPanel release];
- [delegate cleanUpAfterMyself];
- [delegate release];
- bool isOk = (rval == NSOKButton);
- if(isOk)
- rescode = QDialog::Accepted;
+ QMacCocoaAutoReleasePool pool;
+ createNSFontPanelDelegate();
+ QCocoaFontPanelDelegate *del = static_cast<QCocoaFontPanelDelegate *>(delegate);
+ if (qt_mac_is_macsheet(q))
+ [del showWindowModalSheet:q->parentWidget()];
else
- rescode = QDialog::Rejected;
+ [del showModelessPanel];
+ return true;
}
+bool QFontDialogPrivate::hideCocoaFontPanel()
+{
+ if (!delegate){
+ // Nothing to do. We return false to leave the question
+ // open regarding whether or not to go native:
+ return false;
+ } else {
+ closeCocoaFontPanel();
+ // Even when we hide it, we are still using a
+ // native dialog, so return true:
+ return true;
+ }
+}
bool QFontDialogPrivate::setVisible_sys(bool visible)
{
Q_Q(QFontDialog);
if (!visible == q->isHidden())
return false;
- return visible;
+
+ return visible ? showCocoaFontPanel() : hideCocoaFontPanel();
}
QT_END_NAMESPACE
diff --git a/src/gui/dialogs/qfontdialog_p.h b/src/gui/dialogs/qfontdialog_p.h
index 7654a80..8676be3 100644
--- a/src/gui/dialogs/qfontdialog_p.h
+++ b/src/gui/dialogs/qfontdialog_p.h
@@ -139,25 +139,21 @@ public:
QByteArray memberToDisconnectOnClose;
#ifdef Q_WS_MAC
- static void *openCocoaFontPanel(const QFont &initial,
- QWidget *parent, const QString &title,
- QFontDialog::FontDialogOptions options,
- QFontDialogPrivate *priv = 0);
- static void closeCocoaFontPanel(void *delegate);
- static QFont execCocoaFontPanel(bool *ok, const QFont &initial, QWidget *parent,
- const QString &title, QFontDialog::FontDialogOptions options);
static void setFont(void *delegate, const QFont &font);
inline void done(int result) { q_func()->done(result); }
inline QFontDialog *fontDialog() { return q_func(); }
void *delegate;
+ void closeCocoaFontPanel();
bool nativeDialogInUse;
bool canBeNativeDialog();
bool setVisible_sys(bool visible);
- void *_q_constructNativePanel();
+ void createNSFontPanelDelegate();
void _q_macRunNativeAppModalPanel();
void mac_nativeDialogModalHelp();
+ bool showCocoaFontPanel();
+ bool hideCocoaFontPanel();
static bool sharedFontPanelAvailable;
#endif
diff --git a/src/gui/dialogs/qmessagebox.cpp b/src/gui/dialogs/qmessagebox.cpp
index ed437ff..fe25b0f 100644
--- a/src/gui/dialogs/qmessagebox.cpp
+++ b/src/gui/dialogs/qmessagebox.cpp
@@ -65,6 +65,10 @@
#include <QtGui/qfontmetrics.h>
#include <QtGui/qclipboard.h>
+#ifndef QT_NO_STYLE_S60
+#include <qs60style.h>
+#endif
+
#ifdef Q_WS_WINCE
extern bool qt_wince_is_mobile(); //defined in qguifunctions_wince.cpp
extern bool qt_wince_is_smartphone();//defined in qguifunctions_wince.cpp
@@ -118,14 +122,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 +215,7 @@ public:
QAbstractButton *escapeButton;
QPushButton *defaultButton;
QAbstractButton *clickedButton;
- QPushButton *detailsButton;
+ DetailButton *detailsButton;
#ifndef QT_NO_TEXTEDIT
QMessageBoxDetailsText *detailsText;
#endif
@@ -314,6 +348,7 @@ void QMessageBoxPrivate::updateSize()
}
width = hardLimit;
}
+ }
#ifdef Q_WS_S60
// in S60 portait messageBoxes should always occupy maximum width
if (QApplication::desktop()->size().height() > QApplication::desktop()->size().width()){
@@ -323,7 +358,6 @@ void QMessageBoxPrivate::updateSize()
width = qMin(QApplication::desktop()->size().height(), hardLimit);
}
#endif
- }
if (informativeLabel) {
label->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
@@ -353,6 +387,16 @@ void QMessageBoxPrivate::updateSize()
int height = (layout->hasHeightForWidth())
? layout->totalHeightForWidth(width)
: layout->totalMinimumSize().height();
+
+#ifndef QT_NO_STYLE_S60
+ QS60Style *s60Style = 0;
+ s60Style = qobject_cast<QS60Style *>(QApplication::style());
+
+ //use custom pixel metric to deduce the minimum height of the messagebox
+ if (s60Style)
+ height = qMax(height, s60Style->pixelMetric((QStyle::PixelMetric)PM_MessageBoxHeight));
+#endif
+
q->setFixedSize(width, height);
QCoreApplication::removePostedEvents(q, QEvent::LayoutRequest);
}
@@ -421,7 +465,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 +1935,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 +2443,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
diff --git a/src/gui/dialogs/qprintdialog.h b/src/gui/dialogs/qprintdialog.h
index ecd50c1..94177ea 100644
--- a/src/gui/dialogs/qprintdialog.h
+++ b/src/gui/dialogs/qprintdialog.h
@@ -56,7 +56,7 @@ class QPrintDialogPrivate;
class QPushButton;
class QPrinter;
-#if defined (Q_OS_UNIX) && !defined(QTOPIA_PRINTDIALOG) && !defined(Q_WS_MAC)
+#if defined (Q_OS_UNIX) && !defined(QTOPIA_PRINTDIALOG) && !defined(Q_WS_MAC) && !defined(Q_OS_SYMBIAN)
class QUnixPrintWidgetPrivate;
class Q_GUI_EXPORT QUnixPrintWidget : public QWidget
diff --git a/src/gui/dialogs/qprintdialog_qws.cpp b/src/gui/dialogs/qprintdialog_qws.cpp
index 1336c04..b071427 100644
--- a/src/gui/dialogs/qprintdialog_qws.cpp
+++ b/src/gui/dialogs/qprintdialog_qws.cpp
@@ -178,6 +178,10 @@ void QPrintDialogPrivate::_q_okClicked()
q->setPrintRange(QPrintDialog::PageRange);
q->setFromTo(firstPage->value(), lastPage->value());
break;
+ case (int)QPrintDialog::CurrentPage:
+ q->setPrintRange(QPrintDialog::CurrentPage);
+ q->setFromTo(0, 0);
+ break;
}
q->accept();
}
@@ -375,6 +379,7 @@ void QPrintDialogPrivate::setupOptions()
rangeCombo->addItem(QPrintDialog::tr("Print all"), QPrintDialog::AllPages);
rangeCombo->addItem(QPrintDialog::tr("Print selection"), QPrintDialog::Selection);
rangeCombo->addItem(QPrintDialog::tr("Print range"), QPrintDialog::PageRange);
+ rangeCombo->addItem(QPrintDialog::tr("Print current page"), QPrintDialog::CurrentPage);
QObject::connect(rangeCombo, SIGNAL(activated(int)),
q, SLOT(_q_printRangeSelected(int)));
@@ -490,6 +495,9 @@ void QPrintDialogPrivate::setPrinter(QPrinter *p, bool pickUpSettings)
if (!q->isOptionEnabled(QPrintDialog::PrintPageRange)
&& rangeCombo->findData(QPrintDialog::PageRange) > 0)
rangeCombo->removeItem(rangeCombo->findData(QPrintDialog::PageRange));
+ if (!q->isOptionEnabled(QPrintDialog::PrintCurrentPage)
+ && rangeCombo->findData(QPrintDialog::CurrentPage) > 0)
+ rangeCombo->removeItem(rangeCombo->findData(QPrintDialog::CurrentPage));
switch (q->printRange()) {
case QPrintDialog::AllPages:
@@ -501,6 +509,9 @@ void QPrintDialogPrivate::setPrinter(QPrinter *p, bool pickUpSettings)
case QPrintDialog::PageRange:
rangeCombo->setCurrentIndex((int)(QPrintDialog::PageRange));
break;
+ case QPrintDialog::CurrentPage:
+ rangeCombo->setCurrentIndex((int)(QPrintDialog::CurrentPage));
+ break;
}
}
diff --git a/src/gui/dialogs/qprintdialog_unix.cpp b/src/gui/dialogs/qprintdialog_unix.cpp
index 2d169cf..9b4d6e8 100644
--- a/src/gui/dialogs/qprintdialog_unix.cpp
+++ b/src/gui/dialogs/qprintdialog_unix.cpp
@@ -152,6 +152,9 @@ public:
bool checkFields();
void setupPrinter();
void setOptionsPane(QPrintDialogPrivate *pane);
+#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
+ void setCupsProperties();
+#endif
// slots
void _q_printerChanged(int index);
@@ -502,6 +505,9 @@ void QPrintDialogPrivate::setupPrinter()
} else if (options.printSelection->isChecked()) {
p->setPrintRange(QPrinter::Selection);
p->setFromTo(0,0);
+ } else if (options.printCurrentPage->isChecked()) {
+ p->setPrintRange(QPrinter::CurrentPage);
+ p->setFromTo(0,0);
} else if (options.printRange->isChecked()) {
p->setPrintRange(QPrinter::PageRange);
p->setFromTo(options.from->value(), qMax(options.from->value(), options.to->value()));
@@ -518,10 +524,12 @@ void QPrintDialogPrivate::updateWidgets()
{
Q_Q(QPrintDialog);
options.gbPrintRange->setVisible(q->isOptionEnabled(QPrintDialog::PrintPageRange) ||
- q->isOptionEnabled(QPrintDialog::PrintSelection));
+ q->isOptionEnabled(QPrintDialog::PrintSelection) ||
+ q->isOptionEnabled(QPrintDialog::PrintCurrentPage));
options.printRange->setEnabled(q->isOptionEnabled(QPrintDialog::PrintPageRange));
options.printSelection->setVisible(q->isOptionEnabled(QPrintDialog::PrintSelection));
+ options.printCurrentPage->setVisible(q->isOptionEnabled(QPrintDialog::PrintCurrentPage));
options.collate->setVisible(q->isOptionEnabled(QPrintDialog::PrintCollateCopies));
switch (q->printRange()) {
@@ -534,6 +542,10 @@ void QPrintDialogPrivate::updateWidgets()
case QPrintDialog::PageRange:
options.printRange->setChecked(true);
break;
+ case QPrintDialog::CurrentPage:
+ if (q->isOptionEnabled(QPrintDialog::PrintCurrentPage))
+ options.printCurrentPage->setChecked(true);
+ break;
default:
break;
}
@@ -694,9 +706,7 @@ QUnixPrintWidgetPrivate::QUnixPrintWidgetPrivate(QUnixPrintWidget *p)
#ifndef QT_NO_FILESYSTEMMODEL
QFileSystemModel *fsm = new QFileSystemModel(widget.filename);
fsm->setRootPath(QDir::homePath());
-#if !defined(QT_NO_FSCOMPLETER) && !defined(QT_NO_FILEDIALOG)
- widget.filename->setCompleter(new QFSCompleter(fsm, widget.filename));
-#endif
+ widget.filename->setCompleter(new QCompleter(fsm, widget.filename));
#endif
_q_printerChanged(currentPrinterIndex);
@@ -940,7 +950,7 @@ bool QUnixPrintWidgetPrivate::checkFields()
void QUnixPrintWidgetPrivate::_q_btnPropertiesClicked()
{
- if (propertiesDialog == 0) {
+ if (!propertiesDialog) {
propertiesDialog = new QPrintPropertiesDialog(q);
propertiesDialog->setResult(QDialog::Rejected);
}
@@ -960,6 +970,35 @@ void QUnixPrintWidgetPrivate::_q_btnPropertiesClicked()
propertiesDialog->exec();
}
+#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
+void QUnixPrintWidgetPrivate::setCupsProperties()
+{
+ if (cups && QCUPSSupport::isAvailable()) {
+ QPrintEngine *engine = printer->printEngine();
+ const ppd_option_t* pageSizes = cups->pageSizes();
+ QByteArray cupsPageSize;
+ for (int i = 0; i < pageSizes->num_choices; ++i) {
+ if (static_cast<int>(pageSizes->choices[i].marked) == 1)
+ cupsPageSize = pageSizes->choices[i].choice;
+ }
+ engine->setProperty(PPK_CupsStringPageSize, QString::fromLatin1(cupsPageSize));
+ engine->setProperty(PPK_CupsOptions, cups->options());
+
+ QRect pageRect = cups->pageRect(cupsPageSize);
+ engine->setProperty(PPK_CupsPageRect, pageRect);
+
+ QRect paperRect = cups->paperRect(cupsPageSize);
+ engine->setProperty(PPK_CupsPaperRect, paperRect);
+
+ for (int ps = 0; ps < QPrinter::NPaperSize; ++ps) {
+ QPdf::PaperSize size = QPdf::paperSize(QPrinter::PaperSize(ps));
+ if (size.width == paperRect.width() && size.height == paperRect.height())
+ printer->setPaperSize(static_cast<QPrinter::PaperSize>(ps));
+ }
+ }
+}
+#endif
+
void QUnixPrintWidgetPrivate::setupPrinter()
{
const int printerCount = widget.printers->count();
@@ -984,6 +1023,10 @@ void QUnixPrintWidgetPrivate::setupPrinter()
if (propertiesDialog && propertiesDialog->result() == QDialog::Accepted)
propertiesDialog->setupPrinter();
+#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
+ if (!propertiesDialog)
+ setCupsProperties();
+#endif
}
diff --git a/src/gui/dialogs/qprintdialog_win.cpp b/src/gui/dialogs/qprintdialog_win.cpp
index fa0c99f..38c8759 100644
--- a/src/gui/dialogs/qprintdialog_win.cpp
+++ b/src/gui/dialogs/qprintdialog_win.cpp
@@ -128,17 +128,20 @@ static void qt_win_setup_PRINTDLGEX(PRINTDLGEX *pd, QWidget *parent,
if (pd->nMinPage==0 && pd->nMaxPage==0)
pd->Flags |= PD_NOPAGENUMS;
- // we don't have a 'current page' notion in the QPrinter API yet.
- // Neither do we support more than one page range, so limit those
- // options
- pd->Flags |= PD_NOCURRENTPAGE;
+ // Disable Current Page option if not required as default is Enabled
+ if (!pdlg->isOptionEnabled(QPrintDialog::PrintCurrentPage))
+ pd->Flags |= PD_NOCURRENTPAGE;
+
+ // Default to showing the General tab first
pd->nStartPage = START_PAGE_GENERAL;
+
+ // We don't support more than one page range in the QPrinter API yet.
pd->nPageRanges = 1;
pd->nMaxPageRanges = 1;
if (d->ep->printToFile)
pd->Flags |= PD_PRINTTOFILE;
- Q_ASSERT(parent != 0 && parent->testAttribute(Qt::WA_WState_Created));
+ Q_ASSERT(parent);
pd->hwndOwner = parent->window()->winId();
pd->lpPageRanges[0].nFromPage = qMax(pdlg->fromPage(), pdlg->minPage());
pd->lpPageRanges[0].nToPage = (pdlg->toPage() > 0) ? qMin(pdlg->toPage(), pdlg->maxPage()) : 1;
@@ -153,7 +156,10 @@ static void qt_win_read_back_PRINTDLGEX(PRINTDLGEX *pd, QPrintDialog *pdlg, QPri
} else if (pd->Flags & PD_PAGENUMS) {
pdlg->setPrintRange(QPrintDialog::PageRange);
pdlg->setFromTo(pd->lpPageRanges[0].nFromPage, pd->lpPageRanges[0].nToPage);
- } else {
+ } else if (pd->Flags & PD_CURRENTPAGE) {
+ pdlg->setPrintRange(QPrintDialog::CurrentPage);
+ pdlg->setFromTo(0, 0);
+ } else { // PD_ALLPAGES
pdlg->setPrintRange(QPrintDialog::AllPages);
pdlg->setFromTo(0, 0);
}
diff --git a/src/gui/dialogs/qprintpreviewdialog.cpp b/src/gui/dialogs/qprintpreviewdialog.cpp
index 6723b53..f21343e 100644
--- a/src/gui/dialogs/qprintpreviewdialog.cpp
+++ b/src/gui/dialogs/qprintpreviewdialog.cpp
@@ -273,7 +273,20 @@ void QPrintPreviewDialogPrivate::init(QPrinter *_printer)
QWidget *pageEdit = new QWidget(toolbar);
QVBoxLayout *vboxLayout = new QVBoxLayout;
vboxLayout->setContentsMargins(0, 0, 0, 0);
+#ifdef Q_WS_MAC
+ // We query the widgets about their size and then we fix the size.
+ // This should do the trick for the laying out part...
+ QSize pageNumEditSize, pageNumLabelSize;
+ pageNumEditSize = pageNumEdit->minimumSizeHint();
+ pageNumLabelSize = pageNumLabel->minimumSizeHint();
+ pageNumEdit->resize(pageNumEditSize);
+ pageNumLabel->resize(pageNumLabelSize);
+#endif
QFormLayout *formLayout = new QFormLayout;
+#ifdef Q_WS_MAC
+ // We have to change the growth policy in Mac.
+ formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
+#endif
formLayout->setWidget(0, QFormLayout::LabelRole, pageNumEdit);
formLayout->setWidget(0, QFormLayout::FieldRole, pageNumLabel);
vboxLayout->addLayout(formLayout);
diff --git a/src/gui/dialogs/qprintsettingsoutput.ui b/src/gui/dialogs/qprintsettingsoutput.ui
index fc57e86..be91679 100644
--- a/src/gui/dialogs/qprintsettingsoutput.ui
+++ b/src/gui/dialogs/qprintsettingsoutput.ui
@@ -1,121 +1,114 @@
-<ui version="4.0" >
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
<class>QPrintSettingsOutput</class>
- <widget class="QWidget" name="QPrintSettingsOutput" >
- <property name="geometry" >
+ <widget class="QWidget" name="QPrintSettingsOutput">
+ <property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>416</width>
- <height>166</height>
+ <width>426</width>
+ <height>171</height>
</rect>
</property>
- <property name="windowTitle" >
+ <property name="windowTitle">
<string>Form</string>
</property>
- <layout class="QHBoxLayout" name="horizontalLayout_2" >
- <property name="margin" >
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <property name="margin">
<number>0</number>
</property>
<item>
- <widget class="QTabWidget" name="tabs" >
- <property name="currentIndex" >
+ <widget class="QTabWidget" name="tabs">
+ <property name="currentIndex">
<number>0</number>
</property>
- <widget class="QWidget" name="copiesTab" >
- <property name="geometry" >
- <rect>
- <x>0</x>
- <y>0</y>
- <width>412</width>
- <height>139</height>
- </rect>
- </property>
- <attribute name="title" >
+ <widget class="QWidget" name="copiesTab">
+ <attribute name="title">
<string>Copies</string>
</attribute>
- <layout class="QHBoxLayout" name="horizontalLayout" >
+ <layout class="QHBoxLayout" name="horizontalLayout">
<item>
- <widget class="QGroupBox" name="gbPrintRange" >
- <property name="sizePolicy" >
- <sizepolicy vsizetype="Minimum" hsizetype="Preferred" >
+ <widget class="QGroupBox" name="gbPrintRange">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="title" >
+ <property name="title">
<string>Print range</string>
</property>
- <layout class="QVBoxLayout" name="_3" >
- <property name="spacing" >
+ <layout class="QVBoxLayout" name="_3">
+ <property name="spacing">
<number>4</number>
</property>
- <property name="margin" >
+ <property name="margin">
<number>6</number>
</property>
<item>
- <widget class="QRadioButton" name="printAll" >
- <property name="text" >
+ <widget class="QRadioButton" name="printAll">
+ <property name="text">
<string>Print all</string>
</property>
- <property name="checked" >
+ <property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
- <layout class="QHBoxLayout" name="_4" >
- <property name="spacing" >
+ <layout class="QHBoxLayout" name="_4">
+ <property name="spacing">
<number>6</number>
</property>
- <property name="margin" >
+ <property name="margin">
<number>0</number>
</property>
<item>
- <widget class="QRadioButton" name="printRange" >
- <property name="text" >
+ <widget class="QRadioButton" name="printRange">
+ <property name="text">
<string>Pages from</string>
</property>
</widget>
</item>
<item>
- <widget class="QSpinBox" name="from" >
- <property name="enabled" >
+ <widget class="QSpinBox" name="from">
+ <property name="enabled">
<bool>false</bool>
</property>
- <property name="minimum" >
+ <property name="minimum">
<number>1</number>
</property>
- <property name="maximum" >
+ <property name="maximum">
<number>999</number>
</property>
</widget>
</item>
<item>
- <widget class="QLabel" name="label_3" >
- <property name="text" >
+ <widget class="QLabel" name="label_3">
+ <property name="text">
<string>to</string>
</property>
</widget>
</item>
<item>
- <widget class="QSpinBox" name="to" >
- <property name="enabled" >
+ <widget class="QSpinBox" name="to">
+ <property name="enabled">
<bool>false</bool>
</property>
- <property name="minimum" >
+ <property name="minimum">
<number>1</number>
</property>
- <property name="maximum" >
+ <property name="maximum">
<number>999</number>
</property>
</widget>
</item>
<item>
<spacer>
- <property name="orientation" >
+ <property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
- <property name="sizeHint" stdset="0" >
+ <property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>20</height>
@@ -126,18 +119,25 @@
</layout>
</item>
<item>
- <widget class="QRadioButton" name="printSelection" >
- <property name="text" >
+ <widget class="QRadioButton" name="printCurrentPage">
+ <property name="text">
+ <string>Current Page</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="printSelection">
+ <property name="text">
<string>Selection</string>
</property>
</widget>
</item>
<item>
- <spacer name="verticalSpacer" >
- <property name="orientation" >
+ <spacer name="verticalSpacer">
+ <property name="orientation">
<enum>Qt::Vertical</enum>
</property>
- <property name="sizeHint" stdset="0" >
+ <property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>1</height>
@@ -149,37 +149,37 @@
</widget>
</item>
<item>
- <widget class="QGroupBox" name="groupBox" >
- <property name="title" >
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
<string>Output Settings</string>
</property>
- <layout class="QGridLayout" name="gridLayout" >
- <item row="0" column="0" >
- <widget class="QLabel" name="label" >
- <property name="text" >
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
<string>Copies:</string>
</property>
- <property name="buddy" >
+ <property name="buddy">
<cstring>copies</cstring>
</property>
</widget>
</item>
- <item row="0" column="1" colspan="2" >
- <widget class="QSpinBox" name="copies" >
- <property name="minimum" >
+ <item row="0" column="1" colspan="2">
+ <widget class="QSpinBox" name="copies">
+ <property name="minimum">
<number>1</number>
</property>
- <property name="maximum" >
+ <property name="maximum">
<number>999</number>
</property>
</widget>
</item>
- <item row="0" column="3" >
- <spacer name="horizontalSpacer" >
- <property name="orientation" >
+ <item row="0" column="3">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
- <property name="sizeHint" stdset="0" >
+ <property name="sizeHint" stdset="0">
<size>
<width>91</width>
<height>20</height>
@@ -187,36 +187,36 @@
</property>
</spacer>
</item>
- <item row="1" column="0" colspan="2" >
- <widget class="QCheckBox" name="collate" >
- <property name="text" >
+ <item row="1" column="0" colspan="2">
+ <widget class="QCheckBox" name="collate">
+ <property name="text">
<string>Collate</string>
</property>
</widget>
</item>
- <item rowspan="2" row="1" column="2" colspan="2" >
- <widget class="QLabel" name="outputIcon" >
- <property name="sizePolicy" >
- <sizepolicy vsizetype="Ignored" hsizetype="Ignored" >
+ <item row="1" column="2" rowspan="2" colspan="2">
+ <widget class="QLabel" name="outputIcon">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Ignored" vsizetype="Ignored">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
- <item row="2" column="0" colspan="2" >
- <widget class="QCheckBox" name="reverse" >
- <property name="text" >
+ <item row="2" column="0" colspan="2">
+ <widget class="QCheckBox" name="reverse">
+ <property name="text">
<string>Reverse</string>
</property>
</widget>
</item>
- <item row="3" column="0" colspan="4" >
- <spacer name="verticalSpacer_2" >
- <property name="orientation" >
+ <item row="3" column="0" colspan="4">
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
<enum>Qt::Vertical</enum>
</property>
- <property name="sizeHint" stdset="0" >
+ <property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>1</height>
@@ -229,31 +229,23 @@
</item>
</layout>
</widget>
- <widget class="QWidget" name="optionsTab" >
- <property name="geometry" >
- <rect>
- <x>0</x>
- <y>0</y>
- <width>412</width>
- <height>139</height>
- </rect>
- </property>
- <attribute name="title" >
+ <widget class="QWidget" name="optionsTab">
+ <attribute name="title">
<string>Options</string>
</attribute>
- <layout class="QGridLayout" name="gridLayout_2" >
- <item row="0" column="1" >
- <widget class="QGroupBox" name="colorMode" >
- <property name="title" >
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="1">
+ <widget class="QGroupBox" name="colorMode">
+ <property name="title">
<string>Color Mode</string>
</property>
- <layout class="QGridLayout" name="gridLayout_4" >
- <item row="2" column="0" >
- <spacer name="verticalSpacer_6" >
- <property name="orientation" >
+ <layout class="QGridLayout" name="gridLayout_4">
+ <item row="2" column="0">
+ <spacer name="verticalSpacer_6">
+ <property name="orientation">
<enum>Qt::Vertical</enum>
</property>
- <property name="sizeHint" stdset="0" >
+ <property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>0</height>
@@ -261,19 +253,19 @@
</property>
</spacer>
</item>
- <item row="0" column="0" >
- <widget class="QRadioButton" name="color" >
- <property name="text" >
+ <item row="0" column="0">
+ <widget class="QRadioButton" name="color">
+ <property name="text">
<string>Color</string>
</property>
</widget>
</item>
- <item rowspan="3" row="0" column="1" >
- <widget class="QLabel" name="colorIcon" />
+ <item row="0" column="1" rowspan="3">
+ <widget class="QLabel" name="colorIcon"/>
</item>
- <item row="1" column="0" >
- <widget class="QRadioButton" name="grayscale" >
- <property name="text" >
+ <item row="1" column="0">
+ <widget class="QRadioButton" name="grayscale">
+ <property name="text">
<string>Grayscale</string>
</property>
</widget>
@@ -281,42 +273,42 @@
</layout>
</widget>
</item>
- <item row="0" column="0" >
- <widget class="QGroupBox" name="duplex" >
- <property name="title" >
+ <item row="0" column="0">
+ <widget class="QGroupBox" name="duplex">
+ <property name="title">
<string>Duplex Printing</string>
</property>
- <layout class="QVBoxLayout" name="verticalLayout" >
+ <layout class="QVBoxLayout" name="verticalLayout">
<item>
- <widget class="QRadioButton" name="noDuplex" >
- <property name="text" >
+ <widget class="QRadioButton" name="noDuplex">
+ <property name="text">
<string>None</string>
</property>
- <property name="checked" >
+ <property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
- <widget class="QRadioButton" name="duplexLong" >
- <property name="text" >
+ <widget class="QRadioButton" name="duplexLong">
+ <property name="text">
<string>Long side</string>
</property>
</widget>
</item>
<item>
- <widget class="QRadioButton" name="duplexShort" >
- <property name="text" >
+ <widget class="QRadioButton" name="duplexShort">
+ <property name="text">
<string>Short side</string>
</property>
</widget>
</item>
<item>
- <spacer name="verticalSpacer_42" >
- <property name="orientation" >
+ <spacer name="verticalSpacer_42">
+ <property name="orientation">
<enum>Qt::Vertical</enum>
</property>
- <property name="sizeHint" stdset="0" >
+ <property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>0</height>
@@ -341,11 +333,11 @@
<receiver>from</receiver>
<slot>setEnabled(bool)</slot>
<hints>
- <hint type="sourcelabel" >
+ <hint type="sourcelabel">
<x>76</x>
<y>59</y>
</hint>
- <hint type="destinationlabel" >
+ <hint type="destinationlabel">
<x>122</x>
<y>57</y>
</hint>
@@ -357,11 +349,11 @@
<receiver>to</receiver>
<slot>setEnabled(bool)</slot>
<hints>
- <hint type="sourcelabel" >
+ <hint type="sourcelabel">
<x>69</x>
<y>67</y>
</hint>
- <hint type="destinationlabel" >
+ <hint type="destinationlabel">
<x>215</x>
<y>67</y>
</hint>
diff --git a/src/gui/dialogs/qprogressdialog.cpp b/src/gui/dialogs/qprogressdialog.cpp
index 4fffdba..a2d7b23 100644
--- a/src/gui/dialogs/qprogressdialog.cpp
+++ b/src/gui/dialogs/qprogressdialog.cpp
@@ -46,7 +46,6 @@
#include "qshortcut.h"
#include "qpainter.h"
#include "qdrawutil.h"
-#include "qdatetime.h"
#include "qlabel.h"
#include "qprogressbar.h"
#include "qapplication.h"
@@ -54,6 +53,7 @@
#include "qpushbutton.h"
#include "qcursor.h"
#include "qtimer.h"
+#include "qelapsedtimer.h"
#include <private/qdialog_p.h>
#include <limits.h>
@@ -103,7 +103,7 @@ public:
QTimer *forceTimer;
bool shown_once;
bool cancellation_flag;
- QTime starttime;
+ QElapsedTimer starttime;
#ifndef QT_NO_CURSOR
QCursor parentCursor;
#endif
diff --git a/src/gui/dialogs/qwizard.cpp b/src/gui/dialogs/qwizard.cpp
index a58057d..8607529 100644
--- a/src/gui/dialogs/qwizard.cpp
+++ b/src/gui/dialogs/qwizard.cpp
@@ -218,8 +218,8 @@ public:
: topLevelMarginLeft(-1), topLevelMarginRight(-1), topLevelMarginTop(-1),
topLevelMarginBottom(-1), childMarginLeft(-1), childMarginRight(-1),
childMarginTop(-1), childMarginBottom(-1), hspacing(-1), vspacing(-1),
- wizStyle(QWizard::ClassicStyle), header(false), watermark(false), title(false),
- subTitle(false), extension(false) {}
+ wizStyle(QWizard::ClassicStyle), header(false), watermark(false), title(false),
+ subTitle(false), extension(false), sideWidget(false) {}
int topLevelMarginLeft;
int topLevelMarginRight;
@@ -238,6 +238,7 @@ public:
bool title;
bool subTitle;
bool extension;
+ bool sideWidget;
bool operator==(const QWizardLayoutInfo &other);
inline bool operator!=(const QWizardLayoutInfo &other) { return !operator==(other); }
@@ -261,7 +262,8 @@ bool QWizardLayoutInfo::operator==(const QWizardLayoutInfo &other)
&& watermark == other.watermark
&& title == other.title
&& subTitle == other.subTitle
- && extension == other.extension;
+ && extension == other.extension
+ && sideWidget == other.sideWidget;
}
class QWizardHeader : public QWidget
@@ -425,6 +427,40 @@ public:
: QWizardHeader(Ruler, parent) {}
};
+class QWatermarkLabel : public QLabel
+{
+public:
+ QWatermarkLabel(QWidget *parent, QWidget *sideWidget) : QLabel(parent), m_sideWidget(sideWidget) {
+ m_layout = new QVBoxLayout(this);
+ if (m_sideWidget)
+ m_layout->addWidget(m_sideWidget);
+ }
+
+ QSize minimumSizeHint() const {
+ if (!pixmap() && !pixmap()->isNull())
+ return pixmap()->size();
+ return QFrame::minimumSizeHint();
+ }
+
+ void setSideWidget(QWidget *widget) {
+ if (m_sideWidget == widget)
+ return;
+ if (m_sideWidget) {
+ m_layout->removeWidget(m_sideWidget);
+ m_sideWidget->hide();
+ }
+ m_sideWidget = widget;
+ if (m_sideWidget)
+ m_layout->addWidget(m_sideWidget);
+ }
+ QWidget *sideWidget() const {
+ return m_sideWidget;
+ }
+private:
+ QVBoxLayout *m_layout;
+ QWidget *m_sideWidget;
+};
+
class QWizardPagePrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QWizardPage)
@@ -501,6 +537,7 @@ public:
inline QWizardPrivate()
: start(-1)
+ , startSetByUser(false)
, current(-1)
, canContinue(false)
, canFinish(false)
@@ -513,6 +550,7 @@ public:
, placeholderWidget2(0)
, headerWidget(0)
, watermarkLabel(0)
+ , sideWidget(0)
, titleLabel(0)
, subTitleLabel(0)
, bottomRuler(0)
@@ -581,6 +619,7 @@ public:
QList<int> history;
QSet<int> initialized; // ### remove and move bit to QWizardPage?
int start;
+ bool startSetByUser;
int current;
bool canContinue;
bool canFinish;
@@ -612,7 +651,8 @@ public:
QWidget *placeholderWidget1;
QWidget *placeholderWidget2;
QWizardHeader *headerWidget;
- QLabel *watermarkLabel;
+ QWatermarkLabel *watermarkLabel;
+ QWidget *sideWidget;
QFrame *pageFrame;
QLabel *titleLabel;
QLabel *subTitleLabel;
@@ -907,11 +947,12 @@ QWizardLayoutInfo QWizardPrivate::layoutInfoForCurrentPage()
info.header = (info.wizStyle == QWizard::ClassicStyle || info.wizStyle == QWizard::ModernStyle)
&& !(opts & QWizard::IgnoreSubTitles) && !subTitleText.isEmpty();
+ info.sideWidget = sideWidget;
info.watermark = (info.wizStyle != QWizard::MacStyle) && (info.wizStyle != QWizard::AeroStyle)
&& !watermarkPixmap.isNull();
info.title = !info.header && !titleText.isEmpty();
info.subTitle = !(opts & QWizard::IgnoreSubTitles) && !info.header && !subTitleText.isEmpty();
- info.extension = info.watermark && (opts & QWizard::ExtendedWatermarkPixmap);
+ info.extension = (info.watermark || info.sideWidget) && (opts & QWizard::ExtendedWatermarkPixmap);
return info;
}
@@ -954,7 +995,7 @@ void QWizardPrivate::recreateLayout(const QWizardLayoutInfo &info)
int numColumns;
if (mac) {
numColumns = 3;
- } else if (info.watermark) {
+ } else if (info.watermark || info.sideWidget) {
numColumns = 2;
} else {
numColumns = 1;
@@ -1096,8 +1137,8 @@ void QWizardPrivate::recreateLayout(const QWizardLayoutInfo &info)
pageFrame->setContentsMargins(hMargin, vMargin, hMargin, vMargin);
}
- if (info.watermark && !watermarkLabel) {
- watermarkLabel = new QLabel(antiFlickerWidget);
+ if ((info.watermark || info.sideWidget) && !watermarkLabel) {
+ watermarkLabel = new QWatermarkLabel(antiFlickerWidget, sideWidget);
watermarkLabel->setBackgroundRole(QPalette::Base);
watermarkLabel->setMinimumHeight(1);
watermarkLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
@@ -1173,7 +1214,7 @@ void QWizardPrivate::recreateLayout(const QWizardLayoutInfo &info)
mainLayout->addLayout(buttonLayout, row++, buttonStartColumn, 1, buttonNumColumns);
- if (info.watermark) {
+ if (info.watermark || info.sideWidget) {
if (info.extension)
watermarkEndRow = row;
mainLayout->addWidget(watermarkLabel, watermarkStartRow, 0,
@@ -1193,7 +1234,7 @@ void QWizardPrivate::recreateLayout(const QWizardLayoutInfo &info)
if (bottomRuler)
bottomRuler->setVisible(classic || modern);
if (watermarkLabel)
- watermarkLabel->setVisible(info.watermark);
+ watermarkLabel->setVisible(info.watermark || info.sideWidget);
layoutInfo = info;
}
@@ -1233,10 +1274,17 @@ void QWizardPrivate::updateLayout()
titleFmt, subTitleFmt);
}
- if (info.watermark) {
- Q_ASSERT(page);
- watermarkLabel->setPixmap(page->pixmap(QWizard::WatermarkPixmap));
+ if (info.watermark || info.sideWidget) {
+ QPixmap pix;
+ if (info.watermark) {
+ if (page)
+ pix = page->pixmap(QWizard::WatermarkPixmap);
+ else
+ pix = q->pixmap(QWizard::WatermarkPixmap);
+ }
+ watermarkLabel->setPixmap(pix); // in case there is no watermark and we show the side widget we need to clear the watermark
}
+
if (info.title) {
Q_ASSERT(page);
titleLabel->setTextFormat(titleFmt);
@@ -1267,7 +1315,7 @@ void QWizardPrivate::updateMinMaxSizes(const QWizardLayoutInfo &info)
minimumSize.setWidth(headerWidget->maximumWidth());
maximumSize.setWidth(headerWidget->maximumWidth());
}
- if (info.watermark) {
+ if (info.watermark && !info.sideWidget) {
minimumSize.setHeight(mainLayout->totalSizeHint().height());
maximumSize.setHeight(mainLayout->totalSizeHint().height());
}
@@ -2149,7 +2197,7 @@ QWizard::~QWizard()
The ID is guaranteed to be larger than any other ID in the
QWizard so far.
- \sa setPage(), page()
+ \sa setPage(), page(), pageAdded()
*/
int QWizard::addPage(QWizardPage *page)
{
@@ -2166,7 +2214,10 @@ int QWizard::addPage(QWizardPage *page)
Adds the given \a page to the wizard with the given \a id.
- \sa addPage(), page()
+ \note Adding a page may influence the value of the startId property
+ in case it was not set explicitly.
+
+ \sa addPage(), page(), pageAdded()
*/
void QWizard::setPage(int theid, QWizardPage *page)
{
@@ -2210,12 +2261,19 @@ void QWizard::setPage(int theid, QWizardPage *page)
// hide new page and reset layout to old status
page->hide();
d->pageVBoxLayout->setEnabled(pageVBoxLayoutEnabled);
+
+ if (!d->startSetByUser && d->pageMap.constBegin().key() == theid)
+ d->start = theid;
+ emit pageAdded(theid);
}
/*!
Removes the page with the given \a id. cleanupPage() will be called if necessary.
+
+ \note Removing a page may influence the value of the startId property.
+
\since 4.5
- \sa addPage(), setPage()
+ \sa addPage(), setPage(), pageRemoved(), startId()
*/
void QWizard::removePage(int id)
{
@@ -2223,8 +2281,24 @@ void QWizard::removePage(int id)
QWizardPage *removedPage = 0;
- if (d->start == id)
- d->start = -1;
+ // update startItem accordingly
+ if (d->pageMap.count() > 0) { // only if we have any pages
+ if (d->start == id) {
+ const int firstId = d->pageMap.constBegin().key();
+ if (firstId == id) {
+ if (d->pageMap.count() > 1)
+ d->start = (++d->pageMap.constBegin()).key(); // secondId
+ else
+ d->start = -1; // removing the last page
+ } else { // startSetByUser has to be "true" here
+ d->start = firstId;
+ }
+ d->startSetByUser = false;
+ }
+ }
+
+ if (d->pageMap.contains(id))
+ emit pageRemoved(id);
if (!d->history.contains(id)) {
// Case 1: removing a page not in the history
@@ -2334,21 +2408,27 @@ QList<int> QWizard::pageIds() const
void QWizard::setStartId(int theid)
{
Q_D(QWizard);
- if (!d->pageMap.contains(theid)) {
- qWarning("QWizard::setStartId: Invalid page ID %d", theid);
+ int newStart = theid;
+ if (theid == -1)
+ newStart = d->pageMap.count() ? d->pageMap.constBegin().key() : -1;
+
+ if (d->start == newStart) {
+ d->startSetByUser = theid != -1;
return;
}
- d->start = theid;
+
+ if (!d->pageMap.contains(newStart)) {
+ qWarning("QWizard::setStartId: Invalid page ID %d", newStart);
+ return;
+ }
+ d->start = newStart;
+ d->startSetByUser = theid != -1;
}
int QWizard::startId() const
{
Q_D(const QWizard);
- if (d->start != -1)
- return d->start;
- if (!d->pageMap.isEmpty())
- return d->pageMap.constBegin().key();
- return -1;
+ return d->start;
}
/*!
@@ -2825,6 +2905,55 @@ void QWizard::setDefaultProperty(const char *className, const char *property,
}
/*!
+ \since 4.7
+
+ Sets the given \a widget to be shown on the left side of the wizard.
+ For styles which use the WatermarkPixmap (ClassicStyle and ModernStyle)
+ the side widget is displayed on top of the watermark, for other styles
+ or when the watermark is not provided the side widget is displayed
+ on the left side of the wizard.
+
+ Passing 0 shows no side widget.
+
+ When the \a widget is not 0 the wizard reparents it.
+
+ Any previous side widget is hidden.
+
+ You may call setSideWidget() with the same widget at different
+ times.
+
+ All widgets set here will be deleted by the wizard when it is
+ destroyed unless you separately reparent the widget after setting
+ some other side widget (or 0).
+
+ By default, no side widget is present.
+*/
+void QWizard::setSideWidget(QWidget *widget)
+{
+ Q_D(QWizard);
+
+ d->sideWidget = widget;
+ if (d->watermarkLabel) {
+ d->watermarkLabel->setSideWidget(widget);
+ d->updateLayout();
+ }
+}
+
+/*!
+ \since 4.7
+
+ Returns the widget on the left side of the wizard or 0.
+
+ By default, no side widget is present.
+*/
+QWidget *QWizard::sideWidget() const
+{
+ Q_D(const QWizard);
+
+ return d->sideWidget;
+}
+
+/*!
\reimp
*/
void QWizard::setVisible(bool visible)
@@ -2878,6 +3007,28 @@ QSize QWizard::sizeHint() const
*/
/*!
+ \fn void QWizard::pageAdded(int id)
+
+ \since 4.7
+
+ This signal is emitted whenever a page is added to the
+ wizard. The page's \a id is passed as parameter.
+
+ \sa addPage(), setPage(), startId()
+*/
+
+/*!
+ \fn void QWizard::pageRemoved(int id)
+
+ \since 4.7
+
+ This signal is emitted whenever a page is removed from the
+ wizard. The page's \a id is passed as parameter.
+
+ \sa removePage(), startId()
+*/
+
+/*!
\fn void QWizard::helpRequested()
This signal is emitted when the user clicks the \gui Help button.
diff --git a/src/gui/dialogs/qwizard.h b/src/gui/dialogs/qwizard.h
index 58b13fe..b146147 100644
--- a/src/gui/dialogs/qwizard.h
+++ b/src/gui/dialogs/qwizard.h
@@ -165,6 +165,9 @@ public:
void setPixmap(WizardPixmap which, const QPixmap &pixmap);
QPixmap pixmap(WizardPixmap which) const;
+ void setSideWidget(QWidget *widget);
+ QWidget *sideWidget() const;
+
void setDefaultProperty(const char *className, const char *property,
const char *changedSignal);
@@ -175,6 +178,8 @@ Q_SIGNALS:
void currentIdChanged(int id);
void helpRequested();
void customButtonClicked(int which);
+ void pageAdded(int id);
+ void pageRemoved(int id);
public Q_SLOTS:
void back();
diff --git a/src/gui/dialogs/qwizard_win_p.h b/src/gui/dialogs/qwizard_win_p.h
index fe01587..5f3b6c2 100644
--- a/src/gui/dialogs/qwizard_win_p.h
+++ b/src/gui/dialogs/qwizard_win_p.h
@@ -82,7 +82,6 @@ class QWizard;
class QVistaHelper : public QObject
{
- Q_OBJECT
public:
QVistaHelper(QWizard *wizard);
~QVistaHelper();
diff --git a/src/gui/egl/egl.pri b/src/gui/egl/egl.pri
index 669d311..b90b9b0 100644
--- a/src/gui/egl/egl.pri
+++ b/src/gui/egl/egl.pri
@@ -2,6 +2,7 @@ CONFIG += egl
HEADERS += \
egl/qegl_p.h \
+ egl/qeglcontext_p.h \
egl/qeglproperties_p.h
SOURCES += \
diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp
index 0ed95ea..6f215cc 100644
--- a/src/gui/egl/qegl.cpp
+++ b/src/gui/egl/qegl.cpp
@@ -43,7 +43,10 @@
#include <QtGui/qpixmap.h>
#include <QtGui/qwidget.h>
#include <QtCore/qdebug.h>
+
#include "qegl_p.h"
+#include "qeglcontext_p.h"
+
QT_BEGIN_NAMESPACE
@@ -54,12 +57,10 @@ QT_BEGIN_NAMESPACE
static QEglContext * volatile currentGLContext = 0;
static QEglContext * volatile currentVGContext = 0;
-EGLDisplay QEglContext::dpy = EGL_NO_DISPLAY;
-
QEglContext::QEglContext()
: apiType(QEgl::OpenGL)
, ctx(EGL_NO_CONTEXT)
- , cfg(0)
+ , cfg(QEGL_NO_CONFIG)
, currentSurface(EGL_NO_SURFACE)
, current(false)
, ownsContext(true)
@@ -87,15 +88,177 @@ bool QEglContext::isCurrent() const
return current;
}
+EGLConfig QEgl::defaultConfig(int devType, API api, ConfigOptions options)
+{
+ if ( (devType != QInternal::Pixmap) && ((options & Renderable) == 0))
+ qWarning("QEgl::defaultConfig() - Only configs for pixmaps make sense to be read-only!");
+
+ EGLConfig* targetConfig = 0;
+
+ static EGLConfig defaultVGConfigs[] = {
+ QEGL_NO_CONFIG, // 0 Window Renderable Translucent
+ QEGL_NO_CONFIG, // 1 Window Renderable Opaque
+ QEGL_NO_CONFIG, // 2 Pixmap Renderable Translucent
+ QEGL_NO_CONFIG, // 3 Pixmap Renderable Opaque
+ QEGL_NO_CONFIG, // 4 Pixmap ReadOnly Translucent
+ QEGL_NO_CONFIG // 5 Pixmap ReadOnly Opaque
+ };
+ if (api == OpenVG) {
+ if (devType == QInternal::Widget) {
+ if (options & Translucent)
+ targetConfig = &(defaultVGConfigs[0]);
+ else
+ targetConfig = &(defaultVGConfigs[1]);
+ } else if (devType == QInternal::Pixmap) {
+ if (options & Renderable) {
+ if (options & Translucent)
+ targetConfig = &(defaultVGConfigs[2]);
+ else // Opaque
+ targetConfig = &(defaultVGConfigs[3]);
+ } else { // Read-only
+ if (options & Translucent)
+ targetConfig = &(defaultVGConfigs[4]);
+ else // Opaque
+ targetConfig = &(defaultVGConfigs[5]);
+ }
+ }
+ }
+
+
+ static EGLConfig defaultGLConfigs[] = {
+ QEGL_NO_CONFIG, // 0 Window Renderable Translucent
+ QEGL_NO_CONFIG, // 1 Window Renderable Opaque
+ QEGL_NO_CONFIG, // 2 PBuffer Renderable Translucent
+ QEGL_NO_CONFIG, // 3 PBuffer Renderable Opaque
+ QEGL_NO_CONFIG, // 4 Pixmap Renderable Translucent
+ QEGL_NO_CONFIG, // 5 Pixmap Renderable Opaque
+ QEGL_NO_CONFIG, // 6 Pixmap ReadOnly Translucent
+ QEGL_NO_CONFIG // 7 Pixmap ReadOnly Opaque
+ };
+ if (api == OpenGL) {
+ if (devType == QInternal::Widget) {
+ if (options & Translucent)
+ targetConfig = &(defaultGLConfigs[0]);
+ else // Opaque
+ targetConfig = &(defaultGLConfigs[1]);
+ } else if (devType == QInternal::Pbuffer) {
+ if (options & Translucent)
+ targetConfig = &(defaultGLConfigs[2]);
+ else // Opaque
+ targetConfig = &(defaultGLConfigs[3]);
+ } else if (devType == QInternal::Pixmap) {
+ if (options & Renderable) {
+ if (options & Translucent)
+ targetConfig = &(defaultGLConfigs[4]);
+ else // Opaque
+ targetConfig = &(defaultGLConfigs[5]);
+ } else { // ReadOnly
+ if (options & Translucent)
+ targetConfig = &(defaultGLConfigs[6]);
+ else // Opaque
+ targetConfig = &(defaultGLConfigs[7]);
+ }
+ }
+ }
+
+ if (!targetConfig) {
+ qWarning("QEgl::defaultConfig() - No default config for device/api/options combo");
+ return QEGL_NO_CONFIG;
+ }
+ if (*targetConfig != QEGL_NO_CONFIG)
+ return *targetConfig;
+
+
+ // We haven't found an EGL config for the target config yet, so do it now:
+
+
+ // Allow overriding from an environment variable:
+ QByteArray configId;
+ if (api == OpenVG)
+ configId = qgetenv("QT_VG_EGL_CONFIG");
+ else
+ configId = qgetenv("QT_GL_EGL_CONFIG");
+ if (!configId.isEmpty()) {
+ // Overriden, so get the EGLConfig for the specified config ID:
+ EGLint properties[] = {
+ EGL_CONFIG_ID, (EGLint)configId.toInt(),
+ EGL_NONE
+ };
+ EGLint configCount = 0;
+ eglChooseConfig(display(), properties, targetConfig, 1, &configCount);
+ if (configCount > 0)
+ return *targetConfig;
+ qWarning() << "QEgl::defaultConfig() -" << configId << "appears to be invalid";
+ }
+
+ QEglProperties configAttribs;
+ configAttribs.setRenderableType(api);
+
+ EGLint surfaceType;
+ switch (devType) {
+ case QInternal::Widget:
+ surfaceType = EGL_WINDOW_BIT;
+ break;
+ case QInternal::Pixmap:
+ surfaceType = EGL_PIXMAP_BIT;
+ break;
+ case QInternal::Pbuffer:
+ surfaceType = EGL_PBUFFER_BIT;
+ break;
+ default:
+ qWarning("QEgl::defaultConfig() - Can't create EGL surface for %d device type", devType);
+ return QEGL_NO_CONFIG;
+ };
+#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
+ // For OpenVG, we try to create a surface using a pre-multiplied format if
+ // the surface needs to have an alpha channel:
+ if (api == OpenVG && (options & Translucent))
+ surfaceType |= EGL_VG_ALPHA_FORMAT_PRE_BIT;
+#endif
+ configAttribs.setValue(EGL_SURFACE_TYPE, surfaceType);
+
+#ifdef EGL_BIND_TO_TEXTURE_RGBA
+ if (devType == QInternal::Pixmap || devType == QInternal::Pbuffer) {
+ if (options & Translucent)
+ configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE);
+ else
+ configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE);
+ }
+#endif
+
+ // Add paint engine requirements
+ if (api == OpenVG) {
+#ifndef QVG_SCISSOR_CLIP
+ configAttribs.setValue(EGL_ALPHA_MASK_SIZE, 1);
+#endif
+ } else {
+ // Both OpenGL paint engines need to have stencil and sample buffers
+ configAttribs.setValue(EGL_STENCIL_SIZE, 1);
+ configAttribs.setValue(EGL_SAMPLE_BUFFERS, 1);
+#ifndef QT_OPENGL_ES_2
+ // Aditionally, the GL1 engine likes to have a depth buffer for clipping
+ configAttribs.setValue(EGL_DEPTH_SIZE, 1);
+#endif
+ }
+
+ if (options & Translucent)
+ configAttribs.setValue(EGL_ALPHA_SIZE, 1);
+
+ *targetConfig = chooseConfig(&configAttribs, QEgl::BestPixelFormat);
+ return *targetConfig;
+}
+
+
// Choose a configuration that matches "properties".
-bool QEglContext::chooseConfig
- (const QEglProperties& properties, QEgl::PixelFormatMatch match)
+EGLConfig QEgl::chooseConfig(const QEglProperties* properties, QEgl::PixelFormatMatch match)
{
- QEglProperties props(properties);
+ QEglProperties props(*properties);
+ EGLConfig cfg = QEGL_NO_CONFIG;
do {
// Get the number of matching configurations for this set of properties.
EGLint matching = 0;
- if (!eglChooseConfig(display(), props.properties(), 0, 0, &matching) || !matching)
+ EGLDisplay dpy = QEgl::display();
+ if (!eglChooseConfig(dpy, props.properties(), 0, 0, &matching) || !matching)
continue;
// If we want the best pixel format, then return the first
@@ -104,7 +267,7 @@ bool QEglContext::chooseConfig
eglChooseConfig(display(), props.properties(), &cfg, 1, &matching);
if (matching < 1)
continue;
- return true;
+ return cfg;
}
// Fetch all of the matching configurations and find the
@@ -125,7 +288,7 @@ bool QEglContext::chooseConfig
alpha == props.value(EGL_ALPHA_SIZE))) {
cfg = configs[index];
delete [] configs;
- return true;
+ return cfg;
}
}
delete [] configs;
@@ -142,11 +305,23 @@ bool QEglContext::chooseConfig
qWarning() << "QEglContext::chooseConfig(): Could not find a suitable EGL configuration";
qWarning() << "Requested:" << props.toString();
qWarning() << "Available:";
- dumpAllConfigs();
+ QEgl::dumpAllConfigs();
}
- return false;
+ return QEGL_NO_CONFIG;
}
+bool QEglContext::chooseConfig(const QEglProperties& properties, QEgl::PixelFormatMatch match)
+{
+ cfg = QEgl::chooseConfig(&properties, match);
+ return cfg != QEGL_NO_CONFIG;
+}
+
+EGLSurface QEglContext::createSurface(QPaintDevice* device, const QEglProperties *properties)
+{
+ return QEgl::createSurface(device, cfg, properties);
+}
+
+
// Create the EGLContext.
bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties *properties)
{
@@ -172,9 +347,9 @@ bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties
if (shareContext && shareContext->ctx == EGL_NO_CONTEXT)
shareContext = 0;
if (shareContext) {
- ctx = eglCreateContext(display(), cfg, shareContext->ctx, contextProps.properties());
+ ctx = eglCreateContext(QEgl::display(), cfg, shareContext->ctx, contextProps.properties());
if (ctx == EGL_NO_CONTEXT) {
- qWarning() << "QEglContext::createContext(): Could not share context:" << errorString(eglGetError());
+ qWarning() << "QEglContext::createContext(): Could not share context:" << QEgl::errorString();
shareContext = 0;
} else {
sharing = true;
@@ -183,7 +358,7 @@ bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties
if (ctx == EGL_NO_CONTEXT) {
ctx = eglCreateContext(display(), cfg, 0, contextProps.properties());
if (ctx == EGL_NO_CONTEXT) {
- qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << errorString(eglGetError());
+ qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << QEgl::errorString();
return false;
}
}
@@ -217,6 +392,11 @@ bool QEglContext::makeCurrent(EGLSurface surface)
return false;
}
+ if (surface == EGL_NO_SURFACE) {
+ qWarning() << "QEglContext::makeCurrent(): Cannot make invalid surface current";
+ return false;
+ }
+
// If lazyDoneCurrent() was called on the surface, then we may be able
// to assume that it is still current within the thread.
if (surface == currentSurface && currentContext(apiType) == this) {
@@ -240,9 +420,9 @@ bool QEglContext::makeCurrent(EGLSurface surface)
eglBindAPI(EGL_OPENVG_API);
#endif
- bool ok = eglMakeCurrent(display(), surface, surface, ctx);
+ bool ok = eglMakeCurrent(QEgl::display(), surface, surface, ctx);
if (!ok)
- qWarning() << "QEglContext::makeCurrent():" << errorString(eglGetError());
+ qWarning() << "QEglContext::makeCurrent(" << surface << "):" << QEgl::errorString();
return ok;
}
@@ -269,9 +449,9 @@ bool QEglContext::doneCurrent()
eglBindAPI(EGL_OPENVG_API);
#endif
- bool ok = eglMakeCurrent(display(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ bool ok = eglMakeCurrent(QEgl::display(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (!ok)
- qWarning() << "QEglContext::doneCurrent():" << errorString(eglGetError());
+ qWarning() << "QEglContext::doneCurrent():" << QEgl::errorString();
return ok;
}
@@ -291,9 +471,9 @@ bool QEglContext::swapBuffers(EGLSurface surface)
if(ctx == EGL_NO_CONTEXT)
return false;
- bool ok = eglSwapBuffers(display(), surface);
+ bool ok = eglSwapBuffers(QEgl::display(), surface);
if (!ok)
- qWarning() << "QEglContext::swapBuffers():" << errorString(eglGetError());
+ qWarning() << "QEglContext::swapBuffers():" << QEgl::errorString();
return ok;
}
@@ -330,59 +510,106 @@ void QEglContext::waitClient()
// Query the value of a configuration attribute.
bool QEglContext::configAttrib(int name, EGLint *value) const
{
- return eglGetConfigAttrib(display(), cfg, name, value);
+ return eglGetConfigAttrib(QEgl::display(), cfg, name, value);
}
-// Retrieve all of the properties on "cfg". If zero, return
-// the context's configuration.
-QEglProperties QEglContext::configProperties(EGLConfig cfg) const
+int QEglContext::configAttrib(int name) const
{
- if (!cfg)
- cfg = config();
- QEglProperties props;
- for (int name = 0x3020; name <= 0x304F; ++name) {
- EGLint value;
- if (name != EGL_NONE && eglGetConfigAttrib(display(), cfg, name, &value))
- props.setValue(name, value);
- }
- eglGetError(); // Clear the error state.
- return props;
+ EGLint value;
+ EGLBoolean success = eglGetConfigAttrib(QEgl::display(), cfg, name, &value);
+ if (success)
+ return value;
+ else
+ return EGL_DONT_CARE;
+}
+
+QEglProperties QEglContext::configProperties() const
+{
+ return QEglProperties(config());
}
-EGLDisplay QEglContext::display()
+#if (defined(EGL_KHR_image) || defined(EGL_KHR_image_base)) && !defined(EGL_EGLEXT_PROTOTYPES)
+_eglCreateImageKHR eglCreateImageKHR = 0;
+_eglDestroyImageKHR eglDestroyImageKHR = 0;
+#endif
+
+EGLDisplay QEgl::display()
{
+ static EGLDisplay dpy = EGL_NO_DISPLAY;
static bool openedDisplay = false;
if (!openedDisplay) {
dpy = eglGetDisplay(nativeDisplay());
openedDisplay = true;
if (dpy == EGL_NO_DISPLAY) {
- qWarning("QEglContext::display(): Falling back to EGL_DEFAULT_DISPLAY");
+ qWarning("QEgl::display(): Falling back to EGL_DEFAULT_DISPLAY");
dpy = eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY));
}
if (dpy == EGL_NO_DISPLAY) {
- qWarning("QEglContext::display(): Can't even open the default display");
+ qWarning("QEgl::display(): Can't even open the default display");
return EGL_NO_DISPLAY;
}
if (!eglInitialize(dpy, NULL, NULL)) {
- qWarning() << "QEglContext::display(): Cannot initialize EGL display:" << errorString(eglGetError());
+ qWarning() << "QEgl::display(): Cannot initialize EGL display:" << QEgl::errorString();
return EGL_NO_DISPLAY;
}
+
+ // Resolve the egl extension function pointers:
+#if (defined(EGL_KHR_image) || defined(EGL_KHR_image_base)) && !defined(EGL_EGLEXT_PROTOTYPES)
+ if (QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_base")) {
+ eglCreateImageKHR = (_eglCreateImageKHR) eglGetProcAddress("eglCreateImageKHR");
+ eglDestroyImageKHR = (_eglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR");
+ }
+#endif
}
return dpy;
}
-#if !defined(Q_WS_X11) && !defined(Q_WS_WINCE) // WinCE & X11 implement this properly
-EGLNativeDisplayType QEglContext::nativeDisplay()
+#ifndef Q_WS_X11
+EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig cfg, const QEglProperties *properties)
{
- return EGL_DEFAULT_DISPLAY;
+ // Create the native drawable for the paint device.
+ int devType = device->devType();
+ EGLNativePixmapType pixmapDrawable = 0;
+ EGLNativeWindowType windowDrawable = 0;
+ bool ok;
+ if (devType == QInternal::Pixmap) {
+ pixmapDrawable = nativePixmap(static_cast<QPixmap *>(device));
+ ok = (pixmapDrawable != 0);
+ } else if (devType == QInternal::Widget) {
+ windowDrawable = nativeWindow(static_cast<QWidget *>(device));
+ ok = (windowDrawable != 0);
+ } else {
+ ok = false;
+ }
+ if (!ok) {
+ qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable");
+ return EGL_NO_SURFACE;
+ }
+
+ // Create the EGL surface to draw into, based on the native drawable.
+ const int *props;
+ if (properties)
+ props = properties->properties();
+ else
+ props = 0;
+ EGLSurface surf;
+ if (devType == QInternal::Widget)
+ surf = eglCreateWindowSurface(QEgl::display(), cfg, windowDrawable, props);
+ else
+ surf = eglCreatePixmapSurface(QEgl::display(), cfg, pixmapDrawable, props);
+ if (surf == EGL_NO_SURFACE) {
+ qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError());
+ }
+ return surf;
}
#endif
+
// Return the error string associated with a specific code.
-QString QEglContext::errorString(EGLint code)
+QString QEgl::errorString(EGLint code)
{
static const char * const errors[] = {
"Success (0x3000)", // No tr
@@ -408,8 +635,24 @@ QString QEglContext::errorString(EGLint code)
}
}
+QString QEgl::errorString()
+{
+ return errorString(error());
+}
+
+void QEgl::clearError()
+{
+ eglGetError();
+}
+
+EGLint QEgl::error()
+{
+ return eglGetError();
+}
+
+
// Dump all of the EGL configurations supported by the system.
-void QEglContext::dumpAllConfigs()
+void QEgl::dumpAllConfigs()
{
QEglProperties props;
EGLint count = 0;
@@ -418,23 +661,23 @@ void QEglContext::dumpAllConfigs()
EGLConfig *configs = new EGLConfig [count];
eglGetConfigs(display(), configs, count, &count);
for (EGLint index = 0; index < count; ++index) {
- props = configProperties(configs[index]);
+ props = QEglProperties(configs[index]);
qWarning() << props.toString();
}
delete [] configs;
}
-QString QEglContext::extensions()
+QString QEgl::extensions()
{
- const char* exts = eglQueryString(QEglContext::display(), EGL_EXTENSIONS);
+ const char* exts = eglQueryString(QEgl::display(), EGL_EXTENSIONS);
return QString(QLatin1String(exts));
}
-bool QEglContext::hasExtension(const char* extensionName)
+bool QEgl::hasExtension(const char* extensionName)
{
QList<QByteArray> extensions =
QByteArray(reinterpret_cast<const char *>
- (eglQueryString(QEglContext::display(), EGL_EXTENSIONS))).split(' ');
+ (eglQueryString(QEgl::display(), EGL_EXTENSIONS))).split(' ');
return extensions.contains(extensionName);
}
diff --git a/src/gui/egl/qegl_p.h b/src/gui/egl/qegl_p.h
index 87ed818..540cd3d 100644
--- a/src/gui/egl/qegl_p.h
+++ b/src/gui/egl/qegl_p.h
@@ -53,13 +53,40 @@
// We mean it.
//
-#include <QtCore/qsize.h>
-#include <QtGui/qimage.h>
+QT_BEGIN_INCLUDE_NAMESPACE
-#include <private/qeglproperties_p.h>
+#if defined(QT_OPENGL_ES_2)
+# include <GLES2/gl2.h>
+#endif
-QT_BEGIN_INCLUDE_NAMESPACE
+#if defined(QT_GLES_EGL)
+# include <GLES/egl.h>
+#else
+# include <EGL/egl.h>
+#endif
+
+#if defined(Q_WS_X11)
+// If <EGL/egl.h> included <X11/Xlib.h>, then the global namespace
+// may have been polluted with X #define's. The following makes sure
+// the X11 headers were included properly and then cleans things up.
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#undef Bool
+#undef Status
+#undef None
+#undef KeyPress
+#undef KeyRelease
+#undef FocusIn
+#undef FocusOut
+#undef Type
+#undef FontChange
+#undef CursorShape
+#undef Unsorted
+#undef GrayScale
+#endif
+// Internally we use the EGL-prefixed native types which are used in EGL >= 1.3.
+// For older versions of EGL, we have to define these types ourselves here:
#if !defined(EGL_VERSION_1_3) && !defined(QEGL_NATIVE_TYPES_DEFINED)
#undef EGLNativeWindowType
#undef EGLNativePixmapType
@@ -69,74 +96,124 @@ typedef NativePixmapType EGLNativePixmapType;
typedef NativeDisplayType EGLNativeDisplayType;
#define QEGL_NATIVE_TYPES_DEFINED 1
#endif
+
QT_END_INCLUDE_NAMESPACE
+#include <QtGui/qpaintdevice.h>
+#include <QFlags>
+
QT_BEGIN_NAMESPACE
-class Q_GUI_EXPORT QEglContext
-{
-public:
- QEglContext();
- ~QEglContext();
+#define QEGL_NO_CONFIG ((EGLConfig)-1)
- bool isValid() const;
- bool isCurrent() const;
- bool isSharing() const { return sharing; }
+#ifndef EGLAPIENTRY
+#define EGLAPIENTRY
+#endif
- QEgl::API api() const { return apiType; }
- void setApi(QEgl::API api) { apiType = api; }
+// Try to get some info to debug the symbian build failues:
+#ifdef Q_OS_SYMBIAN
- bool chooseConfig(const QEglProperties& properties, QEgl::PixelFormatMatch match = QEgl::ExactPixelFormat);
- bool createContext(QEglContext *shareContext = 0, const QEglProperties *properties = 0);
- void destroyContext();
- EGLSurface createSurface(QPaintDevice *device, const QEglProperties *properties = 0);
- void destroySurface(EGLSurface surface);
+#ifdef EGL_KHR_image
+#warning "EGL_KHR_image is defined"
+#else
+#warning "EGL_KHR_image is NOT defined"
+#endif
- bool makeCurrent(EGLSurface surface);
- bool doneCurrent();
- bool lazyDoneCurrent();
- bool swapBuffers(EGLSurface surface);
+#ifdef EGL_KHR_image_base
+#warning "EGL_KHR_image_base is defined"
+#else
+#warning "EGL_KHR_image_base is NOT defined"
+#endif
- void waitNative();
- void waitClient();
+#ifdef EGL_EGLEXT_PROTOTYPES
+#warning "EGL_EGLEXT_PROTOTYPES is defined"
+#else
+#warning "EGL_EGLEXT_PROTOTYPES NOT not defined"
+#endif
- bool configAttrib(int name, EGLint *value) const;
+#endif
+
+
+// Declare/define the bits of EGL_KHR_image_base we need:
+#if !defined(EGL_KHR_image) && !defined(EGL_KHR_image_base)
+typedef void *EGLImageKHR;
+#define EGL_NO_IMAGE_KHR ((EGLImageKHR)0)
+#define EGL_IMAGE_PRESERVED_KHR 0x30D2
+#endif
+
+// It is possible that something has included eglext.h (like Symbian 10.1's broken egl.h), in
+// which case, EGL_KHR_image/EGL_KHR_image_base will be defined. They may have also defined
+// the actual function prototypes, but generally EGL_EGLEXT_PROTOTYPES will be defined in that
+// case and we shouldn't re-define them here.
+#if (defined(EGL_KHR_image) || defined(EGL_KHR_image_base)) && !defined(EGL_EGLEXT_PROTOTYPES)
+typedef EGLImageKHR (EGLAPIENTRY *_eglCreateImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, EGLint*);
+typedef EGLBoolean (EGLAPIENTRY *_eglDestroyImageKHR)(EGLDisplay, EGLImageKHR);
+
+// Defined in qegl.cpp:
+extern Q_GUI_EXPORT _eglCreateImageKHR eglCreateImageKHR;
+extern Q_GUI_EXPORT _eglDestroyImageKHR eglDestroyImageKHR;
+#endif // (defined(EGL_KHR_image) || defined(EGL_KHR_image_base)) && !defined(EGL_EGLEXT_PROTOTYPES)
+
+#if !defined(EGL_KHR_image) && !defined(EGL_KHR_image_pixmap)
+#define EGL_NATIVE_PIXMAP_KHR 0x30B0
+#endif
- static void clearError() { eglGetError(); }
- static EGLint error() { return eglGetError(); }
- static QString errorString(EGLint code);
- static EGLDisplay display();
+class QEglProperties;
- EGLContext context() const { return ctx; }
- void setContext(EGLContext context) { ctx = context; ownsContext = false;}
+namespace QEgl {
+ enum API
+ {
+ OpenGL,
+ OpenVG
+ };
- EGLConfig config() const { return cfg; }
- void setConfig(EGLConfig config) { cfg = config; }
+ enum PixelFormatMatch
+ {
+ ExactPixelFormat,
+ BestPixelFormat
+ };
- QEglProperties configProperties(EGLConfig cfg = 0) const;
+ enum ConfigOption
+ {
+ NoOptions = 0,
+ Translucent = 0x01,
+ Renderable = 0x02 // Config will be compatable with the paint engines (VG or GL)
+ };
+ Q_DECLARE_FLAGS(ConfigOptions, ConfigOption);
- void dumpAllConfigs();
+ // Most of the time we use the same config for things like widgets & pixmaps, so rather than
+ // go through the eglChooseConfig loop every time, we use defaultConfig, which will return
+ // the config for a particular device/api/option combo. This function assumes that once a
+ // config is chosen for a particular combo, it's safe to always use that combo.
+ Q_GUI_EXPORT EGLConfig defaultConfig(int devType, API api, ConfigOptions options);
- static QString extensions();
- static bool hasExtension(const char* extensionName);
+ Q_GUI_EXPORT EGLConfig chooseConfig(const QEglProperties* configAttribs, QEgl::PixelFormatMatch match = QEgl::ExactPixelFormat);
+ Q_GUI_EXPORT EGLSurface createSurface(QPaintDevice *device, EGLConfig cfg, const QEglProperties *surfaceAttribs = 0);
-private:
- QEgl::API apiType;
- EGLContext ctx;
- EGLConfig cfg;
- EGLSurface currentSurface;
- bool current;
- bool ownsContext;
- bool sharing;
+ Q_GUI_EXPORT void dumpAllConfigs();
- static EGLDisplay dpy;
- static EGLNativeDisplayType nativeDisplay();
+ Q_GUI_EXPORT void clearError();
+ Q_GUI_EXPORT EGLint error();
+ Q_GUI_EXPORT QString errorString(EGLint code);
+ Q_GUI_EXPORT QString errorString();
- static QEglContext *currentContext(QEgl::API api);
- static void setCurrentContext(QEgl::API api, QEglContext *context);
+ Q_GUI_EXPORT QString extensions();
+ Q_GUI_EXPORT bool hasExtension(const char* extensionName);
+
+ Q_GUI_EXPORT EGLDisplay display();
+
+ Q_GUI_EXPORT EGLNativeDisplayType nativeDisplay();
+ Q_GUI_EXPORT EGLNativeWindowType nativeWindow(QWidget*);
+ Q_GUI_EXPORT EGLNativePixmapType nativePixmap(QPixmap*);
+
+#ifdef Q_WS_X11
+ Q_GUI_EXPORT VisualID getCompatibleVisualId(EGLConfig config);
+#endif
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QEgl::ConfigOptions);
+
QT_END_NAMESPACE
-#endif // QEGL_P_H
+#endif //QEGL_P_H
diff --git a/src/gui/egl/qegl_qws.cpp b/src/gui/egl/qegl_qws.cpp
index 2a61beb..56383a5 100644
--- a/src/gui/egl/qegl_qws.cpp
+++ b/src/gui/egl/qegl_qws.cpp
@@ -42,7 +42,9 @@
#include <QtGui/qpaintdevice.h>
#include <QtGui/qpixmap.h>
#include <QtGui/qwidget.h>
+
#include "qegl_p.h"
+#include "qeglcontext_p.h"
#if !defined(QT_NO_EGL)
@@ -53,17 +55,6 @@
QT_BEGIN_NAMESPACE
-// Create the surface for a QPixmap, QImage, or QWidget.
-// We don't have QGLScreen to create EGL surfaces for us,
-// so surface creation needs to be done in QtOpenGL or
-// QtOpenVG for Qt/Embedded.
-EGLSurface QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties)
-{
- Q_UNUSED(device);
- Q_UNUSED(properties);
- return EGL_NO_SURFACE;
-}
-
static QScreen *screenForDevice(QPaintDevice *device)
{
QScreen *screen = qt_screen;
@@ -101,6 +92,23 @@ void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev)
setPixelFormat(screen->pixelFormat());
}
+EGLNativeDisplayType QEgl::nativeDisplay()
+{
+ return EGL_DEFAULT_DISPLAY;
+}
+
+EGLNativeWindowType QEgl::nativeWindow(QWidget* widget)
+{
+ return (EGLNativeWindowType)(widget->winId()); // Might work
+}
+
+EGLNativePixmapType QEgl::nativePixmap(QPixmap*)
+{
+ qWarning("QEgl: EGL pixmap surfaces not supported on QWS");
+ return (EGLNativePixmapType)0;
+}
+
+
QT_END_NAMESPACE
#endif // !QT_NO_EGL
diff --git a/src/gui/egl/qegl_symbian.cpp b/src/gui/egl/qegl_symbian.cpp
index 5a010cd..9744ed0 100644
--- a/src/gui/egl/qegl_symbian.cpp
+++ b/src/gui/egl/qegl_symbian.cpp
@@ -42,48 +42,28 @@
#include <QtGui/qpaintdevice.h>
#include <QtGui/qpixmap.h>
#include <QtGui/qwidget.h>
+
#include "qegl_p.h"
+#include "qeglcontext_p.h"
#include <coecntrl.h>
QT_BEGIN_NAMESPACE
-EGLSurface QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties)
+EGLNativeDisplayType QEgl::nativeDisplay()
{
- // Create the native drawable for the paint device.
- int devType = device->devType();
- EGLNativePixmapType pixmapDrawable = 0;
- EGLNativeWindowType windowDrawable = 0;
- bool ok;
- if (devType == QInternal::Pixmap) {
- pixmapDrawable = 0;
- ok = (pixmapDrawable != 0);
- } else if (devType == QInternal::Widget) {
- QWidget *w = static_cast<QWidget *>(device);
- windowDrawable = (EGLNativeWindowType)(w->winId()->DrawableWindow());
- ok = (windowDrawable != 0);
- } else {
- ok = false;
- }
- if (!ok) {
- qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable");
- return EGL_NO_SURFACE;
- }
+ return EGL_DEFAULT_DISPLAY;
+}
- // Create the EGL surface to draw into, based on the native drawable.
- const int *props;
- if (properties)
- props = properties->properties();
- else
- props = 0;
- EGLSurface surf;
- if (devType == QInternal::Widget)
- surf = eglCreateWindowSurface(dpy, cfg, windowDrawable, props);
- else
- surf = eglCreatePixmapSurface(dpy, cfg, pixmapDrawable, props);
- if (surf == EGL_NO_SURFACE)
- qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError());
- return surf;
+EGLNativeWindowType QEgl::nativeWindow(QWidget* widget)
+{
+ return (EGLNativeWindowType)(widget->winId()->DrawableWindow());
+}
+
+EGLNativePixmapType QEgl::nativePixmap(QPixmap*)
+{
+ qWarning("QEgl: EGL pixmap surfaces not implemented yet on Symbian");
+ return (EGLNativePixmapType)0;
}
// Set pixel format and other properties based on a paint device.
diff --git a/src/gui/egl/qegl_wince.cpp b/src/gui/egl/qegl_wince.cpp
index c9c9773..2d08805 100644
--- a/src/gui/egl/qegl_wince.cpp
+++ b/src/gui/egl/qegl_wince.cpp
@@ -42,55 +42,18 @@
#include <QtGui/qpaintdevice.h>
#include <QtGui/qpixmap.h>
#include <QtGui/qwidget.h>
+
#include "qegl_p.h"
+#include "qeglcontext_p.h"
#include <windows.h>
QT_BEGIN_NAMESPACE
-EGLSurface QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties)
-{
- // Create the native drawable for the paint device.
- int devType = device->devType();
- EGLNativePixmapType pixmapDrawable = 0;
- EGLNativeWindowType windowDrawable = 0;
- bool ok;
- if (devType == QInternal::Pixmap) {
- pixmapDrawable = 0;
- ok = (pixmapDrawable != 0);
- } else if (devType == QInternal::Widget) {
- windowDrawable = (EGLNativeWindowType)(static_cast<QWidget *>(device))->winId();
- ok = (windowDrawable != 0);
- } else {
- ok = false;
- }
- if (!ok) {
- qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable");
- return EGL_NO_SURFACE;
- }
-
- // Create the EGL surface to draw into, based on the native drawable.
- const int *props;
- if (properties)
- props = properties->properties();
- else
- props = 0;
- EGLSurface surf;
- if (devType == QInternal::Widget)
- surf = eglCreateWindowSurface(dpy, cfg, windowDrawable, props);
- else
- surf = eglCreatePixmapSurface(dpy, cfg, pixmapDrawable, props);
- if (surf == EGL_NO_SURFACE) {
- qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError());
- }
- return surf;
-}
-
-EGLNativeDisplayType QEglContext::nativeDisplay()
+EGLNativeDisplayType QEgl::nativeDisplay()
{
- HWND win = (static_cast<QWidget*>(device))->winId();
- HDC myDc = GetDC(win);
+ HDC myDc = GetDC(0);
if (!myDc) {
qWarning("QEglContext::nativeDisplay(): WinCE display is not open");
return EGL_DEFAULT_DISPLAY;
@@ -98,6 +61,17 @@ EGLNativeDisplayType QEglContext::nativeDisplay()
return EGLNativeDisplayType(myDc);
}
+EGLNativeWindowType QEgl::nativeWindow(QWidget* widget)
+{
+ return (EGLNativeWindowType)(widget->winId());
+}
+
+EGLNativePixmapType QEgl::nativePixmap(QPixmap*)
+{
+ qWarning("QEgl: EGL pixmap surfaces not supported on WinCE");
+ return (EGLNativePixmapType)0;
+}
+
// Set pixel format and other properties based on a paint device.
void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev)
{
diff --git a/src/gui/egl/qegl_x11.cpp b/src/gui/egl/qegl_x11.cpp
index 634ff13..91423c8 100644
--- a/src/gui/egl/qegl_x11.cpp
+++ b/src/gui/egl/qegl_x11.cpp
@@ -41,59 +41,24 @@
#include <QtCore/qdebug.h>
-#include <private/qt_x11_p.h>
+#include <QtGui/private/qt_x11_p.h>
#include <QtGui/qx11info_x11.h>
-#include <private/qpixmapdata_p.h>
-#include <private/qpixmap_x11_p.h>
+#include <QtGui/private/qpixmapdata_p.h>
+#include <QtGui/private/qpixmap_x11_p.h>
+#include <QtGui/private/qimagepixmapcleanuphooks_p.h>
#include <QtGui/qpaintdevice.h>
#include <QtGui/qpixmap.h>
#include <QtGui/qwidget.h>
-#include "qegl_p.h"
+#include <QtGui/qcolormap.h>
+#include "QtGui/private/qegl_p.h"
+#include "QtGui/private/qeglcontext_p.h"
QT_BEGIN_NAMESPACE
-EGLSurface QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties)
-{
- // Create the native drawable for the paint device.
- int devType = device->devType();
- EGLNativePixmapType pixmapDrawable = 0;
- EGLNativeWindowType windowDrawable = 0;
- bool ok;
- if (devType == QInternal::Pixmap) {
- pixmapDrawable = (EGLNativePixmapType)(static_cast<QPixmap *>(device))->handle();
- ok = (pixmapDrawable != 0);
- } else if (devType == QInternal::Widget) {
- windowDrawable = (EGLNativeWindowType)(static_cast<QWidget *>(device))->winId();
- ok = (windowDrawable != 0);
- } else {
- ok = false;
- }
- if (!ok) {
- qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable");
- return EGL_NO_SURFACE;
- }
- // Create the EGL surface to draw into, based on the native drawable.
- const int *props;
- if (properties)
- props = properties->properties();
- else
- props = 0;
- EGLSurface surf;
- if (devType == QInternal::Widget)
- surf = eglCreateWindowSurface(dpy, cfg, windowDrawable, props);
- else
- surf = eglCreatePixmapSurface(dpy, cfg, pixmapDrawable, props);
- if (surf == EGL_NO_SURFACE) {
- qWarning() << "QEglContext::createSurface(): Unable to create EGL surface:"
- << errorString(eglGetError());
- }
- return surf;
-}
-
-EGLNativeDisplayType QEglContext::nativeDisplay()
+EGLNativeDisplayType QEgl::nativeDisplay()
{
Display *xdpy = QX11Info::display();
if (!xdpy) {
@@ -103,6 +68,16 @@ EGLNativeDisplayType QEglContext::nativeDisplay()
return EGLNativeDisplayType(xdpy);
}
+EGLNativeWindowType QEgl::nativeWindow(QWidget* widget)
+{
+ return (EGLNativeWindowType)(widget->winId());
+}
+
+EGLNativePixmapType QEgl::nativePixmap(QPixmap* pixmap)
+{
+ return (EGLNativePixmapType)(pixmap->handle());
+}
+
static int countBits(unsigned long mask)
{
int count = 0;
@@ -153,4 +128,292 @@ void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev)
setVisualFormat(qt_x11Info(dev));
}
+//#define QT_DEBUG_X11_VISUAL_SELECTION 1
+
+VisualID QEgl::getCompatibleVisualId(EGLConfig config)
+{
+ VisualID visualId = 0;
+ EGLint eglValue = 0;
+
+ EGLint configRedSize = 0;
+ eglGetConfigAttrib(display(), config, EGL_RED_SIZE, &configRedSize);
+
+ EGLint configGreenSize = 0;
+ eglGetConfigAttrib(display(), config, EGL_GREEN_SIZE, &configGreenSize);
+
+ EGLint configBlueSize = 0;
+ eglGetConfigAttrib(display(), config, EGL_BLUE_SIZE, &configBlueSize);
+
+ EGLint configAlphaSize = 0;
+ eglGetConfigAttrib(display(), config, EGL_ALPHA_SIZE, &configAlphaSize);
+
+ eglGetConfigAttrib(display(), config, EGL_BUFFER_SIZE, &eglValue);
+ int configBitDepth = eglValue;
+
+ eglGetConfigAttrib(display(), config, EGL_CONFIG_ID, &eglValue);
+ int configId = eglValue;
+
+ // See if EGL provided a valid VisualID:
+ eglGetConfigAttrib(display(), config, EGL_NATIVE_VISUAL_ID, &eglValue);
+ visualId = (VisualID)eglValue;
+ if (visualId) {
+ // EGL has suggested a visual id, so get the rest of the visual info for that id:
+ XVisualInfo visualInfoTemplate;
+ memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
+ visualInfoTemplate.visualid = visualId;
+
+ XVisualInfo *chosenVisualInfo;
+ int matchingCount = 0;
+ chosenVisualInfo = XGetVisualInfo(X11->display, VisualIDMask, &visualInfoTemplate, &matchingCount);
+ if (chosenVisualInfo) {
+ if (configBitDepth == chosenVisualInfo->depth) {
+#if !defined(QT_NO_XRENDER)
+ // If we have XRender, actually check the visual supplied by EGL is ARGB
+ if (configAlphaSize > 0) {
+ XRenderPictFormat *format;
+ format = XRenderFindVisualFormat(X11->display, chosenVisualInfo->visual);
+ if (!format || (format->type != PictTypeDirect) || (!format->direct.alphaMask)) {
+ qWarning("Warning: EGL suggested using X visual ID %d for config %d, but this is not ARGB",
+ (int)visualId, configId);
+ visualId = 0;
+ }
+ }
+#endif
+ } else {
+ qWarning("Warning: EGL suggested using X visual ID %d (%d bpp) for config %d (%d bpp), but the depths do not match!",
+ (int)visualId, chosenVisualInfo->depth, configId, configBitDepth);
+ visualId = 0;
+ }
+ }
+ XFree(chosenVisualInfo);
+ }
+
+ if (visualId) {
+#ifdef QT_DEBUG_X11_VISUAL_SELECTION
+ if (configAlphaSize > 0)
+ qDebug("Using ARGB Visual ID %d provided by EGL for config %d", (int)visualId, configId);
+ else
+ qDebug("Using Opaque Visual ID %d provided by EGL for config %d", (int)visualId, configId);
+#endif
+ return visualId;
+ }
+
+
+ // If EGL didn't give us a valid visual ID, try XRender
+#if !defined(QT_NO_XRENDER)
+ if (!visualId) {
+ XVisualInfo visualInfoTemplate;
+ memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
+
+ visualInfoTemplate.depth = configBitDepth;
+ visualInfoTemplate.c_class = TrueColor;
+
+ XVisualInfo *matchingVisuals;
+ int matchingCount = 0;
+ matchingVisuals = XGetVisualInfo(X11->display,
+ VisualDepthMask|VisualClassMask,
+ &visualInfoTemplate,
+ &matchingCount);
+
+ for (int i = 0; i < matchingCount; ++i) {
+ XRenderPictFormat *format;
+ format = XRenderFindVisualFormat(X11->display, matchingVisuals[i].visual);
+
+ // Check the format for the visual matches the EGL config
+ if ( (countBits(format->direct.redMask) == configRedSize) &&
+ (countBits(format->direct.greenMask) == configGreenSize) &&
+ (countBits(format->direct.blueMask) == configBlueSize) &&
+ (countBits(format->direct.alphaMask) == configAlphaSize) )
+ {
+ visualId = matchingVisuals[i].visualid;
+ break;
+ }
+ }
+ if (matchingVisuals)
+ XFree(matchingVisuals);
+
+ }
+ if (visualId) {
+# ifdef QT_DEBUG_X11_VISUAL_SELECTION
+ if (configAlphaSize > 0)
+ qDebug("Using ARGB Visual ID %d provided by XRender for EGL config %d", (int)visualId, configId);
+ else
+ qDebug("Using Opaque Visual ID %d provided by XRender for EGL config %d", (int)visualId, configId);
+# endif // QT_DEBUG_X11_VISUAL_SELECTION
+ return visualId;
+ }
+#endif //!defined(QT_NO_XRENDER)
+
+
+ // Finally, if XRender also failed to find a visual (or isn't present), try to
+ // use XGetVisualInfo and only use the bit depth to match on:
+ if (!visualId) {
+ XVisualInfo visualInfoTemplate;
+ memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
+
+ visualInfoTemplate.depth = configBitDepth;
+
+ XVisualInfo *matchingVisuals;
+ int matchingCount = 0;
+ matchingVisuals = XGetVisualInfo(X11->display,
+ VisualDepthMask,
+ &visualInfoTemplate,
+ &matchingCount);
+ if (matchingVisuals) {
+ visualId = matchingVisuals[0].visualid;
+ XFree(matchingVisuals);
+ }
+ }
+
+ if (visualId) {
+#ifdef QT_DEBUG_X11_VISUAL_SELECTION
+ qDebug("Using Visual ID %d provided by XGetVisualInfo for EGL config %d", (int)visualId, configId);
+#endif
+ return visualId;
+ }
+
+ qWarning("Unable to find an X11 visual which matches EGL config %d", configId);
+ return (VisualID)0;
+}
+
+void qt_set_winid_on_widget(QWidget* w, Qt::HANDLE id)
+{
+ w->create(id);
+}
+
+
+// NOTE: The X11 version of createSurface will re-create the native drawable if it's visual doesn't
+// match the one for the passed in EGLConfig
+EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig config, const QEglProperties *unusedProperties)
+{
+ Q_UNUSED(unusedProperties);
+
+ int devType = device->devType();
+
+ if (devType == QInternal::Pbuffer) {
+ // TODO
+ return EGL_NO_SURFACE;
+ }
+
+ QX11PixmapData *x11PixmapData = 0;
+ if (devType == QInternal::Pixmap) {
+ QPixmapData *pmd = static_cast<QPixmap*>(device)->data_ptr().data();
+ if (pmd->classId() == QPixmapData::X11Class)
+ x11PixmapData = static_cast<QX11PixmapData*>(pmd);
+ else {
+ // TODO: Replace the pixmap's data with a new QX11PixmapData
+ qWarning("WARNING: Creating an EGL surface on a QPixmap is only supported for QX11PixmapData");
+ return EGL_NO_SURFACE;
+ }
+ } else if ((devType != QInternal::Widget) && (devType != QInternal::Pbuffer)) {
+ qWarning("WARNING: Creating an EGLSurface for device type %d isn't supported", devType);
+ return EGL_NO_SURFACE;
+ }
+
+ VisualID visualId = QEgl::getCompatibleVisualId(config);
+ EGLint alphaSize;
+ eglGetConfigAttrib(QEgl::display(), config, EGL_ALPHA_SIZE, &alphaSize);
+
+ if (devType == QInternal::Widget) {
+ QWidget *widget = static_cast<QWidget*>(device);
+
+ VisualID currentVisualId = 0;
+ if (widget->testAttribute(Qt::WA_WState_Created))
+ currentVisualId = XVisualIDFromVisual((Visual*)widget->x11Info().visual());
+
+ if (currentVisualId != visualId) {
+ // The window is either not created or has the wrong visual. Either way, we need
+ // to create a window with the correct visual and call create() on the widget:
+
+ bool visible = widget->isVisible();
+ if (visible)
+ widget->hide();
+
+ XVisualInfo visualInfo;
+ visualInfo.visualid = visualId;
+ {
+ XVisualInfo *visualInfoPtr;
+ int matchingCount = 0;
+ visualInfoPtr = XGetVisualInfo(widget->x11Info().display(), VisualIDMask,
+ &visualInfo, &matchingCount);
+ Q_ASSERT(visualInfoPtr); // visualId really should be valid!
+ visualInfo = *visualInfoPtr;
+ XFree(visualInfoPtr);
+ }
+
+ Window parentWindow = RootWindow(widget->x11Info().display(), widget->x11Info().screen());
+ if (widget->parentWidget())
+ parentWindow = widget->parentWidget()->winId();
+
+ XSetWindowAttributes windowAttribs;
+ QColormap colmap = QColormap::instance(widget->x11Info().screen());
+ windowAttribs.background_pixel = colmap.pixel(widget->palette().color(widget->backgroundRole()));
+ windowAttribs.border_pixel = colmap.pixel(Qt::black);
+
+ unsigned int valueMask = CWBackPixel|CWBorderPixel;
+ if (alphaSize > 0) {
+ windowAttribs.colormap = XCreateColormap(widget->x11Info().display(), parentWindow,
+ visualInfo.visual, AllocNone);
+ valueMask |= CWColormap;
+ }
+
+ Window window = XCreateWindow(widget->x11Info().display(), parentWindow,
+ widget->x(), widget->y(), widget->width(), widget->height(),
+ 0, visualInfo.depth, InputOutput, visualInfo.visual,
+ valueMask, &windowAttribs);
+
+ // This is a nasty hack to get round the fact that we can't be a friend of QWidget:
+ qt_set_winid_on_widget(widget, window);
+
+ if (visible)
+ widget->show();
+ }
+
+ // At this point, the widget's window should be created and have the correct visual. Now we
+ // just need to create the EGL surface for it:
+ return eglCreateWindowSurface(QEgl::display(), config, (EGLNativeWindowType)widget->winId(), 0);
+ }
+
+ if (x11PixmapData) {
+ // X11 Pixmaps are only created with a depth, so that's all we need to check
+ EGLint configDepth;
+ eglGetConfigAttrib(QEgl::display(), config, EGL_BUFFER_SIZE , &configDepth);
+ if (x11PixmapData->depth() != configDepth) {
+ // The bit depths are wrong which means the EGLConfig isn't compatable with
+ // this pixmap. So we need to replace the pixmap's existing data with a new
+ // one which is created with the correct depth:
+
+#ifndef QT_NO_XRENDER
+ if (configDepth == 32) {
+ qWarning("Warning: EGLConfig's depth (32) != pixmap's depth (%d), converting to ARGB32",
+ x11PixmapData->depth());
+ x11PixmapData->convertToARGB32(true);
+ } else
+#endif
+ {
+ qWarning("Warning: EGLConfig's depth (%d) != pixmap's depth (%d)",
+ configDepth, x11PixmapData->depth());
+ }
+ }
+
+ QEglProperties surfaceAttribs;
+
+ // If the pixmap can't be bound to a texture, it's pretty useless
+ surfaceAttribs.setValue(EGL_TEXTURE_TARGET, EGL_TEXTURE_2D);
+ if (alphaSize > 0)
+ surfaceAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA);
+ else
+ surfaceAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB);
+
+ EGLSurface surf = eglCreatePixmapSurface(QEgl::display(), config,
+ (EGLNativePixmapType) x11PixmapData->handle(),
+ surfaceAttribs.properties());
+ x11PixmapData->gl_surface = (void*)surf;
+ QImagePixmapCleanupHooks::enableCleanupHooks(x11PixmapData);
+ return surf;
+ }
+
+ return EGL_NO_SURFACE;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/egl/qeglcontext_p.h b/src/gui/egl/qeglcontext_p.h
new file mode 100644
index 0000000..7eec7eb
--- /dev/null
+++ b/src/gui/egl/qeglcontext_p.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** 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 QtGui module 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 QEGLCONTEXT_P_H
+#define QEGLCONTEXT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience of
+// the QtOpenGL and QtOpenVG modules. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qsize.h>
+#include <QtGui/qimage.h>
+
+#include <QtGui/private/qegl_p.h>
+#include <QtGui/private/qeglproperties_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_GUI_EXPORT QEglContext
+{
+public:
+ QEglContext();
+ ~QEglContext();
+
+ bool isValid() const;
+ bool isCurrent() const;
+ bool isSharing() const { return sharing; }
+
+ QEgl::API api() const { return apiType; }
+ void setApi(QEgl::API api) { apiType = api; }
+
+ bool chooseConfig(const QEglProperties& properties, QEgl::PixelFormatMatch match = QEgl::ExactPixelFormat);
+ bool createContext(QEglContext *shareContext = 0, const QEglProperties *properties = 0);
+ void destroyContext();
+ EGLSurface createSurface(QPaintDevice *device, const QEglProperties *properties = 0);
+ void destroySurface(EGLSurface surface);
+
+ bool makeCurrent(EGLSurface surface);
+ bool doneCurrent();
+ bool lazyDoneCurrent();
+ bool swapBuffers(EGLSurface surface);
+
+ void waitNative();
+ void waitClient();
+
+ bool configAttrib(int name, EGLint *value) const;
+ int configAttrib(int name) const;
+
+ EGLContext context() const { return ctx; }
+ void setContext(EGLContext context) { ctx = context; ownsContext = false;}
+
+ EGLDisplay display() {return QEgl::display();}
+
+ EGLConfig config() const { return cfg; }
+ void setConfig(EGLConfig config) { cfg = config; }
+
+ QEglProperties configProperties() const;
+
+private:
+ QEgl::API apiType;
+ EGLContext ctx;
+ EGLConfig cfg;
+ EGLSurface currentSurface;
+ bool current;
+ bool ownsContext;
+ bool sharing;
+
+ static QEglContext *currentContext(QEgl::API api);
+ static void setCurrentContext(QEgl::API api, QEglContext *context);
+};
+
+QT_END_NAMESPACE
+
+#endif // QEGLCONTEXT_P_H
diff --git a/src/gui/egl/qeglproperties.cpp b/src/gui/egl/qeglproperties.cpp
index 236ec37..b5d3103 100644
--- a/src/gui/egl/qeglproperties.cpp
+++ b/src/gui/egl/qeglproperties.cpp
@@ -39,15 +39,13 @@
**
****************************************************************************/
-#include "qeglproperties_p.h"
-
-QT_BEGIN_NAMESPACE
-
#include <QtCore/qdebug.h>
#include <QtCore/qstringlist.h>
-#include "qegl_p.h"
+#include "qeglproperties_p.h"
+#include "qeglcontext_p.h"
+QT_BEGIN_NAMESPACE
// Initialize a property block.
QEglProperties::QEglProperties()
@@ -60,7 +58,7 @@ QEglProperties::QEglProperties(EGLConfig cfg)
props.append(EGL_NONE);
for (int name = 0x3020; name <= 0x304F; ++name) {
EGLint value;
- if (name != EGL_NONE && eglGetConfigAttrib(QEglContext::display(), cfg, name, &value))
+ if (name != EGL_NONE && eglGetConfigAttrib(QEgl::display(), cfg, name, &value))
setValue(name, value);
}
eglGetError(); // Clear the error state.
@@ -166,6 +164,17 @@ bool QEglProperties::removeValue(int name)
return false;
}
+void QEglProperties::setDeviceType(int devType)
+{
+ if (devType == QInternal::Pixmap || devType == QInternal::Image)
+ setValue(EGL_SURFACE_TYPE, EGL_PIXMAP_BIT);
+ else if (devType == QInternal::Pbuffer)
+ setValue(EGL_SURFACE_TYPE, EGL_PBUFFER_BIT);
+ else
+ setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
+}
+
+
// Sets the red, green, blue, and alpha sizes based on a pixel format.
// Normally used to match a configuration request to the screen format.
void QEglProperties::setPixelFormat(QImage::Format pixelFormat)
@@ -229,6 +238,16 @@ void QEglProperties::setRenderableType(QEgl::API api)
// reductions in complexity are possible.
bool QEglProperties::reduceConfiguration()
{
+#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
+ // For OpenVG, we sometimes try to create a surface using a pre-multiplied format. If we can't
+ // find a config which supports pre-multiplied formats, remove the flag on the surface type:
+ EGLint surfaceType = value(EGL_SURFACE_TYPE);
+ if (surfaceType & EGL_VG_ALPHA_FORMAT_PRE_BIT) {
+ surfaceType ^= EGL_VG_ALPHA_FORMAT_PRE_BIT;
+ setValue(EGL_SURFACE_TYPE, surfaceType);
+ return true;
+ }
+#endif
// EGL chooses configs with the highest color depth over
// those with smaller (but faster) lower color depths. One
// way around this is to set EGL_BUFFER_SIZE to 16, which
@@ -273,12 +292,12 @@ static void addTag(QString& str, const QString& tag)
void QEglProperties::dumpAllConfigs()
{
EGLint count = 0;
- eglGetConfigs(QEglContext::display(), 0, 0, &count);
+ eglGetConfigs(QEgl::display(), 0, 0, &count);
if (count < 1)
return;
EGLConfig *configs = new EGLConfig [count];
- eglGetConfigs(QEglContext::display(), configs, count, &count);
+ eglGetConfigs(QEgl::display(), configs, count, &count);
for (EGLint index = 0; index < count; ++index)
qWarning() << QEglProperties(configs[index]).toString();
delete [] configs;
diff --git a/src/gui/egl/qeglproperties_p.h b/src/gui/egl/qeglproperties_p.h
index feed1d2..eebcf72 100644
--- a/src/gui/egl/qeglproperties_p.h
+++ b/src/gui/egl/qeglproperties_p.h
@@ -56,50 +56,10 @@
#include <QtCore/qvarlengtharray.h>
#include <QtGui/qimage.h>
-QT_BEGIN_INCLUDE_NAMESPACE
-
-#if defined(QT_GLES_EGL)
-#include <GLES/egl.h>
-#else
-#include <EGL/egl.h>
-#endif
-
-#if defined(Q_WS_X11)
-// If <EGL/egl.h> included <X11/Xlib.h>, then the global namespace
-// may have been polluted with X #define's. The following makes sure
-// the X11 headers were included properly and then cleans things up.
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#undef Bool
-#undef Status
-#undef None
-#undef KeyPress
-#undef KeyRelease
-#undef FocusIn
-#undef FocusOut
-#undef Type
-#undef FontChange
-#undef CursorShape
-#endif
-
-QT_END_INCLUDE_NAMESPACE
+#include <QtGui/private/qegl_p.h>
QT_BEGIN_NAMESPACE
-namespace QEgl {
- enum API
- {
- OpenGL,
- OpenVG
- };
-
- enum PixelFormatMatch
- {
- ExactPixelFormat,
- BestPixelFormat
- };
-};
-
class QX11Info;
class QPaintDevice;
@@ -122,9 +82,9 @@ public:
#ifdef Q_WS_X11
void setVisualFormat(const QX11Info *xinfo);
#endif
- void setRenderableType(QEgl::API api);
-
+ void setDeviceType(int devType);
void setPaintDeviceFormat(QPaintDevice *dev);
+ void setRenderableType(QEgl::API api);
bool reduceConfiguration();
diff --git a/src/gui/embedded/directfb.pri b/src/gui/embedded/directfb.pri
index d6d77b4..75d693e 100644
--- a/src/gui/embedded/directfb.pri
+++ b/src/gui/embedded/directfb.pri
@@ -15,7 +15,7 @@
#DEFINES += QT_DIRECTFB_TIMING
#DEFINES += QT_NO_DIRECTFB_OPAQUE_DETECTION
#DEFINES += QT_NO_DIRECTFB_STRETCHBLIT
-#DIRECTFB_DRAWINGOPERATIONS=DRAW_RECTS|DRAW_LINES|DRAW_IMAGE|DRAW_PIXMAP|DRAW_TILED_PIXMAP|STROKE_PATH|DRAW_PATH|DRAW_POINTS|DRAW_ELLIPSE|DRAW_POLYGON|DRAW_TEXT|FILL_PATH|FILL_RECT|DRAW_COLORSPANS|DRAW_ROUNDED_RECT|DRAW_STATICTEXT
+DIRECTFB_DRAWINGOPERATIONS=DRAW_RECTS|DRAW_LINES|DRAW_IMAGE|DRAW_PIXMAP|DRAW_TILED_PIXMAP|STROKE_PATH|DRAW_PATH|DRAW_POINTS|DRAW_ELLIPSE|DRAW_POLYGON|DRAW_TEXT|FILL_PATH|FILL_RECT|DRAW_COLORSPANS|DRAW_ROUNDED_RECT|DRAW_STATICTEXT
#DEFINES += \"QT_DIRECTFB_WARN_ON_RASTERFALLBACKS=$$DIRECTFB_DRAWINGOPERATIONS\"
#DEFINES += \"QT_DIRECTFB_DISABLE_RASTERFALLBACKS=$$DIRECTFB_DRAWINGOPERATIONS\"
diff --git a/src/gui/embedded/qscreen_qws.cpp b/src/gui/embedded/qscreen_qws.cpp
index 65a3fb5..a3fe1ab 100644
--- a/src/gui/embedded/qscreen_qws.cpp
+++ b/src/gui/embedded/qscreen_qws.cpp
@@ -2740,7 +2740,7 @@ void QScreen::compose(int level, const QRegion &exposed, QRegion &blend,
default:
break;
}
- spanData.setup(qwsServer->backgroundBrush(), 256, QPainter::CompositionMode_SourceOver);
+ spanData.setup(qwsServer->backgroundBrush(), 256, QPainter::CompositionMode_Source);
spanData.dx = off.x();
spanData.dy = off.y();
} else if (!surface->isBuffered()) {
diff --git a/src/gui/embedded/qwsmanager_qws.cpp b/src/gui/embedded/qwsmanager_qws.cpp
index d6ef148..79076c5 100644
--- a/src/gui/embedded/qwsmanager_qws.cpp
+++ b/src/gui/embedded/qwsmanager_qws.cpp
@@ -267,8 +267,10 @@ void QWSManager::mouseMoveEvent(QMouseEvent *e)
#ifndef QT_NO_CURSOR
- QWSDisplay *qwsd = QApplication::desktop()->qwsDisplay();
- qwsd->selectCursor(d->managed, regionToShape(d->cachedRegionAt()));
+ if (d->managed->minimumSize() != d->managed->maximumSize()) {
+ QWSDisplay *qwsd = QApplication::desktop()->qwsDisplay();
+ qwsd->selectCursor(d->managed, regionToShape(d->cachedRegionAt()));
+ }
#endif //QT_NO_CURSOR
if (d->activeRegion)
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index 5735cd6..d6daf4d 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -381,7 +381,9 @@
\value ItemSendsGeometryChanges The item enables itemChange()
notifications for ItemPositionChange, ItemPositionHasChanged,
- ItemMatrixChange, ItemTransformChange, and ItemTransformHasChanged. For
+ ItemMatrixChange, ItemTransformChange, ItemTransformHasChanged,
+ ItemRotationChange, ItemRotationHasChanged, ItemScaleChange, ItemScaleHasChanged,
+ ItemTransformOriginPointChange, and ItemTransformOriginPointHasChanged. For
performance reasons, these notifications are disabled by default. You must
enable this flag to receive notifications for position and transform
changes. This flag was introduced in Qt 4.6.
@@ -475,6 +477,52 @@
(same as transform()), and QGraphicsItem ignores the return value for this
notification (i.e., a read-only notification).
+ \value ItemRotationChange The item's rotation property changes. This
+ notification is sent if the ItemSendsGeometryChanges flag is enabled, and
+ when the item's rotation property changes (i.e., as a result of calling
+ setRotation()). The value argument is the new rotation (i.e., a double);
+ to get the old rotation, call rotation(). Do not call setRotation() in
+ itemChange() as this notification is delivered; instead, you can return
+ the new rotation from itemChange().
+
+ \value ItemRotationHasChanged The item's rotation property has changed.
+ This notification is sent if the ItemSendsGeometryChanges flag is enabled,
+ and after the item's rotation property has changed. The value argument is
+ the new rotation (i.e., a double), and QGraphicsItem ignores the return
+ value for this notification (i.e., a read-only notification). Do not call
+ setRotation() in itemChange() as this notification is delivered.
+
+ \value ItemScaleChange The item's scale property changes. This notification
+ is sent if the ItemSendsGeometryChanges flag is enabled, and when the item's
+ scale property changes (i.e., as a result of calling setScale()). The value
+ argument is the new scale (i.e., a double); to get the old scale, call
+ scale(). Do not call setScale() in itemChange() as this notification is
+ delivered; instead, you can return the new scale from itemChange().
+
+ \value ItemScaleHasChanged The item's scale property has changed. This
+ notification is sent if the ItemSendsGeometryChanges flag is enabled, and
+ after the item's scale property has changed. The value argument is the new
+ scale (i.e., a double), and QGraphicsItem ignores the return value for this
+ notification (i.e., a read-only notification). Do not call setScale() in
+ itemChange() as this notification is delivered.
+
+ \value ItemTransformOriginPointChange The item's transform origin point
+ property changes. This notification is sent if the ItemSendsGeometryChanges
+ flag is enabled, and when the item's transform origin point property changes
+ (i.e., as a result of calling setTransformOriginPoint()). The value argument
+ is the new origin point (i.e., a QPointF); to get the old origin point, call
+ transformOriginPoint(). Do not call setTransformOriginPoint() in itemChange()
+ as this notification is delivered; instead, you can return the new transform
+ origin point from itemChange().
+
+ \value ItemTransformOriginPointHasChanged The item's transform origin point
+ property has changed. This notification is sent if the ItemSendsGeometryChanges
+ flag is enabled, and after the item's transform origin point property has
+ changed. The value argument is the new origin point (i.e., a QPointF), and
+ QGraphicsItem ignores the return value for this notification (i.e., a read-only
+ notification). Do not call setTransformOriginPoint() in itemChange() as this
+ notification is delivered.
+
\value ItemSelectedChange The item's selected state changes. If the item is
presently selected, it will become unselected, and vice verca. The value
argument is the new selected state (i.e., true or false). Do not call
@@ -641,10 +689,10 @@
are children of a modal panel are not blocked.
The values are:
-
+
\value NonModal The panel is not modal and does not block input to
other panels. This is the default value for panels.
-
+
\value PanelModal The panel is modal to a single item hierarchy
and blocks input to its parent pane, all grandparent panels, and
all siblings of its parent and grandparent panels.
@@ -683,6 +731,9 @@
#include <QtGui/qevent.h>
#include <QtGui/qinputcontext.h>
#include <QtGui/qgraphicseffect.h>
+#ifndef QT_NO_ACCESSIBILITY
+# include "qaccessible.h"
+#endif
#include <private/qgraphicsitem_p.h>
#include <private/qgraphicswidget_p.h>
@@ -690,6 +741,7 @@
#include <private/qtextdocumentlayout_p.h>
#include <private/qtextengine_p.h>
#include <private/qwidget_p.h>
+#include <private/qapplication_p.h>
#ifdef Q_WS_X11
#include <private/qt_x11_p.h>
@@ -1131,6 +1183,9 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, const Q
}
}
+ // Resolve depth.
+ invalidateDepthRecursively();
+
if ((parent = newParent)) {
if (parent->d_func()->scene && parent->d_func()->scene != scene) {
// Move this item to its new parent's scene
@@ -1181,8 +1236,6 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, const Q
}
}
- // Resolve depth.
- invalidateDepthRecursively();
dirtySceneTransform = 1;
// Restore the sub focus chain.
@@ -1883,7 +1936,8 @@ void QGraphicsItem::setCacheMode(CacheMode mode, const QSize &logicalCacheSize)
d_ptr->cacheMode = mode;
bool noVisualChange = (mode == NoCache && lastMode == NoCache)
|| (mode == NoCache && lastMode == DeviceCoordinateCache)
- || (mode == DeviceCoordinateCache && lastMode == NoCache);
+ || (mode == DeviceCoordinateCache && lastMode == NoCache)
+ || (mode == DeviceCoordinateCache && lastMode == DeviceCoordinateCache);
if (mode == NoCache) {
d_ptr->removeExtraItemCache();
} else {
@@ -2177,11 +2231,16 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo
QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData));
if (c)
c->purge();
- if (scene)
+ if (scene) {
+#ifndef QT_NO_GRAPHICSEFFECT
+ invalidateParentGraphicsEffectsRecursively();
+#endif //QT_NO_GRAPHICSEFFECT
scene->d_func()->markDirty(q_ptr, QRectF(), /*invalidateChildren=*/false, /*force=*/true);
+ }
}
// Certain properties are dropped as an item becomes invisible.
+ bool hasFocus = q_ptr->hasFocus();
if (!newVisible) {
if (scene) {
if (scene->d_func()->mouseGrabberItems.contains(q))
@@ -2191,7 +2250,7 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo
if (q->isPanel() && panelModality != QGraphicsItem::NonModal)
scene->d_func()->leaveModal(q_ptr);
}
- if (q_ptr->hasFocus() && scene) {
+ if (hasFocus && scene) {
// Hiding the closest non-panel ancestor of the focus item
QGraphicsItem *focusItem = scene->focusItem();
bool clear = true;
@@ -2204,7 +2263,7 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo
} while ((focusItem = focusItem->parentWidget()) && !focusItem->isPanel());
}
if (clear)
- q_ptr->clearFocus();
+ clearFocusHelper(/* giveFocusToParent = */ false);
}
if (q_ptr->isSelected())
q_ptr->setSelected(false);
@@ -2242,26 +2301,45 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo
}
// Enable subfocus
- if (scene && newVisible) {
- QGraphicsItem *p = parent;
- bool done = false;
- while (p) {
- if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
- QGraphicsItem *fsi = p->d_ptr->focusScopeItem;
- if (q_ptr == fsi || q_ptr->isAncestorOf(fsi)) {
- done = true;
- while (fsi->d_ptr->focusScopeItem && fsi->d_ptr->focusScopeItem->isVisible())
- fsi = fsi->d_ptr->focusScopeItem;
- scene->setFocusItem(fsi);
+ if (scene) {
+ if (newVisible) {
+ // Item is shown
+ QGraphicsItem *p = parent;
+ bool done = false;
+ while (p) {
+ if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
+ QGraphicsItem *fsi = p->d_ptr->focusScopeItem;
+ if (q_ptr == fsi || q_ptr->isAncestorOf(fsi)) {
+ done = true;
+ while (fsi->d_ptr->focusScopeItem && fsi->d_ptr->focusScopeItem->isVisible())
+ fsi = fsi->d_ptr->focusScopeItem;
+ fsi->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ true,
+ /* focusFromShow = */ true);
+ }
+ break;
}
- break;
+ p = p->d_ptr->parent;
}
- p = p->d_ptr->parent;
- }
- if (!done) {
- QGraphicsItem *fi = subFocusItem;
- if (fi && fi != scene->focusItem()) {
- scene->setFocusItem(fi);
+ if (!done) {
+ QGraphicsItem *fi = subFocusItem;
+ if (fi && fi != scene->focusItem()) {
+ scene->setFocusItem(fi);
+ }
+ }
+ } else {
+ // Item is hidden
+ if (hasFocus) {
+ QGraphicsItem *p = parent;
+ while (p) {
+ if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
+ if (p->d_ptr->visible) {
+ p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ true,
+ /* focusFromShow = */ true);
+ }
+ break;
+ }
+ p = p->d_ptr->parent;
+ }
}
}
}
@@ -3112,13 +3190,13 @@ bool QGraphicsItem::hasFocus() const
*/
void QGraphicsItem::setFocus(Qt::FocusReason focusReason)
{
- d_ptr->setFocusHelper(focusReason, /* climb = */ true);
+ d_ptr->setFocusHelper(focusReason, /* climb = */ true, /* focusFromShow = */ false);
}
/*!
\internal
*/
-void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool climb)
+void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool climb, bool focusFromShow)
{
// Disabled / unfocusable items cannot accept focus.
if (!q_ptr->isEnabled() || !(flags & QGraphicsItem::ItemIsFocusable))
@@ -3138,7 +3216,7 @@ void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool clim
while (p) {
if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
p->d_ptr->focusScopeItem = q_ptr;
- if (!p->focusItem()) {
+ if (!p->focusItem() && !focusFromShow) {
// If you call setFocus on a child of a focus scope that
// doesn't currently have a focus item, then stop.
return;
@@ -3179,25 +3257,35 @@ void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool clim
*/
void QGraphicsItem::clearFocus()
{
- // Pass focus to the closest parent focus scope when clearing focus
- // from a focus scope.
- if (!d_ptr->inDestructor && (d_ptr->flags & ItemIsFocusScope)) {
- QGraphicsItem *p = d_ptr->parent;
- while (p) {
- if (p->flags() & ItemIsFocusScope) {
- p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ false);
- return;
+ d_ptr->clearFocusHelper(/* giveFocusToParent = */ true);
+}
+
+/*!
+ \internal
+*/
+void QGraphicsItemPrivate::clearFocusHelper(bool giveFocusToParent)
+{
+ if (giveFocusToParent) {
+ // Pass focus to the closest parent focus scope
+ if (!inDestructor) {
+ QGraphicsItem *p = parent;
+ while (p) {
+ if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
+ p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ false,
+ /* focusFromShow = */ false);
+ return;
+ }
+ p = p->d_ptr->parent;
}
- p = p->d_ptr->parent;
}
}
// Invisible items with focus must explicitly clear subfocus.
- d_ptr->clearSubFocus(this);
+ clearSubFocus(q_ptr);
- if (hasFocus()) {
+ if (q_ptr->hasFocus()) {
// If this item has the scene's input focus, clear it.
- d_ptr->scene->setFocusItem(0);
+ scene->setFocusItem(0);
}
}
@@ -3452,7 +3540,7 @@ void QGraphicsItem::setX(qreal x)
if (qIsNaN(x))
return;
- d_ptr->setPosHelper(QPointF(x, d_ptr->pos.y()));
+ setPos(QPointF(x, d_ptr->pos.y()));
}
/*!
@@ -3479,7 +3567,7 @@ void QGraphicsItem::setY(qreal y)
if (qIsNaN(y))
return;
- d_ptr->setPosHelper(QPointF(d_ptr->pos.x(), y));
+ setPos(QPointF(d_ptr->pos.x(), y));
}
/*!
@@ -3547,7 +3635,7 @@ void QGraphicsItem::setPos(const QPointF &pos)
return;
// Update and repositition.
- if (!(d_ptr->flags & ItemSendsGeometryChanges)) {
+ if (!(d_ptr->flags & (ItemSendsGeometryChanges | ItemSendsScenePositionChanges))) {
d_ptr->setPosHelper(pos);
return;
}
@@ -3692,12 +3780,28 @@ qreal QGraphicsItem::rotation() const
void QGraphicsItem::setRotation(qreal angle)
{
prepareGeometryChange();
+ qreal newRotation = angle;
+
+ if (d_ptr->flags & ItemSendsGeometryChanges) {
+ // Notify the item that the rotation is changing.
+ const QVariant newRotationVariant(itemChange(ItemRotationChange, angle));
+ newRotation = newRotationVariant.toReal();
+ }
+
if (!d_ptr->transformData)
d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
- d_ptr->transformData->rotation = angle;
+
+ if (d_ptr->transformData->rotation == newRotation)
+ return;
+
+ d_ptr->transformData->rotation = newRotation;
d_ptr->transformData->onlyTransform = false;
d_ptr->dirtySceneTransform = 1;
+ // Send post-notification.
+ if (d_ptr->flags & ItemSendsGeometryChanges)
+ itemChange(ItemRotationHasChanged, newRotation);
+
if (d_ptr->isObject)
emit static_cast<QGraphicsObject *>(this)->rotationChanged();
}
@@ -3740,12 +3844,28 @@ qreal QGraphicsItem::scale() const
void QGraphicsItem::setScale(qreal factor)
{
prepareGeometryChange();
+ qreal newScale = factor;
+
+ if (d_ptr->flags & ItemSendsGeometryChanges) {
+ // Notify the item that the scale is changing.
+ const QVariant newScaleVariant(itemChange(ItemScaleChange, factor));
+ newScale = newScaleVariant.toReal();
+ }
+
if (!d_ptr->transformData)
d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
- d_ptr->transformData->scale = factor;
+
+ if (d_ptr->transformData->scale == newScale)
+ return;
+
+ d_ptr->transformData->scale = newScale;
d_ptr->transformData->onlyTransform = false;
d_ptr->dirtySceneTransform = 1;
+ // Send post-notification.
+ if (d_ptr->flags & ItemSendsGeometryChanges)
+ itemChange(ItemScaleHasChanged, newScale);
+
if (d_ptr->isObject)
emit static_cast<QGraphicsObject *>(this)->scaleChanged();
}
@@ -3808,6 +3928,22 @@ void QGraphicsItem::setTransformations(const QList<QGraphicsTransform *> &transf
/*!
\internal
*/
+void QGraphicsItemPrivate::prependGraphicsTransform(QGraphicsTransform *t)
+{
+ if (!transformData)
+ transformData = new QGraphicsItemPrivate::TransformData;
+ if (!transformData->graphicsTransforms.contains(t))
+ transformData->graphicsTransforms.prepend(t);
+
+ Q_Q(QGraphicsItem);
+ t->d_func()->setItem(q);
+ transformData->onlyTransform = false;
+ dirtySceneTransform = 1;
+}
+
+/*!
+ \internal
+*/
void QGraphicsItemPrivate::appendGraphicsTransform(QGraphicsTransform *t)
{
if (!transformData)
@@ -3847,12 +3983,31 @@ QPointF QGraphicsItem::transformOriginPoint() const
void QGraphicsItem::setTransformOriginPoint(const QPointF &origin)
{
prepareGeometryChange();
+ QPointF newOrigin = origin;
+
+ if (d_ptr->flags & ItemSendsGeometryChanges) {
+ // Notify the item that the origin point is changing.
+ const QVariant newOriginVariant(itemChange(ItemTransformOriginPointChange,
+ qVariantFromValue<QPointF>(origin)));
+ newOrigin = newOriginVariant.toPointF();
+ }
+
if (!d_ptr->transformData)
d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
- d_ptr->transformData->xOrigin = origin.x();
- d_ptr->transformData->yOrigin = origin.y();
+
+ if (d_ptr->transformData->xOrigin == newOrigin.x()
+ && d_ptr->transformData->yOrigin == newOrigin.y()) {
+ return;
+ }
+
+ d_ptr->transformData->xOrigin = newOrigin.x();
+ d_ptr->transformData->yOrigin = newOrigin.y();
d_ptr->transformData->onlyTransform = false;
d_ptr->dirtySceneTransform = 1;
+
+ // Send post-notification.
+ if (d_ptr->flags & ItemSendsGeometryChanges)
+ itemChange(ItemTransformOriginPointHasChanged, qVariantFromValue<QPointF>(newOrigin));
}
/*!
@@ -5196,6 +5351,8 @@ void QGraphicsItemPrivate::addChild(QGraphicsItem *child)
needSortChildren = 1; // ### maybe 0
child->d_ptr->siblingIndex = children.size();
children.append(child);
+ if (isObject)
+ emit static_cast<QGraphicsObject *>(q_ptr)->childrenChanged();
}
/*!
@@ -5218,6 +5375,8 @@ void QGraphicsItemPrivate::removeChild(QGraphicsItem *child)
// the child is not guaranteed to be at the index after the list is sorted.
// (see ensureSortedChildren()).
child->d_ptr->siblingIndex = -1;
+ if (isObject)
+ emit static_cast<QGraphicsObject *>(q_ptr)->childrenChanged();
}
/*!
@@ -6953,7 +7112,8 @@ void QGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
// Root items that ignore transformations need to
// calculate their diff by mapping viewport coordinates
// directly to parent coordinates.
- QTransform viewToParentTransform = (item->transform().translate(item->d_ptr->pos.x(), item->d_ptr->pos.y()))
+ // COMBINE
+ QTransform viewToParentTransform = (item->d_func()->transformData->computedFullTransform().translate(item->d_ptr->pos.x(), item->d_ptr->pos.y()))
* (item->sceneTransform() * view->viewportTransform()).inverted();
currentParentPos = viewToParentTransform.map(QPointF(view->mapFromGlobal(event->screenPos())));
buttonDownParentPos = viewToParentTransform.map(QPointF(view->mapFromGlobal(event->buttonDownScreenPos(Qt::LeftButton))));
@@ -7150,6 +7310,31 @@ void QGraphicsItem::setInputMethodHints(Qt::InputMethodHints hints)
}
/*!
+ Updates the item's micro focus.
+
+ \since 4.7
+
+ \sa QInputContext
+*/
+void QGraphicsItem::updateMicroFocus()
+{
+#if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN))
+ if (QWidget *fw = qApp->focusWidget()) {
+ if (qt_widget_private(fw)->ic || qApp->d_func()->inputContext) {
+ if (QInputContext *ic = fw->inputContext()) {
+ if (ic)
+ ic->update();
+ }
+ }
+#ifndef QT_NO_ACCESSIBILITY
+ // ##### is this correct
+ QAccessible::updateAccessibility(fw, 0, QAccessible::StateChanged);
+#endif
+ }
+#endif
+}
+
+/*!
This virtual function is called by QGraphicsItem to notify custom items
that some part of the item's state changes. By reimplementing this
function, your can react to a change, and in some cases, (depending on \a
@@ -7425,6 +7610,93 @@ void QGraphicsObject::ungrabGesture(Qt::GestureType gesture)
}
}
+void QGraphicsObject::updateMicroFocus()
+{
+ QGraphicsItem::updateMicroFocus();
+}
+
+void QGraphicsItemPrivate::append(QDeclarativeListProperty<QGraphicsObject> *list, QGraphicsObject *item)
+{
+ QGraphicsItemPrivate::get(item)->setParentItemHelper(static_cast<QGraphicsObject *>(list->object), /*newParentVariant=*/0, /*thisPointerVariant=*/0);
+}
+
+/*!
+ Returns a list of this item's children.
+
+ The items are sorted by stacking order. This takes into account both the
+ items' insertion order and their Z-values.
+
+*/
+QDeclarativeListProperty<QGraphicsObject> QGraphicsItemPrivate::childrenList()
+{
+ Q_Q(QGraphicsItem);
+ if (isObject) {
+ QGraphicsObject *that = static_cast<QGraphicsObject *>(q);
+ return QDeclarativeListProperty<QGraphicsObject>(that, &children, QGraphicsItemPrivate::append);
+ } else {
+ //QGraphicsItem is not supported for this property
+ return QDeclarativeListProperty<QGraphicsObject>();
+ }
+}
+
+/*!
+ \internal
+ Returns the width of the item
+ Reimplemented by QGraphicsWidget
+*/
+qreal QGraphicsItemPrivate::width() const
+{
+ return 0;
+}
+
+/*!
+ \internal
+ Set the width of the item
+ Reimplemented by QGraphicsWidget
+*/
+void QGraphicsItemPrivate::setWidth(qreal w)
+{
+ Q_UNUSED(w);
+}
+
+/*!
+ \internal
+ Reset the width of the item
+ Reimplemented by QGraphicsWidget
+*/
+void QGraphicsItemPrivate::resetWidth()
+{
+}
+
+/*!
+ \internal
+ Returns the height of the item
+ Reimplemented by QGraphicsWidget
+*/
+qreal QGraphicsItemPrivate::height() const
+{
+ return 0;
+}
+
+/*!
+ \internal
+ Set the height of the item
+ Reimplemented by QGraphicsWidget
+*/
+void QGraphicsItemPrivate::setHeight(qreal h)
+{
+ Q_UNUSED(h);
+}
+
+/*!
+ \internal
+ Reset the height of the item
+ Reimplemented by QGraphicsWidget
+*/
+void QGraphicsItemPrivate::resetHeight()
+{
+}
+
/*!
\property QGraphicsObject::parent
\brief the parent of the item
@@ -7611,6 +7883,23 @@ void QGraphicsObject::ungrabGesture(Qt::GestureType gesture)
\sa scale, rotation, QGraphicsItem::transformOriginPoint()
*/
+/*!
+ \fn void QGraphicsObject::widthChanged()
+ \internal
+*/
+
+/*!
+ \fn void QGraphicsObject::heightChanged()
+ \internal
+*/
+
+/*!
+
+ \fn QGraphicsObject::childrenChanged()
+
+ This signal gets emitted whenever the children list changes
+ \internal
+*/
/*!
\class QAbstractGraphicsShapeItem
@@ -10818,6 +11107,7 @@ void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter)
}
}
+// sourceRect must be in the given coordinate system
QRect QGraphicsItemEffectSourcePrivate::paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded) const
{
QRectF effectRectF;
@@ -10827,7 +11117,8 @@ QRect QGraphicsItemEffectSourcePrivate::paddedEffectRect(Qt::CoordinateSystem sy
if (mode == QGraphicsEffect::PadToEffectiveBoundingRect) {
if (info) {
- effectRectF = item->graphicsEffect()->boundingRectFor(boundingRect(Qt::DeviceCoordinates));
+ QRectF deviceRect = system == Qt::DeviceCoordinates ? sourceRect : info->painter->worldTransform().mapRect(sourceRect);
+ effectRectF = item->graphicsEffect()->boundingRectFor(deviceRect);
if (unpadded)
*unpadded = (effectRectF.size() == sourceRect.size());
if (info && system == Qt::LogicalCoordinates)
@@ -10876,30 +11167,6 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP
return static_cast<QGraphicsPixmapItem *>(item)->pixmap();
}
- if (deviceCoordinates) {
- // Clip to viewport rect.
- int left, top, right, bottom;
- effectRect.getCoords(&left, &top, &right, &bottom);
- if (left < 0) {
- if (offset)
- offset->rx() += -left;
- effectRect.setX(0);
- }
- if (top < 0) {
- if (offset)
- offset->ry() += -top;
- effectRect.setY(0);
- }
- // NB! We use +-1 for historical reasons (see QRect documentation).
- QPaintDevice *device = info->painter->device();
- const int deviceWidth = device->width();
- const int deviceHeight = device->height();
- if (right + 1 > deviceWidth)
- effectRect.setRight(deviceWidth - 1);
- if (bottom + 1 > deviceHeight)
- effectRect.setBottom(deviceHeight -1);
-
- }
if (effectRect.isEmpty())
return QPixmap();
@@ -10921,14 +11188,14 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP
&newEffectTransform, false, true);
} else if (deviceCoordinates) {
// Device coordinates with info.
- scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, info->exposedRegion,
+ scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, 0,
info->widget, info->opacity, &effectTransform, info->wasDirtySceneTransform,
info->drawItem);
} else {
// Item coordinates with info.
QTransform newEffectTransform = info->transformPtr->inverted();
newEffectTransform *= effectTransform;
- scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, info->exposedRegion,
+ scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, 0,
info->widget, info->opacity, &newEffectTransform, info->wasDirtySceneTransform,
info->drawItem);
}
@@ -11064,6 +11331,24 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemChange change)
case QGraphicsItem::ItemScenePositionHasChanged:
str = "ItemScenePositionHasChanged";
break;
+ case QGraphicsItem::ItemRotationChange:
+ str = "ItemRotationChange";
+ break;
+ case QGraphicsItem::ItemRotationHasChanged:
+ str = "ItemRotationHasChanged";
+ break;
+ case QGraphicsItem::ItemScaleChange:
+ str = "ItemScaleChange";
+ break;
+ case QGraphicsItem::ItemScaleHasChanged:
+ str = "ItemScaleHasChanged";
+ break;
+ case QGraphicsItem::ItemTransformOriginPointChange:
+ str = "ItemTransformOriginPointChange";
+ break;
+ case QGraphicsItem::ItemTransformOriginPointHasChanged:
+ str = "ItemTransformOriginPointHasChanged";
+ break;
}
debug << str;
return debug;
@@ -11133,7 +11418,7 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlags flags)
{
debug << '(';
bool f = false;
- for (int i = 0; i < 16; ++i) {
+ for (int i = 0; i < 17; ++i) {
if (flags & (1 << i)) {
if (f)
debug << '|';
diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h
index d72833b..9cc75af 100644
--- a/src/gui/graphicsview/qgraphicsitem.h
+++ b/src/gui/graphicsview/qgraphicsitem.h
@@ -139,7 +139,13 @@ public:
ItemZValueHasChanged,
ItemOpacityChange,
ItemOpacityHasChanged,
- ItemScenePositionHasChanged
+ ItemScenePositionHasChanged,
+ ItemRotationChange,
+ ItemRotationHasChanged,
+ ItemScaleChange,
+ ItemScaleHasChanged,
+ ItemTransformOriginPointChange,
+ ItemTransformOriginPointHasChanged
};
enum CacheMode {
@@ -418,6 +424,7 @@ public:
void removeSceneEventFilter(QGraphicsItem *filterItem);
protected:
+ void updateMicroFocus();
virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event);
virtual bool sceneEvent(QEvent *event);
virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
@@ -540,13 +547,17 @@ class Q_GUI_EXPORT QGraphicsObject : public QObject, public QGraphicsItem
Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged FINAL)
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)
Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged FINAL)
- Q_PROPERTY(QPointF pos READ pos WRITE setPos)
- Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
- Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
- Q_PROPERTY(qreal z READ zValue WRITE setZValue NOTIFY zChanged)
+ Q_PROPERTY(QPointF pos READ pos WRITE setPos FINAL)
+ Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged FINAL)
+ Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged FINAL)
+ Q_PROPERTY(qreal z READ zValue WRITE setZValue NOTIFY zChanged FINAL)
Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged)
Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged)
Q_PROPERTY(QPointF transformOriginPoint READ transformOriginPoint WRITE setTransformOriginPoint)
+ Q_PRIVATE_PROPERTY(QGraphicsItem::d_func(), QDeclarativeListProperty<QGraphicsObject> children READ childrenList DESIGNABLE false NOTIFY childrenChanged)
+ Q_PRIVATE_PROPERTY(QGraphicsItem::d_func(), qreal width READ width WRITE setWidth NOTIFY widthChanged RESET resetWidth FINAL)
+ Q_PRIVATE_PROPERTY(QGraphicsItem::d_func(), qreal height READ height WRITE setHeight NOTIFY heightChanged RESET resetHeight FINAL)
+ Q_CLASSINFO("DefaultProperty", "children")
Q_INTERFACES(QGraphicsItem)
public:
QGraphicsObject(QGraphicsItem *parent = 0);
@@ -561,6 +572,9 @@ public:
void grabGesture(Qt::GestureType type, Qt::GestureFlags flags = Qt::GestureFlags());
void ungrabGesture(Qt::GestureType type);
+protected Q_SLOTS:
+ void updateMicroFocus();
+
Q_SIGNALS:
void parentChanged();
void opacityChanged();
@@ -571,6 +585,9 @@ Q_SIGNALS:
void zChanged();
void rotationChanged();
void scaleChanged();
+ void childrenChanged();
+ void widthChanged();
+ void heightChanged();
protected:
QGraphicsObject(QGraphicsItemPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene);
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index 4c4bfaf..73b8f04 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -71,6 +71,63 @@ QT_BEGIN_NAMESPACE
class QGraphicsItemPrivate;
+#ifndef QDECLARATIVELISTPROPERTY
+#define QDECLARATIVELISTPROPERTY
+template<typename T>
+class QDeclarativeListProperty {
+public:
+ typedef void (*AppendFunction)(QDeclarativeListProperty<T> *, T*);
+ typedef int (*CountFunction)(QDeclarativeListProperty<T> *);
+ typedef T *(*AtFunction)(QDeclarativeListProperty<T> *, int);
+ typedef void (*ClearFunction)(QDeclarativeListProperty<T> *);
+
+ QDeclarativeListProperty()
+ : object(0), data(0), append(0), count(0), at(0), clear(0), dummy1(0), dummy2(0) {}
+ QDeclarativeListProperty(QObject *o, QList<T *> &list)
+ : object(o), data(&list), append(qlist_append), count(qlist_count), at(qlist_at),
+ clear(qlist_clear), dummy1(0), dummy2(0) {}
+ QDeclarativeListProperty(QObject *o, void *d, AppendFunction a, CountFunction c = 0, AtFunction t = 0,
+ ClearFunction r = 0)
+ : object(o), data(d), append(a), count(c), at(t), clear(r), dummy1(0), dummy2(0) {}
+
+ bool operator==(const QDeclarativeListProperty &o) const {
+ return object == o.object &&
+ data == o.data &&
+ append == o.append &&
+ count == o.count &&
+ at == o.at &&
+ clear == o.clear;
+ }
+
+ QObject *object;
+ void *data;
+
+ AppendFunction append;
+
+ CountFunction count;
+ AtFunction at;
+
+ ClearFunction clear;
+
+ void *dummy1;
+ void *dummy2;
+
+private:
+ static void qlist_append(QDeclarativeListProperty *p, T *v) {
+ ((QList<T *> *)p->data)->append(v);
+ }
+ static int qlist_count(QDeclarativeListProperty *p) {
+ return ((QList<T *> *)p->data)->count();
+ }
+ static T *qlist_at(QDeclarativeListProperty *p, int idx) {
+ return ((QList<T *> *)p->data)->at(idx);
+ }
+ static void qlist_clear(QDeclarativeListProperty *p) {
+ return ((QList<T *> *)p->data)->clear();
+ }
+};
+#endif
+
class QGraphicsItemCache
{
public:
@@ -220,6 +277,7 @@ public:
virtual void setPosHelper(const QPointF &pos);
void setTransformHelper(const QTransform &transform);
+ void prependGraphicsTransform(QGraphicsTransform *t);
void appendGraphicsTransform(QGraphicsTransform *t);
void setVisibleHelper(bool newVisible, bool explicitly, bool update = true);
void setEnabledHelper(bool newEnabled, bool explicitly, bool update = true);
@@ -237,6 +295,7 @@ public:
void resolveDepth();
void addChild(QGraphicsItem *child);
void removeChild(QGraphicsItem *child);
+ QDeclarativeListProperty<QGraphicsObject> childrenList();
void setParentItemHelper(QGraphicsItem *parent, const QVariant *newParentVariant,
const QVariant *thisPointerVariant);
void childrenBoundingRectHelper(QTransform *x, QRectF *rect);
@@ -414,7 +473,8 @@ public:
inline void markParentDirty(bool updateBoundingRect = false);
- void setFocusHelper(Qt::FocusReason focusReason, bool climb);
+ void setFocusHelper(Qt::FocusReason focusReason, bool climb, bool focusFromShow);
+ void clearFocusHelper(bool giveFocusToParent);
void setSubFocus(QGraphicsItem *rootItem = 0);
void clearSubFocus(QGraphicsItem *rootItem = 0);
void resetFocusProxy();
@@ -422,11 +482,21 @@ public:
inline QTransform transformToParent() const;
inline void ensureSortedChildren();
+ static void append(QDeclarativeListProperty<QGraphicsObject> *list, QGraphicsObject *item);
static inline bool insertionOrder(QGraphicsItem *a, QGraphicsItem *b);
void ensureSequentialSiblingIndex();
inline void sendScenePosChange();
virtual void siblingOrderChange();
+ // Private Properties
+ virtual qreal width() const;
+ virtual void setWidth(qreal);
+ virtual void resetWidth();
+
+ virtual qreal height() const;
+ virtual void setHeight(qreal);
+ virtual void resetHeight();
+
QRectF childrenBoundingRect;
QRectF needsRepaint;
QMap<QWidget *, QRect> paintedViewBoundingRects;
diff --git a/src/gui/graphicsview/qgraphicslinearlayout.cpp b/src/gui/graphicsview/qgraphicslinearlayout.cpp
index 6a9eb29..9722683 100644
--- a/src/gui/graphicsview/qgraphicslinearlayout.cpp
+++ b/src/gui/graphicsview/qgraphicslinearlayout.cpp
@@ -554,6 +554,8 @@ void QGraphicsLinearLayout::dump(int indent) const
d->orientation == Qt::Horizontal ? "Horizontal" : "Vertical");
d->engine.dump(indent + 1);
}
+#else
+ Q_UNUSED(indent);
#endif
}
diff --git a/src/gui/graphicsview/qgraphicsproxywidget.cpp b/src/gui/graphicsview/qgraphicsproxywidget.cpp
index a39ccfd..2132526 100644
--- a/src/gui/graphicsview/qgraphicsproxywidget.cpp
+++ b/src/gui/graphicsview/qgraphicsproxywidget.cpp
@@ -1315,6 +1315,8 @@ void QGraphicsProxyWidget::focusInEvent(QFocusEvent *event)
return;
}
+ d->proxyIsGivingFocus = true;
+
switch (event->reason()) {
case Qt::TabFocusReason: {
if (QWidget *focusChild = d->findFocusChild(0, true))
@@ -1328,10 +1330,11 @@ void QGraphicsProxyWidget::focusInEvent(QFocusEvent *event)
default:
if (d->widget && d->widget->focusWidget()) {
d->widget->focusWidget()->setFocus(event->reason());
- return;
}
break;
}
+
+ d->proxyIsGivingFocus = false;
}
/*!
@@ -1432,7 +1435,7 @@ void QGraphicsProxyWidget::paint(QPainter *painter, const QStyleOptionGraphicsIt
return;
// Filter out repaints on the window frame.
- const QRect exposedWidgetRect = (option->exposedRect & rect()).toRect();
+ const QRect exposedWidgetRect = (option->exposedRect & rect()).toAlignedRect();
if (exposedWidgetRect.isEmpty())
return;
diff --git a/src/gui/graphicsview/qgraphicsproxywidget_p.h b/src/gui/graphicsview/qgraphicsproxywidget_p.h
index 60eb058..8aed363 100644
--- a/src/gui/graphicsview/qgraphicsproxywidget_p.h
+++ b/src/gui/graphicsview/qgraphicsproxywidget_p.h
@@ -118,6 +118,7 @@ public:
quint32 styleChangeMode : 2;
quint32 paletteChangeMode : 2;
quint32 focusFromWidgetToProxy : 1;
+ quint32 proxyIsGivingFocus : 1;
};
QT_END_NAMESPACE
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 365afdd..4b612f4 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -228,6 +228,7 @@
#include <QtCore/qstack.h>
#include <QtCore/qtimer.h>
#include <QtCore/qvarlengtharray.h>
+#include <QtCore/QMetaMethod>
#include <QtGui/qapplication.h>
#include <QtGui/qdesktopwidget.h>
#include <QtGui/qevent.h>
@@ -277,8 +278,6 @@ static void _q_hoverFromMouseEvent(QGraphicsSceneHoverEvent *hover, const QGraph
hover->setAccepted(mouseEvent->isAccepted());
}
-int QGraphicsScenePrivate::changedSignalIndex;
-
/*!
\internal
*/
@@ -329,9 +328,10 @@ void QGraphicsScenePrivate::init()
index = new QGraphicsSceneBspTreeIndex(q);
// Keep this index so we can check for connected slots later on.
- if (!changedSignalIndex) {
- changedSignalIndex = signalIndex("changed(QList<QRectF>)");
- }
+ changedSignalIndex = signalIndex("changed(QList<QRectF>)");
+ processDirtyItemsIndex = q->metaObject()->indexOfSlot("_q_processDirtyItems()");
+ polishItemsIndex = q->metaObject()->indexOfSlot("_q_polishItems()");
+
qApp->d_func()->scene_list.append(q);
q->update();
}
@@ -2537,8 +2537,10 @@ void QGraphicsScene::addItem(QGraphicsItem *item)
return;
}
- if (d->unpolishedItems.isEmpty())
- QMetaObject::invokeMethod(this, "_q_polishItems", Qt::QueuedConnection);
+ if (d->unpolishedItems.isEmpty()) {
+ QMetaMethod method = metaObject()->method(d->polishItemsIndex);
+ method.invoke(this, Qt::QueuedConnection);
+ }
d->unpolishedItems.append(item);
item->d_ptr->pendingPolish = true;
@@ -4299,6 +4301,7 @@ static void _q_paintIntoCache(QPixmap *pix, QGraphicsItem *item, const QRegion &
if (!subPix.isNull()) {
// Blit the subpixmap into the main pixmap.
pixmapPainter.begin(pix);
+ pixmapPainter.setCompositionMode(QPainter::CompositionMode_Source);
pixmapPainter.setClipRegion(pixmapExposed);
pixmapPainter.drawPixmap(br.topLeft(), subPix);
pixmapPainter.end();
@@ -4464,6 +4467,8 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
}
// Create or reuse offscreen pixmap, possibly scroll/blit from the old one.
+ // If the world transform is rotated we always recreate the cache to avoid
+ // wrong blending.
bool pixModified = false;
QGraphicsItemCache::DeviceData *deviceData = &itemCache->deviceData[widget];
bool invertable = true;
@@ -4471,7 +4476,9 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
if (invertable)
diff *= painter->worldTransform();
deviceData->lastTransform = painter->worldTransform();
- if (!invertable || diff.type() > QTransform::TxTranslate) {
+ if (!invertable
+ || diff.type() > QTransform::TxTranslate
+ || painter->worldTransform().type() > QTransform::TxScale) {
pixModified = true;
itemCache->allExposed = true;
itemCache->exposed.clear();
@@ -4713,7 +4720,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
if (item->d_ptr->graphicsEffect && item->d_ptr->graphicsEffect->isEnabled()) {
ENSURE_TRANSFORM_PTR;
QGraphicsItemPaintInfo info(viewTransform, transformPtr, effectTransform, exposedRegion, widget, &styleOptionTmp,
- painter, opacity, wasDirtyParentSceneTransform, drawItem);
+ painter, opacity, wasDirtyParentSceneTransform, itemHasContents && !itemIsFullyTransparent);
QGraphicsEffectSource *source = item->d_ptr->graphicsEffect->d_func()->source;
QGraphicsItemEffectSourcePrivate *sourced = static_cast<QGraphicsItemEffectSourcePrivate *>
(source->d_func());
@@ -4728,31 +4735,18 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
if (sourced->currentCachedSystem() != Qt::LogicalCoordinates
&& sourced->lastEffectTransform != painter->worldTransform())
{
- bool unclipped = false;
if (sourced->lastEffectTransform.type() <= QTransform::TxTranslate
&& painter->worldTransform().type() <= QTransform::TxTranslate)
{
- QRectF itemRect = item->boundingRect();
- if (!item->d_ptr->children.isEmpty())
- itemRect |= item->childrenBoundingRect();
+ QRectF sourceRect = sourced->boundingRect(Qt::DeviceCoordinates);
+ QRect effectRect = sourced->paddedEffectRect(Qt::DeviceCoordinates, sourced->currentCachedMode(), sourceRect);
- QRectF oldSourceRect = sourced->lastEffectTransform.mapRect(itemRect);
- QRectF newSourceRect = painter->worldTransform().mapRect(itemRect);
-
- QRect oldEffectRect = sourced->paddedEffectRect(sourced->currentCachedSystem(), sourced->currentCachedMode(), oldSourceRect);
- QRect newEffectRect = sourced->paddedEffectRect(sourced->currentCachedSystem(), sourced->currentCachedMode(), newSourceRect);
-
- QRect deviceRect(0, 0, painter->device()->width(), painter->device()->height());
- if (deviceRect.contains(oldEffectRect) && deviceRect.contains(newEffectRect)) {
- sourced->setCachedOffset(newEffectRect.topLeft());
- unclipped = true;
- }
+ sourced->setCachedOffset(effectRect.topLeft());
+ } else {
+ sourced->invalidateCache(QGraphicsEffectSourcePrivate::TransformChanged);
}
sourced->lastEffectTransform = painter->worldTransform();
-
- if (!unclipped)
- sourced->invalidateCache(QGraphicsEffectSourcePrivate::TransformChanged);
}
item->d_ptr->graphicsEffect->draw(painter);
@@ -4892,7 +4886,9 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b
return;
if (!processDirtyItemsEmitted) {
- QMetaObject::invokeMethod(q_ptr, "_q_processDirtyItems", Qt::QueuedConnection);
+ QMetaMethod method = q_ptr->metaObject()->method(processDirtyItemsIndex);
+ method.invoke(q_ptr, Qt::QueuedConnection);
+// QMetaObject::invokeMethod(q_ptr, "_q_processDirtyItems", Qt::QueuedConnection);
processDirtyItemsEmitted = true;
}
@@ -5972,12 +5968,12 @@ void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event)
QList<QGesture *> allGestures = event->gestures();
DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
- << "Delivering gestures:" << allGestures;
+ << "Gestures:" << allGestures;
QSet<QGesture *> startedGestures;
- QPoint delta = graphicsView->mapFromGlobal(QPoint());
- QTransform toScene = QTransform::fromTranslate(delta.x(), delta.y())
- * graphicsView->viewportTransform().inverted();
+ QPoint delta = viewport->mapFromGlobal(QPoint());
+ QTransform toScene = QTransform::fromTranslate(delta.x(), delta.y())
+ * graphicsView->viewportTransform().inverted();
foreach (QGesture *gesture, allGestures) {
// cache scene coordinates of the hot spot
if (gesture->hasHotSpot()) {
@@ -6003,7 +5999,8 @@ void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event)
cachedTargetItems = cachedItemGestures.keys();
qSort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst);
DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
- << "Conflicting gestures:" << conflictedGestures;
+ << "Normal gestures:" << normalGestures
+ << "Conflicting gestures:" << conflictedGestures;
// deliver conflicted gestures as override events AND remember
// initial gesture targets
@@ -6080,6 +6077,10 @@ void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event)
const Qt::GestureFlags flags = d->gestureContext.value(gesture->gestureType());
if (flags & Qt::IgnoredGesturesPropagateToParent)
parentPropagatedGestures.insert(gesture);
+ } else {
+ DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
+ << "no target for" << gesture << "at"
+ << gesture->hotSpot() << gesture->d_func()->sceneHotSpot;
}
}
qSort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst);
diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h
index ca8b829..11e250e 100644
--- a/src/gui/graphicsview/qgraphicsscene_p.h
+++ b/src/gui/graphicsview/qgraphicsscene_p.h
@@ -87,7 +87,9 @@ public:
static QGraphicsScenePrivate *get(QGraphicsScene *q);
- static int changedSignalIndex;
+ int changedSignalIndex;
+ int processDirtyItemsIndex;
+ int polishItemsIndex;
QGraphicsScene::ItemIndexMethod indexMethod;
QGraphicsSceneIndex *index;
diff --git a/src/gui/graphicsview/qgraphicssceneevent.h b/src/gui/graphicsview/qgraphicssceneevent.h
index 033a996..c8a0028 100644
--- a/src/gui/graphicsview/qgraphicssceneevent.h
+++ b/src/gui/graphicsview/qgraphicssceneevent.h
@@ -77,6 +77,8 @@ protected:
QGraphicsSceneEvent(QGraphicsSceneEventPrivate &dd, Type type = None);
QScopedPointer<QGraphicsSceneEventPrivate> d_ptr;
Q_DECLARE_PRIVATE(QGraphicsSceneEvent)
+private:
+ Q_DISABLE_COPY(QGraphicsSceneEvent)
};
class QGraphicsSceneMouseEventPrivate;
@@ -124,6 +126,7 @@ public:
private:
Q_DECLARE_PRIVATE(QGraphicsSceneMouseEvent)
+ Q_DISABLE_COPY(QGraphicsSceneMouseEvent)
};
class QGraphicsSceneWheelEventPrivate;
@@ -156,6 +159,7 @@ public:
private:
Q_DECLARE_PRIVATE(QGraphicsSceneWheelEvent)
+ Q_DISABLE_COPY(QGraphicsSceneWheelEvent)
};
class QGraphicsSceneContextMenuEventPrivate;
@@ -184,6 +188,7 @@ public:
private:
Q_DECLARE_PRIVATE(QGraphicsSceneContextMenuEvent)
+ Q_DISABLE_COPY(QGraphicsSceneContextMenuEvent)
};
class QGraphicsSceneHoverEventPrivate;
@@ -216,6 +221,7 @@ public:
private:
Q_DECLARE_PRIVATE(QGraphicsSceneHoverEvent)
+ Q_DISABLE_COPY(QGraphicsSceneHoverEvent)
};
class QGraphicsSceneHelpEventPrivate;
@@ -233,6 +239,7 @@ public:
private:
Q_DECLARE_PRIVATE(QGraphicsSceneHelpEvent)
+ Q_DISABLE_COPY(QGraphicsSceneHelpEvent)
};
class QGraphicsSceneDragDropEventPrivate;
@@ -275,12 +282,14 @@ public:
private:
Q_DECLARE_PRIVATE(QGraphicsSceneDragDropEvent)
+ Q_DISABLE_COPY(QGraphicsSceneDragDropEvent)
};
class QGraphicsSceneResizeEventPrivate;
class Q_GUI_EXPORT QGraphicsSceneResizeEvent : public QGraphicsSceneEvent
{
Q_DECLARE_PRIVATE(QGraphicsSceneResizeEvent)
+ Q_DISABLE_COPY(QGraphicsSceneResizeEvent)
public:
QGraphicsSceneResizeEvent();
~QGraphicsSceneResizeEvent();
@@ -296,6 +305,7 @@ class QGraphicsSceneMoveEventPrivate;
class Q_GUI_EXPORT QGraphicsSceneMoveEvent : public QGraphicsSceneEvent
{
Q_DECLARE_PRIVATE(QGraphicsSceneMoveEvent)
+ Q_DISABLE_COPY(QGraphicsSceneMoveEvent)
public:
QGraphicsSceneMoveEvent();
~QGraphicsSceneMoveEvent();
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index 1ced3d7..a767987 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -3360,12 +3360,6 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
backgroundPainter.setClipRegion(d->backgroundPixmapExposed, Qt::ReplaceClip);
if (viewTransformed)
backgroundPainter.setTransform(viewTransform);
-#ifdef Q_WS_X11
-#undef X11
- if (backgroundPainter.paintEngine()->type() != QPaintEngine::X11)
-#define X11 qt_x11Data
-#endif
- backgroundPainter.setCompositionMode(QPainter::CompositionMode_Source);
QRectF backgroundExposedSceneRect = mapToScene(d->backgroundPixmapExposed.boundingRect()).boundingRect();
drawBackground(&backgroundPainter, backgroundExposedSceneRect);
d->backgroundPixmapExposed = QRegion();
diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp
index 87416b4..bc8ccb01 100644
--- a/src/gui/graphicsview/qgraphicswidget.cpp
+++ b/src/gui/graphicsview/qgraphicswidget.cpp
@@ -324,6 +324,14 @@ void QGraphicsWidget::resize(const QSizeF &size)
*/
/*!
+
+ \fn QGraphicsWidget::geometryChanged()
+
+ This signal gets emitted whenever the geometry of the item changes
+ \internal
+*/
+
+/*!
\property QGraphicsWidget::geometry
\brief the geometry of the widget
@@ -334,7 +342,7 @@ void QGraphicsWidget::resize(const QSizeF &size)
A side effect of calling this function is that the widget will receive
a move event and a resize event. Also, if the widget has a layout
assigned, the layout will activate.
-
+
\sa geometry(), resize()
*/
void QGraphicsWidget::setGeometry(const QRectF &rect)
@@ -384,18 +392,28 @@ void QGraphicsWidget::setGeometry(const QRectF &rect)
}
QSizeF oldSize = size();
QGraphicsLayoutItem::setGeometry(newGeom);
-
+ emit geometryChanged();
// Send resize event
bool resized = newGeom.size() != oldSize;
if (resized) {
QGraphicsSceneResizeEvent re;
re.setOldSize(oldSize);
re.setNewSize(newGeom.size());
+ if (oldSize.width() != newGeom.size().width())
+ emit widthChanged();
+ if (oldSize.height() != newGeom.size().height())
+ emit heightChanged();
QApplication::sendEvent(this, &re);
}
}
/*!
+ \fn QGraphicsWidget::geometryChanged()
+
+ This signal gets emitted whenever the geometry is changed in setGeometry().
+*/
+
+/*!
\fn QRectF QGraphicsWidget::rect() const
Returns the item's local rect as a QRectF. This function is equivalent
@@ -562,7 +580,7 @@ void QGraphicsWidget::getWindowFrameMargins(qreal *left, qreal *top, qreal *righ
void QGraphicsWidget::unsetWindowFrameMargins()
{
Q_D(QGraphicsWidget);
- if ((d->windowFlags & Qt::Window) && (d->windowFlags & Qt::WindowType_Mask) != Qt::Popup &&
+ if ((d->windowFlags & Qt::Window) && (d->windowFlags & Qt::WindowType_Mask) != Qt::Popup &&
(d->windowFlags & Qt::WindowType_Mask) != Qt::ToolTip && !(d->windowFlags & Qt::FramelessWindowHint)) {
QStyleOptionTitleBar bar;
d->initStyleOptionTitleBar(&bar);
@@ -789,6 +807,7 @@ void QGraphicsWidget::setLayout(QGraphicsLayout *l)
l->setParentLayoutItem(this);
l->d_func()->reparentChildItems(this);
l->invalidate();
+ emit layoutChanged();
}
/*!
@@ -1097,13 +1116,13 @@ QVariant QGraphicsWidget::itemChange(GraphicsItemChange change, const QVariant &
QApplication::sendEvent(this, &event);
break;
}
- case ItemCursorChange: {
+ case ItemCursorHasChanged: {
// Deliver CursorChange.
QEvent event(QEvent::CursorChange);
QApplication::sendEvent(this, &event);
break;
}
- case ItemToolTipChange: {
+ case ItemToolTipHasChanged: {
// Deliver ToolTipChange.
QEvent event(QEvent::ToolTipChange);
QApplication::sendEvent(this, &event);
@@ -1169,7 +1188,7 @@ bool QGraphicsWidget::sceneEvent(QEvent *event)
Returns true if \a event has been recognized and processed; otherwise,
returns false.
-
+
\sa event()
*/
bool QGraphicsWidget::windowFrameEvent(QEvent *event)
@@ -1226,7 +1245,7 @@ Qt::WindowFrameSection QGraphicsWidget::windowFrameSectionAt(const QPointF &pos)
const QRectF r = windowFrameRect();
if (!r.contains(pos))
return Qt::NoSection;
-
+
const qreal left = r.left();
const qreal top = r.top();
const qreal right = r.right();
@@ -2352,5 +2371,5 @@ void QGraphicsWidget::dumpFocusChain()
#endif
QT_END_NAMESPACE
-
+
#endif //QT_NO_GRAPHICSVIEW
diff --git a/src/gui/graphicsview/qgraphicswidget.h b/src/gui/graphicsview/qgraphicswidget.h
index 4bea5be..a22b642 100644
--- a/src/gui/graphicsview/qgraphicswidget.h
+++ b/src/gui/graphicsview/qgraphicswidget.h
@@ -73,7 +73,7 @@ class Q_GUI_EXPORT QGraphicsWidget : public QGraphicsObject, public QGraphicsLay
Q_PROPERTY(QPalette palette READ palette WRITE setPalette)
Q_PROPERTY(QFont font READ font WRITE setFont)
Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection RESET unsetLayoutDirection)
- Q_PROPERTY(QSizeF size READ size WRITE resize)
+ Q_PROPERTY(QSizeF size READ size WRITE resize NOTIFY geometryChanged)
Q_PROPERTY(QSizeF minimumSize READ minimumSize WRITE setMinimumSize)
Q_PROPERTY(QSizeF preferredSize READ preferredSize WRITE setPreferredSize)
Q_PROPERTY(QSizeF maximumSize READ maximumSize WRITE setMaximumSize)
@@ -81,12 +81,12 @@ class Q_GUI_EXPORT QGraphicsWidget : public QGraphicsObject, public QGraphicsLay
Q_PROPERTY(Qt::FocusPolicy focusPolicy READ focusPolicy WRITE setFocusPolicy)
Q_PROPERTY(Qt::WindowFlags windowFlags READ windowFlags WRITE setWindowFlags)
Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle)
- Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry)
+ Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry NOTIFY geometryChanged)
Q_PROPERTY(bool autoFillBackground READ autoFillBackground WRITE setAutoFillBackground)
+ Q_PROPERTY(QGraphicsLayout* layout READ layout WRITE setLayout NOTIFY layoutChanged)
public:
QGraphicsWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0);
~QGraphicsWidget();
-
QGraphicsLayout *layout() const;
void setLayout(QGraphicsLayout *layout);
void adjustSize();
@@ -179,6 +179,10 @@ public:
using QObject::children;
#endif
+Q_SIGNALS:
+ void geometryChanged();
+ void layoutChanged();
+
public Q_SLOTS:
bool close();
diff --git a/src/gui/graphicsview/qgraphicswidget_p.cpp b/src/gui/graphicsview/qgraphicswidget_p.cpp
index 1835c74..6e397b6 100644
--- a/src/gui/graphicsview/qgraphicswidget_p.cpp
+++ b/src/gui/graphicsview/qgraphicswidget_p.cpp
@@ -44,6 +44,7 @@
#ifndef QT_NO_GRAPHICSVIEW
#include <QtCore/qdebug.h>
+#include <QtCore/qnumeric.h>
#include "qgraphicswidget_p.h"
#include "qgraphicslayout.h"
#include "qgraphicsscene_p.h"
@@ -825,6 +826,56 @@ void QGraphicsWidgetPrivate::setLayout_helper(QGraphicsLayout *l)
}
}
+qreal QGraphicsWidgetPrivate::width() const
+{
+ Q_Q(const QGraphicsWidget);
+ return q->geometry().width();
+}
+
+void QGraphicsWidgetPrivate::setWidth(qreal w)
+{
+ if (qIsNaN(w))
+ return;
+ Q_Q(QGraphicsWidget);
+ if (q->geometry().width() == w)
+ return;
+
+ QRectF oldGeom = q->geometry();
+
+ q->setGeometry(QRectF(q->x(), q->y(), w, height()));
+}
+
+void QGraphicsWidgetPrivate::resetWidth()
+{
+ Q_Q(QGraphicsWidget);
+ q->setGeometry(QRectF(q->x(), q->y(), 0, height()));
+}
+
+qreal QGraphicsWidgetPrivate::height() const
+{
+ Q_Q(const QGraphicsWidget);
+ return q->geometry().height();
+}
+
+void QGraphicsWidgetPrivate::setHeight(qreal h)
+{
+ if (qIsNaN(h))
+ return;
+ Q_Q(QGraphicsWidget);
+ if (q->geometry().height() == h)
+ return;
+
+ QRectF oldGeom = q->geometry();
+
+ q->setGeometry(QRectF(q->x(), q->y(), width(), h));
+}
+
+void QGraphicsWidgetPrivate::resetHeight()
+{
+ Q_Q(QGraphicsWidget);
+ q->setGeometry(QRectF(q->x(), q->y(), width(), 0));
+}
+
QT_END_NAMESPACE
#endif //QT_NO_GRAPHICSVIEW
diff --git a/src/gui/graphicsview/qgraphicswidget_p.h b/src/gui/graphicsview/qgraphicswidget_p.h
index 3ab8737..7116a23 100644
--- a/src/gui/graphicsview/qgraphicswidget_p.h
+++ b/src/gui/graphicsview/qgraphicswidget_p.h
@@ -131,6 +131,15 @@ public:
void windowFrameHoverLeaveEvent(QGraphicsSceneHoverEvent *event);
bool hasDecoration() const;
+ // Private Properties
+ qreal width() const;
+ void setWidth(qreal);
+ void resetWidth();
+
+ qreal height() const;
+ void setHeight(qreal);
+ void resetHeight();
+
// State
inline int attributeToBitIndex(Qt::WidgetAttribute att) const
{
diff --git a/src/gui/gui.pro b/src/gui/gui.pro
index d46f3b4..300a03f 100644
--- a/src/gui/gui.pro
+++ b/src/gui/gui.pro
@@ -41,6 +41,7 @@ include(math3d/math3d.pri)
include(effects/effects.pri)
contains(QT_CONFIG, egl): include(egl/egl.pri)
+win32:!wince*: DEFINES += QT_NO_EGL
embedded: QT += network
@@ -51,16 +52,17 @@ contains(DEFINES,QT_EVAL):include($$QT_SOURCE_TREE/src/corelib/eval.pri)
QMAKE_DYNAMIC_LIST_FILE = $$PWD/QtGui.dynlist
DEFINES += Q_INTERNAL_QAPP_SRC
-symbian: {
+symbian {
TARGET.UID3=0x2001B2DD
- # ro-section in gui can exceed default allocated space, so move rw-section a little further
- QMAKE_LFLAGS.ARMCC += --rw-base 0x800000
- QMAKE_LFLAGS.GCCE += -Tdata 0xC00000
+ symbian-abld|symbian-sbsv2 {
+ # ro-section in gui can exceed default allocated space, so move rw-section a little further
+ QMAKE_LFLAGS.ARMCC += --rw-base 0x800000
+ QMAKE_LFLAGS.GCCE += -Tdata 0xC00000
+ }
# Partial upgrade SIS file
vendorinfo = \
- "&EN" \
"; Localised Vendor name" \
"%{\"Nokia, Qt\"}" \
" " \
@@ -70,7 +72,7 @@ symbian: {
pu_header = "; Partial upgrade package for testing QtGui changes without reinstalling everything" \
"$${LITERAL_HASH}{\"Qt gui\"}, (0x2001E61C), $${QT_MAJOR_VERSION},$${QT_MINOR_VERSION},$${QT_PATCH_VERSION}, TYPE=PU"
partial_upgrade.pkg_prerules = pu_header vendorinfo
- partial_upgrade.sources = qtgui.dll
+ partial_upgrade.sources = $$QMAKE_LIBDIR_QT/QtGui.dll
partial_upgrade.path = c:/sys/bin
DEPLOYMENT = partial_upgrade $$DEPLOYMENT
}
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index bf6eb8d..fad51f4 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -982,7 +982,9 @@ QIcon QIcon::fromTheme(const QString &name, const QIcon &fallback)
icon = *cachedIcon;
}
- if (icon.availableSizes().isEmpty())
+ // Note the qapp check is to allow lazy loading of static icons
+ // Supporting fallbacks will not work for this case.
+ if (qApp && icon.availableSizes().isEmpty())
return fallback;
return icon;
diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp
index b35e80a..72ec2e8 100644
--- a/src/gui/image/qiconloader.cpp
+++ b/src/gui/image/qiconloader.cpp
@@ -85,19 +85,30 @@ static QString fallbackTheme()
}
QIconLoader::QIconLoader() :
- m_themeKey(1), m_supportsSvg(false)
+ m_themeKey(1), m_supportsSvg(false), m_initialized(false)
{
- m_systemTheme = qt_guiPlatformPlugin()->systemIconThemeName();
- if (m_systemTheme.isEmpty())
- m_systemTheme = fallbackTheme();
+}
+
+// We lazily initialize the loader to make static icons
+// work. Though we do not officially support this.
+void QIconLoader::ensureInitialized()
+{
+ if (!m_initialized) {
+ m_initialized = true;
+
+ Q_ASSERT(qApp);
+ m_systemTheme = qt_guiPlatformPlugin()->systemIconThemeName();
+ if (m_systemTheme.isEmpty())
+ m_systemTheme = fallbackTheme();
#ifndef QT_NO_LIBRARY
- QFactoryLoader iconFactoryLoader(QIconEngineFactoryInterfaceV2_iid,
- QLatin1String("/iconengines"),
- Qt::CaseInsensitive);
- if (iconFactoryLoader.keys().contains(QLatin1String("svg")))
- m_supportsSvg = true;
+ QFactoryLoader iconFactoryLoader(QIconEngineFactoryInterfaceV2_iid,
+ QLatin1String("/iconengines"),
+ Qt::CaseInsensitive);
+ if (iconFactoryLoader.keys().contains(QLatin1String("svg")))
+ m_supportsSvg = true;
#endif //QT_NO_LIBRARY
+ }
}
QIconLoader *QIconLoader::instance()
@@ -339,6 +350,9 @@ bool QIconLoaderEngine::hasIcon() const
// Lazily load the icon
void QIconLoaderEngine::ensureLoaded()
{
+
+ iconLoaderInstance()->ensureInitialized();
+
if (!(iconLoaderInstance()->themeKey() == m_key)) {
while (!m_entries.isEmpty())
diff --git a/src/gui/image/qiconloader_p.h b/src/gui/image/qiconloader_p.h
index 19f2dda..a6b5f5b 100644
--- a/src/gui/image/qiconloader_p.h
+++ b/src/gui/image/qiconloader_p.h
@@ -169,6 +169,7 @@ public:
static QIconLoader *instance();
void updateSystemTheme();
void invalidateKey() { m_themeKey++; }
+ void ensureInitialized();
private:
QThemeIconEntries findIconHelper(const QString &themeName,
@@ -176,6 +177,7 @@ private:
QStringList &visited) const;
uint m_themeKey;
bool m_supportsSvg;
+ bool m_initialized;
mutable QString m_userTheme;
mutable QString m_systemTheme;
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 6bcf72b..d226baf 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -480,9 +480,12 @@ bool QImageData::checkForAlphaPixels() const
\row
\o Low-level information
\o
+
The depth() function returns the depth of the image. The supported
- depths are 1 (monochrome), 8 and 32 (for more information see the
- \l {QImage#Image Formats}{Image Formats} section).
+ depths are 1 (monochrome), 8, 16, 24 and 32 bits. The
+ bitPlaneCount() function tells how many of those bits that are
+ used. For more information see the
+ \l {QImage#Image Formats}{Image Formats} section.
The format(), bytesPerLine(), and byteCount() functions provide
low-level information about the data stored in the image.
@@ -707,7 +710,7 @@ bool QImageData::checkForAlphaPixels() const
packed with the less significant bit (LSB) first.
\value Format_Indexed8 The image is stored using 8-bit indexes
- into a colormap.
+ into a colormap.
\value Format_RGB32 The image is stored using a 32-bit RGB format (0xffRRGGBB).
@@ -1580,12 +1583,12 @@ QRect QImage::rect() const
/*!
Returns the depth of the image.
- The image depth is the number of bits used to encode a single
+ The image depth is the number of bits used to store a single
pixel, also called bits per pixel (bpp).
The supported depths are 1, 8, 16, 24 and 32.
- \sa convertToFormat(), {QImage#Image Formats}{Image Formats},
+ \sa bitPlaneCount(), convertToFormat(), {QImage#Image Formats}{Image Formats},
{QImage#Image Information}{Image Information}
*/
@@ -2985,19 +2988,19 @@ static void convert_Indexed8_to_X32(QImageData *dest, const QImageData *src, Qt:
colorTable.resize(256);
for (int i=0; i<256; ++i)
colorTable[i] = qRgb(i, i, i);
-
}
int w = src->width;
const uchar *src_data = src->data;
uchar *dest_data = dest->data;
+ int tableSize = colorTable.size() - 1;
for (int y = 0; y < src->height; y++) {
uint *p = (uint *)dest_data;
const uchar *b = src_data;
uint *end = p + w;
while (p < end)
- *p++ = colorTable.at(*b++);
+ *p++ = colorTable.at(qMin<int>(tableSize, *b++));
src_data += src->bytes_per_line;
dest_data += dest->bytes_per_line;
@@ -5701,9 +5704,13 @@ void QImage::setAlphaChannel(const QImage &alphaChannel)
return;
}
- detach();
+ if (d->format == QImage::Format_ARGB32_Premultiplied)
+ detach();
+ else
+ *this = convertToFormat(QImage::Format_ARGB32_Premultiplied);
- *this = convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ if (isNull())
+ return;
// Slight optimization since alphachannels are returned as 8-bit grays.
if (alphaChannel.d->depth == 8 && alphaChannel.isGrayscale()) {
@@ -5848,6 +5855,48 @@ bool QImage::hasAlphaChannel() const
}
+/*!
+ \since 4.7
+ Returns the number of bit planes in the image.
+
+ The number of bit planes is the number of bits of color and
+ transparency information for each pixel. This is different from
+ (i.e. smaller than) the depth when the image format contains
+ unused bits.
+
+ \sa depth(), format(), {QImage#Image Formats}{Image Formats}
+*/
+int QImage::bitPlaneCount() const
+{
+ if (!d)
+ return 0;
+ int bpc = 0;
+ switch (d->format) {
+ case QImage::Format_Invalid:
+ break;
+ case QImage::Format_RGB32:
+ bpc = 24;
+ break;
+ case QImage::Format_RGB666:
+ bpc = 18;
+ break;
+ case QImage::Format_RGB555:
+ bpc = 15;
+ break;
+ case QImage::Format_ARGB8555_Premultiplied:
+ bpc = 23;
+ break;
+ case QImage::Format_RGB444:
+ bpc = 12;
+ break;
+ default:
+ bpc = depthForFormat(d->format);
+ break;
+ }
+ return bpc;
+}
+
+
#ifdef QT3_SUPPORT
#if defined(Q_WS_X11)
QT_BEGIN_INCLUDE_NAMESPACE
diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h
index dd13782..896061f 100644
--- a/src/gui/image/qimage.h
+++ b/src/gui/image/qimage.h
@@ -169,6 +169,7 @@ public:
QT_DEPRECATED int numColors() const;
#endif
int colorCount() const;
+ int bitPlaneCount() const;
QRgb color(int i) const;
void setColor(int i, QRgb c);
diff --git a/src/gui/image/qimagepixmapcleanuphooks.cpp b/src/gui/image/qimagepixmapcleanuphooks.cpp
index 517fcb0..521e348 100644
--- a/src/gui/image/qimagepixmapcleanuphooks.cpp
+++ b/src/gui/image/qimagepixmapcleanuphooks.cpp
@@ -96,6 +96,11 @@ void QImagePixmapCleanupHooks::removeImageHook(_qt_image_cleanup_hook_64 hook)
void QImagePixmapCleanupHooks::executePixmapDataModificationHooks(QPixmapData* pmd)
{
QImagePixmapCleanupHooks *h = qt_image_and_pixmap_cleanup_hooks();
+ // the global destructor for the pixmap and image hooks might have
+ // been called already if the app is "leaking" global
+ // pixmaps/images
+ if (!h)
+ return;
for (int i = 0; i < h->pixmapModificationHooks.count(); ++i)
h->pixmapModificationHooks[i](pmd);
@@ -106,6 +111,11 @@ void QImagePixmapCleanupHooks::executePixmapDataModificationHooks(QPixmapData* p
void QImagePixmapCleanupHooks::executePixmapDataDestructionHooks(QPixmapData* pmd)
{
QImagePixmapCleanupHooks *h = qt_image_and_pixmap_cleanup_hooks();
+ // the global destructor for the pixmap and image hooks might have
+ // been called already if the app is "leaking" global
+ // pixmaps/images
+ if (!h)
+ return;
for (int i = 0; i < h->pixmapDestructionHooks.count(); ++i)
h->pixmapDestructionHooks[i](pmd);
diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp
index 9320cfc..27f9627 100644
--- a/src/gui/image/qimagereader.cpp
+++ b/src/gui/image/qimagereader.cpp
@@ -503,7 +503,7 @@ QImageReaderPrivate::~QImageReaderPrivate()
bool QImageReaderPrivate::initHandler()
{
// check some preconditions
- if (!device || (!deleteDevice && !device->isOpen())) {
+ if (!device || (!deleteDevice && !device->isOpen() && !device->open(QIODevice::ReadOnly))) {
imageReaderError = QImageReader::DeviceError;
errorString = QLatin1String(QT_TRANSLATE_NOOP(QImageReader, "Invalid device"));
return false;
diff --git a/src/gui/image/qimagewriter.cpp b/src/gui/image/qimagewriter.cpp
index a5f7b31..503a1b2 100644
--- a/src/gui/image/qimagewriter.cpp
+++ b/src/gui/image/qimagewriter.cpp
@@ -197,6 +197,7 @@ static QImageIOHandler *createWriteHandlerHelper(QIODevice *device,
for (int i = 0; i < keys.size(); ++i) {
QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(l->instance(keys.at(i)));
if (plugin && (plugin->capabilities(device, testFormat) & QImageIOPlugin::CanWrite)) {
+ delete handler;
handler = plugin->create(device, testFormat);
break;
}
diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp
index 3220a67..45b3ed0 100644
--- a/src/gui/image/qpicture.cpp
+++ b/src/gui/image/qpicture.cpp
@@ -651,7 +651,12 @@ bool QPicture::exec(QPainter *painter, QDataStream &s, int nrecords)
s >> dbl;
QFont fnt(font, painter->device());
- qreal scale = painter->device()->logicalDpiY() / (dbl*qt_defaultDpiY());
+ // Fonts that specify a pixel size should not be scaled - QPicture already
+ // have a matrix set to compensate for the DPI differences between the
+ // default Qt DPI and the actual target device DPI, and we have to take that
+ // into consideration in the case where the font has a pixel size set.
+
+ qreal scale = fnt.pointSize() == -1 ? 1 : painter->device()->logicalDpiY() / (dbl*qt_defaultDpiY());
painter->save();
painter->scale(1/scale, 1/scale);
@@ -660,7 +665,7 @@ bool QPicture::exec(QPainter *painter, QDataStream &s, int nrecords)
int flags = Qt::TextSingleLine | Qt::TextDontClip | Qt::TextForceLeftToRight;
- QSizeF size(scale, scale);
+ QSizeF size(1, 1);
if (justificationWidth > 0) {
size.setWidth(justificationWidth*scale);
flags |= Qt::TextJustificationForced;
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index ae62f06..474cd2e 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -831,21 +831,14 @@ bool QPixmap::load(const QString &fileName, const char *format, Qt::ImageConvers
if (QPixmapCache::find(key, *this))
return true;
- bool ok;
-
- if (data) {
- ok = data->fromFile(fileName, format, flags);
- } else {
- QScopedPointer<QPixmapData> tmp(QPixmapData::create(0, 0, QPixmapData::PixmapType));
- ok = tmp->fromFile(fileName, format, flags);
- if (ok)
- data = tmp.take();
- }
-
- if (ok)
+ QScopedPointer<QPixmapData> tmp(QPixmapData::create(0, 0, data ? data->type : QPixmapData::PixmapType));
+ if (tmp->fromFile(fileName, format, flags)) {
+ data = tmp.take();
QPixmapCache::insert(key, *this);
+ return true;
+ }
- return ok;
+ return false;
}
/*!
@@ -2046,12 +2039,16 @@ QPixmap QPixmap::fromImage(const QImage &image, Qt::ImageConversionFlags flags)
over the one you grab, you get pixels from the overlying window,
too. The mouse cursor is generally not grabbed.
- Note on X11that if the given \a window doesn't have the same depth
+ Note on X11 that if the given \a window doesn't have the same depth
as the root window, and another window partially or entirely
obscures the one you grab, you will \e not get pixels from the
overlying window. The contents of the obscured areas in the
pixmap will be undefined and uninitialized.
+ On Windows Vista and above grabbing a layered window, which is
+ created by setting the Qt::WA_TranslucentBackground attribute, will
+ not work. Instead grabbing the desktop widget should work.
+
\warning In general, grabbing an area outside the screen is not
safe. This depends on the underlying window system.
diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp
index 0b1c18d..b183d0d 100644
--- a/src/gui/image/qpixmap_raster.cpp
+++ b/src/gui/image/qpixmap_raster.cpp
@@ -182,6 +182,7 @@ void QRasterPixmapData::fromImage(const QImage &sourceImage,
QImage::Format opaqueFormat = QNativeImage::systemFormat();
QImage::Format alphaFormat = QImage::Format_ARGB32_Premultiplied;
+#ifndef QT_HAVE_NEON
switch (opaqueFormat) {
case QImage::Format_RGB16:
alphaFormat = QImage::Format_ARGB8565_Premultiplied;
@@ -189,6 +190,7 @@ void QRasterPixmapData::fromImage(const QImage &sourceImage,
default: // We don't care about the others...
break;
}
+#endif
if (!sourceImage.hasAlphaChannel()
|| ((flags & Qt::NoOpaqueDetection) == 0
@@ -238,6 +240,7 @@ void QRasterPixmapData::fill(const QColor &color)
if (alpha != 255) {
if (!image.hasAlphaChannel()) {
QImage::Format toFormat;
+#ifndef QT_HAVE_NEON
if (image.format() == QImage::Format_RGB16)
toFormat = QImage::Format_ARGB8565_Premultiplied;
else if (image.format() == QImage::Format_RGB666)
@@ -247,6 +250,7 @@ void QRasterPixmapData::fill(const QColor &color)
else if (image.format() == QImage::Format_RGB444)
toFormat = QImage::Format_ARGB4444_Premultiplied;
else
+#endif
toFormat = QImage::Format_ARGB32_Premultiplied;
image = QImage(image.width(), image.height(), toFormat);
}
diff --git a/src/gui/image/qpixmap_s60.cpp b/src/gui/image/qpixmap_s60.cpp
index 4f3a719..a13c8c8 100644
--- a/src/gui/image/qpixmap_s60.cpp
+++ b/src/gui/image/qpixmap_s60.cpp
@@ -337,7 +337,7 @@ QPixmap QPixmap::fromSymbianCFbsBitmap(CFbsBitmap *bitmap)
if (!bitmap)
return QPixmap();
- QScopedPointer<QS60PixmapData> data(new QS60PixmapData(QPixmapData::PixmapType));
+ QScopedPointer<QPixmapData> data(QPixmapData::create(0,0, QPixmapData::PixmapType));
data->fromNativeType(reinterpret_cast<void*>(bitmap), QPixmapData::FbsBitmap);
QPixmap pixmap(data.take());
return pixmap;
@@ -735,7 +735,7 @@ QPixmap QPixmap::fromSymbianRSgImage(RSgImage *sgImage)
if (!sgImage)
return QPixmap();
- QScopedPointer<QS60PixmapData> data(new QS60PixmapData(QPixmapData::PixmapType));
+ QScopedPointer<QPixmapData> data(QPixmapData::create(0,0, QPixmapData::PixmapType));
data->fromNativeType(reinterpret_cast<void*>(sgImage), QPixmapData::SgImage);
QPixmap pixmap(data.take());
return pixmap;
diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp
index b976376..5a882af 100644
--- a/src/gui/image/qpixmap_x11.cpp
+++ b/src/gui/image/qpixmap_x11.cpp
@@ -314,8 +314,8 @@ static int qt_pixmap_serial = 0;
int Q_GUI_EXPORT qt_x11_preferred_pixmap_depth = 0;
QX11PixmapData::QX11PixmapData(PixelType type)
- : QPixmapData(type, X11Class), hd(0),
- flags(Uninitialized), x11_mask(0), picture(0), mask_picture(0), hd2(0), gl_surface(0),
+ : QPixmapData(type, X11Class), gl_surface(0), hd(0),
+ flags(Uninitialized), x11_mask(0), picture(0), mask_picture(0), hd2(0),
share_mode(QPixmap::ImplicitlyShared), pengine(0)
{
}
diff --git a/src/gui/image/qpixmap_x11_p.h b/src/gui/image/qpixmap_x11_p.h
index 0c0a9bd..7575838 100644
--- a/src/gui/image/qpixmap_x11_p.h
+++ b/src/gui/image/qpixmap_x11_p.h
@@ -94,6 +94,11 @@ public:
static Qt::HANDLE createBitmapFromImage(const QImage &image);
+ void* gl_surface;
+#ifndef QT_NO_XRENDER
+ void convertToARGB32(bool preserveContents = true);
+#endif
+
protected:
int metric(QPaintDevice::PaintDeviceMetric metric) const;
@@ -105,6 +110,7 @@ private:
friend class QRasterWindowSurface;
friend class QGLContextPrivate; // Needs to access xinfo, gl_surface & flags
friend class QEglContext; // Needs gl_surface
+ friend class QGLContext; // Needs gl_surface
friend class QX11GLPixmapData; // Needs gl_surface
friend bool qt_createEGLSurfaceForPixmap(QPixmapData*, bool); // Needs gl_surface
@@ -130,10 +136,6 @@ private:
Qt::HANDLE picture;
Qt::HANDLE mask_picture;
Qt::HANDLE hd2; // sorted in the default display depth
- Qt::HANDLE gl_surface;
-#ifndef QT_NO_XRENDER
- void convertToARGB32(bool preserveContents = true);
-#endif
QPixmap::ShareMode share_mode;
QX11PaintEngine *pengine;
diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp
index 2792e45..5355ad3 100644
--- a/src/gui/image/qpixmapfilter.cpp
+++ b/src/gui/image/qpixmapfilter.cpp
@@ -726,7 +726,7 @@ void expblur(QImage &img, qreal radius, bool improvedQuality = false, int transp
int img_height = img.height();
for (int row = 0; row < img_height; ++row) {
- for (int i = 0; i <= improvedQuality; ++i)
+ for (int i = 0; i <= int(improvedQuality); ++i)
qt_blurrow<aprec, zprec, alphaOnly>(img, row, alpha);
}
@@ -759,7 +759,7 @@ void expblur(QImage &img, qreal radius, bool improvedQuality = false, int transp
img_height = temp.height();
for (int row = 0; row < img_height; ++row) {
- for (int i = 0; i <= improvedQuality; ++i)
+ for (int i = 0; i <= int(improvedQuality); ++i)
qt_blurrow<aprec, zprec, alphaOnly>(temp, row, alpha);
}
@@ -777,6 +777,9 @@ void expblur(QImage &img, qreal radius, bool improvedQuality = false, int transp
Q_GUI_EXPORT QImage qt_halfScaled(const QImage &source)
{
+ if (source.width() < 2 || source.height() < 2)
+ return QImage();
+
QImage srcImage = source;
if (source.format() == QImage::Format_Indexed8) {
@@ -869,7 +872,7 @@ Q_GUI_EXPORT void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, boo
}
qreal scale = 1;
- if (radius >= 4) {
+ if (radius >= 4 && blurImage.width() >= 2 && blurImage.height() >= 2) {
blurImage = qt_halfScaled(blurImage);
scale = 2;
radius *= qreal(0.5);
diff --git a/src/gui/inputmethod/inputmethod.pri b/src/gui/inputmethod/inputmethod.pri
index 6d9f748..02e3e57 100644
--- a/src/gui/inputmethod/inputmethod.pri
+++ b/src/gui/inputmethod/inputmethod.pri
@@ -26,6 +26,6 @@ mac:!embedded {
symbian:contains(QT_CONFIG, s60) {
HEADERS += inputmethod/qcoefepinputcontext_p.h
SOURCES += inputmethod/qcoefepinputcontext_s60.cpp
- LIBS += -lfepbase
+ LIBS += -lfepbase -lakninputlanguage
}
diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp
index 1ac8ace..cc60246 100644
--- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp
+++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp
@@ -551,6 +551,21 @@ void QCoeFepInputContext::StartFepInlineEditL(const TDesC& aInitialInlineText,
m_formatRetriever = &aInlineTextFormatRetriever;
m_pointerHandler = &aPointerEventHandlerDuringInlineEdit;
+ // With T9 aInitialInlineText is typically empty when StartFepInlineEditL is called,
+ // but FEP requires that selected text is always removed at StartFepInlineEditL.
+ // Let's remove the selected text if aInitialInlineText is empty and there is selected text
+ if (m_preeditString.isEmpty()) {
+ int anchor = w->inputMethodQuery(Qt::ImAnchorPosition).toInt();
+ int replacementLength = qAbs(m_cursorPos-anchor);
+ if (replacementLength > 0) {
+ int replacementStart = m_cursorPos < anchor ? 0 : -replacementLength;
+ QList<QInputMethodEvent::Attribute> clearSelectionAttributes;
+ QInputMethodEvent clearSelectionEvent(QLatin1String(""), clearSelectionAttributes);
+ clearSelectionEvent.setCommitString(QLatin1String(""), replacementStart, replacementLength);
+ sendEvent(clearSelectionEvent);
+ }
+ }
+
applyFormat(&attributes);
attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor,
diff --git a/src/gui/inputmethod/qinputcontextfactory.cpp b/src/gui/inputmethod/qinputcontextfactory.cpp
index 501a36e..d47e343 100644
--- a/src/gui/inputmethod/qinputcontextfactory.cpp
+++ b/src/gui/inputmethod/qinputcontextfactory.cpp
@@ -73,6 +73,7 @@
#endif
#ifdef Q_WS_S60
#include "qcoefepinputcontext_p.h"
+#include "akninputlanguageinfo.h"
#endif
#include "private/qfactoryloader_p.h"
@@ -198,6 +199,42 @@ QStringList QInputContextFactory::keys()
return result;
}
+#if defined(Q_WS_S60)
+/*!
+ \internal
+
+ This function contains pure Symbian exception handling code for
+ getting S60 language list.
+ Returned object ownership is transfered to caller.
+*/
+static CAknInputLanguageList* s60LangListL()
+{
+ CAknInputLanguageInfo *langInfo = AknInputLanguageInfoFactory::CreateInputLanguageInfoL();
+ CleanupStack::PushL(langInfo);
+ // In rare phone there is more than 7 languages installed -> use 7 as an array granularity
+ CAknInputLanguageList *langList = new (ELeave) CAknInputLanguageList(7);
+ CleanupStack::PushL(langList);
+ langInfo->AppendAvailableLanguagesL(langList);
+ CleanupStack::Pop(langList);
+ CleanupStack::PopAndDestroy(langInfo);
+ return langList;
+}
+
+/*!
+ \internal
+
+ This function utility function return S60 language list.
+ Returned object ownership is transfered to caller.
+*/
+static CAknInputLanguageList* s60LangList()
+{
+ CAknInputLanguageList *langList = NULL;
+ TRAP_IGNORE(langList = s60LangListL());
+ q_check_ptr(langList);
+ return langList;
+}
+#endif
+
/*!
Returns the languages supported by the QInputContext object
specified by \a key.
@@ -229,7 +266,15 @@ QStringList QInputContextFactory::languages( const QString &key )
#endif
#if defined(Q_WS_S60)
if (key == QLatin1String("coefep"))
- return QStringList(QString());
+ {
+ CAknInputLanguageList *langList = s60LangList();
+ int count = langList->Count();
+ for (int i = 0; i < count; ++i)
+ {
+ result.append(QString(qt_symbianLocaleName(langList->At(i)->LanguageCode())));
+ }
+ delete langList;
+ }
#endif
#if defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS)
Q_UNUSED(key);
diff --git a/src/gui/inputmethod/qximinputcontext_x11.cpp b/src/gui/inputmethod/qximinputcontext_x11.cpp
index 68ade38..d048b36 100644
--- a/src/gui/inputmethod/qximinputcontext_x11.cpp
+++ b/src/gui/inputmethod/qximinputcontext_x11.cpp
@@ -344,7 +344,13 @@ static XFontSet getFontSet(const QFont &f)
return (fontsetCache[i] == (XFontSet)-1) ? 0 : fontsetCache[i];
}
-
+extern bool qt_use_rtl_extensions; // from qapplication_x11.cpp
+#ifndef QT_NO_XKB
+extern void q_getLocaleAndDirection(QLocale *locale,
+ Qt::LayoutDirection *direction,
+ const QByteArray &layoutName,
+ const QByteArray &variantName);
+#endif
QXIMInputContext::QXIMInputContext()
{
@@ -375,6 +381,52 @@ QXIMInputContext::QXIMInputContext()
else
QXIMInputContext::create_xim();
#endif // USE_X11R6_XIM
+
+#ifndef QT_NO_XKB
+ if (X11->use_xkb) {
+ QByteArray layoutName;
+ QByteArray variantName;
+
+ Atom type = XNone;
+ int format = 0;
+ ulong nitems = 0;
+ ulong bytesAfter = 0;
+ uchar *data = 0;
+ if (XGetWindowProperty(X11->display, RootWindow(X11->display, 0), ATOM(_XKB_RULES_NAMES), 0, 1024,
+ false, XA_STRING, &type, &format, &nitems, &bytesAfter, &data) == Success
+ && type == XA_STRING && format == 8 && nitems > 2) {
+
+ char *names[5] = { 0, 0, 0, 0, 0 };
+ char *p = reinterpret_cast<char *>(data), *end = p + nitems;
+ int i = 0;
+ do {
+ names[i++] = p;
+ p += qstrlen(p) + 1;
+ } while (p < end);
+
+ QList<QByteArray> layoutNames = QByteArray::fromRawData(names[2], qstrlen(names[2])).split(',');
+ QList<QByteArray> variantNames = QByteArray::fromRawData(names[3], qstrlen(names[3])).split(',');
+ for (int i = 0; i < qMin(layoutNames.count(), variantNames.count()); ++i ) {
+ QLocale keyboardInputLocale;
+ Qt::LayoutDirection keyboardInputDirection;
+ QByteArray variantName = variantNames.at(i);
+ const int dashPos = variantName.indexOf("-");
+ if (dashPos >= 0)
+ variantName.truncate(dashPos);
+ q_getLocaleAndDirection(&keyboardInputLocale,
+ &keyboardInputDirection,
+ layoutNames.at(i),
+ variantName);
+ if (keyboardInputDirection == Qt::RightToLeft)
+ qt_use_rtl_extensions = true;
+ }
+ }
+
+ if (data)
+ XFree(data);
+ }
+#endif // QT_NO_XKB
+
}
diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp
index bc6db90..97fd6e1 100644
--- a/src/gui/itemviews/qabstractitemview.cpp
+++ b/src/gui/itemviews/qabstractitemview.cpp
@@ -104,8 +104,10 @@ QAbstractItemViewPrivate::QAbstractItemViewPrivate()
horizontalScrollMode(QAbstractItemView::ScrollPerItem),
currentIndexSet(false),
wrapItemText(false),
- delayedPendingLayout(false)
+ delayedPendingLayout(true),
+ moveCursorUpdatedView(false)
{
+ keyboardInputTime.invalidate();
}
QAbstractItemViewPrivate::~QAbstractItemViewPrivate()
@@ -131,8 +133,6 @@ void QAbstractItemViewPrivate::init()
viewport->setBackgroundRole(QPalette::Base);
- doDelayedItemsLayout();
-
q->setAttribute(Qt::WA_InputMethodEnabled);
#ifdef QT_SOFTKEYS_ENABLED
@@ -2090,7 +2090,7 @@ void QAbstractItemView::focusInEvent(QFocusEvent *event)
bool autoScroll = d->autoScroll;
d->autoScroll = false;
QModelIndex index = moveCursor(MoveNext, Qt::NoModifier); // first visible index
- if (index.isValid() && d->isIndexEnabled(index))
+ if (index.isValid() && d->isIndexEnabled(index) && event->reason() != Qt::MouseFocusReason)
selectionModel()->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
d->autoScroll = autoScroll;
}
@@ -2210,6 +2210,7 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event)
#endif
QPersistentModelIndex newCurrent;
+ d->moveCursorUpdatedView = false;
switch (event->key()) {
case Qt::Key_Down:
newCurrent = moveCursor(MoveDown, event->modifiers());
@@ -2266,6 +2267,7 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event)
QRect rect(d->pressedPosition - d->offset(), QSize(1, 1));
setSelection(rect, command);
}
+ event->accept();
return;
}
}
@@ -2297,6 +2299,8 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event)
case Qt::Key_Escape:
case Qt::Key_Shift:
case Qt::Key_Control:
+ case Qt::Key_Delete:
+ case Qt::Key_Backspace:
event->ignore();
break;
case Qt::Key_Space:
@@ -2361,6 +2365,8 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event)
}
break; }
}
+ if (d->moveCursorUpdatedView)
+ event->accept();
}
/*!
@@ -2568,6 +2574,7 @@ void QAbstractItemView::updateEditorGeometries()
QStyleOptionViewItemV4 option = d->viewOptionsV4();
QList<QEditorInfo>::iterator it = d->editors.begin();
QWidgetList editorsToRelease;
+ QWidgetList editorsToHide;
while (it != d->editors.end()) {
QModelIndex index = it->index;
QWidget *editor = it->editor;
@@ -2579,7 +2586,7 @@ void QAbstractItemView::updateEditorGeometries()
if (delegate)
delegate->updateEditorGeometry(editor, option, index);
} else {
- editor->hide();
+ editorsToHide << editor;
}
++it;
} else {
@@ -2588,8 +2595,11 @@ void QAbstractItemView::updateEditorGeometries()
}
}
- //we release the editor outside of the loop because it might change the focus and try
+ //we hide and release the editor outside of the loop because it might change the focus and try
//to change the d->editors list.
+ for (int i = 0; i < editorsToHide.count(); ++i) {
+ editorsToHide.at(i)->hide();
+ }
for (int i = 0; i < editorsToRelease.count(); ++i) {
d->releaseEditor(editorsToRelease.at(i));
}
@@ -2833,16 +2843,16 @@ void QAbstractItemView::keyboardSearch(const QString &search)
QModelIndex start = currentIndex().isValid() ? currentIndex()
: d->model->index(0, 0, d->root);
- QTime now(QTime::currentTime());
bool skipRow = false;
- if (search.isEmpty()
- || (d->keyboardInputTime.msecsTo(now) > QApplication::keyboardInputInterval())) {
+ bool keyboardTimeWasValid = d->keyboardInputTime.isValid();
+ qint64 keyboardInputTimeElapsed = d->keyboardInputTime.restart();
+ if (search.isEmpty() || !keyboardTimeWasValid
+ || keyboardInputTimeElapsed > QApplication::keyboardInputInterval()) {
d->keyboardInput = search;
skipRow = currentIndex().isValid(); //if it is not valid we should really start at QModelIndex(0,0)
} else {
d->keyboardInput += search;
}
- d->keyboardInputTime = now;
// special case for searches with same key like 'aaaaa'
bool sameKey = false;
@@ -3046,6 +3056,7 @@ void QAbstractItemView::setIndexWidget(const QModelIndex &index, QWidget *widget
if (!d->isIndexValid(index))
return;
if (QWidget *oldWidget = indexWidget(index)) {
+ d->persistent.remove(oldWidget);
d->removeEditor(oldWidget);
oldWidget->deleteLater();
}
diff --git a/src/gui/itemviews/qabstractitemview_p.h b/src/gui/itemviews/qabstractitemview_p.h
index 82fd1a6..fce74f3 100644
--- a/src/gui/itemviews/qabstractitemview_p.h
+++ b/src/gui/itemviews/qabstractitemview_p.h
@@ -56,7 +56,6 @@
#include "private/qabstractscrollarea_p.h"
#include "private/qabstractitemmodel_p.h"
#include "QtGui/qapplication.h"
-#include "QtCore/qdatetime.h"
#include "QtGui/qevent.h"
#include "QtGui/qmime.h"
#include "QtGui/qpainter.h"
@@ -65,6 +64,7 @@
#include "QtCore/qdebug.h"
#include "QtGui/qpainter.h"
#include "QtCore/qbasictimer.h"
+#include "QtCore/qelapsedtimer.h"
#ifndef QT_NO_ITEMVIEWS
@@ -390,7 +390,7 @@ public:
#endif
QString keyboardInput;
- QTime keyboardInputTime;
+ QElapsedTimer keyboardInputTime;
bool autoScroll;
QBasicTimer autoScrollTimer;
@@ -419,6 +419,7 @@ public:
bool wrapItemText;
mutable bool delayedPendingLayout;
+ bool moveCursorUpdatedView;
private:
mutable QBasicTimer delayedLayout;
diff --git a/src/gui/itemviews/qdirmodel.cpp b/src/gui/itemviews/qdirmodel.cpp
index 378a238..48599bc 100644
--- a/src/gui/itemviews/qdirmodel.cpp
+++ b/src/gui/itemviews/qdirmodel.cpp
@@ -1182,12 +1182,18 @@ QFileInfo QDirModel::fileInfo(const QModelIndex &index) const
void QDirModelPrivate::init()
{
+ Q_Q(QDirModel);
filters = QDir::AllEntries | QDir::NoDotAndDotDot;
sort = QDir::Name;
nameFilters << QLatin1String("*");
root.parent = 0;
root.info = QFileInfo();
clear(&root);
+ QHash<int, QByteArray> roles = q->roleNames();
+ roles.insertMulti(QDirModel::FileIconRole, "fileIcon"); // == Qt::decoration
+ roles.insert(QDirModel::FilePathRole, "filePath");
+ roles.insert(QDirModel::FileNameRole, "fileName");
+ q->setRoleNames(roles);
}
QDirModelPrivate::QDirNode *QDirModelPrivate::node(int row, QDirNode *parent) const
diff --git a/src/gui/itemviews/qfileiconprovider.cpp b/src/gui/itemviews/qfileiconprovider.cpp
index f321ab3..5dbd1f0 100644
--- a/src/gui/itemviews/qfileiconprovider.cpp
+++ b/src/gui/itemviews/qfileiconprovider.cpp
@@ -254,7 +254,9 @@ QIcon QFileIconProviderPrivate::getWinIcon(const QFileInfo &fileInfo) const
val = SHGetFileInfo((const wchar_t *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info,
sizeof(SHFILEINFO), SHGFI_SMALLICON|SHGFI_SYSICONINDEX);
#endif
- if (val) {
+
+ // Even if GetFileInfo returns a valid result, hIcon can be empty in some cases
+ if (val && info.hIcon) {
if (fileInfo.isDir() && !fileInfo.isRoot()) {
//using the unique icon index provided by windows save us from duplicate keys
key = QString::fromLatin1("qt_dir_%1").arg(info.iIcon);
@@ -293,7 +295,7 @@ QIcon QFileIconProviderPrivate::getWinIcon(const QFileInfo &fileInfo) const
val = SHGetFileInfo((const wchar_t *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info,
sizeof(SHFILEINFO), SHGFI_LARGEICON|SHGFI_SYSICONINDEX);
#endif
- if (val) {
+ if (val && info.hIcon) {
if (fileInfo.isDir() && !fileInfo.isRoot()) {
//using the unique icon index provided by windows save us from duplicate keys
key = QString::fromLatin1("qt_dir_%1").arg(info.iIcon);
diff --git a/src/gui/itemviews/qheaderview.cpp b/src/gui/itemviews/qheaderview.cpp
index 5128b64..cd9ee15 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;
}
@@ -2037,7 +2034,7 @@ bool QHeaderView::event(QEvent *e)
updateSection(d->hover);
}
break; }
- case QEvent::Timer: { // ### reimplement timerEvent() instead ?
+ case QEvent::Timer: {
QTimerEvent *te = static_cast<QTimerEvent*>(e);
if (te->timerId() == d->delayedResize.timerId()) {
d->delayedResize.stop();
@@ -2223,16 +2220,24 @@ void QHeaderView::mouseMoveEvent(QMouseEvent *e)
case QHeaderViewPrivate::MoveSection: {
if (qAbs(pos - d->firstPos) >= QApplication::startDragDistance()
|| !d->sectionIndicator->isHidden()) {
- int indicatorCenter = (d->orientation == Qt::Horizontal
- ? d->sectionIndicator->width()
- : d->sectionIndicator->height()) / 2;
- int centerOffset = indicatorCenter - d->sectionIndicatorOffset;
- // This will drop the moved section to the position under the center of the indicator.
- // If centerOffset is 0, the section will be moved to the position of the mouse cursor.
- int visual = visualIndexAt(pos + centerOffset);
+ int visual = visualIndexAt(pos);
if (visual == -1)
return;
- d->target = d->logicalIndex(visual);
+ int posThreshold = d->headerSectionPosition(visual) + d->headerSectionSize(visual) / 2;
+ int moving = visualIndex(d->section);
+ if (visual < moving) {
+ if (pos < posThreshold)
+ d->target = d->logicalIndex(visual);
+ else
+ d->target = d->logicalIndex(visual + 1);
+ } else if (visual > moving) {
+ if (pos > posThreshold)
+ d->target = d->logicalIndex(visual);
+ else
+ d->target = d->logicalIndex(visual - 1);
+ } else {
+ d->target = d->section;
+ }
d->updateSectionIndicator(d->section, pos);
}
return;
@@ -2610,7 +2615,7 @@ void QHeaderView::updateGeometries()
Q_D(QHeaderView);
d->layoutChildren();
if (d->hasAutoResizeSections())
- resizeSections();
+ d->doDelayedResizeSections();
}
/*!
diff --git a/src/gui/itemviews/qitemdelegate.cpp b/src/gui/itemviews/qitemdelegate.cpp
index 9069ce4..d5f6fd2 100644
--- a/src/gui/itemviews/qitemdelegate.cpp
+++ b/src/gui/itemviews/qitemdelegate.cpp
@@ -69,6 +69,7 @@
#include <qdebug.h>
#include <qlocale.h>
#include <qdialog.h>
+#include <qmath.h>
#include <limits.h>
@@ -1023,7 +1024,7 @@ QPixmap QItemDelegate::decoration(const QStyleOptionViewItem &option, const QVar
// hacky but faster version of "QString::sprintf("%d-%d", i, enabled)"
static QString qPixmapSerial(quint64 i, bool enabled)
{
- ushort arr[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-', '0' + enabled };
+ ushort arr[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-', ushort('0' + enabled) };
ushort *ptr = &arr[16];
while (i > 0) {
@@ -1148,7 +1149,8 @@ QRect QItemDelegate::textRectangle(QPainter * /*painter*/, const QRect &rect,
d->textLayout.setTextOption(d->textOption);
d->textLayout.setFont(font);
d->textLayout.setText(QItemDelegatePrivate::replaceNewLine(text));
- const QSize size = d->doTextLayout(rect.width()).toSize();
+ QSizeF fpSize = d->doTextLayout(rect.width());
+ const QSize size = QSize(qCeil(fpSize.width()), qCeil(fpSize.height()));
// ###: textRectangle should take style option as argument
const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
return QRect(0, 0, size.width() + 2 * textMargin, size.height());
@@ -1297,14 +1299,8 @@ bool QItemDelegate::editorEvent(QEvent *event,
return false;
}
- Qt::CheckState state;
- if ( flags & Qt::ItemIsTristate ) {
- state = static_cast<Qt::CheckState>( (value.toInt() + 1) % 3 );
- } else {
- state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
+ Qt::CheckState state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
? Qt::Unchecked : Qt::Checked);
- }
-
return model->setData(index, state, Qt::CheckStateRole);
}
diff --git a/src/gui/itemviews/qitemselectionmodel.cpp b/src/gui/itemviews/qitemselectionmodel.cpp
index cab002e..d6e68f6 100644
--- a/src/gui/itemviews/qitemselectionmodel.cpp
+++ b/src/gui/itemviews/qitemselectionmodel.cpp
@@ -527,6 +527,27 @@ void QItemSelection::split(const QItemSelectionRange &range,
}
}
+
+void QItemSelectionModelPrivate::initModel(QAbstractItemModel *model)
+{
+ this->model = model;
+ if (model) {
+ Q_Q(QItemSelectionModel);
+ QObject::connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
+ q, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)));
+ QObject::connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
+ q, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int)));
+ QObject::connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
+ q, SLOT(_q_rowsAboutToBeInserted(QModelIndex,int,int)));
+ QObject::connect(model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
+ q, SLOT(_q_columnsAboutToBeInserted(QModelIndex,int,int)));
+ QObject::connect(model, SIGNAL(layoutAboutToBeChanged()),
+ q, SLOT(_q_layoutAboutToBeChanged()));
+ QObject::connect(model, SIGNAL(layoutChanged()),
+ q, SLOT(_q_layoutChanged()));
+ }
+}
+
/*!
\internal
@@ -793,6 +814,10 @@ static QItemSelection mergeIndexes(const QList<QPersistentModelIndex> &indexes)
while (++i < colSpans.count()) {
QModelIndex nextTl = colSpans.at(i).topLeft();
QModelIndex nextBr = colSpans.at(i).bottomRight();
+
+ if (nextTl.parent() != tl.parent())
+ break; // we can't merge selection ranges from different parents
+
if ((nextTl.column() == prevTl.column()) && (nextBr.column() == br.column())
&& (nextTl.row() == prevTl.row() + 1) && (nextBr.row() == br.row() + 1)) {
br = nextBr;
@@ -890,21 +915,7 @@ void QItemSelectionModelPrivate::_q_layoutChanged()
QItemSelectionModel::QItemSelectionModel(QAbstractItemModel *model)
: QObject(*new QItemSelectionModelPrivate, model)
{
- d_func()->model = model;
- if (model) {
- connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)));
- connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int)));
- connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(_q_rowsAboutToBeInserted(QModelIndex,int,int)));
- connect(model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(_q_columnsAboutToBeInserted(QModelIndex,int,int)));
- connect(model, SIGNAL(layoutAboutToBeChanged()),
- this, SLOT(_q_layoutAboutToBeChanged()));
- connect(model, SIGNAL(layoutChanged()),
- this, SLOT(_q_layoutChanged()));
- }
+ d_func()->initModel(model);
}
/*!
@@ -913,21 +924,7 @@ QItemSelectionModel::QItemSelectionModel(QAbstractItemModel *model)
QItemSelectionModel::QItemSelectionModel(QAbstractItemModel *model, QObject *parent)
: QObject(*new QItemSelectionModelPrivate, parent)
{
- d_func()->model = model;
- if (model) {
- connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)));
- connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int)));
- connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(_q_rowsAboutToBeInserted(QModelIndex,int,int)));
- connect(model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(_q_columnsAboutToBeInserted(QModelIndex,int,int)));
- connect(model, SIGNAL(layoutAboutToBeChanged()),
- this, SLOT(_q_layoutAboutToBeChanged()));
- connect(model, SIGNAL(layoutChanged()),
- this, SLOT(_q_layoutChanged()));
- }
+ d_func()->initModel(model);
}
/*!
@@ -936,21 +933,7 @@ QItemSelectionModel::QItemSelectionModel(QAbstractItemModel *model, QObject *par
QItemSelectionModel::QItemSelectionModel(QItemSelectionModelPrivate &dd, QAbstractItemModel *model)
: QObject(dd, model)
{
- d_func()->model = model;
- if (model) {
- connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)));
- connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int)));
- connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(_q_rowsAboutToBeInserted(QModelIndex,int,int)));
- connect(model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(_q_columnsAboutToBeInserted(QModelIndex,int,int)));
- connect(model, SIGNAL(layoutAboutToBeChanged()),
- this, SLOT(_q_layoutAboutToBeChanged()));
- connect(model, SIGNAL(layoutChanged()),
- this, SLOT(_q_layoutChanged()));
- }
+ dd.initModel(model);
}
/*!
@@ -958,21 +941,6 @@ QItemSelectionModel::QItemSelectionModel(QItemSelectionModelPrivate &dd, QAbstra
*/
QItemSelectionModel::~QItemSelectionModel()
{
- Q_D(QItemSelectionModel);
- if (d->model) {
- disconnect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)));
- disconnect(d->model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int)));
- disconnect(d->model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(_q_rowsAboutToBeInserted(QModelIndex,int,int)));
- disconnect(d->model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(_q_columnsAboutToBeInserted(QModelIndex,int,int)));
- disconnect(d->model, SIGNAL(layoutAboutToBeChanged()),
- this, SLOT(_q_layoutAboutToBeChanged()));
- disconnect(d->model, SIGNAL(layoutChanged()),
- this, SLOT(_q_layoutChanged()));
- }
}
/*!
diff --git a/src/gui/itemviews/qitemselectionmodel_p.h b/src/gui/itemviews/qitemselectionmodel_p.h
index 30583b2..5afa90d 100644
--- a/src/gui/itemviews/qitemselectionmodel_p.h
+++ b/src/gui/itemviews/qitemselectionmodel_p.h
@@ -70,6 +70,8 @@ public:
QItemSelection expandSelection(const QItemSelection &selection,
QItemSelectionModel::SelectionFlags command) const;
+ void initModel(QAbstractItemModel *model);
+
void _q_rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
void _q_columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
void _q_rowsAboutToBeInserted(const QModelIndex &parent, int start, int end);
diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp
index b2def39..39ca75a 100644
--- a/src/gui/itemviews/qlistview.cpp
+++ b/src/gui/itemviews/qlistview.cpp
@@ -1387,6 +1387,9 @@ void QListView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFl
/*!
\reimp
+
+ Since 4.7, the returned region only contains rectangles intersecting
+ (or included in) the viewport.
*/
QRegion QListView::visualRegionForSelection(const QItemSelection &selection) const
{
@@ -1394,6 +1397,7 @@ QRegion QListView::visualRegionForSelection(const QItemSelection &selection) con
// ### NOTE: this is a potential bottleneck in non-static mode
int c = d->column;
QRegion selectionRegion;
+ const QRect &viewportRect = d->viewport->rect();
for (int i = 0; i < selection.count(); ++i) {
if (!selection.at(i).isValid())
continue;
@@ -1405,8 +1409,11 @@ QRegion QListView::visualRegionForSelection(const QItemSelection &selection) con
int t = selection.at(i).topLeft().row();
int b = selection.at(i).bottomRight().row();
if (d->viewMode == IconMode || d->isWrapping()) { // in non-static mode, we have to go through all selected items
- for (int r = t; r <= b; ++r)
- selectionRegion += QRegion(visualRect(d->model->index(r, c, parent)));
+ for (int r = t; r <= b; ++r) {
+ const QRect &rect = visualRect(d->model->index(r, c, parent));
+ if (viewportRect.intersects(rect))
+ selectionRegion += rect;
+ }
} else { // in static mode, we can optimize a bit
while (t <= b && d->isHidden(t)) ++t;
while (b >= t && d->isHidden(b)) --b;
@@ -1414,7 +1421,8 @@ QRegion QListView::visualRegionForSelection(const QItemSelection &selection) con
const QModelIndex bottom = d->model->index(b, c, parent);
QRect rect(visualRect(top).topLeft(),
visualRect(bottom).bottomRight());
- selectionRegion += QRegion(rect);
+ if (viewportRect.intersects(rect))
+ selectionRegion += rect;
}
}
diff --git a/src/gui/itemviews/qproxymodel.h b/src/gui/itemviews/qproxymodel.h
index 1a6b14b..f179a7a 100644
--- a/src/gui/itemviews/qproxymodel.h
+++ b/src/gui/itemviews/qproxymodel.h
@@ -67,19 +67,19 @@ public:
// implementing model interface
- QModelIndex index(int row, int column, const QModelIndex &parent) const;
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &child) const;
- int rowCount(const QModelIndex &parent) const;
- int columnCount(const QModelIndex &parent) const;
- bool hasChildren(const QModelIndex &parent) const;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
+ bool hasChildren(const QModelIndex &parent = QModelIndex()) const;
- QVariant data(const QModelIndex &index, int role) const;
- bool setData(const QModelIndex &index, const QVariant &value, int role);
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
- QVariant headerData(int section, Qt::Orientation orientation, int role) const;
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value,
- int role);
+ int role = Qt::EditRole);
QStringList mimeTypes() const;
QMimeData *mimeData(const QModelIndexList &indexes) const;
@@ -87,16 +87,17 @@ public:
int row, int column, const QModelIndex &parent);
Qt::DropActions supportedDropActions() const;
- bool insertRows(int row, int count, const QModelIndex &parent);
- bool insertColumns(int column, int count, const QModelIndex &parent);
+ bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());
+ bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex());
void fetchMore(const QModelIndex &parent);
Qt::ItemFlags flags(const QModelIndex &index) const;
- void sort(int column, Qt::SortOrder order);
+ void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
QModelIndexList match(const QModelIndex &start, int role, const QVariant &value,
- int hits, Qt::MatchFlags flags) const;
+ int hits = 1, Qt::MatchFlags flags =
+ Qt::MatchFlags(Qt::MatchStartsWith|Qt::MatchWrap)) const;
QSize span(const QModelIndex &index) const;
diff --git a/src/gui/itemviews/qsortfilterproxymodel.cpp b/src/gui/itemviews/qsortfilterproxymodel.cpp
index c63a07b..dce5c6a 100644
--- a/src/gui/itemviews/qsortfilterproxymodel.cpp
+++ b/src/gui/itemviews/qsortfilterproxymodel.cpp
@@ -111,6 +111,35 @@ private:
};
+//this struct is used to store what are the rows that are removed
+//between a call to rowsAboutToBeRemoved and rowsRemoved
+//it avoids readding rows to the mapping that are currently being removed
+struct QRowsRemoval
+{
+ QRowsRemoval(const QModelIndex &parent_source, int start, int end) : parent_source(parent_source), start(start), end(end)
+ {
+ }
+
+ QRowsRemoval() : start(-1), end(-1)
+ {
+ }
+
+ bool contains(QModelIndex parent, int row)
+ {
+ do {
+ if (parent == parent_source)
+ return row >= start && row <= end;
+ row = parent.row();
+ parent = parent.parent();
+ } while (row >= 0);
+ return false;
+ }
+private:
+ QModelIndex parent_source;
+ int start;
+ int end;
+};
+
class QSortFilterProxyModelPrivate : public QAbstractProxyModelPrivate
{
Q_DECLARE_PUBLIC(QSortFilterProxyModel)
@@ -122,10 +151,10 @@ public:
QVector<int> proxy_rows;
QVector<int> proxy_columns;
QVector<QModelIndex> mapped_children;
- QMap<QModelIndex, Mapping *>::const_iterator map_iter;
+ QHash<QModelIndex, Mapping *>::const_iterator map_iter;
};
- mutable QMap<QModelIndex, Mapping*> source_index_mapping;
+ mutable QHash<QModelIndex, Mapping*> source_index_mapping;
int source_sort_column;
int proxy_sort_column;
@@ -139,10 +168,11 @@ public:
int filter_role;
bool dynamic_sortfilter;
+ QRowsRemoval itemsBeingRemoved;
QModelIndexPairList saved_persistent_indexes;
- QMap<QModelIndex, Mapping *>::const_iterator create_mapping(
+ QHash<QModelIndex, Mapping *>::const_iterator create_mapping(
const QModelIndex &source_parent) const;
QModelIndex proxy_to_source(const QModelIndex &proxyIndex) const;
QModelIndex source_to_proxy(const QModelIndex &sourceIndex) const;
@@ -150,14 +180,14 @@ public:
void remove_from_mapping(const QModelIndex &source_parent);
- inline QMap<QModelIndex, Mapping *>::const_iterator index_to_iterator(
+ inline QHash<QModelIndex, Mapping *>::const_iterator index_to_iterator(
const QModelIndex &proxy_index) const
{
Q_ASSERT(proxy_index.isValid());
Q_ASSERT(proxy_index.model() == q_func());
const void *p = proxy_index.internalPointer();
Q_ASSERT(p);
- QMap<QModelIndex, Mapping *>::const_iterator it =
+ QHash<QModelIndex, Mapping *>::const_iterator it =
static_cast<const Mapping*>(p)->map_iter;
Q_ASSERT(it != source_index_mapping.constEnd());
Q_ASSERT(it.value());
@@ -165,7 +195,7 @@ public:
}
inline QModelIndex create_index(int row, int column,
- QMap<QModelIndex, Mapping*>::const_iterator it) const
+ QHash<QModelIndex, Mapping*>::const_iterator it) const
{
return q_func()->createIndex(row, column, *it);
}
@@ -246,7 +276,7 @@ public:
virtual void _q_sourceModelDestroyed();
};
-typedef QMap<QModelIndex, QSortFilterProxyModelPrivate::Mapping *> IndexMap;
+typedef QHash<QModelIndex, QSortFilterProxyModelPrivate::Mapping *> IndexMap;
void QSortFilterProxyModelPrivate::_q_sourceModelDestroyed()
{
@@ -292,11 +322,13 @@ IndexMap::const_iterator QSortFilterProxyModelPrivate::create_mapping(
Mapping *m = new Mapping;
int source_rows = model->rowCount(source_parent);
+ m->source_rows.reserve(source_rows);
for (int i = 0; i < source_rows; ++i) {
if (q->filterAcceptsRow(i, source_parent))
m->source_rows.append(i);
}
int source_cols = model->columnCount(source_parent);
+ m->source_columns.reserve(source_cols);
for (int i = 0; i < source_cols; ++i) {
if (q->filterAcceptsColumn(i, source_parent))
m->source_columns.append(i);
@@ -1094,7 +1126,7 @@ void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &sourc
source_rows_change.append(source_row);
}
} else {
- if (q->filterAcceptsRow(source_row, source_parent)) {
+ if (!itemsBeingRemoved.contains(source_parent, source_row) && q->filterAcceptsRow(source_row, source_parent)) {
// This source row now satisfies the filter, so it must be added
source_rows_insert.append(source_row);
}
@@ -1185,13 +1217,13 @@ void QSortFilterProxyModelPrivate::_q_sourceAboutToBeReset()
{
Q_Q(QSortFilterProxyModel);
q->beginResetModel();
- invalidatePersistentIndexes();
- clear_mapping();
}
void QSortFilterProxyModelPrivate::_q_sourceReset()
{
Q_Q(QSortFilterProxyModel);
+ invalidatePersistentIndexes();
+ clear_mapping();
// All internal structures are deleted in clear()
q->endResetModel();
update_source_sort_column();
@@ -1251,6 +1283,7 @@ void QSortFilterProxyModelPrivate::_q_sourceRowsInserted(
void QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeRemoved(
const QModelIndex &source_parent, int start, int end)
{
+ itemsBeingRemoved = QRowsRemoval(source_parent, start, end);
source_items_about_to_be_removed(source_parent, start, end,
Qt::Vertical);
}
@@ -1258,6 +1291,7 @@ void QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeRemoved(
void QSortFilterProxyModelPrivate::_q_sourceRowsRemoved(
const QModelIndex &source_parent, int start, int end)
{
+ itemsBeingRemoved = QRowsRemoval();
source_items_removed(source_parent, start, end, Qt::Vertical);
}
diff --git a/src/gui/itemviews/qstyleditemdelegate.cpp b/src/gui/itemviews/qstyleditemdelegate.cpp
index 9aac554..880f8ab 100644
--- a/src/gui/itemviews/qstyleditemdelegate.cpp
+++ b/src/gui/itemviews/qstyleditemdelegate.cpp
@@ -747,13 +747,8 @@ bool QStyledItemDelegate::editorEvent(QEvent *event,
return false;
}
- Qt::CheckState state;
- if ( flags & Qt::ItemIsTristate ) {
- state = static_cast<Qt::CheckState>( (value.toInt() + 1) % 3 );
- } else {
- state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
+ Qt::CheckState state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
? Qt::Unchecked : Qt::Checked);
- }
return model->setData(index, state, Qt::CheckStateRole);
}
diff --git a/src/gui/itemviews/qtableview.cpp b/src/gui/itemviews/qtableview.cpp
index 3111896..31be224 100644
--- a/src/gui/itemviews/qtableview.cpp
+++ b/src/gui/itemviews/qtableview.cpp
@@ -114,15 +114,14 @@ void QSpanCollection::updateSpan(QSpanCollection::Span *span, int old_height)
}
} else if (old_height > span->height()) {
//remove the span from all the subspans lists that intersect the columns not covered anymore
- Index::iterator it_y = index.lowerBound(-span->bottom());
- if (it_y == index.end())
- it_y = index.find(-span->top()); // This is the only span remaining and we are deleting it.
+ Index::iterator it_y = index.lowerBound(-qMax(span->bottom(), span->top())); //qMax usefull if height is 0
Q_ASSERT(it_y != index.end()); //it_y must exist since the span is in the list
while (-it_y.key() <= span->top() + old_height -1) {
if (-it_y.key() > span->bottom()) {
- (*it_y).remove(-span->left());
+ int removed = (*it_y).remove(-span->left());
+ Q_ASSERT(removed == 1); Q_UNUSED(removed);
if (it_y->isEmpty()) {
- it_y = index.erase(it_y) - 1;
+ it_y = index.erase(it_y);
}
}
if(it_y == index.begin())
@@ -1858,6 +1857,9 @@ void QTableView::setSelection(const QRect &rect, QItemSelectionModel::SelectionF
Returns the rectangle from the viewport of the items in the given
\a selection.
+
+ Since 4.7, the returned region only contains rectangles intersecting
+ (or included in) the viewport.
*/
QRegion QTableView::visualRegionForSelection(const QItemSelection &selection) const
{
@@ -1867,6 +1869,7 @@ QRegion QTableView::visualRegionForSelection(const QItemSelection &selection) co
return QRegion();
QRegion selectionRegion;
+ const QRect &viewportRect = d->viewport->rect();
bool verticalMoved = verticalHeader()->sectionsMoved();
bool horizontalMoved = horizontalHeader()->sectionsMoved();
@@ -1876,8 +1879,11 @@ QRegion QTableView::visualRegionForSelection(const QItemSelection &selection) co
if (range.parent() != d->root || !range.isValid())
continue;
for (int r = range.top(); r <= range.bottom(); ++r)
- for (int c = range.left(); c <= range.right(); ++c)
- selectionRegion += QRegion(visualRect(d->model->index(r, c, d->root)));
+ for (int c = range.left(); c <= range.right(); ++c) {
+ const QRect &rangeRect = visualRect(d->model->index(r, c, d->root));
+ if (viewportRect.intersects(rangeRect))
+ selectionRegion += rangeRect;
+ }
}
} else if (horizontalMoved) {
for (int i = 0; i < selection.count(); ++i) {
@@ -1889,9 +1895,11 @@ QRegion QTableView::visualRegionForSelection(const QItemSelection &selection) co
if (top > bottom)
qSwap<int>(top, bottom);
int height = bottom - top;
- for (int c = range.left(); c <= range.right(); ++c)
- selectionRegion += QRegion(QRect(columnViewportPosition(c), top,
- columnWidth(c), height));
+ for (int c = range.left(); c <= range.right(); ++c) {
+ const QRect rangeRect(columnViewportPosition(c), top, columnWidth(c), height);
+ if (viewportRect.intersects(rangeRect))
+ selectionRegion += rangeRect;
+ }
}
} else if (verticalMoved) {
for (int i = 0; i < selection.count(); ++i) {
@@ -1903,11 +1911,14 @@ QRegion QTableView::visualRegionForSelection(const QItemSelection &selection) co
if (left > right)
qSwap<int>(left, right);
int width = right - left;
- for (int r = range.top(); r <= range.bottom(); ++r)
- selectionRegion += QRegion(QRect(left, rowViewportPosition(r),
- width, rowHeight(r)));
+ for (int r = range.top(); r <= range.bottom(); ++r) {
+ const QRect rangeRect(left, rowViewportPosition(r), width, rowHeight(r));
+ if (viewportRect.intersects(rangeRect))
+ selectionRegion += rangeRect;
+ }
}
} else { // nothing moved
+ const int gridAdjust = showGrid() ? 1 : 0;
for (int i = 0; i < selection.count(); ++i) {
QItemSelectionRange range = selection.at(i);
if (range.parent() != d->root || !range.isValid())
@@ -1916,14 +1927,26 @@ QRegion QTableView::visualRegionForSelection(const QItemSelection &selection) co
const int rtop = rowViewportPosition(range.top());
const int rbottom = rowViewportPosition(range.bottom()) + rowHeight(range.bottom());
- const int rleft = columnViewportPosition(range.left());
- const int rright = columnViewportPosition(range.right()) + columnWidth(range.right());
- selectionRegion += QRect(QPoint(rleft, rtop), QPoint(rright, rbottom));
+ int rleft;
+ int rright;
+ if (isLeftToRight()) {
+ rleft = columnViewportPosition(range.left());
+ rright = columnViewportPosition(range.right()) + columnWidth(range.right());
+ } else {
+ rleft = columnViewportPosition(range.right());
+ rright = columnViewportPosition(range.left()) + columnWidth(range.left());
+ }
+ const QRect rangeRect(QPoint(rleft, rtop), QPoint(rright - 1 - gridAdjust, rbottom - 1 - gridAdjust));
+ if (viewportRect.intersects(rangeRect))
+ selectionRegion += rangeRect;
if (d->hasSpans()) {
foreach (QSpanCollection::Span *s,
d->spans.spansInRect(range.left(), range.top(), range.width(), range.height())) {
- if (range.contains(s->top(), s->left(), range.parent()))
- selectionRegion += d->visualSpanRect(*s);
+ if (range.contains(s->top(), s->left(), range.parent())) {
+ const QRect &visualSpanRect = d->visualSpanRect(*s);
+ if (viewportRect.intersects(visualSpanRect))
+ selectionRegion += visualSpanRect;
+ }
}
}
}
@@ -1960,12 +1983,7 @@ QModelIndexList QTableView::selectedIndexes() const
void QTableView::rowCountChanged(int /*oldCount*/, int /*newCount*/ )
{
Q_D(QTableView);
- updateGeometries();
- if (verticalScrollMode() == QAbstractItemView::ScrollPerItem)
- d->verticalHeader->setOffsetToSectionPosition(verticalScrollBar()->value());
- else
- d->verticalHeader->setOffset(verticalScrollBar()->value());
- d->viewport->update();
+ d->doDelayedItemsLayout();
}
/*!
@@ -2546,7 +2564,7 @@ void QTableView::scrollTo(const QModelIndex &index, ScrollHint hint)
// check if we really need to do anything
if (!d->isIndexValid(index)
|| (d->model->parent(index) != d->root)
- || isIndexHidden(index))
+ || isRowHidden(index.row()) || isColumnHidden(index.column()))
return;
QSpanCollection::Span span;
diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp
index 37168eb..d934683 100644
--- a/src/gui/itemviews/qtreeview.cpp
+++ b/src/gui/itemviews/qtreeview.cpp
@@ -674,21 +674,29 @@ void QTreeView::dataChanged(const QModelIndex &topLeft, const QModelIndex &botto
// refresh the height cache here; we don't really lose anything by getting the size hint,
// since QAbstractItemView::dataChanged() will get the visualRect for the items anyway
- int topViewIndex = d->viewIndex(topLeft);
- if (topViewIndex == 0)
- d->defaultItemHeight = indexRowSizeHint(topLeft);
bool sizeChanged = false;
+ int topViewIndex = d->viewIndex(topLeft);
+ if (topViewIndex == 0) {
+ int newDefaultItemHeight = indexRowSizeHint(topLeft);
+ sizeChanged = d->defaultItemHeight != newDefaultItemHeight;
+ d->defaultItemHeight = newDefaultItemHeight;
+ }
+
if (topViewIndex != -1) {
- if (topLeft == bottomRight) {
+ if (topLeft.row() == bottomRight.row()) {
int oldHeight = d->itemHeight(topViewIndex);
d->invalidateHeightCache(topViewIndex);
- sizeChanged = (oldHeight != d->itemHeight(topViewIndex));
+ sizeChanged |= (oldHeight != d->itemHeight(topViewIndex));
+ if (topLeft.column() == 0)
+ d->viewItems[topViewIndex].hasChildren = d->hasVisibleChildren(topLeft);
} else {
int bottomViewIndex = d->viewIndex(bottomRight);
for (int i = topViewIndex; i <= bottomViewIndex; ++i) {
int oldHeight = d->itemHeight(i);
d->invalidateHeightCache(i);
sizeChanged |= (oldHeight != d->itemHeight(i));
+ if (topLeft.column() == 0)
+ d->viewItems[i].hasChildren = d->hasVisibleChildren(d->viewItems.at(i).index);
}
}
}
@@ -954,16 +962,16 @@ void QTreeView::keyboardSearch(const QString &search)
else
start = d->model->index(0, 0, d->root);
- QTime now(QTime::currentTime());
bool skipRow = false;
- if (search.isEmpty()
- || (d->keyboardInputTime.msecsTo(now) > QApplication::keyboardInputInterval())) {
+ bool keyboardTimeWasValid = d->keyboardInputTime.isValid();
+ qint64 keyboardInputTimeElapsed = d->keyboardInputTime.restart();
+ if (search.isEmpty() || !keyboardTimeWasValid
+ || keyboardInputTimeElapsed > QApplication::keyboardInputInterval()) {
d->keyboardInput = search;
- skipRow = true;
+ skipRow = currentIndex().isValid(); //if it is not valid we should really start at QModelIndex(0,0)
} else {
d->keyboardInput += search;
}
- d->keyboardInputTime = now;
// special case for searches with same key like 'aaaaa'
bool sameKey = false;
@@ -1228,17 +1236,17 @@ bool QTreeView::viewportEvent(QEvent *event)
int oldBranch = d->hoverBranch;
d->hoverBranch = d->itemDecorationAt(he->pos());
if (oldBranch != d->hoverBranch) {
- QModelIndex oldIndex = d->modelIndex(oldBranch),
- newIndex = d->modelIndex(d->hoverBranch);
- if (oldIndex != newIndex) {
- QRect oldRect = visualRect(oldIndex);
- QRect newRect = visualRect(newIndex);
- oldRect.setLeft(oldRect.left() - d->indent);
- newRect.setLeft(newRect.left() - d->indent);
- //we need to paint the whole items (including the decoration) so that when the user
- //moves the mouse over those elements they are updated
- viewport()->update(oldRect);
- viewport()->update(newRect);
+ //we need to paint the whole items (including the decoration) so that when the user
+ //moves the mouse over those elements they are updated
+ if (oldBranch >= 0) {
+ int y = d->coordinateForItem(oldBranch);
+ int h = d->itemHeight(oldBranch);
+ viewport()->update(QRect(0, y, viewport()->width(), h));
+ }
+ if (d->hoverBranch >= 0) {
+ int y = d->coordinateForItem(d->hoverBranch);
+ int h = d->itemHeight(d->hoverBranch);
+ viewport()->update(QRect(0, y, viewport()->width(), h));
}
}
break; }
@@ -1993,6 +2001,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<QPersistentModelIndex>::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)) {
@@ -2134,9 +2160,10 @@ QModelIndex QTreeView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie
return d->modelIndex(d->above(vi), current.column());
case MoveLeft: {
QScrollBar *sb = horizontalScrollBar();
- if (vi < d->viewItems.count() && d->viewItems.at(vi).expanded && d->itemsExpandable && sb->value() == sb->minimum())
+ if (vi < d->viewItems.count() && d->viewItems.at(vi).expanded && d->itemsExpandable && sb->value() == sb->minimum()) {
d->collapse(vi, true);
- else {
+ d->moveCursorUpdatedView = true;
+ } else {
bool descend = style()->styleHint(QStyle::SH_ItemView_ArrowKeysNavigateIntoChildren, 0, this);
if (descend) {
QModelIndex par = current.parent();
@@ -2156,7 +2183,10 @@ QModelIndex QTreeView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie
return next;
}
+ int oldValue = sb->value();
sb->setValue(sb->value() - sb->singleStep());
+ if (oldValue != sb->value())
+ d->moveCursorUpdatedView = true;
}
}
@@ -2168,6 +2198,7 @@ QModelIndex QTreeView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie
if (vi < d->viewItems.count() && !d->viewItems.at(vi).expanded && d->itemsExpandable
&& d->hasVisibleChildren(d->viewItems.at(vi).index)) {
d->expand(vi, true);
+ d->moveCursorUpdatedView = true;
} else {
bool descend = style()->styleHint(QStyle::SH_ItemView_ArrowKeysNavigateIntoChildren, 0, this);
if (descend) {
@@ -2190,7 +2221,10 @@ QModelIndex QTreeView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie
//last restort: we change the scrollbar value
QScrollBar *sb = horizontalScrollBar();
+ int oldValue = sb->value();
sb->setValue(sb->value() + sb->singleStep());
+ if (oldValue != sb->value())
+ d->moveCursorUpdatedView = true;
}
}
updateGeometries();
@@ -2249,6 +2283,9 @@ void QTreeView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFl
/*!
Returns the rectangle from the viewport of the items in the given
\a selection.
+
+ Since 4.7, the returned region only contains rectangles intersecting
+ (or included in) the viewport.
*/
QRegion QTreeView::visualRegionForSelection(const QItemSelection &selection) const
{
@@ -2257,6 +2294,7 @@ QRegion QTreeView::visualRegionForSelection(const QItemSelection &selection) con
return QRegion();
QRegion selectionRegion;
+ const QRect &viewportRect = d->viewport->rect();
for (int i = 0; i < selection.count(); ++i) {
QItemSelectionRange range = selection.at(i);
if (!range.isValid())
@@ -2289,13 +2327,16 @@ QRegion QTreeView::visualRegionForSelection(const QItemSelection &selection) con
qSwap<int>(top, bottom);
int height = bottom - top + 1;
if (d->header->sectionsMoved()) {
- for (int c = range.left(); c <= range.right(); ++c)
- selectionRegion += QRegion(QRect(columnViewportPosition(c), top,
- columnWidth(c), height));
+ for (int c = range.left(); c <= range.right(); ++c) {
+ const QRect rangeRect(columnViewportPosition(c), top, columnWidth(c), height);
+ if (viewportRect.intersects(rangeRect))
+ selectionRegion += rangeRect;
+ }
} else {
QRect combined = leftRect|rightRect;
combined.setX(columnViewportPosition(isRightToLeft() ? range.right() : range.left()));
- selectionRegion += combined;
+ if (viewportRect.intersects(combined))
+ selectionRegion += combined;
}
}
return selectionRegion;
@@ -2402,24 +2443,6 @@ void QTreeView::reexpand()
}
/*!
- \internal
-*/
-static bool treeViewItemLessThan(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.
*/
@@ -2448,84 +2471,7 @@ 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<QTreeViewItem> insertedItems(delta);
- for (int i = 0; i < delta; ++i) {
- QTreeViewItem &item = insertedItems[i];
- item.index = d->model->index(i + start, 0, parent);
- 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<QTreeViewItem>::iterator it;
- it = qLowerBound(d->viewItems.begin() + firstChildItem,
- d->viewItems.begin() + lastChildItem + 1,
- insertedItems.at(0), treeViewItemLessThan);
- 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->viewItems.insert(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);
-
- updateGeometries();
- viewport()->update();
+ d->doDelayedItemsLayout();
} else if ((parentItem != -1) && d->viewItems.at(parentItem).expanded) {
d->doDelayedItemsLayout();
} else if (parentItem != -1 && (d->model->rowCount(parent) == end - start + 1)) {
@@ -2543,8 +2489,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();
}
/*!
@@ -2556,7 +2502,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);
}
/*!
@@ -2658,17 +2607,8 @@ void QTreeView::expandAll()
{
Q_D(QTreeView);
d->viewItems.clear();
- d->expandedIndexes.clear();
d->interruptDelayedItemsLayout();
- d->layout(-1);
- for (int i = 0; i < d->viewItems.count(); ++i) {
- if (d->viewItems[i].expanded)
- continue;
- d->viewItems[i].expanded = true;
- d->layout(i);
- QModelIndex idx = d->viewItems.at(i).index;
- d->expandedIndexes.insert(idx);
- }
+ d->layout(-1, true);
updateGeometries();
d->viewport->update();
}
@@ -2949,6 +2889,39 @@ void QTreeViewPrivate::expand(int item, bool emitSignal)
}
}
+void QTreeViewPrivate::insertViewItems(int pos, int count, const QTreeViewItem &viewItem)
+{
+ viewItems.insert(pos, count, viewItem);
+ QTreeViewItem *items = viewItems.data();
+ for (int i = pos + count; i < viewItems.count(); i++)
+ if (items[i].parentItem >= pos)
+ items[i].parentItem += count;
+}
+
+void QTreeViewPrivate::removeViewItems(int pos, int count)
+{
+ viewItems.remove(pos, count);
+ QTreeViewItem *items = viewItems.data();
+ for (int i = pos; i < viewItems.count(); i++)
+ if (items[i].parentItem >= pos)
+ items[i].parentItem -= count;
+}
+
+#if 0
+bool QTreeViewPrivate::checkViewItems() const
+{
+ for (int i = 0; i < viewItems.count(); ++i) {
+ const QTreeViewItem &vi = viewItems.at(i);
+ if (vi.parentItem == -1) {
+ Q_ASSERT(!vi.index.parent().isValid() || vi.index.parent() == root);
+ } else {
+ Q_ASSERT(vi.index.parent() == viewItems.at(vi.parentItem).index);
+ }
+ }
+ return true;
+}
+#endif
+
void QTreeViewPrivate::collapse(int item, bool emitSignal)
{
Q_Q(QTreeView);
@@ -2977,14 +2950,11 @@ void QTreeViewPrivate::collapse(int item, bool emitSignal)
expandedIndexes.erase(it);
viewItems[item].expanded = false;
int index = item;
- QModelIndex parent = modelIndex;
- while (parent.isValid() && parent != root) {
- Q_ASSERT(index > -1);
+ while (index > -1) {
viewItems[index].total -= total;
- parent = parent.parent();
- index = viewIndex(parent);
+ index = viewItems[index].parentItem;
}
- viewItems.remove(item + 1, total); // collapse
+ removeViewItems(item + 1, total); // collapse
q->setState(oldState);
if (emitSignal) {
@@ -3121,7 +3091,14 @@ void QTreeViewPrivate::_q_columnsRemoved(const QModelIndex &parent, int start, i
QAbstractItemViewPrivate::_q_columnsRemoved(parent, start, end);
}
-void QTreeViewPrivate::layout(int i)
+/** \internal
+ creates and initialize the viewItem structure of the children of the element \i
+
+ set \a recursiveExpanding if the function has to expand all the children (called from expandAll)
+ \a afterIsUninitialized is when we recurse from layout(-1), it means all the items after 'i' are
+ not yet initialized and need not to be moved
+ */
+void QTreeViewPrivate::layout(int i, bool recursiveExpanding, bool afterIsUninitialized)
{
Q_Q(QTreeView);
QModelIndex current;
@@ -3148,8 +3125,12 @@ void QTreeViewPrivate::layout(int i)
defaultItemHeight = q->indexRowSizeHint(index);
}
viewItems.resize(count);
+ afterIsUninitialized = true;
} else if (viewItems[i].total != (uint)count) {
- viewItems.insert(i + 1, count, QTreeViewItem()); // expand
+ if (!afterIsUninitialized)
+ insertViewItems(i + 1, count, QTreeViewItem()); // expand
+ else if (count > 0)
+ viewItems.resize(viewItems.count() + count);
} else {
expanding = false;
}
@@ -3171,15 +3152,18 @@ void QTreeViewPrivate::layout(int i)
item->hasMoreSiblings = true;
item = &viewItems[last];
item->index = current;
+ item->parentItem = i;
item->level = level;
item->height = 0;
item->spanning = q->isFirstColumnSpanned(current.row(), parent);
item->expanded = false;
item->total = 0;
item->hasMoreSiblings = false;
- if (isIndexExpanded(current)) {
+ if (recursiveExpanding || isIndexExpanded(current)) {
+ if (recursiveExpanding)
+ expandedIndexes.insert(current);
item->expanded = true;
- layout(last);
+ layout(last, recursiveExpanding, afterIsUninitialized);
item = &viewItems[last];
children += item->total;
item->hasChildren = item->total > 0;
@@ -3191,17 +3175,19 @@ void QTreeViewPrivate::layout(int i)
}
// remove hidden items
- if (hidden > 0)
- viewItems.remove(last + 1, hidden); // collapse
+ if (hidden > 0) {
+ if (!afterIsUninitialized)
+ removeViewItems(last + 1, hidden);
+ else
+ viewItems.resize(viewItems.size() - hidden);
+ }
if (!expanding)
return; // nothing changed
- while (parent != root) {
- Q_ASSERT(i > -1);
+ while (i > -1) {
viewItems[i].total += count - hidden;
- parent = parent.parent();
- i = viewIndex(parent);
+ i = viewItems[i].parentItem;
}
}
@@ -3356,46 +3342,39 @@ 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 qint64 internalId = index.internalId();
-
- // A quick check near the last item to see if we are just incrementing
- const int start = lastViewedItem > 2 ? lastViewedItem - 2 : 0;
- const int end = lastViewedItem < totalCount - 2 ? lastViewedItem + 2 : totalCount;
- int row = index.row();
- for (int i = start; i < end; ++i) {
- const QModelIndex &idx = viewItems.at(i).index;
- if (idx.row() == row) {
- if (idx.internalId() == index.internalId()) {
- lastViewedItem = i;
- return i;
- }
+ // We start nearest to the lastViewedItem
+ int localCount = qMin(lastViewedItem - 1, totalCount - lastViewedItem);
+ for (int i = 0; i < localCount; ++i) {
+ const QModelIndex &idx1 = viewItems.at(lastViewedItem + i).index;
+ if (idx1.row() == row && idx1.internalId() == internalId) {
+ lastViewedItem = lastViewedItem + i;
+ return lastViewedItem;
+ }
+ const QModelIndex &idx2 = viewItems.at(lastViewedItem - i - 1).index;
+ if (idx2.row() == row && idx2.internalId() == internalId) {
+ lastViewedItem = lastViewedItem - i - 1;
+ return lastViewedItem;
}
}
- // NOTE: this function is slow if the item is outside the visible area
- // search in visible items first and below
- int t = firstVisibleItem();
- t = t > 100 ? t - 100 : 0; // start 100 items above the visible area
-
- for (int i = t; i < totalCount; ++i) {
- const QModelIndex &idx = viewItems.at(i).index;
- if (idx.row() == row) {
- if (idx.internalId() == index.internalId()) {
- lastViewedItem = i;
- return i;
- }
+ for (int j = qMax(0, lastViewedItem + localCount); j < totalCount; ++j) {
+ const QModelIndex &idx = viewItems.at(j).index;
+ if (idx.row() == row && idx.internalId() == internalId) {
+ lastViewedItem = j;
+ return j;
}
}
- // search from top to first visible
- for (int j = 0; j < t; ++j) {
+ for (int j = qMin(totalCount, lastViewedItem - localCount) - 1; j >= 0; --j) {
const QModelIndex &idx = viewItems.at(j).index;
- if (idx.row() == row) {
- if (idx.internalId() == index.internalId()) {
- lastViewedItem = j;
- return j;
- }
+ if (idx.row() == row && idx.internalId() == internalId) {
+ lastViewedItem = j;
+ return j;
}
}
+
// nothing found
return -1;
}
@@ -3717,120 +3696,6 @@ bool QTreeViewPrivate::hasVisibleChildren(const QModelIndex& parent) const
return false;
}
-void QTreeViewPrivate::rowsRemoved(const QModelIndex &parent,
- int start, int end, bool after)
-{
- Q_Q(QTreeView);
- // 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
- viewItems.remove(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) {
- q->updateGeometries();
- viewport->update();
- } 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<QPersistentModelIndex>::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 589a224..261af31 100644
--- a/src/gui/itemviews/qtreeview_p.h
+++ b/src/gui/itemviews/qtreeview_p.h
@@ -55,6 +55,7 @@
#include "private/qabstractitemview_p.h"
#include <QtCore/qvariantanimation.h>
+#include <QtCore/qabstractitemmodel.h>
#ifndef QT_NO_TREEVIEW
@@ -62,9 +63,10 @@ QT_BEGIN_NAMESPACE
struct QTreeViewItem
{
- QTreeViewItem() : expanded(false), spanning(false), hasChildren(false),
+ QTreeViewItem() : parentItem(-1), expanded(false), spanning(false), hasChildren(false),
hasMoreSiblings(false), total(0), level(0), height(0) {}
QModelIndex index; // we remove items whenever the indexes are invalidated
+ int parentItem; // parent item index in viewItems
uint expanded : 1;
uint spanning : 1;
uint hasChildren : 1; // if the item has visible children (even if collapsed)
@@ -74,6 +76,8 @@ struct QTreeViewItem
int height : 16; // row height
};
+Q_DECLARE_TYPEINFO(QTreeViewItem, Q_MOVABLE_TYPE);
+
class QTreeViewPrivate : public QAbstractItemViewPrivate
{
Q_DECLARE_PUBLIC(QTreeView)
@@ -87,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();
@@ -123,7 +127,7 @@ public:
void _q_sortIndicatorChanged(int column, Qt::SortOrder order);
void _q_modelDestroyed();
- void layout(int item);
+ void layout(int item, bool recusiveExpanding = false, bool afterIsUninitialized = false);
int pageUp(int item) const;
int pageDown(int item) const;
@@ -136,6 +140,12 @@ public:
int viewIndex(const QModelIndex &index) const;
QModelIndex modelIndex(int i, int column = 0) const;
+ void insertViewItems(int pos, int count, const QTreeViewItem &viewItem);
+ void removeViewItems(int pos, int count);
+#if 0
+ bool checkViewItems() const;
+#endif
+
int firstVisibleItem(int *offset = 0) const;
int columnAt(int x) const;
bool hasVisibleChildren( const QModelIndex& parent) const;
@@ -155,8 +165,6 @@ public:
QPair<int,int> 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;
@@ -232,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/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp
index 4ec2ae2..b0a23d4 100644
--- a/src/gui/kernel/qapplication.cpp
+++ b/src/gui/kernel/qapplication.cpp
@@ -498,9 +498,7 @@ inline bool QApplicationPrivate::isAlien(QWidget *widget)
{
if (!widget)
return false;
-#if defined(Q_WS_MAC) // Fake alien behavior on the Mac :)
- return !widget->isWindow() && widget->window()->testAttribute(Qt::WA_DontShowOnScreen);
-#elif defined(Q_WS_QWS)
+#if defined(Q_WS_QWS)
return !widget->isWindow()
# ifdef Q_BACKINGSTORE_SUBSURFACES
&& !(widget->d_func()->maybeTopData() && widget->d_func()->maybeTopData()->windowSurface)
@@ -905,6 +903,14 @@ void QApplicationPrivate::initialize()
{
QWidgetPrivate::mapper = new QWidgetMapper;
QWidgetPrivate::allWidgets = new QWidgetSet;
+
+#if !defined(Q_WS_X11) && !defined(Q_WS_QWS)
+ // initialize the graphics system - on X11 this is initialized inside
+ // qt_init() in qapplication_x11.cpp because of several reasons.
+ // On QWS, the graphics system is set by the QScreen plugin.
+ graphics_system = QGraphicsSystemFactory::create(graphics_system_name);
+#endif
+
if (qt_appType != QApplication::Tty)
(void) QApplication::style(); // trigger creation of application style
// trigger registering of QVariant's GUI types
@@ -938,13 +944,7 @@ void QApplicationPrivate::initialize()
// Set up which span functions should be used in raster engine...
qInitDrawhelperAsm();
-
-#if !defined(Q_WS_X11) && !defined(Q_WS_QWS)
- // initialize the graphics system - on X11 this is initialized inside
- // qt_init() in qapplication_x11.cpp because of several reasons.
- // On QWS, the graphics system is set by the QScreen plugin.
- graphics_system = QGraphicsSystemFactory::create(graphics_system_name);
-#endif
+
#ifndef QT_NO_WHEELEVENT
QApplicationPrivate::wheel_scroll_lines = 3;
#endif
@@ -2311,6 +2311,22 @@ static bool qt_detectRTLLanguage()
" languages or to 'RTL' in right-to-left languages (such as Hebrew"
" and Arabic) to get proper widget layout.") == QLatin1String("RTL"));
}
+#if defined(Q_WS_MAC)
+static const char *application_menu_strings[] = {
+ QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Services"),
+ QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Hide %1"),
+ QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Hide Others"),
+ QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Show All"),
+ QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Preferences..."),
+ QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Quit %1"),
+ QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","About %1")
+ };
+QString qt_mac_applicationmenu_string(int type)
+{
+ return qApp->translate("MAC_APPLICATION_MENU",
+ application_menu_strings[type]);
+}
+#endif
#endif
/*!\reimp
@@ -2339,6 +2355,9 @@ bool QApplication::event(QEvent *e)
#ifndef QT_NO_TRANSLATION
setLayoutDirection(qt_detectRTLLanguage()?Qt::RightToLeft:Qt::LeftToRight);
#endif
+#if defined(QT_MAC_USE_COCOA)
+ qt_mac_post_retranslateAppMenu();
+#endif
QWidgetList list = topLevelWidgets();
for (int i = 0; i < list.size(); ++i) {
QWidget *w = list.at(i);
@@ -3013,7 +3032,7 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event,
return result;
}
-#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_MAC)
/*
This function should only be called when the widget changes visibility, i.e.
when the \a widget is shown, hidden or deleted. This function does nothing
@@ -3073,7 +3092,7 @@ void QApplicationPrivate::sendSyntheticEnterLeave(QWidget *widget)
sendMouseEvent(widgetUnderCursor, &e, widgetUnderCursor, tlw, &qt_button_down, qt_last_mouse_receiver);
#endif // QT_NO_CURSOR
}
-#endif // Q_WS_WIN || Q_WS_X11
+#endif // Q_WS_WIN || Q_WS_X11 || Q_WS_MAC
/*!
Returns the desktop widget (also called the root window).
@@ -5273,9 +5292,9 @@ QInputContext *QApplication::inputContext() const
QApplication *that = const_cast<QApplication *>(this);
const QStringList keys = QInputContextFactory::keys();
// Try hbim and coefep first, then try others.
- if (keys.contains("hbim")) {
+ if (keys.contains(QLatin1String("hbim"))) {
that->d_func()->inputContext = QInputContextFactory::create(QLatin1String("hbim"), that);
- } else if (keys.contains("coefep")) {
+ } else if (keys.contains(QLatin1String("coefep"))) {
that->d_func()->inputContext = QInputContextFactory::create(QLatin1String("coefep"), that);
} else {
for (int c = 0; c < keys.size() && !d->inputContext; ++c) {
diff --git a/src/gui/kernel/qapplication.h b/src/gui/kernel/qapplication.h
index ee74350..c21b982 100644
--- a/src/gui/kernel/qapplication.h
+++ b/src/gui/kernel/qapplication.h
@@ -376,6 +376,7 @@ private:
Q_DECLARE_PRIVATE(QApplication)
friend class QGraphicsWidget;
+ friend class QGraphicsItem;
friend class QGraphicsScene;
friend class QGraphicsScenePrivate;
friend class QWidget;
diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm
index e511c3a..28072fc 100644
--- a/src/gui/kernel/qapplication_mac.mm
+++ b/src/gui/kernel/qapplication_mac.mm
@@ -184,7 +184,8 @@ bool qt_mac_app_fullscreen = false;
bool qt_scrollbar_jump_to_pos = false;
static bool qt_mac_collapse_on_dblclick = true;
extern int qt_antialiasing_threshold; // from qapplication.cpp
-QPointer<QWidget> qt_button_down; // widget got last button-down
+QWidget * qt_button_down; // widget got last button-down
+QPointer<QWidget> qt_last_mouse_receiver;
#ifndef QT_MAC_USE_COCOA
static bool qt_button_down_in_content; // whether the button_down was in the content area.
static bool qt_mac_previous_press_in_popup_mode = false;
@@ -1222,9 +1223,16 @@ void qt_init(QApplicationPrivate *priv, int)
#endif
if (!app_proc_ae_handlerUPP) {
app_proc_ae_handlerUPP = AEEventHandlerUPP(QApplicationPrivate::globalAppleEventProcessor);
- for(uint i = 0; i < sizeof(app_apple_events) / sizeof(QMacAppleEventTypeSpec); ++i)
- AEInstallEventHandler(app_apple_events[i].mac_class, app_apple_events[i].mac_id,
- app_proc_ae_handlerUPP, SRefCon(qApp), false);
+ for(uint i = 0; i < sizeof(app_apple_events) / sizeof(QMacAppleEventTypeSpec); ++i) {
+ // Install apple event handler, but avoid overwriting an already
+ // existing handler (it means a 3rd party application has installed one):
+ SRefCon refCon = 0;
+ AEEventHandlerUPP current_handler = NULL;
+ AEGetEventHandler(app_apple_events[i].mac_class, app_apple_events[i].mac_id, &current_handler, &refCon, false);
+ if (!current_handler)
+ AEInstallEventHandler(app_apple_events[i].mac_class, app_apple_events[i].mac_id,
+ app_proc_ae_handlerUPP, SRefCon(qApp), false);
+ }
}
if (QApplicationPrivate::app_style) {
@@ -1751,14 +1759,19 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event
// (actually two events; one for horizontal and one for vertical).
// As a results of this, and to make sure we dont't receive duplicate events,
// we try to detect when this happend by checking the 'compatibilityEvent'.
+ // Since delta is delivered as pixels rather than degrees, we need to
+ // convert from pixels to degrees in a sensible manner.
+ // It looks like 1/4 degrees per pixel behaves most native.
+ // (NB: Qt expects the unit for delta to be 8 per degree):
+ const int pixelsToDegrees = 2;
SInt32 mdelt = 0;
GetEventParameter(event, kEventParamMouseWheelSmoothHorizontalDelta, typeSInt32, 0,
sizeof(mdelt), 0, &mdelt);
- wheel_deltaX = mdelt;
+ wheel_deltaX = mdelt * pixelsToDegrees;
mdelt = 0;
GetEventParameter(event, kEventParamMouseWheelSmoothVerticalDelta, typeSInt32, 0,
sizeof(mdelt), 0, &mdelt);
- wheel_deltaY = mdelt;
+ wheel_deltaY = mdelt * pixelsToDegrees;
GetEventParameter(event, kEventParamEventRef, typeEventRef, 0,
sizeof(compatibilityEvent), 0, &compatibilityEvent);
} else if (ekind == kEventMouseWheelMoved) {
@@ -2495,6 +2508,13 @@ void QApplicationPrivate::setupAppleEvents()
// finished initialization, which appears to be just after [NSApplication run] has
// started to execute. By setting up our apple events handlers this late, we override
// the ones set up by NSApplication.
+
+ // If Qt is used as a plugin, we let the 3rd party application handle events
+ // like quit and open file events. Otherwise, if we install our own handlers, we
+ // easily end up breaking functionallity the 3rd party application depend on:
+ if (QApplication::testAttribute(Qt::AA_MacPluginApplication))
+ return;
+
QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) *newDelegate = [QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate];
NSAppleEventManager *eventManager = [NSAppleEventManager sharedAppleEventManager];
[eventManager setEventHandler:newDelegate andSelector:@selector(appleEventQuit:withReplyEvent:)
diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h
index e0a6103..6d71cfe 100644
--- a/src/gui/kernel/qapplication_p.h
+++ b/src/gui/kernel/qapplication_p.h
@@ -514,7 +514,7 @@ public:
int symbianResourceChange(const QSymbianEvent *symbianEvent);
#endif
-#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC)
void sendSyntheticEnterLeave(QWidget *widget);
#endif
@@ -543,6 +543,7 @@ public:
const QList<QTouchEvent::TouchPoint> &touchPoints);
#if defined(Q_WS_WIN)
+ static bool HasTouchSupport;
static PtrRegisterTouchWindow RegisterTouchWindow;
static PtrGetTouchInputInfo GetTouchInputInfo;
static PtrCloseTouchInputHandle CloseTouchInputHandle;
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp
index baefdfd..c735d1f 100644
--- a/src/gui/kernel/qapplication_s60.cpp
+++ b/src/gui/kernel/qapplication_s60.cpp
@@ -52,6 +52,7 @@
#include "qstring.h"
#include "qdebug.h"
#include "qimage.h"
+#include "qcombobox.h"
#include "private/qkeymapper_p.h"
#include "private/qfont_p.h"
#ifndef QT_NO_STYLE_S60
@@ -371,8 +372,13 @@ QSymbianControl::~QSymbianControl()
{
if (S60->curWin == this)
S60->curWin = 0;
- if (!QApplicationPrivate::is_app_closing)
- setFocusSafely(false);
+ if (!QApplicationPrivate::is_app_closing) {
+ QT_TRY {
+ setFocusSafely(false);
+ } QT_CATCH(const std::exception&) {
+ // ignore exceptions, nothing can be done
+ }
+ }
S60->appUi()->RemoveFromStack(this);
delete m_longTapDetector;
}
@@ -597,9 +603,9 @@ TKeyResponse QSymbianControl::OfferKeyEvent(const TKeyEvent& keyEvent, TEventCod
TUint s60Keysym = QApplicationPrivate::resolveS60ScanCode(keyEvent.iScanCode,
keyEvent.iCode);
int keyCode;
- if (s60Keysym == EKeyNull){ //some key events have 0 in iCode, for them iScanCode should be used
- keyCode = qt_keymapper_private()->mapS60ScanCodesToQt(keyEvent.iScanCode);
- } else if (s60Keysym >= 0x20 && s60Keysym < ENonCharacterKeyBase) {
+ if (s60Keysym == EKeyNull){ //some key events have 0 in iCode, for them iScanCode should be used
+ keyCode = qt_keymapper_private()->mapS60ScanCodesToQt(keyEvent.iScanCode);
+ } else if (s60Keysym >= 0x20 && s60Keysym < ENonCharacterKeyBase) {
// Normal characters keys.
keyCode = s60Keysym;
} else {
@@ -966,16 +972,29 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */)
qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle());
#ifdef Q_WS_S60
// If widget is fullscreen/minimized, hide status pane and button container otherwise show them.
- CEikStatusPane* statusPane = S60->statusPane();
- CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer();
+ CEikStatusPane *statusPane = S60->statusPane();
+ CEikButtonGroupContainer *buttonGroup = S60->buttonGroupContainer();
TBool visible = !(qwidget->windowState() & (Qt::WindowFullScreen | Qt::WindowMinimized));
if (statusPane)
statusPane->MakeVisible(visible);
- if (buttonGroup)
- buttonGroup->MakeVisible(visible);
+ if (buttonGroup) {
+ // Visibility
+ const TBool isFullscreen = qwidget->windowState() & Qt::WindowFullScreen;
+ const TBool cbaVisibilityHint = qwidget->windowFlags() & Qt::WindowSoftkeysVisibleHint;
+ buttonGroup->MakeVisible(visible || (isFullscreen && cbaVisibilityHint));
+
+ // Responsiviness
+ CEikCba *cba = static_cast<CEikCba *>( buttonGroup->ButtonGroup() ); // downcast from MEikButtonGroup
+ TUint cbaFlags = cba->ButtonGroupFlags();
+ if(qwidget->windowFlags() & Qt::WindowSoftkeysRespondHint)
+ cbaFlags |= EAknCBAFlagRespondWhenInvisible;
+ else
+ cbaFlags &= ~EAknCBAFlagRespondWhenInvisible;
+ cba->SetButtonGroupFlags(cbaFlags);
+ }
#endif
} else if (QApplication::activeWindow() == qwidget->window()) {
- if (CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog()) {
+ if (CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog() || S60->menuBeingConstructed) {
QWidget *fw = QApplication::focusWidget();
if (fw) {
QFocusEvent event(QEvent::FocusOut, Qt::PopupFocusReason);
@@ -990,16 +1009,32 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */)
// else { We don't touch the active window unless we were explicitly activated or deactivated }
}
+void QSymbianControl::handleClientAreaChange()
+{
+ const bool cbaVisibilityHint = qwidget->windowFlags() & Qt::WindowSoftkeysVisibleHint;
+ if (qwidget->isFullScreen() && !cbaVisibilityHint) {
+ SetExtentToWholeScreen();
+ } else if (qwidget->isMaximized() || (qwidget->isFullScreen() && cbaVisibilityHint)) {
+ TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect();
+ SetExtent(r.iTl, r.Size());
+ } else if (!qwidget->isMinimized()) { // Normal geometry
+ if (!qwidget->testAttribute(Qt::WA_Resized)) {
+ qwidget->adjustSize();
+ qwidget->setAttribute(Qt::WA_Resized, false); //not a user resize
+ }
+ if (!qwidget->testAttribute(Qt::WA_Moved) && qwidget->windowType() != Qt::Dialog) {
+ TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect();
+ SetPosition(r.iTl);
+ qwidget->setAttribute(Qt::WA_Moved, false); // not really an explicit position
+ }
+ }
+}
+
void QSymbianControl::HandleResourceChange(int resourceType)
{
switch (resourceType) {
case KInternalStatusPaneChange:
- if (qwidget->isFullScreen()) {
- SetExtentToWholeScreen();
- } else if (qwidget->isMaximized()) {
- TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect();
- SetExtent(r.iTl, r.Size());
- }
+ handleClientAreaChange();
if (IsFocused() && IsVisible()) {
qwidget->d_func()->setWindowIcon_sys(true);
qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle());
@@ -1011,12 +1046,7 @@ void QSymbianControl::HandleResourceChange(int resourceType)
#ifdef Q_WS_S60
case KEikDynamicLayoutVariantSwitch:
{
- if (qwidget->isFullScreen()) {
- SetExtentToWholeScreen();
- } else if (qwidget->isMaximized()) {
- TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect();
- SetExtent(r.iTl, r.Size());
- }
+ handleClientAreaChange();
break;
}
#endif
@@ -1214,6 +1244,7 @@ void qt_init(QApplicationPrivate * /* priv */, int)
}
S60->avkonComponentsSupportTransparency = false;
+ S60->menuBeingConstructed = false;
#ifdef Q_WS_S60
TUid KCRUidAvkon = { 0x101F876E };
@@ -1229,13 +1260,15 @@ void qt_init(QApplicationPrivate * /* priv */, int)
S60->avkonComponentsSupportTransparency = (value==1) ? true : false;
}
}
-#endif
+#endif
+#ifdef QT_KEYPAD_NAVIGATION
if (touch) {
QApplicationPrivate::navigationMode = Qt::NavigationModeNone;
} else {
QApplicationPrivate::navigationMode = Qt::NavigationModeKeypadDirectional;
}
+#endif
#ifndef QT_NO_CURSOR
//Check if window server pointer cursors are supported or not
@@ -1384,11 +1417,13 @@ void QApplicationPrivate::leaveModal_sys(QWidget *widget)
void QApplicationPrivate::openPopup(QWidget *popup)
{
+ if (popup && qobject_cast<QComboBox *>(popup->parentWidget()))
+ static_cast<QSymbianControl *>(popup->effectiveWinId())->FadeBehindPopup(ETrue);
+
if (!QApplicationPrivate::popupWidgets)
QApplicationPrivate::popupWidgets = new QWidgetList;
QApplicationPrivate::popupWidgets->append(popup);
-
// Cancel focus widget pointer capture and long tap timer
if (QApplication::focusWidget()) {
static_cast<QSymbianControl*>(QApplication::focusWidget()->effectiveWinId())->CancelLongTapTimer();
@@ -1427,6 +1462,9 @@ void QApplicationPrivate::openPopup(QWidget *popup)
void QApplicationPrivate::closePopup(QWidget *popup)
{
+ if (popup && qobject_cast<QComboBox *>(popup->parentWidget()))
+ static_cast<QSymbianControl *>(popup->effectiveWinId())->FadeBehindPopup(EFalse);
+
if (!QApplicationPrivate::popupWidgets)
return;
QApplicationPrivate::popupWidgets->removeAll(popup);
@@ -1450,6 +1488,9 @@ void QApplicationPrivate::closePopup(QWidget *popup)
QWidget *fw = QApplicationPrivate::active_window ? QApplicationPrivate::active_window->focusWidget()
: q_func()->focusWidget();
if (fw) {
+ if(fw->window()->isModal()) // restore pointer capture for modal window
+ fw->effectiveWinId()->SetPointerCapture(true);
+
if (fw != q_func()->focusWidget()) {
fw->setFocus(Qt::PopupFocusReason);
} else {
diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp
index 131b9bb..1d8eb4c 100644
--- a/src/gui/kernel/qapplication_win.cpp
+++ b/src/gui/kernel/qapplication_win.cpp
@@ -115,6 +115,8 @@ extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.c
# include <winable.h>
#endif
+#include "private/qwinnativepangesturerecognizer_win_p.h"
+
#ifndef WM_TOUCH
# define WM_TOUCH 0x0240
@@ -439,7 +441,7 @@ extern QCursor *qt_grab_cursor();
#define __export
#endif
-extern "C" LRESULT CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
+extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
class QETWidget : public QWidget // event translator widget
{
@@ -1398,8 +1400,7 @@ static bool qt_is_translatable_mouse_event(UINT message)
;
}
-extern "C"
-LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
bool result = true;
QEvent::Type evt_type = QEvent::None;
@@ -1577,6 +1578,10 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
case WM_MBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_XBUTTONDOWN:
+ case WM_LBUTTONDBLCLK:
+ case WM_RBUTTONDBLCLK:
+ case WM_MBUTTONDBLCLK:
+ case WM_XBUTTONDBLCLK:
if (qt_win_ignoreNextMouseReleaseEvent)
qt_win_ignoreNextMouseReleaseEvent = false;
break;
@@ -2277,7 +2282,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
case WM_GETOBJECT:
{
// Ignoring all requests while starting up
- if (QApplication::startingUp() || QApplication::closingDown() || (DWORD)lParam != OBJID_CLIENT) {
+ if (QApplication::startingUp() || QApplication::closingDown() || (LONG)lParam != OBJID_CLIENT) {
result = false;
break;
}
@@ -2524,6 +2529,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
}
result = false;
break;
+#if !defined(Q_WS_WINCE) || defined(QT_WINCE_GESTURES)
case WM_GESTURE: {
GESTUREINFO gi;
memset(&gi, 0, sizeof(GESTUREINFO));
@@ -2556,6 +2562,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
result = true;
break;
}
+#endif // !defined(Q_WS_WINCE) || defined(QT_WINCE_GESTURES)
#ifndef QT_NO_CURSOR
case WM_SETCURSOR: {
QCursor *ovr = QApplication::overrideCursor();
@@ -4012,12 +4019,45 @@ void QSessionManager::cancel()
#endif //QT_NO_SESSIONMANAGER
+bool QApplicationPrivate::HasTouchSupport = false;
PtrRegisterTouchWindow QApplicationPrivate::RegisterTouchWindow = 0;
PtrGetTouchInputInfo QApplicationPrivate::GetTouchInputInfo = 0;
PtrCloseTouchInputHandle QApplicationPrivate::CloseTouchInputHandle = 0;
void QApplicationPrivate::initializeMultitouch_sys()
{
+ static const IID QT_IID_IInkTablets = {0x112086D9, 0x7779, 0x4535, {0xA6, 0x99, 0x86, 0x2B, 0x43, 0xAC, 0x18, 0x63} };
+ static const IID QT_IID_IInkTablet2 = {0x90c91ad2, 0xfa36, 0x49d6, {0x95, 0x16, 0xce, 0x8d, 0x57, 0x0f, 0x6f, 0x85} };
+ static const CLSID QT_CLSID_InkTablets = {0x6E4FCB12, 0x510A, 0x4d40, {0x93, 0x04, 0x1D, 0xA1, 0x0A, 0xE9, 0x14, 0x7C} };
+
+ IInkTablets *iInkTablets = 0;
+ HRESULT hr = CoCreateInstance(QT_CLSID_InkTablets, NULL, CLSCTX_ALL, QT_IID_IInkTablets, (void**)&iInkTablets);
+ if (SUCCEEDED(hr)) {
+ long count = 0;
+ iInkTablets->get_Count(&count);
+ for (long i = 0; i < count; ++i) {
+ IInkTablet *iInkTablet = 0;
+ hr = iInkTablets->Item(i, &iInkTablet);
+ if (FAILED(hr))
+ continue;
+ IInkTablet2 *iInkTablet2 = 0;
+ hr = iInkTablet->QueryInterface(QT_IID_IInkTablet2, (void**)&iInkTablet2);
+ iInkTablet->Release();
+ if (FAILED(hr))
+ continue;
+ TabletDeviceKind kind;
+ hr = iInkTablet2->get_DeviceKind(&kind);
+ iInkTablet2->Release();
+ if (FAILED(hr))
+ continue;
+ if (kind == TDK_Touch) {
+ QApplicationPrivate::HasTouchSupport = true;
+ break;
+ }
+ }
+ iInkTablets->Release();
+ }
+
QLibrary library(QLatin1String("user32"));
// MinGW (g++ 3.4.5) accepts only C casts.
RegisterTouchWindow = (PtrRegisterTouchWindow)(library.resolve("RegisterTouchWindow"));
diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp
index 3c2c743..78fc704 100644
--- a/src/gui/kernel/qapplication_x11.cpp
+++ b/src/gui/kernel/qapplication_x11.cpp
@@ -96,6 +96,11 @@ extern "C" {
}
#endif
+#ifndef QT_GUI_DOUBLE_CLICK_RADIUS
+#define QT_GUI_DOUBLE_CLICK_RADIUS 5
+#endif
+
+
//#define ALIEN_DEBUG
#if !defined(QT_NO_GLIB)
@@ -270,6 +275,8 @@ static const char * x11_atomnames = {
"_NET_SYSTEM_TRAY_VISUAL\0"
+ "_NET_ACTIVE_WINDOW\0"
+
// Property formats
"COMPOUND_TEXT\0"
"TEXT\0"
@@ -312,9 +319,14 @@ static const char * x11_atomnames = {
"_XEMBED\0"
"_XEMBED_INFO\0"
+ // Wacom old. (before version 0.10)
"Wacom Stylus\0"
"Wacom Cursor\0"
"Wacom Eraser\0"
+
+ // Tablet
+ "STYLUS\0"
+ "ERASER\0"
};
Q_GUI_EXPORT QX11Data *qt_x11Data = 0;
@@ -657,11 +669,6 @@ static int qt_x_errhandler(Display *dpy, XErrorEvent *err)
return 0;
break;
- case BadMatch:
- if (err->request_code == 42 /* X_SetInputFocus */)
- return 0;
- break;
-
default:
#if !defined(QT_NO_XINPUT)
if (err->request_code == X11->xinput_major
@@ -699,6 +706,10 @@ static int qt_x_errhandler(Display *dpy, XErrorEvent *err)
extensionName = "XInputExtension";
else if (err->request_code == X11->mitshm_major)
extensionName = "MIT-SHM";
+#ifndef QT_NO_XKB
+ else if(err->request_code == X11->xkb_major)
+ extensionName = "XKEYBOARD";
+#endif
char minor_str[256];
if (extensionName) {
@@ -1625,6 +1636,11 @@ void qt_init(QApplicationPrivate *priv, int,
X11->xinput_eventbase = 0;
X11->xinput_errorbase = 0;
+ X11->use_xkb = false;
+ X11->xkb_major = 0;
+ X11->xkb_eventbase = 0;
+ X11->xkb_errorbase = 0;
+
// MIT-SHM
X11->use_mitshm = false;
X11->use_mitshm_pixmaps = false;
@@ -2098,6 +2114,33 @@ void qt_init(QApplicationPrivate *priv, int,
}
#endif // QT_NO_XINPUT
+#ifndef QT_NO_XKB
+ int xkblibMajor = XkbMajorVersion;
+ int xkblibMinor = XkbMinorVersion;
+ X11->use_xkb = XkbQueryExtension(X11->display,
+ &X11->xkb_major,
+ &X11->xkb_eventbase,
+ &X11->xkb_errorbase,
+ &xkblibMajor,
+ &xkblibMinor);
+ if (X11->use_xkb) {
+ // If XKB is detected, set the GrabsUseXKBState option so input method
+ // compositions continue to work (ie. deadkeys)
+ unsigned int state = XkbPCF_GrabsUseXKBStateMask;
+ (void) XkbSetPerClientControls(X11->display, state, &state);
+
+ // select for group change events
+ XkbSelectEventDetails(X11->display,
+ XkbUseCoreKbd,
+ XkbStateNotify,
+ XkbAllStateComponentsMask,
+ XkbGroupStateMask);
+
+ // current group state is queried when creating the keymapper, no need to do it here
+ }
+#endif
+
+
#if !defined(QT_NO_FONTCONFIG)
int dpi = 0;
getXDefault("Xft", FC_DPI, &dpi);
@@ -2176,15 +2219,6 @@ void qt_init(QApplicationPrivate *priv, int,
// initialize key mapper
QKeyMapper::changeKeyboard();
-#ifndef QT_NO_XKB
- if (qt_keymapper_private()->useXKB) {
- // If XKB is detected, set the GrabsUseXKBState option so input method
- // compositions continue to work (ie. deadkeys)
- unsigned int state = XkbPCF_GrabsUseXKBStateMask;
- (void) XkbSetPerClientControls(X11->display, state, &state);
- }
-#endif // QT_NO_XKB
-
// Misc. initialization
#if 0 //disabled for now..
QSegfaultHandler::initialize(priv->argv, priv->argc);
@@ -2340,12 +2374,12 @@ void qt_init(QApplicationPrivate *priv, int,
gotStylus = true;
}
#else
- if (devs->type == ATOM(XWacomStylus)) {
+ if (devs->type == ATOM(XWacomStylus) || devs->type == ATOM(XTabletStylus)) {
deviceType = QTabletEvent::Stylus;
if (wacomDeviceName()->isEmpty())
wacomDeviceName()->append(devs->name);
gotStylus = true;
- } else if (devs->type == ATOM(XWacomEraser)) {
+ } else if (devs->type == ATOM(XWacomEraser) || devs->type == ATOM(XTabletEraser)) {
deviceType = QTabletEvent::XFreeEraser;
gotEraser = true;
}
@@ -3021,6 +3055,8 @@ int QApplication::x11ClientMessage(QWidget* w, XEvent* event, bool passive_only)
if ((ulong) event->xclient.data.l[1] > X11->time)
X11->time = event->xclient.data.l[1];
QWidget *amw = activeModalWidget();
+ if (amw && amw->testAttribute(Qt::WA_X11DoNotAcceptFocus))
+ amw = 0;
if (amw && !QApplicationPrivate::tryModalHelper(widget, 0)) {
QWidget *p = amw->parentWidget();
while (p && p != widget)
@@ -3219,6 +3255,24 @@ int QApplication::x11ProcessEvent(XEvent* event)
QKeyMapper::changeKeyboard();
return 0;
}
+#ifndef QT_NO_XKB
+ else if (X11->use_xkb && event->type == X11->xkb_eventbase) {
+ XkbAnyEvent *xkbevent = (XkbAnyEvent *) event;
+ switch (xkbevent->xkb_type) {
+ case XkbStateNotify:
+ {
+ XkbStateNotifyEvent *xkbstateevent = (XkbStateNotifyEvent *) xkbevent;
+ if ((xkbstateevent->changed & XkbGroupStateMask) != 0) {
+ qt_keymapper_private()->xkb_currentGroup = xkbstateevent->group;
+ QKeyMapper::changeKeyboard();
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+#endif
if (!widget) { // don't know this windows
QWidget* popup = QApplication::activePopupWidget();
@@ -4194,8 +4248,8 @@ bool QETWidget::translateMouseEvent(const XEvent *event)
mouseButtonPressed == button &&
(long)event->xbutton.time -(long)mouseButtonPressTime
< QApplication::doubleClickInterval() &&
- qAbs(event->xbutton.x - mouseXPos) < 5 &&
- qAbs(event->xbutton.y - mouseYPos) < 5) {
+ qAbs(event->xbutton.x - mouseXPos) < QT_GUI_DOUBLE_CLICK_RADIUS &&
+ qAbs(event->xbutton.y - mouseYPos) < QT_GUI_DOUBLE_CLICK_RADIUS) {
type = QEvent::MouseButtonDblClick;
mouseButtonPressTime -= 2000; // no double-click next time
} else {
diff --git a/src/gui/kernel/qclipboard.cpp b/src/gui/kernel/qclipboard.cpp
index a59bb98..f7c0b6e 100644
--- a/src/gui/kernel/qclipboard.cpp
+++ b/src/gui/kernel/qclipboard.cpp
@@ -107,6 +107,12 @@ QT_BEGIN_NAMESPACE
store or retrieve the clipboard contents in response to timer or
non-user-input events.
+ \i Since there is no standard way to copy and paste files between
+ applications on X11, various MIME types and conventions are currently
+ in use. For instance, Nautilus expects files to be supplied with a
+ \c{x-special/gnome-copied-files} MIME type with data beginning with
+ the cut/copy action, a newline character, and the URL of the file.
+
\endlist
\section1 Notes for Mac OS X Users
diff --git a/src/gui/kernel/qclipboard_x11.cpp b/src/gui/kernel/qclipboard_x11.cpp
index 047bd09..3bdc971 100644
--- a/src/gui/kernel/qclipboard_x11.cpp
+++ b/src/gui/kernel/qclipboard_x11.cpp
@@ -65,7 +65,6 @@
#include "qapplication.h"
#include "qdesktopwidget.h"
#include "qbitmap.h"
-#include "qdatetime.h"
#include "qiodevice.h"
#include "qbuffer.h"
#include "qtextcodec.h"
@@ -76,6 +75,7 @@
#include "qt_x11_p.h"
#include "qx11info_x11.h"
#include "qimagewriter.h"
+#include "qelapsedtimer.h"
#include "qvariant.h"
#include "qdnd_p.h"
#include <private/qwidget_p.h>
@@ -516,8 +516,9 @@ static Bool checkForClipboardEvents(Display *, XEvent *e, XPointer)
bool QX11Data::clipboardWaitForEvent(Window win, int type, XEvent *event, int timeout)
{
- QTime started = QTime::currentTime();
- QTime now = started;
+ QElapsedTimer started;
+ started.start();
+ QElapsedTimer now = started;
if (QAbstractEventDispatcher::instance()->inherits("QtMotif")
|| QApplication::clipboard()->property("useEventLoopWhenWaiting").toBool()) {
@@ -545,9 +546,7 @@ bool QX11Data::clipboardWaitForEvent(Window win, int type, XEvent *event, int ti
XSync(X11->display, false);
usleep(50000);
- now = QTime::currentTime();
- if (started > now) // crossed midnight
- started = now;
+ now.start();
QEventLoop::ProcessEventsFlags flags(QEventLoop::ExcludeUserInputEvents
| QEventLoop::ExcludeSocketNotifiers
@@ -576,9 +575,7 @@ bool QX11Data::clipboardWaitForEvent(Window win, int type, XEvent *event, int ti
if (XCheckIfEvent(X11->display, &e, checkForClipboardEvents, 0))
qApp->x11ProcessEvent(&e);
- now = QTime::currentTime();
- if ( started > now ) // crossed midnight
- started = now;
+ now.start();
XFlush(X11->display);
diff --git a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm
index ab71a05..5dcf613 100644
--- a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm
+++ b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm
@@ -179,7 +179,7 @@ static void cleanupCocoaApplicationDelegate()
}
// This function will only be called when NSApp is actually running. Before
-// that, the kAEQuitApplication apple event will be sendt to
+// that, the kAEQuitApplication Apple event will be sent to
// QApplicationPrivate::globalAppleEventProcessor in qapplication_mac.mm
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
@@ -196,21 +196,18 @@ static void cleanupCocoaApplicationDelegate()
qAppInstance()->quit();
startedQuit = false;
}
+ return NSTerminateNow;
}
if (qtPrivate->threadData->eventLoops.size() == 0) {
// INVARIANT: No event loop is executing. This probably
// means that Qt is used as a plugin, or as a part of a native
- // Cocoa application. In any case it should be fine to
+ // Cocoa application. In any case it should be fine to
// terminate now:
return NSTerminateNow;
- } else {
- // Prevent Cocoa from terminating the application, since this simply
- // exits the program whithout allowing QApplication::exec() to return.
- // The call to QApplication::quit() above will instead quit the
- // application from the Qt side.
- return NSTerminateCancel;
}
+
+ return NSTerminateCancel;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
diff --git a/src/gui/kernel/qcocoamenuloader_mac.mm b/src/gui/kernel/qcocoamenuloader_mac.mm
index 573b763..b58fd7c 100644
--- a/src/gui/kernel/qcocoamenuloader_mac.mm
+++ b/src/gui/kernel/qcocoamenuloader_mac.mm
@@ -48,6 +48,7 @@
#include <private/qt_mac_p.h>
#include <private/qmenubar_p.h>
#include <qmenubar.h>
+#include <private/qt_cocoa_helpers_mac_p.h>
QT_FORWARD_DECLARE_CLASS(QCFString)
QT_FORWARD_DECLARE_CLASS(QString)
@@ -58,6 +59,10 @@ QT_USE_NAMESPACE
- (void)awakeFromNib
{
+ servicesItem = [[appMenu itemWithTitle:@"Services"] retain];
+ hideAllOthersItem = [[appMenu itemWithTitle:@"Hide Others"] retain];
+ showAllItem = [[appMenu itemWithTitle:@"Show All"] retain];
+
// Get the names in the nib to match the app name set by Qt.
NSString *appName = reinterpret_cast<const NSString*>(QCFString::toCFStringRef(qAppName()));
[quitItem setTitle:[[quitItem title] stringByReplacingOccurrencesOfString:@"NewApplication"
@@ -119,6 +124,10 @@ QT_USE_NAMESPACE
- (void)dealloc
{
+ [servicesItem release];
+ [hideAllOthersItem release];
+ [showAllItem release];
+
[lastAppSpecificItem release];
[theMenu release];
[appMenu release];
@@ -214,6 +223,20 @@ QT_USE_NAMESPACE
QMenuBarPrivate::macUpdateMenuBarImmediatly();
}
+- (void)qtTranslateApplicationMenu
+{
+#ifndef QT_NO_TRANSLATION
+ extern QString qt_mac_applicationmenu_string(int type);
+ [servicesItem setTitle: qt_mac_QStringToNSString(qt_mac_applicationmenu_string(0))];
+ [hideItem setTitle: qt_mac_QStringToNSString(qt_mac_applicationmenu_string(1).arg(qAppName()))];
+ [hideAllOthersItem setTitle: qt_mac_QStringToNSString(qt_mac_applicationmenu_string(2))];
+ [showAllItem setTitle: qt_mac_QStringToNSString(qt_mac_applicationmenu_string(3))];
+ [preferencesItem setTitle: qt_mac_QStringToNSString(qt_mac_applicationmenu_string(4))];
+ [quitItem setTitle: qt_mac_QStringToNSString(qt_mac_applicationmenu_string(5).arg(qAppName()))];
+ [aboutItem setTitle: qt_mac_QStringToNSString(qt_mac_applicationmenu_string(6).arg(qAppName()))];
+#endif
+}
+
- (IBAction)qtDispatcherToQAction:(id)sender
{
QScopedLoopLevelCounter loopLevelCounter(QApplicationPrivate::instance()->threadData);
diff --git a/src/gui/kernel/qcocoamenuloader_mac_p.h b/src/gui/kernel/qcocoamenuloader_mac_p.h
index 2504b8c..a75ad0a 100644
--- a/src/gui/kernel/qcocoamenuloader_mac_p.h
+++ b/src/gui/kernel/qcocoamenuloader_mac_p.h
@@ -67,7 +67,9 @@
IBOutlet NSMenuItem *aboutQtItem;
IBOutlet NSMenuItem *hideItem;
NSMenuItem *lastAppSpecificItem;
-
+ NSMenuItem *servicesItem;
+ NSMenuItem *hideAllOthersItem;
+ NSMenuItem *showAllItem;
}
- (void)ensureAppMenuInMenu:(NSMenu *)menu;
- (void)removeActionsFromAppMenu;
diff --git a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h
index 9fe5ae0..129e0a5 100644
--- a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h
+++ b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h
@@ -132,26 +132,6 @@ QT_END_NAMESPACE
[super toggleToolbarShown:sender];
}
-/*
- The methods keyDown, keyUp, and flagsChanged... These really shouldn't ever
- get hit. We automatically say we can be first responder if we are a window.
- So, the handling should get handled by the view. This is here more as a
- last resort (i.e., this is code that can potentially be removed).
- */
-- (void)keyDown:(NSEvent *)theEvent
-{
- bool keyOK = qt_dispatchKeyEvent(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]);
- if (!keyOK)
- [super keyDown:theEvent];
-}
-
-- (void)keyUp:(NSEvent *)theEvent
-{
- bool keyOK = qt_dispatchKeyEvent(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]);
- if (!keyOK)
- [super keyUp:theEvent];
-}
-
- (void)flagsChanged:(NSEvent *)theEvent
{
qt_dispatchModifiersChanged(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]);
diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm
index 6a16403..06eb7ff 100644
--- a/src/gui/kernel/qcocoaview_mac.mm
+++ b/src/gui/kernel/qcocoaview_mac.mm
@@ -185,6 +185,9 @@ extern "C" {
extern NSString *NSTextInputReplacementRangeAttributeName;
}
+#ifdef ALIEN_DEBUG
+static int qCocoaViewCount = 0;
+#endif
@implementation QT_MANGLE_NAMESPACE(QCocoaView)
@@ -194,7 +197,14 @@ extern "C" {
if (self) {
[self finishInitWithQWidget:widget widgetPrivate:widgetprivate];
}
+ [self setFocusRingType:NSFocusRingTypeNone];
composingText = new QString();
+
+#ifdef ALIEN_DEBUG
+ ++qCocoaViewCount;
+ qDebug() << "init: qCocoaViewCount is" << qCocoaViewCount;
+#endif
+
composing = false;
sendKeyEvents = true;
[self setHidden:YES];
@@ -232,7 +242,8 @@ extern "C" {
QRegion mask = qt_widget_private(cursorWidget)->extra->mask;
NSCursor *nscursor = static_cast<NSCursor *>(qt_mac_nsCursorForQCursor(cursorWidget->cursor()));
- if (mask.isEmpty()) {
+ // The mask could have the WA_MouseNoMask attribute set and that means that we have to ignore the mask.
+ if (mask.isEmpty() || cursorWidget->testAttribute(Qt::WA_MouseNoMask)) {
[self addCursorRect:[qt_mac_nativeview_for(cursorWidget) visibleRect] cursor:nscursor];
} else {
const QVector<QRect> &rects = mask.rects();
@@ -414,6 +425,12 @@ extern "C" {
{
delete composingText;
[[NSNotificationCenter defaultCenter] removeObserver:self];
+
+#ifdef ALIEN_DEBUG
+ --qCocoaViewCount;
+ qDebug() << "qCocoaViewCount is" << qCocoaViewCount;
+#endif
+
[super dealloc];
}
@@ -429,7 +446,11 @@ extern "C" {
return YES;
}
-- (BOOL) preservesContentDuringLiveResize;
+// We preserve the content of the view if WA_StaticContents is defined.
+//
+// More info in the Cocoa documentation:
+// http://developer.apple.com/mac/library/documentation/cocoa/conceptual/CocoaViewsGuide/Optimizing/Optimizing.html
+- (BOOL) preservesContentDuringLiveResize
{
return qwidget->testAttribute(Qt::WA_StaticContents);
}
@@ -459,13 +480,25 @@ extern "C" {
}
}
+// We catch the 'setNeedsDisplay:' message in order to avoid a useless full repaint.
+// During the resize, the top of the widget is repainted, probably because of the
+// change of coordinate space (Quartz vs Qt). This is then followed by this message:
+// -[NSView _setNeedsDisplayIfTopLeftChanged]
+// which force a full repaint by sending the message 'setNeedsDisplay:'.
+// That is what we are preventing here.
+- (void)setNeedsDisplay:(BOOL)flag {
+ if (![self inLiveResize] || !(qwidget->testAttribute(Qt::WA_StaticContents))) {
+ [super setNeedsDisplay:flag];
+ }
+}
+
- (void)drawRect:(NSRect)aRect
{
if (!qwidget)
return;
if (QApplicationPrivate::graphicsSystem() != 0) {
- if (QWidgetBackingStore *bs = qwidgetprivate->maybeBackingStore()) {
+ if (qwidgetprivate->maybeBackingStore()) {
// Drawing is handled on the window level
// See qcocoasharedwindowmethods_mac_p.h
if (!qwidget->testAttribute(Qt::WA_PaintOnScreen))
@@ -523,6 +556,10 @@ extern "C" {
CGContextClearRect(cg, NSRectToCGRect(aRect));
}
+ // Check for alien widgets, use qwidgetPrivate->drawWidget() to draw the widget if this
+ // is the case. This makes sure child widgets are drawn as well, Cocoa does not know about
+ // those and wont send them drawRect calls.
+ if (qwidget->testAttribute(Qt::WA_NativeWindow) && qt_widget_private(qwidget)->hasAlienChildren == false) {
if (engine && !qwidget->testAttribute(Qt::WA_NoSystemBackground)
&& (qwidget->isWindow() || qwidget->autoFillBackground())
|| qwidget->testAttribute(Qt::WA_TintedBackground)
@@ -542,6 +579,12 @@ extern "C" {
e.setErased(true);
#endif
qt_sendSpontaneousEvent(qwidget, &e);
+ } else {
+ qwidget->setAttribute(Qt::WA_WState_InPaintEvent, false); // QWidgetPrivate::drawWidget sets this
+ QWidgetPrivate *qwidgetPrivate = qt_widget_private(qwidget);
+ qwidgetPrivate->drawWidget(qwidget, qrgn, QPoint(), QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawPaintOnScreen | QWidgetPrivate::DrawRecursive, 0);
+ }
+
if (!redirectionOffset.isNull())
QPainter::restoreRedirected(qwidget);
if (engine)
@@ -794,11 +837,12 @@ extern "C" {
// The mouse device containts pixel scroll wheel support (Mighty Mouse, Trackpad).
// Since deviceDelta is delivered as pixels rather than degrees, we need to
// convert from pixels to degrees in a sensible manner.
- // It looks like four degrees per pixel behaves most native.
- // Qt expects the unit for delta to be 1/8 of a degree:
- deltaX = [theEvent deviceDeltaX];
- deltaY = [theEvent deviceDeltaY];
- deltaZ = [theEvent deviceDeltaZ];
+ // It looks like 1/4 degrees per pixel behaves most native.
+ // (NB: Qt expects the unit for delta to be 8 per degree):
+ const int pixelsToDegrees = 2; // 8 * 1/4
+ deltaX = [theEvent deviceDeltaX] * pixelsToDegrees;
+ deltaY = [theEvent deviceDeltaY] * pixelsToDegrees;
+ deltaZ = [theEvent deviceDeltaZ] * pixelsToDegrees;
} else {
// carbonEventKind == kEventMouseWheelMoved
// Remove acceleration, and use either -120 or 120 as delta:
@@ -1003,8 +1047,16 @@ extern "C" {
{
if (!qwidget)
return NO;
- if (qwidget->isWindow())
+ // disabled widget shouldn't get focus even if it's a window.
+ // hence disabled windows will not get any key or mouse events.
+ if (!qwidget->isEnabled())
+ return NO;
+ // Before accepting the focus for a window, we check that
+ // the focusWidget (if any) is not contained in the same window.
+ if (qwidget->isWindow() && !qt_widget_private(qwidget)->topData()->embedded
+ && (!qApp->focusWidget() || qApp->focusWidget()->window() != qwidget)) {
return YES; // Always do it, so that windows can accept key press events.
+ }
return qwidget->focusPolicy() != Qt::NoFocus;
}
@@ -1015,7 +1067,17 @@ extern "C" {
// Seems like the following test only triggers if this
// view is inside a QMacNativeWidget:
if (qwidget == QApplication::focusWidget())
- QApplicationPrivate::setFocusWidget(0, Qt::OtherFocusReason);
+ qwidget->clearFocus();
+ return YES;
+}
+
+- (BOOL)becomeFirstResponder
+{
+ // see the comment in the acceptsFirstResponder - if the window "stole" focus
+ // let it become the responder, but don't tell Qt
+ if (qwidget && qt_widget_private(qwidget->window())->topData()->embedded
+ && !QApplication::focusWidget() && qwidget->focusPolicy() != Qt::NoFocus)
+ qwidget->setFocus(Qt::OtherFocusReason);
return YES;
}
@@ -1089,8 +1151,15 @@ extern "C" {
}
if (sendKeyEvents && !composing) {
bool keyOK = qt_dispatchKeyEvent(theEvent, widgetToGetKey);
- if (!keyOK && !sendToPopup)
- [super keyDown:theEvent];
+ if (!keyOK && !sendToPopup) {
+ // find the first responder that is not created by Qt and forward
+ // the event to it (for example if Qt widget is embedded into native).
+ QWidget *toplevel = qwidget->window();
+ if (toplevel && qt_widget_private(toplevel)->topData()->embedded) {
+ if (NSResponder *w = [qt_mac_nativeview_for(toplevel) superview])
+ [w keyDown:theEvent];
+ }
+ }
}
}
@@ -1099,8 +1168,13 @@ extern "C" {
{
if (sendKeyEvents) {
bool keyOK = qt_dispatchKeyEvent(theEvent, qwidget);
- if (!keyOK)
- [super keyUp:theEvent];
+ if (!keyOK) {
+ QWidget *toplevel = qwidget->window();
+ if (toplevel && qt_widget_private(toplevel)->topData()->embedded) {
+ if (NSResponder *w = [qt_mac_nativeview_for(toplevel) superview])
+ [w keyUp:theEvent];
+ }
+ }
}
}
diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp
index f38e4f5..ae1f60d 100644
--- a/src/gui/kernel/qcursor.cpp
+++ b/src/gui/kernel/qcursor.cpp
@@ -348,7 +348,8 @@ QCursor::QCursor(const QPixmap &pixmap, int hotX, int hotY)
\o B=1 and M=1 gives black.
\o B=0 and M=1 gives white.
\o B=0 and M=0 gives transparent.
- \o B=1 and M=0 gives an XOR'd result.
+ \o B=1 and M=0 gives an XOR'd result under Windows, undefined
+ results on all other platforms.
\endlist
Use the global Qt color Qt::color0 to draw 0-pixels and Qt::color1 to
diff --git a/src/gui/kernel/qcursor_mac.mm b/src/gui/kernel/qcursor_mac.mm
index cfebf60..03e38b0 100644
--- a/src/gui/kernel/qcursor_mac.mm
+++ b/src/gui/kernel/qcursor_mac.mm
@@ -114,27 +114,18 @@ void qt_mac_set_cursor(const QCursor *c, const QPoint &)
}
c->handle(); //force the cursor to get loaded, if it's not
- if(1 || currentCursor != c->d) {
- if(currentCursor && currentCursor->type == QCursorData::TYPE_ThemeCursor
- && currentCursor->curs.tc.anim)
- currentCursor->curs.tc.anim->stop();
- QMacCocoaAutoReleasePool pool;
- if(c->d->type == QCursorData::TYPE_ImageCursor) {
- [static_cast<NSCursor *>(c->d->curs.cp.nscursor) set];
- } else if(c->d->type == QCursorData::TYPE_ThemeCursor) {
-#ifdef QT_MAC_USE_COCOA
- if (c->d->curs.cp.nscursor == 0)
- [[NSCursor arrowCursor] set];
- [static_cast<NSCursor *>(c->d->curs.cp.nscursor) set];
-#else
- if(SetAnimatedThemeCursor(c->d->curs.tc.curs, 0) == themeBadCursorIndexErr) {
- SetThemeCursor(c->d->curs.tc.curs);
- } else {
- if(!c->d->curs.tc.anim)
- c->d->curs.tc.anim = new QMacAnimateCursor;
- c->d->curs.tc.anim->start(c->d->curs.tc.curs);
- }
-#endif
+ if(currentCursor && currentCursor->type == QCursorData::TYPE_ThemeCursor
+ && currentCursor->curs.tc.anim)
+ currentCursor->curs.tc.anim->stop();
+ if(c->d->type == QCursorData::TYPE_ImageCursor) {
+ [static_cast<NSCursor *>(c->d->curs.cp.nscursor) set];
+ } else if(c->d->type == QCursorData::TYPE_ThemeCursor) {
+ if(SetAnimatedThemeCursor(c->d->curs.tc.curs, 0) == themeBadCursorIndexErr) {
+ SetThemeCursor(c->d->curs.tc.curs);
+ } else {
+ if(!c->d->curs.tc.anim)
+ c->d->curs.tc.anim = new QMacAnimateCursor;
+ c->d->curs.tc.anim->start(c->d->curs.tc.curs);
}
}
currentCursor = c->d;
diff --git a/src/gui/kernel/qcursor_s60.cpp b/src/gui/kernel/qcursor_s60.cpp
index 54a9176..68e079e 100644
--- a/src/gui/kernel/qcursor_s60.cpp
+++ b/src/gui/kernel/qcursor_s60.cpp
@@ -44,7 +44,7 @@
#include <private/qapplication_p.h>
#include <coecntrl.h>
#include <qcursor.h>
-#include <qt_s60_p.h>
+#include <private/qt_s60_p.h>
#include <qbitmap.h>
#include <w32std.h>
#include <qapplication.h>
diff --git a/src/gui/kernel/qcursor_x11.cpp b/src/gui/kernel/qcursor_x11.cpp
index 4e871a6..8e48628 100644
--- a/src/gui/kernel/qcursor_x11.cpp
+++ b/src/gui/kernel/qcursor_x11.cpp
@@ -294,7 +294,7 @@ void QCursorData::update()
return;
#endif // QT_NO_XCURSOR
- static const char cur_blank_bits[] = {
+ static const uchar cur_blank_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
@@ -302,44 +302,44 @@ void QCursorData::update()
// Non-standard X11 cursors are created from bitmaps
#ifndef QT_USE_APPROXIMATE_CURSORS
- static const char cur_ver_bits[] = {
+ static const uchar cur_ver_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f,
0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xf0, 0x0f,
0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00 };
- static const char mcur_ver_bits[] = {
+ static const uchar mcur_ver_bits[] = {
0x00, 0x00, 0x80, 0x03, 0xc0, 0x07, 0xe0, 0x0f, 0xf0, 0x1f, 0xf8, 0x3f,
0xfc, 0x7f, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xfc, 0x7f, 0xf8, 0x3f,
0xf0, 0x1f, 0xe0, 0x0f, 0xc0, 0x07, 0x80, 0x03 };
- static const char cur_hor_bits[] = {
+ static const uchar cur_hor_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x30, 0x18,
0x38, 0x38, 0xfc, 0x7f, 0xfc, 0x7f, 0x38, 0x38, 0x30, 0x18, 0x20, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- static const char mcur_hor_bits[] = {
+ static const uchar mcur_hor_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x40, 0x04, 0x60, 0x0c, 0x70, 0x1c, 0x78, 0x3c,
0xfc, 0x7f, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfc, 0x7f, 0x78, 0x3c,
0x70, 0x1c, 0x60, 0x0c, 0x40, 0x04, 0x00, 0x00 };
- static const char cur_bdiag_bits[] = {
+ static const uchar cur_bdiag_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x3c, 0x00, 0x3e,
0x00, 0x37, 0x88, 0x23, 0xd8, 0x01, 0xf8, 0x00, 0x78, 0x00, 0xf8, 0x00,
0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- static const char mcur_bdiag_bits[] = {
+ static const uchar mcur_bdiag_bits[] = {
0x00, 0x00, 0xc0, 0x7f, 0x80, 0x7f, 0x00, 0x7f, 0x00, 0x7e, 0x04, 0x7f,
0x8c, 0x7f, 0xdc, 0x77, 0xfc, 0x63, 0xfc, 0x41, 0xfc, 0x00, 0xfc, 0x01,
0xfc, 0x03, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00 };
- static const char cur_fdiag_bits[] = {
+ static const uchar cur_fdiag_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00,
0xf8, 0x00, 0xd8, 0x01, 0x88, 0x23, 0x00, 0x37, 0x00, 0x3e, 0x00, 0x3c,
0x00, 0x3e, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00 };
- static const char mcur_fdiag_bits[] = {
+ static const uchar mcur_fdiag_bits[] = {
0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xfc, 0x03, 0xfc, 0x01, 0xfc, 0x00,
0xfc, 0x41, 0xfc, 0x63, 0xdc, 0x77, 0x8c, 0x7f, 0x04, 0x7f, 0x00, 0x7e,
0x00, 0x7f, 0x80, 0x7f, 0xc0, 0x7f, 0x00, 0x00 };
- static const char *cursor_bits16[] = {
+ static const uchar *cursor_bits16[] = {
cur_ver_bits, mcur_ver_bits, cur_hor_bits, mcur_hor_bits,
cur_bdiag_bits, mcur_bdiag_bits, cur_fdiag_bits, mcur_fdiag_bits,
0, 0, cur_blank_bits, cur_blank_bits };
- static const char vsplit_bits[] = {
+ static const uchar vsplit_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00,
@@ -351,7 +351,7 @@ void QCursorData::update()
0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- static const char vsplitm_bits[] = {
+ static const uchar vsplitm_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xf0, 0x07, 0x00,
@@ -363,7 +363,7 @@ void QCursorData::update()
0x00, 0xe0, 0x03, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- static const char hsplit_bits[] = {
+ static const uchar hsplit_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00,
@@ -375,7 +375,7 @@ void QCursorData::update()
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- static const char hsplitm_bits[] = {
+ static const uchar hsplitm_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
@@ -387,7 +387,7 @@ void QCursorData::update()
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- static const char whatsthis_bits[] = {
+ static const uchar whatsthis_bits[] = {
0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0xf0, 0x07, 0x00,
0x09, 0x18, 0x0e, 0x00, 0x11, 0x1c, 0x0e, 0x00, 0x21, 0x1c, 0x0e, 0x00,
0x41, 0x1c, 0x0e, 0x00, 0x81, 0x1c, 0x0e, 0x00, 0x01, 0x01, 0x07, 0x00,
@@ -399,7 +399,7 @@ void QCursorData::update()
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
- static const char whatsthism_bits[] = {
+ static const uchar whatsthism_bits[] = {
0x01, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x07, 0x00, 0x07, 0xf8, 0x0f, 0x00,
0x0f, 0xfc, 0x1f, 0x00, 0x1f, 0x3e, 0x1f, 0x00, 0x3f, 0x3e, 0x1f, 0x00,
0x7f, 0x3e, 0x1f, 0x00, 0xff, 0x3e, 0x1f, 0x00, 0xff, 0x9d, 0x0f, 0x00,
@@ -411,7 +411,7 @@ void QCursorData::update()
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
- static const char busy_bits[] = {
+ static const uchar busy_bits[] = {
0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
0x41, 0xe0, 0xff, 0x00, 0x81, 0x20, 0x80, 0x00, 0x01, 0xe1, 0xff, 0x00,
@@ -423,7 +423,7 @@ void QCursorData::update()
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
- static const char busym_bits[] = {
+ static const uchar busym_bits[] = {
0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x0f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
0x7f, 0xe0, 0xff, 0x00, 0xff, 0xe0, 0xff, 0x00, 0xff, 0xe1, 0xff, 0x00,
@@ -436,41 +436,41 @@ void QCursorData::update()
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
- static const char * const cursor_bits32[] = {
+ static const uchar * const cursor_bits32[] = {
vsplit_bits, vsplitm_bits, hsplit_bits, hsplitm_bits,
0, 0, 0, 0, whatsthis_bits, whatsthism_bits, busy_bits, busym_bits
};
- static const char forbidden_bits[] = {
+ static const uchar forbidden_bits[] = {
0x00,0x00,0x00,0x80,0x1f,0x00,0xe0,0x7f,0x00,0xf0,0xf0,0x00,0x38,0xc0,0x01,
0x7c,0x80,0x03,0xec,0x00,0x03,0xce,0x01,0x07,0x86,0x03,0x06,0x06,0x07,0x06,
0x06,0x0e,0x06,0x06,0x1c,0x06,0x0e,0x38,0x07,0x0c,0x70,0x03,0x1c,0xe0,0x03,
0x38,0xc0,0x01,0xf0,0xe0,0x00,0xe0,0x7f,0x00,0x80,0x1f,0x00,0x00,0x00,0x00 };
- static const char forbiddenm_bits[] = {
+ static const uchar forbiddenm_bits[] = {
0x80,0x1f,0x00,0xe0,0x7f,0x00,0xf0,0xff,0x00,0xf8,0xff,0x01,0xfc,0xf0,0x03,
0xfe,0xc0,0x07,0xfe,0x81,0x07,0xff,0x83,0x0f,0xcf,0x07,0x0f,0x8f,0x0f,0x0f,
0x0f,0x1f,0x0f,0x0f,0x3e,0x0f,0x1f,0xfc,0x0f,0x1e,0xf8,0x07,0x3e,0xf0,0x07,
0xfc,0xe0,0x03,0xf8,0xff,0x01,0xf0,0xff,0x00,0xe0,0x7f,0x00,0x80,0x1f,0x00};
- static const char openhand_bits[] = {
+ static const uchar openhand_bits[] = {
0x80,0x01,0x58,0x0e,0x64,0x12,0x64,0x52,0x48,0xb2,0x48,0x92,
0x16,0x90,0x19,0x80,0x11,0x40,0x02,0x40,0x04,0x40,0x04,0x20,
0x08,0x20,0x10,0x10,0x20,0x10,0x00,0x00};
- static const char openhandm_bits[] = {
+ static const uchar openhandm_bits[] = {
0x80,0x01,0xd8,0x0f,0xfc,0x1f,0xfc,0x5f,0xf8,0xff,0xf8,0xff,
0xf6,0xff,0xff,0xff,0xff,0x7f,0xfe,0x7f,0xfc,0x7f,0xfc,0x3f,
0xf8,0x3f,0xf0,0x1f,0xe0,0x1f,0x00,0x00};
- static const char closedhand_bits[] = {
+ static const uchar closedhand_bits[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x0d,0x48,0x32,0x08,0x50,
0x10,0x40,0x18,0x40,0x04,0x40,0x04,0x20,0x08,0x20,0x10,0x10,
0x20,0x10,0x20,0x10,0x00,0x00,0x00,0x00};
- static const char closedhandm_bits[] = {
+ static const uchar closedhandm_bits[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x0d,0xf8,0x3f,0xf8,0x7f,
0xf0,0x7f,0xf8,0x7f,0xfc,0x7f,0xfc,0x3f,0xf8,0x3f,0xf0,0x1f,
0xe0,0x1f,0xe0,0x1f,0x00,0x00,0x00,0x00};
- static const char * const cursor_bits20[] = {
+ static const uchar * const cursor_bits20[] = {
forbidden_bits, forbiddenm_bits
};
@@ -484,8 +484,8 @@ void QCursorData::update()
fg.green = 0;
fg.blue = 0;
int i = (cshape - Qt::SizeVerCursor) * 2;
- pm = XCreateBitmapFromData(dpy, rootwin, cursor_bits16[i], 16, 16);
- pmm = XCreateBitmapFromData(dpy, rootwin, cursor_bits16[i + 1], 16, 16);
+ pm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char*>(cursor_bits16[i]), 16, 16);
+ pmm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char*>(cursor_bits16[i + 1]), 16, 16);
hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, 8, 8);
} else if ((cshape >= Qt::SplitVCursor && cshape <= Qt::SplitHCursor)
|| cshape == Qt::WhatsThisCursor || cshape == Qt::BusyCursor) {
@@ -497,8 +497,8 @@ void QCursorData::update()
fg.green = 0;
fg.blue = 0;
int i = (cshape - Qt::SplitVCursor) * 2;
- pm = XCreateBitmapFromData(dpy, rootwin, cursor_bits32[i], 32, 32);
- pmm = XCreateBitmapFromData(dpy, rootwin, cursor_bits32[i + 1], 32, 32);
+ pm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char *>(cursor_bits32[i]), 32, 32);
+ pmm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char *>(cursor_bits32[i + 1]), 32, 32);
int hs = (cshape == Qt::PointingHandCursor || cshape == Qt::WhatsThisCursor
|| cshape == Qt::BusyCursor) ? 0 : 16;
hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, hs, hs);
@@ -511,8 +511,8 @@ void QCursorData::update()
fg.green = 0;
fg.blue = 0;
int i = (cshape - Qt::ForbiddenCursor) * 2;
- pm = XCreateBitmapFromData(dpy, rootwin, cursor_bits20[i], 20, 20);
- pmm = XCreateBitmapFromData(dpy, rootwin, cursor_bits20[i + 1], 20, 20);
+ pm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char *>(cursor_bits20[i]), 20, 20);
+ pmm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char *>(cursor_bits20[i + 1]), 20, 20);
hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, 10, 10);
} else if (cshape == Qt::OpenHandCursor || cshape == Qt::ClosedHandCursor) {
XColor bg, fg;
@@ -523,8 +523,8 @@ void QCursorData::update()
fg.green = 0;
fg.blue = 0;
bool open = cshape == Qt::OpenHandCursor;
- pm = XCreateBitmapFromData(dpy, rootwin, open ? openhand_bits : closedhand_bits, 16, 16);
- pmm = XCreateBitmapFromData(dpy, rootwin, open ? openhandm_bits : closedhandm_bits, 16, 16);
+ pm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char *>(open ? openhand_bits : closedhand_bits), 16, 16);
+ pmm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char *>(open ? openhandm_bits : closedhandm_bits), 16, 16);
hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, 8, 8);
} else if (cshape == Qt::DragCopyCursor || cshape == Qt::DragMoveCursor
|| cshape == Qt::DragLinkCursor) {
diff --git a/src/gui/kernel/qdesktopwidget_s60.cpp b/src/gui/kernel/qdesktopwidget_s60.cpp
index 84e3c5d..e4d0bf3 100644
--- a/src/gui/kernel/qdesktopwidget_s60.cpp
+++ b/src/gui/kernel/qdesktopwidget_s60.cpp
@@ -88,6 +88,7 @@ QDesktopWidgetPrivate::~QDesktopWidgetPrivate()
void QDesktopWidgetPrivate::init(QDesktopWidget *that)
{
+ Q_UNUSED(that);
// int screenCount=0;
// ### TODO: Implement proper multi-display support
diff --git a/src/gui/kernel/qdesktopwidget_win.cpp b/src/gui/kernel/qdesktopwidget_win.cpp
index 1fea8d6..07dbc24 100644
--- a/src/gui/kernel/qdesktopwidget_win.cpp
+++ b/src/gui/kernel/qdesktopwidget_win.cpp
@@ -76,7 +76,7 @@ public:
};
typedef BOOL (WINAPI *InfoFunc)(HMONITOR, MONITORINFO*);
- typedef BOOL (CALLBACK *EnumProc)(HMONITOR, HDC, LPRECT, LPARAM);
+ typedef BOOL (QT_WIN_CALLBACK *EnumProc)(HMONITOR, HDC, LPRECT, LPARAM);
typedef BOOL (WINAPI *EnumFunc)(HDC, LPCRECT, EnumProc, LPARAM);
static EnumFunc enumDisplayMonitors;
@@ -107,7 +107,7 @@ static inline void qt_get_sip_info(QRect &rect)
#endif
-BOOL CALLBACK enumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM)
+BOOL QT_WIN_CALLBACK enumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM)
{
QDesktopWidgetPrivate::screenCount++;
QDesktopWidgetPrivate::rects->resize(QDesktopWidgetPrivate::screenCount);
diff --git a/src/gui/kernel/qdnd_win.cpp b/src/gui/kernel/qdnd_win.cpp
index 0742a93..a164c2a 100644
--- a/src/gui/kernel/qdnd_win.cpp
+++ b/src/gui/kernel/qdnd_win.cpp
@@ -524,18 +524,14 @@ QOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
if (fEscapePressed) {
return ResultFromScode(DRAGDROP_S_CANCEL);
- } else if (!(grfKeyState & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))) {
+ } else if ((GetAsyncKeyState(VK_LBUTTON) == 0)
+ && (GetAsyncKeyState(VK_MBUTTON) == 0)
+ && (GetAsyncKeyState(VK_RBUTTON) == 0)) {
+ // grfKeyState is broken on CE & some Windows XP versions,
+ // therefore we need to check the state manually
return ResultFromScode(DRAGDROP_S_DROP);
} else {
-#if defined(Q_OS_WINCE)
- // grfKeyState is broken on CE, therefore need to check
- // the state manually
- if ((GetAsyncKeyState(VK_LBUTTON) == 0) &&
- (GetAsyncKeyState(VK_MBUTTON) == 0) &&
- (GetAsyncKeyState(VK_RBUTTON) == 0)) {
- return ResultFromScode(DRAGDROP_S_DROP);
- }
-#else
+#if !defined(Q_OS_WINCE)
if (currentButtons == Qt::NoButton) {
currentButtons = keystate_to_mousebutton(grfKeyState);
} else {
diff --git a/src/gui/kernel/qdnd_x11.cpp b/src/gui/kernel/qdnd_x11.cpp
index 9591b9a..0a05d8e 100644
--- a/src/gui/kernel/qdnd_x11.cpp
+++ b/src/gui/kernel/qdnd_x11.cpp
@@ -51,10 +51,10 @@
#include "qbitmap.h"
#include "qdesktopwidget.h"
#include "qevent.h"
-#include "qdatetime.h"
#include "qiodevice.h"
#include "qpointer.h"
#include "qcursor.h"
+#include "qelapsedtimer.h"
#include "qvariant.h"
#include "qvector.h"
#include "qurl.h"
@@ -1911,23 +1911,19 @@ Qt::DropAction QDragManager::drag(QDrag * o)
// then we could still have problems, but this is highly unlikely
QApplication::flush();
- QTime started = QTime::currentTime();
- QTime now = started;
+ QElapsedTimer timer;
+ timer.start();
do {
XEvent event;
if (XCheckTypedEvent(X11->display, ClientMessage, &event))
qApp->x11ProcessEvent(&event);
- now = QTime::currentTime();
- if (started > now) // crossed midnight
- started = now;
-
// sleep 50 ms, so we don't use up CPU cycles all the time.
struct timeval usleep_tv;
usleep_tv.tv_sec = 0;
usleep_tv.tv_usec = 50000;
select(0, 0, 0, 0, &usleep_tv);
- } while (object && started.msecsTo(now) < 1000);
+ } while (object && timer.hasExpired(1000));
}
object = o;
diff --git a/src/gui/kernel/qeventdispatcher_mac.mm b/src/gui/kernel/qeventdispatcher_mac.mm
index afea3ec..a7f1224 100644
--- a/src/gui/kernel/qeventdispatcher_mac.mm
+++ b/src/gui/kernel/qeventdispatcher_mac.mm
@@ -829,7 +829,16 @@ NSModalSession QEventDispatcherMacPrivate::currentModalSession()
ensureNSAppInitialized();
QBoolBlocker block1(blockSendPostedEvents, true);
- info.session = [NSApp beginModalSessionForWindow:window];
+ info.nswindow = window;
+ [(NSWindow*) info.nswindow retain];
+ // When creating a modal session cocoa will rearrange the windows.
+ // In order to avoid windows to be put behind another we need to
+ // keep the window level.
+ {
+ int level = [window level];
+ info.session = [NSApp beginModalSessionForWindow:window];
+ [window setLevel:level];
+ }
}
currentModalSessionCached = info.session;
}
@@ -903,8 +912,10 @@ void QEventDispatcherMacPrivate::cleanupModalSessions()
}
cocoaModalSessionStack.remove(i);
currentModalSessionCached = 0;
- if (info.session)
+ if (info.session) {
[NSApp endModalSession:info.session];
+ [(NSWindow *)info.nswindow release];
+ }
}
updateChildrenWorksWhenModal();
@@ -920,7 +931,7 @@ void QEventDispatcherMacPrivate::beginModalSession(QWidget *widget)
// currentModalSession). A QCocoaModalSessionInfo is considered pending to be stopped if
// the widget pointer is zero, and the session pointer is non-zero (it will be fully
// stopped in cleanupModalSessions()).
- QCocoaModalSessionInfo info = {widget, 0};
+ QCocoaModalSessionInfo info = {widget, 0, 0};
cocoaModalSessionStack.push(info);
updateChildrenWorksWhenModal();
currentModalSessionCached = 0;
diff --git a/src/gui/kernel/qeventdispatcher_mac_p.h b/src/gui/kernel/qeventdispatcher_mac_p.h
index e932532..8ac7c65 100644
--- a/src/gui/kernel/qeventdispatcher_mac_p.h
+++ b/src/gui/kernel/qeventdispatcher_mac_p.h
@@ -100,6 +100,7 @@ typedef struct _NSModalSession *NSModalSession;
typedef struct _QCocoaModalSessionInfo {
QPointer<QWidget> widget;
NSModalSession session;
+ void *nswindow;
} QCocoaModalSessionInfo;
#endif
diff --git a/src/gui/kernel/qgesture_p.h b/src/gui/kernel/qgesture_p.h
index 649a310..bf60f97 100644
--- a/src/gui/kernel/qgesture_p.h
+++ b/src/gui/kernel/qgesture_p.h
@@ -55,8 +55,8 @@
#include "qrect.h"
#include "qpoint.h"
-#include "qdatetime.h"
#include "qgesture.h"
+#include "qelapsedtimer.h"
#include "private/qobject_p.h"
QT_BEGIN_NAMESPACE
@@ -148,7 +148,7 @@ public:
QPoint lastPositions[3];
bool started;
qreal speed;
- QTime time;
+ QElapsedTimer time;
};
class QTapGesturePrivate : public QGesturePrivate
diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp
index 89ad94d..aa6720e 100644
--- a/src/gui/kernel/qgesturemanager.cpp
+++ b/src/gui/kernel/qgesturemanager.cpp
@@ -45,6 +45,7 @@
#include "private/qgesture_p.h"
#include "private/qgraphicsitem_p.h"
#include "private/qevent_p.h"
+#include "private/qapplication_p.h"
#include "qgesture.h"
#include "qevent.h"
#include "qgraphicsitem.h"
@@ -86,7 +87,8 @@ QGestureManager::QGestureManager(QObject *parent)
#endif
#if defined(Q_OS_WIN)
#if !defined(QT_NO_NATIVE_GESTURES)
- registerGestureRecognizer(new QWinNativePanGestureRecognizer);
+ if (QApplicationPrivate::HasTouchSupport)
+ registerGestureRecognizer(new QWinNativePanGestureRecognizer);
#endif
#else
registerGestureRecognizer(new QTapAndHoldGestureRecognizer);
diff --git a/src/gui/kernel/qgesturerecognizer.cpp b/src/gui/kernel/qgesturerecognizer.cpp
index c88a9a7..9dcca17 100644
--- a/src/gui/kernel/qgesturerecognizer.cpp
+++ b/src/gui/kernel/qgesturerecognizer.cpp
@@ -161,6 +161,8 @@ QGestureRecognizer::~QGestureRecognizer()
Reimplement this function to create a custom QGesture-derived gesture
object if necessary.
+
+ The application takes ownership of the created gesture object.
*/
QGesture *QGestureRecognizer::create(QObject *target)
{
diff --git a/src/gui/kernel/qgridlayout.cpp b/src/gui/kernel/qgridlayout.cpp
index dbd3c01..81a4d04 100644
--- a/src/gui/kernel/qgridlayout.cpp
+++ b/src/gui/kernel/qgridlayout.cpp
@@ -1852,7 +1852,7 @@ void QGridLayout::invalidate()
/*!
\fn int QGridLayout::colSpacing(int col) const
- Use columnSpacing() instead.
+ Use columnMinimumWidth() instead.
*/
/*!
diff --git a/src/gui/kernel/qguifunctions_wince.cpp b/src/gui/kernel/qguifunctions_wince.cpp
index ac4cdc8..f5004b0 100644
--- a/src/gui/kernel/qguifunctions_wince.cpp
+++ b/src/gui/kernel/qguifunctions_wince.cpp
@@ -278,7 +278,14 @@ int qt_wince_get_version()
bool qt_wince_is_windows_mobile_65()
{
- return ((qt_wince_get_version() == 52) && (qt_wince_get_build() > 2000));
+ const DWORD dwFirstWM65BuildNumber = 21139;
+ OSVERSIONINFO osvi;
+ osvi.dwOSVersionInfoSize = sizeof(osvi);
+ if (!GetVersionEx(&osvi))
+ return false;
+ return osvi.dwMajorVersion > 5
+ || (osvi.dwMajorVersion == 5 && (osvi.dwMinorVersion > 2 ||
+ (osvi.dwMinorVersion == 2 && osvi.dwBuildNumber >= dwFirstWM65BuildNumber)));
}
bool qt_wince_is_pocket_pc() {
diff --git a/src/gui/kernel/qkeymapper_mac.cpp b/src/gui/kernel/qkeymapper_mac.cpp
index a31480d..f259654 100644
--- a/src/gui/kernel/qkeymapper_mac.cpp
+++ b/src/gui/kernel/qkeymapper_mac.cpp
@@ -323,6 +323,32 @@ static qt_mac_enum_mapper qt_mac_keyvkey_symbols[] = { //real scan codes
{ 0, QT_MAC_MAP_ENUM(0) }
};
+static qt_mac_enum_mapper qt_mac_private_unicode[] = {
+ { 0xF700, QT_MAC_MAP_ENUM(Qt::Key_Up) }, //NSUpArrowFunctionKey
+ { 0xF701, QT_MAC_MAP_ENUM(Qt::Key_Down) }, //NSDownArrowFunctionKey
+ { 0xF702, QT_MAC_MAP_ENUM(Qt::Key_Left) }, //NSLeftArrowFunctionKey
+ { 0xF703, QT_MAC_MAP_ENUM(Qt::Key_Right) }, //NSRightArrowFunctionKey
+ { 0xF727, QT_MAC_MAP_ENUM(Qt::Key_Insert) }, //NSInsertFunctionKey
+ { 0xF728, QT_MAC_MAP_ENUM(Qt::Key_Delete) }, //NSDeleteFunctionKey
+ { 0xF729, QT_MAC_MAP_ENUM(Qt::Key_Home) }, //NSHomeFunctionKey
+ { 0xF72B, QT_MAC_MAP_ENUM(Qt::Key_End) }, //NSEndFunctionKey
+ { 0xF72C, QT_MAC_MAP_ENUM(Qt::Key_PageUp) }, //NSPageUpFunctionKey
+ { 0xF72D, QT_MAC_MAP_ENUM(Qt::Key_PageDown) }, //NSPageDownFunctionKey
+ { 0xF72F, QT_MAC_MAP_ENUM(Qt::Key_ScrollLock) }, //NSScrollLockFunctionKey
+ { 0xF730, QT_MAC_MAP_ENUM(Qt::Key_Pause) }, //NSPauseFunctionKey
+ { 0xF731, QT_MAC_MAP_ENUM(Qt::Key_SysReq) }, //NSSysReqFunctionKey
+ { 0xF735, QT_MAC_MAP_ENUM(Qt::Key_Menu) }, //NSMenuFunctionKey
+ { 0xF738, QT_MAC_MAP_ENUM(Qt::Key_Print) }, //NSPrintFunctionKey
+ { 0xF73A, QT_MAC_MAP_ENUM(Qt::Key_Clear) }, //NSClearDisplayFunctionKey
+ { 0xF73D, QT_MAC_MAP_ENUM(Qt::Key_Insert) }, //NSInsertCharFunctionKey
+ { 0xF73E, QT_MAC_MAP_ENUM(Qt::Key_Delete) }, //NSDeleteCharFunctionKey
+ { 0xF741, QT_MAC_MAP_ENUM(Qt::Key_Select) }, //NSSelectFunctionKey
+ { 0xF742, QT_MAC_MAP_ENUM(Qt::Key_Execute) }, //NSExecuteFunctionKey
+ { 0xF746, QT_MAC_MAP_ENUM(Qt::Key_Help) }, //NSHelpFunctionKey
+ { 0xF747, QT_MAC_MAP_ENUM(Qt::Key_Mode_switch) }, //NSModeSwitchFunctionKey
+ { 0, QT_MAC_MAP_ENUM(0) }
+};
+
static int qt_mac_get_key(int modif, const QChar &key, int virtualKey)
{
#ifdef DEBUG_KEY_BINDINGS
@@ -379,6 +405,19 @@ static int qt_mac_get_key(int modif, const QChar &key, int virtualKey)
}
}
+ // check if they belong to key codes in private unicode range
+ if (key >= 0xf700 && key <= 0xf747) {
+ if (key >= 0xf704 && key <= 0xf726) {
+ return Qt::Key_F1 + (key.unicode() - 0xf704) ;
+ }
+ for (int i = 0; qt_mac_private_unicode[i].qt_code; i++) {
+ if (qt_mac_private_unicode[i].mac_code == key) {
+ return qt_mac_private_unicode[i].qt_code;
+ }
+ }
+
+ }
+
//oh well
#ifdef DEBUG_KEY_BINDINGS
qDebug("Unknown case.. %s:%d %d[%d] %d", __FILE__, __LINE__, key.unicode(), key.toLatin1(), virtualKey);
@@ -847,7 +886,11 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, EventHandlerCallRef e
}
void
-QKeyMapperPrivate::updateKeyMap(EventHandlerCallRef, EventRef event, void *)
+QKeyMapperPrivate::updateKeyMap(EventHandlerCallRef, EventRef event, void *
+#if defined(QT_MAC_USE_COCOA)
+ unicodeKey // unicode character from NSEvent (modifiers applied)
+#endif
+ )
{
UInt32 macVirtualKey = 0;
GetEventParameter(event, kEventParamKeyCode, typeUInt32, 0, sizeof(macVirtualKey), 0, &macVirtualKey);
@@ -875,6 +918,15 @@ QKeyMapperPrivate::updateKeyMap(EventHandlerCallRef, EventRef event, void *)
qtkey = unicode.unicode();
keyLayout[macVirtualKey]->qtKey[i] = qtkey;
}
+#ifndef Q_WS_MAC32
+ else {
+ const QChar unicode(*((UniChar *)unicodeKey));
+ int qtkey = qt_mac_get_key(keyModifier, unicode, macVirtualKey);
+ if (qtkey == Qt::Key_unknown)
+ qtkey = unicode.unicode();
+ keyLayout[macVirtualKey]->qtKey[i] = qtkey;
+ }
+#endif
#ifdef Q_WS_MAC32
} else {
const UInt32 keyModifier = (qt_mac_get_mac_modifiers(ModsTbl[i]));
diff --git a/src/gui/kernel/qkeymapper_p.h b/src/gui/kernel/qkeymapper_p.h
index 3e42d6e..38f141e 100644
--- a/src/gui/kernel/qkeymapper_p.h
+++ b/src/gui/kernel/qkeymapper_p.h
@@ -183,7 +183,7 @@ public:
const XEvent *,
bool grab);
- bool useXKB;
+ int xkb_currentGroup;
QXCoreDesc coreDesc;
#elif defined(Q_WS_MAC)
diff --git a/src/gui/kernel/qkeymapper_win.cpp b/src/gui/kernel/qkeymapper_win.cpp
index e555c5c..f84b902 100644
--- a/src/gui/kernel/qkeymapper_win.cpp
+++ b/src/gui/kernel/qkeymapper_win.cpp
@@ -56,7 +56,7 @@ QT_BEGIN_NAMESPACE
//#define DEBUG_KEYMAPPER
// Implemented elsewhere
-extern "C" LRESULT CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
+extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
extern Q_CORE_EXPORT QLocale qt_localeFromLCID(LCID id);
#ifndef LANG_PASHTO
diff --git a/src/gui/kernel/qkeymapper_x11.cpp b/src/gui/kernel/qkeymapper_x11.cpp
index 4e6c847..807959c 100644
--- a/src/gui/kernel/qkeymapper_x11.cpp
+++ b/src/gui/kernel/qkeymapper_x11.cpp
@@ -80,7 +80,7 @@ QT_BEGIN_NAMESPACE
(((KeySym)(keysym) >= 0x11000000) && ((KeySym)(keysym) <= 0x1100FFFF))
#endif
-static void getLocaleAndDirection(QLocale *locale,
+void q_getLocaleAndDirection(QLocale *locale,
Qt::LayoutDirection *direction,
const QByteArray &layoutName,
const QByteArray &variantName)
@@ -248,22 +248,17 @@ qt_XTranslateKey(register QXCoreDesc *dpy,
QKeyMapperPrivate::QKeyMapperPrivate()
- : keyboardInputDirection(Qt::LeftToRight), useXKB(false)
+ : keyboardInputDirection(Qt::LeftToRight), xkb_currentGroup(0)
{
memset(&coreDesc, 0, sizeof(coreDesc));
#ifndef QT_NO_XKB
- int opcode = -1;
- int xkbEventBase = -1;
- int xkbErrorBase = -1;
- int xkblibMajor = XkbMajorVersion;
- int xkblibMinor = XkbMinorVersion;
- if (XkbQueryExtension(X11->display, &opcode, &xkbEventBase, &xkbErrorBase, &xkblibMajor, &xkblibMinor))
- useXKB = true;
-#endif
-
-#if 0
- qDebug() << "useXKB =" << useXKB;
+ if (X11->use_xkb) {
+ // get the current group
+ XkbStateRec xkbState;
+ if (XkbGetState(X11->display, XkbUseCoreKbd, &xkbState) == Success)
+ xkb_currentGroup = xkbState.group;
+ }
#endif
}
@@ -276,7 +271,7 @@ QKeyMapperPrivate::~QKeyMapperPrivate()
QList<int> QKeyMapperPrivate::possibleKeys(QKeyEvent *event)
{
#ifndef QT_NO_XKB
- if (useXKB)
+ if (X11->use_xkb)
return possibleKeysXKB(event);
#endif
return possibleKeysCore(event);
@@ -486,7 +481,7 @@ enum {
void QKeyMapperPrivate::clearMappings()
{
#ifndef QT_NO_XKB
- if (useXKB) {
+ if (X11->use_xkb) {
// try to determine the layout name and input direction by reading the _XKB_RULES_NAMES property off
// the root window
QByteArray layoutName;
@@ -515,15 +510,20 @@ void QKeyMapperPrivate::clearMappings()
p += qstrlen(p) + 1;
} while (p < end);
- layoutName = QByteArray::fromRawData(names[2], qstrlen(names[2]));
- variantName = QByteArray::fromRawData(names[3], qstrlen(names[3]));
+ // the layout names and variants are saved in the _XKB_RULES_NAMES property as a comma separated list
+ QList<QByteArray> layoutNames = QByteArray::fromRawData(names[2], qstrlen(names[2])).split(',');
+ if (uint(xkb_currentGroup) < uint(layoutNames.count()))
+ layoutName = layoutNames.at(xkb_currentGroup);
+ QList<QByteArray> variantNames = QByteArray::fromRawData(names[3], qstrlen(names[3])).split(',');
+ if (uint(xkb_currentGroup) < uint(variantNames.count()))
+ variantName = variantNames.at(xkb_currentGroup);
}
// ### ???
// if (keyboardLayoutName.isEmpty())
// qWarning("Qt: unable to determine keyboard layout, please talk to qt-bugs@trolltech.com"); ?
- getLocaleAndDirection(&keyboardInputLocale,
+ q_getLocaleAndDirection(&keyboardInputLocale,
&keyboardInputDirection,
layoutName,
variantName);
@@ -534,7 +534,6 @@ void QKeyMapperPrivate::clearMappings()
<< "direction ="
<< keyboardInputDirection;
#endif
-
if (data)
XFree(data);
} else
@@ -574,7 +573,7 @@ void QKeyMapperPrivate::clearMappings()
// look at the modifier mapping, and get the correct masks for alt, meta, super, hyper, and mode_switch
#ifndef QT_NO_XKB
- if (useXKB) {
+ if (X11->use_xkb) {
XkbDescPtr xkbDesc = XkbGetMap(X11->display, XkbAllClientInfoMask, XkbUseCoreKbd);
for (int i = xkbDesc->min_key_code; i < xkbDesc->max_key_code; ++i) {
const uint mask = xkbDesc->map->modmap ? xkbDesc->map->modmap[i] : 0;
@@ -1073,8 +1072,8 @@ static const unsigned int KeyTbl[] = {
XF86XK_AudioNext, Qt::Key_MediaNext,
XF86XK_AudioRecord, Qt::Key_MediaRecord,
XF86XK_Mail, Qt::Key_LaunchMail,
- XF86XK_MyComputer, Qt::Key_Launch0,
- XF86XK_Calculator, Qt::Key_Calculator,
+ XF86XK_MyComputer, Qt::Key_Launch0, // ### Qt 5: remap properly
+ XF86XK_Calculator, Qt::Key_Launch1,
XF86XK_Memo, Qt::Key_Memo,
XF86XK_ToDoList, Qt::Key_ToDoList,
XF86XK_Calendar, Qt::Key_Calendar,
@@ -1172,7 +1171,7 @@ static const unsigned int KeyTbl[] = {
XF86XK_Bluetooth, Qt::Key_Bluetooth,
XF86XK_Suspend, Qt::Key_Suspend,
XF86XK_Hibernate, Qt::Key_Hibernate,
- XF86XK_Launch0, Qt::Key_Launch2,
+ XF86XK_Launch0, Qt::Key_Launch2, // ### Qt 5: remap properly
XF86XK_Launch1, Qt::Key_Launch3,
XF86XK_Launch2, Qt::Key_Launch4,
XF86XK_Launch3, Qt::Key_Launch5,
@@ -1186,6 +1185,8 @@ static const unsigned int KeyTbl[] = {
XF86XK_LaunchB, Qt::Key_LaunchD,
XF86XK_LaunchC, Qt::Key_LaunchE,
XF86XK_LaunchD, Qt::Key_LaunchF,
+ XF86XK_LaunchE, Qt::Key_LaunchG,
+ XF86XK_LaunchF, Qt::Key_LaunchH,
// Qtopia keys
QTOPIAXK_Select, Qt::Key_Select,
diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp
index 99bf971..9efcc4e 100644
--- a/src/gui/kernel/qkeysequence.cpp
+++ b/src/gui/kernel/qkeysequence.cpp
@@ -580,6 +580,41 @@ static const struct {
{ Qt::Key_Hangup, QT_TRANSLATE_NOOP("QShortcut", "Hangup") },
{ Qt::Key_Flip, QT_TRANSLATE_NOOP("QShortcut", "Flip") },
+ // --------------------------------------------------------------
+ // Japanese keyboard support
+ { Qt::Key_Kanji, QT_TRANSLATE_NOOP("QShortcut", "Kanji") },
+ { Qt::Key_Muhenkan, QT_TRANSLATE_NOOP("QShortcut", "Muhenkan") },
+ { Qt::Key_Henkan, QT_TRANSLATE_NOOP("QShortcut", "Henkan") },
+ { Qt::Key_Romaji, QT_TRANSLATE_NOOP("QShortcut", "Romaji") },
+ { Qt::Key_Hiragana, QT_TRANSLATE_NOOP("QShortcut", "Hiragana") },
+ { Qt::Key_Katakana, QT_TRANSLATE_NOOP("QShortcut", "Katakana") },
+ { Qt::Key_Hiragana_Katakana,QT_TRANSLATE_NOOP("QShortcut", "Hiragana Katakana") },
+ { Qt::Key_Zenkaku, QT_TRANSLATE_NOOP("QShortcut", "Zenkaku") },
+ { Qt::Key_Hankaku, QT_TRANSLATE_NOOP("QShortcut", "Hankaku") },
+ { Qt::Key_Zenkaku_Hankaku, QT_TRANSLATE_NOOP("QShortcut", "Zenkaku Hankaku") },
+ { Qt::Key_Touroku, QT_TRANSLATE_NOOP("QShortcut", "Touroku") },
+ { Qt::Key_Massyo, QT_TRANSLATE_NOOP("QShortcut", "Massyo") },
+ { Qt::Key_Kana_Lock, QT_TRANSLATE_NOOP("QShortcut", "Kana Lock") },
+ { Qt::Key_Kana_Shift, QT_TRANSLATE_NOOP("QShortcut", "Kana Shift") },
+ { Qt::Key_Eisu_Shift, QT_TRANSLATE_NOOP("QShortcut", "Eisu Shift") },
+ { Qt::Key_Eisu_toggle, QT_TRANSLATE_NOOP("QShortcut", "Eisu toggle") },
+ { Qt::Key_Codeinput, QT_TRANSLATE_NOOP("QShortcut", "Code input") },
+ { Qt::Key_MultipleCandidate,QT_TRANSLATE_NOOP("QShortcut", "Multiple Candidate") },
+ { Qt::Key_PreviousCandidate,QT_TRANSLATE_NOOP("QShortcut", "Previous Candidate") },
+
+ // --------------------------------------------------------------
+ // Korean keyboard support
+ { Qt::Key_Hangul, QT_TRANSLATE_NOOP("QShortcut", "Hangul") },
+ { Qt::Key_Hangul_Start, QT_TRANSLATE_NOOP("QShortcut", "Hangul Start") },
+ { Qt::Key_Hangul_End, QT_TRANSLATE_NOOP("QShortcut", "Hangul End") },
+ { Qt::Key_Hangul_Hanja, QT_TRANSLATE_NOOP("QShortcut", "Hangul Hanja") },
+ { Qt::Key_Hangul_Jamo, QT_TRANSLATE_NOOP("QShortcut", "Hangul Jamo") },
+ { Qt::Key_Hangul_Romaja, QT_TRANSLATE_NOOP("QShortcut", "Hangul Romaja") },
+ { Qt::Key_Hangul_Jeonja, QT_TRANSLATE_NOOP("QShortcut", "Hangul Jeonja") },
+ { Qt::Key_Hangul_Banja, QT_TRANSLATE_NOOP("QShortcut", "Hangul Banja") },
+ { Qt::Key_Hangul_PreHanja, QT_TRANSLATE_NOOP("QShortcut", "Hangul PreHanja") },
+ { Qt::Key_Hangul_PostHanja,QT_TRANSLATE_NOOP("QShortcut", "Hangul PostHanja") },
+ { Qt::Key_Hangul_Special, QT_TRANSLATE_NOOP("QShortcut", "Hangul Special") },
{ 0, 0 }
};
@@ -696,6 +731,7 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = {
{QKeySequence::Redo, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Z, QApplicationPrivate::KB_Mac}, //different priority from above
{QKeySequence::PreviousChild, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Backtab, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
{QKeySequence::PreviousChild, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Backtab, QApplicationPrivate::KB_Mac },//different priority from above
+ {QKeySequence::Paste, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Insert, QApplicationPrivate::KB_X11},
{QKeySequence::SelectStartOfDocument, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
{QKeySequence::SelectEndOfDocument, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
{QKeySequence::SelectPreviousWord, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Left, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
diff --git a/src/gui/kernel/qmime_win.cpp b/src/gui/kernel/qmime_win.cpp
index e191d7b..2840843 100644
--- a/src/gui/kernel/qmime_win.cpp
+++ b/src/gui/kernel/qmime_win.cpp
@@ -640,14 +640,18 @@ bool QWindowsMimeURI::convertFromMime(const FORMATETC &formatetc, const QMimeDat
} else if (getCf(formatetc) == CF_INETURL_W) {
QList<QUrl> urls = mimeData->urls();
QByteArray result;
- QString url = urls.at(0).toString();
- result = QByteArray((const char *)url.utf16(), url.length() * sizeof(ushort));
+ if (!urls.isEmpty()) {
+ QString url = urls.at(0).toString();
+ result = QByteArray((const char *)url.utf16(), url.length() * sizeof(ushort));
+ }
result.append('\0');
result.append('\0');
return setData(result, pmedium);
} else if (getCf(formatetc) == CF_INETURL) {
QList<QUrl> urls = mimeData->urls();
- QByteArray result = urls.at(0).toString().toLocal8Bit();
+ QByteArray result;
+ if (!urls.isEmpty())
+ result = urls.at(0).toString().toLocal8Bit();
return setData(result, pmedium);
}
}
@@ -948,6 +952,8 @@ bool QWindowsMimeImage::convertFromMime(const FORMATETC &formatetc, const QMimeD
QDataStream s(&ba, QIODevice::WriteOnly);
s.setByteOrder(QDataStream::LittleEndian);// Intel byte order ####
if (cf == CF_DIB) {
+ if (img.format() > QImage::Format_ARGB32)
+ img = img.convertToFormat(QImage::Format_RGB32);
if (qt_write_dib(s, img))
return setData(ba, pmedium);
} else {
diff --git a/src/gui/kernel/qsoftkeymanager.cpp b/src/gui/kernel/qsoftkeymanager.cpp
index c9a94ee..23f1481 100644
--- a/src/gui/kernel/qsoftkeymanager.cpp
+++ b/src/gui/kernel/qsoftkeymanager.cpp
@@ -115,6 +115,8 @@ QAction *QSoftKeyManager::createAction(StandardSoftKey standardKey, QWidget *act
break;
}
action->setSoftKeyRole(softKeyRole);
+ action->setVisible(false);
+ setForceEnabledInSoftkeys(action);
return action;
}
@@ -168,25 +170,55 @@ bool QSoftKeyManager::appendSoftkeys(const QWidget &source, int level)
{
Q_D(QSoftKeyManager);
bool ret = false;
- QList<QAction*> actions = source.actions();
- for (int i = 0; i < actions.count(); ++i) {
- if (actions.at(i)->softKeyRole() != QAction::NoSoftKey) {
- d->requestedSoftKeyActions.insert(level, actions.at(i));
+ foreach(QAction *action, source.actions()) {
+ if (action->softKeyRole() != QAction::NoSoftKey
+ && (action->isVisible() || isForceEnabledInSofkeys(action))) {
+ d->requestedSoftKeyActions.insert(level, action);
ret = true;
}
}
return ret;
}
+
+static bool isChildOf(const QWidget *c, const QWidget *p)
+{
+ while (c) {
+ if (c == p)
+ return true;
+ c = c->parentWidget();
+ }
+ return false;
+}
+
QWidget *QSoftKeyManager::softkeySource(QWidget *previousSource, bool& recursiveMerging)
{
Q_D(QSoftKeyManager);
QWidget *source = NULL;
if (!previousSource) {
// Initial source is primarily focuswidget and secondarily activeWindow
- source = QApplication::focusWidget();
- if (!source)
- source = QApplication::activeWindow();
+ QWidget *focus = QApplication::focusWidget();
+ QWidget *popup = QApplication::activePopupWidget();
+ if (popup) {
+ if (isChildOf(focus, popup))
+ source = focus;
+ else
+ source = popup;
+ }
+ if (!source) {
+ QWidget *modal = QApplication::activeModalWidget();
+ if (modal) {
+ if (isChildOf(focus, modal))
+ source = focus;
+ else
+ source = modal;
+ }
+ }
+ if (!source) {
+ source = focus;
+ if (!source)
+ source = QApplication::activeWindow();
+ }
} else {
// Softkey merging is based on four criterias
// 1. Implicit merging is used whenever focus widget does not specify any softkeys
@@ -210,6 +242,7 @@ bool QSoftKeyManager::handleUpdateSoftKeys()
d->requestedSoftKeyActions.clear();
bool recursiveMerging = false;
QWidget *source = softkeySource(NULL, recursiveMerging);
+ d->initialSoftKeySource = source;
while (source) {
if (appendSoftkeys(*source, level))
++level;
@@ -220,6 +253,20 @@ bool QSoftKeyManager::handleUpdateSoftKeys()
return true;
}
+void QSoftKeyManager::setForceEnabledInSoftkeys(QAction *action)
+{
+ action->setProperty(FORCE_ENABLED_PROPERTY, QVariant(true));
+}
+
+bool QSoftKeyManager::isForceEnabledInSofkeys(QAction *action)
+{
+ bool ret = false;
+ QVariant property = action->property(FORCE_ENABLED_PROPERTY);
+ if (property.isValid() && property.toBool())
+ ret = true;
+ return ret;
+}
+
bool QSoftKeyManager::event(QEvent *e)
{
#ifndef QT_NO_ACTION
diff --git a/src/gui/kernel/qsoftkeymanager_common_p.h b/src/gui/kernel/qsoftkeymanager_common_p.h
index 460d0dc..04ddf7d 100644
--- a/src/gui/kernel/qsoftkeymanager_common_p.h
+++ b/src/gui/kernel/qsoftkeymanager_common_p.h
@@ -70,6 +70,7 @@ protected:
static QSoftKeyManager *self;
QHash<QAction*, Qt::Key> keyedActions;
QMultiHash<int, QAction*> requestedSoftKeyActions;
+ QWidget *initialSoftKeySource;
};
@@ -79,4 +80,4 @@ QT_END_NAMESPACE
QT_END_HEADER
-#endif // QSOFTKEYMANAGER_COMMON_P_H \ No newline at end of file
+#endif // QSOFTKEYMANAGER_COMMON_P_H
diff --git a/src/gui/kernel/qsoftkeymanager_p.h b/src/gui/kernel/qsoftkeymanager_p.h
index a6fe17e..a5b258b 100644
--- a/src/gui/kernel/qsoftkeymanager_p.h
+++ b/src/gui/kernel/qsoftkeymanager_p.h
@@ -63,7 +63,8 @@ QT_BEGIN_NAMESPACE
class QSoftKeyManagerPrivate;
-const char MENU_ACTION_PROPERTY[] = "_q_menuaction";
+const char MENU_ACTION_PROPERTY[] = "_q_menuAction";
+const char FORCE_ENABLED_PROPERTY[] = "_q_forceEnabledInSoftkeys";
class Q_AUTOTEST_EXPORT QSoftKeyManager : public QObject
{
@@ -88,6 +89,8 @@ public:
static QAction *createAction(StandardSoftKey standardKey, QWidget *actionWidget);
static QAction *createKeyedAction(StandardSoftKey standardKey, Qt::Key key, QWidget *actionWidget);
static QString standardSoftKeyText(StandardSoftKey standardKey);
+ static void setForceEnabledInSoftkeys(QAction *action);
+ static bool isForceEnabledInSofkeys(QAction *action);
protected:
bool event(QEvent *e);
diff --git a/src/gui/kernel/qsoftkeymanager_s60.cpp b/src/gui/kernel/qsoftkeymanager_s60.cpp
index 8ac1e31..c0761f0 100644
--- a/src/gui/kernel/qsoftkeymanager_s60.cpp
+++ b/src/gui/kernel/qsoftkeymanager_s60.cpp
@@ -60,7 +60,7 @@ const int LSK_POSITION = 0;
const int MSK_POSITION = 3;
const int RSK_POSITION = 2;
-QSoftKeyManagerPrivateS60::QSoftKeyManagerPrivateS60()
+QSoftKeyManagerPrivateS60::QSoftKeyManagerPrivateS60() : cbaHasImage(4) // 4 since MSK position index is 3
{
cachedCbaIconSize[0] = QSize(0,0);
cachedCbaIconSize[1] = QSize(0,0);
@@ -73,11 +73,21 @@ bool QSoftKeyManagerPrivateS60::skipCbaUpdate()
// Lets not update softkeys if
// 1. We don't have application panes, i.e. cba
// 2. Our CBA is not active, i.e. S60 native dialog or menu with custom CBA is shown
+ // 2.1. Except if thre is no current CBA at all and WindowSoftkeysRespondHint is set
+
// Note: Cannot use IsDisplayingMenuOrDialog since CBA update can be triggered before
// menu/dialog CBA is actually displayed i.e. it is being costructed.
CEikButtonGroupContainer *appUiCba = S60->buttonGroupContainer();
+ // CEikButtonGroupContainer::Current returns 0 if CBA is not visible at all
CEikButtonGroupContainer *currentCba = CEikButtonGroupContainer::Current();
- if (QApplication::testAttribute(Qt::AA_S60DontConstructApplicationPanes) || appUiCba != currentCba) {
+ // Check if softkey need to be update even they are not visible
+ bool cbaRespondsWhenInvisible = false;
+ QWidget *window = QApplication::activeWindow();
+ if (window && (window->windowFlags() & Qt::WindowSoftkeysRespondHint))
+ cbaRespondsWhenInvisible = true;
+
+ if (QApplication::testAttribute(Qt::AA_S60DontConstructApplicationPanes)
+ || (appUiCba != currentCba && !cbaRespondsWhenInvisible)) {
return true;
}
return false;
@@ -255,10 +265,14 @@ bool QSoftKeyManagerPrivateS60::setSoftkeyImage(CEikButtonGroupContainer *cba,
myimage->SetPicture( nBitmap, nMask ); // nBitmap and nMask ownership transfered
EikSoftkeyImage::SetImage(cba, *myimage, left); // Takes myimage ownership
+ cbaHasImage[position] = true;
ret = true;
} else {
// Restore softkey to text based
- EikSoftkeyImage::SetLabel(cba, left);
+ if (cbaHasImage[position]) {
+ EikSoftkeyImage::SetLabel(cba, left);
+ cbaHasImage[position] = false;
+ }
}
}
return ret;
@@ -274,7 +288,8 @@ bool QSoftKeyManagerPrivateS60::setSoftkey(CEikButtonGroupContainer &cba,
TPtrC nativeText = qt_QString2TPtrC(text);
int command = S60_COMMAND_START + position;
setNativeSoftkey(cba, position, command, nativeText);
- cba.DimCommand(command, !action->isEnabled());
+ const bool dimmed = !action->isEnabled() && !QSoftKeyManager::isForceEnabledInSofkeys(action);
+ cba.DimCommand(command, dimmed);
realSoftKeyActions.insert(command, action);
return true;
}
@@ -297,22 +312,17 @@ bool QSoftKeyManagerPrivateS60::setMiddleSoftkey(CEikButtonGroupContainer &cba)
bool QSoftKeyManagerPrivateS60::setRightSoftkey(CEikButtonGroupContainer &cba)
{
if (!setSoftkey(cba, QAction::NegativeSoftKey, RSK_POSITION)) {
- Qt::WindowType windowType = Qt::Window;
- QAction *action = requestedSoftKeyActions.value(0);
- if (action) {
- QWidget *actionParent = action->parentWidget();
- Q_ASSERT_X(actionParent, Q_FUNC_INFO, "No parent set for softkey action!");
-
- QWidget *actionWindow = actionParent->window();
- Q_ASSERT_X(actionWindow, Q_FUNC_INFO, "Softkey action does not have window!");
- windowType = actionWindow->windowType();
- }
-
+ const Qt::WindowType windowType = initialSoftKeySource
+ ? initialSoftKeySource->window()->windowType() : Qt::Window;
if (windowType != Qt::Dialog && windowType != Qt::Popup) {
QString text(QSoftKeyManager::tr("Exit"));
TPtrC nativeText = qt_QString2TPtrC(text);
- EikSoftkeyImage::SetLabel(&cba, false);
+ if (cbaHasImage[RSK_POSITION]) {
+ EikSoftkeyImage::SetLabel(&cba, false);
+ cbaHasImage[RSK_POSITION] = false;
+ }
setNativeSoftkey(cba, RSK_POSITION, EAknSoftkeyExit, nativeText);
+ cba.DimCommand(EAknSoftkeyExit, false);
return true;
}
}
@@ -355,17 +365,30 @@ void QSoftKeyManagerPrivateS60::updateSoftKeys_sys()
nativeContainer->DrawDeferred(); // 3.1 needs an extra invitation
}
+static void resetMenuBeingConstructed(TAny* /*aAny*/)
+{
+ S60->menuBeingConstructed = false;
+}
+
+void QSoftKeyManagerPrivateS60::tryDisplayMenuBarL()
+{
+ CleanupStack::PushL(TCleanupItem(resetMenuBeingConstructed, NULL));
+ S60->menuBeingConstructed = true;
+ S60->menuBar()->TryDisplayMenuBarL();
+ CleanupStack::PopAndDestroy(); // Reset menuBeingConstructed to false in all cases
+}
+
bool QSoftKeyManagerPrivateS60::handleCommand(int command)
{
QAction *action = realSoftKeyActions.value(command);
if (action) {
QVariant property = action->property(MENU_ACTION_PROPERTY);
if (property.isValid() && property.toBool()) {
- QT_TRAP_THROWING(S60->menuBar()->TryDisplayMenuBarL());
+ QT_TRAP_THROWING(tryDisplayMenuBarL());
} else if (action->menu()) {
// TODO: This is hack, in order to use exising QMenuBar implementation for Symbian
// menubar needs to have widget to which it is associated. Since we want to associate
- // menubar to action (which is inherited from QObejct), we create and associate QWidget
+ // menubar to action (which is inherited from QObject), we create and associate QWidget
// to action and pass that for QMenuBar. This associates the menubar to action, and we
// can have own menubar for each action.
QWidget *actionContainer = action->property("_q_action_widget").value<QWidget*>();
@@ -384,15 +407,15 @@ bool QSoftKeyManagerPrivateS60::handleCommand(int command)
action->setProperty("_q_action_widget", v);
}
qt_symbian_next_menu_from_action(actionContainer);
- QT_TRAP_THROWING(S60->menuBar()->TryDisplayMenuBarL());
- } else {
- Q_ASSERT(action->softKeyRole() != QAction::NoSoftKey);
- QWidget *actionParent = action->parentWidget();
- Q_ASSERT_X(actionParent, Q_FUNC_INFO, "No parent set for softkey action!");
- if (actionParent->isEnabled()) {
- action->activate(QAction::Trigger);
- return true;
- }
+ QT_TRAP_THROWING(tryDisplayMenuBarL());
+ }
+
+ Q_ASSERT(action->softKeyRole() != QAction::NoSoftKey);
+ QWidget *actionParent = action->parentWidget();
+ Q_ASSERT_X(actionParent, Q_FUNC_INFO, "No parent set for softkey action!");
+ if (actionParent->isEnabled()) {
+ action->activate(QAction::Trigger);
+ return true;
}
}
return false;
diff --git a/src/gui/kernel/qsoftkeymanager_s60_p.h b/src/gui/kernel/qsoftkeymanager_s60_p.h
index 823a2db..d14993c 100644
--- a/src/gui/kernel/qsoftkeymanager_s60_p.h
+++ b/src/gui/kernel/qsoftkeymanager_s60_p.h
@@ -53,6 +53,7 @@
// We mean it.
//
+#include "qbitarray.h"
#include "private/qobject_p.h"
#include "private/qsoftkeymanager_common_p.h"
@@ -77,6 +78,7 @@ public:
bool handleCommand(int command);
private:
+ void tryDisplayMenuBarL();
bool skipCbaUpdate();
void ensureCbaVisibilityAndResponsiviness(CEikButtonGroupContainer &cba);
void clearSoftkeys(CEikButtonGroupContainer &cba);
@@ -98,6 +100,7 @@ private:
private:
QHash<int, QAction*> realSoftKeyActions;
QSize cachedCbaIconSize[4];
+ QBitArray cbaHasImage;
};
diff --git a/src/gui/kernel/qsound.cpp b/src/gui/kernel/qsound.cpp
index 165e6ce..9d8ffa5 100644
--- a/src/gui/kernel/qsound.cpp
+++ b/src/gui/kernel/qsound.cpp
@@ -147,12 +147,13 @@ public:
supports WAVE and AU files.
\row
\o Mac OS X
- \o NSSound is used. All formats that NSSound supports, including QuickTime formats,
+ \o NSSound is used. All formats that NSSound supports, including QuickTime formats,
are supported by Qt for Mac OS X.
\row
\o Qt for Embedded Linux
\o A built-in mixing sound server is used, accessing \c /dev/dsp
directly. Only the WAVE format is supported.
+ \row
\o Symbian
\o CMdaAudioPlayerUtility is used. All formats that Symbian OS or devices support
are supported also by Qt.
diff --git a/src/gui/kernel/qsound_mac.mm b/src/gui/kernel/qsound_mac.mm
index 61e42ba..71fd663 100644
--- a/src/gui/kernel/qsound_mac.mm
+++ b/src/gui/kernel/qsound_mac.mm
@@ -174,6 +174,7 @@ NSSound *QAuServerMac::createNSSound(const QString &fileName, QSound *qSound)
NSSound * const nsSound = [[NSSound alloc] initWithContentsOfFile: nsFileName byReference:YES];
QMacSoundDelegate * const delegate = [[QMacSoundDelegate alloc] initWithQSound:qSound:this];
[nsSound setDelegate:delegate];
+ [nsFileName release];
return nsSound;
}
diff --git a/src/gui/kernel/qstandardgestures.cpp b/src/gui/kernel/qstandardgestures.cpp
index 86bf1b2e..a575717 100644
--- a/src/gui/kernel/qstandardgestures.cpp
+++ b/src/gui/kernel/qstandardgestures.cpp
@@ -301,7 +301,7 @@ QGestureRecognizer::Result QSwipeGestureRecognizer::recognize(QGesture *state,
switch (event->type()) {
case QEvent::TouchBegin: {
d->speed = 1;
- d->time = QTime::currentTime();
+ d->time.start();
d->started = true;
result = QGestureRecognizer::MayBeGesture;
break;
@@ -338,11 +338,10 @@ QGestureRecognizer::Result QSwipeGestureRecognizer::recognize(QGesture *state,
p3.screenPos().y() - d->lastPositions[2].y()) / 3;
const int distance = xDistance >= yDistance ? xDistance : yDistance;
- int elapsedTime = d->time.msecsTo(QTime::currentTime());
+ int elapsedTime = d->time.restart();
if (!elapsedTime)
elapsedTime = 1;
d->speed = 0.9 * d->speed + distance / elapsedTime;
- d->time = QTime::currentTime();
d->swipeAngle = QLineF(p1.startScreenPos(), p1.screenPos()).angle();
static const int MoveThreshold = 50;
@@ -405,7 +404,7 @@ void QSwipeGestureRecognizer::reset(QGesture *state)
d->lastPositions[0] = d->lastPositions[1] = d->lastPositions[2] = QPoint();
d->started = false;
d->speed = 0;
- d->time = QTime();
+ d->time.invalidate();
QGestureRecognizer::reset(state);
}
diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm
index 9560952..b1e4c94 100644
--- a/src/gui/kernel/qt_cocoa_helpers_mac.mm
+++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm
@@ -139,7 +139,7 @@ void QMacWindowFader::performFade()
extern bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); // qapplication.cpp;
extern QWidget * mac_mouse_grabber;
-extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
+extern QWidget *qt_button_down; //qapplication_mac.cpp
void macWindowFade(void * /*OSWindowRef*/ window, float durationSeconds)
{
@@ -373,7 +373,7 @@ QMacTabletHash *qt_mac_tablet_hash()
// Clears the QWidget pointer that each QCocoaView holds.
void qt_mac_clearCocoaViewQWidgetPointers(QWidget *widget)
{
- QCocoaView *cocoaView = reinterpret_cast<QCocoaView *>(qt_mac_nativeview_for(widget));
+ QT_MANGLE_NAMESPACE(QCocoaView) *cocoaView = reinterpret_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(qt_mac_nativeview_for(widget));
if (cocoaView && [cocoaView respondsToSelector:@selector(qt_qwidget)]) {
[cocoaView qt_clearQWidget];
}
@@ -652,8 +652,7 @@ bool qt_dispatchKeyEventWithCocoa(void * /*NSEvent * */ keyEvent, QWidget *widge
UInt32 macScanCode = 1;
QKeyEventEx ke(cocoaEvent2QtEvent([event type]), qtKey, keyMods, text, [event isARepeat], qMax(1, keyLength),
macScanCode, [event keyCode], [event modifierFlags]);
- qt_sendSpontaneousEvent(widgetToGetEvent, &ke);
- return ke.isAccepted();
+ return qt_sendSpontaneousEvent(widgetToGetEvent, &ke) && ke.isAccepted();
}
#endif
@@ -684,8 +683,16 @@ bool qt_dispatchKeyEvent(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEve
EventRef key_event = static_cast<EventRef>(const_cast<void *>([event eventRef]));
Q_ASSERT(key_event);
if ([event type] == NSKeyDown) {
- qt_keymapper_private()->updateKeyMap(0, key_event, 0);
+ NSString *characters = [event characters];
+ unichar value = [characters characterAtIndex:0];
+ qt_keymapper_private()->updateKeyMap(0, key_event, (void *)&value);
}
+
+ // Redirect keys to alien widgets.
+ if (widgetToGetEvent->testAttribute(Qt::WA_NativeWindow) == false) {
+ widgetToGetEvent = qApp->focusWidget();
+ }
+
if (widgetToGetEvent == 0)
return false;
@@ -695,8 +702,8 @@ bool qt_dispatchKeyEvent(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEve
if (mustUseCocoaKeyEvent())
return qt_dispatchKeyEventWithCocoa(keyEvent, widgetToGetEvent);
bool isAccepted;
- qt_keymapper_private()->translateKeyEvent(widgetToGetEvent, 0, key_event, &isAccepted, true);
- return isAccepted;
+ bool consumed = qt_keymapper_private()->translateKeyEvent(widgetToGetEvent, 0, key_event, &isAccepted, true);
+ return consumed && isAccepted;
#endif
}
@@ -940,7 +947,7 @@ bool qt_mac_handleMouseEvent(void * /* NSView * */view, void * /* NSEvent * */ev
[static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(tmpView) qt_qwidget];
}
} else {
- extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
+ extern QWidget * qt_button_down; //qapplication_mac.cpp
QPoint pos;
widgetToGetMouse = QApplicationPrivate::pickMouseReceiver(qwidget, qglobalPoint,
pos, eventType,
@@ -952,7 +959,20 @@ bool qt_mac_handleMouseEvent(void * /* NSView * */view, void * /* NSEvent * */ev
return false;
NSPoint localPoint = [tmpView convertPoint:windowPoint fromView:nil];
- QPoint qlocalPoint(localPoint.x, localPoint.y);
+ QPoint qlocalPoint = QPoint(localPoint.x, localPoint.y);
+
+ // Search for alien child widgets (either on this qwidget or on the popup)
+ if (widgetToGetMouse->testAttribute(Qt::WA_NativeWindow) == false || qt_widget_private(widgetToGetMouse)->hasAlienChildren) {
+ QPoint qScreenPoint = flipPoint(globalPoint).toPoint();
+#ifdef ALIEN_DEBUG
+ qDebug() << "alien mouse event" << qScreenPoint << possibleAlien;
+#endif
+ QWidget *possibleAlien = widgetToGetMouse->childAt(qlocalPoint);
+ if (possibleAlien) {
+ qlocalPoint = possibleAlien->mapFromGlobal(widgetToGetMouse->mapToGlobal(qlocalPoint));
+ widgetToGetMouse = possibleAlien;
+ }
+ }
EventRef carbonEvent = static_cast<EventRef>(const_cast<void *>([theEvent eventRef]));
if (qt_mac_sendMacEventToWidget(widgetToGetMouse, carbonEvent))
@@ -997,7 +1017,19 @@ bool qt_mac_handleMouseEvent(void * /* NSView * */view, void * /* NSEvent * */ev
}
[QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]->localPoint = localPoint;
QMouseEvent qme(eventType, qlocalPoint, qglobalPoint, button, buttons, keyMods);
- qt_sendSpontaneousEvent(widgetToGetMouse, &qme);
+
+#ifdef ALIEN_DEBUG
+ qDebug() << "sending mouse event to" << widgetToGetMouse;
+#endif
+ extern QWidget *qt_button_down;
+ extern QPointer<QWidget> qt_last_mouse_receiver;
+
+ if (qwidget->testAttribute(Qt::WA_NativeWindow) && qt_widget_private(qwidget)->hasAlienChildren == false)
+ qt_sendSpontaneousEvent(widgetToGetMouse, &qme);
+ else
+ QApplicationPrivate::sendMouseEvent(widgetToGetMouse, &qme, widgetToGetMouse, qwidget, &qt_button_down,
+ qt_last_mouse_receiver);
+
if (eventType == QEvent::MouseButtonPress && button == Qt::RightButton) {
QContextMenuEvent qcme(QContextMenuEvent::Mouse, qlocalPoint, qglobalPoint, keyMods);
qt_sendSpontaneousEvent(widgetToGetMouse, &qcme);
@@ -1355,4 +1387,12 @@ QMacCocoaAutoReleasePool::~QMacCocoaAutoReleasePool()
[(NSAutoreleasePool*)pool release];
}
+void qt_mac_post_retranslateAppMenu()
+{
+#ifdef QT_MAC_USE_COCOA
+ QMacCocoaAutoReleasePool pool;
+ qt_cocoaPostMessage([NSApp QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader)], @selector(qtTranslateApplicationMenu));
+#endif
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qt_cocoa_helpers_mac_p.h b/src/gui/kernel/qt_cocoa_helpers_mac_p.h
index c43ea55..3fd62a4 100644
--- a/src/gui/kernel/qt_cocoa_helpers_mac_p.h
+++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h
@@ -208,4 +208,6 @@ bool qt_cocoaPostMessage(id target, SEL selector);
#endif
+void qt_mac_post_retranslateAppMenu();
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h
index 735ca7a..a714221 100644
--- a/src/gui/kernel/qt_s60_p.h
+++ b/src/gui/kernel/qt_s60_p.h
@@ -68,12 +68,12 @@
#include <eikappui.h>
#ifdef Q_WS_S60
-#include <aknutils.h> // AknLayoutUtils
+#include <AknUtils.h> // AknLayoutUtils
#include <avkon.hrh> // EEikStatusPaneUidTitle
#include <akntitle.h> // CAknTitlePane
#include <akncontext.h> // CAknContextPane
#include <eikspane.h> // CEikStatusPane
-#include <aknpopupfader.h> // MAknFadedComponent and TAknPopupFader
+#include <AknPopupFader.h> // MAknFadedComponent and TAknPopupFader
#endif
QT_BEGIN_NAMESPACE
@@ -122,6 +122,7 @@ public:
int qtOwnsS60Environment : 1;
int supportsPremultipliedAlpha : 1;
int avkonComponentsSupportTransparency : 1;
+ int menuBeingConstructed : 1;
QApplication::QS60MainApplicationFactory s60ApplicationFactory; // typedef'ed pointer type
static inline void updateScreenSize();
static inline RWsSession& wsSession();
@@ -212,6 +213,7 @@ private:
#ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER
void translateAdvancedPointerEvent(const TAdvancedPointerEvent *event);
#endif
+ void handleClientAreaChange();
private:
static QSymbianControl *lastFocusedControl;
diff --git a/src/gui/kernel/qt_x11_p.h b/src/gui/kernel/qt_x11_p.h
index 167557b..7383382 100644
--- a/src/gui/kernel/qt_x11_p.h
+++ b/src/gui/kernel/qt_x11_p.h
@@ -439,6 +439,12 @@ struct QX11Data
int xinput_eventbase;
int xinput_errorbase;
+ // for XKEYBOARD support
+ bool use_xkb;
+ int xkb_major;
+ int xkb_eventbase;
+ int xkb_errorbase;
+
QList<QWidget *> deferred_map;
struct ScrollInProgress {
long id;
@@ -626,6 +632,8 @@ struct QX11Data
_NET_SYSTEM_TRAY_VISUAL,
+ _NET_ACTIVE_WINDOW,
+
// Property formats
COMPOUND_TEXT,
TEXT,
@@ -672,6 +680,9 @@ struct QX11Data
XWacomCursor,
XWacomEraser,
+ XTabletStylus,
+ XTabletEraser,
+
NPredefinedAtoms,
_QT_SETTINGS_TIMESTAMP = NPredefinedAtoms,
diff --git a/src/gui/kernel/qtooltip.cpp b/src/gui/kernel/qtooltip.cpp
index c912129..1343959 100644
--- a/src/gui/kernel/qtooltip.cpp
+++ b/src/gui/kernel/qtooltip.cpp
@@ -368,7 +368,16 @@ void QTipLabel::placeTip(const QPoint &pos, QWidget *w)
#ifdef Q_WS_MAC
- QRect screen = QApplication::desktop()->availableGeometry(getTipScreen(pos, w));
+ // When in full screen mode, there is no Dock nor Menu so we can use
+ // the whole screen for displaying the tooltip. However when not in
+ // full screen mode we need to save space for the dock, so we use
+ // availableGeometry instead.
+ extern bool qt_mac_app_fullscreen; //qapplication_mac.mm
+ QRect screen;
+ if(qt_mac_app_fullscreen)
+ screen = QApplication::desktop()->screenGeometry(getTipScreen(pos, w));
+ else
+ screen = QApplication::desktop()->availableGeometry(getTipScreen(pos, w));
#else
QRect screen = QApplication::desktop()->screenGeometry(getTipScreen(pos, w));
#endif
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index 2f6ec6b..72ffe87 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -205,6 +205,7 @@ QWidgetPrivate::QWidgetPrivate(int version)
, nativeGesturePanEnabled(0)
#elif defined(Q_WS_MAC)
, needWindowChange(0)
+ , hasAlienChildren(0)
, window_event(0)
, qd_hd(0)
#endif
@@ -1121,7 +1122,8 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
qFatal("QWidget: Cannot create a QWidget when no GUI is being used");
Q_ASSERT(allWidgets);
- allWidgets->insert(q);
+ if (allWidgets)
+ allWidgets->insert(q);
QWidget *desktopWidget = 0;
if (parentWidget && parentWidget->windowType() == Qt::Desktop) {
@@ -1168,6 +1170,10 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
if (f & Qt::MSWindowsOwnDC)
q->setAttribute(Qt::WA_NativeWindow);
+#ifdef Q_WS_MAC
+ q->setAttribute(Qt::WA_NativeWindow);
+#endif
+
q->setAttribute(Qt::WA_QuitOnClose); // might be cleared in adjustQuitOnCloseAttribute()
adjustQuitOnCloseAttribute();
@@ -1263,6 +1269,10 @@ void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
}
if (QWidget *parent = parentWidget()) {
+#ifdef Q_WS_MAC
+ if (testAttribute(Qt::WA_NativeWindow) == false)
+ parent->d_func()->hasAlienChildren = true;
+#endif
if (type & Qt::Window) {
if (!parent->testAttribute(Qt::WA_WState_Created))
parent->createWinId();
@@ -1433,7 +1443,7 @@ QWidget::~QWidget()
}
}
-#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC)
else if (!internalWinId() && isVisible()) {
qApp->d_func()->sendSyntheticEnterLeave(this);
#ifdef Q_WS_QWS
@@ -1496,8 +1506,12 @@ QWidget::~QWidget()
if (QWidgetPrivate::allWidgets) // might have been deleted by ~QApplication
QWidgetPrivate::allWidgets->remove(this);
- QEvent e(QEvent::Destroy);
- QCoreApplication::sendEvent(this, &e);
+ QT_TRY {
+ QEvent e(QEvent::Destroy);
+ QCoreApplication::sendEvent(this, &e);
+ } QT_CATCH(const std::exception&) {
+ // if this fails we can't do anything about it but at least we are not allowed to throw.
+ }
}
int QWidgetPrivate::instanceCounter = 0; // Current number of widget instances
@@ -2306,6 +2320,9 @@ QWidget *QWidget::find(WId id)
WId QWidget::winId() const
{
if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
+#ifdef ALIEN_DEBUG
+ qDebug() << "QWidget::winId: creating native window for" << this;
+#endif
QWidget *that = const_cast<QWidget*>(this);
that->setAttribute(Qt::WA_NativeWindow);
that->d_func()->createWinId();
@@ -2318,6 +2335,10 @@ WId QWidget::winId() const
void QWidgetPrivate::createWinId(WId winid)
{
Q_Q(QWidget);
+
+#ifdef ALIEN_DEBUG
+ qDebug() << "QWidgetPrivate::createWinId for" << q << winid;
+#endif
const bool forceNativeWindow = q->testAttribute(Qt::WA_NativeWindow);
if (!q->testAttribute(Qt::WA_WState_Created) || (forceNativeWindow && !q->internalWinId())) {
if (!q->isWindow()) {
@@ -2360,6 +2381,9 @@ Ensures that the widget has a window system identifier, i.e. that it is known to
void QWidget::createWinId()
{
Q_D(QWidget);
+#ifdef ALIEN_DEBUG
+ qDebug() << "QWidget::createWinId" << this;
+#endif
// qWarning("QWidget::createWinId is obsolete, please fix your code.");
d->createWinId();
}
@@ -5249,7 +5273,15 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
QPaintEngine *paintEngine = pdev->paintEngine();
if (paintEngine) {
setRedirected(pdev, -offset);
+#ifdef Q_WS_MAC
+ // (Alien support) Special case for Mac when redirecting: If the paint device
+ // is of the Widget type we need to set WA_WState_InPaintEvent since painting
+ // outside the paint event is not supported on QWidgets. The attributeis
+ // restored further down.
+ if (pdev->devType() == QInternal::Widget)
+ static_cast<QWidget *>(pdev)->setAttribute(Qt::WA_WState_InPaintEvent);
+#endif
if (sharedPainter)
paintEngine->d_func()->systemClip = toBePainted;
else
@@ -5290,6 +5322,10 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
//restore
if (paintEngine) {
+#ifdef Q_WS_MAC
+ if (pdev->devType() == QInternal::Widget)
+ static_cast<QWidget *>(pdev)->setAttribute(Qt::WA_WState_InPaintEvent, false);
+#endif
restoreRedirected();
if (!sharedPainter)
paintEngine->d_func()->systemRect = QRect();
@@ -5339,7 +5375,6 @@ void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset,
const QRegion &sourceRegion, QWidget::RenderFlags renderFlags,
bool readyToRender)
{
- Q_Q(QWidget);
if (!target) {
qWarning("QWidget::render: null pointer to paint device");
return;
@@ -6140,6 +6175,8 @@ void QWidget::setFocus(Qt::FocusReason reason)
previousProxyFocus = topData->proxyWidget->widget()->focusWidget();
if (previousProxyFocus && previousProxyFocus->focusProxy())
previousProxyFocus = previousProxyFocus->focusProxy();
+ if (previousProxyFocus == this && !topData->proxyWidget->d_func()->proxyIsGivingFocus)
+ return;
}
}
#endif
@@ -6469,7 +6506,7 @@ void QWidget::setTabOrder(QWidget* first, QWidget *second)
// QWidget *fp = first->d_func()->focus_prev;
QWidget *fn = first->d_func()->focus_next;
- if (fn == second)
+ if (fn == second || first == second)
return;
QWidget *sp = second->d_func()->focus_prev;
@@ -7322,7 +7359,7 @@ void QWidgetPrivate::hide_helper()
// next bit tries to move the focus if the focus widget is now
// hidden.
if (wasVisible) {
-#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC)
qApp->d_func()->sendSyntheticEnterLeave(q);
#endif
@@ -7454,7 +7491,7 @@ void QWidget::setVisible(bool visible)
d->show_helper();
-#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC)
qApp->d_func()->sendSyntheticEnterLeave(this);
#endif
}
@@ -7552,6 +7589,23 @@ void QWidgetPrivate::hideChildren(bool spontaneous)
QWidget *widget = qobject_cast<QWidget*>(childList.at(i));
if (!widget || widget->isWindow() || widget->testAttribute(Qt::WA_WState_Hidden))
continue;
+#ifdef QT_MAC_USE_COCOA
+ // Before doing anything we need to make sure that we don't leave anything in a non-consistent state.
+ // When hiding a widget we need to make sure that no mouse_down events are active, because
+ // the mouse_up event will never be received by a hidden widget or one of its descendants.
+ // The solution is simple, before going through with this we check if there are any mouse_down events in
+ // progress, if so we check if it is related to this widget or not. If so, we just reset the mouse_down and
+ // then we continue.
+ // In X11 and Windows we send a mouse_release event, however we don't do that here because we were already
+ // ignoring that from before. I.e. Carbon did not send the mouse release event, so we will not send the
+ // mouse release event. There are two ways to interpret this:
+ // 1. If we don't send the mouse release event, the widget might get into an inconsistent state, i.e. it
+ // might be waiting for a release event that will never arrive.
+ // 2. If we send the mouse release event, then the widget might decide to trigger an action that is not
+ // supposed to trigger because it is not visible.
+ if(widget == qt_button_down)
+ qt_button_down = 0;
+#endif // QT_MAC_USE_COCOA
if (spontaneous)
widget->setAttribute(Qt::WA_Mapped, false);
else
@@ -7569,7 +7623,7 @@ void QWidgetPrivate::hideChildren(bool spontaneous)
widget->d_func()->hide_sys();
}
}
-#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC)
qApp->d_func()->sendSyntheticEnterLeave(widget);
#endif
#ifndef QT_NO_ACCESSIBILITY
@@ -7944,13 +7998,16 @@ inline void setDisabledStyle(QWidget *w, bool setStyle)
// set/reset WS_DISABLED style.
if(w && w->isWindow() && w->isVisible() && w->isEnabled()) {
LONG dwStyle = GetWindowLong(w->winId(), GWL_STYLE);
+ LONG newStyle = dwStyle;
if (setStyle)
- dwStyle |= WS_DISABLED;
+ newStyle |= WS_DISABLED;
else
- dwStyle &= ~WS_DISABLED;
- SetWindowLong(w->winId(), GWL_STYLE, dwStyle);
- // we might need to repaint in some situations (eg. menu)
- w->repaint();
+ newStyle &= ~WS_DISABLED;
+ if (newStyle != dwStyle) {
+ SetWindowLong(w->winId(), GWL_STYLE, newStyle);
+ // we might need to repaint in some situations (eg. menu)
+ w->repaint();
+ }
}
}
#endif
@@ -9787,7 +9844,7 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
desktopWidget = parent;
bool newParent = (parent != parentWidget()) || !wasCreated || desktopWidget;
-#if defined(Q_WS_X11) || defined(Q_WS_WIN)
+#if defined(Q_WS_X11) || defined(Q_WS_WIN) || defined(Q_WS_MAC)
if (newParent && parent && !desktopWidget) {
if (testAttribute(Qt::WA_NativeWindow) && !qApp->testAttribute(Qt::AA_DontCreateNativeWidgetSiblings))
parent->d_func()->enforceNativeChildren();
@@ -10262,6 +10319,29 @@ const QPixmap *QWidget::icon() const
#endif // QT3_SUPPORT
+ /*!
+ \internal
+
+ This just sets the corresponding attribute bit to 1 or 0
+ */
+static void setAttribute_internal(Qt::WidgetAttribute attribute, bool on, QWidgetData *data,
+ QWidgetPrivate *d)
+{
+ if (attribute < int(8*sizeof(uint))) {
+ if (on)
+ data->widget_attributes |= (1<<attribute);
+ else
+ data->widget_attributes &= ~(1<<attribute);
+ } else {
+ const int x = attribute - 8*sizeof(uint);
+ const int int_off = x / (8*sizeof(uint));
+ if (on)
+ d->high_attributes[int_off] |= (1<<(x-(int_off*8*sizeof(uint))));
+ else
+ d->high_attributes[int_off] &= ~(1<<(x-(int_off*8*sizeof(uint))));
+ }
+}
+
/*!
Sets the attribute \a attribute on this widget if \a on is true;
otherwise clears the attribute.
@@ -10288,19 +10368,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
}
#endif
- if (attribute < int(8*sizeof(uint))) {
- if (on)
- data->widget_attributes |= (1<<attribute);
- else
- data->widget_attributes &= ~(1<<attribute);
- } else {
- const int x = attribute - 8*sizeof(uint);
- const int int_off = x / (8*sizeof(uint));
- if (on)
- d->high_attributes[int_off] |= (1<<(x-(int_off*8*sizeof(uint))));
- else
- d->high_attributes[int_off] &= ~(1<<(x-(int_off*8*sizeof(uint))));
- }
+ setAttribute_internal(attribute, on, data, d);
switch (attribute) {
@@ -10359,14 +10427,11 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
#ifdef Q_WS_MAC
{
// We can only have one of these set at a time
- static const int MacSizes[] = { Qt::WA_MacNormalSize, Qt::WA_MacSmallSize,
- Qt::WA_MacMiniSize, 0 };
- for (int i = 0; MacSizes[i] != 0; ++i) {
- if (MacSizes[i] == attribute)
- continue;
- int macsize_x = MacSizes[i] - 8*sizeof(uint);
- int macsize_int_off = macsize_x / (8*sizeof(uint));
- d->high_attributes[macsize_int_off] &= ~(1<<(macsize_x-(macsize_int_off*8*sizeof(uint))));
+ const Qt::WidgetAttribute MacSizes[] = { Qt::WA_MacNormalSize, Qt::WA_MacSmallSize,
+ Qt::WA_MacMiniSize };
+ for (int i = 0; i < 3; ++i) {
+ if (MacSizes[i] != attribute)
+ setAttribute_internal(MacSizes[i], false, data, d);
}
d->macUpdateSizeAttribute();
}
@@ -10433,7 +10498,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
}
case Qt::WA_PaintOnScreen:
d->updateIsOpaque();
-#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_MAC)
// Recreate the widget if it's already created as an alien widget and
// WA_PaintOnScreen is enabled. Paint on screen widgets must have win id.
// So must their children.
@@ -10489,6 +10554,10 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
case Qt::WA_X11OpenGLOverlay:
d->updateIsOpaque();
break;
+ case Qt::WA_X11DoNotAcceptFocus:
+ if (testAttribute(Qt::WA_WState_Created))
+ d->updateX11AcceptFocus();
+ break;
#endif
case Qt::WA_DontShowOnScreen: {
if (on && isVisible()) {
diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h
index 0d7475e9..e12148b 100644
--- a/src/gui/kernel/qwidget.h
+++ b/src/gui/kernel/qwidget.h
@@ -773,6 +773,7 @@ private:
#ifdef Q_WS_X11
friend void qt_net_update_user_time(QWidget *tlw, unsigned long timestamp);
friend void qt_net_remove_user_time(QWidget *tlw);
+ friend void qt_set_winid_on_widget(QWidget*, Qt::HANDLE);
#endif
friend Q_GUI_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget);
diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm
index dcb87fc..3d86936 100644
--- a/src/gui/kernel/qwidget_mac.mm
+++ b/src/gui/kernel/qwidget_mac.mm
@@ -152,6 +152,7 @@ static bool qt_mac_raise_process = true;
static OSWindowRef qt_root_win = 0;
QWidget *mac_mouse_grabber = 0;
QWidget *mac_keyboard_grabber = 0;
+extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
#ifndef QT_MAC_USE_COCOA
#ifdef QT_NAMESPACE
@@ -459,7 +460,13 @@ static bool qt_isGenuineQWidget(OSViewRef ref)
bool qt_isGenuineQWidget(const QWidget *window)
{
- return window && qt_isGenuineQWidget(OSViewRef(window->winId()));
+ if (!window)
+ return false;
+
+ if (!window->internalWinId())
+ return true; //alien
+
+ return qt_isGenuineQWidget(OSViewRef(window->internalWinId()));
}
Q_GUI_EXPORT OSWindowRef qt_mac_window_for(const QWidget *w)
@@ -866,7 +873,6 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event,
& ~Qt::WindowMaximized));
QApplication::sendSpontaneousEvent(widget, &e);
}
- extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
qt_button_down = 0;
} else if(ekind == kEventWindowCollapsed) {
if (!widget->isMinimized()) {
@@ -894,7 +900,6 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event,
//we send a hide to be like X11/Windows
QEvent e(QEvent::Hide);
QApplication::sendSpontaneousEvent(widget, &e);
- extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
qt_button_down = 0;
} else if(ekind == kEventWindowToolbarSwitchMode) {
macSendToolbarChangeEvent(widget);
@@ -1268,6 +1273,11 @@ OSStatus QWidgetPrivate::qt_widget_event(EventHandlerCallRef er, EventRef event,
if (widget->isVisible() && widget->updatesEnabled()) { //process the actual paint event.
if(widget->testAttribute(Qt::WA_WState_InPaintEvent))
qWarning("QWidget::repaint: Recursive repaint detected");
+ if (widget->isWindow() && !widget->d_func()->isOpaque
+ && !widget->testAttribute(Qt::WA_MacBrushedMetal)) {
+ QRect qrgnRect = qrgn.boundingRect();
+ CGContextClearRect(cg, CGRectMake(qrgnRect.x(), qrgnRect.y(), qrgnRect.width(), qrgnRect.height()));
+ }
QPoint redirectionOffset(0, 0);
QWidget *tl = widget->window();
@@ -1318,13 +1328,6 @@ OSStatus QWidgetPrivate::qt_widget_event(EventHandlerCallRef er, EventRef event,
widget->d_func()->restoreRedirected();
}
- if (widget->isWindow() && !widget->d_func()->isOpaque
- && !widget->testAttribute(Qt::WA_MacBrushedMetal)) {
- QRect qrgnRect = qrgn.boundingRect();
- CGContextClearRect(cg, CGRectMake(qrgnRect.x(), qrgnRect.y(), qrgnRect.width(), qrgnRect.height()));
- }
-
-
if(!HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget))
CallNextEventHandler(er, event);
@@ -1521,7 +1524,6 @@ OSStatus QWidgetPrivate::qt_widget_event(EventHandlerCallRef er, EventRef event,
if (widget) {
qt_event_request_window_change(widget);
if (!HIViewIsVisible(HIViewRef(widget->winId()))) {
- extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
if (widget == qt_button_down)
qt_button_down = 0;
}
@@ -1530,7 +1532,6 @@ OSStatus QWidgetPrivate::qt_widget_event(EventHandlerCallRef er, EventRef event,
break; }
case kEventClassMouse: {
bool send_to_app = false;
- extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
if(qt_button_down)
send_to_app = true;
if(send_to_app) {
@@ -2608,7 +2609,16 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
}
} else {
data.fstrut_dirty = false; // non-toplevel widgets don't have a frame, so no need to update the strut
- if(OSViewRef osview = qt_mac_create_widget(q, this, qt_mac_nativeview_for(parentWidget))) {
+
+#ifdef QT_MAC_USE_COCOA
+ if (q->testAttribute(Qt::WA_NativeWindow) == false ||
+ q->internalWinId() != 0) {
+#ifdef ALIEN_DEBUG
+ qDebug() << "Skipping native widget creation for" << this;
+#endif
+ } else
+#endif
+ if (OSViewRef osview = qt_mac_create_widget(q, this, qt_mac_nativeview_for(parentWidget))) {
#ifndef QT_MAC_USE_COCOA
HIRect bounds = CGRectMake(data.crect.x(), data.crect.y(), data.crect.width(), data.crect.height());
HIViewSetFrame(osview, &bounds);
@@ -2869,9 +2879,12 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
q->setAttribute(Qt::WA_WState_Visible, false);
q->setAttribute(Qt::WA_WState_Hidden, false);
adjustFlags(data.window_flags, q);
- // keep compatibility with previous versions, we need to preserve the created state
- // (but we recreate the winId for the widget being reparented, again for compatibility)
- if (wasCreated || (!q->isWindow() && parent->testAttribute(Qt::WA_WState_Created))) {
+ // keep compatibility with previous versions, we need to preserve the created state.
+ // (but we recreate the winId for the widget being reparented, again for compatibility,
+ // unless this is an alien widget. )
+ const bool nonWindowWithCreatedParent = !q->isWindow() && parent->testAttribute(Qt::WA_WState_Created);
+ const bool nativeWidget = q->internalWinId() != 0;
+ if (wasCreated || nativeWidget && nonWindowWithCreatedParent) {
createWinId();
if (q->isWindow()) {
#ifndef QT_MAC_USE_COCOA
@@ -2955,7 +2968,7 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
QPoint QWidget::mapToGlobal(const QPoint &pos) const
{
Q_D(const QWidget);
- if (!testAttribute(Qt::WA_WState_Created)) {
+ if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
QPoint p = pos + data->crect.topLeft();
return isWindow() ? p : parentWidget()->mapToGlobal(p);
}
@@ -2982,7 +2995,7 @@ QPoint QWidget::mapToGlobal(const QPoint &pos) const
QPoint QWidget::mapFromGlobal(const QPoint &pos) const
{
Q_D(const QWidget);
- if (!testAttribute(Qt::WA_WState_Created)) {
+ if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
QPoint p = isWindow() ? pos : parentWidget()->mapFromGlobal(pos);
return p - data->crect.topLeft();
}
@@ -3281,7 +3294,7 @@ void QWidgetPrivate::update_sys(const QRect &r)
#ifndef QT_MAC_USE_COCOA
HIViewSetNeedsDisplay(qt_mac_nativeview_for(q), true);
#else
- [qt_mac_nativeview_for(q) setNeedsDisplay:YES];
+ qt_mac_set_needs_display(q, QRegion());
#endif
return;
}
@@ -3319,11 +3332,24 @@ void QWidgetPrivate::update_sys(const QRegion &rgn)
HIViewSetNeedsDisplay(qt_mac_nativeview_for(q), true); // do a complete repaint on overflow.
}
#else
- // Cocoa doesn't do regions, it seems more efficient to just update the bounding rect instead of a potential number of message passes for each rect.
- const QRect &boundingRect = rgn.boundingRect();
- [qt_mac_nativeview_for(q) setNeedsDisplayInRect:NSMakeRect(boundingRect.x(),
- boundingRect.y(), boundingRect.width(),
- boundingRect.height())];
+ // Alien support: get the first native ancestor widget (will be q itself in the non-alien case),
+ // map the coordinates from q space to NSView space and invalidate the rect.
+ QWidget *nativeParent = q->internalWinId() ? q : q->nativeParentWidget();
+ if (nativeParent == 0)
+ return;
+
+ QVector<QRect> rects = rgn.rects();
+ for (int i = 0; i < rects.count(); ++i) {
+ const QRect &rect = rects.at(i);
+
+ const QRect nativeBoundingRect = QRect(
+ QPoint(q->mapTo(nativeParent, rect.topLeft())),
+ QSize(rect.size()));
+
+ [qt_mac_nativeview_for(nativeParent) setNeedsDisplayInRect:NSMakeRect(nativeBoundingRect.x(),
+ nativeBoundingRect.y(), nativeBoundingRect.width(),
+ nativeBoundingRect.height())];
+ }
#endif
}
@@ -3405,8 +3431,10 @@ void QWidgetPrivate::show_sys()
// The window is modally shaddowed, so we need to make
// sure that we don't pop in front of the modal window:
[window orderFront:window];
- if (NSWindow *modalWin = qt_mac_window_for(top))
- [modalWin orderFront:window];
+ if (!top->testAttribute(Qt::WA_DontShowOnScreen)) {
+ if (NSWindow *modalWin = qt_mac_window_for(top))
+ [modalWin orderFront:window];
+ }
}
#endif
if (q->windowType() == Qt::Popup) {
@@ -3465,7 +3493,6 @@ void QWidgetPrivate::hide_sys()
Q_Q(QWidget);
if((q->windowType() == Qt::Desktop)) //you can't hide the desktop!
return;
-
QMacCocoaAutoReleasePool pool;
if(q->isWindow()) {
#ifdef QT_MAC_USE_COCOA
@@ -3906,7 +3933,7 @@ void QWidgetPrivate::stackUnder_sys(QWidget *w)
widget, either by scrolling its contents or repainting, depending on the WA_StaticContents
flag
*/
-static void qt_mac_update_widget_posisiton(QWidget *q, QRect oldRect, QRect newRect)
+static void qt_mac_update_widget_position(QWidget *q, QRect oldRect, QRect newRect)
{
#ifndef QT_MAC_USE_COCOA
HIRect bounds = CGRectMake(newRect.x(), newRect.y(),
@@ -4003,7 +4030,7 @@ static void qt_mac_update_widget_posisiton(QWidget *q, QRect oldRect, QRect newR
#else
Q_UNUSED(oldRect);
NSRect bounds = NSMakeRect(newRect.x(), newRect.y(),
- newRect.width(), newRect.height());
+ newRect.width(), newRect.height());
[qt_mac_nativeview_for(q) setFrame:bounds];
#endif
}
@@ -4040,7 +4067,8 @@ void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect)
QRect xrect = data.crect;
QRect parentWRect;
- if (q->isWindow() && topData()->embedded) {
+ bool isEmbeddedWindow = (q->isWindow() && topData()->embedded);
+ if (isEmbeddedWindow) {
#ifndef QT_MAC_USE_COCOA
HIViewRef parentView = HIViewGetSuperview(qt_mac_nativeview_for(q));
#else
@@ -4065,7 +4093,7 @@ void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect)
if (parentWRect.isValid()) {
// parent is clipped, and we have to clip to the same limit as parent
- if (!parentWRect.contains(xrect)) {
+ if (!parentWRect.contains(xrect) && !isEmbeddedWindow) {
xrect &= parentWRect;
wrect = xrect;
//translate from parent's to my Qt coord sys
@@ -4167,7 +4195,7 @@ void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect)
}
}
- qt_mac_update_widget_posisiton(q, oldRect, xrect);
+ qt_mac_update_widget_position(q, oldRect, xrect);
if (jump)
q->update();
@@ -4759,8 +4787,10 @@ void QWidgetPrivate::syncCocoaMask()
if (!q->testAttribute(Qt::WA_WState_Created) || !extra)
return;
- if (extra->hasMask && extra->maskBits.size() != q->size()) {
- extra->maskBits = QImage(q->size(), QImage::Format_Mono);
+ if (extra->hasMask) {
+ if(extra->maskBits.size() != q->size()) {
+ extra->maskBits = QImage(q->size(), QImage::Format_Mono);
+ }
extra->maskBits.fill(QColor(Qt::color1).rgba());
extra->maskBits.setNumColors(2);
extra->maskBits.setColor(0, QColor(Qt::color0).rgba());
@@ -4804,7 +4834,7 @@ void QWidgetPrivate::finishCocoaMaskSetup()
[window setOpaque:(extra->imageMask == 0)];
[window invalidateShadow];
}
- [qt_mac_nativeview_for(q) setNeedsDisplay:YES];
+ qt_mac_set_needs_display(q, QRegion());
}
#endif
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index efd9a0a..89ea256 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -234,6 +234,15 @@ struct QWExtra {
uint activated : 1; // RWindowBase::Activated has been called
/**
+ * If this bit is set, each native widget receives the signals from the
+ * Symbian control immediately before and immediately after draw ops are
+ * sent to the window server for this control:
+ * void beginNativePaintEvent(const QRect &paintRect);
+ * void endNativePaintEvent(const QRect &paintRect);
+ */
+ uint receiveNativePaintEvents : 1;
+
+ /**
* Defines the behaviour of QSymbianControl::Draw.
*/
enum NativePaintMode {
@@ -258,16 +267,7 @@ struct QWExtra {
Default = Blit
};
- NativePaintMode nativePaintMode : 2;
-
- /**
- * If this bit is set, each native widget receives the signals from the
- * Symbian control immediately before and immediately after draw ops are
- * sent to the window server for this control:
- * void beginNativePaintEvent(const QRect &paintRect);
- * void endNativePaintEvent(const QRect &paintRect);
- */
- uint receiveNativePaintEvents : 1;
+ NativePaintMode nativePaintMode;
#endif
};
@@ -680,7 +680,7 @@ public:
QMap<Qt::GestureType, Qt::GestureFlags> gestureContext;
// Bit fields.
- uint high_attributes[3]; // the low ones are in QWidget::widget_attributes
+ uint high_attributes[4]; // the low ones are in QWidget::widget_attributes
QPalette::ColorRole fg_role : 8;
QPalette::ColorRole bg_role : 8;
uint dirtyOpaqueChildren : 1;
@@ -703,6 +703,7 @@ public:
void setNetWmWindowTypes();
void x11UpdateIsOpaque();
bool isBackgroundInherited() const;
+ void updateX11AcceptFocus();
#elif defined(Q_WS_WIN) // <--------------------------------------------------------- WIN
uint noPaintOnScreen : 1; // see qwidget_win.cpp ::paintEngine()
uint nativeGesturePanEnabled : 1;
@@ -720,6 +721,7 @@ public:
#elif defined(Q_WS_MAC) // <--------------------------------------------------------- MAC
// This is new stuff
uint needWindowChange : 1;
+ uint hasAlienChildren : 1;
// Each wiget keeps a list of all its child and grandchild OpenGL widgets.
// This list is used to update the gl context whenever a parent and a granparent
diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp
index ebd289c..bfa7050 100644
--- a/src/gui/kernel/qwidget_s60.cpp
+++ b/src/gui/kernel/qwidget_s60.cpp
@@ -1037,15 +1037,34 @@ QPoint QWidget::mapFromGlobal(const QPoint &pos) const
return widgetPos;
}
+static Qt::WindowStates effectiveState(Qt::WindowStates state)
+{
+ if (state & Qt::WindowMinimized)
+ return Qt::WindowMinimized;
+ else if (state & Qt::WindowFullScreen)
+ return Qt::WindowFullScreen;
+ else if (state & Qt::WindowMaximized)
+ return Qt::WindowMaximized;
+ return Qt::WindowNoState;
+}
+
void QWidget::setWindowState(Qt::WindowStates newstate)
{
Q_D(QWidget);
Qt::WindowStates oldstate = windowState();
- if (oldstate == newstate)
+
+ const TBool isFullscreen = newstate & Qt::WindowFullScreen;
+ const TBool cbaRequested = windowFlags() & Qt::WindowSoftkeysVisibleHint;
+ const TBool cbaVisible = CEikButtonGroupContainer::Current() ? true : false;
+ const TBool softkeyVisibilityChange = isFullscreen && (cbaRequested != cbaVisible);
+
+ if (oldstate == newstate && !softkeyVisibilityChange)
return;
if (isWindow()) {
+ const bool wasResized = testAttribute(Qt::WA_Resized);
+ const bool wasMoved = testAttribute(Qt::WA_Moved);
QSymbianControl *window = static_cast<QSymbianControl *>(effectiveWinId());
if (window && newstate & Qt::WindowMinimized) {
@@ -1058,36 +1077,58 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
#ifdef Q_WS_S60
// Hide window decoration when switching to fullsccreen / minimized otherwise show decoration.
- // The window decoration visibility has to be changed before doing actual window state
- // change since in that order the availableGeometry will return directly the right size and
+ // The window decoration visibility has to be changed before doing actual window state
+ // change since in that order the availableGeometry will return directly the right size and
// we will avoid unnecessarty redraws
- CEikStatusPane* statusPane = S60->statusPane();
- CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer();
- TBool visible = !(newstate & (Qt::WindowFullScreen | Qt::WindowMinimized));
+ CEikStatusPane *statusPane = S60->statusPane();
+ CEikButtonGroupContainer *buttonGroup = S60->buttonGroupContainer();
+ TBool visible = !(newstate & (Qt::WindowFullScreen | Qt::WindowMinimized));
if (statusPane)
statusPane->MakeVisible(visible);
- if (buttonGroup)
- buttonGroup->MakeVisible(visible);
+ if (buttonGroup) {
+ // Visibility
+ buttonGroup->MakeVisible(visible || (isFullscreen && cbaRequested));
+
+ // Responsiviness
+ CEikCba *cba = static_cast<CEikCba *>( buttonGroup->ButtonGroup() ); // downcast from MEikButtonGroup
+ TUint cbaFlags = cba->ButtonGroupFlags();
+ if(windowFlags() & Qt::WindowSoftkeysRespondHint)
+ cbaFlags |= EAknCBAFlagRespondWhenInvisible;
+ else
+ cbaFlags &= ~EAknCBAFlagRespondWhenInvisible;
+ cba->SetButtonGroupFlags(cbaFlags);
+ }
#endif // Q_WS_S60
createWinId();
Q_ASSERT(testAttribute(Qt::WA_WState_Created));
// Ensure the initial size is valid, since we store it as normalGeometry below.
- if (!testAttribute(Qt::WA_Resized) && !isVisible())
+ if (!wasResized && !isVisible())
adjustSize();
QTLWExtra *top = d->topData();
const QRect normalGeometry = (top->normalGeometry.width() < 0) ? geometry() : top->normalGeometry;
- if (newstate & Qt::WindowFullScreen)
+
+ const bool cbaVisibilityHint = windowFlags() & Qt::WindowSoftkeysVisibleHint;
+ if (newstate & Qt::WindowFullScreen && !cbaVisibilityHint)
setGeometry(qApp->desktop()->screenGeometry(this));
- else if (newstate & Qt::WindowMaximized)
+ else if (newstate & Qt::WindowMaximized || ((newstate & Qt::WindowFullScreen) && cbaVisibilityHint))
setGeometry(qApp->desktop()->availableGeometry(this));
else
setGeometry(normalGeometry);
//restore normal geometry
top->normalGeometry = normalGeometry;
+
+ // FixMe QTBUG-8977
+ // In some platforms, WA_Resized and WA_Moved are also not set when application window state is
+ // anything else than normal. In Symbian we can restore them only for normal window state since
+ // restoring for other modes, will make fluidlauncher to be launched in wrong size (200x100)
+ if (effectiveState(newstate) == Qt::WindowNoState) {
+ setAttribute(Qt::WA_Resized, wasResized);
+ setAttribute(Qt::WA_Moved, wasMoved);
+ }
}
data->window_state = newstate;
@@ -1220,8 +1261,10 @@ void QWidget::releaseMouse()
{
if (!qt_nograb() && QWidgetPrivate::mouseGrabber == this) {
Q_ASSERT(testAttribute(Qt::WA_WState_Created));
- WId id = effectiveWinId();
- id->SetPointerCapture(false);
+ if(!window()->isModal()) {
+ WId id = effectiveWinId();
+ id->SetPointerCapture(false);
+ }
QWidgetPrivate::mouseGrabber = 0;
#ifndef QT_NO_CURSOR
QApplication::restoreOverrideCursor();
diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp
index 8cab387..7d647b7 100644
--- a/src/gui/kernel/qwidget_win.cpp
+++ b/src/gui/kernel/qwidget_win.cpp
@@ -243,7 +243,7 @@ static QCursor *mouseGrbCur = 0;
static QWidget *keyboardGrb = 0;
static HHOOK journalRec = 0;
-extern "C" LRESULT CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
+extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
#define XCOORD_MAX 16383
#define WRECT_MAX 16383
@@ -825,7 +825,7 @@ QCursor *qt_grab_cursor()
// The procedure does nothing, but is required for mousegrabbing to work
#ifndef Q_WS_WINCE
-LRESULT CALLBACK qJournalRecordProc(int nCode, WPARAM wParam, LPARAM lParam)
+LRESULT QT_WIN_CALLBACK qJournalRecordProc(int nCode, WPARAM wParam, LPARAM lParam)
{
return CallNextHookEx(journalRec, nCode, wParam, lParam);
}
@@ -2073,6 +2073,8 @@ void QWidgetPrivate::winSetupGestures()
if (!q || !q->isVisible() || !nativeGesturePanEnabled)
return;
+ if (!QApplicationPrivate::HasTouchSupport)
+ return;
QApplicationPrivate *qAppPriv = QApplicationPrivate::instance();
if (!qAppPriv->SetGestureConfig)
return;
diff --git a/src/gui/kernel/qwidget_wince.cpp b/src/gui/kernel/qwidget_wince.cpp
index fa94703..509847b 100644
--- a/src/gui/kernel/qwidget_wince.cpp
+++ b/src/gui/kernel/qwidget_wince.cpp
@@ -46,7 +46,7 @@
QT_BEGIN_NAMESPACE
const QString qt_reg_winclass(QWidget *w); // defined in qapplication_win.cpp
-extern "C" LRESULT CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
+extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
//#define TABLET_DEBUG
#define PACKETDATA (PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE \
@@ -586,7 +586,7 @@ void QWidgetPrivate::setWindowOpacity_sys(qreal level) {
}
// The procedure does nothing, but is required for mousegrabbing to work
-LRESULT CALLBACK qJournalRecordProc(int nCode, WPARAM wParam, LPARAM lParam) {
+LRESULT QT_WIN_CALLBACK qJournalRecordProc(int nCode, WPARAM wParam, LPARAM lParam) {
Q_UNUSED(nCode);
Q_UNUSED(wParam);
Q_UNUSED(lParam);
diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp
index 10fb009..37ac6bf 100644
--- a/src/gui/kernel/qwidget_x11.cpp
+++ b/src/gui/kernel/qwidget_x11.cpp
@@ -49,7 +49,7 @@
#include "qbitmap.h"
#include "qlayout.h"
#include "qtextcodec.h"
-#include "qdatetime.h"
+#include "qelapsedtimer.h"
#include "qcursor.h"
#include "qstack.h"
#include "qcolormap.h"
@@ -352,7 +352,7 @@ Q_GUI_EXPORT void qt_x11_wait_for_window_manager(QWidget* w)
return;
QApplication::flush();
XEvent ev;
- QTime t;
+ QElapsedTimer t;
t.start();
static const int maximumWaitTime = 2000;
if (!w->testAttribute(Qt::WA_WState_Created))
@@ -369,7 +369,7 @@ Q_GUI_EXPORT void qt_x11_wait_for_window_manager(QWidget* w)
// ConfigureNotify ... MapNotify ... Expose
enum State {
- Initial, Reparented, Mapped
+ Initial, Mapped
} state = Initial;
do {
@@ -377,33 +377,15 @@ Q_GUI_EXPORT void qt_x11_wait_for_window_manager(QWidget* w)
XNextEvent(X11->display, &ev);
qApp->x11ProcessEvent(&ev);
- if (w->windowFlags() & Qt::X11BypassWindowManagerHint) {
- switch (state) {
- case Initial:
- case Reparented:
- if (ev.type == MapNotify && ev.xany.window == winid)
- state = Mapped;
- break;
- case Mapped:
- if (ev.type == Expose && ev.xany.window == winid)
- return;
- break;
- }
- } else {
- switch (state) {
- case Initial:
- if (ev.type == ReparentNotify && ev.xany.window == winid)
- state = Reparented;
- break;
- case Reparented:
- if (ev.type == MapNotify && ev.xany.window == winid)
- state = Mapped;
- break;
- case Mapped:
- if (ev.type == Expose && ev.xany.window == winid)
- return;
- break;
- }
+ switch (state) {
+ case Initial:
+ if (ev.type == MapNotify && ev.xany.window == winid)
+ state = Mapped;
+ break;
+ case Mapped:
+ if (ev.type == Expose && ev.xany.window == winid)
+ return;
+ break;
}
} else {
if (!XEventsQueued(X11->display, QueuedAfterFlush))
@@ -798,7 +780,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
XWMHints wm_hints; // window manager hints
memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
wm_hints.flags = InputHint | StateHint | WindowGroupHint;
- wm_hints.input = True;
+ wm_hints.input = q->testAttribute(Qt::WA_X11DoNotAcceptFocus) ? False : True;
wm_hints.initial_state = NormalState;
wm_hints.window_group = X11->wm_client_leader;
@@ -1184,7 +1166,7 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
adjustFlags(data.window_flags, q);
// keep compatibility with previous versions, we need to preserve the created state
// (but we recreate the winId for the widget being reparented, again for compatibility)
- if (wasCreated || (!q->isWindow() && parent->testAttribute(Qt::WA_WState_Created)))
+ if (wasCreated)
createWinId();
if (q->isWindow() || (!parent || parent->isVisible()) || explicitlyHidden)
q->setAttribute(Qt::WA_WState_Hidden);
@@ -1659,7 +1641,29 @@ void QWidget::activateWindow()
if (X11->userTime == 0)
X11->userTime = X11->time;
qt_net_update_user_time(tlw, X11->userTime);
- XSetInputFocus(X11->display, tlw->internalWinId(), XRevertToParent, X11->time);
+
+ if (X11->isSupportedByWM(ATOM(_NET_ACTIVE_WINDOW))
+ && !(tlw->windowFlags() & Qt::X11BypassWindowManagerHint)) {
+ XEvent e;
+ e.xclient.type = ClientMessage;
+ e.xclient.message_type = ATOM(_NET_ACTIVE_WINDOW);
+ e.xclient.display = X11->display;
+ e.xclient.window = tlw->internalWinId();
+ e.xclient.format = 32;
+ e.xclient.data.l[0] = 1; // 1 == application
+ e.xclient.data.l[1] = X11->userTime;
+ if (QWidget *aw = QApplication::activeWindow())
+ e.xclient.data.l[2] = aw->internalWinId();
+ else
+ e.xclient.data.l[2] = XNone;
+ e.xclient.data.l[3] = 0;
+ e.xclient.data.l[4] = 0;
+ XSendEvent(X11->display, RootWindow(X11->display, tlw->x11Info().screen()),
+ false, SubstructureNotifyMask | SubstructureRedirectMask, &e);
+ } else {
+ if (!qt_widget_private(tlw)->topData()->waitingForMapNotify)
+ XSetInputFocus(X11->display, tlw->internalWinId(), XRevertToParent, X11->time);
+ }
}
}
@@ -3048,4 +3052,24 @@ void qt_x11_getX11InfoForWindow(QX11Info * xinfo, const QX11WindowAttributes &at
xinfo->setX11Data(xd);
}
+void QWidgetPrivate::updateX11AcceptFocus()
+{
+ Q_Q(QWidget);
+ if (!q->isWindow() || !q->internalWinId())
+ return;
+
+ XWMHints *h = XGetWMHints(X11->display, q->internalWinId());
+ XWMHints wm_hints;
+ if (!h) {
+ memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
+ h = &wm_hints;
+ }
+ h->flags |= InputHint;
+ h->input = q->testAttribute(Qt::WA_X11DoNotAcceptFocus) ? False : True;
+
+ XSetWMHints(X11->display, q->internalWinId(), h);
+ if (h != &wm_hints)
+ XFree((char *)h);
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qwinnativepangesturerecognizer_win_p.h b/src/gui/kernel/qwinnativepangesturerecognizer_win_p.h
index c65fa50..146b067 100644
--- a/src/gui/kernel/qwinnativepangesturerecognizer_win_p.h
+++ b/src/gui/kernel/qwinnativepangesturerecognizer_win_p.h
@@ -54,6 +54,38 @@
//
#include <QGestureRecognizer>
+#include <objbase.h>
+
+class IInkRectangle;
+class TabletHardwareCapabilities;
+class TabletPropertyMetricUnit;
+DECLARE_INTERFACE_(IInkTablet, IDispatch)
+{
+ STDMETHOD(get_Name)(THIS_ BSTR *Name) PURE;
+ STDMETHOD(get_PlugAndPlayId)(THIS_ BSTR *Id) PURE;
+ STDMETHOD(get_MaximumInputRectangle)(THIS_ IInkRectangle **Rectangle) PURE;
+ STDMETHOD(get_HardwareCapabilities)(THIS_ TabletHardwareCapabilities *Capabilities) PURE;
+ STDMETHOD(IsPacketPropertySupported)(THIS_ BSTR packetPropertyName) PURE;
+ STDMETHOD(GetPropertyMetrics)(THIS_ BSTR propertyName, long *Minimum, long *Maximum, TabletPropertyMetricUnit *Units, float *Resolution) PURE;
+};
+enum TabletDeviceKind
+{
+ TDK_Mouse = 0,
+ TDK_Pen = 1,
+ TDK_Touch = 2
+};
+DECLARE_INTERFACE_(IInkTablet2, IDispatch)
+{
+ STDMETHOD(get_DeviceKind)(THIS_ TabletDeviceKind *Kind) PURE;
+};
+DECLARE_INTERFACE_(IInkTablets, IDispatch)
+{
+ STDMETHOD(get_Count)(THIS_ long *Count) PURE;
+ STDMETHOD(get__NewEnum)(THIS_ IUnknown **_NewEnum) PURE;
+ STDMETHOD(get_DefaultTablet)(THIS_ IInkTablet **DefaultTablet) PURE;
+ STDMETHOD(Item)(THIS_ long Index, IInkTablet **Tablet) PURE;
+ STDMETHOD(IsPacketPropertySupported)(THIS_ BSTR packetPropertyName, VARIANT_BOOL *Supported) PURE;
+};
QT_BEGIN_NAMESPACE
diff --git a/src/gui/kernel/qx11embed_x11.cpp b/src/gui/kernel/qx11embed_x11.cpp
index 35850db..b527e72 100644
--- a/src/gui/kernel/qx11embed_x11.cpp
+++ b/src/gui/kernel/qx11embed_x11.cpp
@@ -47,7 +47,7 @@
#include <qlayout.h>
#include <qstyle.h>
#include <qstyleoption.h>
-#include <qdatetime.h>
+#include <qelapsedtimer.h>
#include <qpointer.h>
#include <qdebug.h>
#include <qx11info_x11.h>
@@ -1231,7 +1231,7 @@ void QX11EmbedContainer::embedClient(WId id)
For safety, we will not wait more than 500 ms, so that we can
preemptively workaround buggy window managers.
*/
- QTime t;
+ QElapsedTimer t;
t.start();
functorData data;
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
index a6cc9c7..ed8ee76 100644
--- a/src/gui/painting/painting.pri
+++ b/src/gui/painting/painting.pri
@@ -91,6 +91,8 @@ SOURCES += \
HEADERS += \
painting/qpaintengine_raster_p.h \
+ painting/qdrawhelper_p.h \
+ painting/qblendfunctions_p.h \
painting/qrasterdefs_p.h \
painting/qgrayraster_p.h
@@ -379,11 +381,23 @@ symbian {
QMAKE_CXXFLAGS.ARMCC *= -O3
}
-neon {
+neon:*-g++* {
DEFINES += QT_HAVE_NEON
HEADERS += painting/qdrawhelper_neon_p.h
SOURCES += painting/qdrawhelper_neon.cpp
QMAKE_CXXFLAGS *= -mfpu=neon
+
+ DRAWHELPER_NEON_ASM_FILES = ../3rdparty/pixman/pixman-arm-neon-asm.S painting/qdrawhelper_neon_asm.S
+
+ neon_compiler.commands = $$QMAKE_CXX -c
+ neon_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT}
+ neon_compiler.dependency_type = TYPE_C
+ neon_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)}
+ neon_compiler.input = DRAWHELPER_NEON_ASM_FILES
+ neon_compiler.variable_out = OBJECTS
+ neon_compiler.name = compiling[neon] ${QMAKE_FILE_IN}
+ silent:neon_compiler.commands = @echo compiling[neon] ${QMAKE_FILE_IN} && $$neon_compiler.commands
+ QMAKE_EXTRA_COMPILERS += neon_compiler
}
contains(QT_CONFIG, zlib) {
diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp
index c73d9f4..8de9eaa 100644
--- a/src/gui/painting/qbackingstore.cpp
+++ b/src/gui/painting/qbackingstore.cpp
@@ -352,6 +352,10 @@ void QWidgetBackingStore::beginPaint(QRegion &toClean, QWidget *widget, QWindowS
// Always flush repainted areas.
dirtyOnScreen += toClean;
+#ifdef Q_WS_QWS
+ toClean.translate(tlwOffset);
+#endif
+
#ifdef QT_NO_PAINT_DEBUG
windowSurface->beginPaint(toClean);
#else
@@ -766,7 +770,12 @@ void QWidgetBackingStore::paintWindowDecoration()
if (decorationRegion.isEmpty())
return;
- windowSurface->beginPaint(decorationRegion);
+ //### The QWS decorations do not always paint the pixels they promise to paint.
+ // This causes painting problems with QWSMemorySurface. Since none of the other
+ // window surfaces actually use the region, passing an empty region is a safe
+ // workaround.
+
+ windowSurface->beginPaint(QRegion());
QPaintEngine *engine = windowSurface->paintDevice()->paintEngine();
Q_ASSERT(engine);
diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp
index dc33896..24908ce 100644
--- a/src/gui/painting/qblendfunctions.cpp
+++ b/src/gui/painting/qblendfunctions.cpp
@@ -40,7 +40,7 @@
****************************************************************************/
#include <qmath.h>
-#include "qdrawhelper_p.h"
+#include "qblendfunctions_p.h"
QT_BEGIN_NAMESPACE
@@ -88,6 +88,8 @@ static inline quint16 convert_argb32_to_rgb16(quint32 spix)
struct Blend_RGB16_on_RGB16_NoAlpha {
inline void write(quint16 *dst, quint16 src) { *dst = src; }
+
+ inline void flush(void *) {}
};
struct Blend_RGB16_on_RGB16_ConstAlpha {
@@ -100,6 +102,8 @@ struct Blend_RGB16_on_RGB16_ConstAlpha {
*dst = BYTE_MUL_RGB16(src, m_alpha) + BYTE_MUL_RGB16(*dst, m_ialpha);
}
+ inline void flush(void *) {}
+
quint32 m_alpha;
quint32 m_ialpha;
};
@@ -114,6 +118,8 @@ struct Blend_ARGB24_on_RGB16_SourceAlpha {
*dst = s;
}
}
+
+ inline void flush(void *) {}
};
struct Blend_ARGB24_on_RGB16_SourceAndConstAlpha {
@@ -132,6 +138,8 @@ struct Blend_ARGB24_on_RGB16_SourceAndConstAlpha {
}
}
+ inline void flush(void *) {}
+
quint32 m_alpha;
};
@@ -145,6 +153,8 @@ struct Blend_ARGB32_on_RGB16_SourceAlpha {
*dst = s;
}
}
+
+ inline void flush(void *) {}
};
struct Blend_ARGB32_on_RGB16_SourceAndConstAlpha {
@@ -163,99 +173,11 @@ struct Blend_ARGB32_on_RGB16_SourceAndConstAlpha {
}
}
+ inline void flush(void *) {}
+
quint32 m_alpha;
};
-template <typename SRC, typename T>
-void qt_scale_image_16bit(uchar *destPixels, int dbpl,
- const uchar *srcPixels, int sbpl,
- const QRectF &targetRect,
- const QRectF &srcRect,
- const QRect &clip,
- T blender)
-{
- qreal sx = targetRect.width() / (qreal) srcRect.width();
- qreal sy = targetRect.height() / (qreal) srcRect.height();
-
- int ix = 0x00010000 / sx;
- int iy = 0x00010000 / sy;
-
-// qDebug() << "scale:" << endl
-// << " - target" << targetRect << endl
-// << " - source" << srcRect << endl
-// << " - clip" << clip << endl
-// << " - sx=" << sx << " sy=" << sy << " ix=" << ix << " iy=" << iy;
-
- int cx1 = clip.x();
- int cx2 = clip.x() + clip.width();
- int cy1 = clip.top();
- int cy2 = clip.y() + clip.height();
-
- int tx1 = qRound(targetRect.left());
- int tx2 = qRound(targetRect.right());
- int ty1 = qRound(targetRect.top());
- int ty2 = qRound(targetRect.bottom());
-
- if (tx2 < tx1)
- qSwap(tx2, tx1);
-
- if (ty2 < ty1)
- qSwap(ty2, ty1);
-
- if (tx1 < cx1)
- tx1 = cx1;
-
- if (tx2 >= cx2)
- tx2 = cx2;
-
- if (tx1 >= tx2)
- return;
-
- if (ty1 < cy1)
- ty1 = cy1;
-
- if (ty2 >= cy2)
- ty2 = cy2;
-
- if (ty1 >= ty2)
- return;
-
- int h = ty2 - ty1;
- int w = tx2 - tx1;
-
-
- quint32 basex;
- quint32 srcy;
-
- if (sx < 0) {
- int dstx = qFloor((tx1 + qreal(0.5) - targetRect.right()) * ix) + 1;
- basex = quint32(srcRect.right() * 65536) + dstx;
- } else {
- int dstx = qCeil((tx1 + qreal(0.5) - targetRect.left()) * ix) - 1;
- basex = quint32(srcRect.left() * 65536) + dstx;
- }
- if (sy < 0) {
- int dsty = qFloor((ty1 + qreal(0.5) - targetRect.bottom()) * iy) + 1;
- srcy = quint32(srcRect.bottom() * 65536) + dsty;
- } else {
- int dsty = qCeil((ty1 + qreal(0.5) - targetRect.top()) * iy) - 1;
- srcy = quint32(srcRect.top() * 65536) + dsty;
- }
-
- quint16 *dst = ((quint16 *) (destPixels + ty1 * dbpl)) + tx1;
-
- while (h--) {
- const SRC *src = (const SRC *) (srcPixels + (srcy >> 16) * sbpl);
- int srcx = basex;
- for (int x=0; x<w; ++x) {
- blender.write(&dst[x], src[srcx >> 16]);
- srcx += ix;
- }
- dst = (quint16 *)(((uchar *) dst) + dbpl);
- srcy += iy;
- }
-}
-
void qt_scale_image_rgb16_on_rgb16(uchar *destPixels, int dbpl,
const uchar *srcPixels, int sbpl,
const QRectF &targetRect,
@@ -447,10 +369,10 @@ static void qt_blend_argb24_on_rgb16(uchar *destPixels, int dbpl,
-static void qt_blend_argb32_on_rgb16_const_alpha(uchar *destPixels, int dbpl,
- const uchar *srcPixels, int sbpl,
- int w, int h,
- int const_alpha)
+void qt_blend_argb32_on_rgb16_const_alpha(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha)
{
quint16 *dst = (quint16 *) destPixels;
const quint32 *src = (const quint32 *) srcPixels;
@@ -643,6 +565,8 @@ void qt_blend_rgb32_on_rgb32(uchar *destPixels, int dbpl,
struct Blend_RGB32_on_RGB32_NoAlpha {
inline void write(quint32 *dst, quint32 src) { *dst = src; }
+
+ inline void flush(void *) {}
};
struct Blend_RGB32_on_RGB32_ConstAlpha {
@@ -655,6 +579,8 @@ struct Blend_RGB32_on_RGB32_ConstAlpha {
*dst = BYTE_MUL(src, m_alpha) + BYTE_MUL(*dst, m_ialpha);
}
+ inline void flush(void *) {}
+
quint32 m_alpha;
quint32 m_ialpha;
};
@@ -663,6 +589,8 @@ struct Blend_ARGB32_on_ARGB32_SourceAlpha {
inline void write(quint32 *dst, quint32 src) {
*dst = src + BYTE_MUL(*dst, qAlpha(~src));
}
+
+ inline void flush(void *) {}
};
struct Blend_ARGB32_on_ARGB32_SourceAndConstAlpha {
@@ -676,98 +604,12 @@ struct Blend_ARGB32_on_ARGB32_SourceAndConstAlpha {
*dst = src + BYTE_MUL(*dst, qAlpha(~src));
}
+ inline void flush(void *) {}
+
quint32 m_alpha;
quint32 m_ialpha;
};
-template <typename T> void qt_scale_image_32bit(uchar *destPixels, int dbpl,
- const uchar *srcPixels, int sbpl,
- const QRectF &targetRect,
- const QRectF &srcRect,
- const QRect &clip,
- T blender)
-{
- qreal sx = targetRect.width() / (qreal) srcRect.width();
- qreal sy = targetRect.height() / (qreal) srcRect.height();
-
- int ix = 0x00010000 / sx;
- int iy = 0x00010000 / sy;
-
-// qDebug() << "scale:" << endl
-// << " - target" << targetRect << endl
-// << " - source" << srcRect << endl
-// << " - clip" << clip << endl
-// << " - sx=" << sx << " sy=" << sy << " ix=" << ix << " iy=" << iy;
-
- int cx1 = clip.x();
- int cx2 = clip.x() + clip.width();
- int cy1 = clip.top();
- int cy2 = clip.y() + clip.height();
-
- int tx1 = qRound(targetRect.left());
- int tx2 = qRound(targetRect.right());
- int ty1 = qRound(targetRect.top());
- int ty2 = qRound(targetRect.bottom());
-
- if (tx2 < tx1)
- qSwap(tx2, tx1);
-
- if (ty2 < ty1)
- qSwap(ty2, ty1);
-
- if (tx1 < cx1)
- tx1 = cx1;
-
- if (tx2 >= cx2)
- tx2 = cx2;
-
- if (tx1 >= tx2)
- return;
-
- if (ty1 < cy1)
- ty1 = cy1;
-
- if (ty2 >= cy2)
- ty2 = cy2;
-
- if (ty1 >= ty2)
- return;
-
- int h = ty2 - ty1;
- int w = tx2 - tx1;
-
- quint32 basex;
- quint32 srcy;
-
- if (sx < 0) {
- int dstx = qFloor((tx1 + qreal(0.5) - targetRect.right()) * ix) + 1;
- basex = quint32(srcRect.right() * 65536) + dstx;
- } else {
- int dstx = qCeil((tx1 + qreal(0.5) - targetRect.left()) * ix) - 1;
- basex = quint32(srcRect.left() * 65536) + dstx;
- }
- if (sy < 0) {
- int dsty = qFloor((ty1 + qreal(0.5) - targetRect.bottom()) * iy) + 1;
- srcy = quint32(srcRect.bottom() * 65536) + dsty;
- } else {
- int dsty = qCeil((ty1 + qreal(0.5) - targetRect.top()) * iy) - 1;
- srcy = quint32(srcRect.top() * 65536) + dsty;
- }
-
- quint32 *dst = ((quint32 *) (destPixels + ty1 * dbpl)) + tx1;
-
- while (h--) {
- const uint *src = (const quint32 *) (srcPixels + (srcy >> 16) * sbpl);
- int srcx = basex;
- for (int x=0; x<w; ++x) {
- blender.write(&dst[x], src[srcx >> 16]);
- srcx += ix;
- }
- dst = (quint32 *)(((uchar *) dst) + dbpl);
- srcy += iy;
- }
-}
-
void qt_scale_image_rgb32_on_rgb32(uchar *destPixels, int dbpl,
const uchar *srcPixels, int sbpl,
const QRectF &targetRect,
@@ -818,244 +660,6 @@ void qt_scale_image_argb32_on_argb32(uchar *destPixels, int dbpl,
}
}
-struct QTransformImageVertex
-{
- qreal x, y, u, v; // destination coordinates (x, y) and source coordinates (u, v)
-};
-
-template <class SrcT, class DestT, class Blender>
-void qt_transform_image_rasterize(DestT *destPixels, int dbpl,
- const SrcT *srcPixels, int sbpl,
- const QTransformImageVertex &topLeft, const QTransformImageVertex &bottomLeft,
- const QTransformImageVertex &topRight, const QTransformImageVertex &bottomRight,
- const QRect &sourceRect,
- const QRect &clip,
- qreal topY, qreal bottomY,
- int dudx, int dvdx, int dudy, int dvdy, int u0, int v0,
- Blender blender)
-{
- int fromY = qMax(qRound(topY), clip.top());
- int toY = qMin(qRound(bottomY), clip.top() + clip.height());
- if (fromY >= toY)
- return;
-
- qreal leftSlope = (bottomLeft.x - topLeft.x) / (bottomLeft.y - topLeft.y);
- qreal rightSlope = (bottomRight.x - topRight.x) / (bottomRight.y - topRight.y);
- int dx_l = int(leftSlope * 0x10000);
- int dx_r = int(rightSlope * 0x10000);
- int x_l = int((topLeft.x + (0.5 + fromY - topLeft.y) * leftSlope + 0.5) * 0x10000);
- int x_r = int((topRight.x + (0.5 + fromY - topRight.y) * rightSlope + 0.5) * 0x10000);
-
- int fromX, toX, x1, x2, u, v, i, ii;
- DestT *line;
- for (int y = fromY; y < toY; ++y) {
- line = reinterpret_cast<DestT *>(reinterpret_cast<uchar *>(destPixels) + y * dbpl);
-
- fromX = qMax(x_l >> 16, clip.left());
- toX = qMin(x_r >> 16, clip.left() + clip.width());
- if (fromX < toX) {
- // Because of rounding, we can get source coordinates outside the source image.
- // Clamp these coordinates to the source rect to avoid segmentation fault and
- // garbage on the screen.
-
- // Find the first pixel on the current scan line where the source coordinates are within the source rect.
- x1 = fromX;
- u = x1 * dudx + y * dudy + u0;
- v = x1 * dvdx + y * dvdy + v0;
- for (; x1 < toX; ++x1) {
- int uu = u >> 16;
- int vv = v >> 16;
- if (uu >= sourceRect.left() && uu < sourceRect.left() + sourceRect.width()
- && vv >= sourceRect.top() && vv < sourceRect.top() + sourceRect.height()) {
- break;
- }
- u += dudx;
- v += dvdx;
- }
-
- // Find the last pixel on the current scan line where the source coordinates are within the source rect.
- x2 = toX;
- u = (x2 - 1) * dudx + y * dudy + u0;
- v = (x2 - 1) * dvdx + y * dvdy + v0;
- for (; x2 > x1; --x2) {
- int uu = u >> 16;
- int vv = v >> 16;
- if (uu >= sourceRect.left() && uu < sourceRect.left() + sourceRect.width()
- && vv >= sourceRect.top() && vv < sourceRect.top() + sourceRect.height()) {
- break;
- }
- u -= dudx;
- v -= dvdx;
- }
-
- // Set up values at the beginning of the scan line.
- u = fromX * dudx + y * dudy + u0;
- v = fromX * dvdx + y * dvdy + v0;
- line += fromX;
-
- // Beginning of the scan line, with per-pixel checks.
- i = x1 - fromX;
- while (i) {
- int uu = qBound(sourceRect.left(), u >> 16, sourceRect.left() + sourceRect.width() - 1);
- int vv = qBound(sourceRect.top(), v >> 16, sourceRect.top() + sourceRect.height() - 1);
- blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + vv * sbpl)[uu]);
- u += dudx;
- v += dvdx;
- ++line;
- --i;
- }
-
- // Middle of the scan line, without checks.
- // Manual loop unrolling.
- i = x2 - x1;
- ii = i >> 3;
- while (ii) {
- blender.write(&line[0], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
- blender.write(&line[1], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
- blender.write(&line[2], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
- blender.write(&line[3], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
- blender.write(&line[4], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
- blender.write(&line[5], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
- blender.write(&line[6], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
- blender.write(&line[7], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
- line += 8;
- --ii;
- }
- switch (i & 7) {
- case 7: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
- case 6: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
- case 5: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
- case 4: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
- case 3: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
- case 2: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
- case 1: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
- }
-
- // End of the scan line, with per-pixel checks.
- i = toX - x2;
- while (i) {
- int uu = qBound(sourceRect.left(), u >> 16, sourceRect.left() + sourceRect.width() - 1);
- int vv = qBound(sourceRect.top(), v >> 16, sourceRect.top() + sourceRect.height() - 1);
- blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + vv * sbpl)[uu]);
- u += dudx;
- v += dvdx;
- ++line;
- --i;
- }
- }
- x_l += dx_l;
- x_r += dx_r;
- }
-}
-
-template <class SrcT, class DestT, class Blender>
-void qt_transform_image(DestT *destPixels, int dbpl,
- const SrcT *srcPixels, int sbpl,
- const QRectF &targetRect,
- const QRectF &sourceRect,
- const QRect &clip,
- const QTransform &targetRectTransform,
- Blender blender)
-{
- enum Corner
- {
- TopLeft,
- TopRight,
- BottomRight,
- BottomLeft
- };
-
- // map source rectangle to destination.
- QTransformImageVertex v[4];
- v[TopLeft].u = v[BottomLeft].u = sourceRect.left();
- v[TopLeft].v = v[TopRight].v = sourceRect.top();
- v[TopRight].u = v[BottomRight].u = sourceRect.right();
- v[BottomLeft].v = v[BottomRight].v = sourceRect.bottom();
- targetRectTransform.map(targetRect.left(), targetRect.top(), &v[TopLeft].x, &v[TopLeft].y);
- targetRectTransform.map(targetRect.right(), targetRect.top(), &v[TopRight].x, &v[TopRight].y);
- targetRectTransform.map(targetRect.left(), targetRect.bottom(), &v[BottomLeft].x, &v[BottomLeft].y);
- targetRectTransform.map(targetRect.right(), targetRect.bottom(), &v[BottomRight].x, &v[BottomRight].y);
-
- // find topmost vertex.
- int topmost = 0;
- for (int i = 1; i < 4; ++i) {
- if (v[i].y < v[topmost].y)
- topmost = i;
- }
- // rearrange array such that topmost vertex is at index 0.
- switch (topmost) {
- case 1:
- {
- QTransformImageVertex t = v[0];
- for (int i = 0; i < 3; ++i)
- v[i] = v[i+1];
- v[3] = t;
- }
- break;
- case 2:
- qSwap(v[0], v[2]);
- qSwap(v[1], v[3]);
- break;
- case 3:
- {
- QTransformImageVertex t = v[3];
- for (int i = 3; i > 0; --i)
- v[i] = v[i-1];
- v[0] = t;
- }
- break;
- }
-
- // if necessary, swap vertex 1 and 3 such that 1 is to the left of 3.
- qreal dx1 = v[1].x - v[0].x;
- qreal dy1 = v[1].y - v[0].y;
- qreal dx2 = v[3].x - v[0].x;
- qreal dy2 = v[3].y - v[0].y;
- if (dx1 * dy2 - dx2 * dy1 > 0)
- qSwap(v[1], v[3]);
-
- QTransformImageVertex u = {v[1].x - v[0].x, v[1].y - v[0].y, v[1].u - v[0].u, v[1].v - v[0].v};
- QTransformImageVertex w = {v[2].x - v[0].x, v[2].y - v[0].y, v[2].u - v[0].u, v[2].v - v[0].v};
-
- qreal det = u.x * w.y - u.y * w.x;
- if (det == 0)
- return;
-
- qreal invDet = 1.0 / det;
- qreal m11, m12, m21, m22, mdx, mdy;
-
- m11 = (u.u * w.y - u.y * w.u) * invDet;
- m12 = (u.x * w.u - u.u * w.x) * invDet;
- m21 = (u.v * w.y - u.y * w.v) * invDet;
- m22 = (u.x * w.v - u.v * w.x) * invDet;
- mdx = v[0].u - m11 * v[0].x - m12 * v[0].y;
- mdy = v[0].v - m21 * v[0].x - m22 * v[0].y;
-
- int dudx = int(m11 * 0x10000);
- int dvdx = int(m21 * 0x10000);
- int dudy = int(m12 * 0x10000);
- int dvdy = int(m22 * 0x10000);
- int u0 = qCeil((0.5 * m11 + 0.5 * m12 + mdx) * 0x10000) - 1;
- int v0 = qCeil((0.5 * m21 + 0.5 * m22 + mdy) * 0x10000) - 1;
-
- int x1 = qFloor(sourceRect.left());
- int y1 = qFloor(sourceRect.top());
- int x2 = qCeil(sourceRect.right());
- int y2 = qCeil(sourceRect.bottom());
- QRect sourceRectI(x1, y1, x2 - x1, y2 - y1);
-
- // rasterize trapezoids.
- if (v[1].y < v[3].y) {
- qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[0], v[1], v[0], v[3], sourceRectI, clip, v[0].y, v[1].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
- qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[1], v[2], v[0], v[3], sourceRectI, clip, v[1].y, v[3].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
- qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[1], v[2], v[3], v[2], sourceRectI, clip, v[3].y, v[2].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
- } else {
- qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[0], v[1], v[0], v[3], sourceRectI, clip, v[0].y, v[3].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
- qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[0], v[1], v[3], v[2], sourceRectI, clip, v[3].y, v[1].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
- qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[1], v[2], v[3], v[2], sourceRectI, clip, v[1].y, v[2].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
- }
-}
-
void qt_transform_image_rgb16_on_rgb16(uchar *destPixels, int dbpl,
const uchar *srcPixels, int sbpl,
const QRectF &targetRect,
diff --git a/src/gui/painting/qblendfunctions_p.h b/src/gui/painting/qblendfunctions_p.h
new file mode 100644
index 0000000..ad754b0
--- /dev/null
+++ b/src/gui/painting/qblendfunctions_p.h
@@ -0,0 +1,497 @@
+/****************************************************************************
+**
+** 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 QtGui module 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 QBLENDFUNCTIONS_P_H
+#define QBLENDFUNCTIONS_P_H
+
+#include <qmath.h>
+#include "qdrawhelper_p.h"
+
+QT_BEGIN_NAMESPACE
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+template <typename SRC, typename T>
+void qt_scale_image_16bit(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &srcRect,
+ const QRect &clip,
+ T blender)
+{
+ qreal sx = targetRect.width() / (qreal) srcRect.width();
+ qreal sy = targetRect.height() / (qreal) srcRect.height();
+
+ int ix = 0x00010000 / sx;
+ int iy = 0x00010000 / sy;
+
+// qDebug() << "scale:" << endl
+// << " - target" << targetRect << endl
+// << " - source" << srcRect << endl
+// << " - clip" << clip << endl
+// << " - sx=" << sx << " sy=" << sy << " ix=" << ix << " iy=" << iy;
+
+ int cx1 = clip.x();
+ int cx2 = clip.x() + clip.width();
+ int cy1 = clip.top();
+ int cy2 = clip.y() + clip.height();
+
+ int tx1 = qRound(targetRect.left());
+ int tx2 = qRound(targetRect.right());
+ int ty1 = qRound(targetRect.top());
+ int ty2 = qRound(targetRect.bottom());
+
+ if (tx2 < tx1)
+ qSwap(tx2, tx1);
+
+ if (ty2 < ty1)
+ qSwap(ty2, ty1);
+
+ if (tx1 < cx1)
+ tx1 = cx1;
+
+ if (tx2 >= cx2)
+ tx2 = cx2;
+
+ if (tx1 >= tx2)
+ return;
+
+ if (ty1 < cy1)
+ ty1 = cy1;
+
+ if (ty2 >= cy2)
+ ty2 = cy2;
+
+ if (ty1 >= ty2)
+ return;
+
+ int h = ty2 - ty1;
+ int w = tx2 - tx1;
+
+
+ quint32 basex;
+ quint32 srcy;
+
+ if (sx < 0) {
+ int dstx = qFloor((tx1 + qreal(0.5) - targetRect.right()) * ix) + 1;
+ basex = quint32(srcRect.right() * 65536) + dstx;
+ } else {
+ int dstx = qCeil((tx1 + qreal(0.5) - targetRect.left()) * ix) - 1;
+ basex = quint32(srcRect.left() * 65536) + dstx;
+ }
+ if (sy < 0) {
+ int dsty = qFloor((ty1 + qreal(0.5) - targetRect.bottom()) * iy) + 1;
+ srcy = quint32(srcRect.bottom() * 65536) + dsty;
+ } else {
+ int dsty = qCeil((ty1 + qreal(0.5) - targetRect.top()) * iy) - 1;
+ srcy = quint32(srcRect.top() * 65536) + dsty;
+ }
+
+ quint16 *dst = ((quint16 *) (destPixels + ty1 * dbpl)) + tx1;
+
+ while (h--) {
+ const SRC *src = (const SRC *) (srcPixels + (srcy >> 16) * sbpl);
+ int srcx = basex;
+ int x = 0;
+ for (; x<w-7; x+=8) {
+ blender.write(&dst[x], src[srcx >> 16]); srcx += ix;
+ blender.write(&dst[x+1], src[srcx >> 16]); srcx += ix;
+ blender.write(&dst[x+2], src[srcx >> 16]); srcx += ix;
+ blender.write(&dst[x+3], src[srcx >> 16]); srcx += ix;
+ blender.write(&dst[x+4], src[srcx >> 16]); srcx += ix;
+ blender.write(&dst[x+5], src[srcx >> 16]); srcx += ix;
+ blender.write(&dst[x+6], src[srcx >> 16]); srcx += ix;
+ blender.write(&dst[x+7], src[srcx >> 16]); srcx += ix;
+ }
+ for (; x<w; ++x) {
+ blender.write(&dst[x], src[srcx >> 16]);
+ srcx += ix;
+ }
+ blender.flush(&dst[x]);
+ dst = (quint16 *)(((uchar *) dst) + dbpl);
+ srcy += iy;
+ }
+}
+
+template <typename T> void qt_scale_image_32bit(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &srcRect,
+ const QRect &clip,
+ T blender)
+{
+ qreal sx = targetRect.width() / (qreal) srcRect.width();
+ qreal sy = targetRect.height() / (qreal) srcRect.height();
+
+ int ix = 0x00010000 / sx;
+ int iy = 0x00010000 / sy;
+
+// qDebug() << "scale:" << endl
+// << " - target" << targetRect << endl
+// << " - source" << srcRect << endl
+// << " - clip" << clip << endl
+// << " - sx=" << sx << " sy=" << sy << " ix=" << ix << " iy=" << iy;
+
+ int cx1 = clip.x();
+ int cx2 = clip.x() + clip.width();
+ int cy1 = clip.top();
+ int cy2 = clip.y() + clip.height();
+
+ int tx1 = qRound(targetRect.left());
+ int tx2 = qRound(targetRect.right());
+ int ty1 = qRound(targetRect.top());
+ int ty2 = qRound(targetRect.bottom());
+
+ if (tx2 < tx1)
+ qSwap(tx2, tx1);
+
+ if (ty2 < ty1)
+ qSwap(ty2, ty1);
+
+ if (tx1 < cx1)
+ tx1 = cx1;
+
+ if (tx2 >= cx2)
+ tx2 = cx2;
+
+ if (tx1 >= tx2)
+ return;
+
+ if (ty1 < cy1)
+ ty1 = cy1;
+
+ if (ty2 >= cy2)
+ ty2 = cy2;
+
+ if (ty1 >= ty2)
+ return;
+
+ int h = ty2 - ty1;
+ int w = tx2 - tx1;
+
+ quint32 basex;
+ quint32 srcy;
+
+ if (sx < 0) {
+ int dstx = qFloor((tx1 + qreal(0.5) - targetRect.right()) * ix) + 1;
+ basex = quint32(srcRect.right() * 65536) + dstx;
+ } else {
+ int dstx = qCeil((tx1 + qreal(0.5) - targetRect.left()) * ix) - 1;
+ basex = quint32(srcRect.left() * 65536) + dstx;
+ }
+ if (sy < 0) {
+ int dsty = qFloor((ty1 + qreal(0.5) - targetRect.bottom()) * iy) + 1;
+ srcy = quint32(srcRect.bottom() * 65536) + dsty;
+ } else {
+ int dsty = qCeil((ty1 + qreal(0.5) - targetRect.top()) * iy) - 1;
+ srcy = quint32(srcRect.top() * 65536) + dsty;
+ }
+
+ quint32 *dst = ((quint32 *) (destPixels + ty1 * dbpl)) + tx1;
+
+ while (h--) {
+ const uint *src = (const quint32 *) (srcPixels + (srcy >> 16) * sbpl);
+ int srcx = basex;
+ int x = 0;
+ for (; x<w; ++x) {
+ blender.write(&dst[x], src[srcx >> 16]);
+ srcx += ix;
+ }
+ blender.flush(&dst[x]);
+ dst = (quint32 *)(((uchar *) dst) + dbpl);
+ srcy += iy;
+ }
+}
+
+struct QTransformImageVertex
+{
+ qreal x, y, u, v; // destination coordinates (x, y) and source coordinates (u, v)
+};
+
+template <class SrcT, class DestT, class Blender>
+void qt_transform_image_rasterize(DestT *destPixels, int dbpl,
+ const SrcT *srcPixels, int sbpl,
+ const QTransformImageVertex &topLeft, const QTransformImageVertex &bottomLeft,
+ const QTransformImageVertex &topRight, const QTransformImageVertex &bottomRight,
+ const QRect &sourceRect,
+ const QRect &clip,
+ qreal topY, qreal bottomY,
+ int dudx, int dvdx, int dudy, int dvdy, int u0, int v0,
+ Blender blender)
+{
+ int fromY = qMax(qRound(topY), clip.top());
+ int toY = qMin(qRound(bottomY), clip.top() + clip.height());
+ if (fromY >= toY)
+ return;
+
+ qreal leftSlope = (bottomLeft.x - topLeft.x) / (bottomLeft.y - topLeft.y);
+ qreal rightSlope = (bottomRight.x - topRight.x) / (bottomRight.y - topRight.y);
+ int dx_l = int(leftSlope * 0x10000);
+ int dx_r = int(rightSlope * 0x10000);
+ int x_l = int((topLeft.x + (0.5 + fromY - topLeft.y) * leftSlope + 0.5) * 0x10000);
+ int x_r = int((topRight.x + (0.5 + fromY - topRight.y) * rightSlope + 0.5) * 0x10000);
+
+ int fromX, toX, x1, x2, u, v, i, ii;
+ DestT *line;
+ for (int y = fromY; y < toY; ++y) {
+ line = reinterpret_cast<DestT *>(reinterpret_cast<uchar *>(destPixels) + y * dbpl);
+
+ fromX = qMax(x_l >> 16, clip.left());
+ toX = qMin(x_r >> 16, clip.left() + clip.width());
+ if (fromX < toX) {
+ // Because of rounding, we can get source coordinates outside the source image.
+ // Clamp these coordinates to the source rect to avoid segmentation fault and
+ // garbage on the screen.
+
+ // Find the first pixel on the current scan line where the source coordinates are within the source rect.
+ x1 = fromX;
+ u = x1 * dudx + y * dudy + u0;
+ v = x1 * dvdx + y * dvdy + v0;
+ for (; x1 < toX; ++x1) {
+ int uu = u >> 16;
+ int vv = v >> 16;
+ if (uu >= sourceRect.left() && uu < sourceRect.left() + sourceRect.width()
+ && vv >= sourceRect.top() && vv < sourceRect.top() + sourceRect.height()) {
+ break;
+ }
+ u += dudx;
+ v += dvdx;
+ }
+
+ // Find the last pixel on the current scan line where the source coordinates are within the source rect.
+ x2 = toX;
+ u = (x2 - 1) * dudx + y * dudy + u0;
+ v = (x2 - 1) * dvdx + y * dvdy + v0;
+ for (; x2 > x1; --x2) {
+ int uu = u >> 16;
+ int vv = v >> 16;
+ if (uu >= sourceRect.left() && uu < sourceRect.left() + sourceRect.width()
+ && vv >= sourceRect.top() && vv < sourceRect.top() + sourceRect.height()) {
+ break;
+ }
+ u -= dudx;
+ v -= dvdx;
+ }
+
+ // Set up values at the beginning of the scan line.
+ u = fromX * dudx + y * dudy + u0;
+ v = fromX * dvdx + y * dvdy + v0;
+ line += fromX;
+
+ // Beginning of the scan line, with per-pixel checks.
+ i = x1 - fromX;
+ while (i) {
+ int uu = qBound(sourceRect.left(), u >> 16, sourceRect.left() + sourceRect.width() - 1);
+ int vv = qBound(sourceRect.top(), v >> 16, sourceRect.top() + sourceRect.height() - 1);
+ blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + vv * sbpl)[uu]);
+ u += dudx;
+ v += dvdx;
+ ++line;
+ --i;
+ }
+
+ // Middle of the scan line, without checks.
+ // Manual loop unrolling.
+ i = x2 - x1;
+ ii = i >> 3;
+ while (ii) {
+ blender.write(&line[0], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
+ blender.write(&line[1], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
+ blender.write(&line[2], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
+ blender.write(&line[3], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
+ blender.write(&line[4], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
+ blender.write(&line[5], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
+ blender.write(&line[6], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
+ blender.write(&line[7], reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx;
+
+ line += 8;
+
+ --ii;
+ }
+ switch (i & 7) {
+ case 7: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
+ case 6: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
+ case 5: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
+ case 4: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
+ case 3: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
+ case 2: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
+ case 1: blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line;
+ }
+
+ // End of the scan line, with per-pixel checks.
+ i = toX - x2;
+ while (i) {
+ int uu = qBound(sourceRect.left(), u >> 16, sourceRect.left() + sourceRect.width() - 1);
+ int vv = qBound(sourceRect.top(), v >> 16, sourceRect.top() + sourceRect.height() - 1);
+ blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + vv * sbpl)[uu]);
+ u += dudx;
+ v += dvdx;
+ ++line;
+ --i;
+ }
+
+ blender.flush(line);
+ }
+ x_l += dx_l;
+ x_r += dx_r;
+ }
+}
+
+template <class SrcT, class DestT, class Blender>
+void qt_transform_image(DestT *destPixels, int dbpl,
+ const SrcT *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ const QTransform &targetRectTransform,
+ Blender blender)
+{
+ enum Corner
+ {
+ TopLeft,
+ TopRight,
+ BottomRight,
+ BottomLeft
+ };
+
+ // map source rectangle to destination.
+ QTransformImageVertex v[4];
+ v[TopLeft].u = v[BottomLeft].u = sourceRect.left();
+ v[TopLeft].v = v[TopRight].v = sourceRect.top();
+ v[TopRight].u = v[BottomRight].u = sourceRect.right();
+ v[BottomLeft].v = v[BottomRight].v = sourceRect.bottom();
+ targetRectTransform.map(targetRect.left(), targetRect.top(), &v[TopLeft].x, &v[TopLeft].y);
+ targetRectTransform.map(targetRect.right(), targetRect.top(), &v[TopRight].x, &v[TopRight].y);
+ targetRectTransform.map(targetRect.left(), targetRect.bottom(), &v[BottomLeft].x, &v[BottomLeft].y);
+ targetRectTransform.map(targetRect.right(), targetRect.bottom(), &v[BottomRight].x, &v[BottomRight].y);
+
+ // find topmost vertex.
+ int topmost = 0;
+ for (int i = 1; i < 4; ++i) {
+ if (v[i].y < v[topmost].y)
+ topmost = i;
+ }
+ // rearrange array such that topmost vertex is at index 0.
+ switch (topmost) {
+ case 1:
+ {
+ QTransformImageVertex t = v[0];
+ for (int i = 0; i < 3; ++i)
+ v[i] = v[i+1];
+ v[3] = t;
+ }
+ break;
+ case 2:
+ qSwap(v[0], v[2]);
+ qSwap(v[1], v[3]);
+ break;
+ case 3:
+ {
+ QTransformImageVertex t = v[3];
+ for (int i = 3; i > 0; --i)
+ v[i] = v[i-1];
+ v[0] = t;
+ }
+ break;
+ }
+
+ // if necessary, swap vertex 1 and 3 such that 1 is to the left of 3.
+ qreal dx1 = v[1].x - v[0].x;
+ qreal dy1 = v[1].y - v[0].y;
+ qreal dx2 = v[3].x - v[0].x;
+ qreal dy2 = v[3].y - v[0].y;
+ if (dx1 * dy2 - dx2 * dy1 > 0)
+ qSwap(v[1], v[3]);
+
+ QTransformImageVertex u = {v[1].x - v[0].x, v[1].y - v[0].y, v[1].u - v[0].u, v[1].v - v[0].v};
+ QTransformImageVertex w = {v[2].x - v[0].x, v[2].y - v[0].y, v[2].u - v[0].u, v[2].v - v[0].v};
+
+ qreal det = u.x * w.y - u.y * w.x;
+ if (det == 0)
+ return;
+
+ qreal invDet = 1.0 / det;
+ qreal m11, m12, m21, m22, mdx, mdy;
+
+ m11 = (u.u * w.y - u.y * w.u) * invDet;
+ m12 = (u.x * w.u - u.u * w.x) * invDet;
+ m21 = (u.v * w.y - u.y * w.v) * invDet;
+ m22 = (u.x * w.v - u.v * w.x) * invDet;
+ mdx = v[0].u - m11 * v[0].x - m12 * v[0].y;
+ mdy = v[0].v - m21 * v[0].x - m22 * v[0].y;
+
+ int dudx = int(m11 * 0x10000);
+ int dvdx = int(m21 * 0x10000);
+ int dudy = int(m12 * 0x10000);
+ int dvdy = int(m22 * 0x10000);
+ int u0 = qCeil((0.5 * m11 + 0.5 * m12 + mdx) * 0x10000) - 1;
+ int v0 = qCeil((0.5 * m21 + 0.5 * m22 + mdy) * 0x10000) - 1;
+
+ int x1 = qFloor(sourceRect.left());
+ int y1 = qFloor(sourceRect.top());
+ int x2 = qCeil(sourceRect.right());
+ int y2 = qCeil(sourceRect.bottom());
+ QRect sourceRectI(x1, y1, x2 - x1, y2 - y1);
+
+ // rasterize trapezoids.
+ if (v[1].y < v[3].y) {
+ qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[0], v[1], v[0], v[3], sourceRectI, clip, v[0].y, v[1].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
+ qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[1], v[2], v[0], v[3], sourceRectI, clip, v[1].y, v[3].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
+ qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[1], v[2], v[3], v[2], sourceRectI, clip, v[3].y, v[2].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
+ } else {
+ qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[0], v[1], v[0], v[3], sourceRectI, clip, v[0].y, v[3].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
+ qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[0], v[1], v[3], v[2], sourceRectI, clip, v[3].y, v[1].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
+ qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[1], v[2], v[3], v[2], sourceRectI, clip, v[1].y, v[2].y, dudx, dvdx, dudy, dvdy, u0, v0, blender);
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // QBLENDFUNCTIONS_P_H
diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp
index a82d0f9..182cce9 100644
--- a/src/gui/painting/qbrush.cpp
+++ b/src/gui/painting/qbrush.cpp
@@ -989,7 +989,8 @@ QDebug operator<<(QDebug dbg, const QBrush &b)
"LinearGradientPattern",
"RadialGradientPattern",
"ConicalGradientPattern",
- "TexturePattern"
+ 0, 0, 0, 0, 0, 0,
+ "TexturePattern" // 24
};
dbg.nospace() << "QBrush(" << b.color() << ',' << BRUSH_STYLES[b.style()] << ')';
diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp
index 1b43161..08d5572 100644
--- a/src/gui/painting/qcolor.cpp
+++ b/src/gui/painting/qcolor.cpp
@@ -537,23 +537,26 @@ void QColor::setNamedColor(const QString &name)
}
/*!
- Checks if the \a name is a valid color name. The algorithm used is the same as with
- \a setNamedColor().
+ \since 4.7
- \return true if the color name is valid, false otherwise.
+ Returns true if the \a name is a valid color name and can
+ be used to construct a valid QColor object, otherwise returns
+ false.
+
+ It uses the same algorithm used in setNamedColor().
\sa setNamedColor()
*/
bool QColor::isValidColor(const QString &name)
{
- return QColor().setColorFromString(name);
+ return !name.isEmpty() && QColor().setColorFromString(name);
}
bool QColor::setColorFromString(const QString &name)
{
if (name.isEmpty()) {
invalidate();
- return false;
+ return true;
}
if (name.startsWith(QLatin1Char('#'))) {
@@ -2714,12 +2717,4 @@ QDataStream &operator>>(QDataStream &stream, QColor &color)
\sa QColor::rgb(), QColor::rgba()
*/
-/*! \fn void QColormap::initialize()
- \internal
-*/
-
-/*! \fn void QColormap::cleanup()
- \internal
-*/
-
QT_END_NAMESPACE
diff --git a/src/gui/painting/qcolormap.qdoc b/src/gui/painting/qcolormap.qdoc
index 56fabf7..22a73fd 100644
--- a/src/gui/painting/qcolormap.qdoc
+++ b/src/gui/painting/qcolormap.qdoc
@@ -150,3 +150,13 @@
Assigns the given \a colormap to \e this color map and returns
a reference to \e this color map.
*/
+
+/*!
+ \fn void QColormap::initialize()
+ \internal
+*/
+
+/*!
+ \fn void QColormap::cleanup()
+ \internal
+*/
diff --git a/src/gui/painting/qcups.cpp b/src/gui/painting/qcups.cpp
index ac41692..1ea1670 100644
--- a/src/gui/painting/qcups.cpp
+++ b/src/gui/painting/qcups.cpp
@@ -343,7 +343,8 @@ bool QCUPSSupport::printerHasPPD(const char *printerName)
if (!isAvailable())
return false;
const char *ppdFile = _cupsGetPPD(printerName);
- unlink(ppdFile);
+ if (ppdFile)
+ unlink(ppdFile);
return (ppdFile != 0);
}
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index eca7a39..917b910 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -175,7 +175,7 @@ Q_STATIC_TEMPLATE_FUNCTION uint * QT_FASTCALL destFetch(uint *buffer, QRasterBuf
# define SPANFUNC_POINTER_DESTFETCH(Arg) destFetch<Arg>
-static const DestFetchProc destFetchProc[QImage::NImageFormats] =
+static DestFetchProc destFetchProc[QImage::NImageFormats] =
{
0, // Format_Invalid
destFetchMono, // Format_Mono,
@@ -323,7 +323,7 @@ Q_STATIC_TEMPLATE_FUNCTION void QT_FASTCALL destStore(QRasterBuffer *rasterBuffe
# define SPANFUNC_POINTER_DESTSTORE(DEST) destStore<DEST>
-static const DestStoreProc destStoreProc[QImage::NImageFormats] =
+static DestStoreProc destStoreProc[QImage::NImageFormats] =
{
0, // Format_Invalid
destStoreMono, // Format_Mono,
@@ -2827,7 +2827,7 @@ static void QT_FASTCALL rasterop_SourceAndNotDestination(uint *dest,
}
}
-static const CompositionFunctionSolid functionForModeSolid_C[] = {
+static CompositionFunctionSolid functionForModeSolid_C[] = {
comp_func_solid_SourceOver,
comp_func_solid_DestinationOver,
comp_func_solid_Clear,
@@ -2865,7 +2865,7 @@ static const CompositionFunctionSolid functionForModeSolid_C[] = {
static const CompositionFunctionSolid *functionForModeSolid = functionForModeSolid_C;
-static const CompositionFunction functionForMode_C[] = {
+static CompositionFunction functionForMode_C[] = {
comp_func_SourceOver,
comp_func_DestinationOver,
comp_func_Clear,
@@ -3884,8 +3884,8 @@ inline void interpolate_pixel_unaligned_2(DST *dest, const SRC *src,
template <class DST, class SRC>
inline void interpolate_pixel_2(DST *dest, const SRC *src, quint16 alpha)
{
- Q_ASSERT((long(dest) & 0x3) == 0);
- Q_ASSERT((long(src) & 0x3) == 0);
+ Q_ASSERT((quintptr(dest) & 0x3) == 0);
+ Q_ASSERT((quintptr(src) & 0x3) == 0);
const quint16 a = eff_alpha_2(alpha, dest);
const quint16 ia = eff_ialpha_2(alpha, dest);
@@ -3958,8 +3958,8 @@ template <class DST, class SRC>
inline void interpolate_pixel_2(DST *dest, quint8 a,
const SRC *src, quint8 b)
{
- Q_ASSERT((long(dest) & 0x3) == 0);
- Q_ASSERT((long(src) & 0x3) == 0);
+ Q_ASSERT((quintptr(dest) & 0x3) == 0);
+ Q_ASSERT((quintptr(src) & 0x3) == 0);
Q_ASSERT(!SRC::hasAlpha());
@@ -4007,8 +4007,8 @@ inline void interpolate_pixel_2(qrgb444 *dest, quint8 a,
template <class DST, class SRC>
inline void interpolate_pixel_4(DST *dest, const SRC *src, quint32 alpha)
{
- Q_ASSERT((long(dest) & 0x3) == 0);
- Q_ASSERT((long(src) & 0x3) == 0);
+ Q_ASSERT((quintptr(dest) & 0x3) == 0);
+ Q_ASSERT((quintptr(src) & 0x3) == 0);
const quint32 a = eff_alpha_4(alpha, dest);
const quint32 ia = eff_ialpha_4(alpha, dest);
@@ -4411,7 +4411,7 @@ void QT_FASTCALL blendUntransformed_dest16(DST *dest, const SRC *src,
{
Q_ASSERT(sizeof(DST) == 2);
Q_ASSERT(sizeof(SRC) == 2);
- Q_ASSERT((long(dest) & 0x3) == (long(src) & 0x3));
+ Q_ASSERT((quintptr(dest) & 0x3) == (quintptr(src) & 0x3));
Q_ASSERT(coverage > 0);
const int align = quintptr(dest) & 0x3;
@@ -4479,8 +4479,8 @@ void QT_FASTCALL blendUntransformed_dest16(DST *dest, const SRC *src,
}
while (length >= 2) {
- Q_ASSERT((long(dest) & 3) == 0);
- Q_ASSERT((long(src) & 3) == 0);
+ Q_ASSERT((quintptr(dest) & 3) == 0);
+ Q_ASSERT((quintptr(src) & 3) == 0);
const quint16 a = alpha_2(src);
if (a == 0xffff) {
@@ -4511,7 +4511,7 @@ template <class DST, class SRC>
void QT_FASTCALL blendUntransformed_dest24(DST *dest, const SRC *src,
quint8 coverage, int length)
{
- Q_ASSERT((long(dest) & 0x3) == (long(src) & 0x3));
+ Q_ASSERT((quintptr(dest) & 0x3) == (quintptr(src) & 0x3));
Q_ASSERT(sizeof(DST) == 3);
Q_ASSERT(coverage > 0);
@@ -4734,7 +4734,7 @@ static void blend_untransformed_argb8565(int count, const QSpan *spans,
static void blend_untransformed_rgb565(int count, const QSpan *spans,
void *userData)
{
-#if defined(QT_QWS_DEPTH_16)
+#if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16)
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
if (data->texture.format == QImage::Format_ARGB8565_Premultiplied)
@@ -5072,7 +5072,7 @@ static void blend_tiled_argb8565(int count, const QSpan *spans, void *userData)
static void blend_tiled_rgb565(int count, const QSpan *spans, void *userData)
{
-#if defined(QT_QWS_DEPTH_16)
+#if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16)
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
if (data->texture.format == QImage::Format_ARGB8565_Premultiplied)
@@ -5577,7 +5577,7 @@ static void blend_transformed_bilinear_argb8565(int count, const QSpan *spans, v
static void blend_transformed_bilinear_rgb565(int count, const QSpan *spans,
void *userData)
{
-#if defined(QT_QWS_DEPTH_16)
+#if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16)
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
if (data->texture.format == QImage::Format_RGB16)
@@ -6164,7 +6164,7 @@ static void blend_transformed_argb8565(int count, const QSpan *spans,
static void blend_transformed_rgb565(int count, const QSpan *spans,
void *userData)
{
-#if defined(QT_QWS_DEPTH_16)
+#if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16)
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
if (data->texture.format == QImage::Format_ARGB8565_Premultiplied)
@@ -6577,7 +6577,7 @@ static void blend_transformed_tiled_argb8565(int count, const QSpan *spans,
static void blend_transformed_tiled_rgb565(int count, const QSpan *spans,
void *userData)
{
-#if defined(QT_QWS_DEPTH_16)
+#if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16)
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
if (data->texture.format == QImage::Format_ARGB8565_Premultiplied)
@@ -7175,9 +7175,9 @@ static inline void rgbBlendPixel(quint32 *dst, int coverage, int sr, int sg, int
) {
int a = qGray(coverage);
- sr = qt_div_255(sr * a);
- sg = qt_div_255(sg * a);
- sb = qt_div_255(sb * a);
+ sr = qt_div_255(qt_pow_rgb_invgamma[sr] * a);
+ sg = qt_div_255(qt_pow_rgb_invgamma[sg] * a);
+ sb = qt_div_255(qt_pow_rgb_invgamma[sb] * a);
int ia = 255 - a;
dr = qt_div_255(dr * ia);
@@ -7813,7 +7813,6 @@ static void qt_blend_color_argb_armv6(int count, const QSpan *spans, void *userD
void qInitDrawhelperAsm()
{
- const uint features = qDetectCPUFeatures();
qt_memfill32 = qt_memfill_template<quint32, quint32>;
qt_memfill16 = qt_memfill_quint16; //qt_memfill_template<quint16, quint16>;
@@ -7821,7 +7820,7 @@ void qInitDrawhelperAsm()
CompositionFunction *functionForModeAsm = 0;
CompositionFunctionSolid *functionForModeSolidAsm = 0;
-#ifdef QT_NO_DEBUG
+ const uint features = qDetectCPUFeatures();
if (false) {
#ifdef QT_HAVE_SSE2
} else if (features & SSE2) {
@@ -7897,20 +7896,43 @@ void qInitDrawhelperAsm()
qDrawHelper[QImage::Format_ARGB32_Premultiplied].blendColor = qt_blend_color_argb_sse3dnow;
}
#endif // 3DNOW
- extern void qt_blend_rgb32_on_rgb32_sse(uchar *destPixels, int dbpl,
- const uchar *srcPixels, int sbpl,
- int w, int h,
- int const_alpha);
- extern void qt_blend_argb32_on_argb32_sse(uchar *destPixels, int dbpl,
- const uchar *srcPixels, int sbpl,
- int w, int h,
- int const_alpha);
- qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse;
- qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse;
- qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse;
- qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse;
- }
+
+#ifdef QT_HAVE_SSE2
+ if (features & SSE2) {
+ extern void qt_blend_rgb32_on_rgb32_sse2(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha);
+ extern void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha);
+
+
+ qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse2;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse2;
+ qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse2;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse2;
+ } else
+#endif
+ {
+ extern void qt_blend_rgb32_on_rgb32_sse(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha);
+ extern void qt_blend_argb32_on_argb32_sse(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha);
+
+
+ qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse;
+ qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse;
+ }
+}
#endif // SSE
#ifdef QT_HAVE_IWMMXT
@@ -7921,8 +7943,6 @@ void qInitDrawhelperAsm()
}
#endif // IWMMXT
-#endif // QT_NO_DEBUG
-
#if defined(Q_CC_RVCT) && defined(QT_HAVE_ARMV6)
functionForModeAsm = qt_functionForMode_ARMv6;
functionForModeSolidAsm = qt_functionForModeSolid_ARMv6;
@@ -7941,6 +7961,20 @@ void qInitDrawhelperAsm()
qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;
qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;
+ qBlendFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_rgb16_neon;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB16] = qt_blend_rgb16_on_argb32_neon;
+
+ qScaleFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_scale_image_argb32_on_rgb16_neon;
+ qScaleFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_scale_image_rgb16_on_rgb16_neon;
+
+ qTransformFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_transform_image_argb32_on_rgb16_neon;
+ qTransformFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_transform_image_rgb16_on_rgb16_neon;
+
+ qDrawHelper[QImage::Format_RGB16].alphamapBlit = qt_alphamapblit_quint16_neon;
+
+ functionForMode_C[QPainter::CompositionMode_SourceOver] = qt_blend_argb32_on_argb32_scanline_neon;
+ destFetchProc[QImage::Format_RGB16] = qt_destFetchRGB16_neon;
+ destStoreProc[QImage::Format_RGB16] = qt_destStoreRGB16_neon;
}
#endif
diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp
index 77c5202..ee5f24a 100644
--- a/src/gui/painting/qdrawhelper_neon.cpp
+++ b/src/gui/painting/qdrawhelper_neon.cpp
@@ -40,10 +40,13 @@
****************************************************************************/
#include <private/qdrawhelper_p.h>
+#include <private/qblendfunctions_p.h>
+#include <private/qmath_p.h>
#ifdef QT_HAVE_NEON
#include <private/qdrawhelper_neon_p.h>
+#include <private/qpaintengine_raster_p.h>
#include <arm_neon.h>
QT_BEGIN_NAMESPACE
@@ -87,60 +90,142 @@ static inline uint16x8_t qvsource_over_u16(uint16x8_t src16, uint16x8_t dst16, u
return vaddq_u16(src16, qvbyte_mul_u16(dst16, alpha16, half));
}
-void qt_blend_argb32_on_argb32_neon(uchar *destPixels, int dbpl,
- const uchar *srcPixels, int sbpl,
- int w, int h,
- int const_alpha)
+extern "C" void
+pixman_composite_over_8888_0565_asm_neon (int32_t w,
+ int32_t h,
+ uint16_t *dst,
+ int32_t dst_stride,
+ uint32_t *src,
+ int32_t src_stride);
+
+extern "C" void
+pixman_composite_over_8888_8888_asm_neon (int32_t w,
+ int32_t h,
+ uint32_t *dst,
+ int32_t dst_stride,
+ uint32_t *src,
+ int32_t src_stride);
+
+extern "C" void
+pixman_composite_src_0565_8888_asm_neon (int32_t w,
+ int32_t h,
+ uint32_t *dst,
+ int32_t dst_stride,
+ uint16_t *src,
+ int32_t src_stride);
+
+extern "C" void
+pixman_composite_over_n_8_0565_asm_neon (int32_t w,
+ int32_t h,
+ uint16_t *dst,
+ int32_t dst_stride,
+ uint32_t src,
+ int32_t unused,
+ uint8_t *mask,
+ int32_t mask_stride);
+
+extern "C" void
+pixman_composite_scanline_over_asm_neon (int32_t w,
+ const uint32_t *dst,
+ const uint32_t *src);
+
+// qblendfunctions.cpp
+void qt_blend_argb32_on_rgb16_const_alpha(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha);
+
+void qt_blend_rgb16_on_argb32_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha)
{
- const uint *src = (const uint *) srcPixels;
- uint *dst = (uint *) destPixels;
- uint16x8_t half = vdupq_n_u16(0x80);
- uint16x8_t full = vdupq_n_u16(0xff);
- if (const_alpha == 256) {
- for (int y = 0; y < h; ++y) {
- int x = 0;
- for (; x < w-3; x += 4) {
- uint32x4_t src32 = vld1q_u32((uint32_t *)&src[x]);
- if ((src[x] & src[x+1] & src[x+2] & src[x+3]) >= 0xff000000) {
- // all opaque
- vst1q_u32((uint32_t *)&dst[x], src32);
- } else if (src[x] | src[x+1] | src[x+2] | src[x+3]) {
- uint32x4_t dst32 = vld1q_u32((uint32_t *)&dst[x]);
+ dbpl /= 4;
+ sbpl /= 2;
- const uint8x16_t src8 = vreinterpretq_u8_u32(src32);
- const uint8x16_t dst8 = vreinterpretq_u8_u32(dst32);
+ quint32 *dst = (quint32 *) destPixels;
+ quint16 *src = (quint16 *) srcPixels;
- const uint8x8_t src8_low = vget_low_u8(src8);
- const uint8x8_t dst8_low = vget_low_u8(dst8);
+ if (const_alpha != 256) {
+ quint8 a = (255 * const_alpha) >> 8;
+ quint8 ia = 255 - a;
+
+ while (h--) {
+ for (int x=0; x<w; ++x)
+ dst[x] = INTERPOLATE_PIXEL_255(qt_colorConvert(src[x], dst[x]), a, dst[x], ia);
+ dst += dbpl;
+ src += sbpl;
+ }
+ return;
+ }
- const uint8x8_t src8_high = vget_high_u8(src8);
- const uint8x8_t dst8_high = vget_high_u8(dst8);
+ pixman_composite_src_0565_8888_asm_neon(w, h, dst, dbpl, src, sbpl);
+}
- const uint16x8_t src16_low = vmovl_u8(src8_low);
- const uint16x8_t dst16_low = vmovl_u8(dst8_low);
+extern "C" void blend_8_pixels_argb32_on_rgb16_neon(quint16 *dst, const quint32 *src, int const_alpha);
- const uint16x8_t src16_high = vmovl_u8(src8_high);
- const uint16x8_t dst16_high = vmovl_u8(dst8_high);
+void qt_blend_argb32_on_rgb16_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha)
+{
+ quint16 *dst = (quint16 *) destPixels;
+ quint32 *src = (quint32 *) srcPixels;
- const uint16x8_t result16_low = qvsource_over_u16(src16_low, dst16_low, half, full);
- const uint16x8_t result16_high = qvsource_over_u16(src16_high, dst16_high, half, full);
+ if (const_alpha != 256) {
+ for (int y=0; y<h; ++y) {
+ int i = 0;
+ for (; i < w-7; i += 8)
+ blend_8_pixels_argb32_on_rgb16_neon(&dst[i], &src[i], const_alpha);
- const uint32x2_t result32_low = vreinterpret_u32_u8(vmovn_u16(result16_low));
- const uint32x2_t result32_high = vreinterpret_u32_u8(vmovn_u16(result16_high));
+ if (i < w) {
+ int tail = w - i;
- vst1q_u32((uint32_t *)&dst[x], vcombine_u32(result32_low, result32_high));
+ quint16 dstBuffer[8];
+ quint32 srcBuffer[8];
+
+ for (int j = 0; j < tail; ++j) {
+ dstBuffer[j] = dst[i + j];
+ srcBuffer[j] = src[i + j];
+ }
+
+ blend_8_pixels_argb32_on_rgb16_neon(dstBuffer, srcBuffer, const_alpha);
+
+ for (int j = 0; j < tail; ++j) {
+ dst[i + j] = dstBuffer[j];
+ src[i + j] = srcBuffer[j];
}
}
- for (; x<w; ++x) {
- uint s = src[x];
- if (s >= 0xff000000)
- dst[x] = s;
- else if (s != 0)
- dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s));
- }
- dst = (quint32 *)(((uchar *) dst) + dbpl);
- src = (const quint32 *)(((const uchar *) src) + sbpl);
+
+ dst = (quint16 *)(((uchar *) dst) + dbpl);
+ src = (quint32 *)(((uchar *) src) + sbpl);
}
+ return;
+ }
+
+ pixman_composite_over_8888_0565_asm_neon(w, h, dst, dbpl / 2, src, sbpl / 4);
+}
+
+void qt_blend_argb32_on_argb32_scanline_neon(uint *dest, const uint *src, int length, uint const_alpha)
+{
+ if (const_alpha == 255) {
+ pixman_composite_scanline_over_asm_neon(length, dest, src);
+ } else {
+ qt_blend_argb32_on_argb32_neon((uchar *)dest, 4 * length, (uchar *)src, 4 * length, length, 1, (const_alpha * 256) / 255);
+ }
+}
+
+void qt_blend_argb32_on_argb32_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha)
+{
+ const uint *src = (const uint *) srcPixels;
+ uint *dst = (uint *) destPixels;
+ uint16x8_t half = vdupq_n_u16(0x80);
+ uint16x8_t full = vdupq_n_u16(0xff);
+ if (const_alpha == 256) {
+ pixman_composite_over_8888_8888_asm_neon(w, h, (uint32_t *)destPixels, dbpl / 4, (uint32_t *)srcPixels, sbpl / 4);
} else if (const_alpha != 0) {
const_alpha = (const_alpha * 255) >> 8;
uint16x8_t const_alpha16 = vdupq_n_u16(const_alpha);
@@ -254,6 +339,246 @@ void qt_blend_rgb32_on_rgb32_neon(uchar *destPixels, int dbpl,
}
}
+void qt_alphamapblit_quint16_neon(QRasterBuffer *rasterBuffer,
+ int x, int y, quint32 color,
+ const uchar *bitmap,
+ int mapWidth, int mapHeight, int mapStride,
+ const QClipData *)
+{
+ quint16 *dest = reinterpret_cast<quint16*>(rasterBuffer->scanLine(y)) + x;
+ const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16);
+
+ uchar *mask = const_cast<uchar *>(bitmap);
+
+ pixman_composite_over_n_8_0565_asm_neon(mapWidth, mapHeight, dest, destStride, color, 0, mask, mapStride);
+}
+
+extern "C" void blend_8_pixels_rgb16_on_rgb16_neon(quint16 *dst, const quint16 *src, int const_alpha);
+
+template <typename SRC, typename BlendFunc>
+struct Blend_on_RGB16_SourceAndConstAlpha_Neon {
+ Blend_on_RGB16_SourceAndConstAlpha_Neon(BlendFunc blender, int const_alpha)
+ : m_index(0)
+ , m_blender(blender)
+ , m_const_alpha(const_alpha)
+ {
+ }
+
+ inline void write(quint16 *dst, quint32 src)
+ {
+ srcBuffer[m_index++] = src;
+
+ if (m_index == 8) {
+ m_blender(dst - 7, srcBuffer, m_const_alpha);
+ m_index = 0;
+ }
+ }
+
+ inline void flush(quint16 *dst)
+ {
+ if (m_index > 0) {
+ quint16 dstBuffer[8];
+ for (int i = 0; i < m_index; ++i)
+ dstBuffer[i] = dst[i - m_index];
+
+ m_blender(dstBuffer, srcBuffer, m_const_alpha);
+
+ for (int i = 0; i < m_index; ++i)
+ dst[i - m_index] = dstBuffer[i];
+
+ m_index = 0;
+ }
+ }
+
+ SRC srcBuffer[8];
+
+ int m_index;
+ BlendFunc m_blender;
+ int m_const_alpha;
+};
+
+template <typename SRC, typename BlendFunc>
+Blend_on_RGB16_SourceAndConstAlpha_Neon<SRC, BlendFunc>
+Blend_on_RGB16_SourceAndConstAlpha_Neon_create(BlendFunc blender, int const_alpha)
+{
+ return Blend_on_RGB16_SourceAndConstAlpha_Neon<SRC, BlendFunc>(blender, const_alpha);
+}
+
+void qt_scale_image_argb32_on_rgb16_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ int const_alpha)
+{
+ if (const_alpha == 0)
+ return;
+
+ qt_scale_image_16bit<quint32>(destPixels, dbpl, srcPixels, sbpl, targetRect, sourceRect, clip,
+ Blend_on_RGB16_SourceAndConstAlpha_Neon_create<quint32>(blend_8_pixels_argb32_on_rgb16_neon, const_alpha));
+}
+
+void qt_scale_image_rgb16_on_rgb16(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ int const_alpha);
+
+void qt_scale_image_rgb16_on_rgb16_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ int const_alpha)
+{
+ if (const_alpha == 0)
+ return;
+
+ if (const_alpha == 256) {
+ qt_scale_image_rgb16_on_rgb16(destPixels, dbpl, srcPixels, sbpl, targetRect, sourceRect, clip, const_alpha);
+ return;
+ }
+
+ qt_scale_image_16bit<quint16>(destPixels, dbpl, srcPixels, sbpl, targetRect, sourceRect, clip,
+ Blend_on_RGB16_SourceAndConstAlpha_Neon_create<quint16>(blend_8_pixels_rgb16_on_rgb16_neon, const_alpha));
+}
+
+extern void qt_transform_image_rgb16_on_rgb16(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ const QTransform &targetRectTransform,
+ int const_alpha);
+
+void qt_transform_image_rgb16_on_rgb16_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ const QTransform &targetRectTransform,
+ int const_alpha)
+{
+ if (const_alpha == 0)
+ return;
+
+ if (const_alpha == 256) {
+ qt_transform_image_rgb16_on_rgb16(destPixels, dbpl, srcPixels, sbpl, targetRect, sourceRect, clip, targetRectTransform, const_alpha);
+ return;
+ }
+
+ qt_transform_image(reinterpret_cast<quint16 *>(destPixels), dbpl,
+ reinterpret_cast<const quint16 *>(srcPixels), sbpl, targetRect, sourceRect, clip, targetRectTransform,
+ Blend_on_RGB16_SourceAndConstAlpha_Neon_create<quint16>(blend_8_pixels_rgb16_on_rgb16_neon, const_alpha));
+}
+
+void qt_transform_image_argb32_on_rgb16_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ const QTransform &targetRectTransform,
+ int const_alpha)
+{
+ if (const_alpha == 0)
+ return;
+
+ qt_transform_image(reinterpret_cast<quint16 *>(destPixels), dbpl,
+ reinterpret_cast<const quint32 *>(srcPixels), sbpl, targetRect, sourceRect, clip, targetRectTransform,
+ Blend_on_RGB16_SourceAndConstAlpha_Neon_create<quint32>(blend_8_pixels_argb32_on_rgb16_neon, const_alpha));
+}
+
+static inline void convert_8_pixels_rgb16_to_argb32(quint32 *dst, const quint16 *src)
+{
+ asm volatile (
+ "vld1.16 { d0, d1 }, [%[SRC]]\n\t"
+
+ /* convert 8 r5g6b5 pixel data from {d0, d1} to planar 8-bit format
+ and put data into d4 - red, d3 - green, d2 - blue */
+ "vshrn.u16 d4, q0, #8\n\t"
+ "vshrn.u16 d3, q0, #3\n\t"
+ "vsli.u16 q0, q0, #5\n\t"
+ "vsri.u8 d4, d4, #5\n\t"
+ "vsri.u8 d3, d3, #6\n\t"
+ "vshrn.u16 d2, q0, #2\n\t"
+
+ /* fill d5 - alpha with 0xff */
+ "mov r2, #255\n\t"
+ "vdup.8 d5, r2\n\t"
+
+ "vst4.8 { d2, d3, d4, d5 }, [%[DST]]"
+ : : [DST]"r" (dst), [SRC]"r" (src)
+ : "memory", "r2", "d0", "d1", "d2", "d3", "d4", "d5"
+ );
+}
+
+uint * QT_FASTCALL qt_destFetchRGB16_neon(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length)
+{
+ const ushort *data = (const ushort *)rasterBuffer->scanLine(y) + x;
+
+ int i = 0;
+ for (; i < length - 7; i += 8)
+ convert_8_pixels_rgb16_to_argb32(&buffer[i], &data[i]);
+
+ if (i < length) {
+ quint16 srcBuffer[8];
+ quint32 dstBuffer[8];
+
+ int tail = length - i;
+ for (int j = 0; j < tail; ++j)
+ srcBuffer[j] = data[i + j];
+
+ convert_8_pixels_rgb16_to_argb32(dstBuffer, srcBuffer);
+
+ for (int j = 0; j < tail; ++j)
+ buffer[i + j] = dstBuffer[j];
+ }
+
+ return buffer;
+}
+
+static inline void convert_8_pixels_argb32_to_rgb16(quint16 *dst, const quint32 *src)
+{
+ asm volatile (
+ "vld4.8 { d0, d1, d2, d3 }, [%[SRC]]\n\t"
+
+ /* convert to r5g6b5 and store it into {d28, d29} */
+ "vshll.u8 q14, d2, #8\n\t"
+ "vshll.u8 q8, d1, #8\n\t"
+ "vshll.u8 q9, d0, #8\n\t"
+ "vsri.u16 q14, q8, #5\n\t"
+ "vsri.u16 q14, q9, #11\n\t"
+
+ "vst1.16 { d28, d29 }, [%[DST]]"
+ : : [DST]"r" (dst), [SRC]"r" (src)
+ : "memory", "d0", "d1", "d2", "d3", "d16", "d17", "d18", "d19", "d28", "d29"
+ );
+}
+
+void QT_FASTCALL qt_destStoreRGB16_neon(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length)
+{
+ quint16 *data = (quint16*)rasterBuffer->scanLine(y) + x;
+
+ int i = 0;
+ for (; i < length - 7; i += 8)
+ convert_8_pixels_argb32_to_rgb16(&data[i], &buffer[i]);
+
+ if (i < length) {
+ quint32 srcBuffer[8];
+ quint16 dstBuffer[8];
+
+ int tail = length - i;
+ for (int j = 0; j < tail; ++j)
+ srcBuffer[j] = buffer[i + j];
+
+ convert_8_pixels_argb32_to_rgb16(dstBuffer, srcBuffer);
+
+ for (int j = 0; j < tail; ++j)
+ data[i + j] = dstBuffer[j];
+ }
+}
+
QT_END_NAMESPACE
#endif // QT_HAVE_NEON
diff --git a/src/gui/painting/qdrawhelper_neon_asm.S b/src/gui/painting/qdrawhelper_neon_asm.S
new file mode 100644
index 0000000..9992817
--- /dev/null
+++ b/src/gui/painting/qdrawhelper_neon_asm.S
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** 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 QtGui module 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$
+**
+****************************************************************************/
+
+/* Prevent the stack from becoming executable for no reason... */
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
+
+.text
+.fpu neon
+.arch armv7a
+.altmacro
+
+/* void blend_8_pixels_argb32_on_rgb16_neon(quint16 *dst, const quint32 *src, int const_alpha) */
+
+ .func blend_8_pixels_argb32_on_rgb16_neon
+ .global blend_8_pixels_argb32_on_rgb16_neon
+ /* For ELF format also set function visibility to hidden */
+#ifdef __ELF__
+ .hidden blend_8_pixels_argb32_on_rgb16_neon
+ .type blend_8_pixels_argb32_on_rgb16_neon, %function
+#endif
+blend_8_pixels_argb32_on_rgb16_neon:
+ vld4.8 { d0, d1, d2, d3 }, [r1]
+ vld1.16 { d4, d5 }, [r0]
+
+ cmp r2, #256
+ beq .blend_32_inner
+
+ vdup.8 d6, r2
+
+ /* multiply by const_alpha */
+ vmull.u8 q8, d6, d0
+ vmull.u8 q9, d6, d1
+ vmull.u8 q10, d6, d2
+ vmull.u8 q11, d6, d3
+
+ vshrn.u16 d0, q8, #8
+ vshrn.u16 d1, q9, #8
+ vshrn.u16 d2, q10, #8
+ vshrn.u16 d3, q11, #8
+
+.blend_32_inner:
+ /* convert 8 r5g6b5 pixel data from {d4, d5} to planar 8-bit format
+ and put data into d6 - red, d7 - green, d30 - blue */
+ vshrn.u16 d6, q2, #8
+ vshrn.u16 d7, q2, #3
+ vsli.u16 q2, q2, #5
+ vsri.u8 d6, d6, #5
+ vmvn.8 d3, d3
+ vsri.u8 d7, d7, #6
+ vshrn.u16 d30, q2, #2
+
+ pld [r0, #128]
+
+ /* now do alpha blending, storing results in 8-bit planar format
+ into d16 - red, d19 - green, d18 - blue */
+ vmull.u8 q10, d3, d6
+ vmull.u8 q11, d3, d7
+ vmull.u8 q12, d3, d30
+ vrshr.u16 q13, q10, #8
+ vrshr.u16 q3, q11, #8
+ vrshr.u16 q15, q12, #8
+ vraddhn.u16 d20, q10, q13
+ vraddhn.u16 d23, q11, q3
+ vraddhn.u16 d22, q12, q15
+ vqadd.u8 d16, d2, d20
+ vqadd.u8 q9, q0, q11
+ /* convert the result to r5g6b5 and store it into {d28, d29} */
+ vshll.u8 q14, d16, #8
+ vshll.u8 q8, d19, #8
+ vshll.u8 q9, d18, #8
+ vsri.u16 q14, q8, #5
+ vsri.u16 q14, q9, #11
+
+ vst1.16 { d28, d29 }, [r0]
+
+ bx lr
+
+ .endfunc
+
+/* void blend_8_pixels_rgb16_on_rgb16_neon(quint16 *dst, const quint16 *src, int const_alpha) */
+
+ .func blend_8_pixels_rgb16_on_rgb16_neon
+ .global blend_8_pixels_rgb16_on_rgb16_neon
+ /* For ELF format also set function visibility to hidden */
+#ifdef __ELF__
+ .hidden blend_8_pixels_rgb16_on_rgb16_neon
+ .type blend_8_pixels_rgb16_on_rgb16_neon, %function
+#endif
+blend_8_pixels_rgb16_on_rgb16_neon:
+ vld1.16 { d0, d1 }, [r0]
+ vld1.16 { d2, d3 }, [r1]
+
+ rsb r3, r2, #256
+ vdup.8 d4, r2
+ vdup.8 d5, r3
+
+ /* convert 8 r5g6b5 pixel data from {d0, d1} to planar 8-bit format
+ and put data into d6 - red, d7 - green, d30 - blue */
+ vshrn.u16 d6, q0, #8
+ vshrn.u16 d7, q0, #3
+ vsli.u16 q0, q0, #5
+ vsri.u8 d6, d6, #5
+ vsri.u8 d7, d7, #6
+ vshrn.u16 d30, q0, #2
+
+ /* same from {d2, d3} into {d26, d27, d28} */
+ vshrn.u16 d26, q1, #8
+ vshrn.u16 d27, q1, #3
+ vsli.u16 q1, q1, #5
+ vsri.u8 d26, d26, #5
+ vsri.u8 d27, d27, #6
+ vshrn.u16 d28, q1, #2
+
+ /* multiply dst by inv const_alpha */
+ vmull.u8 q10, d5, d6
+ vmull.u8 q11, d5, d7
+ vmull.u8 q12, d5, d30
+
+ vshrn.u16 d6, q10, #8
+ vshrn.u16 d7, q11, #8
+ vshrn.u16 d30, q12, #8
+
+ /* multiply src by const_alpha */
+ vmull.u8 q10, d4, d26
+ vmull.u8 q11, d4, d27
+ vmull.u8 q12, d4, d28
+
+ vshrn.u16 d26, q10, #8
+ vshrn.u16 d27, q11, #8
+ vshrn.u16 d28, q12, #8
+
+ /* preload dst + 128 */
+ pld [r0, #128]
+
+ /* add components, storing results in 8-bit planar format
+ into d16 - red, d19 - green, d18 - blue */
+ vadd.u8 d16, d26, d6
+ vadd.u8 d19, d27, d7
+ vadd.u8 d18, d28, d30
+
+ /* convert the result to r5g6b5 and store it into {d28, d29} */
+ vshll.u8 q14, d16, #8
+ vshll.u8 q8, d19, #8
+ vshll.u8 q9, d18, #8
+ vsri.u16 q14, q8, #5
+ vsri.u16 q14, q9, #11
+
+ vst1.16 { d28, d29 }, [r0]
+
+ bx lr
+
+ .endfunc
diff --git a/src/gui/painting/qdrawhelper_neon_p.h b/src/gui/painting/qdrawhelper_neon_p.h
index 1994441..d6a4509 100644
--- a/src/gui/painting/qdrawhelper_neon_p.h
+++ b/src/gui/painting/qdrawhelper_neon_p.h
@@ -69,6 +69,64 @@ void qt_blend_rgb32_on_rgb32_neon(uchar *destPixels, int dbpl,
int w, int h,
int const_alpha);
+void qt_blend_argb32_on_rgb16_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha);
+
+void qt_blend_argb32_on_argb32_scanline_neon(uint *dest,
+ const uint *src,
+ int length,
+ uint const_alpha);
+
+void qt_blend_rgb16_on_argb32_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha);
+
+void qt_alphamapblit_quint16_neon(QRasterBuffer *rasterBuffer,
+ int x, int y, quint32 color,
+ const uchar *bitmap,
+ int mapWidth, int mapHeight, int mapStride,
+ const QClipData *clip);
+
+void qt_scale_image_argb32_on_rgb16_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ int const_alpha);
+
+void qt_scale_image_rgb16_on_rgb16_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ int const_alpha);
+
+void qt_transform_image_argb32_on_rgb16_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ const QTransform &targetRectTransform,
+ int const_alpha);
+
+void qt_transform_image_rgb16_on_rgb16_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ const QTransform &targetRectTransform,
+ int const_alpha);
+
+uint * QT_FASTCALL qt_destFetchRGB16_neon(uint *buffer,
+ QRasterBuffer *rasterBuffer,
+ int x, int y, int length);
+
+void QT_FASTCALL qt_destStoreRGB16_neon(QRasterBuffer *rasterBuffer,
+ int x, int y, const uint *buffer, int length);
+
#endif // QT_HAVE_NEON
QT_END_NAMESPACE
diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp
index dd6fa1b..6ac64d3 100644
--- a/src/gui/painting/qdrawhelper_sse2.cpp
+++ b/src/gui/painting/qdrawhelper_sse2.cpp
@@ -57,6 +57,217 @@
QT_BEGIN_NAMESPACE
+/*
+ * Multiply the components of pixelVector by alphaChannel
+ * Each 32bits components of alphaChannel must be in the form 0x00AA00AA
+ * colorMask must have 0x00ff00ff on each 32 bits component
+ * half must have the value 128 (0x80) for each 32 bits compnent
+ */
+#define BYTE_MUL_SSE2(result, pixelVector, alphaChannel, colorMask, half) \
+{ \
+ /* 1. separate the colors in 2 vectors so each color is on 16 bits \
+ (in order to be multiplied by the alpha \
+ each 32 bit of dstVectorAG are in the form 0x00AA00GG \
+ each 32 bit of dstVectorRB are in the form 0x00RR00BB */\
+ __m128i pixelVectorAG = _mm_srli_epi16(pixelVector, 8); \
+ __m128i pixelVectorRB = _mm_and_si128(pixelVector, colorMask); \
+ \
+ /* 2. multiply the vectors by the alpha channel */\
+ pixelVectorAG = _mm_mullo_epi16(pixelVectorAG, alphaChannel); \
+ pixelVectorRB = _mm_mullo_epi16(pixelVectorRB, alphaChannel); \
+ \
+ /* 3. devide by 255, that's the tricky part. \
+ we do it like for BYTE_MUL(), with bit shift: X/255 ~= (X + X/256 + rounding)/256 */ \
+ /** so first (X + X/256 + rounding) */\
+ pixelVectorRB = _mm_add_epi16(pixelVectorRB, _mm_srli_epi16(pixelVectorRB, 8)); \
+ pixelVectorRB = _mm_add_epi16(pixelVectorRB, half); \
+ pixelVectorAG = _mm_add_epi16(pixelVectorAG, _mm_srli_epi16(pixelVectorAG, 8)); \
+ pixelVectorAG = _mm_add_epi16(pixelVectorAG, half); \
+ \
+ /** second devide by 256 */\
+ pixelVectorRB = _mm_srli_epi16(pixelVectorRB, 8); \
+ /** for AG, we could >> 8 to divide followed by << 8 to put the \
+ bytes in the correct position. By masking instead, we execute \
+ only one instruction */\
+ pixelVectorAG = _mm_andnot_si128(colorMask, pixelVectorAG); \
+ \
+ /* 4. combine the 2 pairs of colors */ \
+ result = _mm_or_si128(pixelVectorAG, pixelVectorRB); \
+}
+
+/*
+ * Each 32bits components of alphaChannel must be in the form 0x00AA00AA
+ * oneMinusAlphaChannel must be 255 - alpha for each 32 bits component
+ * colorMask must have 0x00ff00ff on each 32 bits component
+ * half must have the value 128 (0x80) for each 32 bits compnent
+ */
+#define INTERPOLATE_PIXEL_255_SSE2(result, srcVector, dstVector, alphaChannel, oneMinusAlphaChannel, colorMask, half) { \
+ /* interpolate AG */\
+ __m128i srcVectorAG = _mm_srli_epi16(srcVector, 8); \
+ __m128i dstVectorAG = _mm_srli_epi16(dstVector, 8); \
+ __m128i srcVectorAGalpha = _mm_mullo_epi16(srcVectorAG, alphaChannel); \
+ __m128i dstVectorAGoneMinusAlphalpha = _mm_mullo_epi16(dstVectorAG, oneMinusAlphaChannel); \
+ __m128i finalAG = _mm_add_epi16(srcVectorAGalpha, dstVectorAGoneMinusAlphalpha); \
+ finalAG = _mm_add_epi16(finalAG, _mm_srli_epi16(finalAG, 8)); \
+ finalAG = _mm_add_epi16(finalAG, half); \
+ finalAG = _mm_andnot_si128(colorMask, finalAG); \
+ \
+ /* interpolate RB */\
+ __m128i srcVectorRB = _mm_and_si128(srcVector, colorMask); \
+ __m128i dstVectorRB = _mm_and_si128(dstVector, colorMask); \
+ __m128i srcVectorRBalpha = _mm_mullo_epi16(srcVectorRB, alphaChannel); \
+ __m128i dstVectorRBoneMinusAlphalpha = _mm_mullo_epi16(dstVectorRB, oneMinusAlphaChannel); \
+ __m128i finalRB = _mm_add_epi16(srcVectorRBalpha, dstVectorRBoneMinusAlphalpha); \
+ finalRB = _mm_add_epi16(finalRB, _mm_srli_epi16(finalRB, 8)); \
+ finalRB = _mm_add_epi16(finalRB, half); \
+ finalRB = _mm_srli_epi16(finalRB, 8); \
+ \
+ /* combine */\
+ result = _mm_or_si128(finalAG, finalRB); \
+}
+
+void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha)
+{
+ const quint32 *src = (const quint32 *) srcPixels;
+ quint32 *dst = (uint *) destPixels;
+ if (const_alpha == 256) {
+ const __m128i alphaMask = _mm_set1_epi32(0xff000000);
+ const __m128i nullVector = _mm_set1_epi32(0);
+ const __m128i half = _mm_set1_epi16(0x80);
+ const __m128i one = _mm_set1_epi16(0xff);
+ const __m128i colorMask = _mm_set1_epi32(0x00ff00ff);
+ for (int y = 0; y < h; ++y) {
+ int x = 0;
+ for (; x < w-3; x += 4) {
+ const __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]);
+ const __m128i srcVectorAlpha = _mm_and_si128(srcVector, alphaMask);
+ if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, alphaMask)) == 0xffff) {
+ // all opaque
+ _mm_storeu_si128((__m128i *)&dst[x], srcVector);
+ } else if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, nullVector)) != 0xffff) {
+ // not fully transparent
+ // result = s + d * (1-alpha)
+
+ // extract the alpha channel on 2 x 16 bits
+ // so we have room for the multiplication
+ // each 32 bits will be in the form 0x00AA00AA
+ // with A being the 1 - alpha
+ __m128i alphaChannel = _mm_srli_epi32(srcVector, 24);
+ alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16));
+ alphaChannel = _mm_sub_epi16(one, alphaChannel);
+
+ const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]);
+ __m128i destMultipliedByOneMinusAlpha;
+ BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half);
+
+ // result = s + d * (1-alpha)
+ const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha);
+ _mm_storeu_si128((__m128i *)&dst[x], result);
+ }
+ }
+ for (; x<w; ++x) {
+ uint s = src[x];
+ if (s >= 0xff000000)
+ dst[x] = s;
+ else if (s != 0)
+ dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s));
+ }
+ dst = (quint32 *)(((uchar *) dst) + dbpl);
+ src = (const quint32 *)(((const uchar *) src) + sbpl);
+ }
+ } else if (const_alpha != 0) {
+ // dest = (s + d * sia) * ca + d * cia
+ // = s * ca + d * (sia * ca + cia)
+ // = s * ca + d * (1 - sa*ca)
+ const_alpha = (const_alpha * 255) >> 8;
+ const __m128i nullVector = _mm_set1_epi32(0);
+ const __m128i half = _mm_set1_epi16(0x80);
+ const __m128i one = _mm_set1_epi16(0xff);
+ const __m128i colorMask = _mm_set1_epi32(0x00ff00ff);
+ const __m128i constAlphaVector = _mm_set1_epi16(const_alpha);
+ for (int y = 0; y < h; ++y) {
+ int x = 0;
+ for (; x < w-3; x += 4) {
+ __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]);
+ if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVector, nullVector)) != 0xffff) {
+ BYTE_MUL_SSE2(srcVector, srcVector, constAlphaVector, colorMask, half);
+
+ __m128i alphaChannel = _mm_srli_epi32(srcVector, 24);
+ alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16));
+ alphaChannel = _mm_sub_epi16(one, alphaChannel);
+
+ const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]);
+ __m128i destMultipliedByOneMinusAlpha;
+ BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half);
+
+ const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha);
+ _mm_storeu_si128((__m128i *)&dst[x], result);
+ }
+ }
+ for (; x<w; ++x) {
+ quint32 s = src[x];
+ if (s != 0) {
+ s = BYTE_MUL(s, const_alpha);
+ dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s));
+ }
+ }
+ dst = (quint32 *)(((uchar *) dst) + dbpl);
+ src = (const quint32 *)(((const uchar *) src) + sbpl);
+ }
+ }
+}
+
+// qblendfunctions.cpp
+void qt_blend_rgb32_on_rgb32(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha);
+
+void qt_blend_rgb32_on_rgb32_sse2(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha)
+{
+ const quint32 *src = (const quint32 *) srcPixels;
+ quint32 *dst = (uint *) destPixels;
+ if (const_alpha != 256) {
+ if (const_alpha != 0) {
+ const __m128i nullVector = _mm_set1_epi32(0);
+ const __m128i half = _mm_set1_epi16(0x80);
+ const __m128i colorMask = _mm_set1_epi32(0x00ff00ff);
+
+ const_alpha = (const_alpha * 255) >> 8;
+ int one_minus_const_alpha = 255 - const_alpha;
+ const __m128i constAlphaVector = _mm_set1_epi16(const_alpha);
+ const __m128i oneMinusConstAlpha = _mm_set1_epi16(one_minus_const_alpha);
+ for (int y = 0; y < h; ++y) {
+ int x = 0;
+ for (; x < w-3; x += 4) {
+ __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]);
+ if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVector, nullVector)) != 0xffff) {
+ const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]);
+ __m128i result;
+ INTERPOLATE_PIXEL_255_SSE2(result, srcVector, dstVector, constAlphaVector, oneMinusConstAlpha, colorMask, half);
+ _mm_storeu_si128((__m128i *)&dst[x], result);
+ }
+ }
+ for (; x<w; ++x) {
+ quint32 s = src[x];
+ s = BYTE_MUL(s, const_alpha);
+ dst[x] = INTERPOLATE_PIXEL_255(src[x], const_alpha, dst[x], one_minus_const_alpha);
+ }
+ dst = (quint32 *)(((uchar *) dst) + dbpl);
+ src = (const quint32 *)(((const uchar *) src) + sbpl);
+ }
+ }
+ } else {
+ qt_blend_rgb32_on_rgb32(destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha);
+ }
+}
+
void qt_memfill32_sse2(quint32 *dest, quint32 value, int count)
{
if (count < 7) {
diff --git a/src/gui/painting/qdrawhelper_x86_p.h b/src/gui/painting/qdrawhelper_x86_p.h
index 30aadd0..d7282a7 100644
--- a/src/gui/painting/qdrawhelper_x86_p.h
+++ b/src/gui/painting/qdrawhelper_x86_p.h
@@ -114,6 +114,14 @@ void qt_bitmapblit32_sse2(QRasterBuffer *rasterBuffer, int x, int y,
void qt_bitmapblit16_sse2(QRasterBuffer *rasterBuffer, int x, int y,
quint32 color,
const uchar *src, int width, int height, int stride);
+void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha);
+void qt_blend_rgb32_on_rgb32_sse2(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha);
#endif // QT_HAVE_SSE2
#ifdef QT_HAVE_IWMMXT
diff --git a/src/gui/painting/qdrawutil.cpp b/src/gui/painting/qdrawutil.cpp
index d76c709..a62f06b 100644
--- a/src/gui/painting/qdrawutil.cpp
+++ b/src/gui/painting/qdrawutil.cpp
@@ -1081,7 +1081,7 @@ void qDrawItem(QPainter *p, Qt::GUIStyle gs,
according to the \a margins structure.
*/
-typedef QVarLengthArray<QPainter::Fragment, 16> QPixmapFragmentsArray;
+typedef QVarLengthArray<QPainter::PixmapFragment, 16> QPixmapFragmentsArray;
/*!
\since 4.6
@@ -1102,7 +1102,7 @@ void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargin
const QPixmap &pixmap, const QRect &sourceRect,const QMargins &sourceMargins,
const QTileRules &rules, QDrawBorderPixmap::DrawingHints hints)
{
- QPainter::Fragment d;
+ QPainter::PixmapFragment d;
d.opacity = 1.0;
d.rotation = 0.0;
diff --git a/src/gui/painting/qgraphicssystem_raster.cpp b/src/gui/painting/qgraphicssystem_raster.cpp
index f90aea0..909508e 100644
--- a/src/gui/painting/qgraphicssystem_raster.cpp
+++ b/src/gui/painting/qgraphicssystem_raster.cpp
@@ -41,19 +41,32 @@
#include "qgraphicssystem_raster_p.h"
+#ifdef Q_OS_SYMBIAN
+#include "private/qpixmap_s60_p.h"
+#include "private/qwindowsurface_s60_p.h"
+#else
#include "private/qpixmap_raster_p.h"
#include "private/qwindowsurface_raster_p.h"
+#endif
QT_BEGIN_NAMESPACE
QPixmapData *QRasterGraphicsSystem::createPixmapData(QPixmapData::PixelType type) const
{
+#ifdef Q_OS_SYMBIAN
+ return new QS60PixmapData(type);
+#else
return new QRasterPixmapData(type);
+#endif
}
QWindowSurface *QRasterGraphicsSystem::createWindowSurface(QWidget *widget) const
{
+#ifdef Q_OS_SYMBIAN
+ return new QS60WindowSurface(widget);
+#else
return new QRasterWindowSurface(widget);
+#endif
}
QT_END_NAMESPACE
diff --git a/src/gui/painting/qmemrotate_p.h b/src/gui/painting/qmemrotate_p.h
index 8df0520..2911860 100644
--- a/src/gui/painting/qmemrotate_p.h
+++ b/src/gui/painting/qmemrotate_p.h
@@ -82,8 +82,9 @@ QT_BEGIN_NAMESPACE
void Q_GUI_QWS_EXPORT qt_memrotate270(const srctype*, int, int, int, desttype*, int)
void Q_GUI_EXPORT qt_memrotate90(const quint32*, int, int, int, quint32*, int);
+void Q_GUI_QWS_EXPORT qt_memrotate180(const quint32*, int, int, int, quint32*, int);
+void Q_GUI_QWS_EXPORT qt_memrotate270(const quint32*, int, int, int, quint32*, int);
-QT_DECL_MEMROTATE(quint32, quint32);
QT_DECL_MEMROTATE(quint32, quint16);
QT_DECL_MEMROTATE(quint16, quint32);
QT_DECL_MEMROTATE(quint16, quint16);
diff --git a/src/gui/painting/qpaintbuffer.cpp b/src/gui/painting/qpaintbuffer.cpp
index 39b76c8..e1156dc 100644
--- a/src/gui/painting/qpaintbuffer.cpp
+++ b/src/gui/painting/qpaintbuffer.cpp
@@ -269,24 +269,300 @@ void QPaintBuffer::draw(QPainter *painter, int frame) const
printf("\n");
#endif
- if (painter && !painter->isActive())
- return;
+ processCommands(painter, frameStartIndex(frame), frameEndIndex(frame));
+
+#ifdef QPAINTBUFFER_DEBUG_DRAW
+ qDebug() << "QPaintBuffer::draw() -------------------------------- DONE!";
+#endif
+}
+
+int QPaintBuffer::frameStartIndex(int frame) const
+{
+ return (frame == 0) ? 0 : d_ptr->frames.at(frame - 1);
+}
+
+int QPaintBuffer::frameEndIndex(int frame) const
+{
+ return (frame == d_ptr->frames.size()) ? d_ptr->commands.size() : d_ptr->frames.at(frame);
+}
+
+int QPaintBuffer::processCommands(QPainter *painter, int begin, int end) const
+{
+ if (!painter || !painter->isActive())
+ return 0;
QPaintEngineEx *xengine = painter->paintEngine()->isExtended()
? (QPaintEngineEx *) painter->paintEngine() : 0;
if (xengine) {
QPaintEngineExReplayer player;
- player.draw(*this, painter, frame);
+ player.processCommands(*this, painter, begin, end);
} else {
QPainterReplayer player;
- player.draw(*this, painter, frame);
+ player.processCommands(*this, painter, begin, end);
}
-#ifdef QPAINTBUFFER_DEBUG_DRAW
- qDebug() << "QPaintBuffer::draw() -------------------------------- DONE!";
-#endif
+ int depth = 0;
+ for (int i = begin; i < end; ++i) {
+ const QPaintBufferCommand &cmd = d_ptr->commands.at(i);
+ if (cmd.id == QPaintBufferPrivate::Cmd_Save)
+ ++depth;
+ else if (cmd.id == QPaintBufferPrivate::Cmd_Restore)
+ --depth;
+ }
+ return depth;
}
+QString QPaintBuffer::commandDescription(int command) const
+{
+ QString desc;
+ QDebug debug(&desc);
+
+ const QPaintBufferCommand &cmd = d_ptr->commands.at(command);
+
+ switch (cmd.id) {
+ case QPaintBufferPrivate::Cmd_Save: {
+ debug << "Cmd_Save";
+ break; }
+
+ case QPaintBufferPrivate::Cmd_Restore: {
+ debug << "Cmd_Restore";
+ break; }
+
+ case QPaintBufferPrivate::Cmd_SetBrush: {
+ QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.offset));
+ debug << "Cmd_SetBrush: " << brush;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_SetBrushOrigin: {
+ debug << "Cmd_SetBrushOrigin: " << d_ptr->variants.at(cmd.offset).toPointF();
+ break; }
+
+ case QPaintBufferPrivate::Cmd_SetCompositionMode: {
+ QPainter::CompositionMode mode = (QPainter::CompositionMode) cmd.extra;
+ debug << "ExCmd_SetCompositionMode, mode: " << mode;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_SetOpacity: {
+ debug << "ExCmd_SetOpacity: " << d_ptr->variants.at(cmd.offset).toDouble();
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawVectorPath: {
+ debug << "ExCmd_DrawVectorPath: size: " << cmd.size
+// << ", hints:" << d->ints[cmd.offset2+cmd.size]
+ << "pts/elms:" << cmd.offset << cmd.offset2;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_StrokeVectorPath: {
+ QPen pen = qVariantValue<QPen>(d_ptr->variants.at(cmd.extra));
+ debug << "ExCmd_StrokeVectorPath: size: " << cmd.size
+// << ", hints:" << d->ints[cmd.offset2+cmd.size]
+ << "pts/elms:" << cmd.offset << cmd.offset2 << pen;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_FillVectorPath: {
+ QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.extra));
+ debug << "ExCmd_FillVectorPath: size: " << cmd.size
+// << ", hints:" << d->ints[cmd.offset2+cmd.size]
+ << "pts/elms:" << cmd.offset << cmd.offset2 << brush;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_FillRectBrush: {
+ QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.extra));
+ QRectF *rect = (QRectF *)(d_ptr->floats.constData() + cmd.offset);
+ debug << "ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " brush: " << brush;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_FillRectColor: {
+ QColor color = qVariantValue<QColor>(d_ptr->variants.at(cmd.extra));
+ QRectF *rect = (QRectF *)(d_ptr->floats.constData() + cmd.offset);
+ debug << "ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " color: " << color;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawPolygonF: {
+ debug << "ExCmd_DrawPolygonF, offset: " << cmd.offset << " size: " << cmd.size
+ << " mode: " << cmd.extra
+ << d_ptr->floats.at(cmd.offset)
+ << d_ptr->floats.at(cmd.offset+1);
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawPolygonI: {
+ debug << "ExCmd_DrawPolygonI, offset: " << cmd.offset << " size: " << cmd.size
+ << " mode: " << cmd.extra
+ << d_ptr->ints.at(cmd.offset)
+ << d_ptr->ints.at(cmd.offset+1);
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawEllipseF: {
+ debug << "ExCmd_DrawEllipseF, offset: " << cmd.offset;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawLineF: {
+ debug << "ExCmd_DrawLineF, offset: " << cmd.offset << " size: " << cmd.size;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawLineI: {
+ debug << "ExCmd_DrawLineI, offset: " << cmd.offset << " size: " << cmd.size;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawPointsF: {
+ debug << "ExCmd_DrawPointsF, offset: " << cmd.offset << " size: " << cmd.size;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawPointsI: {
+ debug << "ExCmd_DrawPointsI, offset: " << cmd.offset << " size: " << cmd.size;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawPolylineF: {
+ debug << "ExCmd_DrawPolylineF, offset: " << cmd.offset << " size: " << cmd.size;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawPolylineI: {
+ debug << "ExCmd_DrawPolylineI, offset: " << cmd.offset << " size: " << cmd.size;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawRectF: {
+ debug << "ExCmd_DrawRectF, offset: " << cmd.offset << " size: " << cmd.size;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawRectI: {
+ debug << "ExCmd_DrawRectI, offset: " << cmd.offset << " size: " << cmd.size;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_SetClipEnabled: {
+ bool clipEnabled = d_ptr->variants.at(cmd.offset).toBool();
+ debug << "ExCmd_SetClipEnabled:" << clipEnabled;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_ClipVectorPath: {
+ QVectorPathCmd path(d_ptr, cmd);
+ debug << "ExCmd_ClipVectorPath:" << path().elementCount();
+ break; }
+
+ case QPaintBufferPrivate::Cmd_ClipRect: {
+ QRect rect(QPoint(d_ptr->ints.at(cmd.offset), d_ptr->ints.at(cmd.offset + 1)),
+ QPoint(d_ptr->ints.at(cmd.offset + 2), d_ptr->ints.at(cmd.offset + 3)));
+ debug << "ExCmd_ClipRect:" << rect << cmd.extra;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_ClipRegion: {
+ QRegion region(d_ptr->variants.at(cmd.offset).value<QRegion>());
+ debug << "ExCmd_ClipRegion:" << region.boundingRect() << cmd.extra;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_SetPen: {
+ QPen pen = qVariantValue<QPen>(d_ptr->variants.at(cmd.offset));
+ debug << "Cmd_SetPen: " << pen;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_SetTransform: {
+ QTransform xform = qVariantValue<QTransform>(d_ptr->variants.at(cmd.offset));
+ debug << "Cmd_SetTransform, offset: " << cmd.offset << xform;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_SetRenderHints: {
+ debug << "Cmd_SetRenderHints, hints: " << cmd.extra;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_SetBackgroundMode: {
+ debug << "Cmd_SetBackgroundMode: " << cmd.extra;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawConvexPolygonF: {
+ debug << "Cmd_DrawConvexPolygonF, offset: " << cmd.offset << " size: " << cmd.size;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawConvexPolygonI: {
+ debug << "Cmd_DrawConvexPolygonI, offset: " << cmd.offset << " size: " << cmd.size;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawEllipseI: {
+ debug << "Cmd_DrawEllipseI, offset: " << cmd.offset;
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawPixmapRect: {
+ QPixmap pm(d_ptr->variants.at(cmd.offset).value<QPixmap>());
+ QRectF r(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1),
+ d_ptr->floats.at(cmd.extra+2), d_ptr->floats.at(cmd.extra+3));
+
+ QRectF sr(d_ptr->floats.at(cmd.extra+4), d_ptr->floats.at(cmd.extra+5),
+ d_ptr->floats.at(cmd.extra+6), d_ptr->floats.at(cmd.extra+7));
+ debug << "Cmd_DrawPixmapRect:" << r << sr << pm.size();
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawPixmapPos: {
+ QPixmap pm(d_ptr->variants.at(cmd.offset).value<QPixmap>());
+ QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
+ debug << "Cmd_DrawPixmapPos:" << pos << pm.size();
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawTiledPixmap: {
+ QPixmap pm(d_ptr->variants.at(cmd.offset).value<QPixmap>());
+ QRectF r(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1),
+ d_ptr->floats.at(cmd.extra+2), d_ptr->floats.at(cmd.extra+3));
+
+ QPointF offset(d_ptr->floats.at(cmd.extra+4), d_ptr->floats.at(cmd.extra+5));
+ debug << "Cmd_DrawTiledPixmap:" << r << offset << pm.size();
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawImageRect: {
+ QImage image(d_ptr->variants.at(cmd.offset).value<QImage>());
+ QRectF r(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1),
+ d_ptr->floats.at(cmd.extra+2), d_ptr->floats.at(cmd.extra+3));
+ QRectF sr(d_ptr->floats.at(cmd.extra+4), d_ptr->floats.at(cmd.extra+5),
+ d_ptr->floats.at(cmd.extra+6), d_ptr->floats.at(cmd.extra+7));
+ debug << "Cmd_DrawImageRect:" << r << sr << image.size();
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawImagePos: {
+ QImage image(d_ptr->variants.at(cmd.offset).value<QImage>());
+ QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
+ debug << "Cmd_DrawImagePos:" << pos << image.size();
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawText: {
+ QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
+ QList<QVariant> variants(d_ptr->variants.at(cmd.offset).value<QList<QVariant> >());
+
+ QFont font(variants.at(0).value<QFont>());
+ QString text(variants.at(1).value<QString>());
+
+ debug << "Cmd_DrawText:" << pos << text << font.family();
+ break; }
+
+ case QPaintBufferPrivate::Cmd_DrawTextItem: {
+ QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
+ QTextItemIntCopy *tiCopy = reinterpret_cast<QTextItemIntCopy *>(qVariantValue<void *>(d_ptr->variants.at(cmd.offset)));
+ QTextItemInt &ti = (*tiCopy)();
+ QString text(ti.text());
+
+ QFont font(ti.font());
+ font.setUnderline(false);
+ font.setStrikeOut(false);
+ font.setOverline(false);
+
+ const QTextItemInt &si = static_cast<const QTextItemInt &>(ti);
+ qreal justificationWidth = 0;
+ if (si.justified)
+ justificationWidth = si.width.toReal();
+
+ debug << "Cmd_DrawTextItem:" << pos << " " << text;
+ break; }
+ case QPaintBufferPrivate::Cmd_SystemStateChanged: {
+ QRegion systemClip(d_ptr->variants.at(cmd.offset).value<QRegion>());
+
+ debug << "Cmd_SystemStateChanged:" << systemClip;
+ break; }
+ case QPaintBufferPrivate::Cmd_Translate: {
+ QPointF delta(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
+ debug << "Cmd_Translate:" << delta;
+ break; }
+ case QPaintBufferPrivate::Cmd_DrawStaticText: {
+ debug << "Cmd_DrawStaticText";
+ break; }
+ }
+
+ return desc;
+}
QRectF QPaintBuffer::boundingRect() const
{
@@ -992,13 +1268,14 @@ void QPaintBufferEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pm, con
void QPaintBufferEngine::drawStaticTextItem(QStaticTextItem *staticTextItem)
{
- QString text = QString(staticTextItem->chars, staticTextItem->numChars);
+ QVariantList variants;
- QStaticText staticText(text);
- staticText.prepare(state()->matrix, staticTextItem->font);
+ variants << QVariant(staticTextItem->font);
+ for (int i=0; i<staticTextItem->numGlyphs; ++i) {
+ variants.append(staticTextItem->glyphs[i]);
+ variants.append(staticTextItem->glyphPositions[i].toPointF());
+ }
- QVariantList variants;
- variants << QVariant(staticTextItem->font) << QVariant::fromValue(staticText);
buffer->addCommand(QPaintBufferPrivate::Cmd_DrawStaticText, QVariant(variants));
}
@@ -1110,15 +1387,12 @@ void QPainterReplayer::setupTransform(QPainter *_painter)
painter->setTransform(m_world_matrix);
}
-void QPainterReplayer::draw(const QPaintBuffer &buffer, QPainter *_painter, int frame)
+void QPainterReplayer::processCommands(const QPaintBuffer &buffer, QPainter *p, int begin, int end)
{
d = buffer.d_ptr;
- setupTransform(_painter);
-
- int frameStart = (frame == 0) ? 0 : d->frames.at(frame-1);
- int frameEnd = (frame == d->frames.size()) ? d->commands.size() : d->frames.at(frame);
+ painter = p;
- for (int cmdIndex=frameStart; cmdIndex<frameEnd; ++cmdIndex) {
+ for (int cmdIndex = begin; cmdIndex < end; ++cmdIndex) {
const QPaintBufferCommand &cmd = d->commands.at(cmdIndex);
process(cmd);
}
@@ -1484,11 +1758,19 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd)
QVariantList variants(d->variants.at(cmd.offset).value<QVariantList>());
- QFont font(variants.at(0).value<QFont>());
- QStaticText text(variants.at(0).value<QStaticText>());
-
+ QFont font = variants.at(0).value<QFont>();
+
+ QVector<quint32> glyphs;
+ QVector<QPointF> positions;
+
+ for (int i=0; i<(variants.size() - 1) / 2; ++i) {
+ glyphs.append(variants.at(i*2 + 1).toUInt());
+ positions.append(variants.at(i*2 + 2).toPointF());
+ }
+
painter->setFont(font);
- painter->drawStaticText(QPointF(0, 0), text);
+
+ qt_draw_glyphs(painter, glyphs.constData(), positions.constData(), glyphs.size());
break;
}
diff --git a/src/gui/painting/qpaintbuffer_p.h b/src/gui/painting/qpaintbuffer_p.h
index 0fde290..4576947 100644
--- a/src/gui/painting/qpaintbuffer_p.h
+++ b/src/gui/painting/qpaintbuffer_p.h
@@ -78,6 +78,12 @@ public:
int numFrames() const;
void draw(QPainter *painter, int frame = 0) const;
+
+ int frameStartIndex(int frame) const;
+ int frameEndIndex(int frame) const;
+ int processCommands(QPainter *painter, int begin, int end) const;
+ QString commandDescription(int command) const;
+
void setBoundingRect(const QRectF &rect);
QRectF boundingRect() const;
@@ -317,7 +323,7 @@ public:
void setupTransform(QPainter *painter);
virtual void process(const QPaintBufferCommand &cmd);
- void draw(const QPaintBuffer &buffer, QPainter *painter, int frame);
+ void processCommands(const QPaintBuffer &buffer, QPainter *painter, int begin, int end);
protected:
QPaintBufferPrivate *d;
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index a7c2a0b..03d0825 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -1725,9 +1725,10 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
if (patternLength > 0) {
int n = qFloor(dashOffset / patternLength);
dashOffset -= n * patternLength;
- while (dashOffset > pattern.at(dashIndex)) {
+ while (dashOffset >= pattern.at(dashIndex)) {
dashOffset -= pattern.at(dashIndex);
- dashIndex = (dashIndex + 1) % pattern.size();
+ if (++dashIndex >= pattern.size())
+ dashIndex = 0;
inDash = !inDash;
}
}
@@ -1738,7 +1739,6 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
const QLineF *lines = reinterpret_cast<const QLineF *>(path.points());
for (int i = 0; i < lineCount; ++i) {
- dashOffset = s->lastPen.dashOffset();
if (lines[i].p1() == lines[i].p2()) {
if (s->lastPen.capStyle() != Qt::FlatCap) {
QPointF p = lines[i].p1();
@@ -3390,7 +3390,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte
};
for(int i = 0; i < glyphs.size(); i++) {
- QFontEngineFT::Glyph *glyph = gset->glyph_data.value(glyphs[i]);
+ QFontEngineFT::Glyph *glyph = gset->getGlyph(glyphs[i]);
if (!glyph || glyph->format != neededFormat) {
if (!lockedFace)
@@ -3626,13 +3626,14 @@ void QRasterPaintEnginePrivate::rasterizeLine_dashed(QLineF line,
} else {
*dashOffset = 0;
*inDash = !(*inDash);
- *dashIndex = (*dashIndex + 1) % pattern.size();
+ if (++*dashIndex >= pattern.size())
+ *dashIndex = 0;
length -= dash;
l.setLength(dash);
line.setP1(l.p2());
}
- if (rasterize && dash != 0)
+ if (rasterize && dash > 0)
rasterizer->rasterizeLine(l.p1(), l.p2(), width / dash, squareCap);
}
}
diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
index 98762f0..990e3c4 100644
--- a/src/gui/painting/qpaintengineex.cpp
+++ b/src/gui/painting/qpaintengineex.cpp
@@ -607,11 +607,11 @@ void QPaintEngineEx::clip(const QRect &r, Qt::ClipOperation op)
{
qreal right = r.x() + r.width();
qreal bottom = r.y() + r.height();
- qreal pts[] = { r.x(), r.y(),
- right, r.y(),
+ qreal pts[] = { qreal(r.x()), qreal(r.y()),
+ right, qreal(r.y()),
right, bottom,
- r.x(), bottom,
- r.x(), r.y() };
+ qreal(r.x()), bottom,
+ qreal(r.x()), qreal(r.y()) };
QVectorPath vp(pts, 5, 0, QVectorPath::RectangleHint);
clip(vp, op);
}
@@ -711,11 +711,11 @@ void QPaintEngineEx::drawRects(const QRect *rects, int rectCount)
// ### Is there a one off here?
qreal right = r.x() + r.width();
qreal bottom = r.y() + r.height();
- qreal pts[] = { r.x(), r.y(),
- right, r.y(),
+ qreal pts[] = { qreal(r.x()), qreal(r.y()),
+ right, qreal(r.y()),
right, bottom,
- r.x(), bottom,
- r.x(), r.y() };
+ qreal(r.x()), bottom,
+ qreal(r.x()), qreal(r.y()) };
QVectorPath vp(pts, 5, 0, QVectorPath::RectangleHint);
draw(vp);
}
@@ -903,7 +903,8 @@ void QPaintEngineEx::drawPoints(const QPoint *points, int pointCount)
}
} else {
for (int i=0; i<pointCount; ++i) {
- qreal pts[] = { points[i].x(), points[i].y(), points[i].x() +1/63., points[i].y() };
+ qreal pts[] = { qreal(points[i].x()), qreal(points[i].y()),
+ qreal(points[i].x() +1/63.), qreal(points[i].y()) };
QVectorPath path(pts, 2, 0);
stroke(path, pen);
}
@@ -970,8 +971,8 @@ void QPaintEngineEx::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, con
fill(path, brush);
}
-void QPaintEngineEx::drawPixmapFragments(const QPainter::Fragment *fragments, int fragmentCount,
- const QPixmap &pixmap, QPainter::FragmentHints /*hints*/)
+void QPaintEngineEx::drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount,
+ const QPixmap &pixmap, QPainter::PixmapFragmentHints /*hints*/)
{
qreal oldOpacity = state()->opacity;
QTransform oldTransform = state()->matrix;
diff --git a/src/gui/painting/qpaintengineex_p.h b/src/gui/painting/qpaintengineex_p.h
index 2401b94..6c654bd 100644
--- a/src/gui/painting/qpaintengineex_p.h
+++ b/src/gui/painting/qpaintengineex_p.h
@@ -197,7 +197,8 @@ public:
virtual void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s);
- virtual void drawPixmapFragments(const QPainter::Fragment *fragments, int fragmentCount, const QPixmap &pixmap, QFlags<QPainter::FragmentHint> hints);
+ virtual void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap,
+ QFlags<QPainter::PixmapFragmentHint> hints);
virtual void updateState(const QPaintEngineState &state);
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index dc96c17..898a996 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -5414,10 +5414,15 @@ void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
scale(w / sw, h / sh);
setBackgroundMode(Qt::TransparentMode);
setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform);
- QBrush brush(d->state->pen.color(), pm);
+ QBrush brush;
+
+ if (sw == pm.width() && sh == pm.height())
+ brush = QBrush(d->state->pen.color(), pm);
+ else
+ brush = QBrush(d->state->pen.color(), pm.copy(sx, sy, sw, sh));
+
setBrush(brush);
setPen(Qt::NoPen);
- setBrushOrigin(QPointF(-sx, -sy));
drawRect(QRectF(0, 0, sw, sh));
restore();
@@ -5715,6 +5720,16 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *posit
QFontEngine *fontEngine = state->font.d->engineForScript(QUnicodeTables::Common);
+ while (fontEngine->type() == QFontEngine::Multi) {
+ // Pick engine based on first glyph in array if we are using a multi engine.
+ // (all glyphs must be for same font)
+ int engineIdx = 0;
+ if (glyphCount > 0)
+ engineIdx = glyphArray[0] >> 24;
+
+ fontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx);
+ }
+
QVarLengthArray<QFixedPoint, 128> positions;
for (int i=0; i<glyphCount; ++i) {
QFixedPoint fp = QFixedPoint::fromPointF(positionArray[i]);
@@ -5757,19 +5772,24 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *posit
/*!
- \fn void QPainter::drawStaticText(const QPoint &position, const QStaticText &staticText)
-
+ \fn void QPainter::drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText)
\since 4.7
-
\overload
+
+ Draws the \a staticText at the \a topLeftPosition.
+
+ \note The y-position is used as the top of the font.
+
*/
/*!
- \fn void QPainter::drawStaticText(int x, int y, const QStaticText &staticText)
-
+ \fn void QPainter::drawStaticText(int left, int top, const QStaticText &staticText)
\since 4.7
-
\overload
+
+ Draws the \a staticText at coordinates \a left and \a top.
+
+ \note The y-position is used as the top of the font.
*/
/*!
@@ -5797,7 +5817,7 @@ void QPainter::drawText(const QPointF &p, const QString &str)
/*!
\since 4.7
- Draws the given \a staticText at the given \a position.
+ Draws the given \a staticText at the given \a topLeftPosition.
The text will be drawn using the font and the transformation set on the painter. If the
font and/or transformation set on the painter are different from the ones used to initialize
@@ -5805,15 +5825,17 @@ void QPainter::drawText(const QPointF &p, const QString &str)
QStaticText::prepare() to initialize \a staticText with the font and transformation with which
it will later be drawn.
- If \a position is not the same as when \a staticText was initialized, or when it was last drawn,
- then there will be a slight overhead when translating the text to its new position.
+ If \a topLeftPosition is not the same as when \a staticText was initialized, or when it was
+ last drawn, then there will be a slight overhead when translating the text to its new position.
+
+ \note If the painter's transformation is not affine, then \a staticText will be drawn using
+ regular calls to drawText(), losing any potential for performance improvement.
- \note If the painter's transformation is not affine, then \a staticText will be drawn using regular
- calls to drawText(), losing any potential performance improvement.
+ \note The y-position is used as the top of the font.
\sa QStaticText
*/
-void QPainter::drawStaticText(const QPointF &position, const QStaticText &staticText)
+void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText)
{
Q_D(QPainter);
if (!d->engine || staticText.text().isEmpty() || pen().style() == Qt::NoPen)
@@ -5822,16 +5844,21 @@ void QPainter::drawStaticText(const QPointF &position, const QStaticText &static
QStaticTextPrivate *staticText_d =
const_cast<QStaticTextPrivate *>(QStaticTextPrivate::get(&staticText));
+ if (font() != staticText_d->font) {
+ staticText_d->font = font();
+ staticText_d->needsRelayout = true;
+ }
+
// If we don't have an extended paint engine, or if the painter is projected,
// we go through standard code path
if (d->extended == 0 || !d->state->matrix.isAffine()) {
- staticText_d->paintText(position, this);
+ staticText_d->paintText(topLeftPosition, this);
return;
}
// Don't recalculate entire layout because of translation, rather add the dx and dy
// into the position to move each text item the correct distance.
- QPointF transformedPosition = position * d->state->matrix;
+ QPointF transformedPosition = topLeftPosition * d->state->matrix;
QTransform matrix = d->state->matrix;
// The translation has been applied to transformedPosition. Remove translation
@@ -5852,25 +5879,12 @@ void QPainter::drawStaticText(const QPointF &position, const QStaticText &static
// If the transform is not identical to the text transform,
// we have to relayout the text (for other transformations than plain translation)
- bool staticTextNeedsReinit = false;
+ bool staticTextNeedsReinit = staticText_d->needsRelayout;
if (staticText_d->matrix != d->state->matrix) {
staticText_d->matrix = d->state->matrix;
staticTextNeedsReinit = true;
}
- bool restoreWhenFinished = false;
- if (staticText_d->needsClipRect) {
- save();
- setClipRect(QRectF(position, staticText_d->maximumSize));
-
- restoreWhenFinished = true;
- }
-
- if (font() != staticText_d->font) {
- staticText_d->font = font();
- staticTextNeedsReinit = true;
- }
-
// Recreate the layout of the static text because the matrix or font has changed
if (staticTextNeedsReinit)
staticText_d->init();
@@ -5896,7 +5910,7 @@ void QPainter::drawStaticText(const QPointF &position, const QStaticText &static
QColor currentColor = oldPen.color();
for (int i=0; i<staticText_d->itemCount; ++i) {
QStaticTextItem *item = staticText_d->items + i;
- if (currentColor != item->color) {
+ if (item->color.isValid() && currentColor != item->color) {
setPen(item->color);
currentColor = item->color;
}
@@ -5905,9 +5919,6 @@ void QPainter::drawStaticText(const QPointF &position, const QStaticText &static
if (currentColor != oldPen.color())
setPen(oldPen);
- if (restoreWhenFinished)
- restore();
-
if (matrix.isTranslating())
d->state->matrix = matrix;
}
@@ -7994,10 +8005,11 @@ start_lengthVariant:
for (int i = 0; i < textLayout.lineCount(); i++) {
QTextLine line = textLayout.lineAt(i);
+ qreal advance = line.horizontalAdvance();
if (tf & Qt::AlignRight)
- xoff = r.width() - line.naturalTextWidth();
+ xoff = r.width() - advance;
else if (tf & Qt::AlignHCenter)
- xoff = (r.width() - line.naturalTextWidth())/2;
+ xoff = (r.width() - advance)/2;
line.draw(painter, QPointF(r.x() + xoff + line.x(), r.y() + yoff));
}
@@ -8914,11 +8926,11 @@ QTransform QPainter::combinedTransform() const
This function is potentially faster than multiple calls to drawPixmap(),
since the backend can optimize state changes.
- \sa QPainter::Fragment, QPainter::FragmentHint
+ \sa QPainter::PixmapFragment, QPainter::PixmapFragmentHint
*/
-void QPainter::drawPixmapFragments(const Fragment *fragments, int fragmentCount,
- const QPixmap &pixmap, FragmentHints hints)
+void QPainter::drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount,
+ const QPixmap &pixmap, PixmapFragmentHints hints)
{
Q_D(QPainter);
@@ -8933,8 +8945,15 @@ void QPainter::drawPixmapFragments(const Fragment *fragments, int fragmentCount,
for (int i = 0; i < fragmentCount; ++i) {
QTransform transform = oldTransform;
- transform.translate(fragments[i].x, fragments[i].y);
- transform.rotate(fragments[i].rotation);
+ qreal xOffset = 0;
+ qreal yOffset = 0;
+ if (fragments[i].rotation == 0) {
+ xOffset = fragments[i].x;
+ yOffset = fragments[i].y;
+ } else {
+ transform.translate(fragments[i].x, fragments[i].y);
+ transform.rotate(fragments[i].rotation);
+ }
setOpacity(oldOpacity * fragments[i].opacity);
setTransform(transform);
@@ -8942,7 +8961,7 @@ void QPainter::drawPixmapFragments(const Fragment *fragments, int fragmentCount,
qreal h = fragments[i].scaleY * fragments[i].height;
QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
fragments[i].width, fragments[i].height);
- drawPixmap(QRectF(-0.5 * w, -0.5 * h, w, h), pixmap, sourceRect);
+ drawPixmap(QRectF(-0.5 * w + xOffset, -0.5 * h + yOffset, w, h), pixmap, sourceRect);
}
setOpacity(oldOpacity);
@@ -8952,7 +8971,7 @@ void QPainter::drawPixmapFragments(const Fragment *fragments, int fragmentCount,
/*!
\since 4.7
- \class QPainter::Fragment
+ \class QPainter::PixmapFragment
\brief This class is used in conjunction with the
QPainter::drawPixmapFragments() function to specify how a pixmap, or
@@ -8973,73 +8992,73 @@ void QPainter::drawPixmapFragments(const Fragment *fragments, int fragmentCount,
/*!
\since 4.7
- This is a convenience function that returns a QPainter::Fragment that is
+ This is a convenience function that returns a QPainter::PixmapFragment that is
initialized with the \a pos, \a sourceRect, \a scaleX, \a scaleY, \a
rotation, \a opacity parameters.
*/
-QPainter::Fragment QPainter::Fragment::create(const QPointF &pos, const QRectF &sourceRect,
+QPainter::PixmapFragment QPainter::PixmapFragment::create(const QPointF &pos, const QRectF &sourceRect,
qreal scaleX, qreal scaleY, qreal rotation,
qreal opacity)
{
- Fragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(),
- sourceRect.height(), scaleX, scaleY, rotation, opacity};
+ PixmapFragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(),
+ sourceRect.height(), scaleX, scaleY, rotation, opacity};
return fragment;
}
/*!
- \variable QPainter::Fragment::x
+ \variable QPainter::PixmapFragment::x
\brief the x coordinate of center point in the target rectangle.
*/
/*!
- \variable QPainter::Fragment::y
+ \variable QPainter::PixmapFragment::y
\brief the y coordinate of the center point in the target rectangle.
*/
/*!
- \variable QPainter::Fragment::sourceLeft
+ \variable QPainter::PixmapFragment::sourceLeft
\brief the left coordinate of the source rectangle.
*/
/*!
- \variable QPainter::Fragment::sourceTop
+ \variable QPainter::PixmapFragment::sourceTop
\brief the top coordinate of the source rectangle.
*/
/*!
- \variable QPainter::Fragment::width
+ \variable QPainter::PixmapFragment::width
\brief the width of the source rectangle and is used to calculate the width
of the target rectangle.
*/
/*!
- \variable QPainter::Fragment::height
+ \variable QPainter::PixmapFragment::height
\brief the height of the source rectangle and is used to calculate the
height of the target rectangle.
*/
/*!
- \variable QPainter::Fragment::scaleX
+ \variable QPainter::PixmapFragment::scaleX
\brief the horizontal scale of the target rectangle.
*/
/*!
- \variable QPainter::Fragment::scaleY
+ \variable QPainter::PixmapFragment::scaleY
\brief the vertical scale of the target rectangle.
*/
/*!
- \variable QPainter::Fragment::rotation
+ \variable QPainter::PixmapFragment::rotation
\brief the rotation of the target rectangle in degrees. The target
rectangle is rotated after it has been scaled.
*/
/*!
- \variable QPainter::Fragment::opacity
+ \variable QPainter::PixmapFragment::opacity
\brief the opacity of the target rectangle, where 0.0 is fully transparent
and 1.0 is fully opaque.
@@ -9048,12 +9067,12 @@ QPainter::Fragment QPainter::Fragment::create(const QPointF &pos, const QRectF &
/*!
\since 4.7
- \enum QPainter::FragmentHint
+ \enum QPainter::PixmapFragmentHint
\value OpaqueHint Indicates that the pixmap fragments to be drawn are
opaque. Opaque fragments are potentially faster to draw.
- \sa QPainter::drawPixmapFragments(), QPainter::Fragment
+ \sa QPainter::drawPixmapFragments(), QPainter::PixmapFragment
*/
void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation)
diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h
index bcb0b50..edfb67e 100644
--- a/src/gui/painting/qpainter.h
+++ b/src/gui/painting/qpainter.h
@@ -99,7 +99,7 @@ public:
Q_DECLARE_FLAGS(RenderHints, RenderHint)
- class Fragment {
+ class PixmapFragment {
public:
qreal x;
qreal y;
@@ -111,16 +111,16 @@ public:
qreal scaleY;
qreal rotation;
qreal opacity;
- static Fragment Q_GUI_EXPORT create(const QPointF &pos, const QRectF &sourceRect,
+ static PixmapFragment Q_GUI_EXPORT create(const QPointF &pos, const QRectF &sourceRect,
qreal scaleX = 1, qreal scaleY = 1,
qreal rotation = 0, qreal opacity = 1);
};
- enum FragmentHint {
+ enum PixmapFragmentHint {
OpaqueHint = 0x01
};
- Q_DECLARE_FLAGS(FragmentHints, FragmentHint)
+ Q_DECLARE_FLAGS(PixmapFragmentHints, PixmapFragmentHint)
QPainter();
explicit QPainter(QPaintDevice *);
@@ -375,8 +375,8 @@ public:
inline void drawPixmap(const QRect &r, const QPixmap &pm);
inline void drawPixmap(int x, int y, int w, int h, const QPixmap &pm);
- void drawPixmapFragments(const Fragment *fragments, int fragmentCount,
- const QPixmap &pixmap, FragmentHints hints = 0);
+ void drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount,
+ const QPixmap &pixmap, PixmapFragmentHints hints = 0);
void drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect,
Qt::ImageConversionFlags flags = Qt::AutoColor);
@@ -396,9 +396,9 @@ public:
void setLayoutDirection(Qt::LayoutDirection direction);
Qt::LayoutDirection layoutDirection() const;
- void drawStaticText(const QPointF &p, const QStaticText &staticText);
- inline void drawStaticText(const QPoint &p, const QStaticText &staticText);
- inline void drawStaticText(int x, int y, const QStaticText &staticText);
+ void drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText);
+ inline void drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText);
+ inline void drawStaticText(int left, int top, const QStaticText &staticText);
void drawText(const QPointF &p, const QString &s);
inline void drawText(const QPoint &p, const QString &s);
diff --git a/src/gui/painting/qpainterpath.h b/src/gui/painting/qpainterpath.h
index 296ce33..15d83b8 100644
--- a/src/gui/painting/qpainterpath.h
+++ b/src/gui/painting/qpainterpath.h
@@ -288,6 +288,8 @@ public:
QPainterPath createStroke(const QPainterPath &path) const;
private:
+ Q_DISABLE_COPY(QPainterPathStroker)
+
friend class QX11PaintEngine;
QScopedPointer<QPainterPathStrokerPrivate> d_ptr;
diff --git a/src/gui/painting/qprinter.cpp b/src/gui/painting/qprinter.cpp
index edf224d..ae21416 100644
--- a/src/gui/painting/qprinter.cpp
+++ b/src/gui/painting/qprinter.cpp
@@ -382,6 +382,7 @@ void QPrinterPrivate::addToManualSetList(QPrintEngine::PrintEnginePropertyKey ke
\value AllPages All pages should be printed.
\value Selection Only the selection should be printed.
\value PageRange The specified page range should be printed.
+ \value CurrentPage Only the current page should be printed.
\sa QAbstractPrintDialog::PrintRange
*/
@@ -571,6 +572,7 @@ void QPrinterPrivate::addToManualSetList(QPrintEngine::PrintEnginePropertyKey ke
\value AllPages All the pages should be printed.
\value Selection Only the selection should be printed.
\value PageRange Print according to the from page and to page options.
+ \value CurrentPage Only the current page should be printed.
\sa setPrintRange(), printRange()
*/
@@ -586,6 +588,7 @@ void QPrinterPrivate::addToManualSetList(QPrintEngine::PrintEnginePropertyKey ke
\value PrintSelection Describes if printing selections should be enabled.
\value PrintPageRange Describes if printing page ranges (from, to) should
be enabled
+ \value PrintCurrentPage if Print Current Page option should be enabled
\sa setOptionEnabled(), isOptionEnabled()
*/
diff --git a/src/gui/painting/qprinter.h b/src/gui/painting/qprinter.h
index 6636179..996a954 100644
--- a/src/gui/painting/qprinter.h
+++ b/src/gui/painting/qprinter.h
@@ -124,7 +124,7 @@ public:
enum OutputFormat { NativeFormat, PdfFormat, PostScriptFormat };
// ### Qt 5: Merge with QAbstractPrintDialog::PrintRange
- enum PrintRange { AllPages, Selection, PageRange };
+ enum PrintRange { AllPages, Selection, PageRange, CurrentPage };
enum Unit {
Millimeter,
diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp
index 614d2c0..bfeef72 100644
--- a/src/gui/painting/qregion.cpp
+++ b/src/gui/painting/qregion.cpp
@@ -704,28 +704,13 @@ bool QRegion::intersects(const QRegion &region) const
}
/*!
+ \fn bool QRegion::intersects(const QRect &rect) const
\since 4.2
Returns true if this region intersects with \a rect, otherwise
returns false.
*/
-bool QRegion::intersects(const QRect &rect) const
-{
- if (isEmpty() || rect.isNull())
- return false;
- const QRect r = rect.normalized();
- if (!rect_intersects(boundingRect(), r))
- return false;
- if (rectCount() == 1)
- return true;
-
- const QVector<QRect> myRects = rects();
- for (QVector<QRect>::const_iterator it = myRects.constBegin(); it < myRects.constEnd(); ++it)
- if (rect_intersects(r, *it))
- return true;
- return false;
-}
#if !defined (Q_OS_UNIX) && !defined (Q_WS_WIN)
/*!
@@ -3134,8 +3119,8 @@ SOFTWARE.
************************************************************************/
/* $XFree86: xc/lib/X11/PolyReg.c,v 1.1.1.2.8.2 1998/10/04 15:22:49 hohndel Exp $ */
-#define LARGE_COORDINATE 1000000
-#define SMALL_COORDINATE -LARGE_COORDINATE
+#define LARGE_COORDINATE INT_MAX
+#define SMALL_COORDINATE INT_MIN
/*
* InsertEdgeInET
@@ -4349,5 +4334,24 @@ bool QRegion::operator==(const QRegion &r) const
return EqualRegion(d->qt_rgn, r.d->qt_rgn);
}
+bool QRegion::intersects(const QRect &rect) const
+{
+ if (isEmptyHelper(d->qt_rgn) || rect.isNull())
+ return false;
+
+ const QRect r = rect.normalized();
+ if (!rect_intersects(d->qt_rgn->extents, r))
+ return false;
+ if (d->qt_rgn->numRects == 1)
+ return true;
+
+ const QVector<QRect> myRects = rects();
+ for (QVector<QRect>::const_iterator it = myRects.constBegin(); it < myRects.constEnd(); ++it)
+ if (rect_intersects(r, *it))
+ return true;
+ return false;
+}
+
+
#endif
QT_END_NAMESPACE
diff --git a/src/gui/painting/qstroker.cpp b/src/gui/painting/qstroker.cpp
index 16e3c38..9740fce 100644
--- a/src/gui/painting/qstroker.cpp
+++ b/src/gui/painting/qstroker.cpp
@@ -1043,6 +1043,47 @@ QVector<qfixed> QDashStroker::patternForStyle(Qt::PenStyle style)
return pattern;
}
+static inline bool lineRectIntersectsRect(qfixed2d p1, qfixed2d p2, const qfixed2d &tl, const qfixed2d &br)
+{
+ return ((p1.x > tl.x || p2.x > tl.x) && (p1.x < br.x || p2.x < br.x)
+ && (p1.y > tl.y || p2.y > tl.y) && (p1.y < br.y || p2.y < br.y));
+}
+
+// If the line intersects the rectangle, this function will return true.
+static bool lineIntersectsRect(qfixed2d p1, qfixed2d p2, const qfixed2d &tl, const qfixed2d &br)
+{
+ if (!lineRectIntersectsRect(p1, p2, tl, br))
+ return false;
+ if (p1.x == p2.x || p1.y == p2.y)
+ return true;
+
+ if (p1.y > p2.y)
+ qSwap(p1, p2); // make p1 above p2
+ qfixed2d u;
+ qfixed2d v;
+ qfixed2d w = {p2.x - p1.x, p2.y - p1.y};
+ if (p1.x < p2.x) {
+ // backslash
+ u.x = tl.x - p1.x; u.y = br.y - p1.y;
+ v.x = br.x - p1.x; v.y = tl.y - p1.y;
+ } else {
+ // slash
+ u.x = tl.x - p1.x; u.y = tl.y - p1.y;
+ v.x = br.x - p1.x; v.y = br.y - p1.y;
+ }
+#if defined(QFIXED_IS_26_6) || defined(QFIXED_IS_16_16)
+ qint64 val1 = qint64(u.x) * qint64(w.y) - qint64(u.y) * qint64(w.x);
+ qint64 val2 = qint64(v.x) * qint64(w.y) - qint64(v.y) * qint64(w.x);
+ return (val1 < 0 && val2 > 0) || (val1 > 0 && val2 < 0);
+#elif defined(QFIXED_IS_32_32)
+ // Cannot do proper test because it may overflow.
+ return true;
+#else
+ qreal val1 = u.x * w.y - u.y * w.x;
+ qreal val2 = v.x * w.y - v.y * w.x;
+ return (val1 < 0 && val2 > 0) || (val1 > 0 && val2 < 0);
+#endif
+}
void QDashStroker::processCurrentSubpath()
{
@@ -1067,9 +1108,11 @@ void QDashStroker::processCurrentSubpath()
if (qFuzzyIsNull(sumLength))
return;
+ qreal invSumLength = qreal(1) / sumLength;
+
Q_ASSERT(dashCount > 0);
- dashCount = (dashCount / 2) * 2; // Round down to even number
+ dashCount = dashCount & -2; // Round down to even number
int idash = 0; // Index to current dash
qreal pos = 0; // The position on the curve, 0 <= pos <= path.length
@@ -1077,11 +1120,12 @@ void QDashStroker::processCurrentSubpath()
qreal doffset = m_dashOffset * m_stroke_width;
// make sure doffset is in range [0..sumLength)
- doffset -= qFloor(doffset / sumLength) * sumLength;
+ doffset -= qFloor(doffset * invSumLength) * sumLength;
while (doffset >= dashes[idash]) {
doffset -= dashes[idash];
- idash = (idash + 1) % dashCount;
+ if (++idash >= dashCount)
+ idash = 0;
}
qreal estart = 0; // The elements starting position
@@ -1119,12 +1163,41 @@ void QDashStroker::processCurrentSubpath()
estop = estart + elen;
bool done = pos >= estop;
+
+ if (clipping) {
+ // Check if the entire line can be clipped away.
+ if (!lineIntersectsRect(prev, e, clip_tl, clip_br)) {
+ // Cut away full dash sequences.
+ elen -= qFloor(elen * invSumLength) * sumLength;
+ // Update dash offset.
+ while (!done) {
+ qreal dpos = pos + dashes[idash] - doffset - estart;
+
+ Q_ASSERT(dpos >= 0);
+
+ if (dpos > elen) { // dash extends this line
+ doffset = dashes[idash] - (dpos - elen); // subtract the part already used
+ pos = estop; // move pos to next path element
+ done = true;
+ } else { // Dash is on this line
+ pos = dpos + estart;
+ done = pos >= estop;
+ if (++idash >= dashCount)
+ idash = 0;
+ doffset = 0; // full segment so no offset on next.
+ }
+ }
+ hasMoveTo = false;
+ move_to_pos = e;
+ }
+ }
+
// Dash away...
while (!done) {
QPointF p2;
- int idash_incr = 0;
bool has_offset = doffset > 0;
+ bool evenDash = (idash & 1) == 0;
qreal dpos = pos + dashes[idash] - doffset - estart;
Q_ASSERT(dpos >= 0);
@@ -1138,39 +1211,36 @@ void QDashStroker::processCurrentSubpath()
p2 = cline.pointAt(dpos/elen);
pos = dpos + estart;
done = pos >= estop;
- idash_incr = 1;
+ if (++idash >= dashCount)
+ idash = 0;
doffset = 0; // full segment so no offset on next.
}
- if (idash % 2 == 0) {
+ if (evenDash) {
line_to_pos.x = qt_real_to_fixed(p2.x());
line_to_pos.y = qt_real_to_fixed(p2.y());
- // If we have an offset, we're continuing a dash
- // from a previous element and should only
- // continue the current dash, without starting a
- // new subpath.
- if (!has_offset || !hasMoveTo) {
- emitMoveTo(move_to_pos.x, move_to_pos.y);
- hasMoveTo = true;
- }
-
if (!clipping
- // if move_to is inside...
- || (move_to_pos.x > clip_tl.x && move_to_pos.x < clip_br.x
- && move_to_pos.y > clip_tl.y && move_to_pos.y < clip_br.y)
- // Or if line_to is inside...
- || (line_to_pos.x > clip_tl.x && line_to_pos.x < clip_br.x
- && line_to_pos.y > clip_tl.y && line_to_pos.y < clip_br.y))
+ || lineRectIntersectsRect(move_to_pos, line_to_pos, clip_tl, clip_br))
{
+ // If we have an offset, we're continuing a dash
+ // from a previous element and should only
+ // continue the current dash, without starting a
+ // new subpath.
+ if (!has_offset || !hasMoveTo) {
+ emitMoveTo(move_to_pos.x, move_to_pos.y);
+ hasMoveTo = true;
+ }
+
emitLineTo(line_to_pos.x, line_to_pos.y);
+ } else {
+ hasMoveTo = false;
}
+ move_to_pos = line_to_pos;
} else {
move_to_pos.x = qt_real_to_fixed(p2.x());
move_to_pos.y = qt_real_to_fixed(p2.y());
}
-
- idash = (idash + idash_incr) % dashCount;
}
// Shuffle to the next cycle...
diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp
index cf3957b..9eda0ef 100644
--- a/src/gui/painting/qtextureglyphcache.cpp
+++ b/src/gui/painting/qtextureglyphcache.cpp
@@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE
// returns the highest number closest to v, which is a power of 2
// NB! assumes 32 bit ints
-int qt_next_power_of_two(int v)
+static inline int qt_next_power_of_two(int v)
{
v--;
v |= v >> 1;
@@ -73,7 +73,7 @@ void QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const
const QFixedPoint *)
{
#ifdef CACHE_DEBUG
- printf("Populating with '%s'\n", QString::fromRawData(ti.chars, ti.num_chars).toLatin1().data());
+ printf("Populating with %d glyphs\n", numGlyphs);
qDebug() << " -> current transformation: " << m_transform;
#endif
@@ -93,17 +93,14 @@ void QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const
glyph_metrics_t metrics = fontEngine->boundingBox(glyph, m_transform);
#ifdef CACHE_DEBUG
- printf("'%c' (%4x): w=%.2f, h=%.2f, xoff=%.2f, yoff=%.2f, x=%.2f, y=%.2f, ti.ascent=%.2f, ti.descent=%.2f\n",
- ti.chars[i].toLatin1(),
+ printf("(%4x): w=%.2f, h=%.2f, xoff=%.2f, yoff=%.2f, x=%.2f, y=%.2f\n",
glyph,
metrics.width.toReal(),
metrics.height.toReal(),
metrics.xoff.toReal(),
metrics.yoff.toReal(),
metrics.x.toReal(),
- metrics.y.toReal(),
- ti.ascent.toReal(),
- ti.descent.toReal());
+ metrics.y.toReal());
#endif
int glyph_width = metrics.width.ceil().toInt();
int glyph_height = metrics.height.ceil().toInt();
@@ -136,10 +133,13 @@ void QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const
while (iter != listItemCoordinates.end()) {
Coord c = iter.value();
+ m_currentRowHeight = qMax(m_currentRowHeight, c.h + margin * 2);
+
if (m_cx + c.w > m_w) {
// no room on the current line, start new glyph strip
m_cx = 0;
- m_cy = m_h;
+ m_cy += m_currentRowHeight;
+ m_currentRowHeight = 0; // New row
}
if (m_cy + c.h > m_h) {
int new_height = m_h*2;
@@ -156,14 +156,7 @@ void QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const
fillTexture(c, iter.key());
coords.insert(iter.key(), c);
- if (m_cx + c.w > m_w) {
- m_cx = 0;
- m_cy += rowHeight;
- } else {
- // for the Mono case, glyph_width is 8-bit aligned,
- // and therefore so will m_cx
- m_cx += c.w;
- }
+ m_cx += c.w;
++iter;
}
@@ -195,7 +188,7 @@ QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g) const
QFontEngineFT::QGlyphSet *gset = ft->loadTransformedGlyphSet(m_transform);
if (gset && ft->loadGlyphs(gset, &g, 1, format)) {
- QFontEngineFT::Glyph *glyph = gset->glyph_data.value(g);
+ QFontEngineFT::Glyph *glyph = gset->getGlyph(g);
const int bytesPerLine = (format == QFontEngineFT::Format_Mono ? ((glyph->width + 31) & ~31) >> 3
: (glyph->width + 3) & ~3);
return QImage(glyph->data, glyph->width, glyph->height, bytesPerLine, imageFormat);
@@ -333,10 +326,7 @@ void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g)
QPoint base(c.x + glyphMargin(), c.y + glyphMargin() + c.baseLineY-1);
if (m_image.rect().contains(base))
m_image.setPixel(base, 255);
- m_image.save(QString::fromLatin1("cache-%1-%2-%3.png")
- .arg(m_current_textitem->font().family())
- .arg(m_current_textitem->font().pointSize())
- .arg(m_transform.type()));
+ m_image.save(QString::fromLatin1("cache-%1.png").arg(int(this)));
#endif
}
diff --git a/src/gui/painting/qtextureglyphcache_p.h b/src/gui/painting/qtextureglyphcache_p.h
index 803e71b..8c2f5b4 100644
--- a/src/gui/painting/qtextureglyphcache_p.h
+++ b/src/gui/painting/qtextureglyphcache_p.h
@@ -77,7 +77,7 @@ class Q_GUI_EXPORT QTextureGlyphCache : public QFontEngineGlyphCache
public:
QTextureGlyphCache(QFontEngineGlyphCache::Type type, const QTransform &matrix)
: QFontEngineGlyphCache(matrix, type), m_current_fontengine(0),
- m_w(0), m_h(0), m_cx(0), m_cy(0)
+ m_w(0), m_h(0), m_cx(0), m_cy(0), m_currentRowHeight(0)
{ }
virtual ~QTextureGlyphCache() { }
@@ -120,6 +120,7 @@ protected:
int m_h; // image height
int m_cx; // current x
int m_cy; // current y
+ int m_currentRowHeight; // Height of last row
};
diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp
index 4f42a58..988d678 100644
--- a/src/gui/painting/qtransform.cpp
+++ b/src/gui/painting/qtransform.cpp
@@ -1037,8 +1037,18 @@ QDataStream & operator>>(QDataStream &s, QTransform &t)
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QTransform &m)
{
- dbg.nospace() << "QTransform("
- << "11=" << m.m11()
+ static const char *typeStr[] =
+ {
+ "TxNone",
+ "TxTranslate",
+ "TxScale",
+ "TxRotate",
+ "TxShear",
+ "TxProject"
+ };
+
+ dbg.nospace() << "QTransform(type=" << typeStr[m.type()] << ','
+ << " 11=" << m.m11()
<< " 12=" << m.m12()
<< " 13=" << m.m13()
<< " 21=" << m.m21()
@@ -1048,6 +1058,7 @@ QDebug operator<<(QDebug dbg, const QTransform &m)
<< " 32=" << m.m32()
<< " 33=" << m.m33()
<< ')';
+
return dbg.space();
}
#endif
diff --git a/src/gui/painting/qtransform.h b/src/gui/painting/qtransform.h
index 9909643..212a582 100644
--- a/src/gui/painting/qtransform.h
+++ b/src/gui/painting/qtransform.h
@@ -293,7 +293,8 @@ inline QTransform &QTransform::operator*=(qreal num)
affine._dx *= num;
affine._dy *= num;
m_33 *= num;
- m_dirty |= TxScale;
+ if (m_dirty < TxScale)
+ m_dirty = TxScale;
return *this;
}
inline QTransform &QTransform::operator/=(qreal div)
@@ -316,7 +317,7 @@ inline QTransform &QTransform::operator+=(qreal num)
affine._dx += num;
affine._dy += num;
m_33 += num;
- m_dirty |= TxProject;
+ m_dirty = TxProject;
return *this;
}
inline QTransform &QTransform::operator-=(qreal num)
@@ -332,7 +333,7 @@ inline QTransform &QTransform::operator-=(qreal num)
affine._dx -= num;
affine._dy -= num;
m_33 -= num;
- m_dirty |= TxProject;
+ m_dirty = TxProject;
return *this;
}
diff --git a/src/gui/painting/qwindowsurface_qws.cpp b/src/gui/painting/qwindowsurface_qws.cpp
index d3fc9de..a816ed2 100644
--- a/src/gui/painting/qwindowsurface_qws.cpp
+++ b/src/gui/painting/qwindowsurface_qws.cpp
@@ -80,7 +80,7 @@ static void qt_insertWindowSurface(int winId, QWSWindowSurface *surface)
inline bool isWidgetOpaque(const QWidget *w)
{
- return w->d_func()->isOpaque;
+ return w->d_func()->isOpaque && !w->testAttribute(Qt::WA_TranslucentBackground);
}
static inline QScreen *getScreen(const QWidget *w)
@@ -873,6 +873,21 @@ bool QWSMemorySurface::isValid() const
return true;
}
+// ### copied from qwindowsurface_raster.cpp -- should be cross-platform
+void QWSMemorySurface::beginPaint(const QRegion &rgn)
+{
+ if (!isWidgetOpaque(window())) {
+ QPainter p(&img);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ const QVector<QRect> rects = rgn.rects();
+ const QColor blank = Qt::transparent;
+ for (QVector<QRect>::const_iterator it = rects.begin(); it != rects.end(); ++it) {
+ p.fillRect(*it, blank);
+ }
+ }
+ QWSWindowSurface::beginPaint(rgn);
+}
+
// from qwindowsurface.cpp
extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
diff --git a/src/gui/painting/qwindowsurface_qws_p.h b/src/gui/painting/qwindowsurface_qws_p.h
index a8371c8..30900dc 100644
--- a/src/gui/painting/qwindowsurface_qws_p.h
+++ b/src/gui/painting/qwindowsurface_qws_p.h
@@ -176,6 +176,8 @@ public:
QImage image() const { return img; }
QPoint painterOffset() const;
+ void beginPaint(const QRegion &rgn);
+
bool lock(int timeout = -1);
void unlock();
diff --git a/src/gui/painting/qwindowsurface_s60.cpp b/src/gui/painting/qwindowsurface_s60.cpp
index 028ec48..b25dce5 100644
--- a/src/gui/painting/qwindowsurface_s60.cpp
+++ b/src/gui/painting/qwindowsurface_s60.cpp
@@ -44,8 +44,8 @@
#include <QtGui/qpaintdevice.h>
#include <private/qwidget_p.h>
#include "qwindowsurface_s60_p.h"
-#include "qpixmap_s60_p.h"
-#include "qt_s60_p.h"
+#include <private/qpixmap_s60_p.h>
+#include <private/qt_s60_p.h>
#include "private/qdrawhelper_p.h"
QT_BEGIN_NAMESPACE
@@ -70,13 +70,13 @@ QS60WindowSurface::QS60WindowSurface(QWidget* widget)
// We create empty CFbsBitmap here -> it will be resized in setGeometry
CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap); // CBase derived object needs check on new
qt_symbian_throwIfError( bitmap->Create( TSize(0, 0), mode ) );
-
+
QS60PixmapData *data = new QS60PixmapData(QPixmapData::PixmapType);
if (data) {
data->fromSymbianBitmap(bitmap, true);
d_ptr->device = QPixmap(data);
}
-
+
setStaticContentsSupport(true);
}
QS60WindowSurface::~QS60WindowSurface()
@@ -89,24 +89,15 @@ void QS60WindowSurface::beginPaint(const QRegion &rgn)
if (!qt_widget_private(window())->isOpaque) {
QS60PixmapData *pixmapData = static_cast<QS60PixmapData *>(d_ptr->device.data_ptr().data());
pixmapData->beginDataAccess();
- QImage &image = pixmapData->image;
- QRgb *data = reinterpret_cast<QRgb *>(image.bits());
- const int row_stride = image.bytesPerLine() / 4;
+ QPainter p(&pixmapData->image);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
const QVector<QRect> rects = rgn.rects();
+ const QColor blank = Qt::transparent;
for (QVector<QRect>::const_iterator it = rects.begin(); it != rects.end(); ++it) {
- const int x_start = it->x();
- const int width = it->width();
-
- const int y_start = it->y();
- const int height = it->height();
-
- QRgb *row = data + row_stride * y_start;
- for (int y = 0; y < height; ++y) {
- qt_memfill(row + x_start, 0U, width);
- row += row_stride;
- }
+ p.fillRect(*it, blank);
}
+
pixmapData->endDataAccess();
}
}
@@ -128,7 +119,7 @@ QImage* QS60WindowSurface::buffer(const QWidget *widget)
const QPoint off = offset(widget);
QImage *img = &(static_cast<QS60PixmapData *>(d_ptr->device.data_ptr().data())->image);
-
+
QRect rect(off, widget->size());
rect &= QRect(QPoint(), img->size());
diff --git a/src/gui/s60framework/qs60mainapplication.cpp b/src/gui/s60framework/qs60mainapplication.cpp
index 2a7c4aa..41ac1a8 100644
--- a/src/gui/s60framework/qs60mainapplication.cpp
+++ b/src/gui/s60framework/qs60mainapplication.cpp
@@ -41,6 +41,7 @@
// INCLUDE FILES
#include <exception>
+#include <private/qcore_symbian_p.h>
#include "qs60maindocument.h"
#include "qs60mainapplication_p.h"
#include "qs60mainapplication.h"
@@ -57,17 +58,17 @@ CApaApplication *newS60Application()
return new QS60MainApplication;
}
-_LIT(KQtWrapperResourceFile, "\\resource\\apps\\s60main.rsc");
+_LIT(KQtWrapperResourceFile, "\\resource\\apps\\s60main" QT_LIBINFIX_UNICODE L".rsc");
/*!
\class QS60MainApplication
\since 4.6
\brief The QS60MainApplication class provides support for migration from S60.
-
+
\warning This class is provided only to get access to S60 specific
functionality in the application framework classes. It is not
portable. We strongly recommend against using it in new applications.
-
+
The QS60MainApplication provides a helper class for use in migrating
from existing S60 based applications to Qt based applications. It is
used in the exact same way as the \c CAknApplication class from
diff --git a/src/gui/s60framework/qs60mainappui.cpp b/src/gui/s60framework/qs60mainappui.cpp
index 012985b..3b5b9d3 100644
--- a/src/gui/s60framework/qs60mainappui.cpp
+++ b/src/gui/s60framework/qs60mainappui.cpp
@@ -45,7 +45,15 @@
#include <eikmenub.h>
#include <eikmenup.h>
#include <barsread.h>
-#include <s60main.rsg>
+#include <qconfig.h>
+#if defined(QT_LIBINFIX_UNQUOTED)
+// Two level macro needed for proper expansion of libinfix
+# define QT_S60MAIN_RSG_2(x) <s60main##x##.rsg>
+# define QT_S60MAIN_RSG(x) QT_S60MAIN_RSG_2(x)
+# include QT_S60MAIN_RSG(QT_LIBINFIX_UNQUOTED)
+#else
+# include <s60main.rsg>
+#endif
#include <avkon.rsg>
#include "qs60mainappui.h"
diff --git a/src/gui/s60framework/qs60maindocument.h b/src/gui/s60framework/qs60maindocument.h
index 438b80c..553675f 100644
--- a/src/gui/s60framework/qs60maindocument.h
+++ b/src/gui/s60framework/qs60maindocument.h
@@ -46,7 +46,7 @@
#ifdef Q_WS_S60
-#include <akndoc.h>
+#include <AknDoc.h>
class CEikApplication;
diff --git a/src/gui/s60framework/s60framework.pri b/src/gui/s60framework/s60framework.pri
index 5884b68..f9d89dc 100644
--- a/src/gui/s60framework/s60framework.pri
+++ b/src/gui/s60framework/s60framework.pri
@@ -4,11 +4,14 @@
minimalAppResource31 = \
"SOURCEPATH s60framework" \
"START RESOURCE s60main.rss" \
+ "TARGET s60main$${QT_LIBINFIX}" \
"HEADER" \
- "TARGETPATH resource\apps" \
+ "TARGETPATH /resource/apps" \
"END"
MMP_RULES += minimalAppResource31
+SYMBIAN_RESOURCES += s60framework/s60main.rss
+
SOURCES += s60framework/qs60mainapplication.cpp \
s60framework/qs60mainappui.cpp \
s60framework/qs60maindocument.cpp
@@ -17,3 +20,5 @@ HEADERS += s60framework/qs60mainapplication_p.h \
s60framework/qs60mainapplication.h \
s60framework/qs60mainappui.h \
s60framework/qs60maindocument.h
+
+!isEmpty(QT_LIBINFIX): DEFINES += QT_LIBINFIX_UNQUOTED=$$QT_LIBINFIX \ No newline at end of file
diff --git a/src/gui/styles/qcommonstyle.cpp b/src/gui/styles/qcommonstyle.cpp
index f8464cc..b0e2d37 100644
--- a/src/gui/styles/qcommonstyle.cpp
+++ b/src/gui/styles/qcommonstyle.cpp
@@ -4760,7 +4760,7 @@ QSize QCommonStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
int margins = 0;
// we add 4 pixels for label margins
- if (btn->icon.isNull() || !btn->text.isEmpty())
+ if (!btn->icon.isNull() || !btn->text.isEmpty())
margins = 4 + proxy()->pixelMetric(isRadio ? PM_RadioButtonLabelSpacing
: PM_CheckBoxLabelSpacing, opt, widget);
sz += QSize(w + margins, 4);
diff --git a/src/gui/styles/qgtkpainter.cpp b/src/gui/styles/qgtkpainter.cpp
index 6cc7455..1f68f2f 100644
--- a/src/gui/styles/qgtkpainter.cpp
+++ b/src/gui/styles/qgtkpainter.cpp
@@ -142,7 +142,7 @@ QPixmap QGtkPainter::renderTheme(uchar *bdata, uchar *wdata, const QRect &rect)
}
QGtkPainter::QGtkPainter(QPainter *_painter)
- : m_window(QGtkStylePrivate::gtkWidget(QLatin1String("GtkWindow")))
+ : m_window(QGtkStylePrivate::gtkWidget("GtkWindow"))
, m_painter(_painter)
, m_alpha(true)
, m_hflipped(false)
diff --git a/src/gui/styles/qgtkstyle.cpp b/src/gui/styles/qgtkstyle.cpp
index b5f052b..9c61023 100644
--- a/src/gui/styles/qgtkstyle.cpp
+++ b/src/gui/styles/qgtkstyle.cpp
@@ -222,7 +222,7 @@ QPalette QGtkStyle::standardPalette() const
QPalette palette = QCleanlooksStyle::standardPalette();
if (d->isThemeAvailable()) {
GtkStyle *style = d->gtkStyle();
- GtkWidget *gtkButton = d->gtkWidget(QLS("GtkButton"));
+ GtkWidget *gtkButton = d->gtkWidget("GtkButton");
GtkWidget *gtkEntry = d->getTextColorWidget();
GdkColor gdkBg, gdkBase, gdkText, gdkForeground, gdkSbg, gdkSfg;
@@ -253,7 +253,7 @@ QPalette QGtkStyle::standardPalette() const
palette.setColor(QPalette::Base, base);
QColor alternateRowColor = palette.base().color().lighter(93); // ref gtkstyle.c draw_flat_box
- GtkWidget *gtkTreeView = d->gtkWidget(QLS("GtkTreeView"));
+ GtkWidget *gtkTreeView = d->gtkWidget("GtkTreeView");
GdkColor *gtkAltBase = NULL;
d->gtk_widget_style_get(gtkTreeView, "odd-row-color", &gtkAltBase, NULL);
if (gtkAltBase) {
@@ -421,14 +421,14 @@ int QGtkStyle::pixelMetric(PixelMetric metric,
return 0;
case PM_ButtonShiftHorizontal: {
- GtkWidget *gtkButton = d->gtkWidget(QLS("GtkButton"));
+ GtkWidget *gtkButton = d->gtkWidget("GtkButton");
guint horizontal_shift;
d->gtk_widget_style_get(gtkButton, "child-displacement-x", &horizontal_shift, NULL);
return horizontal_shift;
}
case PM_ButtonShiftVertical: {
- GtkWidget *gtkButton = d->gtkWidget(QLS("GtkButton"));
+ GtkWidget *gtkButton = d->gtkWidget("GtkButton");
guint vertical_shift;
d->gtk_widget_style_get(gtkButton, "child-displacement-y", &vertical_shift, NULL);
return vertical_shift;
@@ -438,7 +438,7 @@ int QGtkStyle::pixelMetric(PixelMetric metric,
return 0;
case PM_MenuPanelWidth: {
- GtkWidget *gtkMenu = d->gtkWidget(QLS("GtkMenu"));
+ GtkWidget *gtkMenu = d->gtkWidget("GtkMenu");
guint horizontal_padding = 0;
// horizontal-padding is used by Maemo to get thicker borders
if (!d->gtk_check_version(2, 10, 0))
@@ -495,7 +495,7 @@ int QGtkStyle::pixelMetric(PixelMetric metric,
case PM_SliderThickness:
case PM_SliderControlThickness: {
- GtkWidget *gtkScale = d->gtkWidget(QLS("GtkHScale"));
+ GtkWidget *gtkScale = d->gtkWidget("GtkHScale");
gint val;
d->gtk_widget_style_get(gtkScale, "slider-width", &val, NULL);
if (metric == PM_SliderControlThickness)
@@ -506,7 +506,7 @@ int QGtkStyle::pixelMetric(PixelMetric metric,
case PM_ScrollBarExtent: {
gint sliderLength;
gint trough_border;
- GtkWidget *hScrollbar = d->gtkWidget(QLS("GtkHScrollbar"));
+ GtkWidget *hScrollbar = d->gtkWidget("GtkHScrollbar");
d->gtk_widget_style_get(hScrollbar,
"trough-border", &trough_border,
"slider-width", &sliderLength,
@@ -519,34 +519,34 @@ int QGtkStyle::pixelMetric(PixelMetric metric,
case PM_SliderLength:
gint val;
- d->gtk_widget_style_get(d->gtkWidget(QLS("GtkHScale")), "slider-length", &val, NULL);
+ d->gtk_widget_style_get(d->gtkWidget("GtkHScale"), "slider-length", &val, NULL);
return val;
case PM_ExclusiveIndicatorWidth:
case PM_ExclusiveIndicatorHeight:
case PM_IndicatorWidth:
case PM_IndicatorHeight: {
- GtkWidget *gtkCheckButton = d->gtkWidget(QLS("GtkCheckButton"));
+ GtkWidget *gtkCheckButton = d->gtkWidget("GtkCheckButton");
gint size, spacing;
d->gtk_widget_style_get(gtkCheckButton, "indicator-spacing", &spacing, "indicator-size", &size, NULL);
return size + 2 * spacing;
}
case PM_MenuBarVMargin: {
- GtkWidget *gtkMenubar = d->gtkWidget(QLS("GtkMenuBar"));
+ GtkWidget *gtkMenubar = d->gtkWidget("GtkMenuBar");
return qMax(0, gtkMenubar->style->ythickness);
}
case PM_ScrollView_ScrollBarSpacing:
{
gint spacing = 3;
- GtkWidget *gtkScrollWindow = d->gtkWidget(QLS("GtkScrolledWindow"));
+ GtkWidget *gtkScrollWindow = d->gtkWidget("GtkScrolledWindow");
Q_ASSERT(gtkScrollWindow);
d->gtk_widget_style_get(gtkScrollWindow, "scrollbar-spacing", &spacing, NULL);
return spacing;
}
case PM_SubMenuOverlap: {
gint offset = 0;
- GtkWidget *gtkMenu = d->gtkWidget(QLS("GtkMenu"));
+ GtkWidget *gtkMenu = d->gtkWidget("GtkMenu");
d->gtk_widget_style_get(gtkMenu, "horizontal-offset", &offset, NULL);
return offset;
}
@@ -587,7 +587,7 @@ int QGtkStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidg
{
if (d->isKDE4Session())
return QCleanlooksStyle::styleHint(hint, option, widget, returnData);
- GtkWidget *gtkToolbar = d->gtkWidget(QLS("GtkToolbar"));
+ GtkWidget *gtkToolbar = d->gtkWidget("GtkToolbar");
GtkToolbarStyle toolbar_style = GTK_TOOLBAR_ICONS;
g_object_get(gtkToolbar, "toolbar-style", &toolbar_style, NULL);
switch (toolbar_style) {
@@ -610,7 +610,7 @@ int QGtkStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidg
return int(false);
case SH_ComboBox_Popup: {
- GtkWidget *gtkComboBox = d->gtkWidget(QLS("GtkComboBox"));
+ GtkWidget *gtkComboBox = d->gtkWidget("GtkComboBox");
gboolean appears_as_list;
d->gtk_widget_style_get((GtkWidget*)gtkComboBox, "appears-as-list", &appears_as_list, NULL);
return appears_as_list ? 0 : 1;
@@ -634,7 +634,7 @@ int QGtkStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidg
if (widget && widget->isWindow())
scrollbars_within_bevel = true;
else if (!d->gtk_check_version(2, 12, 0)) {
- GtkWidget *gtkScrollWindow = d->gtkWidget(QLS("GtkScrolledWindow"));
+ GtkWidget *gtkScrollWindow = d->gtkWidget("GtkScrolledWindow");
d->gtk_widget_style_get(gtkScrollWindow, "scrollbars-within-bevel", &scrollbars_within_bevel, NULL);
}
return !scrollbars_within_bevel;
@@ -712,7 +712,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
GtkStyle *style = d->gtk_rc_get_style_by_paths(d->gtk_settings_get_default(),
"*.GtkScrolledWindow", "*.GtkScrolledWindow", d->gtk_window_get_type());
if (style)
- gtkFramePainter.paintShadow(d->gtkWidget(QLS("GtkFrame")), "viewport", pmRect,
+ gtkFramePainter.paintShadow(d->gtkWidget("GtkFrame"), "viewport", pmRect,
option->state & State_Enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE,
shadow_type, style);
QPixmapCache::insert(pmKey, pixmap);
@@ -739,7 +739,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
break;
case PE_PanelTipLabel: {
- GtkWidget *gtkWindow = d->gtkWidget(QLS("GtkWindow")); // The Murrine Engine currently assumes a widget is passed
+ GtkWidget *gtkWindow = d->gtkWidget("GtkWindow"); // The Murrine Engine currently assumes a widget is passed
style = d->gtk_rc_get_style_by_paths(d->gtk_settings_get_default(), "gtk-tooltips", "GtkWindow",
d->gtk_window_get_type());
gtkPainter.paintFlatBox(gtkWindow, "tooltip", option->rect, GTK_STATE_NORMAL, GTK_SHADOW_NONE, style);
@@ -754,7 +754,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
break;
}
GtkShadowType shadow_type;
- GtkWidget *gtkStatusbarFrame = d->gtkWidget(QLS("GtkStatusbar.GtkFrame"));
+ GtkWidget *gtkStatusbarFrame = d->gtkWidget("GtkStatusbar.GtkFrame");
d->gtk_widget_style_get(gtkStatusbarFrame->parent, "shadow-type", &shadow_type, NULL);
gtkPainter.paintShadow(gtkStatusbarFrame, "frame", option->rect, GTK_STATE_NORMAL,
shadow_type, gtkStatusbarFrame->style);
@@ -763,12 +763,14 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
case PE_IndicatorHeaderArrow:
if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
- GtkWidget *gtkTreeHeader = d->gtkWidget(QLS("GtkTreeView.GtkButton"));
+ GtkWidget *gtkTreeHeader = d->gtkWidget("GtkTreeView.GtkButton");
GtkStateType state = gtkPainter.gtkState(option);
style = gtkTreeHeader->style;
GtkArrowType type = GTK_ARROW_UP;
QRect r = header->rect;
QImage arrow;
+ // This sorting indicator inversion is intentional, and follows the GNOME HIG.
+ // See http://library.gnome.org/devel/hig-book/stable/controls-lists.html.en#controls-lists-sortable
if (header->sortIndicator & QStyleOptionHeader::SortUp)
type = GTK_ARROW_UP;
else if (header->sortIndicator & QStyleOptionHeader::SortDown)
@@ -801,7 +803,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
rect.translate(2, 0);
GtkExpanderStyle openState = GTK_EXPANDER_EXPANDED;
GtkExpanderStyle closedState = GTK_EXPANDER_COLLAPSED;
- GtkWidget *gtkTreeView = d->gtkWidget(QLS("GtkTreeView"));
+ GtkWidget *gtkTreeView = d->gtkWidget("GtkTreeView");
GtkStateType state = GTK_STATE_NORMAL;
if (!(option->state & State_Enabled))
@@ -837,7 +839,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
case PE_IndicatorToolBarSeparator:
{
const int margin = 6;
- GtkWidget *gtkSeparator = d->gtkWidget(QLS("GtkToolbar.GtkSeparatorToolItem"));
+ GtkWidget *gtkSeparator = d->gtkWidget("GtkToolbar.GtkSeparatorToolItem");
if (option->state & State_Horizontal) {
const int offset = option->rect.width()/2;
QRect rect = option->rect.adjusted(offset, margin, 0, -margin);
@@ -857,7 +859,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
break;
case PE_IndicatorToolBarHandle: {
- GtkWidget *gtkToolbar = d->gtkWidget(QLS("GtkToolbar"));
+ GtkWidget *gtkToolbar = d->gtkWidget("GtkToolbar");
GtkShadowType shadow_type;
d->gtk_widget_style_get(gtkToolbar, "shadow-type", &shadow_type, NULL);
//Note when the toolbar is horizontal, the handle is vertical
@@ -905,7 +907,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
GtkStateType state = gtkPainter.gtkState(option);
QColor arrowColor = option->palette.buttonText().color();
- GtkWidget *gtkArrow = d->gtkWidget(QLS("GtkArrow"));
+ GtkWidget *gtkArrow = d->gtkWidget("GtkArrow");
GdkColor color = fromQColor(arrowColor);
d->gtk_widget_modify_fg (gtkArrow, state, &color);
gtkPainter.paintArrow(gtkArrow, "button", arrowRect,
@@ -921,7 +923,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
break;
case PE_PanelMenu: {
- GtkWidget *gtkMenu = d->gtkWidget(QLS("GtkMenu"));
+ GtkWidget *gtkMenu = d->gtkWidget("GtkMenu");
gtkPainter.setAlphaSupport(false); // Note, alpha disabled for performance reasons
gtkPainter.paintBox(gtkMenu, "menu", option->rect, GTK_STATE_NORMAL, GTK_SHADOW_OUT, gtkMenu->style, QString());
}
@@ -933,7 +935,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
// This is only used by floating tool bars
if (qobject_cast<const QToolBar *>(widget)) {
- GtkWidget *gtkMenubar = d->gtkWidget(QLS("GtkMenuBar"));
+ GtkWidget *gtkMenubar = d->gtkWidget("GtkMenuBar");
gtkPainter.paintBox( gtkMenubar, "toolbar", option->rect,
GTK_STATE_NORMAL, GTK_SHADOW_OUT, style);
gtkPainter.paintBox( gtkMenubar, "menu", option->rect,
@@ -942,7 +944,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
break;
case PE_FrameLineEdit: {
- GtkWidget *gtkEntry = d->gtkWidget(QLS("GtkEntry"));
+ GtkWidget *gtkEntry = d->gtkWidget("GtkEntry");
gboolean interior_focus;
@@ -976,7 +978,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
case PE_PanelLineEdit:
if (const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
- GtkWidget *gtkEntry = d->gtkWidget(QLS("GtkEntry"));
+ GtkWidget *gtkEntry = d->gtkWidget("GtkEntry");
if (panel->lineWidth > 0)
proxy()->drawPrimitive(PE_FrameLineEdit, option, painter, widget);
uint resolve_mask = option->palette.resolve();
@@ -994,7 +996,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
case PE_FrameTabWidget:
if (const QStyleOptionTabWidgetFrame *frame = qstyleoption_cast<const QStyleOptionTabWidgetFrame*>(option)) {
- GtkWidget *gtkNotebook = d->gtkWidget(QLS("GtkNotebook"));
+ GtkWidget *gtkNotebook = d->gtkWidget("GtkNotebook");
style = gtkPainter.getStyle(gtkNotebook);
gtkPainter.setAlphaSupport(false);
GtkShadowType shadow = GTK_SHADOW_OUT;
@@ -1042,7 +1044,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
GtkStateType state = gtkPainter.gtkState(option);
if (option->state & State_On || option->state & State_Sunken)
state = GTK_STATE_ACTIVE;
- GtkWidget *gtkButton = d->gtkWidget(isTool ? QLS("GtkToolButton.GtkButton") : QLS("GtkButton"));
+ GtkWidget *gtkButton = isTool ? d->gtkWidget("GtkToolButton.GtkButton") : d->gtkWidget("GtkButton");
gint focusWidth, focusPad;
gboolean interiorFocus = false;
d->gtk_widget_style_get (gtkButton,
@@ -1098,14 +1100,14 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
else
shadow = GTK_SHADOW_OUT;
- GtkWidget *gtkRadioButton = d->gtkWidget(QLS("GtkRadioButton"));
+ GtkWidget *gtkRadioButton = d->gtkWidget("GtkRadioButton");
gint spacing;
d->gtk_widget_style_get(gtkRadioButton, "indicator-spacing", &spacing, NULL);
QRect buttonRect = option->rect.adjusted(spacing, spacing, -spacing, -spacing);
gtkPainter.setClipRect(option->rect);
// ### Note: Ubuntulooks breaks when the proper widget is passed
// Murrine engine requires a widget not to get RGBA check - warnings
- GtkWidget *gtkCheckButton = d->gtkWidget(QLS("GtkCheckButton"));
+ GtkWidget *gtkCheckButton = d->gtkWidget("GtkCheckButton");
QString key(QLS("radiobutton"));
if (option->state & State_HasFocus) { // Themes such as Nodoka check this flag
key += QLatin1Char('f');
@@ -1133,7 +1135,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
int spacing;
- GtkWidget *gtkCheckButton = d->gtkWidget(QLS("GtkCheckButton"));
+ GtkWidget *gtkCheckButton = d->gtkWidget("GtkCheckButton");
QString key(QLS("checkbutton"));
if (option->state & State_HasFocus) { // Themes such as Nodoka checks this flag
key += QLatin1Char('f');
@@ -1275,7 +1277,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && !groupBox->text.isEmpty()) {
// Draw prelight background
- GtkWidget *gtkCheckButton = d->gtkWidget(QLS("GtkCheckButton"));
+ GtkWidget *gtkCheckButton = d->gtkWidget("GtkCheckButton");
if (option->state & State_MouseOver) {
QRect bgRect = textRect | checkBoxRect;
@@ -1348,7 +1350,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
GtkShadowType shadow = (option->state & State_Sunken || option->state & State_On ) ?
GTK_SHADOW_IN : GTK_SHADOW_OUT;
- QString comboBoxPath = QLS(comboBox->editable ? "GtkComboBoxEntry" : "GtkComboBox");
+ const QHashableLatin1Literal comboBoxPath = comboBox->editable ? QHashableLatin1Literal("GtkComboBoxEntry") : QHashableLatin1Literal("GtkComboBox");
// We use the gtk widget to position arrows and separators for us
GtkWidget *gtkCombo = d->gtkWidget(comboBoxPath);
@@ -1356,7 +1358,8 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
d->gtk_widget_set_direction(gtkCombo, reverse ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR);
d->gtk_widget_size_allocate(gtkCombo, &geometry);
- QString buttonPath = comboBoxPath + QLS(".GtkToggleButton");
+ QHashableLatin1Literal buttonPath = comboBox->editable ? QHashableLatin1Literal("GtkComboBoxEntry.GtkToggleButton")
+ : QHashableLatin1Literal("GtkComboBox.GtkToggleButton");
GtkWidget *gtkToggleButton = d->gtkWidget(buttonPath);
d->gtk_widget_set_direction(gtkToggleButton, reverse ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR);
if (gtkToggleButton && (appears_as_list || comboBox->editable)) {
@@ -1365,7 +1368,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
// Draw the combo box as a line edit with a button next to it
if (comboBox->editable || appears_as_list) {
GtkStateType frameState = (state == GTK_STATE_PRELIGHT) ? GTK_STATE_NORMAL : state;
- QString entryPath = QLS(comboBox->editable ? "GtkComboBoxEntry.GtkEntry" : "GtkComboBox.GtkFrame");
+ QHashableLatin1Literal entryPath = comboBox->editable ? QHashableLatin1Literal("GtkComboBoxEntry.GtkEntry") : QHashableLatin1Literal("GtkComboBox.GtkFrame");
GtkWidget *gtkEntry = d->gtkWidget(entryPath);
d->gtk_widget_set_direction(gtkEntry, reverse ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR);
QRect frameRect = option->rect;
@@ -1391,11 +1394,11 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
else {
gtkCachedPainter.paintFlatBox(gtkEntry, "entry_bg", contentRect,
option->state & State_Enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE,
- GTK_SHADOW_NONE, gtkEntry->style, entryPath + QString::number(focus));
+ GTK_SHADOW_NONE, gtkEntry->style, entryPath.toString() + QString::number(focus));
}
gtkCachedPainter.paintShadow(gtkEntry, comboBox->editable ? "entry" : "frame", frameRect, frameState,
- GTK_SHADOW_IN, gtkEntry->style, entryPath +
+ GTK_SHADOW_IN, gtkEntry->style, entryPath.toString() +
QString::number(focus) + QString::number(comboBox->editable) +
QString::number(option->direction));
if (focus)
@@ -1416,7 +1419,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
Q_ASSERT(gtkToggleButton);
gtkCachedPainter.paintBox( gtkToggleButton, "button", arrowButtonRect, buttonState,
- shadow, gtkToggleButton->style, buttonPath +
+ shadow, gtkToggleButton->style, buttonPath.toString() +
QString::number(focus) + QString::number(option->direction));
if (focus)
GTK_WIDGET_UNSET_FLAGS(gtkToggleButton, GTK_HAS_FOCUS);
@@ -1429,12 +1432,17 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
gtkCachedPainter.paintBox(gtkToggleButton, "button",
buttonRect, state,
shadow, gtkToggleButton->style,
- buttonPath + QString::number(focus));
+ buttonPath.toString() + QString::number(focus));
if (focus)
GTK_WIDGET_UNSET_FLAGS(gtkToggleButton, GTK_HAS_FOCUS);
+ QHashableLatin1Literal buttonPath = comboBox->editable ? QHashableLatin1Literal("GtkComboBoxEntry.GtkToggleButton")
+ : QHashableLatin1Literal("GtkComboBox.GtkToggleButton");
+
// Draw the separator between label and arrows
- QString vSeparatorPath = buttonPath + QLS(".GtkHBox.GtkVSeparator");
+ QHashableLatin1Literal vSeparatorPath = comboBox->editable
+ ? QHashableLatin1Literal("GtkComboBoxEntry.GtkToggleButton.GtkHBox.GtkVSeparator")
+ : QHashableLatin1Literal("GtkComboBox.GtkToggleButton.GtkHBox.GtkVSeparator");
if (GtkWidget *gtkVSeparator = d->gtkWidget(vSeparatorPath)) {
QRect vLineRect(gtkVSeparator->allocation.x,
@@ -1444,7 +1452,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
gtkCachedPainter.paintVline( gtkVSeparator, "vseparator",
vLineRect, state, gtkVSeparator->style,
- 0, vLineRect.height(), 0, vSeparatorPath);
+ 0, vLineRect.height(), 0, vSeparatorPath.toString());
gint interiorFocus = true;
@@ -1469,8 +1477,18 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
else
state = GTK_STATE_NORMAL;
- QString arrowPath = comboBoxPath + QLS(appears_as_list ? ".GtkToggleButton.GtkArrow"
- : ".GtkToggleButton.GtkHBox.GtkArrow");
+ QHashableLatin1Literal arrowPath("");
+ if (comboBox->editable) {
+ if (appears_as_list)
+ arrowPath = QHashableLatin1Literal("GtkComboBoxEntry.GtkToggleButton.GtkArrow");
+ else
+ arrowPath = QHashableLatin1Literal("GtkComboBoxEntry.GtkToggleButton.GtkHBox.GtkArrow");
+ } else {
+ if (appears_as_list)
+ arrowPath = QHashableLatin1Literal("GtkComboBox.GtkToggleButton.GtkArrow");
+ else
+ arrowPath = QHashableLatin1Literal("GtkComboBox.GtkToggleButton.GtkHBox.GtkArrow");
+ }
GtkWidget *gtkArrow = d->gtkWidget(arrowPath);
gfloat scale = 0.7;
@@ -1497,7 +1515,11 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
if (sunken) {
int xoff, yoff;
- GtkWidget *gtkButton = d->gtkWidget(comboBoxPath + QLS(".GtkToggleButton"));
+ const QHashableLatin1Literal toggleButtonPath = comboBox->editable
+ ? QHashableLatin1Literal("GtkComboBoxEntry.GtkToggleButton")
+ : QHashableLatin1Literal("GtkComboBox.GtkToggleButton");
+
+ GtkWidget *gtkButton = d->gtkWidget(toggleButtonPath);
d->gtk_widget_style_get(gtkButton, "child-displacement-x", &xoff, NULL);
d->gtk_widget_style_get(gtkButton, "child-displacement-y", &yoff, NULL);
arrowRect = arrowRect.adjusted(xoff, yoff, xoff, yoff);
@@ -1509,7 +1531,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
gtkCachedPainter.setClipRect(option->rect);
gtkCachedPainter.paintArrow( gtkArrow, "arrow", arrowRect,
GTK_ARROW_DOWN, state, GTK_SHADOW_NONE, TRUE,
- style, arrowPath + QString::number(option->direction));
+ style, arrowPath.toString() + QString::number(option->direction));
}
}
END_STYLE_PIXMAPCACHE;
@@ -1570,7 +1592,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
QStyleOptionToolButton label = *toolbutton;
label.state = bflags;
- GtkWidget *gtkButton = d->gtkWidget(QLS("GtkToolButton.GtkButton"));
+ GtkWidget *gtkButton = d->gtkWidget("GtkToolButton.GtkButton");
QPalette pal = toolbutton->palette;
if (option->state & State_Enabled &&
option->state & State_MouseOver && !(widget && widget->testAttribute(Qt::WA_SetPalette))) {
@@ -1605,8 +1627,8 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
case CC_ScrollBar:
if (const QStyleOptionSlider *scrollBar = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- GtkWidget *gtkHScrollBar = d->gtkWidget(QLS("GtkHScrollbar"));
- GtkWidget *gtkVScrollBar = d->gtkWidget(QLS("GtkVScrollbar"));
+ GtkWidget *gtkHScrollBar = d->gtkWidget("GtkHScrollbar");
+ GtkWidget *gtkVScrollBar = d->gtkWidget("GtkVScrollbar");
// Fill background in case the scrollbar is partially transparent
painter->fillRect(option->rect, option->palette.background());
@@ -1751,10 +1773,9 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
case CC_SpinBox:
if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
- GtkWidget *gtkSpinButton = d->gtkWidget(
- spinBox->buttonSymbols == QAbstractSpinBox::NoButtons ?
- QLS("GtkEntry") :
- QLS("GtkSpinButton"));
+ GtkWidget *gtkSpinButton = spinBox->buttonSymbols == QAbstractSpinBox::NoButtons
+ ? d->gtkWidget("GtkEntry")
+ : d->gtkWidget("GtkSpinButton");
bool isEnabled = (spinBox->state & State_Enabled);
bool hover = isEnabled && (spinBox->state & State_MouseOver);
bool sunken = (spinBox->state & State_Sunken);
@@ -1906,8 +1927,8 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
case CC_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- GtkWidget *hScaleWidget = d->gtkWidget(QLS("GtkHScale"));
- GtkWidget *vScaleWidget = d->gtkWidget(QLS("GtkVScale"));
+ GtkWidget *hScaleWidget = d->gtkWidget("GtkHScale");
+ GtkWidget *vScaleWidget = d->gtkWidget("GtkVScale");
QRect groove = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget);
QRect handle = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
@@ -2097,7 +2118,7 @@ void QGtkStyle::drawControl(ControlElement element,
switch (element) {
case CE_ProgressBarLabel:
if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
- GtkWidget *gtkProgressBar = d->gtkWidget(QLS("GtkProgressBar"));
+ GtkWidget *gtkProgressBar = d->gtkWidget("GtkProgressBar");
if (!gtkProgressBar)
return;
@@ -2200,7 +2221,7 @@ void QGtkStyle::drawControl(ControlElement element,
if (button->features & QStyleOptionButton::HasMenu)
ir = ir.adjusted(0, 0, -pixelMetric(PM_MenuButtonIndicator, button, widget), 0);
- GtkWidget *gtkButton = d->gtkWidget(QLS("GtkButton"));
+ GtkWidget *gtkButton = d->gtkWidget("GtkButton");
QPalette pal = button->palette;
int labelState = GTK_STATE_INSENSITIVE;
if (option->state & State_Enabled)
@@ -2221,7 +2242,7 @@ void QGtkStyle::drawControl(ControlElement element,
bool isRadio = (element == CE_RadioButton);
// Draw prelight background
- GtkWidget *gtkRadioButton = d->gtkWidget(QLS("GtkRadioButton"));
+ GtkWidget *gtkRadioButton = d->gtkWidget("GtkRadioButton");
if (option->state & State_MouseOver) {
gtkPainter.paintFlatBox(gtkRadioButton, "checkbutton", option->rect,
@@ -2289,7 +2310,7 @@ void QGtkStyle::drawControl(ControlElement element,
}
if (!cb->currentText.isEmpty() && !cb->editable) {
- GtkWidget *gtkCombo = d->gtkWidget(QLS("GtkComboBox"));
+ GtkWidget *gtkCombo = d->gtkWidget("GtkComboBox");
QPalette pal = cb->palette;
int labelState = GTK_STATE_INSENSITIVE;
@@ -2366,7 +2387,7 @@ void QGtkStyle::drawControl(ControlElement element,
// Draws the header in tables.
if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
Q_UNUSED(header);
- GtkWidget *gtkTreeView = d->gtkWidget(QLS("GtkTreeView"));
+ GtkWidget *gtkTreeView = d->gtkWidget("GtkTreeView");
// Get the middle column
GtkTreeViewColumn *column = d->gtk_tree_view_get_column((GtkTreeView*)gtkTreeView, 1);
Q_ASSERT(column);
@@ -2387,7 +2408,7 @@ void QGtkStyle::drawControl(ControlElement element,
#ifndef QT_NO_SIZEGRIP
case CE_SizeGrip: {
- GtkWidget *gtkStatusbar = d->gtkWidget(QLS("GtkStatusbar.GtkFrame"));
+ GtkWidget *gtkStatusbar = d->gtkWidget("GtkStatusbar.GtkFrame");
QRect gripRect = option->rect.adjusted(0, 0, -gtkStatusbar->style->xthickness, -gtkStatusbar->style->ythickness);
gtkPainter.paintResizeGrip( gtkStatusbar, "statusbar", gripRect, GTK_STATE_NORMAL,
GTK_SHADOW_OUT, QApplication::isRightToLeft() ?
@@ -2399,7 +2420,7 @@ void QGtkStyle::drawControl(ControlElement element,
#endif // QT_NO_SIZEGRIP
case CE_MenuBarEmptyArea: {
- GtkWidget *gtkMenubar = d->gtkWidget(QLS("GtkMenuBar"));
+ GtkWidget *gtkMenubar = d->gtkWidget("GtkMenuBar");
GdkColor gdkBg = gtkMenubar->style->bg[GTK_STATE_NORMAL]; // Theme can depend on transparency
painter->fillRect(option->rect, QColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8));
if (widget) { // See CE_MenuBarItem
@@ -2422,8 +2443,8 @@ void QGtkStyle::drawControl(ControlElement element,
painter->save();
if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
- GtkWidget *gtkMenubarItem = d->gtkWidget(QLS("GtkMenuBar.GtkMenuItem"));
- GtkWidget *gtkMenubar = d->gtkWidget(QLS("GtkMenuBar"));
+ GtkWidget *gtkMenubarItem = d->gtkWidget("GtkMenuBar.GtkMenuItem");
+ GtkWidget *gtkMenubar = d->gtkWidget("GtkMenuBar");
style = gtkMenubarItem->style;
@@ -2479,7 +2500,7 @@ void QGtkStyle::drawControl(ControlElement element,
break;
case CE_Splitter: {
- GtkWidget *gtkWindow = d->gtkWidget(QLS("GtkWindow")); // The Murrine Engine currently assumes a widget is passed
+ GtkWidget *gtkWindow = d->gtkWidget("GtkWindow"); // The Murrine Engine currently assumes a widget is passed
gtkPainter.paintHandle(gtkWindow, "splitter", option->rect, gtkPainter.gtkState(option), GTK_SHADOW_NONE,
!(option->state & State_Horizontal) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL,
style);
@@ -2499,7 +2520,7 @@ void QGtkStyle::drawControl(ControlElement element,
if (toolbar->positionWithinLine != QStyleOptionToolBar::End)
rect.adjust(0, 0, 1, 0);
- GtkWidget *gtkToolbar = d->gtkWidget(QLS("GtkToolbar"));
+ GtkWidget *gtkToolbar = d->gtkWidget("GtkToolbar");
GtkShadowType shadow_type = GTK_SHADOW_NONE;
d->gtk_widget_style_get(gtkToolbar, "shadow-type", &shadow_type, NULL);
gtkPainter.paintBox( gtkToolbar, "toolbar", rect,
@@ -2518,15 +2539,15 @@ void QGtkStyle::drawControl(ControlElement element,
const int windowsItemHMargin = 3; // menu item hor text margin
const int windowsItemVMargin = 26; // menu item ver text margin
const int windowsRightBorder = 15; // right border on windows
- GtkWidget *gtkMenuItem = menuItem->checked ? d->gtkWidget(QLS("GtkMenu.GtkCheckMenuItem")) :
- d->gtkWidget(QLS("GtkMenu.GtkMenuItem"));
+ GtkWidget *gtkMenuItem = menuItem->checked ? d->gtkWidget("GtkMenu.GtkCheckMenuItem") :
+ d->gtkWidget("GtkMenu.GtkMenuItem");
style = gtkPainter.getStyle(gtkMenuItem);
QColor borderColor = option->palette.background().color().darker(160);
QColor shadow = option->palette.dark().color();
if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
- GtkWidget *gtkMenuSeparator = d->gtkWidget(QLS("GtkMenu.GtkSeparatorMenuItem"));
+ GtkWidget *gtkMenuSeparator = d->gtkWidget("GtkMenu.GtkSeparatorMenuItem");
painter->setPen(shadow.lighter(106));
gboolean wide_separators = 0;
gint separator_height = 0;
@@ -2570,7 +2591,7 @@ void QGtkStyle::drawControl(ControlElement element,
bool ignoreCheckMark = false;
gint checkSize;
- d->gtk_widget_style_get(d->gtkWidget(QLS("GtkMenu.GtkCheckMenuItem")), "indicator-size", &checkSize, NULL);
+ d->gtk_widget_style_get(d->gtkWidget("GtkMenu.GtkCheckMenuItem"), "indicator-size", &checkSize, NULL);
int checkcol = qMax(menuItem->maxIconWidth, qMax(20, checkSize));
@@ -2781,7 +2802,7 @@ void QGtkStyle::drawControl(ControlElement element,
case CE_PushButton:
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
- GtkWidget *gtkButton = d->gtkWidget(QLS("GtkButton"));
+ GtkWidget *gtkButton = d->gtkWidget("GtkButton");
proxy()->drawControl(CE_PushButtonBevel, btn, painter, widget);
QStyleOptionButton subopt = *btn;
subopt.rect = subElementRect(SE_PushButtonContents, btn, widget);
@@ -2807,7 +2828,7 @@ void QGtkStyle::drawControl(ControlElement element,
case CE_TabBarTabShape:
if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option)) {
- GtkWidget *gtkNotebook = d->gtkWidget(QLS("GtkNotebook"));
+ GtkWidget *gtkNotebook = d->gtkWidget("GtkNotebook");
style = gtkPainter.getStyle(gtkNotebook);
QRect rect = option->rect;
@@ -2874,7 +2895,7 @@ void QGtkStyle::drawControl(ControlElement element,
case CE_ProgressBarGroove:
if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
Q_UNUSED(bar);
- GtkWidget *gtkProgressBar = d->gtkWidget(QLS("GtkProgressBar"));
+ GtkWidget *gtkProgressBar = d->gtkWidget("GtkProgressBar");
GtkStateType state = gtkPainter.gtkState(option);
gtkPainter.paintBox( gtkProgressBar, "trough", option->rect, state, GTK_SHADOW_IN, gtkProgressBar->style);
}
@@ -2884,7 +2905,7 @@ void QGtkStyle::drawControl(ControlElement element,
case CE_ProgressBarContents:
if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
GtkStateType state = option->state & State_Enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE;
- GtkWidget *gtkProgressBar = d->gtkWidget(QLS("GtkProgressBar"));
+ GtkWidget *gtkProgressBar = d->gtkWidget("GtkProgressBar");
style = gtkProgressBar->style;
gtkPainter.paintBox( gtkProgressBar, "trough", option->rect, state, GTK_SHADOW_IN, style);
int xt = style->xthickness;
@@ -3042,7 +3063,7 @@ QRect QGtkStyle::subControlRect(ComplexControl control, const QStyleOptionComple
case CC_SpinBox:
if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
- GtkWidget *gtkSpinButton = d->gtkWidget(QLS("GtkSpinButton"));
+ GtkWidget *gtkSpinButton = d->gtkWidget("GtkSpinButton");
int center = spinbox->rect.height() / 2;
int xt = spinbox->frame ? gtkSpinButton->style->xthickness : 0;
int yt = spinbox->frame ? gtkSpinButton->style->ythickness : 0;
@@ -3096,15 +3117,19 @@ QRect QGtkStyle::subControlRect(ComplexControl control, const QStyleOptionComple
if (const QStyleOptionComboBox *box = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
// We employ the gtk widget to position arrows and separators for us
QString comboBoxPath = box->editable ? QLS("GtkComboBoxEntry") : QLS("GtkComboBox");
- GtkWidget *gtkCombo = d->gtkWidget(comboBoxPath);
+ GtkWidget *gtkCombo = box->editable ? d->gtkWidget("GtkComboBoxEntry")
+ : d->gtkWidget("GtkComboBox");
d->gtk_widget_set_direction(gtkCombo, (option->direction == Qt::RightToLeft) ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR);
GtkAllocation geometry = {0, 0, qMax(0, option->rect.width()), qMax(0, option->rect.height())};
d->gtk_widget_size_allocate(gtkCombo, &geometry);
int appears_as_list = !proxy()->styleHint(QStyle::SH_ComboBox_Popup, option, widget);
- QString arrowPath = comboBoxPath + QLS(".GtkToggleButton");
-
- if (!box->editable && !appears_as_list)
- arrowPath += QLS(".GtkHBox.GtkArrow");
+ QHashableLatin1Literal arrowPath("GtkComboBoxEntry.GtkToggleButton");
+ if (!box->editable) {
+ if (appears_as_list)
+ arrowPath = "GtkComboBox.GtkToggleButton";
+ else
+ arrowPath = "GtkComboBox.GtkToggleButton.GtkHBox.GtkArrow";
+ }
GtkWidget *arrowWidget = d->gtkWidget(arrowPath);
if (!arrowWidget)
@@ -3163,7 +3188,7 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
case CT_ToolButton:
if (const QStyleOptionToolButton *toolbutton = qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
- GtkWidget *gtkButton = d->gtkWidget(QLS("GtkToolButton.GtkButton"));
+ GtkWidget *gtkButton = d->gtkWidget("GtkToolButton.GtkButton");
newSize = size + QSize(2 * gtkButton->style->xthickness, 2 + 2 * gtkButton->style->ythickness);
if (widget && qobject_cast<QToolBar *>(widget->parentWidget())) {
QSize minSize(0, 25);
@@ -3181,14 +3206,14 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
int textMargin = 8;
if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
- GtkWidget *gtkMenuSeparator = d->gtkWidget(QLS("GtkMenu.GtkSeparatorMenuItem"));
+ GtkWidget *gtkMenuSeparator = d->gtkWidget("GtkMenu.GtkSeparatorMenuItem");
GtkRequisition sizeReq = {0, 0};
d->gtk_widget_size_request(gtkMenuSeparator, &sizeReq);
newSize = QSize(size.width(), sizeReq.height);
break;
}
- GtkWidget *gtkMenuItem = d->gtkWidget(QLS("GtkMenu.GtkCheckMenuItem"));
+ GtkWidget *gtkMenuItem = d->gtkWidget("GtkMenu.GtkCheckMenuItem");
GtkStyle* style = gtkMenuItem->style;
// Note we get the perfect height for the default font since we
@@ -3210,12 +3235,12 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
case CT_SpinBox:
// QSpinBox does some nasty things that depends on CT_LineEdit
- newSize = size + QSize(0, -d->gtkWidget(QLS("GtkSpinButton"))->style->ythickness * 2);
+ newSize = size + QSize(0, -d->gtkWidget("GtkSpinButton")->style->ythickness * 2);
break;
case CT_PushButton:
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
- GtkWidget *gtkButton = d->gtkWidget(QLS("GtkButton"));
+ GtkWidget *gtkButton = d->gtkWidget("GtkButton");
gint focusPadding, focusWidth;
d->gtk_widget_style_get(gtkButton, "focus-padding", &focusPadding, NULL);
d->gtk_widget_style_get(gtkButton, "focus-line-width", &focusWidth, NULL);
@@ -3223,7 +3248,7 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
newSize += QSize(2*gtkButton->style->xthickness + 4, 2*gtkButton->style->ythickness);
newSize += QSize(2*(focusWidth + focusPadding + 2), 2*(focusWidth + focusPadding));
- GtkWidget *gtkButtonBox = d->gtkWidget(QLS("GtkHButtonBox"));
+ GtkWidget *gtkButtonBox = d->gtkWidget("GtkHButtonBox");
gint minWidth = 85, minHeight = 0;
d->gtk_widget_style_get(gtkButtonBox, "child-min-width", &minWidth,
"child-min-height", &minHeight, NULL);
@@ -3236,13 +3261,13 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
break;
case CT_Slider: {
- GtkWidget *gtkSlider = d->gtkWidget(QLS("GtkHScale"));
+ GtkWidget *gtkSlider = d->gtkWidget("GtkHScale");
newSize = size + QSize(2*gtkSlider->style->xthickness, 2*gtkSlider->style->ythickness);
}
break;
case CT_LineEdit: {
- GtkWidget *gtkEntry = d->gtkWidget(QLS("GtkEntry"));
+ GtkWidget *gtkEntry = d->gtkWidget("GtkEntry");
newSize = size + QSize(2*gtkEntry->style->xthickness, 2 + 2*gtkEntry->style->ythickness);
}
break;
@@ -3253,7 +3278,7 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
case CT_ComboBox:
if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
- GtkWidget *gtkCombo = d->gtkWidget(QLS("GtkComboBox"));
+ GtkWidget *gtkCombo = d->gtkWidget("GtkComboBox");
QRect arrowButtonRect = proxy()->subControlRect(CC_ComboBox, combo, SC_ComboBoxArrow, widget);
newSize = size + QSize(12 + arrowButtonRect.width() + 2*gtkCombo->style->xthickness, 4 + 2*gtkCombo->style->ythickness);
@@ -3398,6 +3423,9 @@ QRect QGtkStyle::subElementRect(SubElement element, const QStyleOption *option,
Q_D(const QGtkStyle);
QRect r = QCleanlooksStyle::subElementRect(element, option, widget);
+ if (!d->isThemeAvailable())
+ return r;
+
switch (element) {
case SE_ProgressBarLabel:
case SE_ProgressBarContents:
@@ -3405,7 +3433,7 @@ QRect QGtkStyle::subElementRect(SubElement element, const QStyleOption *option,
return option->rect;
case SE_PushButtonContents:
if (!d->gtk_check_version(2, 10, 0)) {
- GtkWidget *gtkButton = d->gtkWidget(QLS("GtkButton"));
+ GtkWidget *gtkButton = d->gtkWidget("GtkButton");
GtkBorder *border = 0;
d->gtk_widget_style_get(gtkButton, "inner-border", &border, NULL);
if (border) {
diff --git a/src/gui/styles/qgtkstyle_p.cpp b/src/gui/styles/qgtkstyle_p.cpp
index a033407..3c6a1ef 100644
--- a/src/gui/styles/qgtkstyle_p.cpp
+++ b/src/gui/styles/qgtkstyle_p.cpp
@@ -60,6 +60,7 @@
#include <QtCore/QHash>
#include <QtCore/QUrl>
#include <QtCore/QLibrary>
+#include <QtCore/QDebug>
#include <private/qapplication_p.h>
#include <private/qiconloader_p.h>
@@ -91,8 +92,8 @@ Ptr_gtk_widget_set_default_direction QGtkStylePrivate::gtk_widget_set_default_di
Ptr_gtk_widget_modify_color QGtkStylePrivate::gtk_widget_modify_fg = 0;
Ptr_gtk_widget_modify_color QGtkStylePrivate::gtk_widget_modify_bg = 0;
Ptr_gtk_arrow_new QGtkStylePrivate::gtk_arrow_new = 0;
-Ptr_gtk_menu_item_new QGtkStylePrivate::gtk_menu_item_new = 0;
-Ptr_gtk_check_menu_item_new QGtkStylePrivate::gtk_check_menu_item_new = 0;
+Ptr_gtk_menu_item_new_with_label QGtkStylePrivate::gtk_menu_item_new_with_label = 0;
+Ptr_gtk_check_menu_item_new_with_label QGtkStylePrivate::gtk_check_menu_item_new_with_label = 0;
Ptr_gtk_menu_bar_new QGtkStylePrivate::gtk_menu_bar_new = 0;
Ptr_gtk_menu_new QGtkStylePrivate::gtk_menu_new = 0;
Ptr_gtk_button_new QGtkStylePrivate::gtk_button_new = 0;
@@ -233,17 +234,22 @@ static void update_toolbar_style(GtkWidget *gtkToolBar, GParamSpec *, gpointer)
}
}
-static QString classPath(GtkWidget *widget)
+static QHashableLatin1Literal classPath(GtkWidget *widget)
{
- char* class_path;
+ char *class_path;
QGtkStylePrivate::gtk_widget_path (widget, NULL, &class_path, NULL);
- QString path = QLS(class_path);
+
+ char *copy = class_path;
+ if (strncmp(copy, "GtkWindow.", 10) == 0)
+ copy += 10;
+ if (strncmp(copy, "GtkFixed.", 9) == 0)
+ copy += 9;
+
+ copy = strdup(copy);
+
g_free(class_path);
- // Remove the prefixes
- path.remove(QLS("GtkWindow."));
- path.remove(QLS("GtkFixed."));
- return path;
+ return QHashableLatin1Literal::fromData(copy);
}
@@ -261,6 +267,7 @@ bool QGtkStyleFilter::eventFilter(QObject *obj, QEvent *e)
}
QList<QGtkStylePrivate *> QGtkStylePrivate::instances;
+QGtkStylePrivate::WidgetMap *QGtkStylePrivate::widgetMap = 0;
QGtkStylePrivate::QGtkStylePrivate()
: QCleanlooksStylePrivate()
@@ -282,7 +289,7 @@ void QGtkStylePrivate::init()
qApp->installEventFilter(&filter);
}
-GtkWidget* QGtkStylePrivate::gtkWidget(const QString &path)
+GtkWidget* QGtkStylePrivate::gtkWidget(const QHashableLatin1Literal &path)
{
GtkWidget *widget = gtkWidgetMap()->value(path);
if (!widget) {
@@ -292,10 +299,10 @@ GtkWidget* QGtkStylePrivate::gtkWidget(const QString &path)
return widget;
}
-GtkStyle* QGtkStylePrivate::gtkStyle(const QString &path)
+GtkStyle* QGtkStylePrivate::gtkStyle(const QHashableLatin1Literal &path)
{
- if (gtkWidgetMap()->contains(path))
- return gtkWidgetMap()->value(path)->style;
+ if (GtkWidget *w = gtkWidgetMap()->value(path))
+ return w->style;
return 0;
}
@@ -347,8 +354,8 @@ void QGtkStylePrivate::resolveGtk() const
gtk_widget_modify_fg = (Ptr_gtk_widget_modify_color)libgtk.resolve("gtk_widget_modify_fg");
gtk_widget_modify_bg = (Ptr_gtk_widget_modify_color)libgtk.resolve("gtk_widget_modify_bg");
gtk_arrow_new = (Ptr_gtk_arrow_new)libgtk.resolve("gtk_arrow_new");
- gtk_menu_item_new = (Ptr_gtk_menu_item_new)libgtk.resolve("gtk_menu_item_new");
- gtk_check_menu_item_new = (Ptr_gtk_check_menu_item_new)libgtk.resolve("gtk_check_menu_item_new");
+ gtk_menu_item_new_with_label = (Ptr_gtk_menu_item_new_with_label)libgtk.resolve("gtk_menu_item_new_with_label");
+ gtk_check_menu_item_new_with_label = (Ptr_gtk_check_menu_item_new_with_label)libgtk.resolve("gtk_check_menu_item_new_with_label");
gtk_menu_bar_new = (Ptr_gtk_menu_bar_new)libgtk.resolve("gtk_menu_bar_new");
gtk_menu_new = (Ptr_gtk_menu_new)libgtk.resolve("gtk_menu_new");
gtk_toolbar_new = (Ptr_gtk_toolbar_new)libgtk.resolve("gtk_toolbar_new");
@@ -439,7 +446,7 @@ void QGtkStylePrivate::initGtkMenu() const
GtkWidget *gtkMenuBar = QGtkStylePrivate::gtk_menu_bar_new();
setupGtkWidget(gtkMenuBar);
- GtkWidget *gtkMenuBarItem = QGtkStylePrivate::gtk_menu_item_new();
+ GtkWidget *gtkMenuBarItem = QGtkStylePrivate::gtk_menu_item_new_with_label("X");
gtk_menu_shell_append((GtkMenuShell*)(gtkMenuBar), gtkMenuBarItem);
gtk_widget_realize(gtkMenuBarItem);
@@ -448,14 +455,11 @@ void QGtkStylePrivate::initGtkMenu() const
gtk_menu_item_set_submenu((GtkMenuItem*)(gtkMenuBarItem), gtkMenu);
gtk_widget_realize(gtkMenu);
- GtkWidget *gtkMenuItem = QGtkStylePrivate::gtk_menu_item_new();
- g_object_set(gtkMenuItem, "label", "X", NULL);
-
+ GtkWidget *gtkMenuItem = QGtkStylePrivate::gtk_menu_item_new_with_label("X");
gtk_menu_shell_append((GtkMenuShell*)gtkMenu, gtkMenuItem);
gtk_widget_realize(gtkMenuItem);
- GtkWidget *gtkCheckMenuItem = QGtkStylePrivate::gtk_check_menu_item_new();
- g_object_set(gtkCheckMenuItem, "label", "X", NULL);
+ GtkWidget *gtkCheckMenuItem = QGtkStylePrivate::gtk_check_menu_item_new_with_label("X");
gtk_menu_shell_append((GtkMenuShell*)gtkMenu, gtkCheckMenuItem);
gtk_widget_realize(gtkCheckMenuItem);
@@ -497,7 +501,7 @@ void QGtkStylePrivate::initGtkWidgets() const
}
static QString themeName;
- if (!gtkWidgetMap()->contains(QLS("GtkWindow")) && themeName.isEmpty()) {
+ if (!gtkWidgetMap()->contains("GtkWindow") && themeName.isEmpty()) {
themeName = getThemeName();
if (themeName.isEmpty()) {
@@ -522,18 +526,18 @@ void QGtkStylePrivate::initGtkWidgets() const
QGtkStylePrivate::gtk_widget_realize(gtkWindow);
if (displayDepth == -1)
displayDepth = QGtkStylePrivate::gdk_drawable_get_depth(gtkWindow->window);
- gtkWidgetMap()->insert(QLS("GtkWindow"), gtkWindow);
+ gtkWidgetMap()->insert(QHashableLatin1Literal::fromData(strdup("GtkWindow")), gtkWindow);
// Make all other widgets. respect the text direction
if (qApp->layoutDirection() == Qt::RightToLeft)
QGtkStylePrivate::gtk_widget_set_default_direction(GTK_TEXT_DIR_RTL);
- if (!gtkWidgetMap()->contains(QLS("GtkButton"))) {
+ if (!gtkWidgetMap()->contains("GtkButton")) {
GtkWidget *gtkButton = QGtkStylePrivate::gtk_button_new();
addWidget(gtkButton);
g_signal_connect(gtkButton, "style-set", G_CALLBACK(gtkStyleSetCallback), 0);
- addWidget(QGtkStylePrivate::gtk_tool_button_new(NULL, NULL));
+ addWidget(QGtkStylePrivate::gtk_tool_button_new(NULL, "Qt"));
addWidget(QGtkStylePrivate::gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE));
addWidget(QGtkStylePrivate::gtk_hbutton_box_new());
addWidget(QGtkStylePrivate::gtk_check_button_new());
@@ -566,12 +570,12 @@ void QGtkStylePrivate::initGtkWidgets() const
// When styles change subwidgets can get rearranged
// as with the combo box. We need to update the widget map
// to reflect this;
- QHash<QString, GtkWidget*> oldMap = *gtkWidgetMap();
+ QHash<QHashableLatin1Literal, GtkWidget*> oldMap = *gtkWidgetMap();
gtkWidgetMap()->clear();
- QHashIterator<QString, GtkWidget*> it(oldMap);
+ QHashIterator<QHashableLatin1Literal, GtkWidget*> it(oldMap);
while (it.hasNext()) {
it.next();
- if (!it.key().contains(QLatin1Char('.'))) {
+ if (!strchr(it.key().data(), '.')) {
addAllSubWidgets(it.value());
}
}
@@ -586,8 +590,13 @@ void QGtkStylePrivate::initGtkWidgets() const
*/
void QGtkStylePrivate::cleanupGtkWidgets()
{
- if (gtkWidgetMap()->contains(QLS("GtkWindow"))) // Gtk will destroy all children
- gtk_widget_destroy(gtkWidgetMap()->value(QLS("GtkWindow")));
+ if (!widgetMap)
+ return;
+ if (widgetMap->contains("GtkWindow")) // Gtk will destroy all children
+ gtk_widget_destroy(widgetMap->value("GtkWindow"));
+ for (QHash<QHashableLatin1Literal, GtkWidget *>::const_iterator it = widgetMap->constBegin();
+ it != widgetMap->constEnd(); ++it)
+ free(const_cast<char *>(it.key().data()));
}
static bool resolveGConf()
@@ -678,7 +687,7 @@ QString QGtkStylePrivate::getThemeName()
int QGtkStylePrivate::getSpinboxArrowSize() const
{
const int MIN_ARROW_WIDTH = 6;
- GtkWidget *spinButton = gtkWidget(QLS("GtkSpinButton"));
+ GtkWidget *spinButton = gtkWidget("GtkSpinButton");
GtkStyle *style = spinButton->style;
gint size = pango_font_description_get_size (style->font_desc);
gint arrow_size;
@@ -698,17 +707,17 @@ bool QGtkStylePrivate::isKDE4Session()
void QGtkStylePrivate::applyCustomPaletteHash()
{
- QPalette menuPal = gtkWidgetPalette(QLS("GtkMenu"));
- GdkColor gdkBg = gtkWidget(QLS("GtkMenu"))->style->bg[GTK_STATE_NORMAL];
+ QPalette menuPal = gtkWidgetPalette("GtkMenu");
+ GdkColor gdkBg = gtkWidget("GtkMenu")->style->bg[GTK_STATE_NORMAL];
QColor bgColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8);
menuPal.setBrush(QPalette::Base, bgColor);
menuPal.setBrush(QPalette::Window, bgColor);
qApp->setPalette(menuPal, "QMenu");
- QPalette toolbarPal = gtkWidgetPalette(QLS("GtkToolbar"));
+ QPalette toolbarPal = gtkWidgetPalette("GtkToolbar");
qApp->setPalette(toolbarPal, "QToolBar");
- QPalette menuBarPal = gtkWidgetPalette(QLS("GtkMenuBar"));
+ QPalette menuBarPal = gtkWidgetPalette("GtkMenuBar");
qApp->setPalette(menuBarPal, "QMenuBar");
}
@@ -717,7 +726,7 @@ void QGtkStylePrivate::applyCustomPaletteHash()
*/
GtkWidget* QGtkStylePrivate::getTextColorWidget() const
{
- return gtkWidget(QLS("GtkEntry"));
+ return gtkWidget("GtkEntry");
}
void QGtkStylePrivate::setupGtkWidget(GtkWidget* widget)
@@ -726,7 +735,7 @@ void QGtkStylePrivate::setupGtkWidget(GtkWidget* widget)
static GtkWidget* protoLayout = 0;
if (!protoLayout) {
protoLayout = QGtkStylePrivate::gtk_fixed_new();
- QGtkStylePrivate::gtk_container_add((GtkContainer*)(gtkWidgetMap()->value(QLS("GtkWindow"))), protoLayout);
+ QGtkStylePrivate::gtk_container_add((GtkContainer*)(gtkWidgetMap()->value("GtkWindow")), protoLayout);
}
Q_ASSERT(protoLayout);
@@ -739,8 +748,19 @@ void QGtkStylePrivate::setupGtkWidget(GtkWidget* widget)
void QGtkStylePrivate::addWidgetToMap(GtkWidget *widget)
{
if (Q_GTK_IS_WIDGET(widget)) {
- gtk_widget_realize(widget);
- gtkWidgetMap()->insert(classPath(widget), widget);
+ gtk_widget_realize(widget);
+ QHashableLatin1Literal widgetPath = classPath(widget);
+
+ WidgetMap *map = gtkWidgetMap();
+ WidgetMap::iterator it = map->find(widgetPath);
+ if (it != map->end()) {
+ free(const_cast<char *>(it.key().data()));
+ map->erase(it);
+ }
+ map->insert(widgetPath, widget);
+#ifdef DUMP_GTK_WIDGET_TREE
+ qWarning("Inserted Gtk Widget: %s", widgetPath.data());
+#endif
}
}
@@ -753,7 +773,7 @@ void QGtkStylePrivate::addAllSubWidgets(GtkWidget *widget, gpointer v)
}
// Updates window/windowtext palette based on the indicated gtk widget
-QPalette QGtkStylePrivate::gtkWidgetPalette(const QString &gtkWidgetName) const
+QPalette QGtkStylePrivate::gtkWidgetPalette(const QHashableLatin1Literal &gtkWidgetName) const
{
GtkWidget *gtkWidget = QGtkStylePrivate::gtkWidget(gtkWidgetName);
Q_ASSERT(gtkWidget);
@@ -1089,6 +1109,28 @@ QIcon QGtkStylePrivate::getFilesystemIcon(const QFileInfo &info)
return icon;
}
+bool operator==(const QHashableLatin1Literal &l1, const QHashableLatin1Literal &l2)
+{
+ return l1.size() == l2.size() || qstrcmp(l1.data(), l2.data()) == 0;
+}
+
+// copied from qHash.cpp
+uint qHash(const QHashableLatin1Literal &key)
+{
+ int n = key.size();
+ const uchar *p = reinterpret_cast<const uchar *>(key.data());
+ uint h = 0;
+ uint g;
+
+ while (n--) {
+ h = (h << 4) + *p++;
+ if ((g = (h & 0xf0000000)) != 0)
+ h ^= g >> 23;
+ h &= ~g;
+ }
+ return h;
+}
+
QT_END_NAMESPACE
#endif // !defined(QT_NO_STYLE_GTK)
diff --git a/src/gui/styles/qgtkstyle_p.h b/src/gui/styles/qgtkstyle_p.h
index db5b9b9..68a04e9 100644
--- a/src/gui/styles/qgtkstyle_p.h
+++ b/src/gui/styles/qgtkstyle_p.h
@@ -56,6 +56,10 @@
#include <QtCore/qglobal.h>
#if !defined(QT_NO_STYLE_GTK)
+#include <QtCore/qstring.h>
+#include <QtCore/qstringbuilder.h>
+#include <QtCore/qcoreapplication.h>
+
#include <QtGui/QFileDialog>
#include <QtGui/QGtkStyle>
@@ -72,6 +76,59 @@ typedef unsigned long XID;
#define QLS(x) QLatin1String(x)
+QT_BEGIN_NAMESPACE
+
+// ### Qt 4.7 - merge with QLatin1Literal
+class QHashableLatin1Literal
+{
+public:
+ int size() const { return m_size; }
+ const char *data() const { return m_data; }
+
+#ifdef __SUNPRO_CC
+ QHashableLatin1Literal(const char* str)
+ : m_size(strlen(str)), m_data(str) {}
+#else
+ template <int N>
+ QHashableLatin1Literal(const char (&str)[N])
+ : m_size(N - 1), m_data(str) {}
+#endif
+
+ QHashableLatin1Literal(const QHashableLatin1Literal &other)
+ : m_size(other.m_size), m_data(other.m_data)
+ {}
+
+ QHashableLatin1Literal &operator=(const QHashableLatin1Literal &other)
+ {
+ if (this == &other)
+ return *this;
+ *const_cast<int *>(&m_size) = other.m_size;
+ *const_cast<char **>(&m_data) = const_cast<char *>(other.m_data);
+ return *this;
+ }
+
+ QString toString() const { return QString::fromLatin1(m_data, m_size); }
+
+ static QHashableLatin1Literal fromData(const char *str)
+ {
+ return QHashableLatin1Literal(str, qstrlen(str));
+ }
+
+private:
+ QHashableLatin1Literal(const char *str, int length)
+ : m_size(length), m_data(str)
+ {}
+
+ const int m_size;
+ const char *m_data;
+};
+
+bool operator==(const QHashableLatin1Literal &l1, const QHashableLatin1Literal &l2);
+inline bool operator!=(const QHashableLatin1Literal &l1, const QHashableLatin1Literal &l2) { return !operator==(l1, l2); }
+uint qHash(const QHashableLatin1Literal &key);
+
+QT_END_NAMESPACE
+
class GConf;
class GConfClient;
@@ -87,9 +144,9 @@ typedef void (*Ptr_gtk_widget_realize) (GtkWidget *);
typedef void (*Ptr_gtk_widget_set_default_direction) (GtkTextDirection);
typedef void (*Ptr_gtk_widget_modify_color)(GtkWidget *widget, GtkStateType state, const GdkColor *color);
typedef GtkWidget* (*Ptr_gtk_arrow_new)(GtkArrowType, GtkShadowType);
-typedef GtkWidget* (*Ptr_gtk_menu_item_new)(void);
+typedef GtkWidget* (*Ptr_gtk_menu_item_new_with_label)(const gchar *);
typedef GtkWidget* (*Ptr_gtk_separator_menu_item_new)(void);
-typedef GtkWidget* (*Ptr_gtk_check_menu_item_new)(void);
+typedef GtkWidget* (*Ptr_gtk_check_menu_item_new_with_label)(const gchar *);
typedef GtkWidget* (*Ptr_gtk_menu_bar_new)(void);
typedef GtkWidget* (*Ptr_gtk_menu_new)(void);
typedef GtkWidget* (*Ptr_gtk_combo_box_entry_new)(void);
@@ -252,7 +309,6 @@ typedef char* (*Ptr_gnome_icon_lookup_sync) (
GnomeIconLookupFlags flags,
GnomeIconLookupResultFlags *result);
-
class QGtkStylePrivate : public QCleanlooksStylePrivate
{
Q_DECLARE_PUBLIC(QGtkStyle)
@@ -262,8 +318,8 @@ public:
QGtkStyleFilter filter;
- static GtkWidget* gtkWidget(const QString &path);
- static GtkStyle* gtkStyle(const QString &path = QLatin1String("GtkWindow"));
+ static GtkWidget* gtkWidget(const QHashableLatin1Literal &path);
+ static GtkStyle* gtkStyle(const QHashableLatin1Literal &path = QHashableLatin1Literal("GtkWindow"));
virtual void resolveGtk() const;
virtual void initGtkMenu() const;
@@ -306,9 +362,9 @@ public:
static Ptr_gtk_widget_set_default_direction gtk_widget_set_default_direction;
static Ptr_gtk_widget_modify_color gtk_widget_modify_fg;
static Ptr_gtk_widget_modify_color gtk_widget_modify_bg;
- static Ptr_gtk_menu_item_new gtk_menu_item_new;
+ static Ptr_gtk_menu_item_new_with_label gtk_menu_item_new_with_label;
static Ptr_gtk_arrow_new gtk_arrow_new;
- static Ptr_gtk_check_menu_item_new gtk_check_menu_item_new;
+ static Ptr_gtk_check_menu_item_new_with_label gtk_check_menu_item_new_with_label;
static Ptr_gtk_menu_bar_new gtk_menu_bar_new;
static Ptr_gtk_menu_new gtk_menu_new;
static Ptr_gtk_expander_new gtk_expander_new;
@@ -418,17 +474,25 @@ public:
static Ptr_gnome_icon_lookup_sync gnome_icon_lookup_sync;
static Ptr_gnome_vfs_init gnome_vfs_init;
- virtual QPalette gtkWidgetPalette(const QString &gtkWidgetName) const;
+ virtual QPalette gtkWidgetPalette(const QHashableLatin1Literal &gtkWidgetName) const;
protected:
- typedef QHash<QString, GtkWidget*> WidgetMap;
+ typedef QHash<QHashableLatin1Literal, GtkWidget*> WidgetMap;
+
+ static inline void destroyWidgetMap()
+ {
+ cleanupGtkWidgets();
+ delete widgetMap;
+ widgetMap = 0;
+ }
static inline WidgetMap *gtkWidgetMap()
{
- static WidgetMap *map = 0;
- if (!map)
- map = new WidgetMap();
- return map;
+ if (!widgetMap) {
+ widgetMap = new WidgetMap();
+ qAddPostRoutine(destroyWidgetMap);
+ }
+ return widgetMap;
}
static QStringList extract_filter(const QString &rawFilter);
@@ -443,6 +507,7 @@ protected:
private:
static QList<QGtkStylePrivate *> instances;
+ static WidgetMap *widgetMap;
friend class QGtkStyleUpdateScheduler;
};
diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm
index 116b03e..074dd89 100644
--- a/src/gui/styles/qmacstyle_mac.mm
+++ b/src/gui/styles/qmacstyle_mac.mm
@@ -237,12 +237,14 @@ void drawTabShape(QPainter *p, const QStyleOptionTabV3 *tabOpt)
// fill body
if (active) {
- p->fillRect(rect, QColor(151, 151, 151));
+ int d = (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) ? 16 : 0;
+ p->fillRect(rect, QColor(151 + d, 151 + d, 151 + d));
} else {
+ int d = (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) ? 9 : 0;
QLinearGradient gradient(rect.topLeft(), rect.bottomLeft());
- gradient.setColorAt(0, QColor(207, 207, 207));
- gradient.setColorAt(0.5, QColor(206, 206, 206));
- gradient.setColorAt(1, QColor(201, 201, 201));
+ gradient.setColorAt(0, QColor(207 + d, 207 + d, 207 + d));
+ gradient.setColorAt(0.5, QColor(206 + d, 206 + d, 206 + d));
+ gradient.setColorAt(1, QColor(201 + d, 201 + d, 201 + d));
p->fillRect(rect, gradient);
}
@@ -432,13 +434,13 @@ static inline bool isTreeView(const QWidget *widget)
QString qt_mac_removeMnemonics(const QString &original)
{
- // copied from qt_format_text (to be bug-for-bug compatible).
QString returnText(original.size(), 0);
int finalDest = 0;
int currPos = 0;
int l = original.length();
while (l) {
- if (original.at(currPos) == QLatin1Char('&')) {
+ if (original.at(currPos) == QLatin1Char('&')
+ && (l == 1 || original.at(currPos + 1) != QLatin1Char('&'))) {
++currPos;
--l;
if (l == 0)
diff --git a/src/gui/styles/qplastiquestyle.cpp b/src/gui/styles/qplastiquestyle.cpp
index 9f69fd8..fbb5e4d 100644
--- a/src/gui/styles/qplastiquestyle.cpp
+++ b/src/gui/styles/qplastiquestyle.cpp
@@ -56,7 +56,6 @@ static const int blueFrameWidth = 2; // with of line edit focus frame
#include <qabstractitemview.h>
#include <qcheckbox.h>
#include <qcombobox.h>
-#include <qdatetime.h>
#include <qdebug.h>
#include <qdialogbuttonbox.h>
#include <qformlayout.h>
@@ -81,6 +80,7 @@ static const int blueFrameWidth = 2; // with of line edit focus frame
#include <qsplitter.h>
#include <qstyleoption.h>
#include <qtextedit.h>
+#include <qelapsedtimer.h>
#include <qtoolbar.h>
#include <qtoolbox.h>
#include <qtoolbutton.h>
@@ -980,7 +980,7 @@ public:
#ifndef QT_NO_PROGRESSBAR
QList<QProgressBar *> bars;
int progressBarAnimateTimer;
- QTime timer;
+ QElapsedTimer timer;
#endif
};
@@ -5846,7 +5846,6 @@ void QPlastiqueStyle::polish(QApplication *app)
void QPlastiqueStyle::polish(QPalette &pal)
{
QWindowsStyle::polish(pal);
- pal.setBrush(QPalette::AlternateBase, pal.base().color().darker(110));
#ifdef Q_WS_MAC
pal.setBrush(QPalette::Shadow, Qt::black);
#endif
diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp
index 565cc2c..f49acc4 100644
--- a/src/gui/styles/qs60style.cpp
+++ b/src/gui/styles/qs60style.cpp
@@ -50,6 +50,7 @@
#include "qcalendarwidget.h"
#include "qdial.h"
#include "qdialog.h"
+#include "qmessagebox.h"
#include "qgroupbox.h"
#include "qheaderview.h"
#include "qlist.h"
@@ -61,7 +62,6 @@
#include "qscrollarea.h"
#include "qscrollbar.h"
#include "qtabbar.h"
-#include "qtablewidget.h"
#include "qtableview.h"
#include "qtextedit.h"
#include "qtoolbar.h"
@@ -92,10 +92,10 @@ static const qreal goldenRatio = 1.618;
const layoutHeader QS60StylePrivate::m_layoutHeaders[] = {
// *** generated layout data ***
-{240,320,1,16,"QVGA Landscape"},
-{320,240,1,16,"QVGA Portrait"},
-{360,640,1,16,"NHD Landscape"},
-{640,360,1,16,"NHD Portrait"},
+{240,320,1,17,"QVGA Landscape"},
+{320,240,1,17,"QVGA Portrait"},
+{360,640,1,17,"NHD Landscape"},
+{640,360,1,17,"NHD Portrait"},
{352,800,1,12,"E90 Landscape"}
// *** End of generated data ***
};
@@ -104,11 +104,11 @@ const int QS60StylePrivate::m_numberOfLayouts =
const short QS60StylePrivate::data[][MAX_PIXELMETRICS] = {
// *** generated pixel metrics ***
-{5,0,-909,0,0,2,0,0,-1,7,12,19,13,13,6,200,-909,-909,-909,20,13,2,0,0,21,7,18,-909,3,3,1,-909,-909,0,1,0,0,12,20,15,15,18,18,1,115,18,0,-909,-909,-909,-909,0,0,16,2,-909,0,0,-909,16,-909,-909,-909,-909,32,18,55,24,55,4,4,4,9,13,-909,5,51,11,5,0,3,3,6,8,3,3,-909,2,-909,-909,-909,-909,5,5,3,1},
-{5,0,-909,0,0,1,0,0,-1,8,14,22,15,15,7,164,-909,-909,-909,19,15,2,0,0,21,8,27,-909,4,4,1,-909,-909,0,7,6,0,13,23,17,17,21,21,7,115,21,0,-909,-909,-909,-909,0,0,15,1,-909,0,0,-909,15,-909,-909,-909,-909,32,21,65,27,65,3,3,5,10,15,-909,5,58,13,5,0,4,4,7,9,4,4,-909,2,-909,-909,-909,-909,6,6,3,1},
-{7,0,-909,0,0,2,0,0,-1,25,69,28,19,19,9,258,-909,-909,-909,23,19,26,0,0,32,25,72,-909,5,5,2,-909,-909,0,7,21,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,25,2,-909,0,0,-909,25,-909,-909,-909,-909,87,27,77,35,77,13,13,6,8,19,-909,7,74,19,7,0,5,5,8,12,5,5,-909,3,-909,-909,-909,-909,7,7,3,1},
-{7,0,-909,0,0,2,0,0,-1,25,68,28,19,19,9,258,-909,-909,-909,31,19,6,0,0,32,25,60,-909,5,5,2,-909,-909,0,7,32,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,26,2,-909,0,0,-909,26,-909,-909,-909,-909,87,27,96,35,96,12,12,6,8,19,-909,7,74,22,7,0,5,5,8,12,5,5,-909,3,-909,-909,-909,-909,7,7,3,1},
-{7,0,-909,0,0,2,0,0,-1,10,20,27,18,18,9,301,-909,-909,-909,29,18,5,0,0,35,7,32,-909,5,5,2,-909,-909,0,2,8,0,16,28,21,21,26,26,2,170,26,0,-909,-909,-909,-909,0,0,21,6,-909,0,0,-909,-909,-909,-909,-909,-909,54,26,265,34,265,5,5,6,3,18,-909,7,72,19,7,0,5,6,8,11,6,5,-909,2,-909,-909,-909,-909,5,5,3,1}
+{5,0,-909,0,0,2,0,0,-1,7,12,19,13,13,6,200,-909,-909,-909,20,13,2,0,0,21,7,18,0,3,3,1,-909,-909,0,1,0,0,12,20,15,15,18,18,1,115,18,0,-909,-909,-909,-909,0,0,16,2,-909,0,0,-909,16,-909,-909,-909,-909,32,18,55,24,55,4,4,4,9,13,-909,5,51,11,5,0,3,3,6,8,3,3,-909,2,-909,-909,-909,-909,5,5,3,1, 106},
+{5,0,-909,0,0,1,0,0,-1,8,14,22,15,15,7,164,-909,-909,-909,19,15,2,0,0,21,8,27,0,4,4,1,-909,-909,0,7,6,0,13,23,17,17,21,21,7,115,21,0,-909,-909,-909,-909,0,0,15,1,-909,0,0,-909,15,-909,-909,-909,-909,32,21,65,27,65,3,3,5,10,15,-909,5,58,13,5,0,4,4,7,9,4,4,-909,2,-909,-909,-909,-909,6,6,3,1, 106},
+{7,0,-909,0,0,2,0,0,-1,25,69,28,19,19,9,258,-909,-909,-909,23,19,26,0,0,32,25,72,0,5,5,2,-909,-909,0,7,21,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,25,2,-909,0,0,-909,25,-909,-909,-909,-909,87,27,77,35,77,13,13,6,8,19,-909,7,74,19,7,0,5,5,8,12,5,5,-909,3,-909,-909,-909,-909,7,7,3,1, 135},
+{7,0,-909,0,0,2,0,0,-1,25,68,28,19,19,9,258,-909,-909,-909,31,19,6,0,0,32,25,60,0,5,5,2,-909,-909,0,7,32,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,26,2,-909,0,0,-909,26,-909,-909,-909,-909,87,27,96,35,96,12,12,6,8,19,-909,7,74,22,7,0,5,5,8,12,5,5,-909,3,-909,-909,-909,-909,7,7,3,1, 135},
+{7,0,-909,0,0,2,0,0,-1,10,20,27,18,18,9,301,-909,-909,-909,29,18,5,0,0,35,7,32,0,5,5,2,-909,-909,0,2,8,0,16,28,21,21,26,26,2,170,26,0,-909,-909,-909,-909,0,0,21,6,-909,0,0,-909,-909,-909,-909,-909,-909,54,26,265,34,265,5,5,6,3,18,-909,7,72,19,7,0,5,6,8,11,6,5,-909,2,-909,-909,-909,-909,5,5,3,1, 106}
// *** End of generated data ***
};
@@ -127,7 +127,7 @@ const struct QS60StylePrivate::frameElementCenter QS60StylePrivate::m_frameEleme
{SE_ButtonPressed, QS60StyleEnums::SP_QsnFrButtonTbCenterPressed},
{SE_FrameLineEdit, QS60StyleEnums::SP_QsnFrInputCenter},
{SE_ListHighlight, QS60StyleEnums::SP_QsnFrListCenter},
- {SE_OptionsMenu, QS60StyleEnums::SP_QsnFrPopupCenter},
+ {SE_PopupBackground, QS60StyleEnums::SP_QsnFrPopupCenter},
{SE_SettingsList, QS60StyleEnums::SP_QsnFrSetOptCenter},
{SE_TableItem, QS60StyleEnums::SP_QsnFrCaleCenter},
{SE_TableHeaderItem, QS60StyleEnums::SP_QsnFrCaleHeadingCenter},
@@ -250,8 +250,8 @@ void QS60StylePrivate::drawSkinElement(SkinElements element, QPainter *painter,
case SE_ListHighlight:
drawFrame(SF_ListHighlight, painter, rect, flags | SF_PointNorth);
break;
- case SE_OptionsMenu:
- drawFrame(SF_OptionsMenu, painter, rect, flags | SF_PointNorth);
+ case SE_PopupBackground:
+ drawFrame(SF_PopupBackground, painter, rect, flags | SF_PointNorth);
break;
case SE_SettingsList:
drawFrame(SF_SettingsList, painter, rect, flags | SF_PointNorth);
@@ -307,6 +307,13 @@ void QS60StylePrivate::drawSkinPart(QS60StyleEnums::SkinParts part,
short QS60StylePrivate::pixelMetric(int metric)
{
+ //If it is a custom value, need to strip away the base to map to internal
+ //pixel metric value table
+ if (metric & QStyle::PM_CustomBase) {
+ metric -= QStyle::PM_CustomBase;
+ metric += MAX_NON_CUSTOM_PIXELMETRICS - 1;
+ }
+
Q_ASSERT(metric < MAX_PIXELMETRICS);
const short returnValue = m_pmPointer[metric];
return returnValue;
@@ -407,8 +414,8 @@ QColor QS60StylePrivate::colorFromFrameGraphics(SkinFrameElements frame) const
{
const bool cachedColorExists = m_colorCache.contains(frame);
if (!cachedColorExists) {
- const int frameCornerWidth = pixelMetric(PM_Custom_FrameCornerWidth);
- const int frameCornerHeight = pixelMetric(PM_Custom_FrameCornerHeight);
+ const int frameCornerWidth = pixelMetric(PM_FrameCornerWidth);
+ const int frameCornerHeight = pixelMetric(PM_FrameCornerHeight);
Q_ASSERT(2 * frameCornerWidth < 32);
Q_ASSERT(2 * frameCornerHeight < 32);
@@ -630,6 +637,8 @@ void QS60StylePrivate::setFont(QWidget *widget) const
fontCategory = QS60StyleEnums::FC_Secondary;
} else if (qobject_cast<QGroupBox *>(widget)){
fontCategory = QS60StyleEnums::FC_Title;
+ } else if (qobject_cast<QMessageBox *>(widget)){
+ fontCategory = QS60StyleEnums::FC_Primary;
}
if (fontCategory != QS60StyleEnums::FC_Undefined) {
const bool resolveFontSize = widget->testAttribute(Qt::WA_SetFont)
@@ -759,13 +768,29 @@ void QS60StylePrivate::setThemePaletteHash(QPalette *palette) const
QApplication::setPalette(widgetPalette, "QMenuBar");
widgetPalette = *palette;
+ widgetPalette.setColor(QPalette::Text,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 22, 0));
+ widgetPalette.setColor(QPalette::HighlightedText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 11, 0));
+ QApplication::setPalette(widgetPalette, "QMenu");
+ widgetPalette = *palette;
+
widgetPalette.setColor(QPalette::WindowText,
s60Color(QS60StyleEnums::CL_QsnTextColors, 4, 0));
+ widgetPalette.setColor(QPalette::HighlightedText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 3, 0));
QApplication::setPalette(widgetPalette, "QTabBar");
widgetPalette = *palette;
+ widgetPalette.setColor(QPalette::HighlightedText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 10, 0));
+ QApplication::setPalette(widgetPalette, "QListView");
+ widgetPalette = *palette;
+
widgetPalette.setColor(QPalette::Text,
s60Color(QS60StyleEnums::CL_QsnTextColors, 22, 0));
+ widgetPalette.setColor(QPalette::HighlightedText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 11, 0));
QApplication::setPalette(widgetPalette, "QTableView");
widgetPalette = *palette;
@@ -789,6 +814,8 @@ void QS60StylePrivate::setThemePaletteHash(QPalette *palette) const
widgetPalette = *palette;
widgetPalette.setColor(QPalette::WindowText, s60Color(QS60StyleEnums::CL_QsnTextColors, 7, 0));
+ widgetPalette.setColor(QPalette::HighlightedText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 11, 0));
QApplication::setPalette(widgetPalette, "QRadioButton");
QApplication::setPalette(widgetPalette, "QCheckBox");
widgetPalette = *palette;
@@ -850,7 +877,7 @@ QSize QS60StylePrivate::partSize(QS60StyleEnums::SkinParts part, SkinElementFlag
case QS60StyleEnums::SP_QgnGrafBarFrameSideL:
case QS60StyleEnums::SP_QgnGrafBarFrameSideR:
- result.setWidth(pixelMetric(PM_Custom_FrameCornerWidth));
+ result.setWidth(pixelMetric(PM_FrameCornerWidth));
break;
case QS60StyleEnums::SP_QsnCpScrollHandleTopPressed:
@@ -877,15 +904,15 @@ QSize QS60StylePrivate::partSize(QS60StyleEnums::SkinParts part, SkinElementFlag
case 7: /* CornerTr */
case 6: /* CornerBl */
case 5: /* CornerBr */
- result.setWidth(pixelMetric(PM_Custom_FrameCornerWidth));
+ result.setWidth(pixelMetric(PM_FrameCornerWidth));
// Falltrough intended...
case 4: /* SideT */
case 3: /* SideB */
- result.setHeight(pixelMetric(PM_Custom_FrameCornerHeight));
+ result.setHeight(pixelMetric(PM_FrameCornerHeight));
break;
case 2: /* SideL */
case 1: /* SideR */
- result.setWidth(pixelMetric(PM_Custom_FrameCornerWidth));
+ result.setWidth(pixelMetric(PM_FrameCornerWidth));
break;
case 0: /* center */
default:
@@ -984,7 +1011,6 @@ void QS60Style::drawComplexControl(ComplexControl control, const QStyleOptionCom
QS60StylePrivate::SE_SliderGrooveVertical;
QS60StylePrivate::drawSkinElement(grooveElement, painter, sliderGroove, flags);
} else {
- const QRect sliderGroove = subControlRect(control, optionSlider, SC_SliderGroove, widget);
const QPoint sliderGrooveCenter = sliderGroove.center();
const bool horizontal = optionSlider->orientation == Qt::Horizontal;
painter->save();
@@ -1111,7 +1137,7 @@ void QS60Style::drawComplexControl(ComplexControl control, const QStyleOptionCom
drawPrimitive(pe, &toolButton, painter, widget);
}
- if (toolBtn->text.length()>0 ||
+ if (toolBtn->text.length() > 0 ||
!toolBtn->icon.isNull()) {
const int frameWidth = pixelMetric(PM_DefaultFrameWidth, option, widget);
toolButton.rect = button.adjusted(frameWidth, frameWidth, -frameWidth, -frameWidth);
@@ -1241,6 +1267,8 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option,
case CE_RadioButton:
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
bool isRadio = (element == CE_RadioButton);
+ QStyleOptionButton subopt = *btn;
+
// Highlight needs to be drawn first, as it goes "underneath" the text and indicator.
if (btn->state & State_HasFocus) {
QStyleOptionFocusRect fropt;
@@ -1248,8 +1276,10 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option,
fropt.rect = subElementRect(isRadio ? SE_RadioButtonFocusRect
: SE_CheckBoxFocusRect, btn, widget);
drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
+
+ subopt.palette.setColor(QPalette::Active, QPalette::WindowText,
+ subopt.palette.highlightedText().color());
}
- QStyleOptionButton subopt = *btn;
subopt.rect = subElementRect(isRadio ? SE_RadioButtonIndicator
: SE_CheckBoxIndicator, btn, widget);
@@ -1349,7 +1379,7 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option,
}
if (!comboBox->currentText.isEmpty() && !comboBox->editable) {
QCommonStyle::drawItemText(painter,
- editRect.adjusted(QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth), 0, -1, 0),
+ editRect.adjusted(QS60StylePrivate::pixelMetric(PM_FrameCornerWidth), 0, -1, 0),
visualAlignment(comboBox->direction, Qt::AlignLeft | Qt::AlignVCenter),
comboBox->palette, comboBox->state & State_Enabled, comboBox->currentText);
}
@@ -1408,7 +1438,7 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option,
} else { QCommonStyle::drawPrimitive(PE_PanelItemViewItem, &voptAdj, painter, widget);}
// draw the focus rect
- if (isSelected | hasFocus) {
+ if (isSelected || hasFocus ) {
QRect highlightRect = option->rect.adjusted(1,1,-1,-1);
QAbstractItemView::SelectionBehavior selectionBehavior =
itemView ? itemView->selectionBehavior() : QAbstractItemView::SelectItems;
@@ -1480,15 +1510,10 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option,
// draw the text
if (!voptAdj.text.isEmpty()) {
- if (isSelected) {
- if (qobject_cast<const QTableView *>(widget))
- voptAdj.palette.setColor(
- QPalette::Text, QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 11, 0));
- else
- voptAdj.palette.setColor(
- QPalette::Text, QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 10, 0));
- }
- painter->setPen(voptAdj.palette.text().color());
+ if (isSelected || hasFocus )
+ painter->setPen(voptAdj.palette.highlightedText().color());
+ else
+ painter->setPen(voptAdj.palette.text().color());
d->viewItemDrawText(painter, &voptAdj, textRect);
}
painter->restore();
@@ -1590,7 +1615,7 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option,
const bool selected = optionTab.state & State_Selected;
if (selected)
optionTab.palette.setColor(QPalette::Active, QPalette::WindowText,
- QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 3, option));
+ optionTab.palette.highlightedText().color());
const bool verticalTabs = optionTab.shape == QTabBar::RoundedEast
|| optionTab.shape == QTabBar::RoundedWest
@@ -1723,7 +1748,8 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option,
if (!styleHint(SH_UnderlineShortcut, menuItem, widget))
text_flags |= Qt::TextHideMnemonic;
- if ((option->state & State_Selected) && (option->state & State_Enabled))
+ const bool selected = (option->state & State_Selected) && (option->state & State_Enabled);
+ if (selected)
QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ListHighlight, painter, option->rect, flags);
QRect iconRect = subElementRect(SE_ItemViewItemDecoration, &optionMenuItem, widget);
@@ -1793,6 +1819,10 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option,
painter->save();
painter->setOpacity(0.5);
}
+ if (selected)
+ optionMenuItem.palette.setColor(
+ QPalette::Active, QPalette::Text, optionMenuItem.palette.highlightedText().color());
+
QCommonStyle::drawItemText(painter, textRect, text_flags,
optionMenuItem.palette, enabled,
optionMenuItem.text, QPalette::Text);
@@ -1814,8 +1844,8 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option,
painter->save();
QPen linePen = QPen(QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnLineColors, 1, header));
const int penWidth = (header->orientation == Qt::Horizontal) ?
- linePen.width() + QS60StylePrivate::pixelMetric(PM_Custom_BoldLineWidth)
- : linePen.width() + QS60StylePrivate::pixelMetric(PM_Custom_ThinLineWidth);
+ linePen.width() + QS60StylePrivate::pixelMetric(PM_BoldLineWidth)
+ : linePen.width() + QS60StylePrivate::pixelMetric(PM_ThinLineWidth);
linePen.setWidth(penWidth);
painter->setPen(linePen);
if (header->orientation == Qt::Horizontal){
@@ -1834,7 +1864,7 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option,
//Make cornerButton slightly smaller so that it is not on top of table border graphic.
QStyleOptionHeader subopt = *header;
const int borderTweak =
- QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth) >> 1;
+ QS60StylePrivate::pixelMetric(PM_FrameCornerWidth) >> 1;
if (subopt.direction == Qt::LeftToRight)
subopt.rect.adjust(borderTweak, borderTweak, 0, -borderTweak);
else
@@ -1942,40 +1972,37 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option,
case CE_MenuScroller:
break;
case CE_FocusFrame: {
- // The pen width should nearly fill the layoutspacings around the widget
- const int penWidth =
- qMin(pixelMetric(QS60Style::PM_LayoutVerticalSpacing), pixelMetric(QS60Style::PM_LayoutHorizontalSpacing))
- - 2; // But keep 1 pixel distance to the focus widget and 1 pixel to the adjacent widgets
-
#ifdef QT_KEYPAD_NAVIGATION
bool editFocus = false;
if (const QFocusFrame *focusFrame = qobject_cast<const QFocusFrame*>(widget)) {
if (focusFrame->widget() && focusFrame->widget()->hasEditFocus())
editFocus = true;
}
- const qreal opacity = editFocus ? 0.65 : 0.45; // Trial and error factors. Feel free to improve.
+ const qreal opacity = editFocus ? 1 : 0.75; // Trial and error factors. Feel free to improve.
#else
- const qreal opacity = 0.5;
+ const qreal opacity = 0.85;
#endif
- // Because of Qts coordinate system, we need to tweak the rect by .5 pixels, otherwise it gets blurred.
- const qreal rectAdjustment = (penWidth % 2) ? -.5 : 0;
-
- // Make sure that the pen stroke is inside the rect
- const QRectF adjustedRect =
- QRectF(option->rect).adjusted(
- rectAdjustment + penWidth,
- rectAdjustment + penWidth,
- -rectAdjustment - penWidth,
- -rectAdjustment - penWidth
- );
-
- const qreal roundRectRadius = penWidth * goldenRatio;
+ // We need to reduce the focus frame size if LayoutSpacing is smaller than FocusFrameMargin
+ // Otherwise, we would overlay adjacent widgets.
+ const int frameHeightReduction =
+ qMin(0, pixelMetric(QStyle::PM_LayoutVerticalSpacing)
+ - pixelMetric(QStyle::PM_FocusFrameVMargin));
+ const int frameWidthReduction =
+ qMin(0, pixelMetric(QStyle::PM_LayoutHorizontalSpacing)
+ - pixelMetric(QStyle::PM_FocusFrameHMargin));
+ const int rounding =
+ qMin(pixelMetric(QStyle::PM_FocusFrameVMargin),
+ pixelMetric(QStyle::PM_LayoutVerticalSpacing));
+ const QRect frameRect =
+ option->rect.adjusted(-frameWidthReduction, -frameHeightReduction,
+ frameWidthReduction, frameHeightReduction);
+ QPainterPath framePath;
+ framePath.addRoundedRect(frameRect, rounding, rounding);
painter->save();
painter->setRenderHint(QPainter::Antialiasing);
painter->setOpacity(opacity);
- painter->setPen(QPen(option->palette.color(QPalette::Text), penWidth));
- painter->drawRoundedRect(adjustedRect, roundRectRadius, roundRectRadius);
+ painter->fillPath(framePath, option->palette.color(QPalette::Text));
painter->restore();
}
break;
@@ -2047,18 +2074,18 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti
break;
case PE_IndicatorViewItemCheck:
#ifndef QT_NO_ITEMVIEWS
- if (const QListView *listItem = (qobject_cast<const QListView *>(widget))) {
+ if (const QAbstractItemView *itemView = (qobject_cast<const QAbstractItemView *>(widget))) {
if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option)) {
const bool checkBoxVisible = vopt->features & QStyleOptionViewItemV2::HasCheckIndicator;
- const bool singleSelection = listItem->selectionMode() ==
- QAbstractItemView::SingleSelection || listItem->selectionMode() == QAbstractItemView::NoSelection;
+ const bool singleSelection = itemView->selectionMode() ==
+ QAbstractItemView::SingleSelection || itemView->selectionMode() == QAbstractItemView::NoSelection;
// draw either checkbox at the beginning
if (checkBoxVisible && singleSelection) {
drawPrimitive(PE_IndicatorCheckBox, option, painter, widget);
// ... or normal "tick" selection at the end.
} else if (option->state & State_Selected) {
QRect tickRect = option->rect;
- const int frameBorderWidth = QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth);
+ const int frameBorderWidth = QS60StylePrivate::pixelMetric(PM_FrameCornerWidth);
// adjust tickmark rect to exclude frame border
tickRect.adjust(0, -frameBorderWidth, 0, -frameBorderWidth);
QS60StyleEnums::SkinParts skinPart = QS60StyleEnums::SP_QgnIndiMarkedAdd;
@@ -2139,7 +2166,7 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti
const QS60StyleEnums::SkinParts part = (element == PE_IndicatorSpinUp) ?
QS60StyleEnums::SP_QgnGrafScrollArrowUp :
QS60StyleEnums::SP_QgnGrafScrollArrowDown;
- const int iconMargin = QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth) >> 1;
+ const int iconMargin = QS60StylePrivate::pixelMetric(PM_FrameCornerWidth) >> 1;
optionSpinBox.rect.translate(0, (element == PE_IndicatorSpinDown) ? iconMargin : -iconMargin );
QS60StylePrivate::drawSkinPart(part, painter, optionSpinBox.rect, flags);
} else {
@@ -2153,7 +2180,7 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti
// We want to draw down arrow here for comboboxes as well.
QStyleOptionFrame optionsComboBox = *cmb;
const QS60StyleEnums::SkinParts part = QS60StyleEnums::SP_QgnGrafScrollArrowDown;
- const int iconMargin = QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth) >> 1;
+ const int iconMargin = QS60StylePrivate::pixelMetric(PM_FrameCornerWidth) >> 1;
optionsComboBox.rect.translate(0, (element == PE_IndicatorSpinDown) ? iconMargin : -iconMargin );
QS60StylePrivate::drawSkinPart(part, painter, optionsComboBox.rect, flags);
} else {
@@ -2191,7 +2218,7 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti
if (QS60StylePrivate::canDrawThemeBackground(option->palette.base(), widget) &&
option->palette.window().texture().cacheKey() ==
QS60StylePrivate::m_themePalette->window().texture().cacheKey())
- QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_OptionsMenu, painter, option->rect, flags);
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_PopupBackground, painter, option->rect, flags);
else
commonStyleDraws = true;
}
@@ -2287,7 +2314,7 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti
(option->state & State_Open) ? QS60StyleEnums::SP_QgnIndiHlColSuper : QS60StyleEnums::SP_QgnIndiHlExpSuper;
int minDimension = qMin(option->rect.width(), option->rect.height());
QRect iconRect(option->rect.topLeft(), QSize(minDimension, minDimension));
- const int magicTweak = 3;
+ const int magicTweak = 3;
int resizeValue = minDimension >> 1;
if (!QS60StylePrivate::isTouchSupported()) {
minDimension += resizeValue; // Adjust the icon bigger because of empty space in svg icon.
@@ -2362,13 +2389,6 @@ int QS60Style::pixelMetric(PixelMetric metric, const QStyleOption *option, const
if (metricValue == KNotFound)
metricValue = QCommonStyle::pixelMetric(metric, option, widget);
- if (metric == PM_SubMenuOverlap && widget) {
- const QMenu *menu = qobject_cast<const QMenu *>(widget);
- if (menu && menu->activeAction() && menu->activeAction()->menu()) {
- const int menuWidth = menu->activeAction()->menu()->sizeHint().width();
- metricValue = -menuWidth;
- }
- }
//if layout direction is mirrored, switch left and right border margins
if (option && option->direction == Qt::RightToLeft) {
if (metric == PM_LayoutLeftMargin)
@@ -2376,6 +2396,12 @@ int QS60Style::pixelMetric(PixelMetric metric, const QStyleOption *option, const
else if (metric == PM_LayoutRightMargin)
metricValue = QS60StylePrivate::pixelMetric(PM_LayoutLeftMargin);
}
+
+ if (widget && (metric == PM_LayoutTopMargin))
+ if (widget->windowType() == Qt::Dialog)
+ //double the top layout margin for dialogs, it is very close to real value
+ //without having to define custom pixel metric
+ metricValue *= 2;
return metricValue;
}
@@ -2407,7 +2433,7 @@ QSize QS60Style::sizeFromContents(ContentsType ct, const QStyleOption *opt,
const int contentHeight =
qMax(qMax(iconHeight, decoratorHeight) + pixelMetric(PM_ButtonMargin),
textHeight + 2*pixelMetric(PM_ButtonMargin));
- sz.setHeight(contentHeight);
+ sz.setHeight(qMax(sz.height(), contentHeight));
sz += QSize(2 * pixelMetric(PM_ButtonMargin), 0);
}
break;
@@ -2432,9 +2458,9 @@ QSize QS60Style::sizeFromContents(ContentsType ct, const QStyleOption *opt,
#ifndef QT_NO_COMBOBOX
case CT_ComboBox: {
// Fixing Ui design issues with too wide QComboBoxes and greedy SizeHints
- // Make sure, that the combobox says within the screen.
+ // Make sure, that the combobox stays within the screen.
const QSize desktopContentSize = QApplication::desktop()->availableGeometry().size()
- -QSize(pixelMetric(PM_LayoutLeftMargin) + pixelMetric(PM_LayoutRightMargin), 0);
+ - QSize(pixelMetric(PM_LayoutLeftMargin) + pixelMetric(PM_LayoutRightMargin), 0);
sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget).
boundedTo(desktopContentSize);
}
@@ -2453,6 +2479,15 @@ int QS60Style::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w
{
int retValue = -1;
switch (sh) {
+ case SH_RequestSoftwareInputPanel:
+ if (QS60StylePrivate::isSingleClickUi())
+ retValue = RSIP_OnMouseClick;
+ else
+ retValue = RSIP_OnMouseClickAndAlreadyFocused;
+ break;
+ case SH_ComboBox_Popup:
+ retValue = true;
+ break;
case SH_Table_GridLineColor:
retValue = int(QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnLineColors, 2, 0).rgba());
break;
@@ -2506,9 +2541,6 @@ int QS60Style::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w
case SH_UnderlineShortcut:
retValue = 0;
break;
- case SH_RequestSoftwareInputPanel:
- retValue = RSIP_OnMouseClickAndAlreadyFocused;
- break;
case SH_FormLayoutWrapPolicy:
retValue = QFormLayout::WrapLongRows;
break;
@@ -2594,14 +2626,22 @@ QRect QS60Style::subControlRect(ComplexControl control, const QStyleOptionComple
const int frameThickness = spinbox->frame ? pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0;
const int buttonMargin = spinbox->frame ? 2 : 0;
const int buttonContentWidth = QS60StylePrivate::pixelMetric(PM_ButtonIconSize) + 2 * buttonMargin;
+ // Spinbox buttons should be no larger than one fourth of total width.
+ // Thus, side-by-side buttons would take half of the total width.
+ const int maxSize = qMax(spinbox->rect.width() / 4, buttonContentWidth);
QSize buttonSize;
- buttonSize.setHeight(qMax(8, spinbox->rect.height() - frameThickness));
+ buttonSize.setHeight(qMin(maxSize, qMax(8, spinbox->rect.height() - frameThickness)));
//width should at least be equal to height
buttonSize.setWidth(qMax(buttonSize.height(), buttonContentWidth));
buttonSize = buttonSize.expandedTo(QApplication::globalStrut());
- const int y = frameThickness + spinbox->rect.y();
- const int x = spinbox->rect.x() + spinbox->rect.width() - frameThickness - 2 * buttonSize.width();
+ // Normally spinbuttons should be side-by-side, but if spinbox grows very big
+ // and spinbuttons reach their maximum size, they can be deployed one top of the other.
+ const bool sideBySide = (buttonSize.height() * 2 < spinbox->rect.height()) ? false : true;
+ const int y = frameThickness + spinbox->rect.y() +
+ (spinbox->rect.height() - (sideBySide ? 1 : 2) * buttonSize.height()) / 2;
+ const int x = spinbox->rect.x() +
+ spinbox->rect.width() - frameThickness - (sideBySide ? 2 : 1) * buttonSize.width();
switch (scontrol) {
case SC_SpinBoxUp:
@@ -2612,7 +2652,9 @@ QRect QS60Style::subControlRect(ComplexControl control, const QStyleOptionComple
case SC_SpinBoxDown:
if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
return QRect();
- ret = QRect(x + buttonSize.width(), y, buttonSize.width(), buttonSize.height());
+ ret = QRect(x + (sideBySide ? buttonSize.width() : 0),
+ y + (sideBySide ? 0 : buttonSize.height()),
+ buttonSize.width(), buttonSize.height());
break;
case SC_SpinBoxEditField:
if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
@@ -2668,6 +2710,19 @@ QRect QS60Style::subControlRect(ComplexControl control, const QStyleOptionComple
height - 2 * frameThickness);
}
break;
+ case SC_ComboBoxListBoxPopup: {
+ const QRect desktopContent = QApplication::desktop()->availableGeometry();
+
+ // take the size of this and position bottom above available area
+ QRect popupRect;
+ const int width = desktopContent.width() - pixelMetric(PM_LayoutRightMargin) - pixelMetric(PM_LayoutLeftMargin);
+ popupRect.setWidth(width);
+ popupRect.setHeight(desktopContent.height()); //combobox resets height anyway based on content
+ popupRect.setBottom(desktopContent.bottom());
+ popupRect.translate(pixelMetric(PM_LayoutLeftMargin), 0);
+ ret = popupRect;
+ }
+ break;
default:
break;
}
@@ -2742,11 +2797,10 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con
break;
case SE_LineEditContents: {
// in S60 the input text box doesn't start from line Edit's TL, but
- // a bit indented.
- QRect lineEditRect = opt->rect;
- const int adjustment = opt->rect.height() >> 2;
- lineEditRect.adjust(adjustment, 0, 0, 0);
- ret = lineEditRect;
+ // a bit indented (8 pixels).
+ const int KLineEditDefaultIndention = 8;
+ ret = visualRect(
+ opt->direction, opt->rect, opt->rect.adjusted(KLineEditDefaultIndention, 0, 0, 0));
}
break;
case SE_TabBarTearIndicator:
@@ -2822,9 +2876,13 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con
ret = menuItem->rect;
if (element == SE_ItemViewItemDecoration) {
- if (menuItem->direction == Qt::RightToLeft)
- ret.translate(ret.width()-indicatorWidth, 0);
- ret.setWidth(indicatorWidth);
+ if (menuItem->icon.isNull()) {
+ ret = QRect();
+ } else {
+ if (menuItem->direction == Qt::RightToLeft)
+ ret.translate(ret.width()-indicatorWidth, 0);
+ ret.setWidth(indicatorWidth);
+ }
} else {
ret = menuItem->rect;
if (!menuItem->icon.isNull())
@@ -2884,9 +2942,9 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con
if (qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
// Subtract area needed for line
if (opt->state & State_Horizontal)
- ret.setHeight(ret.height() - QS60StylePrivate::pixelMetric(PM_Custom_BoldLineWidth));
+ ret.setHeight(ret.height() - QS60StylePrivate::pixelMetric(PM_BoldLineWidth));
else
- ret.setWidth(ret.width() - QS60StylePrivate::pixelMetric(PM_Custom_ThinLineWidth));
+ ret.setWidth(ret.width() - QS60StylePrivate::pixelMetric(PM_ThinLineWidth));
}
ret = visualRect(opt->direction, opt->rect, ret);
break;
@@ -3197,7 +3255,7 @@ bool QS60Style::eventFilter(QObject *object, QEvent *event)
/*!
\internal
- Handle the timer \a event.
+ Handle the timer \a event.
*/
void QS60Style::timerEvent(QTimerEvent *event)
{
diff --git a/src/gui/styles/qs60style.h b/src/gui/styles/qs60style.h
index 82cc21c..c878538 100644
--- a/src/gui/styles/qs60style.h
+++ b/src/gui/styles/qs60style.h
@@ -52,6 +52,16 @@ QT_MODULE(Gui)
#if !defined(QT_NO_STYLE_S60)
+//Public custom pixel metrics values.
+//These can be used to fetch custom pixel metric value from outside QS60Style.
+enum {
+ PM_FrameCornerWidth = QStyle::PM_CustomBase + 1,
+ PM_FrameCornerHeight,
+ PM_BoldLineWidth,
+ PM_ThinLineWidth,
+ PM_MessageBoxHeight
+ };
+
class QS60StylePrivate;
class Q_GUI_EXPORT QS60Style : public QCommonStyle
diff --git a/src/gui/styles/qs60style_p.h b/src/gui/styles/qs60style_p.h
index 16d82e7..6ce4960 100644
--- a/src/gui/styles/qs60style_p.h
+++ b/src/gui/styles/qs60style_p.h
@@ -60,13 +60,8 @@
QT_BEGIN_NAMESPACE
const int MAX_NON_CUSTOM_PIXELMETRICS = 92;
-const int CUSTOMVALUESCOUNT = 4;
-enum {
- PM_Custom_FrameCornerWidth = MAX_NON_CUSTOM_PIXELMETRICS,
- PM_Custom_FrameCornerHeight,
- PM_Custom_BoldLineWidth,
- PM_Custom_ThinLineWidth
- };
+const int CUSTOMVALUESCOUNT = 5;
+
const int MAX_PIXELMETRICS = MAX_NON_CUSTOM_PIXELMETRICS + CUSTOMVALUESCOUNT;
typedef struct {
@@ -416,7 +411,7 @@ public:
SE_TabBarTabWestActive,
SE_TabBarTabWestInactive,
SE_ListHighlight,
- SE_OptionsMenu,
+ SE_PopupBackground,
SE_SettingsList,
SE_TableItem,
SE_TableHeaderItem,
@@ -425,7 +420,7 @@ public:
SE_ToolBarButton,
SE_ToolBarButtonPressed,
SE_PanelBackground,
- SE_ScrollBarHandlePressedHorizontal, //only for 5.0+
+ SE_ScrollBarHandlePressedHorizontal,
SE_ScrollBarHandlePressedVertical,
SE_ButtonInactive,
SE_Editor,
@@ -437,7 +432,7 @@ public:
SF_ButtonPressed,
SF_FrameLineEdit,
SF_ListHighlight,
- SF_OptionsMenu,
+ SF_PopupBackground,
SF_SettingsList,
SF_TableItem,
SF_TableHeaderItem,
diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp
index cb49fbc..6a552e0 100644
--- a/src/gui/styles/qs60style_s60.cpp
+++ b/src/gui/styles/qs60style_s60.cpp
@@ -50,20 +50,20 @@
#include "qapplication.h"
#include <w32std.h>
-#include <aknsconstants.h>
+#include <AknsConstants.h>
#include <aknconsts.h>
-#include <aknsitemid.h>
-#include <aknsutils.h>
-#include <aknsdrawutils.h>
-#include <aknsskininstance.h>
-#include <aknsbasicbackgroundcontrolcontext.h>
+#include <AknsItemID.h>
+#include <AknsUtils.h>
+#include <AknsDrawUtils.h>
+#include <AknsSkinInstance.h>
+#include <AknsBasicBackgroundControlContext.h>
#include <avkon.mbg>
#include <aknfontaccess.h>
#include <aknlayoutfont.h>
-#include <aknutils.h>
+#include <AknUtils.h>
#include <aknnavi.h>
#include <gulicon.h>
-#include <AknBitmapAnimation.h>
+#include <aknbitmapanimation.h>
#if !defined(QT_NO_STYLE_S60) || defined(QT_PLUGIN)
@@ -755,7 +755,7 @@ QPixmap QS60StyleModeSpecifics::createSkinnedGraphicsLX(
if (drawn)
result = fromFbsBitmap(background, NULL, flags, targetSize);
- // if drawing fails in skin server, just ignore the background (probably OOM occured)
+ // if drawing fails in skin server, just ignore the background (probably OOM case)
CleanupStack::PopAndDestroy(4, background); //background, dev, gc, bgContext
// QS60WindowSurface::lockBitmapHeap();
@@ -787,7 +787,7 @@ QPixmap QS60StyleModeSpecifics::createSkinnedGraphicsLX(
const int currentFrame = QS60StylePrivate::currentAnimationFrame(part);
if (constructedFromTheme && aknAnimation && aknAnimation->BitmapAnimData()->FrameArray().Count() > 0) {
- //Animation was created succesfully and contains frames, just fetch current frame
+ //Animation was created successfully and contains frames, just fetch current frame
if(currentFrame >= aknAnimation->BitmapAnimData()->FrameArray().Count())
User::Leave(KErrOverflow);
const CBitmapFrameData* frameData = aknAnimation->BitmapAnimData()->FrameArray().At(currentFrame);
@@ -859,11 +859,9 @@ QPixmap QS60StyleModeSpecifics::createSkinnedGraphicsLX(QS60StylePrivate::SkinFr
User::LeaveIfError(bitmapDev->CreateContext(bitmapGc));
CleanupStack::PushL(bitmapGc);
-#ifndef Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE
frame->LockHeap();
memset(frame->DataAddress(), 0, frame->SizeInPixels().iWidth * frame->SizeInPixels().iHeight * 4); // 4: argb bytes
frame->UnlockHeap();
-#endif
const TRect outerRect(TPoint(0, 0), targetSize);
const TRect innerRect = innerRectFromElement(frameElement, outerRect);
@@ -978,21 +976,25 @@ void QS60StyleModeSpecifics::frameIdAndCenterId(QS60StylePrivate::SkinFrameEleme
TRect QS60StyleModeSpecifics::innerRectFromElement(QS60StylePrivate::SkinFrameElements frameElement, const TRect &outerRect)
{
- TInt widthShrink = QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth);
- TInt heightShrink = QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerHeight);
+ TInt widthShrink = QS60StylePrivate::pixelMetric(PM_FrameCornerWidth);
+ TInt heightShrink = QS60StylePrivate::pixelMetric(PM_FrameCornerHeight);
switch(frameElement) {
case QS60StylePrivate::SF_PanelBackground:
// panel should have slightly slimmer border to enable thin line of background graphics between closest component
- widthShrink = widthShrink-2;
- heightShrink = heightShrink-2;
+ widthShrink = widthShrink - 2;
+ heightShrink = heightShrink - 2;
break;
case QS60StylePrivate::SF_ToolTip:
- widthShrink = widthShrink>>1;
- heightShrink = heightShrink>>1;
+ widthShrink = widthShrink >> 1;
+ heightShrink = heightShrink >> 1;
break;
case QS60StylePrivate::SF_ListHighlight:
- widthShrink = widthShrink-2;
- heightShrink = heightShrink-2;
+ widthShrink = widthShrink - 2;
+ heightShrink = heightShrink - 2;
+ break;
+ case QS60StylePrivate::SF_PopupBackground:
+ widthShrink = widthShrink + 5;
+ heightShrink = heightShrink + 5;
break;
default:
break;
@@ -1096,7 +1098,7 @@ void QS60StylePrivate::setActiveLayout()
activeLayoutIndex += (!landscape) ? 1 : 0;
}
- m_pmPointer = data[activeLayoutIndex];
+ setCurrentLayout(activeLayoutIndex);
}
Q_GLOBAL_STATIC(QList<QS60StyleAnimation *>, m_animations)
@@ -1121,7 +1123,7 @@ QColor QS60StylePrivate::s60Color(QS60StyleEnums::ColorLists list,
&KAknsIIDQsnParentColors,
&KAknsIIDQsnTextColors
};
- Q_ASSERT((int)list <= (int)sizeof(idMap)/sizeof(idMap[0]));
+ Q_ASSERT((int)list < (int)sizeof(idMap)/sizeof(idMap[0]));
const QColor color = QS60StyleModeSpecifics::colorValue(*idMap[(int) list], index - 1);
return option ? QS60StylePrivate::stateColor(color, option) : color;
}
diff --git a/src/gui/styles/qstylehelper.cpp b/src/gui/styles/qstylehelper.cpp
index 071ec23..296c51c 100644
--- a/src/gui/styles/qstylehelper.cpp
+++ b/src/gui/styles/qstylehelper.cpp
@@ -54,24 +54,71 @@
#include <private/qt_cocoa_helpers_mac_p.h>
#endif
+#include <qstringbuilder.h>
+
QT_BEGIN_NAMESPACE
+// internal helper. Converts an integer value to an unique string token
+template <typename T>
+struct HexString
+{
+ inline HexString(const T t)
+ : val(t)
+ {}
+
+ inline void write(QChar *&dest) const
+ {
+ const ushort hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+ const char *c = reinterpret_cast<const char *>(&val);
+ for (uint i = 0; i < sizeof(T); ++i) {
+ *dest++ = hexChars[*c & 0xf];
+ *dest++ = hexChars[(*c & 0xf0) >> 4];
+ ++c;
+ }
+ }
+
+ const T val;
+};
+
+// specialization to enable fast concatenating of our string tokens to a string
+template <typename T>
+struct QConcatenable<HexString<T> >
+{
+ typedef HexString<T> type;
+ enum { ExactSize = true };
+ static int size(const HexString<T> &str) { return sizeof(str.val) * 2; }
+ static inline void appendTo(const HexString<T> &str, QChar *&out) { str.write(out); }
+};
+
namespace QStyleHelper {
QString uniqueName(const QString &key, const QStyleOption *option, const QSize &size)
{
const QStyleOptionComplex *complexOption = qstyleoption_cast<const QStyleOptionComplex *>(option);
- QString tmp = QString::fromLatin1("%1-%2-%3-%4-%5-%6x%7").arg(key).arg(uint(option->state)).arg(option->direction)
- .arg(complexOption ? uint(complexOption->activeSubControls) : uint(0))
- .arg(option->palette.cacheKey()).arg(size.width()).arg(size.height());
+
+ QString tmp = key
+ % QLatin1Char('-')
+ % HexString<uint>(option->state)
+ % QLatin1Char('-')
+ % HexString<uint>(option->direction)
+ % QLatin1Char('-')
+ % HexString<uint>(complexOption ? uint(complexOption->activeSubControls) : 0u)
+ % QLatin1Char('-')
+ % HexString<quint64>(option->palette.cacheKey())
+ % QLatin1Char('-')
+ % HexString<uint>(size.width())
+ % QLatin1Char('x')
+ % HexString<uint>(size.height());
+
#ifndef QT_NO_SPINBOX
if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
- tmp.append(QLatin1Char('-'));
- tmp.append(QString::number(spinBox->buttonSymbols));
- tmp.append(QLatin1Char('-'));
- tmp.append(QString::number(spinBox->stepEnabled));
- tmp.append(QLatin1Char('-'));
- tmp.append(QLatin1Char(spinBox->frame ? '1' : '0'));
+ tmp = tmp
+ % QLatin1Char('-')
+ % HexString<uint>(spinBox->buttonSymbols)
+ % QLatin1Char('-')
+ % HexString<uint>(spinBox->stepEnabled)
+ % QLatin1Char('-')
+ % QLatin1Char(spinBox->frame ? '1' : '0');
}
#endif // QT_NO_SPINBOX
return tmp;
diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp
index bc1bece..cc0ce08 100644
--- a/src/gui/styles/qstylesheetstyle.cpp
+++ b/src/gui/styles/qstylesheetstyle.cpp
@@ -2541,7 +2541,7 @@ void QStyleSheetStyle::setPalette(QWidget *w)
int state;
QPalette::ColorGroup group;
} map[3] = {
- { PseudoClass_Active | PseudoClass_Enabled, QPalette::Active },
+ { int(PseudoClass_Active | PseudoClass_Enabled), QPalette::Active },
{ PseudoClass_Disabled, QPalette::Disabled },
{ PseudoClass_Enabled, QPalette::Inactive }
};
@@ -3457,10 +3457,17 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
case CE_RadioButton:
case CE_CheckBox:
- rule.drawRule(p, opt->rect);
- ParentStyle::drawControl(ce, opt, p, w);
- return;
-
+ if (rule.hasBox() || !rule.hasNativeBorder() || rule.hasDrawable() || hasStyleRule(w, PseudoElement_Indicator)) {
+ rule.drawRule(p, opt->rect);
+ ParentStyle::drawControl(ce, opt, p, w);
+ return;
+ } else if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
+ QStyleOptionButton butOpt(*btn);
+ rule.configurePalette(&butOpt.palette, QPalette::ButtonText, QPalette::Button);
+ baseStyle()->drawControl(ce, &butOpt, p, w);
+ return;
+ }
+ break;
case CE_RadioButtonLabel:
case CE_CheckBoxLabel:
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
diff --git a/src/gui/styles/qwindowsmobilestyle.cpp b/src/gui/styles/qwindowsmobilestyle.cpp
index a264b1b..5f939d0 100644
--- a/src/gui/styles/qwindowsmobilestyle.cpp
+++ b/src/gui/styles/qwindowsmobilestyle.cpp
@@ -4040,25 +4040,26 @@ enum QSliderDirection { SliderUp, SliderDown, SliderLeft, SliderRight };
void QWindowsMobileStylePrivate::tintImagesButton(QColor color)
{
- if (currentTintButton == color)
+ if (currentTintButton == color)
return;
-
- imageTabEnd = QImage(tabend_xpm);
- imageTabSelectedEnd = QImage(tabselectedend_xpm);
- imageTabSelectedBegin = QImage(tabselectedbeginn_xpm);
- imageTabMiddle = QImage(tabmiddle_xpm);
- tintImage(&imageTabEnd, color, 0.0);
- tintImage(&imageTabSelectedEnd, color, 0.0);
- tintImage(&imageTabSelectedBegin, color, 0.0);
- tintImage(&imageTabMiddle, color, 0.0);
-
- if (!doubleControls) {
- int height = imageTabMiddle.height() / 2 + 1;
- imageTabEnd = imageTabEnd.scaledToHeight(height);
- imageTabMiddle = imageTabMiddle.scaledToHeight(height);
- imageTabSelectedEnd = imageTabSelectedEnd.scaledToHeight(height);
- imageTabSelectedBegin = imageTabSelectedBegin.scaledToHeight(height);
- }
+ currentTintButton = color;
+
+ imageTabEnd = QImage(tabend_xpm);
+ imageTabSelectedEnd = QImage(tabselectedend_xpm);
+ imageTabSelectedBegin = QImage(tabselectedbeginn_xpm);
+ imageTabMiddle = QImage(tabmiddle_xpm);
+ tintImage(&imageTabEnd, color, 0.0);
+ tintImage(&imageTabSelectedEnd, color, 0.0);
+ tintImage(&imageTabSelectedBegin, color, 0.0);
+ tintImage(&imageTabMiddle, color, 0.0);
+
+ if (!doubleControls) {
+ int height = imageTabMiddle.height() / 2 + 1;
+ imageTabEnd = imageTabEnd.scaledToHeight(height);
+ imageTabMiddle = imageTabMiddle.scaledToHeight(height);
+ imageTabSelectedEnd = imageTabSelectedEnd.scaledToHeight(height);
+ imageTabSelectedBegin = imageTabSelectedBegin.scaledToHeight(height);
+ }
}
void QWindowsMobileStylePrivate::tintImagesHigh(QColor color)
@@ -5075,6 +5076,10 @@ void QWindowsMobileStyle::drawPrimitive(PrimitiveElement element, const QStyleOp
color = option->palette.buttonText().color();
QImage image;
int xoffset, yoffset;
+ bool isTabBarArrow = widget && widget->parent()
+ && widget->inherits("QToolButton")
+ && widget->parent()->inherits("QTabBar");
+
switch (element) {
case PE_IndicatorArrowUp:
image = d->imageArrowUp;
@@ -5089,12 +5094,12 @@ void QWindowsMobileStyle::drawPrimitive(PrimitiveElement element, const QStyleOp
case PE_IndicatorArrowLeft:
image = d->imageArrowLeft;
xoffset = 8;
- yoffset = 2;
+ yoffset = isTabBarArrow ? 12 : 2;
break;
case PE_IndicatorArrowRight:
image = d->imageArrowRight;
xoffset = 8;
- yoffset = 2;
+ yoffset = isTabBarArrow ? 12 : 2;
break;
case PE_IndicatorArrowUpBig:
image = d->imageArrowUpBig;
@@ -6948,10 +6953,11 @@ int QWindowsMobileStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, co
case PM_SliderThickness:
ret = d->doubleControls ? windowsMobileSliderThickness * 2: windowsMobileSliderThickness;
break;
- case PM_TabBarScrollButtonWidth:
- ret = d->doubleControls ? 14 * 2 : 18;
- case PM_CheckBoxLabelSpacing:
- case PM_RadioButtonLabelSpacing:
+ case PM_TabBarScrollButtonWidth:
+ ret = d->doubleControls ? 14 * 2 : 18;
+ break;
+ case PM_CheckBoxLabelSpacing:
+ case PM_RadioButtonLabelSpacing:
ret = d->doubleControls ? 6 * 2 : 6;
break;
// Returns the number of pixels to use for the business part of the
diff --git a/src/gui/styles/qwindowsstyle.cpp b/src/gui/styles/qwindowsstyle.cpp
index 6c48590..1653baa 100644
--- a/src/gui/styles/qwindowsstyle.cpp
+++ b/src/gui/styles/qwindowsstyle.cpp
@@ -497,7 +497,7 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW
{
#ifndef Q_OS_WINCE
NONCLIENTMETRICS ncm;
- ncm.cbSize = sizeof(NONCLIENTMETRICS);
+ ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT);
if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0))
ret = qMax(ncm.iScrollHeight, ncm.iScrollWidth);
else
@@ -3105,7 +3105,9 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
qDrawWinButton(p, copy.rect, shadePal, copy.state & (State_Sunken | State_On),
&copy.palette.brush(QPalette::Button));
copy.rect.adjust(4, 1, -5, -1);
- if (!enabled || !(sb->stepEnabled & QAbstractSpinBox::StepUpEnabled) ) {
+ if ((!enabled || !(sb->stepEnabled & QAbstractSpinBox::StepUpEnabled))
+ && proxy()->styleHint(SH_EtchDisabledText, opt, widget) )
+ {
QStyleOptionSpinBox lightCopy = copy;
lightCopy.rect.adjust(1, 1, 1, 1);
lightCopy.palette.setBrush(QPalette::ButtonText, copy.palette.light());
@@ -3138,7 +3140,9 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
qDrawWinButton(p, copy.rect, shadePal, copy.state & (State_Sunken | State_On),
&copy.palette.brush(QPalette::Button));
copy.rect.adjust(4, 0, -5, -1);
- if (!enabled || !(sb->stepEnabled & QAbstractSpinBox::StepDownEnabled) ) {
+ if ((!enabled || !(sb->stepEnabled & QAbstractSpinBox::StepDownEnabled))
+ && proxy()->styleHint(SH_EtchDisabledText, opt, widget) )
+ {
QStyleOptionSpinBox lightCopy = copy;
lightCopy.rect.adjust(1, 1, 1, 1);
lightCopy.palette.setBrush(QPalette::ButtonText, copy.palette.light());
diff --git a/src/gui/styles/qwindowsstyle_p.h b/src/gui/styles/qwindowsstyle_p.h
index 808abe1..2a89b84 100644
--- a/src/gui/styles/qwindowsstyle_p.h
+++ b/src/gui/styles/qwindowsstyle_p.h
@@ -58,8 +58,8 @@
#ifndef QT_NO_STYLE_WINDOWS
#include <qlist.h>
-#include <qdatetime.h>
#include <qhash.h>
+#include <qelapsedtimer.h>
QT_BEGIN_NAMESPACE
@@ -80,7 +80,7 @@ public:
QList<QProgressBar *> bars;
int animationFps;
int animateTimer;
- QTime startTime;
+ QElapsedTimer startTime;
int animateStep;
QColor inactiveCaptionText;
QColor activeCaptionColor;
diff --git a/src/gui/styles/qwindowsvistastyle_p.h b/src/gui/styles/qwindowsvistastyle_p.h
index 673568d..ab941a1 100644
--- a/src/gui/styles/qwindowsvistastyle_p.h
+++ b/src/gui/styles/qwindowsvistastyle_p.h
@@ -86,6 +86,7 @@
#include <qlistview.h>
#include <qtableview.h>
#include <qbasictimer.h>
+#include <qdatetime.h>
#include <qcommandlinkbutton.h>
QT_BEGIN_NAMESPACE
diff --git a/src/gui/styles/styles.pri b/src/gui/styles/styles.pri
index 676f59e..5084442 100644
--- a/src/gui/styles/styles.pri
+++ b/src/gui/styles/styles.pri
@@ -164,17 +164,17 @@ contains( styles, windowsmobile ) {
}
contains( styles, s60 ):contains(QT_CONFIG, s60) {
- HEADERS += \
- styles/qs60style.h \
- styles/qs60style_p.h
- SOURCES += styles/qs60style.cpp
- symbian {
- SOURCES += styles/qs60style_s60.cpp
- LIBS += -laknicon -laknskins -laknskinsrv -lfontutils -legul -lbmpanim
- } else {
- SOURCES += styles/qs60style_simulated.cpp
- RESOURCES += styles/qstyle_s60_simulated.qrc
- }
+ HEADERS += \
+ styles/qs60style.h \
+ styles/qs60style_p.h
+ SOURCES += styles/qs60style.cpp
+ symbian {
+ SOURCES += styles/qs60style_s60.cpp
+ LIBS += -lAknIcon -lAKNSKINS -lAKNSKINSRV -lFontUtils -legul -lbmpanim
+ } else {
+ SOURCES += styles/qs60style_simulated.cpp
+ RESOURCES += styles/qstyle_s60_simulated.qrc
+ }
} else {
- DEFINES += QT_NO_STYLE_S60
+ DEFINES += QT_NO_STYLE_S60
}
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index dd9e69e..cb16a16 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -73,7 +73,7 @@
#endif
#endif
#ifdef Q_OS_SYMBIAN
-#include "qt_s60_p.h"
+#include <private/qt_s60_p.h>
#endif
#include <QMutexLocker>
@@ -1297,6 +1297,8 @@ QFont::StyleHint QFont::styleHint() const
\value PreferQuality prefer the best quality font. The font matcher
will use the nearest standard point size that the font
supports.
+ \value ForceIntegerMetrics forces the use of integer values in font engines that support fractional
+ font metrics.
*/
/*!
@@ -2612,8 +2614,10 @@ void QFontCache::cleanup()
} QT_CATCH (const std::bad_alloc &) {
// no cache - just ignore
}
- if (cache && cache->hasLocalData())
+ if (cache && cache->hasLocalData()) {
+ cache->localData()->clear();
cache->setLocalData(0);
+ }
}
#endif // QT_NO_THREAD
diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h
index 5adf237..6f62424 100644
--- a/src/gui/text/qfont.h
+++ b/src/gui/text/qfont.h
@@ -76,17 +76,18 @@ public:
};
enum StyleStrategy {
- PreferDefault = 0x0001,
- PreferBitmap = 0x0002,
- PreferDevice = 0x0004,
- PreferOutline = 0x0008,
- ForceOutline = 0x0010,
- PreferMatch = 0x0020,
- PreferQuality = 0x0040,
- PreferAntialias = 0x0080,
- NoAntialias = 0x0100,
- OpenGLCompatible = 0x0200,
- NoFontMerging = 0x8000
+ PreferDefault = 0x0001,
+ PreferBitmap = 0x0002,
+ PreferDevice = 0x0004,
+ PreferOutline = 0x0008,
+ ForceOutline = 0x0010,
+ PreferMatch = 0x0020,
+ PreferQuality = 0x0040,
+ PreferAntialias = 0x0080,
+ NoAntialias = 0x0100,
+ OpenGLCompatible = 0x0200,
+ ForceIntegerMetrics = 0x0400,
+ NoFontMerging = 0x8000
};
enum Weight {
diff --git a/src/gui/text/qfont_s60.cpp b/src/gui/text/qfont_s60.cpp
index 52c77d6..ccd17a2 100644
--- a/src/gui/text/qfont_s60.cpp
+++ b/src/gui/text/qfont_s60.cpp
@@ -40,8 +40,8 @@
****************************************************************************/
#include "qfont.h"
-#include "qt_s60_p.h"
-#include "qpixmap_s60_p.h"
+#include <private/qt_s60_p.h>
+#include <private/qpixmap_s60_p.h>
#include "qmutex.h"
QT_BEGIN_NAMESPACE
diff --git a/src/gui/text/qfontdatabase_qws.cpp b/src/gui/text/qfontdatabase_qws.cpp
index 62d7793..a3d8d65 100644
--- a/src/gui/text/qfontdatabase_qws.cpp
+++ b/src/gui/text/qfontdatabase_qws.cpp
@@ -632,8 +632,9 @@ QFontEngine *loadSingleEngine(int script, const QFontPrivate *fp,
#ifndef QT_NO_FREETYPE
QScopedPointer<QFontEngineFT> fte(new QFontEngineFT(def));
- if (fte->init(faceId, style->antialiased,
- style->antialiased ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono)) {
+ bool antialias = style->antialiased && !(request.styleStrategy & QFont::NoAntialias);
+ if (fte->init(faceId, antialias,
+ antialias ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono)) {
#ifdef QT_NO_QWS_QPF2
return fte.take();
#else
@@ -793,7 +794,7 @@ QFontDatabase::findFont(int script, const QFontPrivate *fp,
" family: %s [%s], script: %d\n"
" weight: %d, style: %d\n"
" stretch: %d\n"
- " pixelSize: %d\n"
+ " pixelSize: %g\n"
" pitch: %c",
family_name.isEmpty() ? "-- first in script --" : family_name.toLatin1().constData(),
foundry_name.isEmpty() ? "-- any --" : foundry_name.toLatin1().constData(),
diff --git a/src/gui/text/qfontdatabase_s60.cpp b/src/gui/text/qfontdatabase_s60.cpp
index 87a73df..ef5e0c4 100644
--- a/src/gui/text/qfontdatabase_s60.cpp
+++ b/src/gui/text/qfontdatabase_s60.cpp
@@ -45,8 +45,8 @@
#include "qfontengine_s60_p.h"
#include "qabstractfileengine.h"
#include "qdesktopservices.h"
-#include "qpixmap_s60_p.h"
-#include "qt_s60_p.h"
+#include <private/qpixmap_s60_p.h>
+#include <private/qt_s60_p.h>
#include "qendian.h"
#include <private/qcore_symbian_p.h>
#if defined(QT_NO_FREETYPE)
@@ -332,6 +332,11 @@ bool QFontDatabase::removeApplicationFont(int handle)
return false;
}
+bool QFontDatabase::removeAllApplicationFonts()
+{
+ return false;
+}
+
bool QFontDatabase::supportsThreadedFontRendering()
{
return false;
diff --git a/src/gui/text/qfontdatabase_x11.cpp b/src/gui/text/qfontdatabase_x11.cpp
index bb1e60d..b1ab478 100644
--- a/src/gui/text/qfontdatabase_x11.cpp
+++ b/src/gui/text/qfontdatabase_x11.cpp
@@ -41,9 +41,9 @@
#include <qplatformdefs.h>
-#include <qdatetime.h>
#include <qdebug.h>
#include <qpaintdevice.h>
+#include <qelapsedtimer.h>
#include <private/qt_x11_p.h>
#include "qx11info_x11.h"
@@ -1218,7 +1218,7 @@ static void load(const QString &family = QString(), int script = -1, bool forceX
}
#ifdef QFONTDATABASE_DEBUG
- QTime t;
+ QElapsedTimer t;
t.start();
#endif
@@ -1301,7 +1301,7 @@ static void initializeDb()
if (!db || db->count)
return;
- QTime t;
+ QElapsedTimer t;
t.start();
#ifndef QT_NO_FONTCONFIG
@@ -1314,7 +1314,7 @@ static void initializeDb()
}
loadFontConfig();
- FD_DEBUG("QFontDatabase: loaded FontConfig: %d ms", t.elapsed());
+ FD_DEBUG("QFontDatabase: loaded FontConfig: %d ms", int(t.elapsed()));
#endif
t.start();
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index e5975d2..194c5f3 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -379,6 +379,15 @@ void QFontEngine::getGlyphPositions(const QGlyphLayout &glyphs, const QTransform
Q_ASSERT(positions.size() == glyphs_out.size());
}
+void QFontEngine::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing)
+{
+ glyph_metrics_t gi = boundingBox(glyph);
+ bool isValid = gi.isValid();
+ if (leftBearing != 0)
+ *leftBearing = isValid ? gi.x.toReal() : 0.0;
+ if (rightBearing != 0)
+ *rightBearing = isValid ? (gi.xoff - gi.x - gi.width).toReal() : 0.0;
+}
glyph_metrics_t QFontEngine::tightBoundingBox(const QGlyphLayout &glyphs)
{
@@ -1389,6 +1398,12 @@ glyph_metrics_t QFontEngineMulti::boundingBox(const QGlyphLayout &glyphs)
return overall;
}
+void QFontEngineMulti::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing)
+{
+ int which = highByte(glyph);
+ engine(which)->getGlyphBearings(stripped(glyph), leftBearing, rightBearing);
+}
+
void QFontEngineMulti::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs,
QPainterPath *path, QTextItem::RenderFlags flags)
{
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index 17ade64..a9def8e 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -619,7 +619,7 @@ QFontEngineFT::QFontEngineFT(const QFontDef &fd)
transform = false;
antialias = true;
freetype = 0;
- default_load_flags = 0;
+ default_load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
default_hint_style = HintNone;
subpixelType = Subpixel_None;
lcdFilterType = 0;
@@ -746,7 +746,7 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format)
QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph) const
{
- Glyph *g = set->glyph_data.value(glyph);
+ Glyph *g = set->getGlyph(glyph);
if (g)
return g;
@@ -858,10 +858,10 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, Glyph
}
}
- Glyph *g = set->glyph_data.value(glyph);
+ Glyph *g = set->getGlyph(glyph);
if (g && g->format == format) {
if (uploadToServer && !g->uploadedToServer) {
- set->glyph_data[glyph] = 0;
+ set->setGlyph(glyph, 0);
delete g;
g = 0;
} else {
@@ -1158,7 +1158,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, Glyph
uploadGlyphToServer(set, glyph, g, &info, glyph_buffer_size);
}
- set->glyph_data[glyph] = g;
+ set->setGlyph(glyph, g);
return g;
}
@@ -1381,8 +1381,7 @@ QFontEngineFT::QGlyphSet *QFontEngineFT::loadTransformedGlyphSet(const QTransfor
}
gs = &transformedGlyphSets[0];
- qDeleteAll(gs->glyph_data);
- gs->glyph_data.clear();
+ gs->clear();
gs->id = allocateServerGlyphSet();
@@ -1398,7 +1397,7 @@ bool QFontEngineFT::loadGlyphs(QGlyphSet *gs, glyph_t *glyphs, int num_glyphs, G
FT_Face face = 0;
for (int i = 0; i < num_glyphs; ++i) {
- Glyph *glyph = gs->glyph_data.value(glyphs[i]);
+ Glyph *glyph = gs->getGlyph(glyphs[i]);
if (glyph == 0 || glyph->format != format) {
if (!face) {
face = lockFace();
@@ -1635,7 +1634,7 @@ void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlag
FT_Face face = 0;
if (flags & QTextEngine::DesignMetrics) {
for (int i = 0; i < glyphs->numGlyphs; i++) {
- Glyph *g = defaultGlyphSet.glyph_data.value(glyphs->glyphs[i]);
+ Glyph *g = defaultGlyphSet.getGlyph(glyphs->glyphs[i]);
if (g) {
glyphs->advances_x[i] = QFixed::fromFixed(g->linearAdvance);
} else {
@@ -1648,7 +1647,7 @@ void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlag
}
} else {
for (int i = 0; i < glyphs->numGlyphs; i++) {
- Glyph *g = defaultGlyphSet.glyph_data.value(glyphs->glyphs[i]);
+ Glyph *g = defaultGlyphSet.getGlyph(glyphs->glyphs[i]);
if (g) {
glyphs->advances_x[i] = QFixed(g->advance);
} else {
@@ -1677,7 +1676,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs)
QFixed ymax = 0;
QFixed xmax = 0;
for (int i = 0; i < glyphs.numGlyphs; i++) {
- Glyph *g = defaultGlyphSet.glyph_data.value(glyphs.glyphs[i]);
+ Glyph *g = defaultGlyphSet.getGlyph(glyphs.glyphs[i]);
if (!g) {
if (!face)
face = lockFace();
@@ -1719,7 +1718,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph)
{
FT_Face face = 0;
glyph_metrics_t overall;
- Glyph *g = defaultGlyphSet.glyph_data.value(glyph);
+ Glyph *g = defaultGlyphSet.getGlyph(glyph);
if (!g) {
face = lockFace();
g = loadGlyph(glyph, Format_None, true);
@@ -1783,8 +1782,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph, const QTransform &matr
transformedGlyphSets.prepend(QGlyphSet());
}
glyphSet = &transformedGlyphSets[0];
- qDeleteAll(glyphSet->glyph_data);
- glyphSet->glyph_data.clear();
+ glyphSet->clear();
glyphSet->id = allocateServerGlyphSet();
glyphSet->transformationMatrix = m;
}
@@ -1792,7 +1790,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph, const QTransform &matr
} else {
glyphSet = &defaultGlyphSet;
}
- Glyph * g = glyphSet->glyph_data.value(glyph);
+ Glyph * g = glyphSet->getGlyph(glyph);
if (!g) {
face = lockFace();
g = loadGlyphMetrics(glyphSet, glyph);
@@ -1881,7 +1879,7 @@ QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, int margin, const QTransfor
void QFontEngineFT::removeGlyphFromCache(glyph_t glyph)
{
- delete defaultGlyphSet.glyph_data.take(glyph);
+ defaultGlyphSet.removeGlyphFromCache(glyph);
}
int QFontEngineFT::glyphCount() const
@@ -1937,11 +1935,53 @@ QFontEngineFT::QGlyphSet::QGlyphSet()
transformationMatrix.yy = 0x10000;
transformationMatrix.xy = 0;
transformationMatrix.yx = 0;
+ memset(fast_glyph_data, 0, sizeof(fast_glyph_data));
+ fast_glyph_count = 0;
}
QFontEngineFT::QGlyphSet::~QGlyphSet()
{
+ clear();
+}
+
+void QFontEngineFT::QGlyphSet::clear()
+{
+ if (fast_glyph_count > 0) {
+ for (int i = 0; i < 256; ++i) {
+ if (fast_glyph_data[i]) {
+ delete fast_glyph_data[i];
+ fast_glyph_data[i] = 0;
+ }
+ }
+ fast_glyph_count = 0;
+ }
qDeleteAll(glyph_data);
+ glyph_data.clear();
+}
+
+void QFontEngineFT::QGlyphSet::removeGlyphFromCache(int index)
+{
+ if (index < 256) {
+ if (fast_glyph_data[index]) {
+ delete fast_glyph_data[index];
+ fast_glyph_data[index] = 0;
+ if (fast_glyph_count > 0)
+ --fast_glyph_count;
+ }
+ } else {
+ delete glyph_data.take(index);
+ }
+}
+
+void QFontEngineFT::QGlyphSet::setGlyph(int index, Glyph *glyph)
+{
+ if (index < 256) {
+ if (!fast_glyph_data[index])
+ ++fast_glyph_count;
+ fast_glyph_data[index] = glyph;
+ } else {
+ glyph_data.insert(index, glyph);
+ }
}
unsigned long QFontEngineFT::allocateServerGlyphSet()
diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h
index 98dd002..12b7da8 100644
--- a/src/gui/text/qfontengine_ft_p.h
+++ b/src/gui/text/qfontengine_ft_p.h
@@ -180,7 +180,21 @@ public:
FT_Matrix transformationMatrix;
unsigned long id; // server sided id, GlyphSet for X11
bool outline_drawing;
+
+ void removeGlyphFromCache(int index);
+ void clear();
+ inline Glyph *getGlyph(int index) const
+ {
+ if (index < 256)
+ return fast_glyph_data[index];
+ return glyph_data.value(index);
+ }
+ void setGlyph(int index, Glyph *glyph);
+
+private:
mutable QHash<int, Glyph *> glyph_data; // maps from glyph index to glyph data
+ mutable Glyph *fast_glyph_data[256]; // for fast lookup of glyphs < 256
+ mutable int fast_glyph_count;
};
virtual QFontEngine::FaceId faceId() const;
@@ -252,7 +266,7 @@ public:
QGlyphSet *defaultGlyphs() { return &defaultGlyphSet; }
GlyphFormat defaultGlyphFormat() const { return defaultFormat; }
- inline Glyph *cachedGlyph(glyph_t g) const { return defaultGlyphSet.glyph_data.value(g); }
+ inline Glyph *cachedGlyph(glyph_t g) const { return defaultGlyphSet.getGlyph(g); }
QGlyphSet *loadTransformedGlyphSet(const QTransform &matrix);
bool loadGlyphs(QGlyphSet *gs, glyph_t *glyphs, int num_glyphs, GlyphFormat format = Format_Render);
diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm
index 48bc635..0bfdbc0 100644
--- a/src/gui/text/qfontengine_mac.mm
+++ b/src/gui/text/qfontengine_mac.mm
@@ -53,6 +53,7 @@
#include <qvarlengtharray.h>
#include <qdebug.h>
#include <qendian.h>
+#include <qmath.h>
#include <ApplicationServices/ApplicationServices.h>
#include <AppKit/AppKit.h>
@@ -303,12 +304,20 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay
outGlyphs[idx] = tmpGlyphs[i] | fontIndex;
outAdvances_x[idx] = QFixed::fromReal(tmpPoints[i + 1].x - tmpPoints[i].x);
outAdvances_y[idx] = QFixed::fromReal(tmpPoints[i + 1].y - tmpPoints[i].y);
+
+ if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
+ outAdvances_x[idx] = outAdvances_x[idx].round();
+ outAdvances_y[idx] = outAdvances_y[idx].round();
+ }
}
CGSize lastGlyphAdvance;
CTFontGetAdvancesForGlyphs(runFont, kCTFontHorizontalOrientation, tmpGlyphs + glyphCount - 1, &lastGlyphAdvance, 1);
outGlyphs[rtl ? 0 : (glyphCount - 1)] = tmpGlyphs[glyphCount - 1] | fontIndex;
- outAdvances_x[rtl ? 0 : (glyphCount - 1)] = QFixed::fromReal(lastGlyphAdvance.width).ceil();
+ outAdvances_x[rtl ? 0 : (glyphCount - 1)] =
+ (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? QFixed::fromReal(lastGlyphAdvance.width).round()
+ : QFixed::fromReal(lastGlyphAdvance.width);
}
outGlyphs += glyphCount;
outAttributes += glyphCount;
@@ -378,8 +387,11 @@ bool QCoreTextFontEngine::stringToCMap(const QChar *, int, QGlyphLayout *, int *
glyph_metrics_t QCoreTextFontEngine::boundingBox(const QGlyphLayout &glyphs)
{
QFixed w;
- for (int i = 0; i < glyphs.numGlyphs; ++i)
- w += glyphs.effectiveAdvance(i);
+ for (int i = 0; i < glyphs.numGlyphs; ++i) {
+ w += (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? glyphs.effectiveAdvance(i).round()
+ : glyphs.effectiveAdvance(i);
+ }
return glyph_metrics_t(0, -(ascent()), w, ascent()+descent(), w, 0);
}
glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph)
@@ -393,33 +405,51 @@ glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph)
ret.y = -QFixed::fromReal(rect.origin.y) - ret.height;
CGSize advances[1];
CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, &g, advances, 1);
- ret.xoff = QFixed::fromReal(advances[0].width).ceil();
- ret.yoff = QFixed::fromReal(advances[0].height).ceil();
+ ret.xoff = QFixed::fromReal(advances[0].width);
+ ret.yoff = QFixed::fromReal(advances[0].height);
+
+ if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
+ ret.xoff = ret.xoff.round();
+ ret.yoff = ret.yoff.round();
+ }
+
return ret;
}
QFixed QCoreTextFontEngine::ascent() const
{
- return QFixed::fromReal(CTFontGetAscent(ctfont)).ceil();
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? QFixed::fromReal(CTFontGetAscent(ctfont)).round()
+ : QFixed::fromReal(CTFontGetAscent(ctfont));
}
QFixed QCoreTextFontEngine::descent() const
{
+ QFixed d = QFixed::fromReal(CTFontGetDescent(ctfont));
+ if (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ d = d.round();
+
// subtract a pixel to even out the historical +1 in QFontMetrics::height().
// Fix in Qt 5.
- return QFixed::fromReal(CTFontGetDescent(ctfont)).ceil() - 1;
+ return d - 1;
}
QFixed QCoreTextFontEngine::leading() const
{
- return QFixed::fromReal(CTFontGetLeading(ctfont)).ceil();
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? QFixed::fromReal(CTFontGetLeading(ctfont)).round()
+ : QFixed::fromReal(CTFontGetLeading(ctfont));
}
QFixed QCoreTextFontEngine::xHeight() const
{
- return QFixed::fromReal(CTFontGetXHeight(ctfont)).ceil();
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? QFixed::fromReal(CTFontGetXHeight(ctfont)).round()
+ : QFixed::fromReal(CTFontGetXHeight(ctfont));
}
QFixed QCoreTextFontEngine::averageCharWidth() const
{
// ### Need to implement properly and get the information from the OS/2 Table.
- return QFontEngine::averageCharWidth();
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? QFontEngine::averageCharWidth().round()
+ : QFontEngine::averageCharWidth();
}
qreal QCoreTextFontEngine::maxCharWidth() const
@@ -787,6 +817,7 @@ struct QGlyphLayoutInfo
int *mappedFonts;
QTextEngine::ShaperFlags flags;
QFontEngineMacMulti::ShaperItem *shaperItem;
+ unsigned int styleStrategy;
};
static OSStatus atsuPostLayoutCallback(ATSULayoutOperationSelector selector, ATSULineRef lineRef, URefCon refCon,
@@ -856,6 +887,11 @@ static OSStatus atsuPostLayoutCallback(ATSULayoutOperationSelector selector, ATS
QFixed yAdvance = FixedToQFixed(baselineDeltas[glyphIdx]);
QFixed xAdvance = FixedToQFixed(layoutData[glyphIdx + 1].realPos - layoutData[glyphIdx].realPos);
+ if (nfo->styleStrategy & QFont::ForceIntegerMetrics) {
+ yAdvance = yAdvance.round();
+ xAdvance = xAdvance.round();
+ }
+
if (glyphId != 0xffff || i == 0) {
if (i < nfo->glyphs->numGlyphs)
{
@@ -1032,6 +1068,7 @@ bool QFontEngineMacMulti::stringToCMapInternal(const QChar *str, int len, QGlyph
nfo.callbackCalled = false;
nfo.flags = flags;
nfo.shaperItem = shaperItem;
+ nfo.styleStrategy = fontDef.styleStrategy;
int prevNumGlyphs = *nglyphs;
@@ -1061,8 +1098,6 @@ bool QFontEngineMacMulti::stringToCMapInternal(const QChar *str, int len, QGlyph
| kATSLineDisableAllJustification
;
- layopts |= kATSLineUseDeviceMetrics;
-
if (fontDef.styleStrategy & QFont::NoAntialias)
layopts |= kATSLineNoAntiAliasing;
@@ -1366,14 +1401,22 @@ void QFontEngineMac::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFla
for (int i = 0; i < glyphs->numGlyphs; ++i) {
glyphs->advances_x[i] = QFixed::fromReal(metrics[i].deviceAdvance.x);
glyphs->advances_y[i] = QFixed::fromReal(metrics[i].deviceAdvance.y);
+
+ if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
+ glyphs->advances_x[i] = glyphs->advances_x[i].round();
+ glyphs->advances_y[i] = glyphs->advances_y[i].round();
+ }
}
}
glyph_metrics_t QFontEngineMac::boundingBox(const QGlyphLayout &glyphs)
{
QFixed w;
- for (int i = 0; i < glyphs.numGlyphs; ++i)
- w += glyphs.effectiveAdvance(i);
+ for (int i = 0; i < glyphs.numGlyphs; ++i) {
+ w += (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? glyphs.effectiveAdvance(i).round()
+ : glyphs.effectiveAdvance(i);
+ }
return glyph_metrics_t(0, -(ascent()), w, ascent()+descent(), w, 0);
}
@@ -1398,39 +1441,58 @@ glyph_metrics_t QFontEngineMac::boundingBox(glyph_t glyph)
gm.xoff = QFixed::fromReal(metrics.deviceAdvance.x);
gm.yoff = QFixed::fromReal(metrics.deviceAdvance.y);
+ if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
+ gm.x = gm.x.floor();
+ gm.y = gm.y.floor();
+ gm.xoff = gm.xoff.round();
+ gm.yoff = gm.yoff.round();
+ }
+
return gm;
}
QFixed QFontEngineMac::ascent() const
{
- return m_ascent;
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? m_ascent.round()
+ : m_ascent;
}
QFixed QFontEngineMac::descent() const
{
// subtract a pixel to even out the historical +1 in QFontMetrics::height().
// Fix in Qt 5.
- return m_descent - 1;
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? m_descent.round() - 1
+ : m_descent;
}
QFixed QFontEngineMac::leading() const
{
- return m_leading;
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? m_leading.round()
+ : m_leading;
}
qreal QFontEngineMac::maxCharWidth() const
{
- return m_maxCharWidth;
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? qRound(m_maxCharWidth)
+ : m_maxCharWidth;
}
QFixed QFontEngineMac::xHeight() const
{
- return m_xHeight;
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? m_xHeight.round()
+ : m_xHeight;
}
QFixed QFontEngineMac::averageCharWidth() const
{
- return m_averageCharWidth;
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? m_averageCharWidth.round()
+ : m_averageCharWidth;
}
static void addGlyphsToPathHelper(ATSUStyle style, glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, QPainterPath *path)
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index 71ab5a5..e645caf 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -206,6 +206,8 @@ public:
virtual qreal minLeftBearing() const { return qreal(); }
virtual qreal minRightBearing() const { return qreal(); }
+ virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0);
+
virtual const char *name() const = 0;
virtual bool canRender(const QChar *string, int len) = 0;
@@ -374,6 +376,7 @@ public:
virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const;
virtual void doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const;
virtual void addOutlineToPath(qreal, qreal, const QGlyphLayout &, QPainterPath *, QTextItem::RenderFlags flags);
+ virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0);
virtual QFixed ascent() const;
virtual QFixed descent() const;
diff --git a/src/gui/text/qfontengine_qpf.cpp b/src/gui/text/qfontengine_qpf.cpp
index 136737d..a0593cc 100644
--- a/src/gui/text/qfontengine_qpf.cpp
+++ b/src/gui/text/qfontengine_qpf.cpp
@@ -920,8 +920,18 @@ void QFontEngineQPF::loadGlyph(glyph_t glyph)
if (!renderingFontEngine)
return;
-
- QImage img = renderingFontEngine->alphaMapForGlyph(glyph).convertToFormat(QImage::Format_Indexed8);
+ QImage img = renderingFontEngine->alphaMapForGlyph(glyph);
+ if (img.format() != QImage::Format_Indexed8) {
+ bool mono = img.depth() == 1;
+ img = img.convertToFormat(QImage::Format_Indexed8);
+ if (mono) {
+ //### we know that 1 is opaque and 0 is transparent
+ uchar *byte = img.bits();
+ int count = img.byteCount();
+ while (count--)
+ *byte++ *= 0xff;
+ }
+ }
glyph_metrics_t metrics = renderingFontEngine->boundingBox(glyph);
renderingFontEngine->removeGlyphFromCache(glyph);
diff --git a/src/gui/text/qfontengine_s60.cpp b/src/gui/text/qfontengine_s60.cpp
index 3ea084b..c9ff661 100644
--- a/src/gui/text/qfontengine_s60.cpp
+++ b/src/gui/text/qfontengine_s60.cpp
@@ -79,6 +79,31 @@ QByteArray QFontEngineS60Extensions::getSfntTable(uint tag) const
return result;
}
+bool QFontEngineS60Extensions::getSfntTableData(uint tag, uchar *buffer, uint *length) const
+{
+ if (!m_trueTypeExtension->HasTrueTypeTable(tag))
+ return false;
+
+ bool result = true;
+ TInt error = KErrNone;
+ TInt tableByteLength;
+ TAny *table =
+ q_check_ptr(m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength));
+
+ if (error != KErrNone) {
+ return false;
+ } else if (*length > 0 && *length < tableByteLength) {
+ result = false; // Caller did not allocate enough memory
+ } else {
+ *length = tableByteLength;
+ if (buffer)
+ qMemCopy(buffer, table, tableByteLength);
+ }
+
+ m_trueTypeExtension->ReleaseTrueTypeTable(table);
+ return result;
+}
+
const unsigned char *QFontEngineS60Extensions::cmap() const
{
if (!m_cmap) {
@@ -326,6 +351,11 @@ QByteArray QFontEngineS60::getSfntTable(uint tag) const
return m_extensions->getSfntTable(tag);
}
+bool QFontEngineS60::getSfntTableData(uint tag, uchar *buffer, uint *length) const
+{
+ return m_extensions->getSfntTableData(tag, buffer, length);
+}
+
QFontEngine::Type QFontEngineS60::type() const
{
return QFontEngine::S60FontEngine;
diff --git a/src/gui/text/qfontengine_s60_p.h b/src/gui/text/qfontengine_s60_p.h
index 5834cc4..a80af4d 100644
--- a/src/gui/text/qfontengine_s60_p.h
+++ b/src/gui/text/qfontengine_s60_p.h
@@ -69,6 +69,7 @@ public:
QFontEngineS60Extensions(CFont* fontOwner, COpenFont *font);
QByteArray getSfntTable(uint tag) const;
+ bool getSfntTableData(uint tag, uchar *buffer, uint *length) const;
const unsigned char *cmap() const;
QPainterPath glyphOutline(glyph_t glyph) const;
CFont *fontOwner() const;
@@ -106,6 +107,7 @@ public:
qreal minRightBearing() const { return 0; }
QByteArray getSfntTable(uint tag) const;
+ bool getSfntTableData(uint tag, uchar *buffer, uint *length) const;
static qreal pixelsToPoints(qreal pixels, Qt::Orientation orientation = Qt::Horizontal);
static qreal pointsToPixels(qreal points, Qt::Orientation orientation = Qt::Horizontal);
diff --git a/src/gui/text/qfontengine_win.cpp b/src/gui/text/qfontengine_win.cpp
index 55e93bd..a805612 100644
--- a/src/gui/text/qfontengine_win.cpp
+++ b/src/gui/text/qfontengine_win.cpp
@@ -39,6 +39,11 @@
**
****************************************************************************/
+#if _WIN32_WINNT < 0x0500
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0500
+#endif
+
#include "qfontengine_p.h"
#include "qtextengine_p.h"
#include <qglobal.h>
@@ -649,6 +654,32 @@ static const ushort char_table[] = {
static const int char_table_entries = sizeof(char_table)/sizeof(ushort);
+#ifndef Q_CC_MINGW
+void QFontEngineWin::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing)
+{
+ HDC hdc = shared_dc();
+ SelectObject(hdc, hfont);
+
+#ifndef Q_WS_WINCE
+ if (ttf)
+#endif
+
+ {
+ ABC abcWidths;
+ GetCharABCWidthsI(hdc, glyph, 1, 0, &abcWidths);
+ if (leftBearing)
+ *leftBearing = abcWidths.abcA;
+ if (rightBearing)
+ *rightBearing = abcWidths.abcC;
+ }
+
+#ifndef Q_WS_WINCE
+ else {
+ QFontEngine::getGlyphBearings(glyph, leftBearing, rightBearing);
+ }
+#endif
+}
+#endif // Q_CC_MINGW
qreal QFontEngineWin::minLeftBearing() const
{
diff --git a/src/gui/text/qfontengine_win_p.h b/src/gui/text/qfontengine_win_p.h
index f9d8f8b..68b53b5 100644
--- a/src/gui/text/qfontengine_win_p.h
+++ b/src/gui/text/qfontengine_win_p.h
@@ -106,6 +106,10 @@ public:
virtual QImage alphaMapForGlyph(glyph_t, const QTransform &xform);
virtual QImage alphaRGBMapForGlyph(glyph_t t, int margin, const QTransform &xform);
+#ifndef Q_CC_MINGW
+ virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0);
+#endif
+
int getGlyphIndexes(const QChar *ch, int numChars, QGlyphLayout *glyphs, bool mirrored) const;
void getCMap();
diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp
index 41d0af1..3a52e8e 100644
--- a/src/gui/text/qfontmetrics.cpp
+++ b/src/gui/text/qfontmetrics.cpp
@@ -328,7 +328,7 @@ int QFontMetrics::height() const
{
QFontEngine *engine = d->engineForScript(QUnicodeTables::Common);
Q_ASSERT(engine != 0);
- return qRound(engine->ascent() + engine->descent()) + 1;
+ return qRound(engine->ascent()) + qRound(engine->descent()) + 1;
}
/*!
@@ -356,7 +356,7 @@ int QFontMetrics::lineSpacing() const
{
QFontEngine *engine = d->engineForScript(QUnicodeTables::Common);
Q_ASSERT(engine != 0);
- return qRound(engine->leading() + engine->ascent() + engine->descent()) + 1;
+ return qRound(engine->leading()) + qRound(engine->ascent()) + qRound(engine->descent()) + 1;
}
/*!
@@ -472,8 +472,9 @@ int QFontMetrics::leftBearing(QChar ch) const
int nglyphs = 9;
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0);
// ### can nglyphs != 1 happen at all? Not currently I think
- glyph_metrics_t gi = engine->boundingBox(glyphs.glyphs[0]);
- return qRound(gi.x);
+ qreal lb;
+ engine->getGlyphBearings(glyphs.glyphs[0], &lb);
+ return qRound(lb);
}
/*!
@@ -506,8 +507,9 @@ int QFontMetrics::rightBearing(QChar ch) const
int nglyphs = 9;
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0);
// ### can nglyphs != 1 happen at all? Not currently I think
- glyph_metrics_t gi = engine->boundingBox(glyphs.glyphs[0]);
- return qRound(gi.xoff - gi.x - gi.width);
+ qreal rb;
+ engine->getGlyphBearings(glyphs.glyphs[0], 0, &rb);
+ return qRound(rb);
}
/*!
@@ -533,7 +535,7 @@ int QFontMetrics::width(const QString &text, int len) const
if (len == 0)
return 0;
- QTextEngine layout(text, d.data());
+ QStackTextEngine layout(text, d.data());
layout.ignoreBidi = true;
return qRound(layout.width(0, len));
}
@@ -609,7 +611,7 @@ int QFontMetrics::charWidth(const QString &text, int pos) const
int from = qMax(0, pos - 8);
int to = qMin(text.length(), pos + 8);
QString cstr = QString::fromRawData(text.unicode() + from, to - from);
- QTextEngine layout(cstr, d.data());
+ QStackTextEngine layout(cstr, d.data());
layout.ignoreBidi = true;
layout.itemize();
width = qRound(layout.width(pos-from, 1));
@@ -658,7 +660,7 @@ QRect QFontMetrics::boundingRect(const QString &text) const
if (text.length() == 0)
return QRect();
- QTextEngine layout(text, d.data());
+ QStackTextEngine layout(text, d.data());
layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.boundingBox(0, text.length());
@@ -828,7 +830,7 @@ QRect QFontMetrics::tightBoundingRect(const QString &text) const
if (text.length() == 0)
return QRect();
- QTextEngine layout(text, d.data());
+ QStackTextEngine layout(text, d.data());
layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.tightBoundingBox(0, text.length());
@@ -1317,8 +1319,9 @@ qreal QFontMetricsF::leftBearing(QChar ch) const
int nglyphs = 9;
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0);
// ### can nglyphs != 1 happen at all? Not currently I think
- glyph_metrics_t gi = engine->boundingBox(glyphs.glyphs[0]);
- return gi.x.toReal();
+ qreal lb;
+ engine->getGlyphBearings(glyphs.glyphs[0], &lb);
+ return lb;
}
/*!
@@ -1351,8 +1354,10 @@ qreal QFontMetricsF::rightBearing(QChar ch) const
int nglyphs = 9;
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0);
// ### can nglyphs != 1 happen at all? Not currently I think
- glyph_metrics_t gi = engine->boundingBox(glyphs.glyphs[0]);
- return (gi.xoff - gi.x - gi.width).toReal();
+ qreal rb;
+ engine->getGlyphBearings(glyphs.glyphs[0], 0, &rb);
+ return rb;
+
}
/*!
@@ -1370,7 +1375,7 @@ qreal QFontMetricsF::width(const QString &text) const
int pos = text.indexOf(QLatin1Char('\x9c'));
int len = (pos != -1) ? pos : text.length();
- QTextEngine layout(text, d.data());
+ QStackTextEngine layout(text, d.data());
layout.ignoreBidi = true;
layout.itemize();
return layout.width(0, len).toReal();
@@ -1447,7 +1452,7 @@ QRectF QFontMetricsF::boundingRect(const QString &text) const
if (len == 0)
return QRectF();
- QTextEngine layout(text, d.data());
+ QStackTextEngine layout(text, d.data());
layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.boundingBox(0, len);
@@ -1620,7 +1625,7 @@ QRectF QFontMetricsF::tightBoundingRect(const QString &text) const
if (text.length() == 0)
return QRect();
- QTextEngine layout(text, d.data());
+ QStackTextEngine layout(text, d.data());
layout.ignoreBidi = true;
layout.itemize();
glyph_metrics_t gm = layout.tightBoundingBox(0, text.length());
diff --git a/src/gui/text/qstatictext.cpp b/src/gui/text/qstatictext.cpp
index 8fe4c47..6c504a7 100644
--- a/src/gui/text/qstatictext.cpp
+++ b/src/gui/text/qstatictext.cpp
@@ -99,20 +99,27 @@ QT_BEGIN_NAMESPACE
point with no boundaries, and also when QPainter::drawText() is called with a bounding
rectangle.
- If a bounding rectangle is not required, create a QStaticText object without setting a maximum
- size. The text will then occupy a single line.
+ If a bounding rectangle is not required, create a QStaticText object without setting a preferred
+ text width. The text will then occupy a single line.
- If you set a maximum size on the QStaticText object, this will bound the text. The text will
- be formatted so that no line exceeds the given width. When the object is painted, it will
- be clipped at the given size. The position of the text is decided by the argument
- passed to QPainter::drawStaticText() and can change from call to call with a minimal impact
- on performance.
+ If you set a text width on the QStaticText object, this will bound the text. The text will
+ be formatted so that no line exceeds the given width. The text width set for QStaticText will
+ not automatically be used for clipping. To achieve clipping in addition to line breaks, use
+ QPainter::setClipRect(). The position of the text is decided by the argument passed to
+ QPainter::drawStaticText() and can change from call to call with a minimal impact on
+ performance.
QStaticText will attempt to guess the format of the input text using Qt::mightBeRichText().
To force QStaticText to display its contents as either plain text or rich text, use the
function QStaticText::setTextFormat() and pass in, respectively, Qt::PlainText and
Qt::RichText.
+ If it's the first time the static text is drawn, or if the static text, or the painter's font
+ or matrix have been altered since the last time it was drawn, the text's layout has to be
+ recalculated. This will impose an overhead on the QPainter::drawStaticText() call where the
+ relayout occurs. To avoid this overhead in the paint event, you can call prepare() ahead of
+ time to ensure that the layout is calculated.
+
\sa QPainter::drawText(), QPainter::drawStaticText(), QTextLayout, QTextDocument
*/
@@ -143,12 +150,11 @@ QStaticText::QStaticText()
If an invalid size is passed for \a size the text will be unbounded.
*/
-QStaticText::QStaticText(const QString &text, const QSizeF &size)
+QStaticText::QStaticText(const QString &text)
: data(new QStaticTextPrivate)
{
data->text = text;
- data->maximumSize = size;
- data->init();
+ data->invalidate();
}
/*!
@@ -177,17 +183,17 @@ void QStaticText::detach()
}
/*!
- Prepares the QStaticText object for being painted with the given \a matrix and the given
- \a font to avoid overhead when the actual drawStaticText() call is made.
+ Prepares the QStaticText object for being painted with the given \a matrix and the given \a font
+ to avoid overhead when the actual drawStaticText() call is made.
- When drawStaticText() is called, the layout of the QStaticText will be recalculated if the
- painter's font or matrix is different from the one used for the currently cached layout. By
- default, QStaticText will use a default constructed QFont and an identity matrix to create
- its layout.
+ When drawStaticText() is called, the layout of the QStaticText will be recalculated if any part
+ of the QStaticText object has changed since the last time it was drawn. It will also be
+ recalculated if the painter's font or matrix are not the same as when the QStaticText was last
+ drawn.
- To avoid the overhead of creating the layout the first time you draw the QStaticText with
- a painter whose matrix or font are different from the defaults, you can use the prepare()
- function and pass in the matrix and font you expect to use when drawing the text.
+ To avoid the overhead of creating the layout the first time you draw the QStaticText after
+ making changes, you can use the prepare() function and pass in the \a matrix and \a font you
+ expect to use when drawing the text.
\sa QPainter::setFont(), QPainter::setMatrix()
*/
@@ -209,7 +215,7 @@ QStaticText &QStaticText::operator=(const QStaticText &other)
}
/*!
- Compares \a other to this QStaticText. Returns true if the texts, fonts and maximum sizes
+ Compares \a other to this QStaticText. Returns true if the texts, fonts and text widths
are equal.
*/
bool QStaticText::operator==(const QStaticText &other) const
@@ -217,7 +223,7 @@ bool QStaticText::operator==(const QStaticText &other) const
return (data == other.data
|| (data->text == other.data->text
&& data->font == other.data->font
- && data->maximumSize == other.data->maximumSize));
+ && data->textWidth == other.data->textWidth));
}
/*!
@@ -232,7 +238,7 @@ bool QStaticText::operator!=(const QStaticText &other) const
/*!
Sets the text of the QStaticText to \a text.
- \note This function will cause the layout of the text to be recalculated.
+ \note This function will cause the layout of the text to require recalculation.
\sa text()
*/
@@ -240,7 +246,7 @@ void QStaticText::setText(const QString &text)
{
detach();
data->text = text;
- data->init();
+ data->invalidate();
}
/*!
@@ -250,7 +256,7 @@ void QStaticText::setText(const QString &text)
displayed as is, whereas it will be interpreted as HTML if the format is Qt::RichText. HTML tags
that alter the font of the text, its color, or its layout are supported by QStaticText.
- \note This function will cause the layout of the text to be recalculated.
+ \note This function will cause the layout of the text to require recalculation.
\sa textFormat(), setText(), text()
*/
@@ -258,7 +264,7 @@ void QStaticText::setTextFormat(Qt::TextFormat textFormat)
{
detach();
data->textFormat = textFormat;
- data->init();
+ data->invalidate();
}
/*!
@@ -282,12 +288,14 @@ QString QStaticText::text() const
}
/*!
- Sets the performance hint of the QStaticText. This hint can be used to customize how much
- caching is done internally to improve performance.
+ Sets the performance hint of the QStaticText according to the \a
+ performanceHint provided. The \a performanceHint is used to
+ customize how much caching is done internally to improve
+ performance.
The default is QStaticText::ModerateCaching.
- \note This function will cause the layout of the text to be recalculated.
+ \note This function will cause the layout of the text to require recalculation.
\sa performanceHint()
*/
@@ -299,7 +307,7 @@ void QStaticText::setPerformanceHint(PerformanceHint performanceHint)
}
detach();
data->useBackendOptimizations = (performanceHint == AggressiveCaching);
- data->init();
+ data->invalidate();
}
/*!
@@ -313,48 +321,56 @@ QStaticText::PerformanceHint QStaticText::performanceHint() const
}
/*!
- Sets the maximum size of the QStaticText to \a size.
+ Sets the preferred width for this QStaticText. If the text is wider than the specified width,
+ it will be broken into multiple lines and grow vertically. If the text cannot be split into
+ multiple lines, it will be larger than the specified \a textWidth.
- \note This function will cause the layout of the text to be recalculated.
+ Setting the preferred text width to a negative number will cause the text to be unbounded.
- \sa maximumSize(), size()
+ Use size() to get the actual size of the text.
+
+ \note This function will cause the layout of the text to require recalculation.
+
+ \sa textWidth(), size()
*/
-void QStaticText::setMaximumSize(const QSizeF &size)
+void QStaticText::setTextWidth(qreal textWidth)
{
detach();
- data->maximumSize = size;
- data->init();
+ data->textWidth = textWidth;
+ data->invalidate();
}
/*!
- Returns the maximum size of the QStaticText.
+ Returns the preferred width for this QStaticText.
- \sa setMaximumSize()
+ \sa setTextWidth()
*/
-QSizeF QStaticText::maximumSize() const
+qreal QStaticText::textWidth() const
{
- return data->maximumSize;
+ return data->textWidth;
}
/*!
Returns the size of the bounding rect for this QStaticText.
- \sa maximumSize()
+ \sa textWidth()
*/
QSizeF QStaticText::size() const
{
+ if (data->needsRelayout)
+ data->init();
return data->actualSize;
}
QStaticTextPrivate::QStaticTextPrivate()
- : items(0), itemCount(0), glyphPool(0), positionPool(0), needsClipRect(false),
- useBackendOptimizations(false), textFormat(Qt::AutoText)
+ : items(0), itemCount(0), glyphPool(0), positionPool(0), textWidth(-1.0),
+ needsRelayout(true), useBackendOptimizations(false), textFormat(Qt::AutoText)
{
}
QStaticTextPrivate::QStaticTextPrivate(const QStaticTextPrivate &other)
- : text(other.text), font(other.font), maximumSize(other.maximumSize), matrix(other.matrix),
- items(0), itemCount(0), glyphPool(0), positionPool(0), needsClipRect(false),
+ : text(other.text), font(other.font), textWidth(other.textWidth), matrix(other.matrix),
+ items(0), itemCount(0), glyphPool(0), positionPool(0), needsRelayout(true),
useBackendOptimizations(other.useBackendOptimizations), textFormat(other.textFormat)
{
}
@@ -386,8 +402,15 @@ namespace {
m_expectedItemCount(expectedItemCount),
m_expectedGlyphCount(expectedGlyphCount),
m_glyphPool(glyphPool),
- m_positionPool(positionPool)
+ m_positionPool(positionPool),
+ m_dirtyPen(false)
+ {
+ }
+
+ virtual void updateState(const QPaintEngineState &newState)
{
+ if (newState.state() & QPaintEngine::DirtyPen)
+ m_dirtyPen = true;
}
virtual void drawTextItem(const QPointF &position, const QTextItem &textItem)
@@ -410,7 +433,8 @@ namespace {
currentItem->numGlyphs = ti.glyphs.numGlyphs;
currentItem->glyphs = m_glyphPool;
currentItem->glyphPositions = m_positionPool;
- currentItem->color = state->pen().color();
+ if (m_dirtyPen)
+ currentItem->color = state->pen().color();
QTransform matrix = state->transform();
matrix.translate(position.x(), position.y());
@@ -433,7 +457,6 @@ namespace {
virtual bool begin(QPaintDevice *) { return true; }
virtual bool end() { return true; }
- virtual void updateState(const QPaintEngineState &) {}
virtual void drawPixmap(const QRectF &, const QPixmap &, const QRectF &) {}
virtual Type type() const
{
@@ -459,6 +482,8 @@ namespace {
glyph_t *m_glyphPool;
QFixedPoint *m_positionPool;
+
+ bool m_dirtyPen;
};
class DrawTextItemDevice: public QPaintDevice
@@ -528,41 +553,59 @@ namespace {
};
}
-void QStaticTextPrivate::paintText(const QPointF &pos, QPainter *p)
+void QStaticTextPrivate::paintText(const QPointF &topLeftPosition, QPainter *p)
{
bool preferRichText = textFormat == Qt::RichText
|| (textFormat == Qt::AutoText && Qt::mightBeRichText(text));
if (!preferRichText) {
- if (maximumSize.isValid()) {
- QRectF boundingRect;
- p->drawText(QRectF(pos, maximumSize), Qt::TextWordWrap, text, &boundingRect);
-
- actualSize = boundingRect.size();
- needsClipRect = boundingRect.width() > maximumSize.width()
- || boundingRect.height() > maximumSize.height();
- } else {
- p->drawText(pos, text);
- needsClipRect = false;
-
- QFontMetrics fm(font);
- actualSize = fm.boundingRect(text).size();
+ QTextLayout textLayout;
+ textLayout.setText(text);
+ textLayout.setFont(font);
+
+ qreal leading = QFontMetricsF(font).leading();
+ qreal height = -leading;
+
+ textLayout.beginLayout();
+ while (1) {
+ QTextLine line = textLayout.createLine();
+ if (!line.isValid())
+ break;
+
+ if (textWidth >= 0.0)
+ line.setLineWidth(textWidth);
+ height += leading;
+ line.setPosition(QPointF(0.0, height));
+ height += line.height();
}
+ textLayout.endLayout();
+
+ actualSize = textLayout.boundingRect().size();
+ textLayout.draw(p, topLeftPosition);
} else {
QTextDocument document;
+ QColor color = p->pen().color();
+ document.setDefaultStyleSheet(QString::fromLatin1("body { color: #%1%2%3 }")
+ .arg(QString::number(color.red(), 16), 2, QLatin1Char('0'))
+ .arg(QString::number(color.green(), 16), 2, QLatin1Char('0'))
+ .arg(QString::number(color.blue(), 16), 2, QLatin1Char('0')));
document.setDefaultFont(font);
+ document.setDocumentMargin(0.0);
+ if (textWidth >= 0.0)
+ document.setTextWidth(textWidth);
+#ifndef QT_NO_TEXTHTMLPARSER
document.setHtml(text);
+#else
+ document.setPlainText(text);
+#endif
- QRectF rect = maximumSize.isValid() ? QRectF(pos, maximumSize) : QRectF();
document.adjustSize();
p->save();
- p->translate(pos);
- document.drawContents(p, rect);
+ p->translate(topLeftPosition);
+ document.drawContents(p);
p->restore();
+
actualSize = document.size();
- needsClipRect = maximumSize.isValid()
- && (actualSize.width() > maximumSize.width()
- || actualSize.height() > maximumSize.height());
}
}
@@ -609,6 +652,7 @@ void QStaticTextPrivate::init()
paintText(QPointF(0, 0), &painter);
}
+ needsRelayout = false;
}
QT_END_NAMESPACE
diff --git a/src/gui/text/qstatictext.h b/src/gui/text/qstatictext.h
index 00d42e0..f3bef93 100644
--- a/src/gui/text/qstatictext.h
+++ b/src/gui/text/qstatictext.h
@@ -66,7 +66,7 @@ public:
};
QStaticText();
- QStaticText(const QString &text, const QSizeF &maximumSize = QSizeF());
+ QStaticText(const QString &text);
QStaticText(const QStaticText &other);
~QStaticText();
@@ -76,12 +76,12 @@ public:
void setTextFormat(Qt::TextFormat textFormat);
Qt::TextFormat textFormat() const;
- void setMaximumSize(const QSizeF &maximumSize);
- QSizeF maximumSize() const;
+ void setTextWidth(qreal textWidth);
+ qreal textWidth() const;
QSizeF size() const;
- void prepare(const QTransform &matrix, const QFont &font);
+ void prepare(const QTransform &matrix = QTransform(), const QFont &font = QFont());
void setPerformanceHint(PerformanceHint performanceHint);
PerformanceHint performanceHint() const;
diff --git a/src/gui/text/qstatictext_p.h b/src/gui/text/qstatictext_p.h
index e758244..f017ed1 100644
--- a/src/gui/text/qstatictext_p.h
+++ b/src/gui/text/qstatictext_p.h
@@ -118,11 +118,16 @@ public:
void init();
void paintText(const QPointF &pos, QPainter *p);
+ void invalidate()
+ {
+ needsRelayout = true;
+ }
+
QAtomicInt ref; // 4 bytes per text
QString text; // 4 bytes per text
QFont font; // 8 bytes per text
- QSizeF maximumSize; // 16 bytes per text
+ qreal textWidth; // 8 bytes per text
QSizeF actualSize; // 16 bytes per text
QPointF position; // 16 bytes per text
@@ -132,11 +137,11 @@ public:
glyph_t *glyphPool; // 4 bytes per text
QFixedPoint *positionPool; // 4 bytes per text
- unsigned char needsClipRect : 1; // 1 byte per text
- unsigned char useBackendOptimizations : 1;
+ unsigned char needsRelayout : 1;
+ unsigned char useBackendOptimizations : 1; // 1 byte per text
unsigned char textFormat : 2;
// ================
- // 171 bytes per text
+ // 163 bytes per text
static QStaticTextPrivate *get(const QStaticText *q);
};
diff --git a/src/gui/text/qsyntaxhighlighter.cpp b/src/gui/text/qsyntaxhighlighter.cpp
index 6750c09..e594b7e 100644
--- a/src/gui/text/qsyntaxhighlighter.cpp
+++ b/src/gui/text/qsyntaxhighlighter.cpp
@@ -59,23 +59,24 @@ class QSyntaxHighlighterPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QSyntaxHighlighter)
public:
- inline QSyntaxHighlighterPrivate() : rehighlightPending(false) {}
+ inline QSyntaxHighlighterPrivate()
+ : rehighlightPending(false), inReformatBlocks(false)
+ {}
QPointer<QTextDocument> doc;
void _q_reformatBlocks(int from, int charsRemoved, int charsAdded);
- void reformatBlock(QTextBlock block);
-
+ void reformatBlocks(int from, int charsRemoved, int charsAdded);
+ void reformatBlock(const QTextBlock &block);
+
inline void rehighlight(QTextCursor &cursor, QTextCursor::MoveOperation operation) {
- QObject::disconnect(doc, SIGNAL(contentsChange(int,int,int)),
- q_func(), SLOT(_q_reformatBlocks(int,int,int)));
+ inReformatBlocks = true;
cursor.beginEditBlock();
int from = cursor.position();
cursor.movePosition(operation);
- _q_reformatBlocks(from, 0, cursor.position() - from);
+ reformatBlocks(from, 0, cursor.position() - from);
cursor.endEditBlock();
- QObject::connect(doc, SIGNAL(contentsChange(int,int,int)),
- q_func(), SLOT(_q_reformatBlocks(int,int,int)));
+ inReformatBlocks = false;
}
inline void _q_delayedRehighlight() {
@@ -83,17 +84,19 @@ public:
return;
rehighlightPending = false;
q_func()->rehighlight();
- return;
}
void applyFormatChanges();
QVector<QTextCharFormat> formatChanges;
QTextBlock currentBlock;
bool rehighlightPending;
+ bool inReformatBlocks;
};
void QSyntaxHighlighterPrivate::applyFormatChanges()
{
+ bool formatsChanged = false;
+
QTextLayout *layout = currentBlock.layout();
QList<QTextLayout::FormatRange> ranges = layout->additionalFormats();
@@ -101,19 +104,26 @@ void QSyntaxHighlighterPrivate::applyFormatChanges()
const int preeditAreaStart = layout->preeditAreaPosition();
const int preeditAreaLength = layout->preeditAreaText().length();
- QList<QTextLayout::FormatRange>::Iterator it = ranges.begin();
- while (it != ranges.end()) {
- if (it->start >= preeditAreaStart
- && it->start + it->length <= preeditAreaStart + preeditAreaLength)
- ++it;
- else
- it = ranges.erase(it);
+ if (preeditAreaLength != 0) {
+ QList<QTextLayout::FormatRange>::Iterator it = ranges.begin();
+ while (it != ranges.end()) {
+ if (it->start >= preeditAreaStart
+ && it->start + it->length <= preeditAreaStart + preeditAreaLength) {
+ ++it;
+ } else {
+ it = ranges.erase(it);
+ formatsChanged = true;
+ }
+ }
+ } else if (!ranges.isEmpty()) {
+ ranges.clear();
+ formatsChanged = true;
}
QTextCharFormat emptyFormat;
QTextLayout::FormatRange r;
- r.start = r.length = -1;
+ r.start = -1;
int i = 0;
while (i < formatChanges.count()) {
@@ -135,34 +145,46 @@ void QSyntaxHighlighterPrivate::applyFormatChanges()
r.length = i - r.start;
- if (r.start >= preeditAreaStart) {
- r.start += preeditAreaLength;
- } else if (r.start + r.length >= preeditAreaStart) {
- r.length += preeditAreaLength;
+ if (preeditAreaLength != 0) {
+ if (r.start >= preeditAreaStart)
+ r.start += preeditAreaLength;
+ else if (r.start + r.length >= preeditAreaStart)
+ r.length += preeditAreaLength;
}
ranges << r;
- r.start = r.length = -1;
+ formatsChanged = true;
+ r.start = -1;
}
if (r.start != -1) {
r.length = formatChanges.count() - r.start;
- if (r.start >= preeditAreaStart) {
- r.start += preeditAreaLength;
- } else if (r.start + r.length >= preeditAreaStart) {
- r.length += preeditAreaLength;
+ if (preeditAreaLength != 0) {
+ if (r.start >= preeditAreaStart)
+ r.start += preeditAreaLength;
+ else if (r.start + r.length >= preeditAreaStart)
+ r.length += preeditAreaLength;
}
ranges << r;
+ formatsChanged = true;
}
- layout->setAdditionalFormats(ranges);
+ if (formatsChanged) {
+ layout->setAdditionalFormats(ranges);
+ doc->markContentsDirty(currentBlock.position(), currentBlock.length());
+ }
}
void QSyntaxHighlighterPrivate::_q_reformatBlocks(int from, int charsRemoved, int charsAdded)
{
- Q_UNUSED(charsRemoved);
+ if (!inReformatBlocks)
+ reformatBlocks(from, charsRemoved, charsAdded);
+}
+
+void QSyntaxHighlighterPrivate::reformatBlocks(int from, int charsRemoved, int charsAdded)
+{
rehighlightPending = false;
QTextBlock block = doc->findBlock(from);
@@ -191,21 +213,18 @@ void QSyntaxHighlighterPrivate::_q_reformatBlocks(int from, int charsRemoved, in
formatChanges.clear();
}
-void QSyntaxHighlighterPrivate::reformatBlock(QTextBlock block)
+void QSyntaxHighlighterPrivate::reformatBlock(const QTextBlock &block)
{
Q_Q(QSyntaxHighlighter);
Q_ASSERT_X(!currentBlock.isValid(), "QSyntaxHighlighter::reformatBlock()", "reFormatBlock() called recursively");
currentBlock = block;
- QTextBlock previous = block.previous();
formatChanges.fill(QTextCharFormat(), block.length() - 1);
q->highlightBlock(block.text());
applyFormatChanges();
- doc->markContentsDirty(block.position(), block.length());
-
currentBlock = QTextBlock();
}
@@ -349,8 +368,8 @@ void QSyntaxHighlighter::setDocument(QTextDocument *doc)
if (d->doc) {
connect(d->doc, SIGNAL(contentsChange(int,int,int)),
this, SLOT(_q_reformatBlocks(int,int,int)));
- QTimer::singleShot(0, this, SLOT(_q_delayedRehighlight()));
d->rehighlightPending = true;
+ QTimer::singleShot(0, this, SLOT(_q_delayedRehighlight()));
}
}
@@ -391,11 +410,16 @@ void QSyntaxHighlighter::rehighlight()
void QSyntaxHighlighter::rehighlightBlock(const QTextBlock &block)
{
Q_D(QSyntaxHighlighter);
- if (!d->doc)
+ if (!d->doc || !block.isValid() || block.document() != d->doc)
return;
+ const bool rehighlightPending = d->rehighlightPending;
+
QTextCursor cursor(block);
d->rehighlight(cursor, QTextCursor::EndOfBlock);
+
+ if (rehighlightPending)
+ d->rehighlightPending = rehighlightPending;
}
/*!
@@ -460,7 +484,6 @@ void QSyntaxHighlighter::rehighlightBlock(const QTextBlock &block)
void QSyntaxHighlighter::setFormat(int start, int count, const QTextCharFormat &format)
{
Q_D(QSyntaxHighlighter);
-
if (start < 0 || start >= d->formatChanges.count())
return;
@@ -628,7 +651,7 @@ QTextBlockUserData *QSyntaxHighlighter::currentBlockUserData() const
\since 4.4
Returns the current text block.
- */
+*/
QTextBlock QSyntaxHighlighter::currentBlock() const
{
Q_D(const QSyntaxHighlighter);
diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp
index f345cd1..3c596e5 100644
--- a/src/gui/text/qtextcontrol.cpp
+++ b/src/gui/text/qtextcontrol.cpp
@@ -91,7 +91,7 @@
QT_BEGIN_NAMESPACE
#ifndef QT_NO_CONTEXTMENU
-#if defined(Q_WS_WIN)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
extern bool qt_use_rtl_extensions;
#endif
#endif
@@ -848,9 +848,9 @@ void QTextControl::copy()
QApplication::clipboard()->setMimeData(data);
}
-void QTextControl::paste()
+void QTextControl::paste(QClipboard::Mode mode)
{
- const QMimeData *md = QApplication::clipboard()->mimeData();
+ const QMimeData *md = QApplication::clipboard()->mimeData(mode);
if (md)
insertFromMimeData(md);
}
@@ -1201,7 +1201,8 @@ void QTextControlPrivate::keyPressEvent(QKeyEvent *e)
blockFmt.setIndent(blockFmt.indent() - 1);
cursor.setBlockFormat(blockFmt);
} else {
- cursor.deletePreviousChar();
+ QTextCursor localCursor = cursor;
+ localCursor.deletePreviousChar();
}
goto accept;
}
@@ -1230,11 +1231,17 @@ void QTextControlPrivate::keyPressEvent(QKeyEvent *e)
q->cut();
}
else if (e == QKeySequence::Paste) {
- q->paste();
+ QClipboard::Mode mode = QClipboard::Clipboard;
+#ifdef Q_WS_X11
+ if (e->modifiers() == (Qt::CTRL | Qt::SHIFT) && e->key() == Qt::Key_Insert)
+ mode = QClipboard::Selection;
+#endif
+ q->paste(mode);
}
#endif
else if (e == QKeySequence::Delete) {
- cursor.deleteChar();
+ QTextCursor localCursor = cursor;
+ localCursor.deleteChar();
}
else if (e == QKeySequence::DeleteEndOfWord) {
if (!cursor.hasSelection())
@@ -2075,7 +2082,7 @@ QMenu *QTextControl::createStandardContextMenu(const QPointF &pos, QWidget *pare
}
#endif
-#if defined(Q_WS_WIN)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
if ((d->interactionFlags & Qt::TextEditable) && qt_use_rtl_extensions) {
#else
if (d->interactionFlags & Qt::TextEditable) {
diff --git a/src/gui/text/qtextcontrol_p.h b/src/gui/text/qtextcontrol_p.h
index 40507f4..8399d50 100644
--- a/src/gui/text/qtextcontrol_p.h
+++ b/src/gui/text/qtextcontrol_p.h
@@ -62,6 +62,7 @@
#include <QtCore/qrect.h>
#include <QtGui/qabstracttextdocumentlayout.h>
#include <QtGui/qtextdocumentfragment.h>
+#include <QtGui/qclipboard.h>
#ifdef QT3_SUPPORT
#include <QtGui/qtextobject.h>
@@ -191,7 +192,7 @@ public Q_SLOTS:
#ifndef QT_NO_CLIPBOARD
void cut();
void copy();
- void paste();
+ void paste(QClipboard::Mode mode = QClipboard::Clipboard);
#endif
void undo();
diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp
index 969d5b4..302a349 100644
--- a/src/gui/text/qtextdocument_p.cpp
+++ b/src/gui/text/qtextdocument_p.cpp
@@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE
// The VxWorks DIAB compiler crashes when initializing the anonymouse union with { a7 }
#if !defined(Q_CC_DIAB)
# define QT_INIT_TEXTUNDOCOMMAND(c, a1, a2, a3, a4, a5, a6, a7, a8) \
- QTextUndoCommand c = { a1, a2, 0, 0, a3, a4, a5, a6, { a7 }, a8 }
+ QTextUndoCommand c = { a1, a2, 0, 0, quint8(a3), a4, a5, a6, { a7 }, a8 }
#else
# define QT_INIT_TEXTUNDOCOMMAND(c, a1, a2, a3, a4, a5, a6, a7, a8) \
QTextUndoCommand c = { a1, a2, 0, 0, a3, a4, a5, a6 }; c.blockFormat = a7; c.revision = a8
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 02eae98..6485966 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -81,7 +81,7 @@ public:
void generate(int start, int length, QFont::Capitalization caps)
{
if ((int)caps == (int)QFont::SmallCaps)
- generateScriptItemsSmallCaps(m_string.utf16(), start, length);
+ generateScriptItemsSmallCaps(reinterpret_cast<const ushort *>(m_string.unicode()), start, length);
else if(caps == QFont::Capitalize)
generateScriptItemsCapitalize(start, length);
else if(caps != QFont::MixedCase) {
@@ -1124,14 +1124,13 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const
bool kerningEnabled = this->font(si).d->kerning;
HB_ShaperItem entire_shaper_item;
- entire_shaper_item.kerning_applied = false;
+ qMemSet(&entire_shaper_item, 0, sizeof(entire_shaper_item));
entire_shaper_item.string = reinterpret_cast<const HB_UChar16 *>(layoutData->string.constData());
entire_shaper_item.stringLength = layoutData->string.length();
entire_shaper_item.item.script = (HB_Script)si.analysis.script;
entire_shaper_item.item.pos = si.position;
entire_shaper_item.item.length = length(item);
entire_shaper_item.item.bidiLevel = si.analysis.bidiLevel;
- entire_shaper_item.glyphIndicesPresent = false;
HB_UChar16 upperCased[256]; // XXX what about making this 4096, so we don't have to extend it ever.
if (si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase
@@ -1299,10 +1298,10 @@ QTextEngine::QTextEngine()
}
QTextEngine::QTextEngine(const QString &str, const QFont &f)
- : fnt(f)
+ : text(str),
+ fnt(f)
{
init(this);
- text = str;
}
QTextEngine::~QTextEngine()
@@ -1434,9 +1433,7 @@ void QTextEngine::itemize() const
layoutData->hasBidi = bidiItemize(const_cast<QTextEngine *>(this), analysis, control);
}
- const ushort *unicode = layoutData->string.utf16();
- // correctly assign script, isTab and isObject to the script analysis
- const ushort *uc = unicode;
+ const ushort *uc = reinterpret_cast<const ushort *>(layoutData->string.unicode());
const ushort *e = uc + length;
int lastScript = QUnicodeTables::Common;
while (uc < e) {
@@ -1650,7 +1647,7 @@ glyph_metrics_t QTextEngine::boundingBox(int from, int len) const
}
}
- glyph_t glyph = glyphs.glyphs[logClusters[pos + ilen - 1]];
+ glyph_t glyph = glyphs.glyphs[logClusters[ilen - 1]];
glyph_metrics_t gi = fe->boundingBox(glyph);
if (gi.isValid())
gm.width -= qRound(gi.xoff - gi.x - gi.width);
@@ -2469,7 +2466,7 @@ void QTextEngine::splitItem(int item, int pos) const
if (pos <= 0)
return;
- layoutData->items.insert(item + 1, QScriptItem(layoutData->items[item]));
+ layoutData->items.insert(item + 1, layoutData->items[item]);
QScriptItem &oldItem = layoutData->items[item];
QScriptItem &newItem = layoutData->items[item+1];
newItem.position += pos;
@@ -2612,10 +2609,9 @@ void QTextEngine::resolveAdditionalFormats() const
}
QStackTextEngine::QStackTextEngine(const QString &string, const QFont &f)
- : _layoutData(string, _memory, MemSize)
+ : QTextEngine(string, f),
+ _layoutData(string, _memory, MemSize)
{
- fnt = f;
- text = string;
stackEngine = true;
layoutData = &_layoutData;
}
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index f36cbd2..5054b66 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -382,6 +382,7 @@ struct Q_AUTOTEST_EXPORT QScriptLine
QFixed y;
QFixed width;
QFixed textWidth;
+ QFixed textAdvance;
int from;
signed int length : 29;
mutable uint justified : 1;
diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp
index dca2da5..140cf43 100644
--- a/src/gui/text/qtextformat.cpp
+++ b/src/gui/text/qtextformat.cpp
@@ -3085,7 +3085,8 @@ int QTextFormatCollection::indexForFormat(const QTextFormat &format)
f.d = new QTextFormatPrivate;
f.d->resolveFont(defaultFnt);
- hashes.insert(hash, idx);
+ if (!hashes.contains(hash, idx))
+ hashes.insert(hash, idx);
} QT_CATCH(...) {
formats.pop_back();
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index af91603..312d135 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -1570,6 +1570,20 @@ qreal QTextLine::naturalTextWidth() const
return eng->lines[i].textWidth.toReal();
}
+/*! \since 4.7
+ Returns the horizontal advance of the text. The advance of the text
+ is the distance from its position to the next position at which
+ text would naturally be drawn.
+
+ By adding the advance to the position of the text line and using this
+ as the position of a second text line, you will be able to position
+ the two lines side-by-side without gaps in-between.
+*/
+qreal QTextLine::horizontalAdvance() const
+{
+ return eng->lines[i].textAdvance.toReal();
+}
+
/*!
Lays out the line with the given \a width. The line is filled from
its starting position with as many characters as will fit into
@@ -1644,28 +1658,67 @@ namespace {
struct LineBreakHelper
{
- LineBreakHelper() : glyphCount(0), maxGlyphs(0), manualWrap(false) {}
+ LineBreakHelper()
+ : glyphCount(0), maxGlyphs(0), currentPosition(0), fontEngine(0), logClusters(0),
+ manualWrap(false)
+ {
+ }
+
QScriptLine tmpData;
QScriptLine spaceData;
+ QGlyphLayout glyphs;
+
int glyphCount;
int maxGlyphs;
+ int currentPosition;
QFixed minw;
QFixed softHyphenWidth;
QFixed rightBearing;
+ QFixed minimumRightBearing;
+
+ QFontEngine *fontEngine;
+ const unsigned short *logClusters;
bool manualWrap;
bool checkFullOtherwiseExtend(QScriptLine &line);
+
+ QFixed calculateNewWidth(const QScriptLine &line) const {
+ return line.textWidth + tmpData.textWidth + spaceData.textWidth + softHyphenWidth
+ - qMin(rightBearing, QFixed());
+ }
+
+ inline glyph_t currentGlyph() const
+ {
+ Q_ASSERT(currentPosition > 0);
+ return glyphs.glyphs[logClusters[currentPosition - 1]];
+ }
+
+ inline void adjustRightBearing()
+ {
+ if (currentPosition <= 0)
+ return;
+
+ qreal rb;
+ fontEngine->getGlyphBearings(currentGlyph(), 0, &rb);
+ rightBearing = qMin(QFixed(), QFixed::fromReal(rb));
+ }
+
+ inline void resetRightBearing()
+ {
+ rightBearing = QFixed(1); // Any positive number is defined as invalid since only
+ // negative right bearings are interesting to us.
+ }
};
inline bool LineBreakHelper::checkFullOtherwiseExtend(QScriptLine &line)
{
LB_DEBUG("possible break width %f, spacew=%f", tmpData.textWidth.toReal(), spaceData.textWidth.toReal());
- QFixed newWidth = line.textWidth + tmpData.textWidth + spaceData.textWidth + softHyphenWidth + rightBearing;
+ QFixed newWidth = calculateNewWidth(line);
if (line.length && !manualWrap && (newWidth > line.width || glyphCount > maxGlyphs))
return true;
@@ -1741,13 +1794,12 @@ void QTextLine::layout_helper(int maxGlyphs)
Qt::Alignment alignment = eng->option.alignment();
const HB_CharAttributes *attributes = eng->attributes();
- int pos = line.from;
+ lbh.currentPosition = line.from;
int end = 0;
- QGlyphLayout glyphs;
- const unsigned short *logClusters = eng->layoutData->logClustersPtr;
+ lbh.logClusters = eng->layoutData->logClustersPtr;
while (newItem < eng->layoutData->items.size()) {
- lbh.rightBearing = 0;
+ lbh.resetRightBearing();
lbh.softHyphenWidth = 0;
if (newItem != item) {
item = newItem;
@@ -1755,13 +1807,19 @@ void QTextLine::layout_helper(int maxGlyphs)
if (!current.num_glyphs) {
eng->shape(item);
attributes = eng->attributes();
- logClusters = eng->layoutData->logClustersPtr;
+ lbh.logClusters = eng->layoutData->logClustersPtr;
}
- pos = qMax(line.from, current.position);
+ lbh.currentPosition = qMax(line.from, current.position);
end = current.position + eng->length(item);
- glyphs = eng->shapedGlyphs(&current);
+ lbh.glyphs = eng->shapedGlyphs(&current);
}
const QScriptItem &current = eng->layoutData->items[item];
+ QFontEngine *fontEngine = eng->fontEngine(current);
+ if (lbh.fontEngine != fontEngine) {
+ lbh.fontEngine = fontEngine;
+ lbh.minimumRightBearing = qMin(QFixed(),
+ QFixed::fromReal(fontEngine->minRightBearing()));
+ }
lbh.tmpData.leading = qMax(lbh.tmpData.leading + lbh.tmpData.ascent,
current.leading + current.ascent) - qMax(lbh.tmpData.ascent,
@@ -1791,8 +1849,8 @@ void QTextLine::layout_helper(int maxGlyphs)
if (!line.length && !lbh.tmpData.length)
line.setDefaultHeight(eng);
if (eng->option.flags() & QTextOption::ShowLineAndParagraphSeparators) {
- addNextCluster(pos, end, lbh.tmpData, lbh.glyphCount,
- current, logClusters, glyphs);
+ addNextCluster(lbh.currentPosition, end, lbh.tmpData, lbh.glyphCount,
+ current, lbh.logClusters, lbh.glyphs);
} else {
lbh.tmpData.length++;
}
@@ -1811,10 +1869,10 @@ void QTextLine::layout_helper(int maxGlyphs)
++lbh.glyphCount;
if (lbh.checkFullOtherwiseExtend(line))
goto found;
- } else if (attributes[pos].whiteSpace) {
- while (pos < end && attributes[pos].whiteSpace)
- addNextCluster(pos, end, lbh.spaceData, lbh.glyphCount,
- current, logClusters, glyphs);
+ } else if (attributes[lbh.currentPosition].whiteSpace) {
+ while (lbh.currentPosition < end && attributes[lbh.currentPosition].whiteSpace)
+ addNextCluster(lbh.currentPosition, end, lbh.spaceData, lbh.glyphCount,
+ current, lbh.logClusters, lbh.glyphs);
if (!lbh.manualWrap && lbh.spaceData.textWidth > line.width) {
lbh.spaceData.textWidth = line.width; // ignore spaces that fall out of the line.
@@ -1823,19 +1881,19 @@ void QTextLine::layout_helper(int maxGlyphs)
} else {
bool sb_or_ws = false;
do {
- addNextCluster(pos, end, lbh.tmpData, lbh.glyphCount,
- current, logClusters, glyphs);
+ addNextCluster(lbh.currentPosition, end, lbh.tmpData, lbh.glyphCount,
+ current, lbh.logClusters, lbh.glyphs);
- if (attributes[pos].whiteSpace || attributes[pos-1].lineBreakType != HB_NoBreak) {
+ if (attributes[lbh.currentPosition].whiteSpace || attributes[lbh.currentPosition-1].lineBreakType != HB_NoBreak) {
sb_or_ws = true;
break;
- } else if (breakany && attributes[pos].charStop) {
+ } else if (breakany && attributes[lbh.currentPosition].charStop) {
break;
}
- } while (pos < end);
+ } while (lbh.currentPosition < end);
lbh.minw = qMax(lbh.tmpData.textWidth, lbh.minw);
- if (pos && attributes[pos - 1].lineBreakType == HB_SoftHyphen) {
+ if (lbh.currentPosition && attributes[lbh.currentPosition - 1].lineBreakType == HB_SoftHyphen) {
// if we are splitting up a word because of
// a soft hyphen then we ...
//
@@ -1853,41 +1911,40 @@ void QTextLine::layout_helper(int maxGlyphs)
// and thus become invisible again.
//
if (line.length)
- lbh.softHyphenWidth = glyphs.advances_x[logClusters[pos - 1]];
+ lbh.softHyphenWidth = lbh.glyphs.advances_x[lbh.logClusters[lbh.currentPosition - 1]];
else if (breakany)
- lbh.tmpData.textWidth += glyphs.advances_x[logClusters[pos - 1]];
+ lbh.tmpData.textWidth += lbh.glyphs.advances_x[lbh.logClusters[lbh.currentPosition - 1]];
}
// The actual width of the text needs to take the right bearing into account. The
// right bearing is left-ward, which means that if the rightmost pixel is to the right
// of the advance of the glyph, the bearing will be negative. We flip the sign
// for the code to be more readable. Logic borrowed from qfontmetrics.cpp.
- if (pos) {
- QFontEngine *fontEngine = eng->fontEngine(current);
- glyph_t glyph = glyphs.glyphs[logClusters[pos - 1]];
- glyph_metrics_t gi = fontEngine->boundingBox(glyph);
- if (gi.isValid())
- lbh.rightBearing = qMax(QFixed(), -(gi.xoff - gi.x - gi.width));
- }
+ // We ignore the right bearing if the minimum negative bearing is too little to
+ // expand the text beyond the edge.
+ if (sb_or_ws|breakany) {
+ if (lbh.calculateNewWidth(line) + lbh.minimumRightBearing > line.width)
+ lbh.adjustRightBearing();
+ if (lbh.checkFullOtherwiseExtend(line)) {
+ if (!breakany) {
+ line.textWidth += lbh.softHyphenWidth;
+ }
- if ((sb_or_ws|breakany) && lbh.checkFullOtherwiseExtend(line)) {
- if (!breakany) {
- line.textWidth += lbh.softHyphenWidth;
+ goto found;
}
-
- line.textWidth += lbh.rightBearing;
-
- goto found;
}
}
- if (pos == end)
+ if (lbh.currentPosition == end)
newItem = item + 1;
}
LB_DEBUG("reached end of line");
lbh.checkFullOtherwiseExtend(line);
- line.textWidth += lbh.rightBearing;
-
found:
+ if (lbh.rightBearing > 0) // If right bearing has not yet been adjusted
+ lbh.adjustRightBearing();
+ line.textAdvance = line.textWidth;
+ line.textWidth -= qMin(QFixed(), lbh.rightBearing);
+
if (line.length == 0) {
LB_DEBUG("no break available in line, adding temp: length %d, width %f, space: length %d, width %f",
lbh.tmpData.length, lbh.tmpData.textWidth.toReal(),
diff --git a/src/gui/text/qtextlayout.h b/src/gui/text/qtextlayout.h
index edae7de..8c93ed6 100644
--- a/src/gui/text/qtextlayout.h
+++ b/src/gui/text/qtextlayout.h
@@ -202,6 +202,7 @@ public:
bool leadingIncluded() const;
qreal naturalTextWidth() const;
+ qreal horizontalAdvance() const;
QRectF naturalTextRect() const;
enum Edge {
diff --git a/src/gui/text/qzip.cpp b/src/gui/text/qzip.cpp
index d30c996..6f099a9 100644
--- a/src/gui/text/qzip.cpp
+++ b/src/gui/text/qzip.cpp
@@ -280,6 +280,21 @@ static QFile::Permissions modeToPermissions(quint32 mode)
return ret;
}
+static QDateTime readMSDosDate(const uchar *src)
+{
+ uint dosDate = readUInt(src);
+ quint64 uDate;
+ uDate = (quint64)(dosDate >> 16);
+ uint tm_mday = (uDate & 0x1f);
+ uint tm_mon = ((uDate & 0x1E0) >> 5);
+ uint tm_year = (((uDate & 0x0FE00) >> 9) + 1980);
+ uint tm_hour = ((dosDate & 0xF800) >> 11);
+ uint tm_min = ((dosDate & 0x7E0) >> 5);
+ uint tm_sec = ((dosDate & 0x1f) << 1);
+
+ return QDateTime(QDate(tm_year, tm_mon, tm_mday), QTime(tm_hour, tm_min, tm_sec));
+}
+
struct LocalFileHeader
{
uchar signature[4]; // 0x04034b50
@@ -343,7 +358,7 @@ struct FileHeader
};
QZipReader::FileInfo::FileInfo()
- : isDir(false), isFile(true), isSymLink(false), crc32(0), size(0)
+ : isDir(false), isFile(false), isSymLink(false), crc32(0), size(0)
{
}
@@ -365,9 +380,15 @@ QZipReader::FileInfo& QZipReader::FileInfo::operator=(const FileInfo &other)
permissions = other.permissions;
crc32 = other.crc32;
size = other.size;
+ lastModified = other.lastModified;
return *this;
}
+bool QZipReader::FileInfo::isValid() const
+{
+ return isDir || isFile || isSymLink;
+}
+
class QZipPrivate
{
public:
@@ -403,6 +424,7 @@ void QZipPrivate::fillFileInfo(int index, QZipReader::FileInfo &fileInfo) const
fileInfo.permissions = modeToPermissions(mode);
fileInfo.crc32 = readUInt(header.h.crc_32);
fileInfo.size = readUInt(header.h.uncompressed_size);
+ fileInfo.lastModified = readMSDosDate(header.h.last_mod_file);
}
class QZipReaderPrivate : public QZipPrivate
@@ -750,6 +772,14 @@ QZipReader::~QZipReader()
}
/*!
+ Returns device used for reading zip archive.
+*/
+QIODevice* QZipReader::device() const
+{
+ return d->device;
+}
+
+/*!
Returns true if the user can read the file; otherwise returns false.
*/
bool QZipReader::isReadable() const
@@ -796,6 +826,7 @@ int QZipReader::count() const
/*!
Returns a FileInfo of an entry in the zipfile.
The \a index is the index into the directoy listing of the zipfile.
+ Returns an invalid FileInfo if \a index is out of boundaries.
\sa fileInfoList()
*/
@@ -803,7 +834,8 @@ QZipReader::FileInfo QZipReader::entryInfoAt(int index) const
{
d->scanFiles();
QZipReader::FileInfo fi;
- d->fillFileInfo(index, fi);
+ if (index >= 0 && index < d->fileHeaders.count())
+ d->fillFileInfo(index, fi);
return fi;
}
@@ -1022,6 +1054,14 @@ QZipWriter::~QZipWriter()
}
/*!
+ Returns device used for writing zip archive.
+*/
+QIODevice* QZipWriter::device() const
+{
+ return d->device;
+}
+
+/*!
Returns true if the user can write to the archive; otherwise returns false.
*/
bool QZipWriter::isWritable() const
diff --git a/src/gui/text/qzipreader_p.h b/src/gui/text/qzipreader_p.h
index 9b73373..6466a7b 100644
--- a/src/gui/text/qzipreader_p.h
+++ b/src/gui/text/qzipreader_p.h
@@ -55,6 +55,7 @@
// We mean it.
//
+#include <QtCore/qdatetime.h>
#include <QtCore/qfile.h>
#include <QtCore/qstring.h>
@@ -70,6 +71,8 @@ public:
explicit QZipReader(QIODevice *device);
~QZipReader();
+ QIODevice* device() const;
+
bool isReadable() const;
bool exists() const;
@@ -79,6 +82,7 @@ public:
FileInfo(const FileInfo &other);
~FileInfo();
FileInfo &operator=(const FileInfo &other);
+ bool isValid() const;
QString filePath;
uint isDir : 1;
uint isFile : 1;
@@ -86,6 +90,7 @@ public:
QFile::Permissions permissions;
uint crc32;
qint64 size;
+ QDateTime lastModified;
void *d;
};
diff --git a/src/gui/text/qzipwriter_p.h b/src/gui/text/qzipwriter_p.h
index 9322f4a..a50c172 100644
--- a/src/gui/text/qzipwriter_p.h
+++ b/src/gui/text/qzipwriter_p.h
@@ -69,6 +69,8 @@ public:
explicit QZipWriter(QIODevice *device);
~QZipWriter();
+ QIODevice* device() const;
+
bool isWritable() const;
bool exists() const;
diff --git a/src/gui/util/qcompleter.cpp b/src/gui/util/qcompleter.cpp
index b7be967..c095b3b 100644
--- a/src/gui/util/qcompleter.cpp
+++ b/src/gui/util/qcompleter.cpp
@@ -907,7 +907,7 @@ void QCompleterPrivate::_q_fileSystemModelDirectoryLoaded(const QString &path)
{
Q_Q(QCompleter);
//the path given by QFileSystemModel does not end with /
- if (q->completionPrefix() != path + QLatin1Char('/'))
+ if (!q->completionPrefix().isEmpty() && q->completionPrefix() != path + QLatin1Char('/'))
q->complete();
}
@@ -1110,7 +1110,7 @@ void QCompleter::setPopup(QAbstractItemView *popup)
delete d->popup;
if (popup->model() != d->proxy)
popup->setModel(d->proxy);
-#ifdef Q_OS_MAC
+#if defined(Q_OS_MAC) && !defined(QT_MAC_USE_COCOA)
popup->show();
#else
popup->hide();
diff --git a/src/gui/util/qdesktopservices_s60.cpp b/src/gui/util/qdesktopservices_s60.cpp
index 65b998f..a415180 100644
--- a/src/gui/util/qdesktopservices_s60.cpp
+++ b/src/gui/util/qdesktopservices_s60.cpp
@@ -62,8 +62,8 @@ const TUid KUidMsgTypeSMTP = {0x10001028}; // 268439592
#ifdef Q_WS_S60
# include <pathinfo.h> // PathInfo
# ifdef USE_DOCUMENTHANDLER
-# include <documenthandler.h> // CDocumentHandler
-# include <aknserverapp.h>
+# include <DocumentHandler.h> // CDocumentHandler
+# include <AknServerApp.h>
# endif
#else
# warning CDocumentHandler requires support for S60
diff --git a/src/gui/util/qsystemtrayicon_mac.mm b/src/gui/util/qsystemtrayicon_mac.mm
index 348657e..d943c8c 100644
--- a/src/gui/util/qsystemtrayicon_mac.mm
+++ b/src/gui/util/qsystemtrayicon_mac.mm
@@ -529,7 +529,11 @@ private:
[item setToolTip:(NSString*)QCFString::toCFStringRef(action->toolTip())];
const QIcon icon = action->icon();
if(!icon.isNull()) {
+#ifndef QT_MAC_USE_COCOA
+ const short scale = GetMBarHeight();
+#else
const short scale = [[NSApp mainMenu] menuBarHeight];
+#endif
NSImage *nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(icon.pixmap(QSize(scale, scale))));
[item setImage: nsimage];
[nsimage release];
diff --git a/src/gui/util/util.pri b/src/gui/util/util.pri
index cdbb7cc..bd2af85 100644
--- a/src/gui/util/util.pri
+++ b/src/gui/util/util.pri
@@ -41,5 +41,12 @@ embedded {
symbian {
LIBS += -lsendas2 -letext -lapmime
- contains(QT_CONFIG, s60): LIBS += -lplatformenv -lcommonui
+ contains(QT_CONFIG, s60) {
+ LIBS += -lplatformenv
+ contains(CONFIG, is_using_gnupoc) {
+ LIBS += -lcommonui
+ } else {
+ LIBS += -lCommonUI
+ }
+ }
}
diff --git a/src/gui/widgets/qabstractslider.cpp b/src/gui/widgets/qabstractslider.cpp
index 2888490..6a01d68 100644
--- a/src/gui/widgets/qabstractslider.cpp
+++ b/src/gui/widgets/qabstractslider.cpp
@@ -712,7 +712,15 @@ bool QAbstractSliderPrivate::scrollByDelta(Qt::Orientation orientation, Qt::Keyb
offset_accumulated = 0;
offset_accumulated += stepsToScrollF;
+#ifndef Q_WS_MAC
+ // Dont't scroll more than one page in any case:
stepsToScroll = qBound(-pageStep, int(offset_accumulated), pageStep);
+#else
+ // Native UI-elements on Mac can scroll hundreds of lines at a time as
+ // a result of acceleration. So keep the same behaviour in Qt, and
+ // dont restrict stepsToScroll to certain maximum (pageStep):
+ stepsToScroll = int(offset_accumulated);
+#endif
offset_accumulated -= int(offset_accumulated);
if (stepsToScroll == 0)
return false;
@@ -756,12 +764,12 @@ void QAbstractSlider::keyPressEvent(QKeyEvent *ev)
SliderAction action = SliderNoAction;
#ifdef QT_KEYPAD_NAVIGATION
if (ev->isAutoRepeat()) {
- if (d->firstRepeat.isNull())
- d->firstRepeat = QTime::currentTime();
+ if (!d->firstRepeat.isValid())
+ d->firstRepeat.start();
else if (1 == d->repeatMultiplier) {
// This is the interval in milli seconds which one key repetition
// takes.
- const int repeatMSecs = d->firstRepeat.msecsTo(QTime::currentTime());
+ const int repeatMSecs = d->firstRepeat.elapsed();
/**
* The time it takes to currently navigate the whole slider.
@@ -779,8 +787,8 @@ void QAbstractSlider::keyPressEvent(QKeyEvent *ev)
}
}
- else if (!d->firstRepeat.isNull()) {
- d->firstRepeat = QTime();
+ else if (!d->firstRepeat.isValid()) {
+ d->firstRepeat.invalidate();
d->repeatMultiplier = 1;
}
diff --git a/src/gui/widgets/qabstractslider_p.h b/src/gui/widgets/qabstractslider_p.h
index 6e6ff6e..19d1fca 100644
--- a/src/gui/widgets/qabstractslider_p.h
+++ b/src/gui/widgets/qabstractslider_p.h
@@ -54,6 +54,7 @@
//
#include "QtCore/qbasictimer.h"
+#include "QtCore/qelapsedtimer.h"
#include "private/qwidget_p.h"
#include "qstyle.h"
@@ -103,7 +104,7 @@ public:
/**
* The time of when the first auto repeating key press event occurs.
*/
- QTime firstRepeat;
+ QElapsedTimer firstRepeat;
#endif
diff --git a/src/gui/widgets/qabstractspinbox.cpp b/src/gui/widgets/qabstractspinbox.cpp
index 4a6235c..7e2f20d 100644
--- a/src/gui/widgets/qabstractspinbox.cpp
+++ b/src/gui/widgets/qabstractspinbox.cpp
@@ -1248,8 +1248,11 @@ void QAbstractSpinBox::contextMenuEvent(QContextMenuEvent *event)
#else
Q_D(QAbstractSpinBox);
- d->reset();
QPointer<QMenu> menu = d->edit->createStandardContextMenu();
+ if (!menu)
+ return;
+
+ d->reset();
QAction *selAll = new QAction(tr("&Select All"), menu);
menu->insertAction(d->edit->d_func()->selectAllAction,
diff --git a/src/gui/widgets/qcheckbox.cpp b/src/gui/widgets/qcheckbox.cpp
index 4e0ff66..bc0900e 100644
--- a/src/gui/widgets/qcheckbox.cpp
+++ b/src/gui/widgets/qcheckbox.cpp
@@ -291,7 +291,7 @@ QSize QCheckBox::sizeHint() const
QFontMetrics fm = fontMetrics();
QStyleOptionButton opt;
initStyleOption(&opt);
- QSize sz = style()->itemTextRect(fm, QRect(0, 0, 1, 1), Qt::TextShowMnemonic, false,
+ QSize sz = style()->itemTextRect(fm, QRect(), Qt::TextShowMnemonic, false,
text()).size();
if (!opt.icon.isNull())
sz = QSize(sz.width() + opt.iconSize.width() + 4, qMax(sz.height(), opt.iconSize.height()));
diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp
index f71d250..b1a27f2 100644
--- a/src/gui/widgets/qcombobox.cpp
+++ b/src/gui/widgets/qcombobox.cpp
@@ -108,7 +108,15 @@ QStyleOptionMenuItem QComboMenuDelegate::getStyleOption(const QStyleOptionViewIt
const QModelIndex &index) const
{
QStyleOptionMenuItem menuOption;
- menuOption.palette = option.palette.resolve(QApplication::palette("QMenu"));
+
+ QPalette resolvedpalette = option.palette.resolve(QApplication::palette("QMenu"));
+ QVariant value = index.data(Qt::ForegroundRole);
+ if (qVariantCanConvert<QBrush>(value)) {
+ resolvedpalette.setBrush(QPalette::WindowText, qvariant_cast<QBrush>(value));
+ resolvedpalette.setBrush(QPalette::ButtonText, qvariant_cast<QBrush>(value));
+ resolvedpalette.setBrush(QPalette::Text, qvariant_cast<QBrush>(value));
+ }
+ menuOption.palette = resolvedpalette;
menuOption.state = QStyle::State_None;
if (mCombo->window()->isActiveWindow())
menuOption.state = QStyle::State_Active;
@@ -532,9 +540,11 @@ void QComboBoxPrivateContainer::setItemView(QAbstractItemView *itemView)
QStyleOptionComboBox opt = comboStyleOption();
const bool usePopup = combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo);
#ifndef QT_NO_SCROLLBAR
+#ifndef Q_WS_S60
if (usePopup)
view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
#endif
+#endif
if (combo->style()->styleHint(QStyle::SH_ComboBox_ListMouseTracking, &opt, combo) ||
usePopup) {
view->setMouseTracking(true);
@@ -2417,24 +2427,44 @@ void QComboBox::showPopup()
// Position horizontally.
listRect.moveLeft(above.x());
+#ifndef Q_WS_S60
// Position vertically so the curently selected item lines up
// with the combo box.
const QRect currentItemRect = view()->visualRect(view()->currentIndex());
const int offset = listRect.top() - currentItemRect.top();
listRect.moveTop(above.y() + offset - listRect.top());
+#endif
// Clamp the listRect height and vertical position so we don't expand outside the
// available screen geometry.This may override the vertical position, but it is more
// important to show as much as possible of the popup.
const int height = !boundToScreen ? listRect.height() : qMin(listRect.height(), screen.height());
+#ifdef Q_WS_S60
+ //popup needs to be stretched with screen minimum dimension
+ listRect.setHeight(qMin(screen.height(), screen.width()));
+#else
listRect.setHeight(height);
+#endif
+
if (boundToScreen) {
if (listRect.top() < screen.top())
listRect.moveTop(screen.top());
if (listRect.bottom() > screen.bottom())
listRect.moveBottom(screen.bottom());
}
+#ifdef Q_WS_S60
+ if (screen.width() < screen.height()) {
+ // in portait, menu should be positioned above softkeys
+ listRect.moveBottom(screen.bottom());
+ } else {
+ // landscape, menu should be at the right and horizontally centered
+ listRect.setWidth(listRect.height());
+ listRect.moveCenter(screen.center());
+ (opt.direction == Qt::LeftToRight) ? listRect.setRight(screen.right()) :
+ listRect.setLeft(screen.left());
+ }
+#endif
} else if (!boundToScreen || listRect.height() <= belowHeight) {
listRect.moveTopLeft(below);
} else if (listRect.height() <= aboveHeight) {
@@ -2643,6 +2673,34 @@ void QComboBox::changeEvent(QEvent *e)
if (d->lineEdit)
d->updateLineEditGeometry();
d->setLayoutItemMargins(QStyle::SE_ComboBoxLayoutItem);
+
+#ifdef Q_WS_S60
+ if (d->container) {
+ QStyleOptionComboBox opt;
+ initStyleOption(&opt);
+
+ if (style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this)) {
+ const QRect screen = d->popupGeometry(QApplication::desktop()->screenNumber(this));
+
+ QRect listRect(style()->subControlRect(QStyle::CC_ComboBox, &opt,
+ QStyle::SC_ComboBoxListBoxPopup, this));
+ listRect.setHeight(qMin(screen.height(), screen.width()));
+
+ if (screen.width() < screen.height()) {
+ // in portait, menu should be positioned above softkeys
+ listRect.moveBottom(screen.bottom());
+ } else {
+ // landscape, menu should be at the right and horizontally centered
+ listRect.setWidth(listRect.height());
+ listRect.moveCenter(screen.center());
+ (opt.direction == Qt::LeftToRight) ? listRect.setRight(screen.right()) :
+ listRect.setLeft(screen.left());
+ }
+ d->container->setGeometry(listRect);
+ }
+ }
+#endif
+
// ### need to update scrollers etc. as well here
break;
case QEvent::EnabledChange:
diff --git a/src/gui/widgets/qcombobox.h b/src/gui/widgets/qcombobox.h
index 9b19a66..fb9af9f 100644
--- a/src/gui/widgets/qcombobox.h
+++ b/src/gui/widgets/qcombobox.h
@@ -111,10 +111,10 @@ public:
bool hasFrame() const;
inline int findText(const QString &text,
- Qt::MatchFlags flags = Qt::MatchExactly|Qt::MatchCaseSensitive) const
+ Qt::MatchFlags flags = static_cast<Qt::MatchFlags>(Qt::MatchExactly|Qt::MatchCaseSensitive)) const
{ return findData(text, Qt::DisplayRole, flags); }
int findData(const QVariant &data, int role = Qt::UserRole,
- Qt::MatchFlags flags = Qt::MatchExactly|Qt::MatchCaseSensitive) const;
+ Qt::MatchFlags flags = static_cast<Qt::MatchFlags>(Qt::MatchExactly|Qt::MatchCaseSensitive)) const;
enum InsertPolicy {
NoInsert,
diff --git a/src/gui/widgets/qcombobox_p.h b/src/gui/widgets/qcombobox_p.h
index 74dfdc9..92d85cc 100644
--- a/src/gui/widgets/qcombobox_p.h
+++ b/src/gui/widgets/qcombobox_p.h
@@ -270,7 +270,9 @@ protected:
const QStyleOptionViewItem &option,
const QModelIndex &index) const {
QStyleOptionMenuItem opt = getStyleOption(option, index);
+#ifndef Q_WS_S60
painter->fillRect(option.rect, opt.palette.background());
+#endif
mCombo->style()->drawControl(QStyle::CE_MenuItem, &opt, painter, mCombo);
}
QSize sizeHint(const QStyleOptionViewItem &option,
diff --git a/src/gui/widgets/qdockarealayout.cpp b/src/gui/widgets/qdockarealayout.cpp
index c1b1ea3..806654c 100644
--- a/src/gui/widgets/qdockarealayout.cpp
+++ b/src/gui/widgets/qdockarealayout.cpp
@@ -1985,23 +1985,29 @@ bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*>
emit widget->dockLocationChanged(toDockWidgetArea(dockPos));
}
}
-
+ if (testing) {
+ //was it is not really added to the layout, we need to delete the object here
+ delete item.widgetItem;
+ }
}
} else if (nextMarker == SequenceMarker) {
int dummy;
#ifdef QT_NO_TABBAR
const int tabBarShape = 0;
#endif
- QDockAreaLayoutInfo *info = new QDockAreaLayoutInfo(sep, dockPos, o,
- tabBarShape, mainWindow);
- QDockAreaLayoutItem item(info);
+ QDockAreaLayoutItem item(new QDockAreaLayoutInfo(sep, dockPos, o,
+ tabBarShape, mainWindow));
stream >> item.pos >> item.size >> dummy >> dummy;
- if (!info->restoreState(stream, widgets, testing))
+ //we need to make sure the element is in the list so the dock widget can eventually be docked correctly
+ if (!testing)
+ item_list.append(item);
+
+ //here we need to make sure we change the item in the item_list
+ QDockAreaLayoutItem &lastItem = testing ? item : item_list.last();
+
+ if (!lastItem.subinfo->restoreState(stream, widgets, testing))
return false;
- if (!testing) {
- item_list.append(item);
- }
} else {
return false;
}
diff --git a/src/gui/widgets/qeffects.cpp b/src/gui/widgets/qeffects.cpp
index dd7fc48..a56d093 100644
--- a/src/gui/widgets/qeffects.cpp
+++ b/src/gui/widgets/qeffects.cpp
@@ -41,7 +41,6 @@
#include "qapplication.h"
#ifndef QT_NO_EFFECTS
-#include "qdatetime.h"
#include "qdesktopwidget.h"
#include "qeffects_p.h"
#include "qevent.h"
@@ -50,6 +49,7 @@
#include "qpixmap.h"
#include "qpointer.h"
#include "qtimer.h"
+#include "qelapsedtimer.h"
#include "qdebug.h"
QT_BEGIN_NAMESPACE
@@ -103,7 +103,7 @@ private:
int elapsed;
bool showWidget;
QTimer anim;
- QTime checkTime;
+ QElapsedTimer checkTime;
double windowOpacity;
};
@@ -384,7 +384,7 @@ private:
int orientation;
QTimer anim;
- QTime checkTime;
+ QElapsedTimer checkTime;
QPixmap pm;
};
diff --git a/src/gui/widgets/qlabel.cpp b/src/gui/widgets/qlabel.cpp
index b81f04f..bdbd0b0 100644
--- a/src/gui/widgets/qlabel.cpp
+++ b/src/gui/widgets/qlabel.cpp
@@ -53,6 +53,7 @@
#include <qurl.h>
#include "qlabel_p.h"
#include "private/qstylesheetstyle_p.h"
+#include <qmath.h>
QT_BEGIN_NAMESPACE
@@ -661,7 +662,9 @@ QSize QLabelPrivate::sizeForWidth(int w) const
} else {
control->setTextWidth(-1);
}
- br = QRect(QPoint(0, 0), control->size().toSize());
+
+ QSizeF controlSize = control->size();
+ br = QRect(QPoint(0, 0), QSize(qCeil(controlSize.width()), qCeil(controlSize.height())));
// restore state
control->setTextWidth(oldTextWidth);
diff --git a/src/gui/widgets/qlabel_p.h b/src/gui/widgets/qlabel_p.h
index 21eb128..fba7224 100644
--- a/src/gui/widgets/qlabel_p.h
+++ b/src/gui/widgets/qlabel_p.h
@@ -55,7 +55,7 @@
#include "qlabel.h"
-#include "../text/qtextdocumentlayout_p.h"
+#include "private/qtextdocumentlayout_p.h"
#include "private/qtextcontrol_p.h"
#include "qtextdocumentfragment.h"
#include "qframe_p.h"
diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp
index db099e8..42df800 100644
--- a/src/gui/widgets/qlinecontrol.cpp
+++ b/src/gui/widgets/qlinecontrol.cpp
@@ -65,7 +65,7 @@ QT_BEGIN_NAMESPACE
Updates the display text based of the current edit text
If the text has changed will emit displayTextChanged()
*/
-void QLineControl::updateDisplayText()
+void QLineControl::updateDisplayText(bool forceUpdate)
{
QString orig = m_textLayout.text();
QString str;
@@ -102,7 +102,7 @@ void QLineControl::updateDisplayText()
m_textLayout.endLayout();
m_ascent = qRound(l.ascent());
- if (str != orig)
+ if (str != orig || forceUpdate)
emit displayTextChanged(str);
}
@@ -136,9 +136,9 @@ void QLineControl::copy(QClipboard::Mode mode) const
\sa insert()
*/
-void QLineControl::paste()
+void QLineControl::paste(QClipboard::Mode clipboardMode)
{
- QString clip = QApplication::clipboard()->text(QClipboard::Clipboard);
+ QString clip = QApplication::clipboard()->text(clipboardMode);
if (!clip.isEmpty() || hasSelectedText()) {
separate(); //make it a separate undo/redo command
insert(clip);
@@ -476,7 +476,7 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event)
}
}
m_textLayout.setAdditionalFormats(formats);
- updateDisplayText();
+ updateDisplayText(/*force*/ true);
if (cursorPositionChanged)
emitCursorPositionChanged();
if (isGettingInput)
@@ -1576,8 +1576,14 @@ void QLineControl::processKeyEvent(QKeyEvent* event)
copy();
}
else if (event == QKeySequence::Paste) {
- if (!isReadOnly())
- paste();
+ if (!isReadOnly()) {
+ QClipboard::Mode mode = QClipboard::Clipboard;
+#ifdef Q_WS_X11
+ if (event->modifiers() == (Qt::CTRL | Qt::SHIFT) && event->key() == Qt::Key_Insert)
+ mode = QClipboard::Selection;
+#endif
+ paste(mode);
+ }
}
else if (event == QKeySequence::Cut) {
if (!isReadOnly()) {
@@ -1761,7 +1767,6 @@ void QLineControl::processKeyEvent(QKeyEvent* event)
}
break;
#endif
-
default:
if (!handled)
unknown = true;
diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h
index d6f2705..5da1831 100644
--- a/src/gui/widgets/qlinecontrol_p.h
+++ b/src/gui/widgets/qlinecontrol_p.h
@@ -94,136 +94,207 @@ public:
delete [] m_maskData;
}
- int nextMaskBlank(int pos);
- int prevMaskBlank(int pos);
+ int nextMaskBlank(int pos)
+ {
+ int c = findInMask(pos, true, false);
+ m_separator |= (c != pos);
+ return (c != -1 ? c : m_maxLength);
+ }
+
+ int prevMaskBlank(int pos)
+ {
+ int c = findInMask(pos, false, false);
+ m_separator |= (c != pos);
+ return (c != -1 ? c : 0);
+ }
+
+ bool isUndoAvailable() const { return !m_readOnly && m_undoState; }
+ bool isRedoAvailable() const { return !m_readOnly && m_undoState < (int)m_history.size(); }
+ void clearUndo() { m_history.clear(); m_modifiedState = m_undoState = 0; }
- bool isUndoAvailable() const;
- bool isRedoAvailable() const;
- void clearUndo();
- bool isModified() const;
- void setModified(bool modified);
+ bool isModified() const { return m_modifiedState != m_undoState; }
+ void setModified(bool modified) { m_modifiedState = modified ? -1 : m_undoState; }
- bool allSelected() const;
- bool hasSelectedText() const;
+ bool allSelected() const { return !m_text.isEmpty() && m_selstart == 0 && m_selend == (int)m_text.length(); }
+ bool hasSelectedText() const { return !m_text.isEmpty() && m_selend > m_selstart; }
- int width() const;
- int height() const;
- int ascent() const;
- qreal naturalTextWidth() const;
+ int width() const { return qRound(m_textLayout.lineAt(0).width()) + 1; }
+ int height() const { return qRound(m_textLayout.lineAt(0).height()) + 1; }
+ int ascent() const { return m_ascent; }
+ qreal naturalTextWidth() const { return m_textLayout.lineAt(0).naturalTextWidth(); }
void setSelection(int start, int length);
- QString selectedText() const;
- QString textBeforeSelection() const;
- QString textAfterSelection() const;
+ inline QString selectedText() const { return hasSelectedText() ? m_text.mid(m_selstart, m_selend - m_selstart) : QString(); }
+ QString textBeforeSelection() const { return hasSelectedText() ? m_text.left(m_selstart) : QString(); }
+ QString textAfterSelection() const { return hasSelectedText() ? m_text.mid(m_selend) : QString(); }
- int selectionStart() const;
- int selectionEnd() const;
- bool inSelection(int x) const;
+ int selectionStart() const { return hasSelectedText() ? m_selstart : -1; }
+ int selectionEnd() const { return hasSelectedText() ? m_selend : -1; }
+ bool inSelection(int x) const
+ {
+ if (m_selstart >= m_selend)
+ return false;
+ int pos = xToPos(x, QTextLine::CursorOnCharacter);
+ return pos >= m_selstart && pos < m_selend;
+ }
- void removeSelection();
+ void removeSelection()
+ {
+ int priorState = m_undoState;
+ removeSelectedText();
+ finishChange(priorState);
+ }
- int start() const;
- int end() const;
+ int start() const { return 0; }
+ int end() const { return m_text.length(); }
#ifndef QT_NO_CLIPBOARD
void copy(QClipboard::Mode mode = QClipboard::Clipboard) const;
- void paste();
+ void paste(QClipboard::Mode mode = QClipboard::Clipboard);
#endif
- int cursor() const;
- int preeditCursor() const;
+ int cursor() const{ return m_cursor; }
+ int preeditCursor() const { return m_preeditCursor; }
+
+ int cursorWidth() const { return m_cursorWidth; }
+ void setCursorWidth(int value) { m_cursorWidth = value; }
- int cursorWidth() const;
- void setCursorWidth(int value);
void moveCursor(int pos, bool mark = false);
- void cursorForward(bool mark, int steps);
- void cursorWordForward(bool mark);
- void cursorWordBackward(bool mark);
- void home(bool mark);
- void end(bool mark);
+ void cursorForward(bool mark, int steps)
+ {
+ int c = m_cursor;
+ if (steps > 0) {
+ while (steps--)
+ c = m_textLayout.nextCursorPosition(c);
+ } else if (steps < 0) {
+ while (steps++)
+ c = m_textLayout.previousCursorPosition(c);
+ }
+ moveCursor(c, mark);
+ }
+
+ void cursorWordForward(bool mark) { moveCursor(m_textLayout.nextCursorPosition(m_cursor, QTextLayout::SkipWords), mark); }
+ void cursorWordBackward(bool mark) { moveCursor(m_textLayout.previousCursorPosition(m_cursor, QTextLayout::SkipWords), mark); }
+
+ void home(bool mark) { moveCursor(0, mark); }
+ void end(bool mark) { moveCursor(text().length(), mark); }
int xToPos(int x, QTextLine::CursorPosition = QTextLine::CursorBetweenCharacters) const;
QRect cursorRect() const;
- qreal cursorToX(int cursor) const;
- qreal cursorToX() const;
-
- bool isReadOnly() const;
- void setReadOnly(bool enable);
+ qreal cursorToX(int cursor) const { return m_textLayout.lineAt(0).cursorToX(cursor); }
+ qreal cursorToX() const
+ {
+ int cursor = m_cursor;
+ if (m_preeditCursor != -1)
+ cursor += m_preeditCursor;
+ return cursorToX(cursor);
+ }
- QString text() const;
- void setText(const QString &txt);
+ bool isReadOnly() const { return m_readOnly; }
+ void setReadOnly(bool enable) { m_readOnly = enable; }
- QString displayText() const;
+ QString text() const
+ {
+ QString res = m_maskData ? stripString(m_text) : m_text;
+ return (res.isNull() ? QString::fromLatin1("") : res);
+ }
+ void setText(const QString &txt) { internalSetText(txt, -1, false); }
+ QString displayText() const { return m_textLayout.text(); }
void backspace();
void del();
- void deselect();
- void selectAll();
+ void deselect() { internalDeselect(); finishChange(); }
+ void selectAll() { m_selstart = m_selend = m_cursor = 0; moveCursor(m_text.length(), true); }
+
void insert(const QString &);
void clear();
- void undo();
- void redo();
+ void undo() { internalUndo(); finishChange(-1, true); }
+ void redo() { internalRedo(); finishChange(); }
void selectWordAtPos(int);
- uint echoMode() const;
- void setEchoMode(uint mode);
+ uint echoMode() const { return m_echoMode; }
+ void setEchoMode(uint mode)
+ {
+ m_echoMode = mode;
+ m_passwordEchoEditing = false;
+ updateDisplayText();
+ }
- void setMaxLength(int maxLength);
- int maxLength() const;
+ int maxLength() const { return m_maxLength; }
+ void setMaxLength(int maxLength)
+ {
+ if (m_maskData)
+ return;
+ m_maxLength = maxLength;
+ setText(m_text);
+ }
#ifndef QT_NO_VALIDATOR
- const QValidator *validator() const;
- void setValidator(const QValidator *);
+ const QValidator *validator() const { return m_validator; }
+ void setValidator(const QValidator *v) { m_validator = const_cast<QValidator*>(v); }
#endif
#ifndef QT_NO_COMPLETER
- QCompleter *completer() const;
- void setCompleter(const QCompleter*);
+ QCompleter *completer() const { return m_completer; }
+ /* Note that you must set the widget for the completer seperately */
+ void setCompleter(const QCompleter *c) { m_completer = const_cast<QCompleter*>(c); }
void complete(int key);
#endif
- void setCursorPosition(int pos);
- int cursorPosition() const;
+ int cursorPosition() const { return m_cursor; }
+ void setCursorPosition(int pos) { if (pos <= m_text.length()) moveCursor(qMax(0, pos)); }
- bool hasAcceptableInput() const;
+ bool hasAcceptableInput() const { return hasAcceptableInput(m_text); }
bool fixup();
- QString inputMask() const;
- void setInputMask(const QString &mask);
+ QString inputMask() const { return m_maskData ? m_inputMask + QLatin1Char(';') + m_blank : QString(); }
+ void setInputMask(const QString &mask)
+ {
+ parseInputMask(mask);
+ if (m_maskData)
+ moveCursor(nextMaskBlank(0));
+ }
// input methods
#ifndef QT_NO_IM
- bool composeMode() const;
- void setPreeditArea(int cursor, const QString &text);
+ bool composeMode() const { return !m_textLayout.preeditAreaText().isEmpty(); }
+ void setPreeditArea(int cursor, const QString &text) { m_textLayout.setPreeditArea(cursor, text); }
#endif
- QString preeditAreaText() const;
+ QString preeditAreaText() const { return m_textLayout.preeditAreaText(); }
void updatePasswordEchoEditing(bool editing);
- bool passwordEchoEditing() const;
+ bool passwordEchoEditing() const { return m_passwordEchoEditing; }
- QChar passwordCharacter() const;
- void setPasswordCharacter(const QChar &character);
+ QChar passwordCharacter() const { return m_passwordCharacter; }
+ void setPasswordCharacter(const QChar &character) { m_passwordCharacter = character; updateDisplayText(); }
- Qt::LayoutDirection layoutDirection() const;
- void setLayoutDirection(Qt::LayoutDirection direction);
- void setFont(const QFont &font);
+ Qt::LayoutDirection layoutDirection() const { return m_layoutDirection; }
+ void setLayoutDirection(Qt::LayoutDirection direction)
+ {
+ if (direction != m_layoutDirection) {
+ m_layoutDirection = direction;
+ updateDisplayText();
+ }
+ }
+
+ void setFont(const QFont &font) { m_textLayout.setFont(font); updateDisplayText(); }
void processInputMethodEvent(QInputMethodEvent *event);
void processMouseEvent(QMouseEvent* ev);
void processKeyEvent(QKeyEvent* ev);
- int cursorBlinkPeriod() const;
+ int cursorBlinkPeriod() const { return m_blinkPeriod; }
void setCursorBlinkPeriod(int msec);
- QString cancelText() const;
- void setCancelText(const QString &text);
+ QString cancelText() const { return m_cancelText; }
+ void setCancelText(const QString &text) { m_cancelText = text; }
- const QPalette &palette() const;
- void setPalette(const QPalette &);
+ const QPalette &palette() const { return m_palette; }
+ void setPalette(const QPalette &p) { m_palette = p; }
enum DrawFlags {
DrawText = 0x01,
@@ -239,7 +310,7 @@ private:
void init(const QString &txt);
void removeSelectedText();
void internalSetText(const QString &txt, int pos = -1, bool edited = true);
- void updateDisplayText();
+ void updateDisplayText(bool forceUpdate = false);
void internalInsert(const QString &s);
void internalDelete(bool wasBackspace = false);
@@ -363,406 +434,6 @@ private Q_SLOTS:
};
-inline int QLineControl::nextMaskBlank(int pos)
-{
- int c = findInMask(pos, true, false);
- m_separator |= (c != pos);
- return (c != -1 ? c : m_maxLength);
-}
-
-inline int QLineControl::prevMaskBlank(int pos)
-{
- int c = findInMask(pos, false, false);
- m_separator |= (c != pos);
- return (c != -1 ? c : 0);
-}
-
-inline bool QLineControl::isUndoAvailable() const
-{
- return !m_readOnly && m_undoState;
-}
-
-inline bool QLineControl::isRedoAvailable() const
-{
- return !m_readOnly && m_undoState < (int)m_history.size();
-}
-
-inline void QLineControl::clearUndo()
-{
- m_history.clear();
- m_modifiedState = m_undoState = 0;
-}
-
-inline bool QLineControl::isModified() const
-{
- return m_modifiedState != m_undoState;
-}
-
-inline void QLineControl::setModified(bool modified)
-{
- m_modifiedState = modified ? -1 : m_undoState;
-}
-
-inline bool QLineControl::allSelected() const
-{
- return !m_text.isEmpty() && m_selstart == 0 && m_selend == (int)m_text.length();
-}
-
-inline bool QLineControl::hasSelectedText() const
-{
- return !m_text.isEmpty() && m_selend > m_selstart;
-}
-
-inline int QLineControl::width() const
-{
- return qRound(m_textLayout.lineAt(0).width()) + 1;
-}
-
-inline qreal QLineControl::naturalTextWidth() const
-{
- return m_textLayout.lineAt(0).naturalTextWidth();
-}
-
-inline int QLineControl::height() const
-{
- return qRound(m_textLayout.lineAt(0).height()) + 1;
-}
-
-inline int QLineControl::ascent() const
-{
- return m_ascent;
-}
-
-inline QString QLineControl::selectedText() const
-{
- if (hasSelectedText())
- return m_text.mid(m_selstart, m_selend - m_selstart);
- return QString();
-}
-
-inline QString QLineControl::textBeforeSelection() const
-{
- if (hasSelectedText())
- return m_text.left(m_selstart);
- return QString();
-}
-
-inline QString QLineControl::textAfterSelection() const
-{
- if (hasSelectedText())
- return m_text.mid(m_selend);
- return QString();
-}
-
-inline int QLineControl::selectionStart() const
-{
- return hasSelectedText() ? m_selstart : -1;
-}
-
-inline int QLineControl::selectionEnd() const
-{
- return hasSelectedText() ? m_selend : -1;
-}
-
-inline int QLineControl::start() const
-{
- return 0;
-}
-
-inline int QLineControl::end() const
-{
- return m_text.length();
-}
-
-inline void QLineControl::removeSelection()
-{
- int priorState = m_undoState;
- removeSelectedText();
- finishChange(priorState);
-}
-
-inline bool QLineControl::inSelection(int x) const
-{
- if (m_selstart >= m_selend)
- return false;
- int pos = xToPos(x, QTextLine::CursorOnCharacter);
- return pos >= m_selstart && pos < m_selend;
-}
-
-inline int QLineControl::cursor() const
-{
- return m_cursor;
-}
-
-inline int QLineControl::preeditCursor() const
-{
- return m_preeditCursor;
-}
-
-inline int QLineControl::cursorWidth() const
-{
- return m_cursorWidth;
-}
-
-inline void QLineControl::setCursorWidth(int value)
-{
- m_cursorWidth = value;
-}
-
-inline void QLineControl::cursorForward(bool mark, int steps)
-{
- int c = m_cursor;
- if (steps > 0) {
- while (steps--)
- c = m_textLayout.nextCursorPosition(c);
- } else if (steps < 0) {
- while (steps++)
- c = m_textLayout.previousCursorPosition(c);
- }
- moveCursor(c, mark);
-}
-
-inline void QLineControl::cursorWordForward(bool mark)
-{
- moveCursor(m_textLayout.nextCursorPosition(m_cursor, QTextLayout::SkipWords), mark);
-}
-
-inline void QLineControl::home(bool mark)
-{
- moveCursor(0, mark);
-}
-
-inline void QLineControl::end(bool mark)
-{
- moveCursor(text().length(), mark);
-}
-
-inline void QLineControl::cursorWordBackward(bool mark)
-{
- moveCursor(m_textLayout.previousCursorPosition(m_cursor, QTextLayout::SkipWords), mark);
-}
-
-inline qreal QLineControl::cursorToX(int cursor) const
-{
- return m_textLayout.lineAt(0).cursorToX(cursor);
-}
-
-inline qreal QLineControl::cursorToX() const
-{
- int cursor = m_cursor;
- if (m_preeditCursor != -1)
- cursor += m_preeditCursor;
- return cursorToX(cursor);
-}
-
-inline bool QLineControl::isReadOnly() const
-{
- return m_readOnly;
-}
-
-inline void QLineControl::setReadOnly(bool enable)
-{
- m_readOnly = enable;
-}
-
-inline QString QLineControl::text() const
-{
- QString res = m_maskData ? stripString(m_text) : m_text;
- return (res.isNull() ? QString::fromLatin1("") : res);
-}
-
-inline void QLineControl::setText(const QString &txt)
-{
- internalSetText(txt, -1, false);
-}
-
-inline QString QLineControl::displayText() const
-{
- return m_textLayout.text();
-}
-
-inline void QLineControl::deselect()
-{
- internalDeselect();
- finishChange();
-}
-
-inline void QLineControl::selectAll()
-{
- m_selstart = m_selend = m_cursor = 0;
- moveCursor(m_text.length(), true);
-}
-
-inline void QLineControl::undo()
-{
- internalUndo();
- finishChange(-1, true);
-}
-
-inline void QLineControl::redo()
-{
- internalRedo();
- finishChange();
-}
-
-inline uint QLineControl::echoMode() const
-{
- return m_echoMode;
-}
-
-inline void QLineControl::setEchoMode(uint mode)
-{
- m_echoMode = mode;
- m_passwordEchoEditing = false;
- updateDisplayText();
-}
-
-inline void QLineControl::setMaxLength(int maxLength)
-{
- if (m_maskData)
- return;
- m_maxLength = maxLength;
- setText(m_text);
-}
-
-inline int QLineControl::maxLength() const
-{
- return m_maxLength;
-}
-
-#ifndef QT_NO_VALIDATOR
-inline const QValidator *QLineControl::validator() const
-{
- return m_validator;
-}
-
-inline void QLineControl::setValidator(const QValidator *v)
-{
- m_validator = const_cast<QValidator*>(v);
-}
-#endif
-
-#ifndef QT_NO_COMPLETER
-inline QCompleter *QLineControl::completer() const
-{
- return m_completer;
-}
-
-/* Note that you must set the widget for the completer seperately */
-inline void QLineControl::setCompleter(const QCompleter* c)
-{
- m_completer = const_cast<QCompleter*>(c);
-}
-#endif
-
-inline void QLineControl::setCursorPosition(int pos)
-{
- if (pos < 0)
- pos = 0;
- if (pos <= m_text.length())
- moveCursor(pos);
-}
-
-inline int QLineControl::cursorPosition() const
-{
- return m_cursor;
-}
-
-inline bool QLineControl::hasAcceptableInput() const
-{
- return hasAcceptableInput(m_text);
-}
-
-inline QString QLineControl::inputMask() const
-{
- return m_maskData ? m_inputMask + QLatin1Char(';') + m_blank : QString();
-}
-
-inline void QLineControl::setInputMask(const QString &mask)
-{
- parseInputMask(mask);
- if (m_maskData)
- moveCursor(nextMaskBlank(0));
-}
-
-// input methods
-#ifndef QT_NO_IM
-inline bool QLineControl::composeMode() const
-{
- return !m_textLayout.preeditAreaText().isEmpty();
-}
-
-inline void QLineControl::setPreeditArea(int cursor, const QString &text)
-{
- m_textLayout.setPreeditArea(cursor, text);
-}
-#endif
-
-inline QString QLineControl::preeditAreaText() const
-{
- return m_textLayout.preeditAreaText();
-}
-
-inline bool QLineControl::passwordEchoEditing() const
-{
- return m_passwordEchoEditing;
-}
-
-inline QChar QLineControl::passwordCharacter() const
-{
- return m_passwordCharacter;
-}
-
-inline void QLineControl::setPasswordCharacter(const QChar &character)
-{
- m_passwordCharacter = character;
- updateDisplayText();
-}
-
-inline Qt::LayoutDirection QLineControl::layoutDirection() const
-{
- return m_layoutDirection;
-}
-
-inline void QLineControl::setLayoutDirection(Qt::LayoutDirection direction)
-{
- if (direction != m_layoutDirection) {
- m_layoutDirection = direction;
- updateDisplayText();
- }
-}
-
-inline void QLineControl::setFont(const QFont &font)
-{
- m_textLayout.setFont(font);
- updateDisplayText();
-}
-
-inline int QLineControl::cursorBlinkPeriod() const
-{
- return m_blinkPeriod;
-}
-
-inline QString QLineControl::cancelText() const
-{
- return m_cancelText;
-}
-
-inline void QLineControl::setCancelText(const QString &text)
-{
- m_cancelText = text;
-}
-
-inline const QPalette & QLineControl::palette() const
-{
- return m_palette;
-}
-
-inline void QLineControl::setPalette(const QPalette &p)
-{
- m_palette = p;
-}
-
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp
index 0ba8b9f..0b8dca9 100644
--- a/src/gui/widgets/qlineedit.cpp
+++ b/src/gui/widgets/qlineedit.cpp
@@ -383,8 +383,6 @@ void QLineEdit::setText(const QString& text)
d->control->setText(text);
}
-// ### Qt 4.7: remove this #if guard
-#if (QT_VERSION >= 0x407000) || defined(Q_WS_MAEMO_5)
/*!
\since 4.7
@@ -414,7 +412,6 @@ void QLineEdit::setPlaceholderText(const QString& placeholderText)
update();
}
}
-#endif
/*!
\property QLineEdit::displayText
@@ -542,11 +539,16 @@ void QLineEdit::setEchoMode(EchoMode mode)
if (mode == (EchoMode)d->control->echoMode())
return;
Qt::InputMethodHints imHints = inputMethodHints();
- if (mode == Password) {
+ if (mode == Password || mode == NoEcho) {
imHints |= Qt::ImhHiddenText;
} else {
imHints &= ~Qt::ImhHiddenText;
}
+ if (mode != Normal) {
+ imHints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
+ } else {
+ imHints &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
+ }
setInputMethodHints(imHints);
d->control->setEchoMode(mode);
update();
@@ -2038,12 +2040,13 @@ void QLineEdit::dropEvent(QDropEvent* e)
*/
void QLineEdit::contextMenuEvent(QContextMenuEvent *event)
{
- QMenu *menu = createStandardContextMenu();
- menu->setAttribute(Qt::WA_DeleteOnClose);
- menu->popup(event->globalPos());
+ if (QMenu *menu = createStandardContextMenu()) {
+ menu->setAttribute(Qt::WA_DeleteOnClose);
+ menu->popup(event->globalPos());
+ }
}
-#if defined(Q_WS_WIN)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
extern bool qt_use_rtl_extensions;
#endif
@@ -2115,7 +2118,7 @@ QMenu *QLineEdit::createStandardContextMenu()
}
#endif
-#if defined(Q_WS_WIN)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
if (!d->control->isReadOnly() && qt_use_rtl_extensions) {
#else
if (!d->control->isReadOnly()) {
diff --git a/src/gui/widgets/qlineedit.h b/src/gui/widgets/qlineedit.h
index fa04bfc..94e0dbe 100644
--- a/src/gui/widgets/qlineedit.h
+++ b/src/gui/widgets/qlineedit.h
@@ -83,10 +83,7 @@ class Q_GUI_EXPORT QLineEdit : public QWidget
Q_PROPERTY(bool undoAvailable READ isUndoAvailable)
Q_PROPERTY(bool redoAvailable READ isRedoAvailable)
Q_PROPERTY(bool acceptableInput READ hasAcceptableInput)
-// ### Qt 4.7: remove this #if guard
-#if (QT_VERSION >= 0x407000) || defined(Q_WS_MAEMO_5)
Q_PROPERTY(QString placeholderText READ placeholderText WRITE setPlaceholderText)
-#endif
public:
explicit QLineEdit(QWidget* parent=0);
@@ -102,11 +99,8 @@ public:
QString displayText() const;
-// ### Qt 4.7: remove this #if guard
-#if (QT_VERSION >= 0x407000) || defined(Q_WS_MAEMO_5)
QString placeholderText() const;
void setPlaceholderText(const QString &);
-#endif
int maxLength() const;
void setMaxLength(int);
diff --git a/src/gui/widgets/qlineedit_p.cpp b/src/gui/widgets/qlineedit_p.cpp
index 2c76a5c..468c111 100644
--- a/src/gui/widgets/qlineedit_p.cpp
+++ b/src/gui/widgets/qlineedit_p.cpp
@@ -134,7 +134,7 @@ void QLineEditPrivate::_q_selectionChanged()
q->initStyleOption(&opt);
bool showCursor = control->hasSelectedText() ?
q->style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, q):
- true;
+ q->hasFocus();
setCursorVisible(showCursor);
}
diff --git a/src/gui/widgets/qmainwindow.cpp b/src/gui/widgets/qmainwindow.cpp
index 4620597..44483ea 100644
--- a/src/gui/widgets/qmainwindow.cpp
+++ b/src/gui/widgets/qmainwindow.cpp
@@ -65,9 +65,6 @@ QT_BEGIN_NAMESPACE
extern OSWindowRef qt_mac_window_for(const QWidget *); // qwidget_mac.cpp
QT_END_NAMESPACE
#endif
-#ifdef QT_SOFTKEYS_ENABLED
-#include <private/qsoftkeymanager_p.h>
-#endif
QT_BEGIN_NAMESPACE
@@ -80,9 +77,6 @@ public:
#ifdef Q_WS_MAC
, useHIToolBar(false)
#endif
-#ifdef QT_SOFTKEYS_ENABLED
- , menuBarAction(0)
-#endif
#if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_CURSOR)
, hasOldCursor(false) , cursorAdjusted(false)
#endif
@@ -94,9 +88,6 @@ public:
#ifdef Q_WS_MAC
bool useHIToolBar;
#endif
-#ifdef QT_SOFTKEYS_ENABLED
- QAction *menuBarAction;
-#endif
void init();
QList<int> hoverSeparator;
QPoint hoverPos;
@@ -117,9 +108,6 @@ void QMainWindowPrivate::init()
const int metric = q->style()->pixelMetric(QStyle::PM_ToolBarIconSize, 0, q);
iconSize = QSize(metric, metric);
q->setAttribute(Qt::WA_Hover);
-#ifdef QT_SOFTKEYS_ENABLED
- menuBarAction = QSoftKeyManager::createAction(QSoftKeyManager::MenuSoftKey, q);
-#endif
}
/*
@@ -491,13 +479,6 @@ void QMainWindow::setMenuBar(QMenuBar *menuBar)
oldMenuBar->deleteLater();
}
d->layout->setMenuBar(menuBar);
-
-#ifdef QT_SOFTKEYS_ENABLED
- if (menuBar)
- addAction(d->menuBarAction);
- else
- removeAction(d->menuBarAction);
-#endif
}
/*!
@@ -1393,7 +1374,9 @@ bool QMainWindow::event(QEvent *event)
#endif // QT_NO_STATUSTIP
case QEvent::StyleChange:
+#ifndef QT_NO_DOCKWIDGET
d->layout->layoutState.dockAreaLayout.styleChangedEvent();
+#endif
if (!d->explicitIconSize)
setIconSize(QSize());
break;
@@ -1427,11 +1410,6 @@ bool QMainWindow::event(QEvent *event)
}
break;
#endif
-#ifdef QT_SOFTKEYS_ENABLED
- case QEvent::LanguageChange:
- d->menuBarAction->setText(QSoftKeyManager::standardSoftKeyText(QSoftKeyManager::MenuSoftKey));
- break;
-#endif
default:
break;
}
@@ -1478,7 +1456,8 @@ void QMainWindow::setUnifiedTitleAndToolBarOnMac(bool set)
return;
// ### Disable the unified toolbar when using anything but the native graphics system.
- if (windowSurface())
+ // ### Disable when using alien widgets as well
+ if (windowSurface() || testAttribute(Qt::WA_NativeWindow) == false)
return;
d->useHIToolBar = set;
diff --git a/src/gui/widgets/qmainwindowlayout_mac.mm b/src/gui/widgets/qmainwindowlayout_mac.mm
index d92168a..9527057 100644
--- a/src/gui/widgets/qmainwindowlayout_mac.mm
+++ b/src/gui/widgets/qmainwindowlayout_mac.mm
@@ -463,6 +463,8 @@ void QMainWindowLayout::removeFromMacToolbar(QToolBar *toolbar)
NSToolbarItem *item = static_cast<NSToolbarItem *>(it.key());
[[qt_mac_window_for(layoutState.mainWindow->window()) toolbar]
removeItemAtIndex:toolbarItemsCopy.indexOf(item)];
+ unifiedToolbarHash.remove(item);
+ qtoolbarsInUnifiedToolbarList.removeAll(toolbar);
#endif
break;
}
diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp
index e2cf25b..9e190b7 100644
--- a/src/gui/widgets/qmenu.cpp
+++ b/src/gui/widgets/qmenu.cpp
@@ -85,9 +85,8 @@
QT_BEGIN_NAMESPACE
-QPointer<QMenu> QMenuPrivate::mouseDown;
-QBasicTimer QMenuPrivate::menuDelayTimer;
-QBasicTimer QMenuPrivate::sloppyDelayTimer;
+QMenu *QMenuPrivate::mouseDown = 0;
+int QMenuPrivate::sloppyDelayTimer = 0;
/* QMenu code */
// internal class used for the torn off popup
@@ -168,8 +167,8 @@ void QMenuPrivate::init()
#ifdef QT_SOFTKEYS_ENABLED
selectAction = QSoftKeyManager::createKeyedAction(QSoftKeyManager::SelectSoftKey, Qt::Key_Select, q);
cancelAction = QSoftKeyManager::createKeyedAction(QSoftKeyManager::CancelSoftKey, Qt::Key_Back, q);
- selectAction->setVisible(false); // Don't show these in the menu
- cancelAction->setVisible(false);
+ selectAction->setPriority(QAction::HighPriority);
+ cancelAction->setPriority(QAction::HighPriority);
q->addAction(selectAction);
q->addAction(cancelAction);
#endif
@@ -261,9 +260,6 @@ void QMenuPrivate::updateActionRects() const
icone = style->pixelMetric(QStyle::PM_SmallIconSize, &opt, q);
const int fw = style->pixelMetric(QStyle::PM_MenuPanelWidth, &opt, q);
const int deskFw = style->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, &opt, q);
-
- const int sfcMargin = style->sizeFromContents(QStyle::CT_Menu, &opt, QApplication::globalStrut(), q).width() - QApplication::globalStrut().width();
- const int min_column_width = q->minimumWidth() - (sfcMargin + leftmargin + rightmargin + 2 * (fw + hmargin));
const int tearoffHeight = tearoff ? style->pixelMetric(QStyle::PM_MenuTearoffHeight, &opt, q) : 0;
//for compatability now - will have to refactor this away..
@@ -337,7 +333,7 @@ void QMenuPrivate::updateActionRects() const
if (!sz.isEmpty()) {
- max_column_width = qMax(min_column_width, qMax(max_column_width, sz.width()));
+ max_column_width = qMax(max_column_width, sz.width());
//wrapping
if (!scroll &&
y+sz.height()+vmargin > dh - (deskFw * 2)) {
@@ -351,6 +347,10 @@ void QMenuPrivate::updateActionRects() const
}
max_column_width += tabWidth; //finally add in the tab width
+ const int sfcMargin = style->sizeFromContents(QStyle::CT_Menu, &opt, QApplication::globalStrut(), q).width() - QApplication::globalStrut().width();
+ const int min_column_width = q->minimumWidth() - (sfcMargin + leftmargin + rightmargin + 2 * (fw + hmargin));
+ max_column_width = qMax(min_column_width, max_column_width);
+
//calculate position
const int base_y = vmargin + fw + topmargin +
@@ -487,8 +487,8 @@ void QMenuPrivate::popupAction(QAction *action, int delay, bool activateFirst)
if (action && action->isEnabled()) {
if (!delay)
q->internalDelayedPopup();
- else
- QMenuPrivate::menuDelayTimer.start(delay, q);
+ else if (!menuDelayTimer.isActive() && (!action->menu() || !action->menu()->isVisible()))
+ menuDelayTimer.start(delay, q);
if (activateFirst && action->menu())
action->menu()->d_func()->setFirstActionActive();
} else if (QMenu *menu = activeMenu) { //hide the current item
@@ -543,15 +543,6 @@ void QMenuPrivate::setCurrentAction(QAction *action, int popup, SelectionReason
{
Q_Q(QMenu);
tearoffHighlighted = 0;
- if (action == currentAction) {
- if (!action || !action->menu() || action->menu() == activeMenu) {
- if(QMenu *menu = qobject_cast<QMenu*>(causedPopup.widget)) {
- if(causedPopup.action && menu->d_func()->activeMenu == q)
- menu->d_func()->setCurrentAction(causedPopup.action, 0, reason, false);
- }
- }
- return;
- }
if (currentAction)
q->update(actionRect(currentAction));
@@ -565,6 +556,7 @@ void QMenuPrivate::setCurrentAction(QAction *action, int popup, SelectionReason
#ifdef QT3_SUPPORT
emitHighlighted = action;
#endif
+
currentAction = action;
if (action) {
if (!action->isSeparator()) {
@@ -1406,12 +1398,14 @@ QMenu::QMenu(QMenuPrivate &dd, QWidget *parent)
QMenu::~QMenu()
{
Q_D(QMenu);
- QHash<QAction *, QWidget *>::iterator it = d->widgetItems.begin();
- for (; it != d->widgetItems.end(); ++it) {
- if (QWidget *widget = it.value()) {
- QWidgetAction *action = static_cast<QWidgetAction *>(it.key());
- action->releaseWidget(widget);
- *it = 0;
+ if (!d->widgetItems.isEmpty()) { // avoid detach on shared null hash
+ QHash<QAction *, QWidget *>::iterator it = d->widgetItems.begin();
+ for (; it != d->widgetItems.end(); ++it) {
+ if (QWidget *widget = it.value()) {
+ QWidgetAction *action = static_cast<QWidgetAction *>(it.key());
+ action->releaseWidget(widget);
+ *it = 0;
+ }
}
}
@@ -2383,8 +2377,8 @@ QMenu::event(QEvent *e)
}
} break;
case QEvent::ContextMenu:
- if(QMenuPrivate::menuDelayTimer.isActive()) {
- QMenuPrivate::menuDelayTimer.stop();
+ if(d->menuDelayTimer.isActive()) {
+ d->menuDelayTimer.stop();
internalDelayedPopup();
}
break;
@@ -2817,7 +2811,7 @@ void QMenu::mouseMoveEvent(QMouseEvent *e)
}
if (d->sloppyRegion.contains(e->pos())) {
d->sloppyAction = action;
- QMenuPrivate::sloppyDelayTimer.start(style()->styleHint(QStyle::SH_Menu_SubMenuPopupDelay, 0, this)*6, this);
+ QMenuPrivate::sloppyDelayTimer = startTimer(style()->styleHint(QStyle::SH_Menu_SubMenuPopupDelay, 0, this)*6);
} else {
d->setCurrentAction(action, style()->styleHint(QStyle::SH_Menu_SubMenuPopupDelay, 0, this));
}
@@ -2855,11 +2849,12 @@ QMenu::timerEvent(QTimerEvent *e)
d->scrollMenu((QMenuPrivate::QMenuScroller::ScrollDirection)d->scroll->scrollDirection);
if (d->scroll->scrollFlags == QMenuPrivate::QMenuScroller::ScrollNone)
d->scroll->scrollTimer.stop();
- } else if(QMenuPrivate::menuDelayTimer.timerId() == e->timerId()) {
- QMenuPrivate::menuDelayTimer.stop();
+ } else if(d->menuDelayTimer.timerId() == e->timerId()) {
+ d->menuDelayTimer.stop();
internalDelayedPopup();
- } else if(QMenuPrivate::sloppyDelayTimer.timerId() == e->timerId()) {
- QMenuPrivate::sloppyDelayTimer.stop();
+ } else if(QMenuPrivate::sloppyDelayTimer == e->timerId()) {
+ killTimer(QMenuPrivate::sloppyDelayTimer);
+ QMenuPrivate::sloppyDelayTimer = 0;
internalSetSloppyAction();
} else if(d->searchBufferTimer.timerId() == e->timerId()) {
d->searchBuffer.clear();
diff --git a/src/gui/widgets/qmenu_mac.mm b/src/gui/widgets/qmenu_mac.mm
index 99c550f..6a0eb53 100644
--- a/src/gui/widgets/qmenu_mac.mm
+++ b/src/gui/widgets/qmenu_mac.mm
@@ -909,6 +909,7 @@ static NSMenuItem *qt_mac_menu_merge_action(OSMenuRef merge, QMacMenuAction *act
static QString qt_mac_menu_merge_text(QMacMenuAction *action)
{
QString ret;
+ extern QString qt_mac_applicationmenu_string(int type);
#ifdef QT_MAC_USE_COCOA
QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader();
#endif
@@ -916,22 +917,26 @@ static QString qt_mac_menu_merge_text(QMacMenuAction *action)
ret = action->action->text();
#ifndef QT_MAC_USE_COCOA
else if (action->command == kHICommandAbout)
- ret = QMenuBar::tr("About %1").arg(qAppName());
+ ret = qt_mac_applicationmenu_string(6).arg(qAppName());
else if (action->command == kHICommandAboutQt)
ret = QMenuBar::tr("About Qt");
else if (action->command == kHICommandPreferences)
- ret = QMenuBar::tr("Preferences");
+ ret = qt_mac_applicationmenu_string(4);
else if (action->command == kHICommandQuit)
- ret = QMenuBar::tr("Quit %1").arg(qAppName());
+ ret = qt_mac_applicationmenu_string(5).arg(qAppName());
#else
- else if (action->menuItem == [loader aboutMenuItem])
- ret = QMenuBar::tr("About %1").arg(qAppName());
- else if (action->menuItem == [loader aboutQtMenuItem])
- ret = QMenuBar::tr("About Qt");
- else if (action->menuItem == [loader preferencesMenuItem])
- ret = QMenuBar::tr("Preferences");
- else if (action->menuItem == [loader quitMenuItem])
- ret = QMenuBar::tr("Quit %1").arg(qAppName());
+ else if (action->menuItem == [loader aboutMenuItem]) {
+ ret = qt_mac_applicationmenu_string(6).arg(qAppName());
+ } else if (action->menuItem == [loader aboutQtMenuItem]) {
+ if (action->action->text() == QString("About Qt"))
+ ret = QMenuBar::tr("About Qt");
+ else
+ ret = action->action->text();
+ } else if (action->menuItem == [loader preferencesMenuItem]) {
+ ret = qt_mac_applicationmenu_string(4);
+ } else if (action->menuItem == [loader quitMenuItem]) {
+ ret = qt_mac_applicationmenu_string(5).arg(qAppName());
+ }
#endif
return ret;
}
@@ -1386,7 +1391,11 @@ QMenuPrivate::QMacMenuPrivate::syncAction(QMacMenuAction *action)
} else {
[item setTitle: qt_mac_QStringToNSString(finalString)];
}
- [item setTitle:qt_mac_QStringToNSString(qt_mac_removeMnemonics(text))];
+
+ if (action->action->menuRole() == QAction::AboutRole || action->action->menuRole() == QAction::QuitRole)
+ [item setTitle:qt_mac_QStringToNSString(text)];
+ else
+ [item setTitle:qt_mac_QStringToNSString(qt_mac_removeMnemonics(text))];
// Cocoa Enabled
[item setEnabled: action->action->isEnabled()];
@@ -1922,7 +1931,7 @@ static bool qt_mac_should_disable_menu(QMenuBar *menuBar)
if (w->isVisible() && w->windowModality() == Qt::ApplicationModal) {
for (int i=0; i<topLevelWidgets.size(); ++i) {
QWidget *top = topLevelWidgets.at(i);
- if (w != top && [qt_mac_window_for(top) isVisible]) {
+ if (w != top && top->isVisible()) {
// INVARIANT: we found another visible window
// on screen other than our modalWidget. We therefore
// disable the menu bar to follow normal modality logic:
@@ -2047,6 +2056,22 @@ bool QMenuBarPrivate::macUpdateMenuBarImmediatly()
QWidget *w = findWindowThatShouldDisplayMenubar();
QMenuBar *mb = findMenubarForWindow(w);
+ // We need to see if we are in full screen mode, if so we need to
+ // switch the full screen mode to be able to show or hide the menubar.
+ if(w && mb) {
+ // This case means we are creating a menubar, check if full screen
+ if(w->isFullScreen()) {
+ // Ok, switch to showing the menubar when hovering over it.
+ SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar);
+ }
+ } else if(w) {
+ // Removing a menubar
+ if(w->isFullScreen()) {
+ // Ok, switch to not showing the menubar when hovering on it
+ SetSystemUIMode(kUIModeAllHidden, 0);
+ }
+ }
+
if (mb && mb->isNativeMenuBar()) {
bool modal = QApplicationPrivate::modalState();
#ifdef QT_MAC_USE_COCOA
@@ -2180,3 +2205,4 @@ static OSMenuRef qt_mac_create_menu(QWidget *w)
QT_END_NAMESPACE
+
diff --git a/src/gui/widgets/qmenu_p.h b/src/gui/widgets/qmenu_p.h
index aaed6b1..39cbbd8 100644
--- a/src/gui/widgets/qmenu_p.h
+++ b/src/gui/widgets/qmenu_p.h
@@ -202,7 +202,7 @@ public:
bool activationRecursionGuard;
//selection
- static QPointer<QMenu> mouseDown;
+ static QMenu *mouseDown;
QPoint mousePopupPos;
uint hasHadMouse : 1;
uint aboutToHide : 1;
@@ -212,7 +212,7 @@ public:
QAction *selectAction;
QAction *cancelAction;
#endif
- static QBasicTimer menuDelayTimer;
+ QBasicTimer menuDelayTimer;
enum SelectionReason {
SelectedFromKeyboard,
SelectedFromElsewhere
@@ -272,7 +272,7 @@ public:
mutable bool hasCheckableItems;
//sloppy selection
- static QBasicTimer sloppyDelayTimer;
+ static int sloppyDelayTimer;
mutable QAction *sloppyAction;
QRegion sloppyRegion;
@@ -347,7 +347,7 @@ public:
void syncAction(QWceMenuAction *);
inline void syncAction(QAction *a) { syncAction(findAction(a)); }
void removeAction(QWceMenuAction *);
- void rebuild(bool reCreate = false);
+ void rebuild();
inline void removeAction(QAction *a) { removeAction(findAction(a)); }
inline QWceMenuAction *findAction(QAction *a) {
for(int i = 0; i < actionItems.size(); i++) {
diff --git a/src/gui/widgets/qmenu_symbian.cpp b/src/gui/widgets/qmenu_symbian.cpp
index eae97a6..4a9cfed 100644
--- a/src/gui/widgets/qmenu_symbian.cpp
+++ b/src/gui/widgets/qmenu_symbian.cpp
@@ -48,7 +48,7 @@
#include <private/qapplication_p.h>
#include <private/qmenu_p.h>
#include <private/qmenubar_p.h>
-#include <qt_s60_p.h>
+#include <private/qt_s60_p.h>
#include <QtCore/qlibrary.h>
#ifdef Q_WS_S60
@@ -256,6 +256,14 @@ void qt_symbian_show_submenu( CEikMenuPane* menuPane, int id)
{
SymbianMenuItem* menu = qt_symbian_find_menu(id, symbianMenus);
if (menu) {
+ // Normally first AddMenuItemL call for menuPane will create the item array.
+ // However if we don't have any items, we still need the item array. Otherwise
+ // menupane will crash. That's why we create item array here manually, and
+ // AddMenuItemL will then use the existing array.
+ CEikMenuPane::CItemArray* itemArray = q_check_ptr(new CEikMenuPane::CItemArray);
+ menuPane->SetItemArray(itemArray);
+ menuPane->SetItemArrayOwnedExternally(EFalse);
+
for (int i = 0; i < menu->children.count(); ++i)
QT_TRAP_THROWING(menuPane->AddMenuItemL(menu->children.at(i)->menuItemData));
}
@@ -316,6 +324,14 @@ void QMenuBarPrivate::symbianDestroyMenuBar()
symbian_menubar = 0;
}
+void QMenuBarPrivate::reparentMenuBar(QWidget *oldParent, QWidget *newParent)
+{
+ if (menubars()->contains(oldParent)) {
+ QMenuBarPrivate *object = menubars()->take(oldParent);
+ menubars()->insert(newParent, object);
+ }
+}
+
QMenuBarPrivate::QSymbianMenuBarPrivate::QSymbianMenuBarPrivate(QMenuBarPrivate *menubar)
{
d = menubar;
diff --git a/src/gui/widgets/qmenu_wince.cpp b/src/gui/widgets/qmenu_wince.cpp
index 28b6b8b..1577f0a 100644
--- a/src/gui/widgets/qmenu_wince.cpp
+++ b/src/gui/widgets/qmenu_wince.cpp
@@ -101,7 +101,6 @@ struct qt_SHMENUBARINFO
COLORREF clrBk;
};
-typedef int (WINAPI *superfunc)(int, int);
typedef BOOL (WINAPI *AygCreateMenuBar)(qt_SHMENUBARINFO*);
typedef HRESULT (WINAPI *AygEnableSoftKey)(HWND,UINT,BOOL,BOOL);
@@ -254,6 +253,12 @@ static void qt_wce_insert_action(HMENU menu, QWceMenuAction *action, bool create
}
}
+// Removes all items from the menu without destroying the handles.
+static void qt_wce_clear_menu(HMENU hMenu)
+{
+ while (RemoveMenu(hMenu, 0, MF_BYPOSITION));
+}
+
/*!
\internal
@@ -404,7 +409,8 @@ QMenuPrivate::QWceMenuPrivate::QWceMenuPrivate() {
QMenuPrivate::QWceMenuPrivate::~QWceMenuPrivate() {
qt_wce_delete_action_list(&actionItems);
- menuHandle = 0;
+ if (menuHandle)
+ DestroyMenu(menuHandle);
}
void QMenuPrivate::QWceMenuPrivate::addAction(QAction *a, QWceMenuAction *before) {
@@ -439,14 +445,17 @@ HMENU QMenuPrivate::wceMenu(bool create) {
if (!wce_menu)
wce_menu = new QWceMenuPrivate;
if (!wce_menu->menuHandle || create)
- wce_menu->rebuild(create);
+ wce_menu->rebuild();
return wce_menu->menuHandle;
}
-void QMenuPrivate::QWceMenuPrivate::rebuild(bool reCreate) {
- if (menuHandle && !reCreate)
- DestroyMenu(menuHandle);
- menuHandle = CreatePopupMenu();
+void QMenuPrivate::QWceMenuPrivate::rebuild()
+{
+ if (!menuHandle)
+ menuHandle = CreatePopupMenu();
+ else
+ qt_wce_clear_menu(menuHandle);
+
for (int i = 0; i < actionItems.size(); ++i) {
QWceMenuAction *action = actionItems.at(i);
action->menuHandle = menuHandle;
@@ -522,6 +531,7 @@ void QMenuBarPrivate::QWceMenuBarPrivate::rebuild() {
resourceHandle = IDR_MAIN_MENU5;
}
Q_ASSERT_X(menubarHandle, "rebuild !created", "menubar already deleted");
+ qt_wce_clear_menu(menuHandle);
DestroyWindow(menubarHandle);
menubarHandle = qt_wce_create_menubar(parentWindowHandle, qt_wce_get_module_handle(), resourceHandle);
Q_ASSERT_X(menubarHandle, "rebuild classic menu", "cannot create menubar from resource");
@@ -563,6 +573,7 @@ void QMenuBarPrivate::QWceMenuBarPrivate::rebuild() {
leftButtonIsMenu = (leftButtonAction && leftButtonAction->menu());
Q_ASSERT_X(menubarHandle, "rebuild !created", "menubar already deleted");
+ qt_wce_clear_menu(menuHandle);
DestroyWindow(menubarHandle);
if (leftButtonIsMenu) {
menubarHandle = qt_wce_create_menubar(parentWindowHandle, qt_wce_get_module_handle(), IDR_MAIN_MENU2);
diff --git a/src/gui/widgets/qmenubar.cpp b/src/gui/widgets/qmenubar.cpp
index 9caadb7..e368d3d 100644
--- a/src/gui/widgets/qmenubar.cpp
+++ b/src/gui/widgets/qmenubar.cpp
@@ -71,6 +71,10 @@
extern bool qt_wince_is_mobile(); //defined in qguifunctions_wce.cpp
#endif
+#ifdef QT_SOFTKEYS_ENABLED
+#include <private/qsoftkeymanager_p.h>
+#endif
+
QT_BEGIN_NAMESPACE
class QMenuBarExtension : public QToolButton
@@ -740,17 +744,14 @@ void QMenuBarPrivate::init()
QApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, true);
}
#endif
-#ifdef Q_WS_S60
- symbianCreateMenuBar(q->parentWidget());
- if(symbian_menubar)
- q->hide();
-#endif
-
q->setBackgroundRole(QPalette::Button);
oldWindow = oldParent = 0;
#ifdef QT3_SUPPORT
doAutoResize = false;
#endif
+#ifdef QT_SOFTKEYS_ENABLED
+ menuBarAction = 0;
+#endif
handleReparent();
q->setMouseTracking(q->style()->styleHint(QStyle::SH_MenuBar_MouseTracking, 0, q));
@@ -1384,10 +1385,37 @@ void QMenuBarPrivate::handleReparent()
wce_menubar->rebuild();
#endif
#ifdef Q_WS_S60
- if (symbian_menubar)
+
+ // Construct symbian_menubar when this code path is entered first time
+ // and when newParent != NULL
+ if (!symbian_menubar)
+ symbianCreateMenuBar(newParent);
+
+ // Reparent and rebuild menubar when parent is changed
+ if (symbian_menubar) {
+ if (oldParent != newParent)
+ reparentMenuBar(oldParent, newParent);
+ q->hide();
symbian_menubar->rebuild();
-#endif
+ }
+#ifdef QT_SOFTKEYS_ENABLED
+ // Constuct menuBarAction when this code path is entered first time
+ if (!menuBarAction) {
+ if (newParent) {
+ menuBarAction = QSoftKeyManager::createAction(QSoftKeyManager::MenuSoftKey, newParent);
+ newParent->addAction(menuBarAction);
+ }
+ } else {
+ // If reparenting i.e. we already have menuBarAction, remove it from old parent
+ // and add for a new parent
+ if (oldParent)
+ oldParent->removeAction(menuBarAction);
+ if (newParent)
+ newParent->addAction(menuBarAction);
+ }
+#endif // QT_SOFTKEYS_ENABLED
+#endif // Q_WS_S60
}
#ifdef QT3_SUPPORT
@@ -1440,7 +1468,13 @@ void QMenuBar::changeEvent(QEvent *e)
|| e->type() == QEvent::ApplicationFontChange) {
d->itemsDirty = true;
d->updateGeometries();
+#ifdef QT_SOFTKEYS_ENABLED
+ } else if (e->type() == QEvent::LanguageChange) {
+ if (d->menuBarAction)
+ d->menuBarAction->setText(QSoftKeyManager::standardSoftKeyText(QSoftKeyManager::MenuSoftKey));
+#endif
}
+
QWidget::changeEvent(e);
}
diff --git a/src/gui/widgets/qmenubar_p.h b/src/gui/widgets/qmenubar_p.h
index 819aee4..82070fe 100644
--- a/src/gui/widgets/qmenubar_p.h
+++ b/src/gui/widgets/qmenubar_p.h
@@ -244,6 +244,7 @@ public:
#ifdef Q_WS_S60
void symbianCreateMenuBar(QWidget *);
void symbianDestroyMenuBar();
+ void reparentMenuBar(QWidget *oldParent, QWidget *newParent);
struct QSymbianMenuBarPrivate {
QList<QSymbianMenuAction*> actionItems;
QMenuBarPrivate *d;
@@ -268,7 +269,9 @@ public:
} *symbian_menubar;
static int symbianCommands(int command);
-
+#ifdef QT_SOFTKEYS_ENABLED
+ QAction *menuBarAction;
+#endif
#endif
};
#endif
diff --git a/src/gui/widgets/qradiobutton.cpp b/src/gui/widgets/qradiobutton.cpp
index d73ff2f..20b6c720 100644
--- a/src/gui/widgets/qradiobutton.cpp
+++ b/src/gui/widgets/qradiobutton.cpp
@@ -195,7 +195,7 @@ QSize QRadioButton::sizeHint() const
ensurePolished();
QStyleOptionButton opt;
initStyleOption(&opt);
- QSize sz = style()->itemTextRect(fontMetrics(), QRect(0, 0, 1, 1), Qt::TextShowMnemonic,
+ QSize sz = style()->itemTextRect(fontMetrics(), QRect(), Qt::TextShowMnemonic,
false, text()).size();
if (!opt.icon.isNull())
sz = QSize(sz.width() + opt.iconSize.width() + 4, qMax(sz.height(), opt.iconSize.height()));
diff --git a/src/gui/widgets/qscrollbar.cpp b/src/gui/widgets/qscrollbar.cpp
index 4eff260..4ee9f27 100644
--- a/src/gui/widgets/qscrollbar.cpp
+++ b/src/gui/widgets/qscrollbar.cpp
@@ -47,7 +47,7 @@
#include "qstyle.h"
#include "qstyleoption.h"
#include "qmenu.h"
-#include <QtCore/qdatetime.h>
+#include <QtCore/qelapsedtimer.h>
#ifndef QT_NO_SCROLLBAR
@@ -523,6 +523,7 @@ bool QScrollBar::event(QEvent *event)
break;
#ifndef QT_NO_WHEELEVENT
case QEvent::Wheel: {
+ event->ignore();
// override wheel event without adding virtual function override
QWheelEvent *ev = static_cast<QWheelEvent *>(event);
int delta = ev->delta();
@@ -612,7 +613,7 @@ void QScrollBar::mousePressEvent(QMouseEvent *e)
}
const int initialDelay = 500; // default threshold
d->activateControl(d->pressedControl, initialDelay);
- QTime time;
+ QElapsedTimer time;
time.start();
repaint(style()->subControlRect(QStyle::CC_ScrollBar, &opt, d->pressedControl, this));
if (time.elapsed() >= initialDelay && d->repeatActionTimer.isActive()) {
diff --git a/src/gui/widgets/qspinbox.cpp b/src/gui/widgets/qspinbox.cpp
index 726426d..2d871d0 100644
--- a/src/gui/widgets/qspinbox.cpp
+++ b/src/gui/widgets/qspinbox.cpp
@@ -448,11 +448,12 @@ void QSpinBox::setRange(int minimum, int maximum)
}
/*!
- This virtual function is used by the spin box whenever it needs
- to display the given \a value. The default implementation returns
- a string containing \a value printed in the standard way using
- QWidget::locale().toString(). Reimplementations may return anything. (See
- the example in the detailed description.)
+ This virtual function is used by the spin box whenever it needs to
+ display the given \a value. The default implementation returns a
+ string containing \a value printed in the standard way using
+ QWidget::locale().toString(), but with the thousand separator
+ removed. Reimplementations may return anything. (See the example
+ in the detailed description.)
Note: QSpinBox does not call this function for specialValueText()
and that neither prefix() nor suffix() should be included in the
@@ -461,7 +462,7 @@ void QSpinBox::setRange(int minimum, int maximum)
If you reimplement this, you may also need to reimplement
valueFromText() and validate()
- \sa valueFromText(), validate()
+ \sa valueFromText(), validate(), QLocale::groupSeparator()
*/
QString QSpinBox::textFromValue(int value) const
@@ -869,7 +870,7 @@ void QDoubleSpinBox::setDecimals(int decimals)
If you reimplement this, you may also need to reimplement
valueFromText().
- \sa valueFromText()
+ \sa valueFromText(), QLocale::groupSeparator()
*/
diff --git a/src/gui/widgets/qsplitter.cpp b/src/gui/widgets/qsplitter.cpp
index 965094e..88b7517 100644
--- a/src/gui/widgets/qsplitter.cpp
+++ b/src/gui/widgets/qsplitter.cpp
@@ -227,6 +227,33 @@ QSize QSplitterHandle::sizeHint() const
/*!
\reimp
*/
+void QSplitterHandle::resizeEvent(QResizeEvent *event)
+{
+ Q_D(const QSplitterHandle);
+
+ // When splitters are only 1 pixel large we increase the
+ // actual grab area to five pixels
+
+ // Note that QSplitter uses contentsRect for layouting
+ // and ensures that handles are drawn on top of widgets
+ // We simply use the contents margins for draggin and only
+ // paint the mask area
+ bool useTinyMode = (d->s->handleWidth() == 1);
+ setAttribute(Qt::WA_MouseNoMask, useTinyMode);
+ if (useTinyMode) {
+ if (orientation() == Qt::Horizontal)
+ setContentsMargins(2, 0, 2, 0);
+ else
+ setContentsMargins(0, 2, 0, 2);
+ setMask(QRegion(contentsRect()));
+ }
+
+ QWidget::resizeEvent(event);
+}
+
+/*!
+ \reimp
+*/
bool QSplitterHandle::event(QEvent *event)
{
Q_D(QSplitterHandle);
@@ -301,7 +328,7 @@ void QSplitterHandle::paintEvent(QPaintEvent *)
Q_D(QSplitterHandle);
QPainter p(this);
QStyleOption opt(0);
- opt.rect = rect();
+ opt.rect = contentsRect();
opt.palette = palette();
if (orientation() == Qt::Horizontal)
opt.state = QStyle::State_Horizontal;
@@ -1276,7 +1303,6 @@ void QSplitter::childEvent(QChildEvent *c)
if (!c->child()->isWidgetType())
return;
QWidget *w = static_cast<QWidget*>(c->child());
-
if (c->added() && !d->blockChildAdd && !w->isWindow() && !d->findWidget(w)) {
d->insertWidget_helper(d->list.count(), w, false);
} else if (c->polished() && !d->blockChildAdd) {
@@ -1306,25 +1332,23 @@ void QSplitter::setRubberBand(int pos)
Q_D(QSplitter);
if (pos < 0) {
if (d->rubberBand)
- QTimer::singleShot(0, d->rubberBand, SLOT(deleteLater()));
+ d->rubberBand->deleteLater();
return;
}
QRect r = contentsRect();
const int rBord = 3; // customizable?
int hw = handleWidth();
if (!d->rubberBand) {
- d->rubberBand = new QRubberBand(QRubberBand::Line);
+ QBoolBlocker b(d->blockChildAdd);
+ d->rubberBand = new QRubberBand(QRubberBand::Line, this);
// For accessibility to identify this special widget.
d->rubberBand->setObjectName(QLatin1String("qt_rubberband"));
}
- if (d->orient == Qt::Horizontal)
- d->rubberBand->setGeometry(QRect(QPoint(pos + hw / 2 - rBord, r.y()),
- QSize(2 * rBord, r.height())).translated(mapToGlobal(QPoint())));
- else
- d->rubberBand->setGeometry(QRect(QPoint(r.x(), pos + hw / 2 - rBord),
- QSize(r.width(), 2 * rBord)).translated(mapToGlobal(QPoint())));
- if (!d->rubberBand->isVisible())
- d->rubberBand->show();
+
+ const QRect newGeom = d->orient == Qt::Horizontal ? QRect(QPoint(pos + hw / 2 - rBord, r.y()), QSize(2 * rBord, r.height()))
+ : QRect(QPoint(r.x(), pos + hw / 2 - rBord), QSize(r.width(), 2 * rBord));
+ d->rubberBand->setGeometry(newGeom);
+ d->rubberBand->show();
}
/*!
@@ -1555,16 +1579,14 @@ QSize QSplitter::sizeHint() const
ensurePolished();
int l = 0;
int t = 0;
- QObjectList childList = children();
- for (int i = 0; i < childList.size(); ++i) {
- if (QWidget *w = qobject_cast<QWidget *>(childList.at(i))) {
- if (w->isHidden())
- continue;
- QSize s = w->sizeHint();
- if (s.isValid()) {
- l += d->pick(s);
- t = qMax(t, d->trans(s));
- }
+ for (int i = 0; i < d->list.size(); ++i) {
+ QWidget *w = d->list.at(i)->widget;
+ if (w->isHidden())
+ continue;
+ QSize s = w->sizeHint();
+ if (s.isValid()) {
+ l += d->pick(s);
+ t = qMax(t, d->trans(s));
}
}
return orientation() == Qt::Horizontal ? QSize(l, t) : QSize(t, l);
@@ -1667,6 +1689,9 @@ void QSplitter::setSizes(const QList<int> &list)
By default, this property contains a value that depends on the user's platform
and style preferences.
+
+ If you set handleWidth to 1, the actual grab area will grow to overlap a
+ few pixels of it's respective widgets.
*/
int QSplitter::handleWidth() const
diff --git a/src/gui/widgets/qsplitter.h b/src/gui/widgets/qsplitter.h
index a793f24..c3b304d 100644
--- a/src/gui/widgets/qsplitter.h
+++ b/src/gui/widgets/qsplitter.h
@@ -172,6 +172,7 @@ protected:
void mouseMoveEvent(QMouseEvent *);
void mousePressEvent(QMouseEvent *);
void mouseReleaseEvent(QMouseEvent *);
+ void resizeEvent(QResizeEvent *);
bool event(QEvent *);
void moveSplitter(int p);
diff --git a/src/gui/widgets/qtoolbarlayout.cpp b/src/gui/widgets/qtoolbarlayout.cpp
index 4eb252a..f87510f 100644
--- a/src/gui/widgets/qtoolbarlayout.cpp
+++ b/src/gui/widgets/qtoolbarlayout.cpp
@@ -654,7 +654,11 @@ void QToolBarLayout::setExpanded(bool exp)
if (!tb)
return;
if (QMainWindow *win = qobject_cast<QMainWindow*>(tb->parentWidget())) {
+#ifdef QT_NO_DOCKWIDGET
+ animating = false;
+#else
animating = !tb->isWindow() && win->isAnimated();
+#endif
QMainWindowLayout *layout = qobject_cast<QMainWindowLayout*>(win->layout());
if (expanded) {
tb->raise();
diff --git a/src/gui/widgets/qvalidator.cpp b/src/gui/widgets/qvalidator.cpp
index 0b5cc5a..b75db45 100644
--- a/src/gui/widgets/qvalidator.cpp
+++ b/src/gui/widgets/qvalidator.cpp
@@ -523,7 +523,7 @@ public:
In addition, QDoubleValidator is always guaranteed to accept a number
formatted according to the "C" locale. QDoubleValidator will not accept
- numbers with thousand-seperators.
+ numbers with thousand-separators.
\sa QIntValidator, QRegExpValidator, {Line Edits Example}
*/
diff --git a/src/gui/widgets/qworkspace.cpp b/src/gui/widgets/qworkspace.cpp
index 2a6a7da..7180c4d 100644
--- a/src/gui/widgets/qworkspace.cpp
+++ b/src/gui/widgets/qworkspace.cpp
@@ -44,7 +44,6 @@
#include "qapplication.h"
#include "qbitmap.h"
#include "qcursor.h"
-#include "qdatetime.h"
#include "qdesktopwidget.h"
#include "qevent.h"
#include "qhash.h"
@@ -59,6 +58,7 @@
#include "qscrollbar.h"
#include "qstyle.h"
#include "qstyleoption.h"
+#include "qelapsedtimer.h"
#include "qtooltip.h"
#include "qdebug.h"
#include <private/qwidget_p.h>
@@ -450,10 +450,10 @@ void QWorkspaceTitleBar::mousePressEvent(QMouseEvent *e)
case QStyle::SC_TitleBarSysMenu:
if (d->flags & Qt::WindowSystemMenuHint) {
d->buttonDown = QStyle::SC_None;
- static QTime *t = 0;
+ static QElapsedTimer *t = 0;
static QWorkspaceTitleBar *tc = 0;
if (!t)
- t = new QTime;
+ t = new QElapsedTimer;
if (tc != this || t->elapsed() > QApplication::doubleClickInterval()) {
emit showOperationMenu();
t->start();
@@ -1839,7 +1839,7 @@ bool QWorkspace::event(QEvent *e)
bool QWorkspace::eventFilter(QObject *o, QEvent * e)
{
Q_D(QWorkspace);
- static QTime* t = 0;
+ static QElapsedTimer* t = 0;
static QWorkspace* tc = 0;
if (o == d->maxtools) {
switch (e->type()) {
@@ -1847,7 +1847,7 @@ bool QWorkspace::eventFilter(QObject *o, QEvent * e)
{
QMenuBar* b = (QMenuBar*)o->parent();
if (!t)
- t = new QTime;
+ t = new QElapsedTimer;
if (tc != this || t->elapsed() > QApplication::doubleClickInterval()) {
if (isRightToLeft()) {
QPoint p = b->mapToGlobal(QPoint(b->x() + b->width(), b->y() + b->height()));
diff --git a/src/gui/widgets/widgets.pri b/src/gui/widgets/widgets.pri
index 6883dd8..937b8d6 100644
--- a/src/gui/widgets/widgets.pri
+++ b/src/gui/widgets/widgets.pri
@@ -164,6 +164,6 @@ wince*: {
!static: QMAKE_WRITE_DEFAULT_RC = 1
}
-symbian*: {
+symbian: {
SOURCES += widgets/qmenu_symbian.cpp
}