summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorEskil Abrahamsen Blomfeldt <eblomfel@trolltech.com>2010-02-15 11:22:25 +0100
committerEskil Abrahamsen Blomfeldt <eblomfel@trolltech.com>2010-02-15 11:22:25 +0100
commit8197e5fae939c264220666162fe9ecb624e47bef (patch)
tree08ad63b681ff701d568d771784c97be1c6274dbd /src/gui
parent9f387357a7e171636c97a7ef13afca60c01a9e3b (diff)
parent4a47bf6a06a4f7ebbf2336cd643c50332ac76d6d (diff)
Merge branch 'master' of scm.dev.troll.no:qt/oslo-staging-2 into qstatictext-4.7
Conflicts: src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp tests/auto/qlineedit/tst_qlineedit.cpp Merge branch 'master' of scm.dev.troll.no:qt/oslo-staging-2 into qstatictext-4.7 Conflicts: src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp tests/auto/qlineedit/tst_qlineedit.cpp Merge branch 'master' of scm.dev.troll.no:qt/oslo-staging-2 into qstatictext-4.7 Conflicts: src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp tests/auto/qlineedit/tst_qlineedit.cpp
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/dialogs/dialogs.pri3
-rw-r--r--src/gui/dialogs/qdialog.cpp7
-rw-r--r--src/gui/dialogs/qfiledialog_win.cpp78
-rw-r--r--src/gui/dialogs/qfiledialog_win_p.h243
-rw-r--r--src/gui/dialogs/qfileinfogatherer.cpp1
-rw-r--r--src/gui/dialogs/qfileinfogatherer_p.h1
-rw-r--r--src/gui/dialogs/qfilesystemmodel.cpp122
-rw-r--r--src/gui/dialogs/qfilesystemmodel.h1
-rw-r--r--src/gui/dialogs/qfilesystemmodel_p.h4
-rw-r--r--src/gui/dialogs/qmessagebox.cpp4
-rw-r--r--src/gui/dialogs/qprintdialog_win.cpp2
-rw-r--r--src/gui/embedded/qscreen_qws.cpp21
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp2
-rw-r--r--src/gui/graphicsview/qgraphicswidget.cpp30
-rw-r--r--src/gui/graphicsview/qgraphicswidget.h4
-rw-r--r--src/gui/graphicsview/qgraphicswidget_p.h2
-rw-r--r--src/gui/image/qimage.cpp40
-rw-r--r--src/gui/image/qimage.h2
-rw-r--r--src/gui/image/qpicture.cpp49
-rw-r--r--src/gui/image/qpixmap.cpp28
-rw-r--r--src/gui/image/qpixmap.h4
-rw-r--r--src/gui/image/qpixmap_x11.cpp26
-rw-r--r--src/gui/image/qpixmap_x11_p.h2
-rw-r--r--src/gui/image/qpnghandler.cpp137
-rw-r--r--src/gui/inputmethod/qwininputcontext_p.h2
-rw-r--r--src/gui/itemviews/qdirmodel.cpp4
-rw-r--r--src/gui/itemviews/qfileiconprovider.cpp2
-rw-r--r--src/gui/itemviews/qheaderview.cpp14
-rw-r--r--src/gui/itemviews/qsortfilterproxymodel.cpp17
-rw-r--r--src/gui/kernel/kernel.pri1
-rw-r--r--src/gui/kernel/qaction.h3
-rw-r--r--src/gui/kernel/qapplication.cpp242
-rw-r--r--src/gui/kernel/qapplication_mac.mm57
-rw-r--r--src/gui/kernel/qapplication_p.h13
-rw-r--r--src/gui/kernel/qapplication_s60.cpp2
-rw-r--r--src/gui/kernel/qapplication_x11.cpp5
-rw-r--r--src/gui/kernel/qcocoaapplicationdelegate_mac.mm7
-rw-r--r--src/gui/kernel/qcocoapanel_mac.mm1
-rw-r--r--src/gui/kernel/qcocoapanel_mac_p.h6
-rw-r--r--src/gui/kernel/qcocoasharedwindowmethods_mac_p.h188
-rw-r--r--src/gui/kernel/qcocoaview_mac.mm76
-rw-r--r--src/gui/kernel/qcocoaview_mac_p.h2
-rw-r--r--src/gui/kernel/qcocoawindow_mac.mm1
-rw-r--r--src/gui/kernel/qcocoawindow_mac_p.h3
-rw-r--r--src/gui/kernel/qcocoawindowdelegate_mac.mm7
-rw-r--r--src/gui/kernel/qcursor.cpp6
-rw-r--r--src/gui/kernel/qcursor_mac.mm24
-rw-r--r--src/gui/kernel/qcursor_win.cpp7
-rw-r--r--src/gui/kernel/qcursor_x11.cpp50
-rw-r--r--src/gui/kernel/qdnd.cpp218
-rw-r--r--src/gui/kernel/qdnd_p.h2
-rw-r--r--src/gui/kernel/qdnd_s60.cpp2
-rw-r--r--src/gui/kernel/qdnd_x11.cpp6
-rw-r--r--src/gui/kernel/qeventdispatcher_mac.mm415
-rw-r--r--src/gui/kernel/qeventdispatcher_mac_p.h11
-rw-r--r--src/gui/kernel/qguieventdispatcher_glib.cpp5
-rw-r--r--src/gui/kernel/qguieventdispatcher_glib_p.h1
-rw-r--r--src/gui/kernel/qkeysequence.cpp36
-rw-r--r--src/gui/kernel/qkeysequence.h12
-rw-r--r--src/gui/kernel/qmime_mac.cpp57
-rw-r--r--src/gui/kernel/qnsthemeframe_mac_p.h2
-rw-r--r--src/gui/kernel/qsound_s60.cpp2
-rw-r--r--src/gui/kernel/qt_cocoa_helpers_mac.mm15
-rw-r--r--src/gui/kernel/qt_cocoa_helpers_mac_p.h4
-rw-r--r--src/gui/kernel/qt_x11_p.h2
-rw-r--r--src/gui/kernel/qwidget.cpp196
-rw-r--r--src/gui/kernel/qwidget_mac.mm180
-rw-r--r--src/gui/kernel/qwidget_p.h5
-rw-r--r--src/gui/kernel/qwidget_win.cpp21
-rw-r--r--src/gui/mac/qt_menu.nib/classes.nib16
-rw-r--r--src/gui/mac/qt_menu.nib/info.nib4
-rw-r--r--src/gui/mac/qt_menu.nib/keyedobjects.nibbin5567 -> 5560 bytes
-rw-r--r--src/gui/math3d/qmatrix4x4.h2
-rw-r--r--src/gui/math3d/qquaternion.h2
-rw-r--r--src/gui/math3d/qvector2d.h2
-rw-r--r--src/gui/math3d/qvector3d.h2
-rw-r--r--src/gui/math3d/qvector4d.h2
-rw-r--r--src/gui/painting/qbrush.cpp36
-rw-r--r--src/gui/painting/qdatabuffer_p.h7
-rw-r--r--src/gui/painting/qemulationpaintengine.cpp30
-rw-r--r--src/gui/painting/qpainterpath.cpp2
-rw-r--r--src/gui/statemachine/qguistatemachine.cpp6
-rw-r--r--src/gui/styles/qcommonstyle.cpp8
-rw-r--r--src/gui/styles/qmacstyle_mac.mm13
-rw-r--r--src/gui/styles/qs60style_s60.cpp4
-rw-r--r--src/gui/styles/qs60style_simulated.cpp12
-rw-r--r--src/gui/styles/qstylesheetstyle.cpp8
-rw-r--r--src/gui/text/qfontdatabase_s60.cpp2
-rw-r--r--src/gui/text/qfontdatabase_win.cpp1
-rw-r--r--src/gui/text/qfontengine_s60_p.h2
-rw-r--r--src/gui/text/qtextcontrol.cpp4
-rw-r--r--src/gui/text/qtextdocument.cpp22
-rw-r--r--src/gui/text/qtextdocument.h7
-rw-r--r--src/gui/text/qtextdocument_p.cpp63
-rw-r--r--src/gui/text/qtextdocument_p.h3
-rw-r--r--src/gui/util/qcompleter.cpp77
-rw-r--r--src/gui/util/qcompleter.h1
-rw-r--r--src/gui/util/qcompleter_p.h1
-rw-r--r--src/gui/util/qdesktopservices_win.cpp16
-rw-r--r--src/gui/util/qsystemtrayicon_win.cpp3
-rw-r--r--src/gui/widgets/qcocoamenu_mac.mm33
-rw-r--r--src/gui/widgets/qcocoamenu_mac_p.h4
-rw-r--r--src/gui/widgets/qcombobox.cpp5
-rw-r--r--src/gui/widgets/qdatetimeedit.cpp2
-rw-r--r--src/gui/widgets/qdockarealayout.cpp62
-rw-r--r--src/gui/widgets/qdockarealayout_p.h5
-rw-r--r--src/gui/widgets/qfocusframe.cpp91
-rw-r--r--src/gui/widgets/qlabel.cpp93
-rw-r--r--src/gui/widgets/qlabel.h7
-rw-r--r--src/gui/widgets/qlineedit.cpp6
-rw-r--r--src/gui/widgets/qmainwindow.cpp13
-rw-r--r--src/gui/widgets/qmenu.cpp4
-rw-r--r--src/gui/widgets/qmenu.h1
-rw-r--r--src/gui/widgets/qmenu_mac.mm190
-rw-r--r--src/gui/widgets/qplaintextedit.cpp1
-rw-r--r--src/gui/widgets/qtabbar.cpp4
-rw-r--r--src/gui/widgets/qtabbar_p.h3
-rw-r--r--src/gui/widgets/qtoolbar.cpp9
-rw-r--r--src/gui/widgets/qtoolbar.h1
-rw-r--r--src/gui/widgets/qvalidator.cpp20
-rw-r--r--src/gui/widgets/qvalidator.h1
121 files changed, 2498 insertions, 1160 deletions
diff --git a/src/gui/dialogs/dialogs.pri b/src/gui/dialogs/dialogs.pri
index 63f64a2d0d..4e1b9a71d1 100644
--- a/src/gui/dialogs/dialogs.pri
+++ b/src/gui/dialogs/dialogs.pri
@@ -50,7 +50,8 @@ HEADERS += \
}
win32 {
- HEADERS += dialogs/qwizard_win_p.h
+ HEADERS += dialogs/qwizard_win_p.h \
+ dialogs/qfiledialog_win_p.h
SOURCES += dialogs/qdialogsbinarycompat_win.cpp \
dialogs/qfiledialog_win.cpp \
dialogs/qpagesetupdialog_win.cpp \
diff --git a/src/gui/dialogs/qdialog.cpp b/src/gui/dialogs/qdialog.cpp
index 9ff2ad821c..fb0dba4e61 100644
--- a/src/gui/dialogs/qdialog.cpp
+++ b/src/gui/dialogs/qdialog.cpp
@@ -648,13 +648,14 @@ void QDialog::contextMenuEvent(QContextMenuEvent *e)
while (w && w->whatsThis().size() == 0 && !w->testAttribute(Qt::WA_CustomWhatsThis))
w = w->isWindow() ? 0 : w->parentWidget();
if (w) {
- QMenu p(this);
- QAction *wt = p.addAction(tr("What's This?"));
- if (p.exec(e->globalPos()) == wt) {
+ QWeakPointer<QMenu> p = new QMenu(this);
+ QAction *wt = p.data()->addAction(tr("What's This?"));
+ if (p.data()->exec(e->globalPos()) == wt) {
QHelpEvent e(QEvent::WhatsThis, w->rect().center(),
w->mapToGlobal(w->rect().center()));
QApplication::sendEvent(w, &e);
}
+ delete p.data();
}
#endif
}
diff --git a/src/gui/dialogs/qfiledialog_win.cpp b/src/gui/dialogs/qfiledialog_win.cpp
index 5a7ace99fe..3120938e43 100644
--- a/src/gui/dialogs/qfiledialog_win.cpp
+++ b/src/gui/dialogs/qfiledialog_win.cpp
@@ -53,53 +53,27 @@
#include <qdir.h>
#include <qstringlist.h>
#include <qlibrary.h>
+#include "qfiledialog_win_p.h"
#ifndef QT_NO_THREAD
# include <private/qmutexpool_p.h>
#endif
-#include <shlobj.h>
-//At some point we can hope that mingw will support that interface
-#if !defined(Q_WS_WINCE) && !defined(Q_CC_MINGW)
-#include <shobjidl.h>
-#endif
-
-#include <objbase.h>
-
-#if defined(__IFileDialog_INTERFACE_DEFINED__) \
- && defined(__IFileOpenDialog_INTERFACE_DEFINED__)
-#define USE_COMMON_ITEM_DIALOG
-#endif
-
#ifdef Q_WS_WINCE
+#include <shlobj.h>
#include <commdlg.h>
-# ifndef BFFM_SETSELECTION
-# define BFFM_SETSELECTION (WM_USER + 102)
-# endif
-// Windows Mobile has a broken definition for BROWSEINFO
-// Only compile fix
-typedef struct qt_priv_browseinfo {
- HWND hwndOwner;
- LPCITEMIDLIST pidlRoot;
- LPWSTR pszDisplayName;
- LPCWSTR lpszTitle;
- UINT ulFlags;
- BFFCALLBACK lpfn;
- LPARAM lParam;
- int iImage;
-} qt_BROWSEINFO;
bool qt_priv_ptr_valid = false;
+#else
+//we have to declare them here because they're not present for all SDK/compilers
+static const IID QT_IID_IFileOpenDialog = {0xd57c7288, 0xd4ad, 0x4768, {0xbe, 0x02, 0x9d, 0x96, 0x95, 0x32, 0xd9, 0x60} };
+static const IID QT_IID_IShellItem = {0x43826d1e, 0xe718, 0x42ee, {0xbc, 0x55, 0xa1, 0xe2, 0x61, 0xc3, 0x7b, 0xfe} };
+static const CLSID QT_CLSID_FileOpenDialog = {0xdc1c5a9c, 0xe88a, 0x4dde, {0xa5, 0xa1, 0x60, 0xf8, 0x2a, 0x20, 0xae, 0xf7} };
#endif
-// Don't remove the lines below!
-//
-// resolving the W methods manually is needed, because Windows 95 doesn't include
-// these methods in Shell32.lib (not even stubs!), so you'd get an unresolved symbol
-// when Qt calls getExistingDirectory(), etc.
-typedef LPITEMIDLIST (WINAPI *PtrSHBrowseForFolder)(BROWSEINFO*);
+typedef qt_LPITEMIDLIST (WINAPI *PtrSHBrowseForFolder)(qt_BROWSEINFO*);
static PtrSHBrowseForFolder ptrSHBrowseForFolder = 0;
-typedef BOOL (WINAPI *PtrSHGetPathFromIDList)(LPITEMIDLIST,LPWSTR);
+typedef BOOL (WINAPI *PtrSHGetPathFromIDList)(qt_LPITEMIDLIST, LPWSTR);
static PtrSHGetPathFromIDList ptrSHGetPathFromIDList = 0;
typedef HRESULT (WINAPI *PtrSHGetMalloc)(LPMALLOC *);
static PtrSHGetMalloc ptrSHGetMalloc = 0;
@@ -132,7 +106,7 @@ static void qt_win_resolve_libs()
ptrSHGetMalloc = (PtrSHGetMalloc) lib.resolve("SHGetMalloc");
#else
// CE stores them in a different lib and does not use unicode version
- HINSTANCE handle = LoadLibraryW(L"Ceshell");
+ HINSTANCE handle = LoadLibrary(L"Ceshell");
ptrSHBrowseForFolder = (PtrSHBrowseForFolder)GetProcAddress(handle, L"SHBrowseForFolder");
ptrSHGetPathFromIDList = (PtrSHGetPathFromIDList)GetProcAddress(handle, L"SHGetPathFromIDList");
ptrSHGetMalloc = (PtrSHGetMalloc)GetProcAddress(handle, L"SHGetMalloc");
@@ -421,7 +395,7 @@ QString qt_win_get_save_file_name(const QFileDialogArgs &args,
}
-#if defined(USE_COMMON_ITEM_DIALOG)
+#ifndef Q_WS_WINCE
typedef HRESULT (WINAPI *PtrSHCreateItemFromParsingName)(PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv);
static PtrSHCreateItemFromParsingName pSHCreateItemFromParsingName = 0;
@@ -469,7 +443,7 @@ static bool qt_win_set_IFileDialogOptions(IFileDialog *pfd,
// Add the filters to the file dialog.
if (numFilters) {
wchar_t *szData = (wchar_t*)winfilters.utf16();
- COMDLG_FILTERSPEC *filterSpec = new COMDLG_FILTERSPEC[numFilters];
+ qt_COMDLG_FILTERSPEC *filterSpec = new qt_COMDLG_FILTERSPEC[numFilters];
for(int i = 0; i<numFilters; i++) {
filterSpec[i].pszName = szData+offsets[i*2];
filterSpec[i].pszSpec = szData+offsets[(i*2)+1];
@@ -481,9 +455,8 @@ static bool qt_win_set_IFileDialogOptions(IFileDialog *pfd,
tInitDir = QDir::toNativeSeparators(initialDirectory);
if (!tInitDir.isEmpty()) {
IShellItem *psiDefaultFolder;
- hr = pSHCreateItemFromParsingName((wchar_t*)tInitDir.utf16(),
- NULL,
- IID_PPV_ARGS(&psiDefaultFolder));
+ hr = pSHCreateItemFromParsingName((wchar_t*)tInitDir.utf16(), NULL, QT_IID_IShellItem,
+ reinterpret_cast<void**>(&psiDefaultFolder));
if (SUCCEEDED(hr)) {
hr = pfd->SetFolder(psiDefaultFolder);
@@ -522,7 +495,7 @@ static bool qt_win_set_IFileDialogOptions(IFileDialog *pfd,
return SUCCEEDED(hr);
}
-QStringList qt_win_CID_get_open_file_names(const QFileDialogArgs &args,
+static QStringList qt_win_CID_get_open_file_names(const QFileDialogArgs &args,
QString *initialDirectory,
const QStringList &filterList,
QString *selectedFilter,
@@ -535,10 +508,8 @@ QStringList qt_win_CID_get_open_file_names(const QFileDialogArgs &args,
QApplicationPrivate::enterModal(&modal_widget);
// Multiple selection is allowed only in IFileOpenDialog.
IFileOpenDialog *pfd = 0;
- HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog,
- NULL,
- CLSCTX_INPROC_SERVER,
- IID_PPV_ARGS(&pfd));
+ 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,
@@ -643,7 +614,7 @@ QStringList qt_win_get_open_file_names(const QFileDialogArgs &args,
// multiple files belonging to different folders from these search results, the
// GetOpenFileName() will return only one folder name for all the files. To retrieve
// the correct path for all selected files, we have to use Common Item Dialog interfaces.
-#if defined(USE_COMMON_ITEM_DIALOG)
+#ifndef Q_WS_WINCE
if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)
return qt_win_CID_get_open_file_names(args, initialDirectory, filterLst, selectedFilter, idx);
#endif
@@ -716,7 +687,7 @@ static int __stdcall winGetExistDirCallbackProc(HWND hwnd,
qt_win_resolve_libs();
if (ptrSHGetPathFromIDList) {
wchar_t path[MAX_PATH];
- ptrSHGetPathFromIDList(LPITEMIDLIST(lParam), path);
+ ptrSHGetPathFromIDList(qt_LPITEMIDLIST(lParam), path);
QString tmpStr = QString::fromWCharArray(path);
if (!tmpStr.isEmpty())
SendMessage(hwnd, BFFM_ENABLEOK, 1, 1);
@@ -728,11 +699,6 @@ static int __stdcall winGetExistDirCallbackProc(HWND hwnd,
return 0;
}
-#ifndef BIF_NEWDIALOGSTYLE
-#define BIF_NEWDIALOGSTYLE 0x0040 // Use the new dialog layout with the ability to resize
-#endif
-
-
QString qt_win_get_existing_directory(const QFileDialogArgs &args)
{
QString currentDir = QDir::currentPath();
@@ -757,11 +723,7 @@ QString qt_win_get_existing_directory(const QFileDialogArgs &args)
path[0] = 0;
tTitle = args.caption;
-#if !defined(Q_WS_WINCE)
- BROWSEINFO bi;
-#else
qt_BROWSEINFO bi;
-#endif
Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created));
bi.hwndOwner = (parent ? parent->winId() : 0);
@@ -775,7 +737,7 @@ QString qt_win_get_existing_directory(const QFileDialogArgs &args)
qt_win_resolve_libs();
if (ptrSHBrowseForFolder) {
- LPITEMIDLIST pItemIDList = ptrSHBrowseForFolder((BROWSEINFO*)&bi);
+ qt_LPITEMIDLIST pItemIDList = ptrSHBrowseForFolder(&bi);
if (pItemIDList) {
ptrSHGetPathFromIDList(pItemIDList, path);
IMalloc *pMalloc;
diff --git a/src/gui/dialogs/qfiledialog_win_p.h b/src/gui/dialogs/qfiledialog_win_p.h
new file mode 100644
index 0000000000..527ab3fc59
--- /dev/null
+++ b/src/gui/dialogs/qfiledialog_win_p.h
@@ -0,0 +1,243 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 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$
+**
+****************************************************************************/
+
+#include <objbase.h>
+#ifndef QFILEDIAG_WIN_P_H
+#define QFILEDIAG_WIN_P_H
+
+//these are the interface declarations needed for the file dialog on Vista and up
+
+//At some point we can hope that all compilers/sdk will support that interface
+//and we won't have to declare it ourselves
+
+//declarations
+#define FOS_OVERWRITEPROMPT 0x2
+#define FOS_STRICTFILETYPES 0x4
+#define FOS_NOCHANGEDIR 0x8
+#define FOS_PICKFOLDERS 0x20
+#define FOS_FORCEFILESYSTEM 0x40
+#define FOS_ALLNONSTORAGEITEMS 0x80
+#define FOS_NOVALIDATE 0x100
+#define FOS_ALLOWMULTISELECT 0x200
+#define FOS_PATHMUSTEXIST 0x800
+#define FOS_FILEMUSTEXIST 0x1000
+#define FOS_CREATEPROMPT 0x2000
+#define FOS_SHAREAWARE 0x4000
+#define FOS_NOREADONLYRETURN 0x8000
+#define FOS_NOTESTFILECREATE 0x10000
+#define FOS_HIDEMRUPLACES 0x20000
+#define FOS_HIDEPINNEDPLACES 0x40000
+#define FOS_NODEREFERENCELINKS 0x100000
+#define FOS_DONTADDTORECENT 0x2000000
+#define FOS_FORCESHOWHIDDEN 0x10000000
+#define FOS_DEFAULTNOMINIMODE 0x20000000
+#define FOS_FORCEPREVIEWPANEON 0x40000000
+
+typedef int GETPROPERTYSTOREFLAGS;
+#define GPS_DEFAULT 0x00000000
+#define GPS_HANDLERPROPERTIESONLY 0x00000001
+#define GPS_READWRITE 0x00000002
+#define GPS_TEMPORARY 0x00000004
+#define GPS_FASTPROPERTIESONLY 0x00000008
+#define GPS_OPENSLOWITEM 0x00000010
+#define GPS_DELAYCREATION 0x00000020
+#define GPS_BESTEFFORT 0x00000040
+#define GPS_MASK_VALID 0x0000007F
+
+typedef int (CALLBACK* BFFCALLBACK)(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData);
+// message from browser
+#define BFFM_INITIALIZED 1
+#define BFFM_SELCHANGED 2
+#define BFFM_ENABLEOK (WM_USER + 101)
+#define BFFM_SETSELECTION (WM_USER + 103)
+#define BFFM_SETSTATUSTEXT (WM_USER + 104)
+
+// Browsing for directory.
+#define BIF_RETURNONLYFSDIRS 0x0001
+#define BIF_DONTGOBELOWDOMAIN 0x0002
+#define BIF_STATUSTEXT 0x0004
+#define BIF_RETURNFSANCESTORS 0x0008
+#define BIF_EDITBOX 0x0010
+#define BIF_VALIDATE 0x0020
+#define BIF_NEWDIALOGSTYLE 0x0040
+#define BIF_BROWSEINCLUDEURLS 0x0080
+#define BIF_UAHINT 0x0100
+#define BIF_NONEWFOLDERBUTTON 0x0200
+#define BIF_NOTRANSLATETARGETS 0x0400
+#define BIF_BROWSEFORCOMPUTER 0x1000
+#define BIF_BROWSEFORPRINTER 0x2000
+#define BIF_BROWSEINCLUDEFILES 0x4000
+#define BIF_SHAREABLE 0x8000
+
+//the enums
+typedef enum {
+ SIATTRIBFLAGS_AND = 0x1,
+ SIATTRIBFLAGS_OR = 0x2,
+ SIATTRIBFLAGS_APPCOMPAT = 0x3,
+ SIATTRIBFLAGS_MASK = 0x3
+} SIATTRIBFLAGS;
+typedef enum {
+ SIGDN_NORMALDISPLAY = 0x00000000,
+ SIGDN_PARENTRELATIVEPARSING = 0x80018001,
+ SIGDN_PARENTRELATIVEFORADDRESSBAR = 0x8001c001,
+ SIGDN_DESKTOPABSOLUTEPARSING = 0x80028000,
+ SIGDN_PARENTRELATIVEEDITING = 0x80031001,
+ SIGDN_DESKTOPABSOLUTEEDITING = 0x8004c000,
+ SIGDN_FILESYSPATH = 0x80058000,
+ SIGDN_URL = 0x80068000
+} SIGDN;
+typedef enum {
+ FDAP_BOTTOM = 0x00000000,
+ FDAP_TOP = 0x00000001
+} FDAP;
+typedef enum {
+ FDESVR_DEFAULT = 0x00000000,
+ FDESVR_ACCEPT = 0x00000001,
+ FDESVR_REFUSE = 0x00000002
+} FDE_SHAREVIOLATION_RESPONSE;
+typedef FDE_SHAREVIOLATION_RESPONSE FDE_OVERWRITE_RESPONSE;
+
+//the structs
+typedef struct {
+ LPCWSTR pszName;
+ LPCWSTR pszSpec;
+} qt_COMDLG_FILTERSPEC;
+typedef struct {
+ GUID fmtid;
+ DWORD pid;
+} qt_PROPERTYKEY;
+
+typedef struct {
+ USHORT cb;
+ BYTE abID[1];
+} qt_SHITEMID, *qt_LPSHITEMID;
+typedef struct {
+ qt_SHITEMID mkid;
+} qt_ITEMIDLIST, *qt_LPITEMIDLIST;
+typedef const qt_ITEMIDLIST *qt_LPCITEMIDLIST;
+typedef struct {
+ HWND hwndOwner;
+ qt_LPCITEMIDLIST pidlRoot;
+ LPWSTR pszDisplayName;
+ LPCWSTR lpszTitle;
+ UINT ulFlags;
+ BFFCALLBACK lpfn;
+ LPARAM lParam;
+ int iImage;
+} qt_BROWSEINFO;
+
+DECLARE_INTERFACE(IFileDialogEvents);
+DECLARE_INTERFACE_(IShellItem, IUnknown)
+{
+ STDMETHOD(BindToHandler)(THIS_ IBindCtx *pbc, REFGUID bhid, REFIID riid, void **ppv) PURE;
+ STDMETHOD(GetParent)(THIS_ IShellItem **ppsi) PURE;
+ STDMETHOD(GetDisplayName)(THIS_ SIGDN sigdnName, LPWSTR *ppszName) PURE;
+ STDMETHOD(GetAttributes)(THIS_ ULONG sfgaoMask, ULONG *psfgaoAttribs) PURE;
+ STDMETHOD(Compare)(THIS_ IShellItem *psi, DWORD hint, int *piOrder) PURE;
+};
+DECLARE_INTERFACE_(IShellItemFilter, IUnknown)
+{
+ STDMETHOD(IncludeItem)(THIS_ IShellItem *psi) PURE;
+ STDMETHOD(GetEnumFlagsForItem)(THIS_ IShellItem *psi, DWORD *pgrfFlags) PURE;
+};
+DECLARE_INTERFACE_(IEnumShellItems, IUnknown)
+{
+ STDMETHOD(Next)(THIS_ ULONG celt, IShellItem **rgelt, ULONG *pceltFetched) PURE;
+ STDMETHOD(Skip)(THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset)(THIS_) PURE;
+ STDMETHOD(Clone)(THIS_ IEnumShellItems **ppenum) PURE;
+};
+DECLARE_INTERFACE_(IShellItemArray, IUnknown)
+{
+ STDMETHOD(BindToHandler)(THIS_ IBindCtx *pbc, REFGUID rbhid, REFIID riid, void **ppvOut) PURE;
+ STDMETHOD(GetPropertyStore)(THIS_ GETPROPERTYSTOREFLAGS flags, REFIID riid, void **ppv) PURE;
+ STDMETHOD(GetPropertyDescriptionList)(THIS_ const qt_PROPERTYKEY *keyType, REFIID riid, void **ppv) PURE;
+ STDMETHOD(GetAttributes)(THIS_ SIATTRIBFLAGS dwAttribFlags, ULONG sfgaoMask, ULONG *psfgaoAttribs) PURE;
+ STDMETHOD(GetCount)(THIS_ DWORD *pdwNumItems) PURE;
+ STDMETHOD(GetItemAt)(THIS_ DWORD dwIndex, IShellItem **ppsi) PURE;
+ STDMETHOD(EnumItems)(THIS_ IEnumShellItems **ppenumShellItems) PURE;
+};
+DECLARE_INTERFACE_(IModalWindow, IUnknown)
+{
+ STDMETHOD(Show)(THIS_ HWND hwndParent) PURE;
+};
+DECLARE_INTERFACE_(IFileDialog, IModalWindow)
+{
+ STDMETHOD(SetFileTypes)(THIS_ UINT cFileTypes, const qt_COMDLG_FILTERSPEC *rgFilterSpec) PURE;
+ STDMETHOD(SetFileTypeIndex)(THIS_ UINT iFileType) PURE;
+ STDMETHOD(GetFileTypeIndex)(THIS_ UINT *piFileType) PURE;
+ STDMETHOD(Advise)(THIS_ IFileDialogEvents *pfde, DWORD *pdwCookie) PURE;
+ STDMETHOD(Unadvise)(THIS_ DWORD dwCookie) PURE;
+ STDMETHOD(SetOptions)(THIS_ DWORD fos) PURE;
+ STDMETHOD(GetOptions)(THIS_ DWORD *pfos) PURE;
+ STDMETHOD(SetDefaultFolder)(THIS_ IShellItem *psi) PURE;
+ STDMETHOD(SetFolder)(THIS_ IShellItem *psi) PURE;
+ STDMETHOD(GetFolder)(THIS_ IShellItem **ppsi) PURE;
+ STDMETHOD(GetCurrentSelection)(THIS_ IShellItem **ppsi) PURE;
+ STDMETHOD(SetFileName)(THIS_ LPCWSTR pszName) PURE;
+ STDMETHOD(GetFileName)(THIS_ LPWSTR *pszName) PURE;
+ STDMETHOD(SetTitle)(THIS_ LPCWSTR pszTitle) PURE;
+ STDMETHOD(SetOkButtonLabel)(THIS_ LPCWSTR pszText) PURE;
+ STDMETHOD(SetFileNameLabel)(THIS_ LPCWSTR pszLabel) PURE;
+ STDMETHOD(GetResult)(THIS_ IShellItem **ppsi) PURE;
+ STDMETHOD(AddPlace)(THIS_ IShellItem *psi, FDAP fdap) PURE;
+ STDMETHOD(SetDefaultExtension)(THIS_ LPCWSTR pszDefaultExtension) PURE;
+ STDMETHOD(Close)(THIS_ HRESULT hr) PURE;
+ STDMETHOD(SetClientGuid)(THIS_ REFGUID guid) PURE;
+ STDMETHOD(ClearClientData)(THIS_) PURE;
+ STDMETHOD(SetFilter)(THIS_ IShellItemFilter *pFilter) PURE;
+};
+DECLARE_INTERFACE_(IFileDialogEvents, IUnknown)
+{
+ STDMETHOD(OnFileOk)(THIS_ IFileDialog *pfd) PURE;
+ STDMETHOD(OnFolderChanging)(THIS_ IFileDialog *pfd, IShellItem *psiFolder) PURE;
+ STDMETHOD(OnFolderChange)(THIS_ IFileDialog *pfd) PURE;
+ STDMETHOD(OnSelectionChange)(THIS_ IFileDialog *pfd) PURE;
+ STDMETHOD(OnShareViolation)(THIS_ IFileDialog *pfd, IShellItem *psi, FDE_SHAREVIOLATION_RESPONSE *pResponse) PURE;
+ STDMETHOD(OnTypeChange)(THIS_ IFileDialog *pfd) PURE;
+ STDMETHOD(OnOverwrite)(THIS_ IFileDialog *pfd, IShellItem *psi, FDE_OVERWRITE_RESPONSE *pResponse) PURE;
+};
+DECLARE_INTERFACE_(IFileOpenDialog, IFileDialog)
+{
+ STDMETHOD(GetResults)(THIS_ IShellItemArray **ppenum) PURE;
+ STDMETHOD(GetSelectedItems)(THIS_ IShellItemArray **ppsai) PURE;
+};
+#endif \ No newline at end of file
diff --git a/src/gui/dialogs/qfileinfogatherer.cpp b/src/gui/dialogs/qfileinfogatherer.cpp
index 1f619578bb..c75cdfd2b7 100644
--- a/src/gui/dialogs/qfileinfogatherer.cpp
+++ b/src/gui/dialogs/qfileinfogatherer.cpp
@@ -354,6 +354,7 @@ void QFileInfoGatherer::getFileInfos(const QString &path, const QStringList &fil
}
if (!updatedFiles.isEmpty())
emit updates(path, updatedFiles);
+ emit directoryLoaded(path);
}
void QFileInfoGatherer::fetch(const QFileInfo &fileInfo, QTime &base, bool &firstTime, QList<QPair<QString, QFileInfo> > &updatedFiles, const QString &path) {
diff --git a/src/gui/dialogs/qfileinfogatherer_p.h b/src/gui/dialogs/qfileinfogatherer_p.h
index 0242178292..b8b58a2c75 100644
--- a/src/gui/dialogs/qfileinfogatherer_p.h
+++ b/src/gui/dialogs/qfileinfogatherer_p.h
@@ -155,6 +155,7 @@ Q_SIGNALS:
void updates(const QString &directory, const QList<QPair<QString, QFileInfo> > &updates);
void newListOfFiles(const QString &directory, const QStringList &listOfFiles) const;
void nameResolved(const QString &fileName, const QString &resolvedName) const;
+ void directoryLoaded(const QString &path);
public:
QFileInfoGatherer(QObject *parent = 0);
diff --git a/src/gui/dialogs/qfilesystemmodel.cpp b/src/gui/dialogs/qfilesystemmodel.cpp
index 6fd947ce3b..ba0a560725 100644
--- a/src/gui/dialogs/qfilesystemmodel.cpp
+++ b/src/gui/dialogs/qfilesystemmodel.cpp
@@ -51,6 +51,9 @@
#ifdef Q_OS_WIN
#include <qt_windows.h>
#endif
+#ifdef Q_OS_WIN32
+#include <QtCore/QVarLengthArray>
+#endif
QT_BEGIN_NAMESPACE
@@ -150,6 +153,14 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \since 4.7
+ \fn void QFileSystemModel::directoryLoaded(const QString &path)
+
+ This signal is emitted when the gatherer thread has finished to load the \a path.
+
+*/
+
+/*!
\fn bool QFileSystemModel::remove(const QModelIndex &index) const
Removes the model item \a index from the file system model and \bold{deletes the
@@ -270,53 +281,38 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QM
return indexNode;
}
-#ifdef Q_OS_WIN
+#ifdef Q_OS_WIN32
static QString qt_GetLongPathName(const QString &strShortPath)
{
- QString longPath;
- int i = 0;
- if (strShortPath == QLatin1String(".")
- || (strShortPath.startsWith(QLatin1String("//")))
- || (strShortPath.startsWith(QLatin1String("\\\\")))) // unc
+ if (strShortPath.isEmpty()
+ || strShortPath == QLatin1String(".") || strShortPath == QLatin1String(".."))
return strShortPath;
- QString::const_iterator it = strShortPath.constBegin();
- QString::const_iterator constEnd = strShortPath.constEnd();
- do {
- bool isSep = (*it == QLatin1Char('\\') || *it == QLatin1Char('/'));
- if (isSep || it == constEnd) {
- QString section = (it == constEnd ? strShortPath : strShortPath.left(i));
- // FindFirstFile does not handle volumes ("C:"), so we have to catch that ourselves.
- if (section.endsWith(QLatin1Char(':'))) {
- longPath.append(section.toUpper());
- } else {
- HANDLE h;
-#ifndef Q_OS_WINCE
- //We add the extend length prefix to handle long path
- QString longSection = QLatin1String("\\\\?\\")+QDir::toNativeSeparators(section);
-#else
- QString longSection = QDir::toNativeSeparators(section);
-#endif
- WIN32_FIND_DATA findData;
- h = ::FindFirstFile((wchar_t*)longSection.utf16(), &findData);
- if (h != INVALID_HANDLE_VALUE) {
- longPath.append(QString::fromWCharArray(findData.cFileName));
- ::FindClose(h);
- } else {
- longPath.append(section);
- break;
- }
- }
- if (it != constEnd)
- longPath.append(*it);
- else
- break;
- }
- ++it;
- if (isSep && it == constEnd) // break out if the last character is a separator
- break;
- ++i;
- } while (true);
- return longPath;
+ if (strShortPath.length() == 2 && strShortPath.endsWith(QLatin1Char(':')))
+ return strShortPath.toUpper();
+ const QString absPath = QDir(strShortPath).absolutePath();
+ if (absPath.startsWith(QLatin1String("//"))
+ || absPath.startsWith(QLatin1String("\\\\"))) // unc
+ return QDir::fromNativeSeparators(absPath);
+ if (absPath.startsWith(QLatin1Char('/')))
+ return QString();
+ const QString inputString = QLatin1String("\\\\?\\") + QDir::toNativeSeparators(absPath);
+ QVarLengthArray<TCHAR, MAX_PATH> buffer(MAX_PATH);
+ DWORD result = ::GetLongPathName((wchar_t*)inputString.utf16(),
+ buffer.data(),
+ buffer.size());
+ if (result > DWORD(buffer.size())) {
+ buffer.resize(result);
+ result = ::GetLongPathName((wchar_t*)inputString.utf16(),
+ buffer.data(),
+ buffer.size());
+ }
+ if (result > 4) {
+ QString longPath = QString::fromWCharArray(buffer.data() + 4); // ignoring prefix
+ longPath[0] = longPath.at(0).toUpper(); // capital drive letters
+ return QDir::fromNativeSeparators(longPath);
+ } else {
+ return QDir::fromNativeSeparators(strShortPath);
+ }
}
#endif
@@ -334,7 +330,7 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS
// Construct the nodes up to the new root path if they need to be built
QString absolutePath;
-#ifdef Q_OS_WIN
+#ifdef Q_OS_WIN32
QString longPath = qt_GetLongPathName(path);
#else
QString longPath = path;
@@ -673,7 +669,7 @@ QVariant QFileSystemModel::data(const QModelIndex &index, int role) const
case Qt::EditRole:
case Qt::DisplayRole:
switch (index.column()) {
- case 0: return d->name(index);
+ case 0: return d->displayName(index);
case 1: return d->size(index);
case 2: return d->type(index);
case 3: return d->time(index);
@@ -789,13 +785,25 @@ QString QFileSystemModelPrivate::name(const QModelIndex &index) const
if (resolvedSymLinks.contains(fullPath))
return resolvedSymLinks[fullPath];
}
- // ### TODO it would be nice to grab the volume name if dirNode->parent == root
return dirNode->fileName;
}
/*!
\internal
*/
+QString QFileSystemModelPrivate::displayName(const QModelIndex &index) const
+{
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ QFileSystemNode *dirNode = node(index);
+ if (!dirNode->volumeName.isNull())
+ return dirNode->volumeName + QLatin1String(" (") + name(index) + QLatin1Char(')');
+#endif
+ return name(index);
+}
+
+/*!
+ \internal
+*/
QIcon QFileSystemModelPrivate::icon(const QModelIndex &index) const
{
if (!index.isValid())
@@ -1337,7 +1345,11 @@ QModelIndex QFileSystemModel::setRootPath(const QString &newPath)
{
Q_D(QFileSystemModel);
#ifdef Q_OS_WIN
- QString longNewPath = QDir::fromNativeSeparators(qt_GetLongPathName(newPath));
+#ifdef Q_OS_WIN32
+ QString longNewPath = qt_GetLongPathName(newPath);
+#else
+ QString longNewPath = QDir::fromNativeSeparators(newPath);
+#endif
#else
QString longNewPath = newPath;
#endif
@@ -1640,6 +1652,18 @@ QFileSystemModelPrivate::QFileSystemNode* QFileSystemModelPrivate::addNode(QFile
#ifndef QT_NO_FILESYSTEMWATCHER
node->populate(info);
#endif
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ //The parentNode is "" so we are listing the drives
+ if (parentNode->fileName.isEmpty()) {
+ wchar_t name[MAX_PATH + 1];
+ //GetVolumeInformation requires to add trailing backslash
+ const QString nodeName = fileName + QLatin1String("\\");
+ BOOL success = ::GetVolumeInformation((wchar_t *)(nodeName.utf16()),
+ name, MAX_PATH + 1, NULL, 0, NULL, NULL, 0);
+ if (success && name[0])
+ node->volumeName = QString::fromWCharArray(name);
+ }
+#endif
parentNode->children.insert(fileName, node);
return node;
}
@@ -1869,6 +1893,8 @@ void QFileSystemModelPrivate::init()
q, SLOT(_q_fileSystemChanged(QString,QList<QPair<QString,QFileInfo> >)));
q->connect(&fileInfoGatherer, SIGNAL(nameResolved(QString,QString)),
q, SLOT(_q_resolvedName(QString,QString)));
+ q->connect(&fileInfoGatherer, SIGNAL(directoryLoaded(QString)),
+ q, SIGNAL(directoryLoaded(QString)));
q->connect(&delayedSortTimer, SIGNAL(timeout()), q, SLOT(_q_performDelayedSort()), Qt::QueuedConnection);
}
diff --git a/src/gui/dialogs/qfilesystemmodel.h b/src/gui/dialogs/qfilesystemmodel.h
index 4dcfe26835..d8178c70b0 100644
--- a/src/gui/dialogs/qfilesystemmodel.h
+++ b/src/gui/dialogs/qfilesystemmodel.h
@@ -70,6 +70,7 @@ class Q_GUI_EXPORT QFileSystemModel : public QAbstractItemModel
Q_SIGNALS:
void rootPathChanged(const QString &newPath);
void fileRenamed(const QString &path, const QString &oldName, const QString &newName);
+ void directoryLoaded(const QString &path);
public:
enum Roles {
diff --git a/src/gui/dialogs/qfilesystemmodel_p.h b/src/gui/dialogs/qfilesystemmodel_p.h
index 6c85a7c348..03e0bfb8bd 100644
--- a/src/gui/dialogs/qfilesystemmodel_p.h
+++ b/src/gui/dialogs/qfilesystemmodel_p.h
@@ -97,6 +97,9 @@ public:
}
QString fileName;
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ QString volumeName;
+#endif
inline qint64 size() const { if (info && !info->isDir()) return info->size(); return 0; }
inline QString type() const { if (info) return info->displayType; return QLatin1String(""); }
@@ -278,6 +281,7 @@ public:
QIcon icon(const QModelIndex &index) const;
QString name(const QModelIndex &index) const;
+ QString displayName(const QModelIndex &index) const;
QString filePath(const QModelIndex &index) const;
QString size(const QModelIndex &index) const;
static QString size(qint64 bytes);
diff --git a/src/gui/dialogs/qmessagebox.cpp b/src/gui/dialogs/qmessagebox.cpp
index d1b2e3f6a0..ed437ff162 100644
--- a/src/gui/dialogs/qmessagebox.cpp
+++ b/src/gui/dialogs/qmessagebox.cpp
@@ -92,8 +92,8 @@ public:
{
#ifndef QT_NO_CONTEXTMENU
QMenu *menu = createStandardContextMenu();
- menu->exec(e->globalPos());
- delete menu;
+ menu->setAttribute(Qt::WA_DeleteOnClose);
+ menu->popup(e->globalPos());
#else
Q_UNUSED(e);
#endif
diff --git a/src/gui/dialogs/qprintdialog_win.cpp b/src/gui/dialogs/qprintdialog_win.cpp
index 5ccd33d27b..fa0c99fda9 100644
--- a/src/gui/dialogs/qprintdialog_win.cpp
+++ b/src/gui/dialogs/qprintdialog_win.cpp
@@ -52,7 +52,7 @@
#include <private/qprintengine_win_p.h>
#include <private/qprinter_p.h>
-#if defined(Q_CC_MINGW) && !defined(PD_NOCURRENTPAGE)
+#if !defined(PD_NOCURRENTPAGE)
#define PD_NOCURRENTPAGE 0x00800000
#define PD_RESULT_PRINT 1
#define PD_RESULT_APPLY 2
diff --git a/src/gui/embedded/qscreen_qws.cpp b/src/gui/embedded/qscreen_qws.cpp
index 8eb8123599..65a3fb5910 100644
--- a/src/gui/embedded/qscreen_qws.cpp
+++ b/src/gui/embedded/qscreen_qws.cpp
@@ -39,6 +39,7 @@
**
****************************************************************************/
+#include "qplatformdefs.h"
#include "qscreen_qws.h"
#include "qcolormap.h"
@@ -3223,13 +3224,13 @@ QScreen * qt_probe_bus()
return qt_dodriver("unaccel.so",0,0);
}
- DIR * dirptr=opendir("/proc/bus/pci");
+ QT_DIR *dirptr = QT_OPENDIR("/proc/bus/pci");
if(!dirptr)
return qt_dodriver("unaccel.so",0,0);
- DIR * dirptr2;
- dirent * cards;
+ QT_DIR * dirptr2;
+ QT_DIRENT *cards;
- dirent * busses=readdir(dirptr);
+ QT_DIRENT *busses = QT_READDIR(dirptr);
while(busses) {
if(busses->d_name[0]!='.') {
@@ -3237,9 +3238,9 @@ QScreen * qt_probe_bus()
strcpy(buf,"/proc/bus/pci/");
qstrcpy(buf+14,busses->d_name);
int p=strlen(buf);
- dirptr2=opendir(buf);
+ dirptr2 = QT_OPENDIR(buf);
if(dirptr2) {
- cards=readdir(dirptr2);
+ cards = QT_READDIR(dirptr2);
while(cards) {
if(cards->d_name[0]!='.') {
buf[p]='/';
@@ -3248,14 +3249,14 @@ QScreen * qt_probe_bus()
if(ret)
return ret;
}
- cards=readdir(dirptr2);
+ cards = QT_READDIR(dirptr2);
}
- closedir(dirptr2);
+ QT_CLOSEDIR(dirptr2);
}
}
- busses=readdir(dirptr);
+ busses = QT_READDIR(dirptr);
}
- closedir(dirptr);
+ QT_CLOSEDIR(dirptr);
return qt_dodriver("unaccel.so",0,0);
}
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 66707fcba1..9a36d46d51 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -4238,6 +4238,8 @@ static void _q_paintItem(QGraphicsItem *item, QPainter *painter,
widgetItem->paintWindowFrame(painter, option, widget);
if (painterStateProtection)
painter->restore();
+ } else if (widgetItem->autoFillBackground()) {
+ painter->fillRect(option->exposedRect, widgetItem->palette().window());
}
widgetItem->paint(painter, option, widget);
diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp
index 5e01785307..87416b40f8 100644
--- a/src/gui/graphicsview/qgraphicswidget.cpp
+++ b/src/gui/graphicsview/qgraphicswidget.cpp
@@ -967,6 +967,36 @@ void QGraphicsWidget::setPalette(const QPalette &palette)
}
/*!
+ \property QGraphicsWidget::autoFillBackground
+ \brief whether the widget background is filled automatically
+ \since 4.7
+
+ If enabled, this property will cause Qt to fill the background of the
+ widget before invoking the paint() method. The color used is defined by the
+ QPalette::Window color role from the widget's \l{QPalette}{palette}.
+
+ In addition, Windows are always filled with QPalette::Window, unless the
+ WA_OpaquePaintEvent or WA_NoSystemBackground attributes are set.
+
+ By default, this property is false.
+
+ \sa Qt::WA_OpaquePaintEvent, Qt::WA_NoSystemBackground,
+*/
+bool QGraphicsWidget::autoFillBackground() const
+{
+ Q_D(const QGraphicsWidget);
+ return d->autoFillBackground;
+}
+void QGraphicsWidget::setAutoFillBackground(bool enabled)
+{
+ Q_D(QGraphicsWidget);
+ if (d->autoFillBackground != enabled) {
+ d->autoFillBackground = enabled;
+ update();
+ }
+}
+
+/*!
If this widget is currently managed by a layout, this function notifies
the layout that the widget's size hints have changed and the layout
may need to resize and reposition the widget accordingly.
diff --git a/src/gui/graphicsview/qgraphicswidget.h b/src/gui/graphicsview/qgraphicswidget.h
index f1d382bb44..4bea5be155 100644
--- a/src/gui/graphicsview/qgraphicswidget.h
+++ b/src/gui/graphicsview/qgraphicswidget.h
@@ -82,6 +82,7 @@ class Q_GUI_EXPORT QGraphicsWidget : public QGraphicsObject, public QGraphicsLay
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(bool autoFillBackground READ autoFillBackground WRITE setAutoFillBackground)
public:
QGraphicsWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0);
~QGraphicsWidget();
@@ -103,6 +104,9 @@ public:
QPalette palette() const;
void setPalette(const QPalette &palette);
+ bool autoFillBackground() const;
+ void setAutoFillBackground(bool enabled);
+
void resize(const QSizeF &size);
inline void resize(qreal w, qreal h) { resize(QSizeF(w, h)); }
QSizeF size() const;
diff --git a/src/gui/graphicsview/qgraphicswidget_p.h b/src/gui/graphicsview/qgraphicswidget_p.h
index 2c5b3bfedd..3ab8737478 100644
--- a/src/gui/graphicsview/qgraphicswidget_p.h
+++ b/src/gui/graphicsview/qgraphicswidget_p.h
@@ -80,6 +80,7 @@ public:
inSetGeometry(0),
polished(0),
inSetPos(0),
+ autoFillBackground(0),
focusPolicy(Qt::NoFocus),
focusNext(0),
focusPrev(0),
@@ -172,6 +173,7 @@ public:
quint32 inSetGeometry : 1;
quint32 polished: 1;
quint32 inSetPos : 1;
+ quint32 autoFillBackground : 1;
// Focus
Qt::FocusPolicy focusPolicy;
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 4f5efa1c46..6bcf72b64d 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -1835,7 +1835,7 @@ void QImage::setColor(int i, QRgb c)
qAlpha() to access the pixels.
\sa bytesPerLine(), bits(), {QImage#Pixel Manipulation}{Pixel
- Manipulation}
+ Manipulation}, constScanLine()
*/
uchar *QImage::scanLine(int i)
{
@@ -1865,6 +1865,28 @@ const uchar *QImage::scanLine(int i) const
/*!
+ Returns a pointer to the pixel data at the scanline with index \a
+ i. The first scanline is at index 0.
+
+ The scanline data is aligned on a 32-bit boundary.
+
+ Note that QImage uses \l{Implicit Data Sharing} {implicit data
+ sharing}, but this function does \e not perform a deep copy of the
+ shared pixel data, because the returned data is const.
+
+ \sa scanLine(), constBits()
+ \since 4.7
+*/
+const uchar *QImage::constScanLine(int i) const
+{
+ if (!d)
+ return 0;
+
+ Q_ASSERT(i >= 0 && i < height());
+ return d->data + i * d->bytes_per_line;
+}
+
+/*!
Returns a pointer to the first pixel data. This is equivalent to
scanLine(0).
@@ -1873,7 +1895,7 @@ const uchar *QImage::scanLine(int i) const
data, thus ensuring that this QImage is the only one using the
current return value.
- \sa scanLine(), byteCount()
+ \sa scanLine(), byteCount(), constBits()
*/
uchar *QImage::bits()
{
@@ -1901,6 +1923,20 @@ const uchar *QImage::bits() const
}
+/*!
+ Returns a pointer to the first pixel data.
+
+ Note that QImage uses \l{Implicit Data Sharing} {implicit data
+ sharing}, but this function does \e not perform a deep copy of the
+ shared pixel data, because the returned data is const.
+
+ \sa bits(), constScanLine()
+ \since 4.7
+*/
+const uchar *QImage::constBits() const
+{
+ return d ? d->data : 0;
+}
/*!
\fn void QImage::reset()
diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h
index ac973a1de9..dd13782304 100644
--- a/src/gui/image/qimage.h
+++ b/src/gui/image/qimage.h
@@ -182,6 +182,7 @@ public:
uchar *bits();
const uchar *bits() const;
+ const uchar *constBits() const;
#ifdef QT_DEPRECATED
QT_DEPRECATED int numBytes() const;
#endif
@@ -189,6 +190,7 @@ public:
uchar *scanLine(int);
const uchar *scanLine(int) const;
+ const uchar *constScanLine(int) const;
int bytesPerLine() const;
bool valid(int x, int y) const;
diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp
index fb70e36e76..3220a67332 100644
--- a/src/gui/image/qpicture.cpp
+++ b/src/gui/image/qpicture.cpp
@@ -440,36 +440,6 @@ bool QPicture::play(QPainter *painter)
return true; // no end-command
}
-
-//
-// QFakeDevice is used to create fonts with a custom DPI
-//
-class QFakeDevice : public QPaintDevice
-{
-public:
- QFakeDevice() { dpi_x = qt_defaultDpiX(); dpi_y = qt_defaultDpiY(); }
- void setDpiX(int dpi) { dpi_x = dpi; }
- void setDpiY(int dpi) { dpi_y = dpi; }
- QPaintEngine *paintEngine() const { return 0; }
- int metric(PaintDeviceMetric m) const
- {
- switch(m) {
- case PdmPhysicalDpiX:
- case PdmDpiX:
- return dpi_x;
- case PdmPhysicalDpiY:
- case PdmDpiY:
- return dpi_y;
- default:
- return QPaintDevice::metric(m);
- }
- }
-
-private:
- int dpi_x;
- int dpi_y;
-};
-
/*!
\internal
Iterates over the internal picture data and draws the picture using
@@ -679,30 +649,29 @@ bool QPicture::exec(QPainter *painter, QDataStream &s, int nrecords)
if (d->formatMajor >= 9) {
s >> dbl;
- QFont fnt(font);
- if (dbl != 1.0) {
- QFakeDevice fake;
- fake.setDpiX(qRound(dbl*qt_defaultDpiX()));
- fake.setDpiY(qRound(dbl*qt_defaultDpiY()));
- fnt = QFont(font, &fake);
- }
+ QFont fnt(font, painter->device());
+
+ qreal scale = painter->device()->logicalDpiY() / (dbl*qt_defaultDpiY());
+ painter->save();
+ painter->scale(1/scale, 1/scale);
qreal justificationWidth;
s >> justificationWidth;
int flags = Qt::TextSingleLine | Qt::TextDontClip | Qt::TextForceLeftToRight;
- QSizeF size(1, 1);
+ QSizeF size(scale, scale);
if (justificationWidth > 0) {
- size.setWidth(justificationWidth);
+ size.setWidth(justificationWidth*scale);
flags |= Qt::TextJustificationForced;
flags |= Qt::AlignJustify;
}
QFontMetrics fm(fnt);
- QPointF pt(p.x(), p.y() - fm.ascent());
+ QPointF pt(p.x()*scale, p.y()*scale - fm.ascent());
qt_format_text(fnt, QRectF(pt, size), flags, /*opt*/0,
str, /*brect=*/0, /*tabstops=*/0, /*...*/0, /*tabarraylen=*/0, painter);
+ painter->restore();
} else {
qt_format_text(font, QRectF(p, QSizeF(1, 1)), Qt::TextSingleLine | Qt::TextDontClip, /*opt*/0,
str, /*brect=*/0, /*tabstops=*/0, /*...*/0, /*tabarraylen=*/0, painter);
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index d1e5c40540..7cafbd0021 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -1078,6 +1078,9 @@ QPixmap QPixmap::grabWidget(QWidget * widget, const QRect &rect)
if (widget->testAttribute(Qt::WA_PendingResizeEvent) || !widget->testAttribute(Qt::WA_WState_Created))
sendResizeEvents(widget);
+ widget->d_func()->prepareToRender(QRegion(),
+ QWidget::DrawWindowBackground | QWidget::DrawChildren | QWidget::IgnoreMask);
+
QRect r(rect);
if (r.width() < 0)
r.setWidth(widget->width() - rect.x());
@@ -1088,8 +1091,8 @@ QPixmap QPixmap::grabWidget(QWidget * widget, const QRect &rect)
return QPixmap();
QPixmap res(r.size());
- widget->render(&res, QPoint(), r,
- QWidget::DrawWindowBackground | QWidget::DrawChildren | QWidget::IgnoreMask);
+ widget->d_func()->render(&res, QPoint(), r, QWidget::DrawWindowBackground
+ | QWidget::DrawChildren | QWidget::IgnoreMask, true);
return res;
}
@@ -1370,10 +1373,27 @@ void QPixmap::deref()
*/
/*!
- \fn bool QPixmap::convertFromImage(const QImage &image, Qt::ImageConversionFlags flags)
+ Replaces this pixmap's data with the given \a image using the
+ specified \a flags to control the conversion. The \a flags
+ argument is a bitwise-OR of the \l{Qt::ImageConversionFlags}.
+ Passing 0 for \a flags sets all the default options. Returns true
+ if the result is that this pixmap is not null.
- Use the static fromImage() function instead.
+ Note: this function was part of Qt 3 support in Qt 4.6 and earlier.
+ It has been promoted to official API status in 4.7 to support updating
+ the pixmap's image without creating a new QPixmap as fromImage() would.
+
+ \sa fromImage()
+ \since 4.7
*/
+bool QPixmap::convertFromImage(const QImage &image, Qt::ImageConversionFlags flags)
+{
+ if (image.isNull() || !data)
+ *this = QPixmap::fromImage(image, flags);
+ else
+ data->fromImage(image, flags);
+ return !isNull();
+}
/*!
\fn QPixmap QPixmap::xForm(const QMatrix &matrix) const
diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h
index 46363f05a1..180af3be1b 100644
--- a/src/gui/image/qpixmap.h
+++ b/src/gui/image/qpixmap.h
@@ -141,6 +141,8 @@ public:
bool save(const QString& fileName, const char* format = 0, int quality = -1) const;
bool save(QIODevice* device, const char* format = 0, int quality = -1) const;
+ bool convertFromImage(const QImage &img, Qt::ImageConversionFlags flags = Qt::AutoColor);
+
#if defined(Q_WS_WIN)
enum HBitmapFormat {
NoAlpha,
@@ -224,8 +226,6 @@ public:
QT3_SUPPORT QPixmap &operator=(const QImage &);
inline QT3_SUPPORT QImage convertToImage() const { return toImage(); }
QT3_SUPPORT bool convertFromImage(const QImage &, ColorMode mode);
- QT3_SUPPORT bool convertFromImage(const QImage &img, Qt::ImageConversionFlags flags = Qt::AutoColor)
- { (*this) = fromImage(img, flags); return !isNull(); }
inline QT3_SUPPORT operator QImage() const { return toImage(); }
inline QT3_SUPPORT QPixmap xForm(const QMatrix &matrix) const { return transformed(QTransform(matrix)); }
inline QT3_SUPPORT bool selfMask() const { return false; }
diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp
index e1e8a0db5e..b9763761ba 100644
--- a/src/gui/image/qpixmap_x11.cpp
+++ b/src/gui/image/qpixmap_x11.cpp
@@ -1142,7 +1142,7 @@ void QX11PixmapData::fromImage(const QImage &img,
}
}
-void QX11PixmapData::bitmapFromImage(const QImage &image)
+Qt::HANDLE QX11PixmapData::createBitmapFromImage(const QImage &image)
{
QImage img = image.convertToFormat(QImage::Format_MonoLSB);
const QRgb c0 = QColor(Qt::black).rgb();
@@ -1155,10 +1155,8 @@ void QX11PixmapData::bitmapFromImage(const QImage &image)
char *bits;
uchar *tmp_bits;
- w = img.width();
- h = img.height();
- d = 1;
- is_null = (w <= 0 || h <= 0);
+ int w = img.width();
+ int h = img.height();
int bpl = (w + 7) / 8;
int ibpl = img.bytesPerLine();
if (bpl != ibpl) {
@@ -1177,18 +1175,26 @@ void QX11PixmapData::bitmapFromImage(const QImage &image)
bits = (char *)img.bits();
tmp_bits = 0;
}
- hd = (Qt::HANDLE)XCreateBitmapFromData(xinfo.display(),
- RootWindow(xinfo.display(), xinfo.screen()),
+ Qt::HANDLE hd = (Qt::HANDLE)XCreateBitmapFromData(X11->display,
+ QX11Info::appRootWindow(),
bits, w, h);
+ if (tmp_bits) // Avoid purify complaint
+ delete [] tmp_bits;
+ return hd;
+}
+void QX11PixmapData::bitmapFromImage(const QImage &image)
+{
+ w = image.width();
+ h = image.height();
+ d = 1;
+ is_null = (w <= 0 || h <= 0);
+ hd = createBitmapFromImage(image);
#ifndef QT_NO_XRENDER
if (X11->use_xrender)
picture = XRenderCreatePicture(X11->display, hd,
XRenderFindStandardFormat(X11->display, PictStandardA1), 0, 0);
#endif // QT_NO_XRENDER
-
- if (tmp_bits) // Avoid purify complaint
- delete [] tmp_bits;
}
void QX11PixmapData::fill(const QColor &fillColor)
diff --git a/src/gui/image/qpixmap_x11_p.h b/src/gui/image/qpixmap_x11_p.h
index 20fb65470e..0c0a9bdd06 100644
--- a/src/gui/image/qpixmap_x11_p.h
+++ b/src/gui/image/qpixmap_x11_p.h
@@ -92,6 +92,8 @@ public:
Qt::HANDLE handle() const { return hd; }
Qt::HANDLE x11ConvertToDefaultDepth();
+ static Qt::HANDLE createBitmapFromImage(const QImage &image);
+
protected:
int metric(QPaintDevice::PaintDeviceMetric metric) const;
diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index d5406cb847..dd31834cae 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -50,8 +50,13 @@
#include <qvariant.h>
#include <qvector.h>
+#ifdef QT_USE_BUNDLED_LIBPNG
+#include <../../3rdparty/libpng/png.h>
+#include <../../3rdparty/libpng/pngconf.h>
+#else
#include <png.h>
#include <pngconf.h>
+#endif
#ifdef Q_OS_WINCE
#define CALLBACK_CALL_TYPE __cdecl
@@ -162,11 +167,16 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, float scre
png_uint_32 height;
int bit_depth;
int color_type;
+ png_bytep trans_alpha = 0;
+ png_color_16p trans_color_p = 0;
+ int num_trans;
+ png_colorp palette = 0;
+ int num_palette;
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
if (color_type == PNG_COLOR_TYPE_GRAY) {
// Black & White or 8-bit grayscale
- if (bit_depth == 1 && info_ptr->channels == 1) {
+ if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) {
png_set_invert_mono(png_ptr);
png_read_update_info(png_ptr, info_ptr);
if (image.size() != QSize(width, height) || image.format() != QImage::Format_Mono) {
@@ -207,20 +217,16 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, float scre
int c = i*255/(ncols-1);
image.setColor(i, qRgba(c,c,c,0xff));
}
- if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
-#if PNG_LIBPNG_VER_MAJOR < 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR < 4)
- const int g = info_ptr->trans_values.gray;
-#else
- const int g = info_ptr->trans_color.gray;
-#endif
+ if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_color_p) {
+ const int g = trans_color_p->gray;
if (g < ncols) {
image.setColor(g, 0);
}
}
}
} else if (color_type == PNG_COLOR_TYPE_PALETTE
- && png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)
- && info_ptr->num_palette <= 256)
+ && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)
+ && num_palette <= 256)
{
// 1-bit and 8-bit color
if (bit_depth != 1)
@@ -233,29 +239,26 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, float scre
if (image.isNull())
return;
}
- image.setColorCount(info_ptr->num_palette);
+ png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
+ image.setColorCount(num_palette);
int i = 0;
- if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
- while (i < info_ptr->num_trans) {
+ if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_alpha) {
+ while (i < num_trans) {
image.setColor(i, qRgba(
- info_ptr->palette[i].red,
- info_ptr->palette[i].green,
- info_ptr->palette[i].blue,
-#if PNG_LIBPNG_VER_MAJOR < 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR < 4)
- info_ptr->trans[i]
-#else
- info_ptr->trans_alpha[i]
-#endif
+ palette[i].red,
+ palette[i].green,
+ palette[i].blue,
+ trans_alpha[i]
)
);
i++;
}
}
- while (i < info_ptr->num_palette) {
+ while (i < num_palette) {
image.setColor(i, qRgba(
- info_ptr->palette[i].red,
- info_ptr->palette[i].green,
- info_ptr->palette[i].blue,
+ palette[i].red,
+ palette[i].green,
+ palette[i].blue,
0xff
)
);
@@ -531,33 +534,36 @@ QImage::Format QPngHandlerPrivate::readImageFormat()
QImage::Format format = QImage::Format_Invalid;
png_uint_32 width, height;
int bit_depth, color_type;
- if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY) {
+ png_colorp palette;
+ int num_palette;
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
+ if (color_type == PNG_COLOR_TYPE_GRAY) {
// Black & White or 8-bit grayscale
- if (info_ptr->bit_depth == 1 && info_ptr->channels == 1) {
+ if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) {
format = QImage::Format_Mono;
- } else if (info_ptr->bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
+ } else if (bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
format = QImage::Format_ARGB32;
} else {
format = QImage::Format_Indexed8;
}
- } else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE
- && png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)
- && info_ptr->num_palette <= 256)
+ } else if (color_type == PNG_COLOR_TYPE_PALETTE
+ && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)
+ && num_palette <= 256)
{
// 1-bit and 8-bit color
- if (info_ptr->bit_depth != 1)
+ if (bit_depth != 1)
png_set_packing(png_ptr);
png_read_update_info(png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
format = bit_depth == 1 ? QImage::Format_Mono : QImage::Format_Indexed8;
} else {
// 32-bit
- if (info_ptr->bit_depth == 16)
+ if (bit_depth == 16)
png_set_strip_16(png_ptr);
format = QImage::Format_ARGB32;
// Only add filler if no alpha, or we can get 5 channel data.
- if (!(info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
+ if (!(color_type & PNG_COLOR_MASK_ALPHA)
&& !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
// We want 4 bytes, but it isn't an alpha channel
format = QImage::Format_RGB32;
@@ -648,7 +654,7 @@ static void set_text(const QImage &image, png_structp png_ptr, png_infop info_pt
text_ptr[i].text = qstrdup(value.constData());
text_ptr[i].text_length = 0;
text_ptr[i].itxt_length = value.size();
- text_ptr[i].lang = "UTF-8";
+ text_ptr[i].lang = const_cast<char*>("UTF-8");
text_ptr[i].lang_key = qstrdup(it.key().toUtf8().constData());
#endif
++i;
@@ -735,64 +741,51 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image_in,
png_set_compression_level(png_ptr, quality);
}
- if (gamma != 0.0) {
- png_set_gAMA(png_ptr, info_ptr, 1.0/gamma);
- }
-
png_set_write_fn(png_ptr, (void*)this, qpiw_write_fn, qpiw_flush_fn);
- info_ptr->channels =
- (image.depth() == 32)
- ? (image.format() == QImage::Format_RGB32 ? 3 : 4)
- : 1;
-
png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(),
image.depth() == 1 ? 1 : 8 /* per channel */,
image.depth() == 32
? image.format() == QImage::Format_RGB32
? PNG_COLOR_TYPE_RGB
: PNG_COLOR_TYPE_RGB_ALPHA
- : PNG_COLOR_TYPE_PALETTE, 0, 0, 0);
+ : PNG_COLOR_TYPE_PALETTE, 0, 0, 0); // also sets #channels
+ if (gamma != 0.0) {
+ png_set_gAMA(png_ptr, info_ptr, 1.0/gamma);
+ }
- //png_set_sBIT(png_ptr, info_ptr, 8);
- info_ptr->sig_bit.red = 8;
- info_ptr->sig_bit.green = 8;
- info_ptr->sig_bit.blue = 8;
+ png_color_8 sig_bit;
+ sig_bit.red = 8;
+ sig_bit.green = 8;
+ sig_bit.blue = 8;
+ sig_bit.alpha = image.hasAlphaChannel() ? 8 : 0;
+ png_set_sBIT(png_ptr, info_ptr, &sig_bit);
if (image.format() == QImage::Format_MonoLSB)
png_set_packswap(png_ptr);
- png_colorp palette = 0;
- png_bytep copy_trans = 0;
if (image.colorCount()) {
// Paletted
- int num_palette = image.colorCount();
- palette = new png_color[num_palette];
- png_set_PLTE(png_ptr, info_ptr, palette, num_palette);
- int* trans = new int[num_palette];
+ int num_palette = qMin(256, image.colorCount());
+ png_color palette[256];
+ png_byte trans[256];
int num_trans = 0;
for (int i=0; i<num_palette; i++) {
- QRgb rgb=image.color(i);
- info_ptr->palette[i].red = qRed(rgb);
- info_ptr->palette[i].green = qGreen(rgb);
- info_ptr->palette[i].blue = qBlue(rgb);
- trans[i] = rgb >> 24;
+ QRgb rgba=image.color(i);
+ palette[i].red = qRed(rgba);
+ palette[i].green = qGreen(rgba);
+ palette[i].blue = qBlue(rgba);
+ trans[i] = qAlpha(rgba);
if (trans[i] < 255) {
num_trans = i+1;
}
}
+ png_set_PLTE(png_ptr, info_ptr, palette, num_palette);
+
if (num_trans) {
- copy_trans = new png_byte[num_trans];
- for (int i=0; i<num_trans; i++)
- copy_trans[i] = trans[i];
- png_set_tRNS(png_ptr, info_ptr, copy_trans, num_trans, 0);
+ png_set_tRNS(png_ptr, info_ptr, trans, num_trans, 0);
}
- delete [] trans;
- }
-
- if (image.format() != QImage::Format_RGB32) {
- info_ptr->sig_bit.alpha = 8;
}
// Swap ARGB to RGBA (normal PNG format) before saving on
@@ -868,11 +861,6 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image_in,
png_write_end(png_ptr, info_ptr);
frames_written++;
- if (palette)
- delete [] palette;
- if (copy_trans)
- delete [] copy_trans;
-
png_destroy_write_struct(&png_ptr, &info_ptr);
return true;
@@ -958,7 +946,8 @@ QVariant QPngHandler::option(ImageOption option) const
else if (option == Description)
return d->description;
else if (option == Size)
- return QSize(d->info_ptr->width, d->info_ptr->height);
+ return QSize(png_get_image_width(d->png_ptr, d->info_ptr),
+ png_get_image_height(d->png_ptr, d->info_ptr));
else if (option == ImageFormat)
return d->readImageFormat();
return 0;
diff --git a/src/gui/inputmethod/qwininputcontext_p.h b/src/gui/inputmethod/qwininputcontext_p.h
index 08cc3d2420..d5bedf49b7 100644
--- a/src/gui/inputmethod/qwininputcontext_p.h
+++ b/src/gui/inputmethod/qwininputcontext_p.h
@@ -56,7 +56,7 @@
#include "QtGui/qinputcontext.h"
#include "QtCore/qt_windows.h"
-#if defined(Q_CC_MINGW) && !defined(IMR_RECONVERTSTRING)
+#if !defined(IMR_RECONVERTSTRING)
typedef struct tagRECONVERTSTRING {
DWORD dwSize;
DWORD dwVersion;
diff --git a/src/gui/itemviews/qdirmodel.cpp b/src/gui/itemviews/qdirmodel.cpp
index ea608c1b3c..378a23878c 100644
--- a/src/gui/itemviews/qdirmodel.cpp
+++ b/src/gui/itemviews/qdirmodel.cpp
@@ -185,12 +185,12 @@ void QDirModelPrivate::invalidate()
/*!
\class QDirModel
-
+ \obsolete
\brief The QDirModel class provides a data model for the local filesystem.
\ingroup model-view
- \note The usage of QDirModel is not recommended anymore. The
+ The usage of QDirModel is not recommended anymore. The
QFileSystemModel class is a more performant alternative.
This class provides access to the local filesystem, providing functions
diff --git a/src/gui/itemviews/qfileiconprovider.cpp b/src/gui/itemviews/qfileiconprovider.cpp
index fcc61e55bf..f321ab305e 100644
--- a/src/gui/itemviews/qfileiconprovider.cpp
+++ b/src/gui/itemviews/qfileiconprovider.cpp
@@ -73,7 +73,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QFileIconProvider
- \brief The QFileIconProvider class provides file icons for the QDirModel class.
+ \brief The QFileIconProvider class provides file icons for the QDirModel and the QFileSystemModel classes.
*/
/*!
diff --git a/src/gui/itemviews/qheaderview.cpp b/src/gui/itemviews/qheaderview.cpp
index 8a456e6b9c..1c26e510e8 100644
--- a/src/gui/itemviews/qheaderview.cpp
+++ b/src/gui/itemviews/qheaderview.cpp
@@ -1853,11 +1853,9 @@ void QHeaderViewPrivate::_q_layoutChanged()
persistentHiddenSections.clear();
return;
}
+
+ QBitArray oldSectionHidden = sectionHidden;
bool sectionCountChanged = false;
- for (int i = 0; i < sectionHidden.count(); ++i) {
- if (sectionHidden.testBit(i))
- q->setSectionHidden(logicalIndex(i), false);
- }
for (int i = 0; i < persistentHiddenSections.count(); ++i) {
QModelIndex index = persistentHiddenSections.at(i);
@@ -1866,6 +1864,7 @@ void QHeaderViewPrivate::_q_layoutChanged()
? index.column()
: index.row());
q->setSectionHidden(logical, true);
+ oldSectionHidden.setBit(logical, false);
} else if (!sectionCountChanged && (modelSectionCount() != sectionCount)) {
sectionCountChanged = true;
break;
@@ -1873,6 +1872,11 @@ void QHeaderViewPrivate::_q_layoutChanged()
}
persistentHiddenSections.clear();
+ for (int i = 0; i < oldSectionHidden.count(); ++i) {
+ if (oldSectionHidden.testBit(i))
+ q->setSectionHidden(logicalIndex(i), false);
+ }
+
// the number of sections changed; we need to reread the state of the model
if (sectionCountChanged)
q->initializeSections();
@@ -2300,7 +2304,7 @@ void QHeaderView::mouseReleaseEvent(QMouseEvent *e)
int section = logicalIndexAt(pos);
if (section != -1 && section == d->pressed) {
d->flipSortIndicator(section);
- emit sectionClicked(logicalIndexAt(pos));
+ emit sectionClicked(section);
}
if (d->pressed != -1)
updateSection(d->pressed);
diff --git a/src/gui/itemviews/qsortfilterproxymodel.cpp b/src/gui/itemviews/qsortfilterproxymodel.cpp
index 41c984e37f..e73013cc9f 100644
--- a/src/gui/itemviews/qsortfilterproxymodel.cpp
+++ b/src/gui/itemviews/qsortfilterproxymodel.cpp
@@ -270,6 +270,11 @@ void QSortFilterProxyModelPrivate::clear_mapping()
qDeleteAll(source_index_mapping);
source_index_mapping.clear();
+ if (dynamic_sortfilter && update_source_sort_column()) {
+ //update_source_sort_column might have created wrong mapping so we have to clear it again
+ qDeleteAll(source_index_mapping);
+ source_index_mapping.clear();
+ }
// update the persistent indexes
update_persistent_indexes(source_indexes);
@@ -1208,11 +1213,6 @@ void QSortFilterProxyModelPrivate::_q_sourceLayoutAboutToBeChanged()
void QSortFilterProxyModelPrivate::_q_sourceLayoutChanged()
{
Q_Q(QSortFilterProxyModel);
- if (saved_persistent_indexes.isEmpty()) {
- clear_mapping();
- emit q->layoutChanged();
- return;
- }
qDeleteAll(source_index_mapping);
source_index_mapping.clear();
@@ -1220,7 +1220,11 @@ void QSortFilterProxyModelPrivate::_q_sourceLayoutChanged()
update_persistent_indexes(saved_persistent_indexes);
saved_persistent_indexes.clear();
- update_source_sort_column();
+ if (dynamic_sortfilter && update_source_sort_column()) {
+ //update_source_sort_column might have created wrong mapping so we have to clear it again
+ qDeleteAll(source_index_mapping);
+ source_index_mapping.clear();
+ }
emit q->layoutChanged();
}
@@ -1481,7 +1485,6 @@ QSortFilterProxyModel::QSortFilterProxyModel(QObject *parent)
d->filter_column = 0;
d->filter_role = Qt::DisplayRole;
d->dynamic_sortfilter = false;
- connect(this, SIGNAL(modelReset()), this, SLOT(invalidate()));
}
/*!
diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri
index 0993b86c2d..6fd45adf44 100644
--- a/src/gui/kernel/kernel.pri
+++ b/src/gui/kernel/kernel.pri
@@ -206,6 +206,7 @@ embedded {
OBJECTIVE_HEADERS += \
qcocoawindow_mac_p.h \
+ qcocoapanel_mac_p.h \
qcocoawindowdelegate_mac_p.h \
qcocoaview_mac_p.h \
qcocoaapplication_mac_p.h \
diff --git a/src/gui/kernel/qaction.h b/src/gui/kernel/qaction.h
index 434136796b..538b04f77b 100644
--- a/src/gui/kernel/qaction.h
+++ b/src/gui/kernel/qaction.h
@@ -246,6 +246,9 @@ private:
friend class QMenuBar;
friend class QShortcutMap;
friend class QToolButton;
+#ifdef Q_WS_MAC
+ friend void qt_mac_clear_status_text(QAction *action);
+#endif
};
QT_BEGIN_INCLUDE_NAMESPACE
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp
index 4fe39006d4..bb6aca9b26 100644
--- a/src/gui/kernel/qapplication.cpp
+++ b/src/gui/kernel/qapplication.cpp
@@ -182,6 +182,15 @@ QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, QApplication::T
gestureManager = 0;
gestureWidget = 0;
+#if defined(Q_WS_X11) || defined(Q_WS_WIN)
+ move_cursor = 0;
+ copy_cursor = 0;
+ link_cursor = 0;
+#endif
+#if defined(Q_WS_WIN)
+ ignore_cursor = 0;
+#endif
+
if (!self)
self = this;
}
@@ -925,7 +934,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.
@@ -1032,6 +1041,15 @@ QApplication::~QApplication()
qt_clipboard = 0;
#endif
+#if defined(Q_WS_X11) || defined(Q_WS_WIN)
+ delete d->move_cursor; d->move_cursor = 0;
+ delete d->copy_cursor; d->copy_cursor = 0;
+ delete d->link_cursor; d->link_cursor = 0;
+#endif
+#if defined(Q_WS_WIN)
+ delete d->ignore_cursor; d->ignore_cursor = 0;
+#endif
+
delete QWidgetPrivate::mapper;
QWidgetPrivate::mapper = 0;
@@ -5689,6 +5707,228 @@ QGestureManager* QGestureManager::instance()
return qAppPriv->gestureManager;
}
+// These pixmaps approximate the images in the Windows User Interface Guidelines.
+
+// XPM
+
+static const char * const move_xpm[] = {
+"11 20 3 1",
+". c None",
+#if defined(Q_WS_WIN)
+"a c #000000",
+"X c #FFFFFF", // Windows cursor is traditionally white
+#else
+"a c #FFFFFF",
+"X c #000000", // X11 cursor is traditionally black
+#endif
+"aa.........",
+"aXa........",
+"aXXa.......",
+"aXXXa......",
+"aXXXXa.....",
+"aXXXXXa....",
+"aXXXXXXa...",
+"aXXXXXXXa..",
+"aXXXXXXXXa.",
+"aXXXXXXXXXa",
+"aXXXXXXaaaa",
+"aXXXaXXa...",
+"aXXaaXXa...",
+"aXa..aXXa..",
+"aa...aXXa..",
+"a.....aXXa.",
+"......aXXa.",
+".......aXXa",
+".......aXXa",
+"........aa."};
+
+#ifdef Q_WS_WIN
+/* XPM */
+static const char * const ignore_xpm[] = {
+"24 30 3 1",
+". c None",
+"a c #000000",
+"X c #FFFFFF",
+"aa......................",
+"aXa.....................",
+"aXXa....................",
+"aXXXa...................",
+"aXXXXa..................",
+"aXXXXXa.................",
+"aXXXXXXa................",
+"aXXXXXXXa...............",
+"aXXXXXXXXa..............",
+"aXXXXXXXXXa.............",
+"aXXXXXXaaaa.............",
+"aXXXaXXa................",
+"aXXaaXXa................",
+"aXa..aXXa...............",
+"aa...aXXa...............",
+"a.....aXXa..............",
+"......aXXa.....XXXX.....",
+".......aXXa..XXaaaaXX...",
+".......aXXa.XaaaaaaaaX..",
+"........aa.XaaaXXXXaaaX.",
+"...........XaaaaX..XaaX.",
+"..........XaaXaaaX..XaaX",
+"..........XaaXXaaaX.XaaX",
+"..........XaaX.XaaaXXaaX",
+"..........XaaX..XaaaXaaX",
+"...........XaaX..XaaaaX.",
+"...........XaaaXXXXaaaX.",
+"............XaaaaaaaaX..",
+".............XXaaaaXX...",
+"...............XXXX....."};
+#endif
+
+/* XPM */
+static const char * const copy_xpm[] = {
+"24 30 3 1",
+". c None",
+"a c #000000",
+"X c #FFFFFF",
+#if defined(Q_WS_WIN) // Windows cursor is traditionally white
+"aa......................",
+"aXa.....................",
+"aXXa....................",
+"aXXXa...................",
+"aXXXXa..................",
+"aXXXXXa.................",
+"aXXXXXXa................",
+"aXXXXXXXa...............",
+"aXXXXXXXXa..............",
+"aXXXXXXXXXa.............",
+"aXXXXXXaaaa.............",
+"aXXXaXXa................",
+"aXXaaXXa................",
+"aXa..aXXa...............",
+"aa...aXXa...............",
+"a.....aXXa..............",
+"......aXXa..............",
+".......aXXa.............",
+".......aXXa.............",
+"........aa...aaaaaaaaaaa",
+#else
+"XX......................",
+"XaX.....................",
+"XaaX....................",
+"XaaaX...................",
+"XaaaaX..................",
+"XaaaaaX.................",
+"XaaaaaaX................",
+"XaaaaaaaX...............",
+"XaaaaaaaaX..............",
+"XaaaaaaaaaX.............",
+"XaaaaaaXXXX.............",
+"XaaaXaaX................",
+"XaaXXaaX................",
+"XaX..XaaX...............",
+"XX...XaaX...............",
+"X.....XaaX..............",
+"......XaaX..............",
+".......XaaX.............",
+".......XaaX.............",
+"........XX...aaaaaaaaaaa",
+#endif
+".............aXXXXXXXXXa",
+".............aXXXXXXXXXa",
+".............aXXXXaXXXXa",
+".............aXXXXaXXXXa",
+".............aXXaaaaaXXa",
+".............aXXXXaXXXXa",
+".............aXXXXaXXXXa",
+".............aXXXXXXXXXa",
+".............aXXXXXXXXXa",
+".............aaaaaaaaaaa"};
+
+/* XPM */
+static const char * const link_xpm[] = {
+"24 30 3 1",
+". c None",
+"a c #000000",
+"X c #FFFFFF",
+#if defined(Q_WS_WIN) // Windows cursor is traditionally white
+"aa......................",
+"aXa.....................",
+"aXXa....................",
+"aXXXa...................",
+"aXXXXa..................",
+"aXXXXXa.................",
+"aXXXXXXa................",
+"aXXXXXXXa...............",
+"aXXXXXXXXa..............",
+"aXXXXXXXXXa.............",
+"aXXXXXXaaaa.............",
+"aXXXaXXa................",
+"aXXaaXXa................",
+"aXa..aXXa...............",
+"aa...aXXa...............",
+"a.....aXXa..............",
+"......aXXa..............",
+".......aXXa.............",
+".......aXXa.............",
+"........aa...aaaaaaaaaaa",
+#else
+"XX......................",
+"XaX.....................",
+"XaaX....................",
+"XaaaX...................",
+"XaaaaX..................",
+"XaaaaaX.................",
+"XaaaaaaX................",
+"XaaaaaaaX...............",
+"XaaaaaaaaX..............",
+"XaaaaaaaaaX.............",
+"XaaaaaaXXXX.............",
+"XaaaXaaX................",
+"XaaXXaaX................",
+"XaX..XaaX...............",
+"XX...XaaX...............",
+"X.....XaaX..............",
+"......XaaX..............",
+".......XaaX.............",
+".......XaaX.............",
+"........XX...aaaaaaaaaaa",
+#endif
+".............aXXXXXXXXXa",
+".............aXXXaaaaXXa",
+".............aXXXXaaaXXa",
+".............aXXXaaaaXXa",
+".............aXXaaaXaXXa",
+".............aXXaaXXXXXa",
+".............aXXaXXXXXXa",
+".............aXXXaXXXXXa",
+".............aXXXXXXXXXa",
+".............aaaaaaaaaaa"};
+
+QPixmap QApplicationPrivate::getPixmapCursor(Qt::CursorShape cshape)
+{
+ if (!move_cursor) {
+ move_cursor = new QPixmap((const char **)move_xpm);
+ copy_cursor = new QPixmap((const char **)copy_xpm);
+ link_cursor = new QPixmap((const char **)link_xpm);
+#ifdef Q_WS_WIN
+ ignore_cursor = new QPixmap((const char **)ignore_xpm);
+#endif
+ }
+
+ switch (cshape) {
+ case Qt::DragMoveCursor:
+ return *move_cursor;
+ case Qt::DragCopyCursor:
+ return *copy_cursor;
+ case Qt::DragLinkCursor:
+ return *link_cursor;
+#ifdef Q_WS_WIN
+ case Qt::ForbiddenCursor:
+ return *ignore_cursor;
+#endif
+ default:
+ break;
+ }
+ return QPixmap();
+}
+
QT_END_NAMESPACE
#include "moc_qapplication.cpp"
diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm
index e8b821af67..3fba83388a 100644
--- a/src/gui/kernel/qapplication_mac.mm
+++ b/src/gui/kernel/qapplication_mac.mm
@@ -1258,10 +1258,6 @@ void qt_init(QApplicationPrivate *priv, int)
[cocoaApp setMenu:[qtMenuLoader menu]];
[newDelegate setMenuLoader:qtMenuLoader];
[qtMenuLoader release];
-
- NSAppleEventManager *eventManager = [NSAppleEventManager sharedAppleEventManager];
- [eventManager setEventHandler:newDelegate andSelector:@selector(getUrl:withReplyEvent:)
- forEventClass:kInternetEventClass andEventID:kAEGetURL];
}
#endif
// Register for Carbon tablet proximity events on the event monitor target.
@@ -1361,12 +1357,39 @@ void QApplication::setMainWidget(QWidget *mainWidget)
/*****************************************************************************
QApplication cursor stack
*****************************************************************************/
+#ifdef QT_MAC_USE_COCOA
+void QApplicationPrivate::disableUsageOfCursorRects(bool disable)
+{
+ // In Cocoa there are two competing ways of setting the cursor; either
+ // by using cursor rects (see qcocoaview_mac.mm), or by pushing/popping
+ // the cursor manually. When we use override cursors, it makes most sense
+ // to use the latter. But then we need to tell cocoa to stop using the
+ // first approach so it doesn't change the cursor back when hovering over
+ // a cursor rect:
+ QWidgetList topLevels = qApp->topLevelWidgets();
+ for (int i=0; i<topLevels.size(); ++i) {
+ if (NSWindow *window = qt_mac_window_for(topLevels.at(i)))
+ disable ? [window disableCursorRects] : [window enableCursorRects];
+ }
+}
+
+void QApplicationPrivate::updateOverrideCursor()
+{
+ // Sometimes Cocoa forgets that we have set a Cursor
+ // manually. In those cases, remind it again:
+ if (QCursor *override = qApp->overrideCursor())
+ [static_cast<NSCursor *>(qt_mac_nsCursorForQCursor(*override)) set];
+}
+#endif
+
void QApplication::setOverrideCursor(const QCursor &cursor)
{
qApp->d_func()->cursor_list.prepend(cursor);
#ifdef QT_MAC_USE_COCOA
QMacCocoaAutoReleasePool pool;
+ if (qApp->d_func()->cursor_list.size() == 1)
+ qApp->d_func()->disableUsageOfCursorRects(true);
[static_cast<NSCursor *>(qt_mac_nsCursorForQCursor(cursor)) push];
#else
if (qApp && qApp->activeWindow())
@@ -1383,6 +1406,8 @@ void QApplication::restoreOverrideCursor()
#ifdef QT_MAC_USE_COCOA
QMacCocoaAutoReleasePool pool;
[NSCursor pop];
+ if (qApp->d_func()->cursor_list.isEmpty())
+ qApp->d_func()->disableUsageOfCursorRects(false);
#else
if (qApp && qApp->activeWindow()) {
const QCursor def(Qt::ArrowCursor);
@@ -2455,6 +2480,28 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event
#endif
}
+#ifdef QT_MAC_USE_COCOA
+void QApplicationPrivate::qt_initAfterNSAppStarted()
+{
+ setupAppleEvents();
+ updateOverrideCursor();
+}
+
+void QApplicationPrivate::setupAppleEvents()
+{
+ // This function is called from the event dispatcher when NSApplication has
+ // 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.
+ QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) *newDelegate = [QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate];
+ NSAppleEventManager *eventManager = [NSAppleEventManager sharedAppleEventManager];
+ [eventManager setEventHandler:newDelegate andSelector:@selector(appleEventQuit:withReplyEvent:)
+ forEventClass:kCoreEventClass andEventID:kAEQuitApplication];
+ [eventManager setEventHandler:newDelegate andSelector:@selector(getUrl:withReplyEvent:)
+ forEventClass:kInternetEventClass andEventID:kAEGetURL];
+}
+#endif
+
// In Carbon this is your one stop for apple events.
// In Cocoa, it ISN'T. This is the catch-all Apple Event handler that exists
// for the time between instantiating the NSApplication, but before the
@@ -3002,7 +3049,7 @@ void onApplicationWindowChangedActivation(QWidget *widget, bool activated)
}
QMenuBar::macUpdateMenuBar();
-
+ QApplicationPrivate::updateOverrideCursor();
#else
Q_UNUSED(widget);
Q_UNUSED(activated);
diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h
index 9c001ab584..d19d86ee60 100644
--- a/src/gui/kernel/qapplication_p.h
+++ b/src/gui/kernel/qapplication_p.h
@@ -457,6 +457,12 @@ public:
static OSStatus globalEventProcessor(EventHandlerCallRef, EventRef, void *);
static OSStatus globalAppleEventProcessor(const AppleEvent *, AppleEvent *, long);
static OSStatus tabletProximityCallback(EventHandlerCallRef, EventRef, void *);
+#ifdef QT_MAC_USE_COCOA
+ static void qt_initAfterNSAppStarted();
+ static void setupAppleEvents();
+ static void updateOverrideCursor();
+ static void disableUsageOfCursorRects(bool disable);
+#endif
static bool qt_mac_apply_settings();
#endif
@@ -512,6 +518,13 @@ public:
QGestureManager *gestureManager;
QWidget *gestureWidget;
+ QPixmap *move_cursor;
+ QPixmap *copy_cursor;
+ QPixmap *link_cursor;
+#if defined(Q_WS_WIN)
+ QPixmap *ignore_cursor;
+#endif
+ QPixmap getPixmapCursor(Qt::CursorShape cshape);
QMap<int, QWeakPointer<QWidget> > widgetForTouchPointId;
QMap<int, QTouchEvent::TouchPoint> appCurrentTouchPoints;
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp
index bf3ad71fbd..3e2e6f67de 100644
--- a/src/gui/kernel/qapplication_s60.cpp
+++ b/src/gui/kernel/qapplication_s60.cpp
@@ -63,7 +63,7 @@
#include "private/qsoftkeymanager_p.h"
#include "apgwgnam.h" // For CApaWindowGroupName
-#include <MdaAudioTonePlayer.h> // For CMdaAudioToneUtility
+#include <mdaaudiotoneplayer.h> // For CMdaAudioToneUtility
#if defined(Q_WS_S60)
# if !defined(QT_NO_IM)
diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp
index 2a1f655373..667db39b31 100644
--- a/src/gui/kernel/qapplication_x11.cpp
+++ b/src/gui/kernel/qapplication_x11.cpp
@@ -614,6 +614,11 @@ static int (*original_xio_errhandler)(Display *dpy);
static int qt_x_errhandler(Display *dpy, XErrorEvent *err)
{
+ if (X11->display != dpy) {
+ // only handle X errors for our display
+ return 0;
+ }
+
switch (err->error_code) {
case BadAtom:
if (err->request_code == 20 /* X_GetProperty */
diff --git a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm
index 47a8026f34..ab71a05973 100644
--- a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm
+++ b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm
@@ -317,5 +317,12 @@ static void cleanupCocoaApplicationDelegate()
qt_sendSpontaneousEvent(qAppInstance(), &qtEvent);
}
+- (void)appleEventQuit:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
+{
+ Q_UNUSED(event);
+ Q_UNUSED(replyEvent);
+ [NSApp terminate:self];
+}
+
@end
#endif
diff --git a/src/gui/kernel/qcocoapanel_mac.mm b/src/gui/kernel/qcocoapanel_mac.mm
index 5e24c84ac6..0b48efd432 100644
--- a/src/gui/kernel/qcocoapanel_mac.mm
+++ b/src/gui/kernel/qcocoapanel_mac.mm
@@ -46,6 +46,7 @@
#import <private/qcocoawindowdelegate_mac_p.h>
#import <private/qcocoaview_mac_p.h>
#import <private/qcocoawindowcustomthemeframe_mac_p.h>
+#import <private/qcocoaapplication_mac_p.h>
#include <private/qapplication_p.h>
#include <private/qbackingstore_p.h>
diff --git a/src/gui/kernel/qcocoapanel_mac_p.h b/src/gui/kernel/qcocoapanel_mac_p.h
index fc83bd892a..3678f81a32 100644
--- a/src/gui/kernel/qcocoapanel_mac_p.h
+++ b/src/gui/kernel/qcocoapanel_mac_p.h
@@ -54,10 +54,16 @@
#ifdef QT_MAC_USE_COCOA
#import <Cocoa/Cocoa.h>
+QT_FORWARD_DECLARE_CLASS(QStringList);
+
@interface QT_MANGLE_NAMESPACE(QCocoaPanel) : NSPanel {
bool leftButtonIsRightButton;
+ QStringList *currentCustomDragTypes;
}
+ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask;
+- (void)registerDragTypes;
+
@end
#endif
+
diff --git a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h
index d2b74d7420..a1d2c6166d 100644
--- a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h
+++ b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h
@@ -57,8 +57,32 @@
QT_BEGIN_NAMESPACE
extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview.mm
extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
+extern const QStringList& qEnabledDraggedTypes(); // qmime_mac.cpp
+extern bool qt_blockCocoaSettingModalWindowLevel; // qeventdispatcher_mac_p.h
+
+Q_GLOBAL_STATIC(QPointer<QWidget>, currentDragTarget);
+
QT_END_NAMESPACE
+- (id)initWithContentRect:(NSRect)contentRect
+ styleMask:(NSUInteger)windowStyle
+ backing:(NSBackingStoreType)bufferingType
+ defer:(BOOL)deferCreation
+{
+ self = [super initWithContentRect:contentRect styleMask:windowStyle
+ backing:bufferingType defer:deferCreation];
+ if (self) {
+ currentCustomDragTypes = 0;
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ delete currentCustomDragTypes;
+ [super dealloc];
+}
+
- (BOOL)canBecomeKeyWindow
{
QWidget *widget = [self QT_MANGLE_NAMESPACE(qt_qwidget)];
@@ -68,6 +92,40 @@ QT_END_NAMESPACE
return !(isPopup || isToolTip);
}
+- (BOOL)canBecomeMainWindow
+{
+ QWidget *widget = [self QT_MANGLE_NAMESPACE(qt_qwidget)];
+
+ bool isToolTip = (widget->windowType() == Qt::ToolTip);
+ bool isPopup = (widget->windowType() == Qt::Popup);
+ bool isTool = (widget->windowType() == Qt::Tool);
+ return !(isPopup || isToolTip || isTool);
+}
+
+- (void)orderWindow:(NSWindowOrderingMode)orderingMode relativeTo:(NSInteger)otherWindowNumber
+{
+ if (qt_blockCocoaSettingModalWindowLevel) {
+ // To avoid windows popping in front while restoring modal sessions
+ // in the event dispatcher, we block cocoa from ordering this window
+ // to front. The result of not doing this can be seen if executing
+ // a native color dialog on top of another executing dialog.
+ return;
+ }
+ [super orderWindow:orderingMode relativeTo:otherWindowNumber];
+}
+
+- (void)setLevel:(NSInteger)windowLevel
+{
+ if (qt_blockCocoaSettingModalWindowLevel) {
+ // To avoid windows popping in front while restoring modal sessions
+ // in the event dispatcher, we block cocoa from ordering this window
+ // to front. The result of not doing this can be seen if executing
+ // a native color dialog on top of another executing dialog.
+ return;
+ }
+ [super setLevel:windowLevel];
+}
+
- (void)toggleToolbarShown:(id)sender
{
macSendToolbarChangeEvent([self QT_MANGLE_NAMESPACE(qt_qwidget)]);
@@ -106,6 +164,23 @@ QT_END_NAMESPACE
qt_dispatchTabletProximityEvent(tabletEvent);
}
+- (void)qtDispatcherToQAction:(id)sender
+{
+ // If this window is modal, the menu bar will be modally shaddowed.
+ // In that case, since the window will be in the first responder chain,
+ // we can still catch the trigger here and forward it to the menu bar.
+ // This is needed as a single modal dialog on Qt should be able to access
+ // the application menu (e.g. quit).
+ [[NSApp QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader)] qtDispatcherToQAction:sender];
+}
+
+- (void)terminate:(id)sender
+{
+ // This function is called from the quit item in the menubar when this window
+ // is in the first responder chain (see also qtDispatcherToQAction above)
+ [NSApp terminate:sender];
+}
+
- (void)sendEvent:(NSEvent *)event
{
QWidget *widget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self];
@@ -133,7 +208,7 @@ QT_END_NAMESPACE
qt_button_down = widget;
handled = qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonPress, mouseButton);
// Don't call super here. This prevents us from getting the mouseUp event,
- // which we need to send even if the mouseDown event was not accepted.
+ // which we need to send even if the mouseDown event was not accepted.
// (this is standard Qt behavior.)
break;
case NSRightMouseDown:
@@ -188,6 +263,115 @@ QT_END_NAMESPACE
return [super frameViewClassForStyleMask:styleMask];
}
+-(void)registerDragTypes
+{
+ // Calling registerForDraggedTypes below is slow, so only do
+ // it once for each window, or when the custom types change.
+ QMacCocoaAutoReleasePool pool;
+ const QStringList& customTypes = qEnabledDraggedTypes();
+ if (currentCustomDragTypes == 0 || *currentCustomDragTypes != customTypes) {
+ if (currentCustomDragTypes == 0)
+ currentCustomDragTypes = new QStringList();
+ *currentCustomDragTypes = customTypes;
+ const NSString* mimeTypeGeneric = @"com.trolltech.qt.MimeTypeName";
+ NSMutableArray *supportedTypes = [NSMutableArray arrayWithObjects:NSColorPboardType,
+ NSFilenamesPboardType, NSStringPboardType,
+ NSFilenamesPboardType, NSPostScriptPboardType, NSTIFFPboardType,
+ NSRTFPboardType, NSTabularTextPboardType, NSFontPboardType,
+ NSRulerPboardType, NSFileContentsPboardType, NSColorPboardType,
+ NSRTFDPboardType, NSHTMLPboardType, NSPICTPboardType,
+ NSURLPboardType, NSPDFPboardType, NSVCardPboardType,
+ NSFilesPromisePboardType, NSInkTextPboardType,
+ NSMultipleTextSelectionPboardType, mimeTypeGeneric, nil];
+ // Add custom types supported by the application.
+ for (int i = 0; i < customTypes.size(); i++) {
+ [supportedTypes addObject:reinterpret_cast<const NSString *>(QCFString::toCFStringRef(customTypes[i]))];
+ }
+ [self registerForDraggedTypes:supportedTypes];
+ }
+}
+
+- (QWidget *)dragTargetHitTest:(id <NSDraggingInfo>)sender
+{
+ // Do a hittest to find the NSView under the
+ // mouse, and return the corresponding QWidget:
+ NSPoint windowPoint = [sender draggingLocation];
+ NSView *candidateView = [[self contentView] hitTest:windowPoint];
+ if (![candidateView isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaView) class]])
+ return 0;
+ return [static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(candidateView) qt_qwidget];
+}
+
+- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
+{
+ // The user dragged something into the window. Send a draggingEntered message
+ // to the QWidget under the mouse. As the drag moves over the window, and over
+ // different widgets, we will handle enter and leave events from within
+ // draggingUpdated below. The reason why we handle this ourselves rather than
+ // subscribing for drag events directly in QCocoaView is that calling
+ // registerForDraggedTypes on the views will severly degrade initialization time
+ // for an application that uses a lot of drag subscribing widgets.
+
+ QWidget *target = [self dragTargetHitTest:sender];
+ if (!target)
+ return [super draggingEntered:sender];
+ if (target->testAttribute(Qt::WA_DropSiteRegistered) == false)
+ return NSDragOperationNone;
+
+ *currentDragTarget() = target;
+ return [reinterpret_cast<NSView *>((*currentDragTarget())->winId()) draggingEntered:sender];
+ }
+
+- (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender
+{
+ QWidget *target = [self dragTargetHitTest:sender];
+ if (!target)
+ return [super draggingUpdated:sender];
+
+ if (target == *currentDragTarget()) {
+ // The drag continues to move over the widget that we have sendt
+ // a draggingEntered message to. So just update the view:
+ return [reinterpret_cast<NSView *>((*currentDragTarget())->winId()) draggingUpdated:sender];
+ } else {
+ // The widget under the mouse has changed.
+ // So we need to fake enter/leave events:
+ if (*currentDragTarget())
+ [reinterpret_cast<NSView *>((*currentDragTarget())->winId()) draggingExited:sender];
+ if (target->testAttribute(Qt::WA_DropSiteRegistered) == false) {
+ *currentDragTarget() = 0;
+ return NSDragOperationNone;
+ }
+ *currentDragTarget() = target;
+ return [reinterpret_cast<NSView *>((*currentDragTarget())->winId()) draggingEntered:sender];
+ }
+}
+
+- (void)draggingExited:(id < NSDraggingInfo >)sender
+{
+ QWidget *target = [self dragTargetHitTest:sender];
+ if (!target)
+ return [super draggingExited:sender];
+
+ if (*currentDragTarget()) {
+ [reinterpret_cast<NSView *>((*currentDragTarget())->winId()) draggingExited:sender];
+ *currentDragTarget() = 0;
+ }
+}
+
+- (BOOL)performDragOperation:(id < NSDraggingInfo >)sender
+{
+ QWidget *target = [self dragTargetHitTest:sender];
+ if (!target)
+ return [super performDragOperation:sender];
+
+ BOOL dropResult = NO;
+ if (*currentDragTarget()) {
+ dropResult = [reinterpret_cast<NSView *>((*currentDragTarget())->winId()) performDragOperation:sender];
+ *currentDragTarget() = 0;
+ }
+ return dropResult;
+}
+
- (void)displayIfNeeded
{
@@ -203,5 +387,3 @@ QT_END_NAMESPACE
}
[super displayIfNeeded];
}
-
-
diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm
index 2c35be2135..70c78c836d 100644
--- a/src/gui/kernel/qcocoaview_mac.mm
+++ b/src/gui/kernel/qcocoaview_mac.mm
@@ -81,7 +81,6 @@ Q_GLOBAL_STATIC(DnDParams, qMacDnDParams);
extern void qt_mac_update_cursor_at_global_pos(const QPoint &globalPos); // qcursor_mac.mm
extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); // qapplication.cpp
extern OSViewRef qt_mac_nativeview_for(const QWidget *w); // qwidget_mac.mm
-extern const QStringList& qEnabledDraggedTypes(); // qmime_mac.cpp
extern QPointer<QWidget> qt_mouseover; //qapplication_mac.mm
extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp
@@ -212,7 +211,6 @@ extern "C" {
composingText = new QString();
composing = false;
sendKeyEvents = true;
- currentCustomTypes = 0;
[self setHidden:YES];
return self;
}
@@ -227,36 +225,12 @@ extern "C" {
object:self];
}
--(void)registerDragTypes
-{
- QMacCocoaAutoReleasePool pool;
- // Calling registerForDraggedTypes is slow, so only do it once for each widget
- // or when the custom types change.
- const QStringList& customTypes = qEnabledDraggedTypes();
- if (currentCustomTypes == 0 || *currentCustomTypes != customTypes) {
- if (currentCustomTypes == 0)
- currentCustomTypes = new QStringList();
- *currentCustomTypes = customTypes;
- const NSString* mimeTypeGeneric = @"com.trolltech.qt.MimeTypeName";
- NSMutableArray *supportedTypes = [NSMutableArray arrayWithObjects:NSColorPboardType,
- NSFilenamesPboardType, NSStringPboardType,
- NSFilenamesPboardType, NSPostScriptPboardType, NSTIFFPboardType,
- NSRTFPboardType, NSTabularTextPboardType, NSFontPboardType,
- NSRulerPboardType, NSFileContentsPboardType, NSColorPboardType,
- NSRTFDPboardType, NSHTMLPboardType, NSPICTPboardType,
- NSURLPboardType, NSPDFPboardType, NSVCardPboardType,
- NSFilesPromisePboardType, NSInkTextPboardType,
- NSMultipleTextSelectionPboardType, mimeTypeGeneric, nil];
- // Add custom types supported by the application.
- for (int i = 0; i < customTypes.size(); i++) {
- [supportedTypes addObject:reinterpret_cast<const NSString *>(QCFString::toCFStringRef(customTypes[i]))];
- }
- [self registerForDraggedTypes:supportedTypes];
- }
-}
-
- (void)resetCursorRects
{
+ // [NSView addCursorRect] is slow, so bail out early if we can:
+ if (NSIsEmptyRect([self visibleRect]))
+ return;
+
QWidget *cursorWidget = qwidget;
if (cursorWidget->testAttribute(Qt::WA_TransparentForMouseEvents))
@@ -300,15 +274,9 @@ extern "C" {
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
{
- if (qwidget->testAttribute(Qt::WA_DropSiteRegistered) == false)
- return NSDragOperationNone;
+ // NB: This function is called from QCoocaWindow/QCocoaPanel rather than directly
+ // from Cocoa. They modify the drag target, and might fake enter/leave events.
NSPoint windowPoint = [sender draggingLocation];
- if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents)) {
- // pass the drag enter event to the view underneath.
- NSView *candidateView = [[[self window] contentView] hitTest:windowPoint];
- if (candidateView && candidateView != self)
- return [candidateView draggingEntered:sender];
- }
dragEnterSequence = [sender draggingSequenceNumber];
[self addDropData:sender];
QMimeData *mimeData = dropData;
@@ -361,13 +329,9 @@ extern "C" {
}
- (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender
{
+ // NB: This function is called from QCoocaWindow/QCocoaPanel rather than directly
+ // from Cocoa. They modify the drag target, and might fake enter/leave events.
NSPoint windowPoint = [sender draggingLocation];
- if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents)) {
- // pass the drag move event to the view underneath.
- NSView *candidateView = [[[self window] contentView] hitTest:windowPoint];
- if (candidateView && candidateView != self)
- return [candidateView draggingUpdated:sender];
- }
// in cases like QFocusFrame, the view under the mouse might
// not have received the drag enter. Generate a synthetic
// drag enter event for that view.
@@ -417,14 +381,10 @@ extern "C" {
- (void)draggingExited:(id < NSDraggingInfo >)sender
{
+ // NB: This function is called from QCoocaWindow/QCocoaPanel rather than directly
+ // from Cocoa. They modify the drag target, and might fake enter/leave events.
+ Q_UNUSED(sender);
dragEnterSequence = -1;
- if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents)) {
- // try sending the leave event to the last view which accepted drag enter.
- DnDParams *dndParams = [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent];
- NSView *candidateView = [[[self window] contentView] hitTest:dndParams->activeDragEnterPos];
- if (candidateView && candidateView != self)
- return [candidateView draggingExited:sender];
- }
// drag enter event was rejected, so ignore the move event.
if (dropData) {
QDragLeaveEvent de;
@@ -435,14 +395,10 @@ extern "C" {
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
{
+ // NB: This function is called from QCoocaWindow/QCocoaPanel rather than directly
+ // from Cocoa. They modify the drag target, and might fake enter/leave events.
NSPoint windowPoint = [sender draggingLocation];
dragEnterSequence = -1;
- if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents)) {
- // pass the drop event to the view underneath.
- NSView *candidateView = [[[self window] contentView] hitTest:windowPoint];
- if (candidateView && candidateView != self)
- return [candidateView performDragOperation:sender];
- }
[self addDropData:sender];
NSPoint globalPoint = [[sender draggingDestinationWindow] convertBaseToScreen:windowPoint];
@@ -472,8 +428,6 @@ extern "C" {
{
delete composingText;
[[NSNotificationCenter defaultCenter] removeObserver:self];
- delete currentCustomTypes;
- [self unregisterDraggedTypes];
[super dealloc];
}
@@ -616,6 +570,10 @@ extern "C" {
- (void)updateTrackingAreas
{
+ // [NSView addTrackingArea] is slow, so bail out early if we can:
+ if (NSIsEmptyRect([self visibleRect]))
+ return;
+
QMacCocoaAutoReleasePool pool;
if (NSArray *trackingArray = [self trackingAreas]) {
NSUInteger size = [trackingArray count];
diff --git a/src/gui/kernel/qcocoaview_mac_p.h b/src/gui/kernel/qcocoaview_mac_p.h
index 797b4d5b2a..4bb10c5d8b 100644
--- a/src/gui/kernel/qcocoaview_mac_p.h
+++ b/src/gui/kernel/qcocoaview_mac_p.h
@@ -87,7 +87,6 @@ Q_GUI_EXPORT
int composingLength;
bool sendKeyEvents;
QString *composingText;
- QStringList *currentCustomTypes;
NSInteger dragEnterSequence;
}
- (id)initWithQWidget:(QWidget *)widget widgetPrivate:(QWidgetPrivate *)widgetprivate;
@@ -97,7 +96,6 @@ Q_GUI_EXPORT
- (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender;
- (void)draggingExited:(id < NSDraggingInfo >)sender;
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender;
-- (void)registerDragTypes;
- (void)removeDropData;
- (void)addDropData:(id <NSDraggingInfo>)sender;
- (void)setSupportedActions:(NSDragOperation)actions;
diff --git a/src/gui/kernel/qcocoawindow_mac.mm b/src/gui/kernel/qcocoawindow_mac.mm
index a644dfebfe..f1b642b50c 100644
--- a/src/gui/kernel/qcocoawindow_mac.mm
+++ b/src/gui/kernel/qcocoawindow_mac.mm
@@ -46,6 +46,7 @@
#import <private/qcocoaview_mac_p.h>
#import <private/qt_cocoa_helpers_mac_p.h>
#import <private/qcocoawindowcustomthemeframe_mac_p.h>
+#import <private/qcocoaapplication_mac_p.h>
#include <QtGui/QWidget>
diff --git a/src/gui/kernel/qcocoawindow_mac_p.h b/src/gui/kernel/qcocoawindow_mac_p.h
index 04748822ce..21f82df078 100644
--- a/src/gui/kernel/qcocoawindow_mac_p.h
+++ b/src/gui/kernel/qcocoawindow_mac_p.h
@@ -73,9 +73,12 @@ QT_FORWARD_DECLARE_CLASS(QStringList);
@interface QT_MANGLE_NAMESPACE(QCocoaWindow) : NSWindow {
bool leftButtonIsRightButton;
+ QStringList *currentCustomDragTypes;
}
+ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask;
+- (void)registerDragTypes;
+
@end
#endif
diff --git a/src/gui/kernel/qcocoawindowdelegate_mac.mm b/src/gui/kernel/qcocoawindowdelegate_mac.mm
index db8749190a..24498f8cc0 100644
--- a/src/gui/kernel/qcocoawindowdelegate_mac.mm
+++ b/src/gui/kernel/qcocoawindowdelegate_mac.mm
@@ -269,9 +269,6 @@ static void cleanupCocoaWindowDelegate()
{
QWidget *qwidget = m_windowHash->value([notification object]);
Q_ASSERT(qwidget);
- if (qwidget->isActiveWindow())
- return; // Widget is already active, no need to go through re-activation.
-
onApplicationWindowChangedActivation(qwidget, true);
}
@@ -288,10 +285,6 @@ static void cleanupCocoaWindowDelegate()
{
QWidget *qwidget = m_windowHash->value([notification object]);
Q_ASSERT(qwidget);
- if (qwidget->isActiveWindow())
- return; // Widget is already active, no need to go through re-activation
-
-
onApplicationWindowChangedActivation(qwidget, true);
}
diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp
index 0f0470c752..f38e4f5c1c 100644
--- a/src/gui/kernel/qcursor.cpp
+++ b/src/gui/kernel/qcursor.cpp
@@ -141,6 +141,12 @@ QT_BEGIN_NAMESPACE
\o Qt::WhatsThisCursor \o \c whats_this
\o \inlineimage cursor-closedhand.png
\o Qt::ClosedHandCursor \o \c closedhand
+ \row \o
+ \o Qt::DragMoveCursor \o \c dnd-move or \c move
+ \o
+ \o Qt::DragCopyCursor \o \c dnd-copy or \c copy
+ \row \o
+ \o Qt::DragLinkCursor \o \c dnd-link or \c link
\endtable
\sa QWidget, {fowler}{GUI Design Handbook: Cursors}
diff --git a/src/gui/kernel/qcursor_mac.mm b/src/gui/kernel/qcursor_mac.mm
index 48bb9cc709..cfebf606b7 100644
--- a/src/gui/kernel/qcursor_mac.mm
+++ b/src/gui/kernel/qcursor_mac.mm
@@ -424,6 +424,18 @@ void QCursorData::update()
type = QCursorData::TYPE_ThemeCursor;
curs.cp.nscursor = [NSCursor closedHandCursor];
break;
+ case Qt::DragCopyCursor:
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.cp.nscursor = [NSCursor dragCopyCursor];
+ break;
+ case Qt::DragMoveCursor:
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.cp.nscursor = [NSCursor arrowCursor];
+ break;
+ case Qt::DragLinkCursor:
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.cp.nscursor = [NSCursor dragLinkCursor];
+ break;
#define QT_USE_APPROXIMATE_CURSORS
#ifdef QT_USE_APPROXIMATE_CURSORS
case Qt::SizeVerCursor:
@@ -519,6 +531,18 @@ void QCursorData::update()
type = QCursorData::TYPE_ThemeCursor;
curs.tc.curs = kThemeClosedHandCursor;
break;
+ case Qt::DragMoveCursor:
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.tc.curs = kThemeArrowCursor;
+ break;
+ case Qt::DragCopyCursor:
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.tc.curs = kThemeCopyArrowCursor;
+ break;
+ case Qt::DragLinkCursor:
+ type = QCursorData::TYPE_ThemeCursor;
+ curs.tc.curs = kThemeAliasArrowCursor;
+ break;
#define QT_USE_APPROXIMATE_CURSORS
#ifdef QT_USE_APPROXIMATE_CURSORS
case Qt::SizeVerCursor:
diff --git a/src/gui/kernel/qcursor_win.cpp b/src/gui/kernel/qcursor_win.cpp
index 6f651d4fab..ae1c004e39 100644
--- a/src/gui/kernel/qcursor_win.cpp
+++ b/src/gui/kernel/qcursor_win.cpp
@@ -47,6 +47,7 @@
#include <qimage.h>
#include <qt_windows.h>
+#include <private/qapplication_p.h>
QT_BEGIN_NAMESPACE
@@ -470,6 +471,12 @@ void QCursorData::update()
#endif
return;
}
+ case Qt::DragCopyCursor:
+ case Qt::DragMoveCursor:
+ case Qt::DragLinkCursor: {
+ QPixmap pixmap = QApplicationPrivate::instance()->getPixmapCursor(cshape);
+ hcurs = create32BitCursor(pixmap, hx, hy);
+ }
default:
qWarning("QCursor::update: Invalid cursor shape %d", cshape);
return;
diff --git a/src/gui/kernel/qcursor_x11.cpp b/src/gui/kernel/qcursor_x11.cpp
index 3e833638a2..4e871a6e1f 100644
--- a/src/gui/kernel/qcursor_x11.cpp
+++ b/src/gui/kernel/qcursor_x11.cpp
@@ -39,9 +39,11 @@
**
****************************************************************************/
+#include <qdebug.h>
#include <qdatastream.h>
#include <private/qcursor_p.h>
#include <private/qt_x11_p.h>
+#include <private/qapplication_p.h>
#include <qbitmap.h>
#include <qcursor.h>
#include <X11/cursorfont.h>
@@ -57,6 +59,7 @@
#endif // QT_NO_XFIXES
#include "qx11info_x11.h"
+#include <private/qpixmap_x11_p.h>
QT_BEGIN_NAMESPACE
@@ -262,12 +265,31 @@ void QCursorData::update()
"whats_this",
"left_ptr_watch",
"openhand",
- "closedhand"
+ "closedhand",
+ "copy",
+ "move",
+ "link"
};
#ifndef QT_NO_XCURSOR
- if (X11->ptrXcursorLibraryLoadCursor)
- hcurs = X11->ptrXcursorLibraryLoadCursor(dpy, cursorNames[cshape]);
+ if (X11->ptrXcursorLibraryLoadCursor) {
+ // special case for non-standard dnd-* cursors
+ switch (cshape) {
+ case Qt::DragCopyCursor:
+ hcurs = X11->ptrXcursorLibraryLoadCursor(dpy, "dnd-copy");
+ break;
+ case Qt::DragMoveCursor:
+ hcurs = X11->ptrXcursorLibraryLoadCursor(dpy, "dnd-move");
+ break;
+ case Qt::DragLinkCursor:
+ hcurs = X11->ptrXcursorLibraryLoadCursor(dpy, "dnd-link");
+ break;
+ default:
+ break;
+ }
+ if (!hcurs)
+ hcurs = X11->ptrXcursorLibraryLoadCursor(dpy, cursorNames[cshape]);
+ }
if (hcurs)
return;
#endif // QT_NO_XCURSOR
@@ -504,6 +526,19 @@ void QCursorData::update()
pm = XCreateBitmapFromData(dpy, rootwin, open ? openhand_bits : closedhand_bits, 16, 16);
pmm = XCreateBitmapFromData(dpy, rootwin, 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) {
+ XColor bg, fg;
+ bg.red = 255 << 8;
+ bg.green = 255 << 8;
+ bg.blue = 255 << 8;
+ fg.red = 0;
+ fg.green = 0;
+ fg.blue = 0;
+ QImage image = QApplicationPrivate::instance()->getPixmapCursor(cshape).toImage();
+ pm = QX11PixmapData::createBitmapFromImage(image);
+ pmm = QX11PixmapData::createBitmapFromImage(image.createAlphaMask().convertToFormat(QImage::Format_MonoLSB));
+ hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, 8, 8);
}
if (hcurs)
@@ -577,6 +612,15 @@ void QCursorData::update()
case Qt::BusyCursor:
sh = XC_watch;
break;
+ case Qt::DragCopyCursor:
+ sh = XC_tcross;
+ break;
+ case Qt::DragLinkCursor:
+ sh = XC_center_ptr;
+ break;
+ case Qt::DragMoveCursor:
+ sh = XC_top_left_arrow;
+ break;
#endif /* QT_USE_APPROXIMATE_CURSORS */
default:
qWarning("QCursor::update: Invalid cursor shape %d", cshape);
diff --git a/src/gui/kernel/qdnd.cpp b/src/gui/kernel/qdnd.cpp
index 21438a8b8a..2b3a3d08c1 100644
--- a/src/gui/kernel/qdnd.cpp
+++ b/src/gui/kernel/qdnd.cpp
@@ -60,204 +60,12 @@
#include "qdebug.h"
#include <ctype.h>
+#include <private/qapplication_p.h>
+
#ifndef QT_NO_DRAGANDDROP
QT_BEGIN_NAMESPACE
-// These pixmaps approximate the images in the Windows User Interface Guidelines.
-
-// XPM
-
-static const char * const move_xpm[] = {
-"11 20 3 1",
-". c None",
-#if defined(Q_WS_WIN)
-"a c #000000",
-"X c #FFFFFF", // Windows cursor is traditionally white
-#else
-"a c #FFFFFF",
-"X c #000000", // X11 cursor is traditionally black
-#endif
-"aa.........",
-"aXa........",
-"aXXa.......",
-"aXXXa......",
-"aXXXXa.....",
-"aXXXXXa....",
-"aXXXXXXa...",
-"aXXXXXXXa..",
-"aXXXXXXXXa.",
-"aXXXXXXXXXa",
-"aXXXXXXaaaa",
-"aXXXaXXa...",
-"aXXaaXXa...",
-"aXa..aXXa..",
-"aa...aXXa..",
-"a.....aXXa.",
-"......aXXa.",
-".......aXXa",
-".......aXXa",
-"........aa."};
-
-#ifdef Q_WS_WIN
-/* XPM */
-static const char * const ignore_xpm[] = {
-"24 30 3 1",
-". c None",
-"a c #000000",
-"X c #FFFFFF",
-"aa......................",
-"aXa.....................",
-"aXXa....................",
-"aXXXa...................",
-"aXXXXa..................",
-"aXXXXXa.................",
-"aXXXXXXa................",
-"aXXXXXXXa...............",
-"aXXXXXXXXa..............",
-"aXXXXXXXXXa.............",
-"aXXXXXXaaaa.............",
-"aXXXaXXa................",
-"aXXaaXXa................",
-"aXa..aXXa...............",
-"aa...aXXa...............",
-"a.....aXXa..............",
-"......aXXa.....XXXX.....",
-".......aXXa..XXaaaaXX...",
-".......aXXa.XaaaaaaaaX..",
-"........aa.XaaaXXXXaaaX.",
-"...........XaaaaX..XaaX.",
-"..........XaaXaaaX..XaaX",
-"..........XaaXXaaaX.XaaX",
-"..........XaaX.XaaaXXaaX",
-"..........XaaX..XaaaXaaX",
-"...........XaaX..XaaaaX.",
-"...........XaaaXXXXaaaX.",
-"............XaaaaaaaaX..",
-".............XXaaaaXX...",
-"...............XXXX....."};
-#endif
-
-/* XPM */
-static const char * const copy_xpm[] = {
-"24 30 3 1",
-". c None",
-"a c #000000",
-"X c #FFFFFF",
-#if defined(Q_WS_WIN) // Windows cursor is traditionally white
-"aa......................",
-"aXa.....................",
-"aXXa....................",
-"aXXXa...................",
-"aXXXXa..................",
-"aXXXXXa.................",
-"aXXXXXXa................",
-"aXXXXXXXa...............",
-"aXXXXXXXXa..............",
-"aXXXXXXXXXa.............",
-"aXXXXXXaaaa.............",
-"aXXXaXXa................",
-"aXXaaXXa................",
-"aXa..aXXa...............",
-"aa...aXXa...............",
-"a.....aXXa..............",
-"......aXXa..............",
-".......aXXa.............",
-".......aXXa.............",
-"........aa...aaaaaaaaaaa",
-#else
-"XX......................",
-"XaX.....................",
-"XaaX....................",
-"XaaaX...................",
-"XaaaaX..................",
-"XaaaaaX.................",
-"XaaaaaaX................",
-"XaaaaaaaX...............",
-"XaaaaaaaaX..............",
-"XaaaaaaaaaX.............",
-"XaaaaaaXXXX.............",
-"XaaaXaaX................",
-"XaaXXaaX................",
-"XaX..XaaX...............",
-"XX...XaaX...............",
-"X.....XaaX..............",
-"......XaaX..............",
-".......XaaX.............",
-".......XaaX.............",
-"........XX...aaaaaaaaaaa",
-#endif
-".............aXXXXXXXXXa",
-".............aXXXXXXXXXa",
-".............aXXXXaXXXXa",
-".............aXXXXaXXXXa",
-".............aXXaaaaaXXa",
-".............aXXXXaXXXXa",
-".............aXXXXaXXXXa",
-".............aXXXXXXXXXa",
-".............aXXXXXXXXXa",
-".............aaaaaaaaaaa"};
-
-/* XPM */
-static const char * const link_xpm[] = {
-"24 30 3 1",
-". c None",
-"a c #000000",
-"X c #FFFFFF",
-#if defined(Q_WS_WIN) // Windows cursor is traditionally white
-"aa......................",
-"aXa.....................",
-"aXXa....................",
-"aXXXa...................",
-"aXXXXa..................",
-"aXXXXXa.................",
-"aXXXXXXa................",
-"aXXXXXXXa...............",
-"aXXXXXXXXa..............",
-"aXXXXXXXXXa.............",
-"aXXXXXXaaaa.............",
-"aXXXaXXa................",
-"aXXaaXXa................",
-"aXa..aXXa...............",
-"aa...aXXa...............",
-"a.....aXXa..............",
-"......aXXa..............",
-".......aXXa.............",
-".......aXXa.............",
-"........aa...aaaaaaaaaaa",
-#else
-"XX......................",
-"XaX.....................",
-"XaaX....................",
-"XaaaX...................",
-"XaaaaX..................",
-"XaaaaaX.................",
-"XaaaaaaX................",
-"XaaaaaaaX...............",
-"XaaaaaaaaX..............",
-"XaaaaaaaaaX.............",
-"XaaaaaaXXXX.............",
-"XaaaXaaX................",
-"XaaXXaaX................",
-"XaX..XaaX...............",
-"XX...XaaX...............",
-"X.....XaaX..............",
-"......XaaX..............",
-".......XaaX.............",
-".......XaaX.............",
-"........XX...aaaaaaaaaaa",
-#endif
-".............aXXXXXXXXXa",
-".............aXXXaaaaXXa",
-".............aXXXXaaaXXa",
-".............aXXXaaaaXXa",
-".............aXXaaaXaXXa",
-".............aXXaaXXXXXa",
-".............aXXaXXXXXXa",
-".............aXXXaXXXXXa",
-".............aXXXXXXXXXa",
-".............aaaaaaaaaaa"};
-
#ifndef QT_NO_DRAGANDDROP
//#define QDND_DEBUG
@@ -326,22 +134,9 @@ QDragManager::QDragManager()
{
Q_ASSERT(!instance);
-#ifdef Q_WS_WIN
- n_cursor = 4;
-#else
- n_cursor = 3;
-#endif
-
#ifdef Q_WS_QWS
currentActionForOverrideCursor = Qt::IgnoreAction;
#endif
- pm_cursor = new QPixmap[n_cursor];
- pm_cursor[0] = QPixmap((const char **)move_xpm);
- pm_cursor[1] = QPixmap((const char **)copy_xpm);
- pm_cursor[2] = QPixmap((const char **)link_xpm);
-#ifdef Q_WS_WIN
- pm_cursor[3] = QPixmap((const char **)ignore_xpm);
-#endif
object = 0;
beingCancelled = false;
restoreCursor = false;
@@ -362,7 +157,6 @@ QDragManager::~QDragManager()
QApplication::restoreOverrideCursor();
#endif
instance = 0;
- delete [] pm_cursor;
delete dropData;
}
@@ -379,14 +173,14 @@ QPixmap QDragManager::dragCursor(Qt::DropAction action) const
if (d && d->customCursors.contains(action))
return d->customCursors[action];
else if (action == Qt::MoveAction)
- return pm_cursor[0];
+ return QApplicationPrivate::instance()->getPixmapCursor(Qt::DragMoveCursor);
else if (action == Qt::CopyAction)
- return pm_cursor[1];
+ return QApplicationPrivate::instance()->getPixmapCursor(Qt::DragCopyCursor);
else if (action == Qt::LinkAction)
- return pm_cursor[2];
+ return QApplicationPrivate::instance()->getPixmapCursor(Qt::DragLinkCursor);
#ifdef Q_WS_WIN
else if (action == Qt::IgnoreAction)
- return pm_cursor[3];
+ return QApplicationPrivate::instance()->getPixmapCursor(Qt::ForbiddenCursor);
#endif
return QPixmap();
}
diff --git a/src/gui/kernel/qdnd_p.h b/src/gui/kernel/qdnd_p.h
index d70b983c30..033e6a6702 100644
--- a/src/gui/kernel/qdnd_p.h
+++ b/src/gui/kernel/qdnd_p.h
@@ -261,8 +261,6 @@ public:
#endif
private:
- QPixmap *pm_cursor;
- int n_cursor;
#ifdef Q_WS_QWS
Qt::DropAction currentActionForOverrideCursor;
#endif
diff --git a/src/gui/kernel/qdnd_s60.cpp b/src/gui/kernel/qdnd_s60.cpp
index 24f0090aae..1aa30af0f7 100644
--- a/src/gui/kernel/qdnd_s60.cpp
+++ b/src/gui/kernel/qdnd_s60.cpp
@@ -52,7 +52,7 @@
#include "qdnd_p.h"
#include "qt_s60_p.h"
-#include <COECNTRL.H>
+#include <coecntrl.h>
// pointer cursor
#include <w32std.h>
#include <gdi.h>
diff --git a/src/gui/kernel/qdnd_x11.cpp b/src/gui/kernel/qdnd_x11.cpp
index 33968bd9fc..9591b9a36c 100644
--- a/src/gui/kernel/qdnd_x11.cpp
+++ b/src/gui/kernel/qdnd_x11.cpp
@@ -1340,9 +1340,9 @@ void QDragManager::updateCursor()
if (!noDropCursor) {
#ifndef QT_NO_CURSOR
noDropCursor = new QCursor(Qt::ForbiddenCursor);
- moveCursor = new QCursor(dragCursor(Qt::MoveAction), 0,0);
- copyCursor = new QCursor(dragCursor(Qt::CopyAction), 0,0);
- linkCursor = new QCursor(dragCursor(Qt::LinkAction), 0,0);
+ moveCursor = new QCursor(Qt::DragMoveCursor);
+ copyCursor = new QCursor(Qt::DragCopyCursor);
+ linkCursor = new QCursor(Qt::DragLinkCursor);
#endif
}
diff --git a/src/gui/kernel/qeventdispatcher_mac.mm b/src/gui/kernel/qeventdispatcher_mac.mm
index c7c7caf74a..c7d042df09 100644
--- a/src/gui/kernel/qeventdispatcher_mac.mm
+++ b/src/gui/kernel/qeventdispatcher_mac.mm
@@ -90,11 +90,16 @@
#ifndef QT_NO_THREAD
# include "qmutex.h"
+#endif
QT_BEGIN_NAMESPACE
QT_USE_NAMESPACE
-#endif
+
+/*****************************************************************************
+ Internal variables and functions
+ *****************************************************************************/
+bool qt_blockCocoaSettingModalWindowLevel = false;
/*****************************************************************************
Externals
@@ -540,6 +545,12 @@ bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags)
{
Q_D(QEventDispatcherMac);
d->interrupt = false;
+
+#ifdef QT_MAC_USE_COCOA
+ bool interruptLater = false;
+ QtMacInterruptDispatcherHelp::cancelInterruptLater();
+#endif
+
// In case we end up recursing while we now process events, make sure
// that we send remaining posted Qt events before this call returns:
wakeUp();
@@ -554,25 +565,25 @@ bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags)
QMacCocoaAutoReleasePool pool;
NSEvent* event = 0;
- // If Qt is used as a plugin, or just added into a native cocoa
- // application, we should not run or stop NSApplication;
- // This will be done from outside Qt.
- // And if processEvents is called manually (rather than from QEventLoop), we
- // cannot enter a tight loop and block the call, but instead return after one flush:
- bool canExec_3rdParty = d->nsAppRunCalledByQt || ![NSApp isRunning];
- bool canExec_Qt = flags & QEventLoop::DialogExec || flags & QEventLoop::EventLoopExec;
+ // If Qt is used as a plugin, or as an extension in a native cocoa
+ // application, we should not run or stop NSApplication; This will be
+ // done from the application itself. And if processEvents is called
+ // manually (rather than from a QEventLoop), we cannot enter a tight
+ // loop and block this call, but instead we need to return after one flush:
+ const bool canExec_3rdParty = d->nsAppRunCalledByQt || ![NSApp isRunning];
+ const bool canExec_Qt = flags & QEventLoop::DialogExec || flags & QEventLoop::EventLoopExec;
if (canExec_Qt && canExec_3rdParty) {
// We can use exec-mode, meaning that we can stay in a tight loop until
- // interrupted. This is mostly an optimization, but it also allow us
- // to use [NSApp run], which is the recommended way of running applications
- // in cocoa. [NSApp run] should be called at least once for any cocoa app.
+ // interrupted. This is mostly an optimization, but it allow us to use
+ // [NSApp run], which is the normal code path for cocoa applications.
if (NSModalSession session = d->currentModalSession()) {
QBoolBlocker execGuard(d->currentExecIsNSAppRun, false);
while ([NSApp runModalSession:session] == NSRunContinuesResponse && !d->interrupt)
qt_mac_waitForMoreModalSessionEvents();
+
if (!d->interrupt && session == d->currentModalSessionCached) {
- // INVARIANT: Someone called e.g. [NSApp stopModal:] from outside the event
+ // Someone called [NSApp stopModal:] from outside the event
// dispatcher (e.g to stop a native dialog). But that call wrongly stopped
// 'session' as well. As a result, we need to restart all internal sessions:
d->temporarilyStopAllModalSessions();
@@ -583,54 +594,63 @@ bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags)
[NSApp run];
}
retVal = true;
- } else do {
- // INVARIANT: We cannot block the thread (and run in a tight loop).
+ } else {
+ // We cannot block the thread (and run in a tight loop).
// Instead we will process all current pending events and return.
- bool mustRelease = false;
-
- if (!(flags & QEventLoop::ExcludeUserInputEvents) && !d->queuedUserInputEvents.isEmpty()) {
- // Process a pending user input event
- mustRelease = true;
- event = static_cast<NSEvent *>(d->queuedUserInputEvents.takeFirst());
- } else {
- if (NSModalSession session = d->currentModalSession()) {
- if (flags & QEventLoop::WaitForMoreEvents)
- qt_mac_waitForMoreModalSessionEvents();
- NSInteger status = [NSApp runModalSession:session];
- if (status != NSRunContinuesResponse && session == d->currentModalSessionCached) {
- // INVARIANT: Someone called e.g. [NSApp stopModal:] from outside the event
- // dispatcher (e.g to stop a native dialog). But that call wrongly stopped
- // 'session' as well. As a result, we need to restart all internal sessions:
- d->temporarilyStopAllModalSessions();
- }
- retVal = true;
- break;
+ d->ensureNSAppInitialized();
+ do {
+ bool releaseEvent = false;
+
+ if (!(flags & QEventLoop::ExcludeUserInputEvents)
+ && !d->queuedUserInputEvents.isEmpty()) {
+ // Process a pending user input event
+ releaseEvent = true;
+ event = static_cast<NSEvent *>(d->queuedUserInputEvents.takeFirst());
} else {
- event = [NSApp nextEventMatchingMask:NSAnyEventMask
- untilDate:nil
- inMode:NSDefaultRunLoopMode
- dequeue: YES];
-
- if (event != nil) {
- if (flags & QEventLoop::ExcludeUserInputEvents) {
- if (IsMouseOrKeyEvent(event)) {
- // retain event here?
- [event retain];
- d->queuedUserInputEvents.append(event);
- continue;
+ if (NSModalSession session = d->currentModalSession()) {
+ if (flags & QEventLoop::WaitForMoreEvents)
+ qt_mac_waitForMoreModalSessionEvents();
+ NSInteger status = [NSApp runModalSession:session];
+ if (status != NSRunContinuesResponse && session == d->currentModalSessionCached) {
+ // INVARIANT: Someone called [NSApp stopModal:] from outside the event
+ // dispatcher (e.g to stop a native dialog). But that call wrongly stopped
+ // 'session' as well. As a result, we need to restart all internal sessions:
+ d->temporarilyStopAllModalSessions();
+ }
+ retVal = true;
+ break;
+ } else {
+ event = [NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate:nil
+ inMode:NSDefaultRunLoopMode
+ dequeue: YES];
+
+ if (event != nil) {
+ if (flags & QEventLoop::ExcludeUserInputEvents) {
+ if (IsMouseOrKeyEvent(event)) {
+ [event retain];
+ d->queuedUserInputEvents.append(event);
+ continue;
+ }
}
}
}
}
- }
- if (event) {
- if (!filterEvent(event) && qt_mac_send_event(flags, event, 0))
- retVal = true;
- if (mustRelease)
- [event release];
- }
- } while(!d->interrupt && event != nil);
-
+ if (event) {
+ if (!filterEvent(event) && qt_mac_send_event(flags, event, 0))
+ retVal = true;
+ if (releaseEvent)
+ [event release];
+ }
+ } while (!d->interrupt && event != nil);
+
+ // Since the window that holds modality might have changed while processing
+ // events, we we need to interrupt when we return back the previous process
+ // event recursion to ensure that we spin the correct modal session.
+ // We do the interruptLater at the end of the function to ensure that we don't
+ // disturb the 'wait for more events' below (as deleteLater will post an event):
+ interruptLater = true;
+ }
#else
do {
EventRef event;
@@ -682,25 +702,19 @@ bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags)
}
}
+ // If we're interrupted, we need to interrupt the _current_
+ // recursion as well to check if it is still supposed to be
+ // executing. This way we wind down the stack until we land
+ // on a recursion that again calls processEvents (typically
+ // from QEventLoop), and set interrupt to false:
+ if (d->interrupt)
+ interrupt();
+
#ifdef QT_MAC_USE_COCOA
- // In case we _now_ process events using [NSApp run], we need to stop it to
- // ensure that:
- // 1. the QEventLoop that called us is still executing, or
- // 2. we have a modal session that needs to be spun instead.
- // In case this is a plain call to processEvents (perhaps from a loop)
- // from the application (rather than from a QEventLoop), we delay the
- // interrupting until we/ actually enter a lower loop level (hence the
- // deffered delete of the object below):
- QtMacInterruptDispatcherHelp::interruptLater();
+ if (interruptLater)
+ QtMacInterruptDispatcherHelp::interruptLater();
#endif
- if (d->interrupt) {
- // We should continue to leave all recursion to processEvents until
- // processEvents is called again (e.g. from a QEventLoop that
- // was not yet told to quit:
- interrupt();
- }
-
return retVal;
}
@@ -729,39 +743,60 @@ void QEventDispatcherMac::flush()
*****************************************************************************/
MacTimerHash QEventDispatcherMacPrivate::macTimerHash;
bool QEventDispatcherMacPrivate::blockSendPostedEvents = false;
+bool QEventDispatcherMacPrivate::interrupt = false;
#ifdef QT_MAC_USE_COCOA
QStack<QCocoaModalSessionInfo> QEventDispatcherMacPrivate::cocoaModalSessionStack;
bool QEventDispatcherMacPrivate::currentExecIsNSAppRun = false;
+bool QEventDispatcherMacPrivate::modalSessionsTemporarilyStopped = false;
bool QEventDispatcherMacPrivate::nsAppRunCalledByQt = false;
+bool QEventDispatcherMacPrivate::cleanupModalSessionsNeeded = false;
NSModalSession QEventDispatcherMacPrivate::currentModalSessionCached = 0;
-int QEventDispatcherMacPrivate::activeModalSessionCount()
+void QEventDispatcherMacPrivate::ensureNSAppInitialized()
{
- // Returns the number of modal sessions created
- // (and not just pushed onto the stack, pending to be created)
- int count = 0;
- for (int i=cocoaModalSessionStack.size()-1; i>=0; --i) {
- QCocoaModalSessionInfo &info = cocoaModalSessionStack[i];
- if (info.session)
- ++count;
- }
- return count;
+ // Some elements in Cocoa require NSApplication to be running before
+ // they get fully initialized, in particular the menu bar. This
+ // function is intended for cases where a dialog is told to execute before
+ // QApplication::exec is called, or the application spins the events loop
+ // manually rather than calling QApplication:exec.
+ // The function makes sure that NSApplication starts running, but stops
+ // it again as soon as the send posted events callback is called. That way
+ // we let Cocoa finish the initialization it seems to need. We'll only
+ // apply this trick at most once for any application, and we avoid doing it
+ // for the common case where main just starts QApplication::exec.
+ if (nsAppRunCalledByQt || [NSApp isRunning])
+ return;
+ nsAppRunCalledByQt = true;
+ QBoolBlocker block1(interrupt, true);
+ QBoolBlocker block2(currentExecIsNSAppRun, true);
+ [NSApp run];
}
void QEventDispatcherMacPrivate::temporarilyStopAllModalSessions()
{
- // Stop all created modal session, and as such, make then
- // pending again. The next call to currentModalSession will
- // recreate the session on top again:
+ // Flush, and Stop, all created modal session, and as
+ // such, make them pending again. The next call to
+ // currentModalSession will recreate them again. The
+ // reason to stop all session like this is that otherwise
+ // a call [NSApp stop] would not stop NSApp, but rather
+ // the current modal session. So if we need to stop NSApp
+ // we need to stop all the modal session first. To avoid changing
+ // the stacking order of the windows while doing so, we put
+ // up a block that is used in QCocoaWindow and QCocoaPanel:
+ QBoolBlocker block1(blockSendPostedEvents, true);
+ QBoolBlocker block2(qt_blockCocoaSettingModalWindowLevel, true);
+
int stackSize = cocoaModalSessionStack.size();
for (int i=stackSize-1; i>=0; --i) {
QCocoaModalSessionInfo &info = cocoaModalSessionStack[i];
if (info.session) {
+ [NSApp runModalSession:info.session];
[NSApp endModalSession:info.session];
info.session = 0;
}
}
+ modalSessionsTemporarilyStopped = true;
currentModalSessionCached = 0;
}
@@ -775,23 +810,6 @@ NSModalSession QEventDispatcherMacPrivate::currentModalSession()
if (cocoaModalSessionStack.isEmpty())
return 0;
- // Since this code will end up calling our Qt event handler
- // (also from beginModalSessionForWindow), we need to block
- // that to avoid side effects of events beeing delivered:
- QBoolBlocker block(blockSendPostedEvents, true);
-
- if (![NSApp isRunning]) {
- // Sadly, we need to introduce this little event flush
- // to stop dialogs from blinking/poping in front if a
- // modal session restart was needed:
- while (NSEvent *event = [NSApp nextEventMatchingMask:0
- untilDate:nil
- inMode:NSDefaultRunLoopMode
- dequeue: YES]) {
- qt_mac_send_event(0, event, 0);
- }
- }
-
int sessionCount = cocoaModalSessionStack.size();
for (int i=0; i<sessionCount; ++i) {
QCocoaModalSessionInfo &info = cocoaModalSessionStack[i];
@@ -804,11 +822,28 @@ NSModalSession QEventDispatcherMacPrivate::currentModalSession()
NSWindow *window = qt_mac_window_for(info.widget);
if (!window)
continue;
+
+ ensureNSAppInitialized();
+ QBoolBlocker block1(blockSendPostedEvents, true);
info.session = [NSApp beginModalSessionForWindow:window];
}
currentModalSessionCached = info.session;
}
+ if (modalSessionsTemporarilyStopped && currentModalSessionCached) {
+ // After a call to temporarilyStopAllModalSessions, cocoa have
+ // now posted events to restore ended modal session windows to
+ // the correct window level. Those events will be processed
+ // _after_ our new calls to beginModalSessionForWindow have
+ // taken effect, which will end up stacking the windows wrong on
+ // screen. To work around this, we block cocoa from changing the
+ // stacking order of the windows, and flush out the pending events
+ // (the block is used in QCocoaWindow and QCocoaPanel):
+ QBoolBlocker block1(blockSendPostedEvents, true);
+ QBoolBlocker block2(qt_blockCocoaSettingModalWindowLevel, true);
+ [NSApp runModalSession:currentModalSessionCached];
+ }
+ modalSessionsTemporarilyStopped = false;
return currentModalSessionCached;
}
@@ -844,6 +879,34 @@ void QEventDispatcherMacPrivate::updateChildrenWorksWhenModal()
}
}
+void QEventDispatcherMacPrivate::cleanupModalSessions()
+{
+ // Go through the list of modal sessions, and end those
+ // that no longer has a widget assosiated; no widget means
+ // the the session has logically ended. The reason we wait like
+ // this to actually end the sessions for real (rather than at the
+ // point they were marked as stopped), is that ending a session
+ // when no other session runs below it on the stack will make cocoa
+ // drop some events on the floor.
+ QMacCocoaAutoReleasePool pool;
+ int stackSize = cocoaModalSessionStack.size();
+
+ for (int i=stackSize-1; i>=0; --i) {
+ QCocoaModalSessionInfo &info = cocoaModalSessionStack[i];
+ if (info.widget) {
+ currentModalSessionCached = info.session;
+ break;
+ }
+ cocoaModalSessionStack.remove(i);
+ currentModalSessionCached = 0;
+ if (info.session)
+ [NSApp endModalSession:info.session];
+ }
+
+ updateChildrenWorksWhenModal();
+ cleanupModalSessionsNeeded = false;
+}
+
void QEventDispatcherMacPrivate::beginModalSession(QWidget *widget)
{
// Add a new, empty (null), NSModalSession to the stack.
@@ -852,7 +915,7 @@ void QEventDispatcherMacPrivate::beginModalSession(QWidget *widget)
// is non-zero, and the session pointer is zero (it will become active upon a call to
// 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 endModalSession().
+ // stopped in cleanupModalSessions()).
QCocoaModalSessionInfo info = {widget, 0};
cocoaModalSessionStack.push(info);
updateChildrenWorksWhenModal();
@@ -869,38 +932,21 @@ void QEventDispatcherMacPrivate::endModalSession(QWidget *widget)
int stackSize = cocoaModalSessionStack.size();
for (int i=stackSize-1; i>=0; --i) {
QCocoaModalSessionInfo &info = cocoaModalSessionStack[i];
- if (info.widget == widget)
+ if (info.widget == widget) {
info.widget = 0;
- }
-
- // Now we stop, and remove, all sessions marked as pending
- // to be stopped on _top_ of the stack, if any:
- bool needToInterruptEventDispatcher = false;
- bool needToUpdateChildrenWorksWhenModal = false;
-
- for (int i=stackSize-1; i>=0; --i) {
- QCocoaModalSessionInfo &info = cocoaModalSessionStack[i];
- if (info.widget)
- break;
- cocoaModalSessionStack.remove(i);
- needToUpdateChildrenWorksWhenModal = true;
- currentModalSessionCached = 0;
- if (info.session) {
- [NSApp endModalSession:info.session];
- needToInterruptEventDispatcher = true;
+ if (i == stackSize-1) {
+ // The top sessions ended. Interrupt the event dispatcher
+ // to start spinning the correct session immidiatly:
+ cleanupModalSessionsNeeded = true;
+ QEventDispatcherMac::instance()->interrupt();
+ }
}
}
-
- if (needToUpdateChildrenWorksWhenModal)
- updateChildrenWorksWhenModal();
- if (needToInterruptEventDispatcher)
- QEventDispatcherMac::instance()->interrupt();
}
#endif
QEventDispatcherMacPrivate::QEventDispatcherMacPrivate()
- : interrupt(false)
{
}
@@ -959,13 +1005,39 @@ Boolean QEventDispatcherMacPrivate::postedEventSourceEqualCallback(const void *i
inline static void processPostedEvents(QEventDispatcherMacPrivate *const d, const bool blockSendPostedEvents)
{
- if (blockSendPostedEvents || d->interrupt) {
+ if (blockSendPostedEvents) {
+ // We're told to not send posted events (because the event dispatcher
+ // is currently working on setting up the correct session to run). But
+ // we still need to make sure that we don't fall asleep until pending events
+ // are sendt, so we just signal this need, and return:
CFRunLoopSourceSignal(d->postedEventsSource);
- } else {
- if (!d->threadData->canWait || (d->serialNumber != d->lastSerial)) {
- d->lastSerial = d->serialNumber;
- QApplicationPrivate::sendPostedEvents(0, 0, d->threadData);
+ return;
+ }
+
+#ifdef QT_MAC_USE_COCOA
+ if (d->cleanupModalSessionsNeeded)
+ d->cleanupModalSessions();
+#endif
+
+ if (d->interrupt) {
+#ifdef QT_MAC_USE_COCOA
+ if (d->currentExecIsNSAppRun) {
+ // The event dispatcher has been interrupted. But since
+ // [NSApplication run] is running the event loop, we
+ // delayed stopping it until now (to let cocoa process
+ // pending cocoa events first).
+ if (d->currentModalSessionCached)
+ d->temporarilyStopAllModalSessions();
+ [NSApp stop:NSApp];
+ d->cancelWaitForMoreEvents();
}
+#endif
+ return;
+ }
+
+ if (!d->threadData->canWait || (d->serialNumber != d->lastSerial)) {
+ d->lastSerial = d->serialNumber;
+ QApplicationPrivate::sendPostedEvents(0, 0, d->threadData);
}
}
@@ -975,6 +1047,9 @@ void QEventDispatcherMacPrivate::firstLoopEntry(CFRunLoopObserverRef ref,
{
Q_UNUSED(ref);
Q_UNUSED(activity);
+#ifdef QT_MAC_USE_COCOA
+ QApplicationPrivate::qt_initAfterNSAppStarted();
+#endif
processPostedEvents(static_cast<QEventDispatcherMacPrivate *>(info), blockSendPostedEvents);
}
@@ -983,6 +1058,19 @@ void QEventDispatcherMacPrivate::postedEventsSourcePerformCallback(void *info)
processPostedEvents(static_cast<QEventDispatcherMacPrivate *>(info), blockSendPostedEvents);
}
+#ifdef QT_MAC_USE_COCOA
+void QEventDispatcherMacPrivate::cancelWaitForMoreEvents()
+{
+ // In case the event dispatcher is waiting for more
+ // events somewhere, we post a dummy event to wake it up:
+ QMacCocoaAutoReleasePool pool;
+ static const short NSAppShouldStopForQt = SHRT_MAX;
+ [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined location:NSZeroPoint
+ modifierFlags:0 timestamp:0. windowNumber:0 context:0
+ subtype:NSAppShouldStopForQt data1:0 data2:0] atStart:NO];
+}
+#endif
+
void QEventDispatcherMac::interrupt()
{
Q_D(QEventDispatcherMac);
@@ -992,20 +1080,14 @@ void QEventDispatcherMac::interrupt()
#ifndef QT_MAC_USE_COCOA
CFRunLoopStop(mainRunLoop());
#else
- QMacCocoaAutoReleasePool pool;
- // In case we wait for more events inside
- // processEvents (or NSApp run), post a dummy to wake it up:
- static const short NSAppShouldStopForQt = SHRT_MAX;
- [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined location:NSZeroPoint
- modifierFlags:0 timestamp:0. windowNumber:0 context:0
- subtype:NSAppShouldStopForQt data1:0 data2:0] atStart:NO];
-
- if (d->activeModalSessionCount() == 0) {
- // We should only stop NSApp if we actually started it (and
- // not some 3rd party application, e.g. if we are a plugin).
- if (d->nsAppRunCalledByQt)
- [NSApp stop:NSApp];
- }
+ // We do nothing more here than setting d->interrupt = true, and
+ // poke the event loop if it is sleeping. Actually stopping
+ // NSApp, or the current modal session, is done inside the send
+ // posted events callback. We do this to ensure that all current pending
+ // cocoa events gets delivered before we stop. Otherwise, if we now stop
+ // the last event loop recursion, cocoa will just drop pending posted
+ // events on the floor before we get a chance to reestablish a new session.
+ d->cancelWaitForMoreEvents();
#endif
}
@@ -1046,17 +1128,18 @@ QEventDispatcherMac::~QEventDispatcherMac()
CFRelease(d->firstTimeObserver);
}
-/////////////////////////////////////////////////////////////////////////////
-
#ifdef QT_MAC_USE_COCOA
QtMacInterruptDispatcherHelp* QtMacInterruptDispatcherHelp::instance = 0;
QtMacInterruptDispatcherHelp::QtMacInterruptDispatcherHelp() : cancelled(false)
{
- // This is the whole point of encapsulation this code
- // inside a class; we can make the code (inside destructor)
- // execute on lower loop level:
+ // The whole point of this class is that we enable a way to interrupt
+ // the event dispatcher when returning back to a lower recursion level
+ // than where interruptLater was called. This is needed to detect if
+ // [NSApp run] should still be running at the recursion level it is at.
+ // Since the interrupt is canceled if processEvents is called before
+ // this object gets deleted, we also avoid interrupting unnecessary.
deleteLater();
}
@@ -1064,34 +1147,26 @@ QtMacInterruptDispatcherHelp::~QtMacInterruptDispatcherHelp()
{
if (cancelled)
return;
-
instance = 0;
-
- if (QEventDispatcherMacPrivate::currentExecIsNSAppRun) {
- int activeCount = QEventDispatcherMacPrivate::activeModalSessionCount();
- if (activeCount > 0) {
- // The problem we now have hit: [NSApp stop] will not stop NSApp
- // if a session is active; it will stop the session instead.
- // So to stop NSApp, we need to temporarily stop all the
- // sessions, then stop NSApp, then restart the session on top again.
- // We need to do this to ensure that we're not stuck inside
- // [NSApp run] when we really should be running a modal session:
- QEventDispatcherMacPrivate::temporarilyStopAllModalSessions();
- }
- }
- // Always interrupt once more in case the modal session stack changed
- // while processEvents was called manually from within the application:
QEventDispatcherMac::instance()->interrupt();
}
-void QtMacInterruptDispatcherHelp::interruptLater() {
- if (instance) {
- instance->cancelled = true;
- delete instance;
- }
+void QtMacInterruptDispatcherHelp::cancelInterruptLater()
+{
+ if (!instance)
+ return;
+ instance->cancelled = true;
+ delete instance;
+ instance = 0;
+}
+
+void QtMacInterruptDispatcherHelp::interruptLater()
+{
+ cancelInterruptLater();
instance = new QtMacInterruptDispatcherHelp;
}
#endif
QT_END_NAMESPACE
+
diff --git a/src/gui/kernel/qeventdispatcher_mac_p.h b/src/gui/kernel/qeventdispatcher_mac_p.h
index a335f162fd..e932532346 100644
--- a/src/gui/kernel/qeventdispatcher_mac_p.h
+++ b/src/gui/kernel/qeventdispatcher_mac_p.h
@@ -174,13 +174,17 @@ public:
static QStack<QCocoaModalSessionInfo> cocoaModalSessionStack;
static bool currentExecIsNSAppRun;
static bool nsAppRunCalledByQt;
+ static bool cleanupModalSessionsNeeded;
+ static bool modalSessionsTemporarilyStopped;
static NSModalSession currentModalSessionCached;
- static void updateChildrenWorksWhenModal();
static NSModalSession currentModalSession();
- static int activeModalSessionCount();
+ static void updateChildrenWorksWhenModal();
static void temporarilyStopAllModalSessions();
static void beginModalSession(QWidget *widget);
static void endModalSession(QWidget *widget);
+ static void cancelWaitForMoreEvents();
+ static void cleanupModalSessions();
+ static void ensureNSAppInitialized();
#endif
MacSocketHash macSockets;
@@ -190,7 +194,7 @@ public:
CFRunLoopObserverRef firstTimeObserver;
QAtomicInt serialNumber;
int lastSerial;
- bool interrupt;
+ static bool interrupt;
private:
static Boolean postedEventSourceEqualCallback(const void *info1, const void *info2);
static void postedEventsSourcePerformCallback(void *info);
@@ -211,6 +215,7 @@ class QtMacInterruptDispatcherHelp : public QObject
public:
static void interruptLater();
+ static void cancelInterruptLater();
};
#endif
diff --git a/src/gui/kernel/qguieventdispatcher_glib.cpp b/src/gui/kernel/qguieventdispatcher_glib.cpp
index 7b30741e86..ac2b5f787c 100644
--- a/src/gui/kernel/qguieventdispatcher_glib.cpp
+++ b/src/gui/kernel/qguieventdispatcher_glib.cpp
@@ -216,4 +216,9 @@ void QGuiEventDispatcherGlib::startingUp()
g_source_add_poll(&d->x11EventSource->source, &d->x11EventSource->pollfd);
}
+void QGuiEventDispatcherGlib::flush()
+{
+ XFlush(X11->display);
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qguieventdispatcher_glib_p.h b/src/gui/kernel/qguieventdispatcher_glib_p.h
index ff778cc744..758650b434 100644
--- a/src/gui/kernel/qguieventdispatcher_glib_p.h
+++ b/src/gui/kernel/qguieventdispatcher_glib_p.h
@@ -71,6 +71,7 @@ public:
bool processEvents(QEventLoop::ProcessEventsFlags flags);
void startingUp();
+ void flush();
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp
index 2a13546061..99bf971ab8 100644
--- a/src/gui/kernel/qkeysequence.cpp
+++ b/src/gui/kernel/qkeysequence.cpp
@@ -861,6 +861,8 @@ QKeySequence::QKeySequence()
Up to four key codes may be entered by separating them with
commas, e.g. "Alt+X,Ctrl+S,Q".
+ \a key should be in NativeText format.
+
This constructor is typically used with \link QObject::tr() tr
\endlink(), so that shortcut keys can be replaced in
translations:
@@ -877,6 +879,16 @@ QKeySequence::QKeySequence(const QString &key)
}
/*!
+ \since 4.x
+ Creates a key sequence from the \a key string based on \a format.
+*/
+QKeySequence::QKeySequence(const QString &key, QKeySequence::SequenceFormat format)
+{
+ d = new QKeySequencePrivate();
+ assign(key, format);
+}
+
+/*!
Constructs a key sequence with up to 4 keys \a k1, \a k2,
\a k3 and \a k4.
@@ -1055,9 +1067,24 @@ QKeySequence QKeySequence::mnemonic(const QString &text)
contain up to four key codes, provided they are separated by a
comma; for example, "Alt+X,Ctrl+S,Z". The return value is the
number of key codes added.
+ \a keys should be in NativeText format.
*/
int QKeySequence::assign(const QString &ks)
{
+ return assign(ks, NativeText);
+}
+
+/*!
+ \fn int QKeySequence::assign(const QString &keys, QKeySequence::SequenceFormat format)
+ \since 4.x
+
+ Adds the given \a keys to the key sequence (based on \a format).
+ \a keys may contain up to four key codes, provided they are
+ separated by a comma; for example, "Alt+X,Ctrl+S,Z". The return
+ value is the number of key codes added.
+*/
+int QKeySequence::assign(const QString &ks, QKeySequence::SequenceFormat format)
+{
QString keyseq = ks;
QString part;
int n = 0;
@@ -1086,7 +1113,7 @@ int QKeySequence::assign(const QString &ks)
}
part = keyseq.left(-1 == p ? keyseq.length() : p - diff);
keyseq = keyseq.right(-1 == p ? 0 : keyseq.length() - (p + 1));
- d->key[n] = decodeString(part);
+ d->key[n] = QKeySequencePrivate::decodeString(part, format);
++n;
}
return n;
@@ -1557,12 +1584,7 @@ QString QKeySequence::toString(SequenceFormat format) const
*/
QKeySequence QKeySequence::fromString(const QString &str, SequenceFormat format)
{
- QStringList sl = str.split(QLatin1String(", "));
- int keys[4] = {0, 0, 0, 0};
- int total = qMin(sl.count(), 4);
- for (int i = 0; i < total; ++i)
- keys[i] = QKeySequencePrivate::decodeString(sl[i], format);
- return QKeySequence(keys[0], keys[1], keys[2], keys[3]);
+ return QKeySequence(str, format);
}
/*****************************************************************************
diff --git a/src/gui/kernel/qkeysequence.h b/src/gui/kernel/qkeysequence.h
index 1409e28f3b..5a973e398c 100644
--- a/src/gui/kernel/qkeysequence.h
+++ b/src/gui/kernel/qkeysequence.h
@@ -141,8 +141,14 @@ public:
Quit
};
+ enum SequenceFormat {
+ NativeText,
+ PortableText
+ };
+
QKeySequence();
QKeySequence(const QString &key);
+ QKeySequence(const QString &key, SequenceFormat format);
QKeySequence(int k1, int k2 = 0, int k3 = 0, int k4 = 0);
QKeySequence(const QKeySequence &ks);
QKeySequence(StandardKey key);
@@ -160,11 +166,6 @@ public:
#endif
};
- enum SequenceFormat {
- NativeText,
- PortableText
- };
-
QString toString(SequenceFormat format = PortableText) const;
static QKeySequence fromString(const QString &str, SequenceFormat format = PortableText);
@@ -194,6 +195,7 @@ private:
static int decodeString(const QString &ks);
static QString encodeString(int key);
int assign(const QString &str);
+ int assign(const QString &str, SequenceFormat format);
void setKey(int key, int index);
QKeySequencePrivate *d;
diff --git a/src/gui/kernel/qmime_mac.cpp b/src/gui/kernel/qmime_mac.cpp
index 071f80df1f..c6fd184447 100644
--- a/src/gui/kernel/qmime_mac.cpp
+++ b/src/gui/kernel/qmime_mac.cpp
@@ -154,6 +154,7 @@ CFStringRef qt_mac_mime_typeUTI = CFSTR("com.pasteboard.trolltech.marker");
\i public.url - converts to "text/uri-list"
\i public.file-url - converts to "text/uri-list"
\i public.tiff - converts to "application/x-qt-image"
+ \i public.vcard - converts to "text/plain"
\i com.apple.traditional-mac-plain-text - converts to "text/plain"
\i com.apple.pict - converts to "application/x-qt-image"
\endlist
@@ -909,6 +910,61 @@ QList<QByteArray> QMacPasteboardMimeUrl::convertFromMime(const QString &mime, QV
return ret;
}
+class QMacPasteboardMimeVCard : public QMacPasteboardMime
+{
+public:
+ QMacPasteboardMimeVCard() : QMacPasteboardMime(MIME_ALL){ }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimeVCard::convertorName()
+{
+ return QString("VCard");
+}
+
+bool QMacPasteboardMimeVCard::canConvert(const QString &mime, QString flav)
+{
+ return mimeFor(flav) == mime;
+}
+
+QString QMacPasteboardMimeVCard::flavorFor(const QString &mime)
+{
+ if(mime.startsWith(QLatin1String("text/plain")))
+ return QLatin1String("public.vcard");
+ return QString();
+}
+
+QString QMacPasteboardMimeVCard::mimeFor(QString flav)
+{
+ if (flav == QLatin1String("public.vcard"))
+ return QLatin1String("text/plain");
+ return QString();
+}
+
+QVariant QMacPasteboardMimeVCard::convertToMime(const QString &mime, QList<QByteArray> data, QString)
+{
+ QByteArray cards;
+ if (mime == QLatin1String("text/plain")) {
+ for (int i=0; i<data.size(); ++i)
+ cards += data[i];
+ }
+ return QVariant(cards);
+}
+
+QList<QByteArray> QMacPasteboardMimeVCard::convertFromMime(const QString &mime, QVariant data, QString)
+{
+ QList<QByteArray> ret;
+ if (mime == QLatin1String("text/plain"))
+ ret.append(data.toString().toUtf8());
+ return ret;
+}
+
#ifdef QT3_SUPPORT
class QMacPasteboardMimeQt3Any : public QMacPasteboardMime {
private:
@@ -1116,6 +1172,7 @@ void QMacPasteboardMime::initialize()
new QMacPasteboardMimeFileUri;
new QMacPasteboardMimeUrl;
new QMacPasteboardMimeTypeName;
+ new QMacPasteboardMimeVCard;
//make sure our "non-standard" types are always last! --Sam
new QMacPasteboardMimeAny;
#ifdef QT3_SUPPORT
diff --git a/src/gui/kernel/qnsthemeframe_mac_p.h b/src/gui/kernel/qnsthemeframe_mac_p.h
index 77a6963f10..d061b1bfbe 100644
--- a/src/gui/kernel/qnsthemeframe_mac_p.h
+++ b/src/gui/kernel/qnsthemeframe_mac_p.h
@@ -157,7 +157,7 @@
- (void)resetCursorRects;
- (char)shouldBeTreatedAsInkEvent:fp8;
- (char)_shouldBeTreatedAsInkEventInInactiveWindow:fp8;
-- hitTest:(struct _NSPoint)fp8;
+//- hitTest:(struct _NSPoint)fp8; // collides with hittest in qcocoasharedwindowmethods_mac_p.h
- (NSRect)_leftGroupRect;
- (NSRect)_rightGroupRect;
- (void)_updateWidgets;
diff --git a/src/gui/kernel/qsound_s60.cpp b/src/gui/kernel/qsound_s60.cpp
index 1832b855d3..df2830bc4e 100644
--- a/src/gui/kernel/qsound_s60.cpp
+++ b/src/gui/kernel/qsound_s60.cpp
@@ -51,7 +51,7 @@
#include <private/qcore_symbian_p.h>
#include <e32std.h>
-#include <MdaAudioSamplePlayer.h>
+#include <mdaaudiosampleplayer.h>
QT_BEGIN_NAMESPACE
diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm
index 65c04e5a47..4e51cf44c2 100644
--- a/src/gui/kernel/qt_cocoa_helpers_mac.mm
+++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm
@@ -1281,6 +1281,21 @@ void qt_cocoaChangeOverrideCursor(const QCursor &cursor)
}
#endif
+@implementation DebugNSApplication {
+}
+- (void)sendEvent:(NSEvent *)event
+{
+ NSLog(@"NSAppDebug: sendEvent: %@", event);
+ return [super sendEvent:event];
+}
+
+- (BOOL)sendAction:(SEL)anAction to:(id)aTarget from:(id)sender
+{
+ NSLog(@"NSAppDebug: sendAction: %s to %@ from %@", anAction, aTarget, sender);
+ return [super sendAction:anAction to:aTarget from:sender];
+}
+@end
+
QMacCocoaAutoReleasePool::QMacCocoaAutoReleasePool()
{
#ifndef QT_MAC_USE_COCOA
diff --git a/src/gui/kernel/qt_cocoa_helpers_mac_p.h b/src/gui/kernel/qt_cocoa_helpers_mac_p.h
index 6f0c4ce1e3..ace8255fde 100644
--- a/src/gui/kernel/qt_cocoa_helpers_mac_p.h
+++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h
@@ -181,6 +181,10 @@ inline QString qt_mac_NSStringToQString(const NSString *nsstr)
inline NSString *qt_mac_QStringToNSString(const QString &qstr)
{ return [reinterpret_cast<const NSString *>(QCFString::toCFStringRef(qstr)) autorelease]; }
+
+@interface DebugNSApplication : NSApplication {}
+@end
+
#endif
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qt_x11_p.h b/src/gui/kernel/qt_x11_p.h
index d110084679..b2ce754bb1 100644
--- a/src/gui/kernel/qt_x11_p.h
+++ b/src/gui/kernel/qt_x11_p.h
@@ -331,7 +331,7 @@ struct QXdndDropTransaction
class QMimeData;
struct QX11Data;
-extern QX11Data *qt_x11Data;
+extern Q_GUI_EXPORT QX11Data *qt_x11Data;
enum DesktopEnvironment {
DE_UNKNOWN,
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index 2a19d233f8..1e92507490 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -4876,90 +4876,7 @@ void QWidget::unsetCursor()
void QWidget::render(QPaintDevice *target, const QPoint &targetOffset,
const QRegion &sourceRegion, RenderFlags renderFlags)
{
- Q_D(QWidget);
- if (!target) {
- qWarning("QWidget::render: null pointer to paint device");
- return;
- }
-
- const bool inRenderWithPainter = d->extra && d->extra->inRenderWithPainter;
- QRegion paintRegion = !inRenderWithPainter ? d->prepareToRender(sourceRegion, renderFlags)
- : sourceRegion;
- if (paintRegion.isEmpty())
- return;
-
-#ifndef Q_WS_MAC
- QPainter *oldSharedPainter = inRenderWithPainter ? d->sharedPainter() : 0;
-
- // Use the target's shared painter if set (typically set when doing
- // "other->render(widget);" in the widget's paintEvent.
- if (target->devType() == QInternal::Widget) {
- QWidgetPrivate *targetPrivate = static_cast<QWidget *>(target)->d_func();
- if (targetPrivate->extra && targetPrivate->extra->inRenderWithPainter) {
- QPainter *targetPainter = targetPrivate->sharedPainter();
- if (targetPainter && targetPainter->isActive())
- d->setSharedPainter(targetPainter);
- }
- }
-#endif
-
- // Use the target's redirected device if set and adjust offset and paint
- // region accordingly. This is typically the case when people call render
- // from the paintEvent.
- QPoint offset = targetOffset;
- offset -= paintRegion.boundingRect().topLeft();
- QPoint redirectionOffset;
- QPaintDevice *redirected = 0;
-
- if (target->devType() == QInternal::Widget)
- redirected = static_cast<QWidget *>(target)->d_func()->redirected(&redirectionOffset);
- if (!redirected)
- redirected = QPainter::redirected(target, &redirectionOffset);
-
- if (redirected) {
- target = redirected;
- offset -= redirectionOffset;
- }
-
- if (!inRenderWithPainter) { // Clip handled by shared painter (in qpainter.cpp).
- if (QPaintEngine *targetEngine = target->paintEngine()) {
- const QRegion targetSystemClip = targetEngine->systemClip();
- if (!targetSystemClip.isEmpty())
- paintRegion &= targetSystemClip.translated(-offset);
- }
- }
-
- // Set backingstore flags.
- int flags = QWidgetPrivate::DrawPaintOnScreen | QWidgetPrivate::DrawInvisible;
- if (renderFlags & DrawWindowBackground)
- flags |= QWidgetPrivate::DrawAsRoot;
-
- if (renderFlags & DrawChildren)
- flags |= QWidgetPrivate::DrawRecursive;
- else
- flags |= QWidgetPrivate::DontSubtractOpaqueChildren;
-
-#ifdef Q_WS_QWS
- flags |= QWidgetPrivate::DontSetCompositionMode;
-#endif
-
- if (target->devType() == QInternal::Printer) {
- QPainter p(target);
- d->render_helper(&p, targetOffset, paintRegion, renderFlags);
- return;
- }
-
-#ifndef Q_WS_MAC
- // Render via backingstore.
- d->drawWidget(target, paintRegion, offset, flags, d->sharedPainter());
-
- // Restore shared painter.
- if (oldSharedPainter)
- d->setSharedPainter(oldSharedPainter);
-#else
- // Render via backingstore (no shared painter).
- d->drawWidget(target, paintRegion, offset, flags, 0);
-#endif
+ d_func()->render(target, targetOffset, sourceRegion, renderFlags, false);
}
/*!
@@ -5405,6 +5322,97 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
}
}
+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;
+ }
+
+ const bool inRenderWithPainter = extra && extra->inRenderWithPainter;
+ QRegion paintRegion = !inRenderWithPainter && !readyToRender
+ ? prepareToRender(sourceRegion, renderFlags)
+ : sourceRegion;
+ if (paintRegion.isEmpty())
+ return;
+
+#ifndef Q_WS_MAC
+ QPainter *oldSharedPainter = inRenderWithPainter ? sharedPainter() : 0;
+
+ // Use the target's shared painter if set (typically set when doing
+ // "other->render(widget);" in the widget's paintEvent.
+ if (target->devType() == QInternal::Widget) {
+ QWidgetPrivate *targetPrivate = static_cast<QWidget *>(target)->d_func();
+ if (targetPrivate->extra && targetPrivate->extra->inRenderWithPainter) {
+ QPainter *targetPainter = targetPrivate->sharedPainter();
+ if (targetPainter && targetPainter->isActive())
+ setSharedPainter(targetPainter);
+ }
+ }
+#endif
+
+ // Use the target's redirected device if set and adjust offset and paint
+ // region accordingly. This is typically the case when people call render
+ // from the paintEvent.
+ QPoint offset = targetOffset;
+ offset -= paintRegion.boundingRect().topLeft();
+ QPoint redirectionOffset;
+ QPaintDevice *redirected = 0;
+
+ if (target->devType() == QInternal::Widget)
+ redirected = static_cast<QWidget *>(target)->d_func()->redirected(&redirectionOffset);
+ if (!redirected)
+ redirected = QPainter::redirected(target, &redirectionOffset);
+
+ if (redirected) {
+ target = redirected;
+ offset -= redirectionOffset;
+ }
+
+ if (!inRenderWithPainter) { // Clip handled by shared painter (in qpainter.cpp).
+ if (QPaintEngine *targetEngine = target->paintEngine()) {
+ const QRegion targetSystemClip = targetEngine->systemClip();
+ if (!targetSystemClip.isEmpty())
+ paintRegion &= targetSystemClip.translated(-offset);
+ }
+ }
+
+ // Set backingstore flags.
+ int flags = DrawPaintOnScreen | DrawInvisible;
+ if (renderFlags & QWidget::DrawWindowBackground)
+ flags |= DrawAsRoot;
+
+ if (renderFlags & QWidget::DrawChildren)
+ flags |= DrawRecursive;
+ else
+ flags |= DontSubtractOpaqueChildren;
+
+#ifdef Q_WS_QWS
+ flags |= DontSetCompositionMode;
+#endif
+
+ if (target->devType() == QInternal::Printer) {
+ QPainter p(target);
+ render_helper(&p, targetOffset, paintRegion, renderFlags);
+ return;
+ }
+
+#ifndef Q_WS_MAC
+ // Render via backingstore.
+ drawWidget(target, paintRegion, offset, flags, sharedPainter());
+
+ // Restore shared painter.
+ if (oldSharedPainter)
+ setSharedPainter(oldSharedPainter);
+#else
+ // Render via backingstore (no shared painter).
+ drawWidget(target, paintRegion, offset, flags, 0);
+#endif
+}
+
void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& siblings, int index, const QRegion &rgn,
const QPoint &offset, int flags
#ifdef Q_BACKINGSTORE_SUBSURFACES
@@ -7592,23 +7600,21 @@ bool QWidgetPrivate::close_helper(CloseMode mode)
if (isMain)
QApplication::quit();
#endif
- // Attempt to close the application only if this widget has the
- // WA_QuitOnClose flag set set and has a non-visible parent
- quitOnClose = quitOnClose && (parentWidget.isNull() || !parentWidget->isVisible() || parentWidget->testAttribute(Qt::WA_DontShowOnScreen));
+ // Attempt to close the application only if this has WA_QuitOnClose set and a non-visible parent
+ quitOnClose = quitOnClose && (parentWidget.isNull() || !parentWidget->isVisible());
if (quitOnClose) {
- // If there is no non-withdrawn primary window left (except
- // the ones without QuitOnClose or with WA_DontShowOnScreen),
- // we emit the lastWindowClosed signal
+ /* if there is no non-withdrawn primary window left (except
+ the ones without QuitOnClose), we emit the lastWindowClosed
+ signal */
QWidgetList list = QApplication::topLevelWidgets();
bool lastWindowClosed = true;
for (int i = 0; i < list.size(); ++i) {
QWidget *w = list.at(i);
- if ((w->isVisible() && !w->testAttribute(Qt::WA_DontShowOnScreen))
- && !w->parentWidget() && w->testAttribute(Qt::WA_QuitOnClose)) {
- lastWindowClosed = false;
- break;
- }
+ if (!w->isVisible() || w->parentWidget() || !w->testAttribute(Qt::WA_QuitOnClose))
+ continue;
+ lastWindowClosed = false;
+ break;
}
if (lastWindowClosed)
QApplicationPrivate::emitLastWindowClosed();
diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm
index 9e7517f013..a5633d3f1d 100644
--- a/src/gui/kernel/qwidget_mac.mm
+++ b/src/gui/kernel/qwidget_mac.mm
@@ -1917,13 +1917,15 @@ void QWidgetPrivate::determineWindowClass()
wclass = kDocumentWindowClass;
else if(popup || (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5 && type == Qt::SplashScreen))
wclass = kModalWindowClass;
- else if(q->testAttribute(Qt::WA_ShowModal) || type == Qt::Dialog)
+ else if(type == Qt::Dialog)
wclass = kMovableModalWindowClass;
else if(type == Qt::ToolTip)
wclass = kHelpWindowClass;
else if(type == Qt::Tool || (QSysInfo::MacintoshVersion < QSysInfo::MV_10_5
&& type == Qt::SplashScreen))
wclass = kFloatingWindowClass;
+ else if(q->testAttribute(Qt::WA_ShowModal))
+ wclass = kMovableModalWindowClass;
else
wclass = kDocumentWindowClass;
@@ -2027,8 +2029,6 @@ void QWidgetPrivate::determineWindowClass()
for(int i = 0; tmp_wattr && known_attribs[i].name; i++) {
if((tmp_wattr & known_attribs[i].tag) == known_attribs[i].tag) {
tmp_wattr ^= known_attribs[i].tag;
- qDebug("Qt: internal: * %s %s", known_attribs[i].name,
- (GetAvailableWindowAttributes(wclass) & known_attribs[i].tag) ? "" : "(*)");
}
}
if(tmp_wattr)
@@ -2223,6 +2223,41 @@ void QWidgetPrivate::finishCreateWindow_sys_Carbon(OSWindowRef windowRef)
applyMaxAndMinSizeOnWindow();
}
#else // QT_MAC_USE_COCOA
+
+void QWidgetPrivate::setWindowLevel()
+{
+ Q_Q(QWidget);
+ const QWidget * const windowParent = q->window()->parentWidget();
+ const QWidget * const primaryWindow = windowParent ? windowParent->window() : 0;
+ NSInteger winLevel = -1;
+
+ if (q->windowType() == Qt::Popup) {
+ winLevel = NSPopUpMenuWindowLevel;
+ // Popup should be in at least the same level as its parent.
+ if (primaryWindow) {
+ OSWindowRef parentRef = qt_mac_window_for(primaryWindow);
+ winLevel = qMax([parentRef level], winLevel);
+ }
+ } else if (q->windowType() == Qt::Tool) {
+ winLevel = NSFloatingWindowLevel;
+ } else if (q->windowType() == Qt::Dialog) {
+ // Correct modality level (NSModalPanelWindowLevel) will be
+ // set by cocoa when creating a modal session later.
+ winLevel = NSNormalWindowLevel;
+ }
+
+ // StayOnTop window should appear above Tool windows.
+ if (data.window_flags & Qt::WindowStaysOnTopHint)
+ winLevel = NSPopUpMenuWindowLevel;
+ // Tooltips should appear above StayOnTop windows.
+ if (q->windowType() == Qt::ToolTip)
+ winLevel = NSScreenSaverWindowLevel;
+ // All other types are Normal level.
+ if (winLevel == -1)
+ winLevel = NSNormalWindowLevel;
+ [qt_mac_window_for(q) setLevel:winLevel];
+}
+
void QWidgetPrivate::finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ voidWindowRef)
{
Q_Q(QWidget);
@@ -2295,6 +2330,10 @@ void QWidgetPrivate::finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ voidWin
q->setAttribute(Qt::WA_WState_WindowOpacitySet, false);
}
+ if (qApp->overrideCursor())
+ [windowRef disableCursorRects];
+
+ setWindowLevel();
macUpdateHideOnSuspend();
macUpdateOpaqueSizeGrip();
macUpdateIgnoreMouseEvents();
@@ -2725,6 +2764,35 @@ void QWidgetPrivate::transferChildren()
}
}
+#ifdef QT_MAC_USE_COCOA
+void QWidgetPrivate::setSubWindowStacking(bool set)
+{
+ Q_Q(QWidget);
+ if (!q->isWindow() || !q->testAttribute(Qt::WA_WState_Created))
+ return;
+
+ if (QWidget *parent = q->parentWidget()) {
+ if (parent->testAttribute(Qt::WA_WState_Created)) {
+ if (set)
+ [qt_mac_window_for(parent) addChildWindow:qt_mac_window_for(q) ordered:NSWindowAbove];
+ else
+ [qt_mac_window_for(parent) removeChildWindow:qt_mac_window_for(q)];
+ }
+ }
+
+ QList<QWidget *> widgets = q->findChildren<QWidget *>();
+ for (int i=0; i<widgets.size(); ++i) {
+ QWidget *child = widgets.at(i);
+ if (child->isWindow() && child->testAttribute(Qt::WA_WState_Created)) {
+ if (set)
+ [qt_mac_window_for(q) addChildWindow:qt_mac_window_for(child) ordered:NSWindowAbove];
+ else
+ [qt_mac_window_for(q) removeChildWindow:qt_mac_window_for(child)];
+ }
+ }
+}
+#endif
+
void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
{
Q_Q(QWidget);
@@ -2879,7 +2947,6 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
current = current->parentWidget();
}
}
-
invalidateBuffer(q->rect());
qt_event_request_window_change(q);
}
@@ -3185,10 +3252,10 @@ void QWidget::activateWindow()
|| windowActive) {
#ifndef QT_MAC_USE_COCOA
ActivateWindow(win, true);
+ qApp->setActiveWindow(tlw);
#else
[win makeKeyWindow];
#endif
- qApp->setActiveWindow(tlw);
} else if(!isMinimized()) {
#ifndef QT_MAC_USE_COCOA
SelectWindow(win);
@@ -3341,13 +3408,23 @@ void QWidgetPrivate::show_sys()
#else
// sync the opacity value back (in case of a fade).
[window setAlphaValue:q->windowOpacity()];
- [window makeKeyAndOrderFront:window];
-
- // If this window is app modal, we need to start spinning
- // a modal session for it. Interrupting
- // the event dispatcher will make this happend:
- if (data.window_modality == Qt::ApplicationModal)
- QEventDispatcherMac::instance()->interrupt();
+ setSubWindowStacking(true);
+
+ QWidget *top = 0;
+ if (QApplicationPrivate::tryModalHelper(q, &top)) {
+ [window makeKeyAndOrderFront:window];
+ // If this window is app modal, we need to start spinning
+ // a modal session for it. Interrupting
+ // the event dispatcher will make this happend:
+ if (data.window_modality == Qt::ApplicationModal)
+ QEventDispatcherMac::instance()->interrupt();
+ } else {
+ // 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];
+ }
#endif
if (q->windowType() == Qt::Popup) {
if (q->focusWidget())
@@ -3366,8 +3443,6 @@ void QWidgetPrivate::show_sys()
} else if (!q->testAttribute(Qt::WA_ShowWithoutActivating)) {
#ifndef QT_MAC_USE_COCOA
qt_event_request_activate(q);
-#else
- [qt_mac_window_for(q) makeKeyWindow];
#endif
}
} else if(topData()->embedded || !q->parentWidget() || q->parentWidget()->isVisible()) {
@@ -3410,6 +3485,9 @@ void QWidgetPrivate::hide_sys()
QMacCocoaAutoReleasePool pool;
if(q->isWindow()) {
+#ifdef QT_MAC_USE_COCOA
+ setSubWindowStacking(false);
+#endif
OSWindowRef window = qt_mac_window_for(q);
if(qt_mac_is_macsheet(q)) {
#ifndef QT_MAC_USE_COCOA
@@ -3475,12 +3553,15 @@ void QWidgetPrivate::hide_sys()
}
#endif
}
- if(q->isActiveWindow() && !(q->windowType() == Qt::Popup)) {
+#ifndef QT_MAC_USE_COCOA
+ // If the window we now hide was the active window, we need
+ // to find, and activate another window on screen. NB: Cocoa takes care of this
+ // logic for us (and distinquishes between main windows and key windows)
+ if (q->isActiveWindow() && !(q->windowType() == Qt::Popup)) {
QWidget *w = 0;
if(q->parentWidget())
w = q->parentWidget()->window();
if(!w || (!w->isVisible() && !w->isMinimized())) {
-#ifndef QT_MAC_USE_COCOA
for (WindowPtr wp = GetFrontWindowOfClass(kMovableModalWindowClass, true);
wp; wp = GetNextWindowOfClass(wp, kMovableModalWindowClass, true)) {
if((w = qt_mac_find_window(wp)))
@@ -3500,24 +3581,12 @@ void QWidgetPrivate::hide_sys()
break;
}
}
-#else
- NSArray *windows = [NSApp windows];
- NSUInteger totalWindows = [windows count];
- for (NSUInteger i = 0; i < totalWindows; ++i) {
- OSWindowRef wp = [windows objectAtIndex:i];
- if ((w = qt_mac_find_window(wp)))
- break;
- }
-#endif
}
if(w && w->isVisible() && !w->isMinimized()) {
-#ifndef QT_MAC_USE_COCOA
- qt_event_request_activate(w);
-#else
- [qt_mac_window_for(w) makeKeyWindow];
-#endif
+ qt_event_request_activate(w);
}
}
+#endif
} else {
invalidateBuffer(q->rect());
#ifndef QT_MAC_USE_COCOA
@@ -4605,9 +4674,12 @@ void QWidgetPrivate::registerDropSite(bool on)
#ifndef QT_MAC_USE_COCOA
SetControlDragTrackingEnabled(qt_mac_nativeview_for(q), on);
#else
- NSView *view = qt_mac_nativeview_for(q);
- if (on && [view isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaView) class]]) {
- [static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(view) registerDragTypes];
+ NSWindow *win = qt_mac_window_for(q);
+ if (on) {
+ if ([win isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaWindow) class]])
+ [static_cast<QT_MANGLE_NAMESPACE(QCocoaWindow) *>(win) registerDragTypes];
+ else if ([win isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaPanel) class]])
+ [static_cast<QT_MANGLE_NAMESPACE(QCocoaPanel) *>(win) registerDragTypes];
}
#endif
}
@@ -4761,7 +4833,7 @@ void QWidgetPrivate::setModal_sys()
bool alreadySheet = [windowRef styleMask] & NSDocModalWindowMask;
if (windowParent && q->windowModality() == Qt::WindowModal){
- // Window should be window-modal, which implies a sheet.
+ // INVARIANT: Window should be window-modal (which implies a sheet).
if (!alreadySheet) {
// NB: the following call will call setModal_sys recursivly:
recreateMacWindow();
@@ -4778,47 +4850,19 @@ void QWidgetPrivate::setModal_sys()
[static_cast<NSPanel *>(windowRef) setWorksWhenModal:YES];
}
} else {
- // Window shold not be window-modal, and as such, not a sheet.
+ // INVARIANT: Window shold _not_ be window-modal (and as such, not a sheet).
if (alreadySheet){
// NB: the following call will call setModal_sys recursivly:
recreateMacWindow();
windowRef = qt_mac_window_for(q);
}
- if (q->windowModality() == Qt::ApplicationModal) {
- [windowRef setLevel:NSModalPanelWindowLevel];
- } else if (primaryWindow && primaryWindow->windowModality() == Qt::ApplicationModal) {
- // INVARIANT: Our window is a dialog that has a dialog parent that is
- // application modal, or . This means that q is supposed to be on top of this
- // dialog and not be modally shaddowed:
- [windowRef setLevel:NSModalPanelWindowLevel];
+ if (q->windowModality() == Qt::NonModal
+ && primaryWindow && primaryWindow->windowModality() == Qt::ApplicationModal) {
+ // INVARIANT: Our window has a parent that is application modal.
+ // This means that q is supposed to be on top of this window and
+ // not be modally shaddowed:
if ([windowRef isKindOfClass:[NSPanel class]])
[static_cast<NSPanel *>(windowRef) setWorksWhenModal:YES];
- } else {
- // INVARIANT: q should not be modal.
- NSInteger winLevel = -1;
- if (q->windowType() == Qt::Popup) {
- winLevel = NSPopUpMenuWindowLevel;
- // Popup should be in at least the same level as its parent.
- if (primaryWindow) {
- OSWindowRef parentRef = qt_mac_window_for(primaryWindow);
- winLevel = qMax([parentRef level], winLevel);
- }
- } else if (q->windowType() == Qt::Tool) {
- winLevel = NSFloatingWindowLevel;
- } else if (q->windowType() == Qt::Dialog) {
- winLevel = NSModalPanelWindowLevel;
- }
-
- // StayOnTop window should appear above Tool windows.
- if (data.window_flags & Qt::WindowStaysOnTopHint)
- winLevel = NSPopUpMenuWindowLevel;
- // Tooltips should appear above StayOnTop windows.
- if (q->windowType() == Qt::ToolTip)
- winLevel = NSScreenSaverWindowLevel;
- // All other types are Normal level.
- if (winLevel == -1)
- winLevel = NSNormalWindowLevel;
- [windowRef setLevel:winLevel];
}
}
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index b421d3049c..75b4c12b33 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -158,6 +158,7 @@ struct QTLWExtra {
quint32 newCounterValueLo;
#endif
#elif defined(Q_WS_WIN) // <--------------------------------------------------------- WIN
+ uint hotkeyRegistered: 1; // Hot key from the STARTUPINFO has been registered.
HICON winIconBig; // internal big Windows icon
HICON winIconSmall; // internal small Windows icon
#elif defined(Q_WS_MAC) // <--------------------------------------------------------- MAC
@@ -385,6 +386,8 @@ public:
QRegion prepareToRender(const QRegion &region, QWidget::RenderFlags renderFlags);
void render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &sourceRegion,
QWidget::RenderFlags renderFlags);
+ void render(QPaintDevice *target, const QPoint &targetOffset, const QRegion &sourceRegion,
+ QWidget::RenderFlags renderFlags, bool readyToRender);
void drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, int flags,
QPainter *sharedPainter = 0, QWidgetBackingStore *backingStore = 0);
@@ -761,6 +764,8 @@ public:
void initWindowPtr();
void finishCreateWindow_sys_Carbon(OSWindowRef windowRef);
#else
+ void setSubWindowStacking(bool set);
+ void setWindowLevel();
void finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ windowRef);
void syncCocoaMask();
void finishCocoaMaskSetup();
diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp
index 10522ed89f..8cab387eab 100644
--- a/src/gui/kernel/qwidget_win.cpp
+++ b/src/gui/kernel/qwidget_win.cpp
@@ -1094,6 +1094,21 @@ void QWidgetPrivate::show_sys()
return;
}
+ if (data.window_flags & Qt::Window) {
+ QTLWExtra *extra = topData();
+ if (!extra->hotkeyRegistered) {
+ // Try to set the hotkey using information from STARTUPINFO
+ STARTUPINFO startupInfo;
+ GetStartupInfo(&startupInfo);
+ // If STARTF_USEHOTKEY is set, hStdInput is the virtual keycode
+ if (startupInfo.dwFlags & 0x00000200) {
+ WPARAM hotKey = (WPARAM)startupInfo.hStdInput;
+ SendMessage(data.winid, WM_SETHOTKEY, hotKey, 0);
+ }
+ extra->hotkeyRegistered = 1;
+ }
+ }
+
int sm = SW_SHOWNORMAL;
bool fakedMaximize = false;
if (q->isWindow()) {
@@ -1141,6 +1156,11 @@ void QWidgetPrivate::show_sys()
data.window_state |= Qt::WindowMinimized;
if (IsZoomed(q->internalWinId()))
data.window_state |= Qt::WindowMaximized;
+ // This is to resolve the problem where popups are opened from the
+ // system tray and not being implicitly activated
+ if (q->windowType() == Qt::Popup &&
+ (!q->parentWidget() || !q->parentWidget()->isActiveWindow()))
+ q->activateWindow();
}
winSetupGestures();
@@ -1687,6 +1707,7 @@ void QWidgetPrivate::deleteSysExtra()
void QWidgetPrivate::createTLSysExtra()
{
+ extra->topextra->hotkeyRegistered = 0;
extra->topextra->savedFlags = 0;
extra->topextra->winIconBig = 0;
extra->topextra->winIconSmall = 0;
diff --git a/src/gui/mac/qt_menu.nib/classes.nib b/src/gui/mac/qt_menu.nib/classes.nib
index fed50a386c..0031e0e4e5 100644
--- a/src/gui/mac/qt_menu.nib/classes.nib
+++ b/src/gui/mac/qt_menu.nib/classes.nib
@@ -5,14 +5,6 @@
<key>IBClasses</key>
<array>
<dict>
- <key>CLASS</key>
- <string>FirstResponder</string>
- <key>LANGUAGE</key>
- <string>ObjC</string>
- <key>SUPERCLASS</key>
- <string>NSObject</string>
- </dict>
- <dict>
<key>ACTIONS</key>
<dict>
<key>hide</key>
@@ -52,6 +44,14 @@
<key>SUPERCLASS</key>
<string>NSResponder</string>
</dict>
+ <dict>
+ <key>CLASS</key>
+ <string>FirstResponder</string>
+ <key>LANGUAGE</key>
+ <string>ObjC</string>
+ <key>SUPERCLASS</key>
+ <string>NSObject</string>
+ </dict>
</array>
<key>IBVersion</key>
<string>1</string>
diff --git a/src/gui/mac/qt_menu.nib/info.nib b/src/gui/mac/qt_menu.nib/info.nib
index 768cb8b9f1..02e5cca562 100644
--- a/src/gui/mac/qt_menu.nib/info.nib
+++ b/src/gui/mac/qt_menu.nib/info.nib
@@ -3,7 +3,7 @@
<plist version="1.0">
<dict>
<key>IBFramework Version</key>
- <string>670</string>
+ <string>672</string>
<key>IBOldestOS</key>
<integer>5</integer>
<key>IBOpenObjects</key>
@@ -11,7 +11,7 @@
<integer>57</integer>
</array>
<key>IBSystem Version</key>
- <string>9G55</string>
+ <string>9L31a</string>
<key>targetFramework</key>
<string>IBCocoaFramework</string>
</dict>
diff --git a/src/gui/mac/qt_menu.nib/keyedobjects.nib b/src/gui/mac/qt_menu.nib/keyedobjects.nib
index 18a66488f5..3edb0ed2eb 100644
--- a/src/gui/mac/qt_menu.nib/keyedobjects.nib
+++ b/src/gui/mac/qt_menu.nib/keyedobjects.nib
Binary files differ
diff --git a/src/gui/math3d/qmatrix4x4.h b/src/gui/math3d/qmatrix4x4.h
index f9902d7083..0671fa8829 100644
--- a/src/gui/math3d/qmatrix4x4.h
+++ b/src/gui/math3d/qmatrix4x4.h
@@ -208,6 +208,8 @@ private:
friend class QGraphicsRotation;
};
+Q_DECLARE_TYPEINFO(QMatrix4x4, Q_MOVABLE_TYPE);
+
inline QMatrix4x4::QMatrix4x4
(qreal m11, qreal m12, qreal m13, qreal m14,
qreal m21, qreal m22, qreal m23, qreal m24,
diff --git a/src/gui/math3d/qquaternion.h b/src/gui/math3d/qquaternion.h
index a446f28af3..16aa5d0774 100644
--- a/src/gui/math3d/qquaternion.h
+++ b/src/gui/math3d/qquaternion.h
@@ -136,6 +136,8 @@ private:
qreal wp, xp, yp, zp;
};
+Q_DECLARE_TYPEINFO(QQuaternion, Q_MOVABLE_TYPE);
+
inline QQuaternion::QQuaternion() : wp(1.0f), xp(0.0f), yp(0.0f), zp(0.0f) {}
inline QQuaternion::QQuaternion(qreal aScalar, qreal xpos, qreal ypos, qreal zpos) : wp(aScalar), xp(xpos), yp(ypos), zp(zpos) {}
diff --git a/src/gui/math3d/qvector2d.h b/src/gui/math3d/qvector2d.h
index d76f35ac57..c92c5e0153 100644
--- a/src/gui/math3d/qvector2d.h
+++ b/src/gui/math3d/qvector2d.h
@@ -126,6 +126,8 @@ private:
friend class QVector4D;
};
+Q_DECLARE_TYPEINFO(QVector2D, Q_MOVABLE_TYPE);
+
inline QVector2D::QVector2D() : xp(0.0f), yp(0.0f) {}
inline QVector2D::QVector2D(float xpos, float ypos, int) : xp(xpos), yp(ypos) {}
diff --git a/src/gui/math3d/qvector3d.h b/src/gui/math3d/qvector3d.h
index 80c71526e0..2fdd1d3d41 100644
--- a/src/gui/math3d/qvector3d.h
+++ b/src/gui/math3d/qvector3d.h
@@ -141,6 +141,8 @@ private:
#endif
};
+Q_DECLARE_TYPEINFO(QVector3D, Q_MOVABLE_TYPE);
+
inline QVector3D::QVector3D() : xp(0.0f), yp(0.0f), zp(0.0f) {}
inline QVector3D::QVector3D(qreal xpos, qreal ypos, qreal zpos) : xp(xpos), yp(ypos), zp(zpos) {}
diff --git a/src/gui/math3d/qvector4d.h b/src/gui/math3d/qvector4d.h
index 4af2961715..a383fbb16f 100644
--- a/src/gui/math3d/qvector4d.h
+++ b/src/gui/math3d/qvector4d.h
@@ -138,6 +138,8 @@ private:
#endif
};
+Q_DECLARE_TYPEINFO(QVector4D, Q_MOVABLE_TYPE);
+
inline QVector4D::QVector4D() : xp(0.0f), yp(0.0f), zp(0.0f), wp(0.0f) {}
inline QVector4D::QVector4D(qreal xpos, qreal ypos, qreal zpos, qreal wpos) : xp(xpos), yp(ypos), zp(zpos), wp(wpos) {}
diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp
index 1a83b1d1cd..a82d0f9432 100644
--- a/src/gui/painting/qbrush.cpp
+++ b/src/gui/painting/qbrush.cpp
@@ -912,7 +912,7 @@ void QBrush::setTransform(const QTransform &matrix)
otherwise returns false.
Two brushes are different if they have different styles, colors or
- pixmaps.
+ transforms or different pixmaps or gradients depending on the style.
\sa operator==()
*/
@@ -924,7 +924,7 @@ void QBrush::setTransform(const QTransform &matrix)
otherwise returns false.
Two brushes are equal if they have equal styles, colors and
- pixmaps.
+ transforms and equal pixmaps or gradients depending on the style.
\sa operator!=()
*/
@@ -933,26 +933,26 @@ bool QBrush::operator==(const QBrush &b) const
{
if (b.d == d)
return true;
- if (b.d->style == d->style && b.d->color == d->color) {
- switch (d->style) {
- case Qt::TexturePattern: {
- QPixmap &us = (static_cast<QTexturedBrushData *>(d.data()))->pixmap();
- QPixmap &them = (static_cast<QTexturedBrushData *>(b.d.data()))->pixmap();
+ if (b.d->style != d->style || b.d->color != d->color || b.d->transform != d->transform)
+ return false;
+ switch (d->style) {
+ case Qt::TexturePattern:
+ {
+ const QPixmap &us = (static_cast<QTexturedBrushData *>(d.data()))->pixmap();
+ const QPixmap &them = (static_cast<QTexturedBrushData *>(b.d.data()))->pixmap();
return ((us.isNull() && them.isNull()) || us.cacheKey() == them.cacheKey());
}
- case Qt::LinearGradientPattern:
- case Qt::RadialGradientPattern:
- case Qt::ConicalGradientPattern:
- {
- QGradientBrushData *d1 = static_cast<QGradientBrushData *>(d.data());
- QGradientBrushData *d2 = static_cast<QGradientBrushData *>(b.d.data());
- return d1->gradient == d2->gradient;
- }
- default:
- return true;
+ case Qt::LinearGradientPattern:
+ case Qt::RadialGradientPattern:
+ case Qt::ConicalGradientPattern:
+ {
+ const QGradientBrushData *d1 = static_cast<QGradientBrushData *>(d.data());
+ const QGradientBrushData *d2 = static_cast<QGradientBrushData *>(b.d.data());
+ return d1->gradient == d2->gradient;
}
+ default:
+ return true;
}
- return false;
}
/*!
diff --git a/src/gui/painting/qdatabuffer_p.h b/src/gui/painting/qdatabuffer_p.h
index a7834ea03c..bc5f1efcf7 100644
--- a/src/gui/painting/qdatabuffer_p.h
+++ b/src/gui/painting/qdatabuffer_p.h
@@ -81,7 +81,9 @@ public:
inline Type &at(int i) { Q_ASSERT(i >= 0 && i < siz); return buffer[i]; }
inline const Type &at(int i) const { Q_ASSERT(i >= 0 && i < siz); return buffer[i]; }
+ inline Type &last() { Q_ASSERT(!isEmpty()); return buffer[siz-1]; }
inline const Type &last() const { Q_ASSERT(!isEmpty()); return buffer[siz-1]; }
+ inline Type &first() { Q_ASSERT(!isEmpty()); return buffer[0]; }
inline const Type &first() const { Q_ASSERT(!isEmpty()); return buffer[0]; }
inline void add(const Type &t) {
@@ -90,6 +92,11 @@ public:
++siz;
}
+ inline void pop_back() {
+ Q_ASSERT(siz > 0);
+ --siz;
+ }
+
inline void resize(int size) {
reserve(size);
siz = size;
diff --git a/src/gui/painting/qemulationpaintengine.cpp b/src/gui/painting/qemulationpaintengine.cpp
index 4067b97ed7..0510b103a7 100644
--- a/src/gui/painting/qemulationpaintengine.cpp
+++ b/src/gui/painting/qemulationpaintengine.cpp
@@ -172,6 +172,36 @@ void QEmulationPaintEngine::drawTextItem(const QPointF &p, const QTextItem &text
QRectF rect(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
fillBGRect(rect);
}
+
+ QPainterState *s = state();
+ Qt::BrushStyle style = qbrush_style(s->pen.brush());
+ if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern)
+ {
+ QPen savedPen = s->pen;
+ QGradient g = *s->pen.brush().gradient();
+
+ if (g.coordinateMode() > QGradient::LogicalMode) {
+ QTransform mat = s->pen.brush().transform();
+ if (g.coordinateMode() == QGradient::StretchToDeviceMode) {
+ mat.scale(real_engine->painter()->device()->width(), real_engine->painter()->device()->height());
+ } else if (g.coordinateMode() == QGradient::ObjectBoundingMode) {
+ const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
+ QRectF r(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
+ mat.translate(r.x(), r.y());
+ mat.scale(r.width(), r.height());
+ }
+ g.setCoordinateMode(QGradient::LogicalMode);
+ QBrush brush(g);
+ brush.setTransform(mat);
+ s->pen.setBrush(brush);
+ penChanged();
+ real_engine->drawTextItem(p, textItem);
+ s->pen = savedPen;
+ penChanged();
+ return;
+ }
+ }
+
real_engine->drawTextItem(p, textItem);
}
diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp
index fba3595b92..f78de34e38 100644
--- a/src/gui/painting/qpainterpath.cpp
+++ b/src/gui/painting/qpainterpath.cpp
@@ -1257,6 +1257,8 @@ Qt::FillRule QPainterPath::fillRule() const
void QPainterPath::setFillRule(Qt::FillRule fillRule)
{
ensureData();
+ if (d_func()->fillRule == fillRule)
+ return;
detach();
d_func()->fillRule = fillRule;
diff --git a/src/gui/statemachine/qguistatemachine.cpp b/src/gui/statemachine/qguistatemachine.cpp
index 70f152d573..63ad94ef59 100644
--- a/src/gui/statemachine/qguistatemachine.cpp
+++ b/src/gui/statemachine/qguistatemachine.cpp
@@ -469,12 +469,6 @@ static QEvent *cloneEvent(QEvent *e)
case QEvent::UngrabKeyboard:
return new QEvent(*e);
-#ifdef QT_MAC_USE_COCOA
- case QEvent::CocoaRequestModal:
- Q_ASSERT_X(false, "cloneEvent()", "not implemented");
- break;
-#endif
-
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
diff --git a/src/gui/styles/qcommonstyle.cpp b/src/gui/styles/qcommonstyle.cpp
index b1924e7566..7f9b058109 100644
--- a/src/gui/styles/qcommonstyle.cpp
+++ b/src/gui/styles/qcommonstyle.cpp
@@ -5662,10 +5662,16 @@ QIcon QCommonStyle::standardIconImplementation(StandardPixmap standardIcon, cons
OSType iconType = 0;
switch (standardIcon) {
case QStyle::SP_MessageBoxQuestion:
+ iconType = kQuestionMarkIcon;
+ break;
case QStyle::SP_MessageBoxInformation:
+ iconType = kAlertNoteIcon;
+ break;
case QStyle::SP_MessageBoxWarning:
+ iconType = kAlertCautionIcon;
+ break;
case QStyle::SP_MessageBoxCritical:
- iconType = kGenericApplicationIcon;
+ iconType = kAlertStopIcon;
break;
case SP_DesktopIcon:
iconType = kDesktopIcon;
diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm
index 78074c798f..40ee31d16e 100644
--- a/src/gui/styles/qmacstyle_mac.mm
+++ b/src/gui/styles/qmacstyle_mac.mm
@@ -3146,6 +3146,18 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
break;
case PE_PanelLineEdit:
QWindowsStyle::drawPrimitive(pe, opt, p, w);
+ // Draw the focus frame for widgets other than QLineEdit (e.g. for line edits in Webkit).
+ // Focus frame is drawn outside the rectangle passed in the option-rect.
+ if (const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
+ if ((opt->state & State_HasFocus) && !qobject_cast<const QLineEdit*>(w)) {
+ int vmargin = pixelMetric(QStyle::PM_FocusFrameVMargin);
+ int hmargin = pixelMetric(QStyle::PM_FocusFrameHMargin);
+ QStyleOptionFrame focusFrame = *panel;
+ focusFrame.rect = panel->rect.adjusted(-hmargin, -vmargin, hmargin, vmargin);
+ drawControl(CE_FocusFrame, &focusFrame, p, w);
+ }
+ }
+
break;
case PE_FrameTabWidget:
if (const QStyleOptionTabWidgetFrame *twf
@@ -3169,7 +3181,6 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
p->drawLine(opt->rect.topLeft(), opt->rect.bottomLeft());
} break;
case PE_FrameStatusBarItem:
- QCommonStyle::drawPrimitive(pe, opt, p, w);
break;
case PE_IndicatorTabClose: {
bool hover = (opt->state & State_MouseOver);
diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp
index 872bc2bd81..6d9ba050a3 100644
--- a/src/gui/styles/qs60style_s60.cpp
+++ b/src/gui/styles/qs60style_s60.cpp
@@ -58,8 +58,8 @@
#include <aknsskininstance.h>
#include <aknsbasicbackgroundcontrolcontext.h>
#include <avkon.mbg>
-#include <AknFontAccess.h>
-#include <AknLayoutFont.h>
+#include <aknfontaccess.h>
+#include <aknlayoutfont.h>
#include <aknutils.h>
#include <aknnavi.h>
#include <gulicon.h>
diff --git a/src/gui/styles/qs60style_simulated.cpp b/src/gui/styles/qs60style_simulated.cpp
index f87cf282e4..3f09ebc0c3 100644
--- a/src/gui/styles/qs60style_simulated.cpp
+++ b/src/gui/styles/qs60style_simulated.cpp
@@ -94,12 +94,12 @@ bool saveThemeToBlob(const QString &themeBlob,
dataOut << color;
}
- const int picturesCount = partPictures.count();
- dataOut << picturesCount;
- foreach (const QString &key, partPictures.keys()) {
- const QPicture picture = partPictures.value(key);
- dataOut << key;
- dataOut << picture;
+ dataOut << partPictures.count();
+ QHashIterator<QString, QPicture> i(partPictures);
+ while (i.hasNext()) {
+ i.next();
+ dataOut << i.key();
+ dataOut << i.value(); // the QPicture
}
QDataStream blobOut(&blob);
diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp
index b36294ad28..1f9fc32c67 100644
--- a/src/gui/styles/qstylesheetstyle.cpp
+++ b/src/gui/styles/qstylesheetstyle.cpp
@@ -1065,7 +1065,7 @@ QRect QRenderRule::boxRect(const QRect& cr, int flags) const
r.adjust(-p[LeftEdge], -p[TopEdge], p[RightEdge], p[BottomEdge]);
}
}
- if (!hasNativeBorder() && (flags & Border)) {
+ if (hasBorder() && (flags & Border)) {
const int *b = border()->borders;
r.adjust(-b[LeftEdge], -b[TopEdge], b[RightEdge], b[BottomEdge]);
}
@@ -1352,6 +1352,12 @@ void QRenderRule::configurePalette(QPalette *p, QPalette::ColorRole fr, QPalette
if (br != QPalette::NoRole)
p->setBrush(br, bg->brush);
p->setBrush(QPalette::Window, bg->brush);
+ if (bg->brush.style() == Qt::SolidPattern) {
+ p->setBrush(QPalette::Light, bg->brush.color().lighter(115));
+ p->setBrush(QPalette::Midlight, bg->brush.color().lighter(107));
+ p->setBrush(QPalette::Dark, bg->brush.color().darker(150));
+ p->setBrush(QPalette::Shadow, bg->brush.color().darker(300));
+ }
}
if (!hasPalette())
diff --git a/src/gui/text/qfontdatabase_s60.cpp b/src/gui/text/qfontdatabase_s60.cpp
index 7e5397d593..87a73df2a3 100644
--- a/src/gui/text/qfontdatabase_s60.cpp
+++ b/src/gui/text/qfontdatabase_s60.cpp
@@ -50,7 +50,7 @@
#include "qendian.h"
#include <private/qcore_symbian_p.h>
#if defined(QT_NO_FREETYPE)
-#include <OPENFONT.H>
+#include <openfont.h>
#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
#include <graphics/openfontrasterizer.h> // COpenFontRasterizer has moved to a new header file
#endif // SYMBIAN_ENABLE_SPLIT_HEADERS
diff --git a/src/gui/text/qfontdatabase_win.cpp b/src/gui/text/qfontdatabase_win.cpp
index 05c8f0861a..b30a6c3ec5 100644
--- a/src/gui/text/qfontdatabase_win.cpp
+++ b/src/gui/text/qfontdatabase_win.cpp
@@ -1101,7 +1101,6 @@ static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
if (AddFontResource((LPCWSTR)fnt->fileName.utf16()) == 0)
return;
#else
- // supported from 2000 on, so no need to deal with the *A variant
PtrAddFontResourceExW ptrAddFontResourceExW = (PtrAddFontResourceExW)QLibrary::resolve(QLatin1String("gdi32"),
"AddFontResourceExW");
if (!ptrAddFontResourceExW
diff --git a/src/gui/text/qfontengine_s60_p.h b/src/gui/text/qfontengine_s60_p.h
index 78f8a9a2fc..5834cc441d 100644
--- a/src/gui/text/qfontengine_s60_p.h
+++ b/src/gui/text/qfontengine_s60_p.h
@@ -56,7 +56,7 @@
#include "qconfig.h"
#include "qfontengine_p.h"
#include "qsize.h"
-#include <OPENFONT.H>
+#include <openfont.h>
class CFont;
diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp
index aaaa3caec5..8d3923fecb 100644
--- a/src/gui/text/qtextcontrol.cpp
+++ b/src/gui/text/qtextcontrol.cpp
@@ -1762,8 +1762,8 @@ void QTextControlPrivate::contextMenuEvent(const QPoint &screenPos, const QPoint
QMenu *menu = q->createStandardContextMenu(docPos, contextWidget);
if (!menu)
return;
- menu->exec(screenPos);
- delete menu;
+ menu->setAttribute(Qt::WA_DeleteOnClose);
+ menu->popup(screenPos);
#endif
}
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index 21f318906f..80931c9418 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -61,6 +61,7 @@
#include <qapplication.h>
#include "qtextcontrol_p.h"
#include "private/qtextedit_p.h"
+#include "private/qdataurl_p.h"
#include "qtextdocument_p.h"
#include <private/qprinter_p.h>
@@ -435,6 +436,23 @@ void QTextDocument::redo(QTextCursor *cursor)
}
/*!
+ \since 4.7
+ Clears the specified stacks.
+
+ This method clears any commands on the undo stack, the redo stack, or both (the
+ default). If any commands got cleared, the appropriate signals
+ (\a QTextDocument::undoAvailable or \a QTextDocument::redoAvailable) get
+ emitted.
+
+ \sa QTextDocument::undoAvailable QTextDocument::redoAvailable
+*/
+void QTextDocument::clearUndoRedoStacks(Stacks stacksToClear)
+{
+ Q_D(QTextDocument);
+ d->clearUndoRedoStacks(stacksToClear, true);
+}
+
+/*!
\overload
*/
@@ -1924,6 +1942,10 @@ QVariant QTextDocument::loadResource(int type, const QUrl &name)
}
#endif
+ // handle data: URLs
+ if (r.isNull() && name.scheme() == QLatin1String("data"))
+ r = qDecodeDataUrl(name).second;
+
// if resource was not loaded try to load it here
if (!doc && r.isNull() && name.isRelative()) {
QUrl currentURL = d->url;
diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h
index b5bcb41277..0140772e1d 100644
--- a/src/gui/text/qtextdocument.h
+++ b/src/gui/text/qtextdocument.h
@@ -256,6 +256,13 @@ public:
void undo(QTextCursor *cursor);
void redo(QTextCursor *cursor);
+ enum Stacks {
+ UndoStack = 0x01,
+ RedoStack = 0x02,
+ UndoAndRedoStacks = UndoStack | RedoStack
+ };
+ void clearUndoRedoStacks(Stacks historyToClear = UndoAndRedoStacks);
+
int maximumBlockCount() const;
void setMaximumBlockCount(int maximum);
diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp
index 372b9dc3e2..969d5b4632 100644
--- a/src/gui/text/qtextdocument_p.cpp
+++ b/src/gui/text/qtextdocument_p.cpp
@@ -259,8 +259,7 @@ void QTextDocumentPrivate::clear()
objects.clear();
title.clear();
- undoState = 0;
- truncateUndoStack();
+ clearUndoRedoStacks(QTextDocument::UndoAndRedoStacks);
text = QString();
unreachableCharacterCount = 0;
modifiedState = 0;
@@ -292,7 +291,7 @@ QTextDocumentPrivate::~QTextDocumentPrivate()
cursors.clear();
undoState = 0;
undoEnabled = true;
- truncateUndoStack();
+ clearUndoRedoStacks(QTextDocument::RedoStack);
}
void QTextDocumentPrivate::setLayout(QAbstractTextDocumentLayout *layout)
@@ -1027,7 +1026,7 @@ void QTextDocumentPrivate::appendUndoItem(const QTextUndoCommand &c)
if (!undoEnabled)
return;
if (undoState < undoStack.size())
- truncateUndoStack();
+ clearUndoRedoStacks(QTextDocument::RedoStack);
if (!undoStack.isEmpty() && modified) {
QTextUndoCommand &last = undoStack[undoState - 1];
@@ -1050,26 +1049,46 @@ void QTextDocumentPrivate::appendUndoItem(const QTextUndoCommand &c)
emit document()->undoCommandAdded();
}
-void QTextDocumentPrivate::truncateUndoStack()
+void QTextDocumentPrivate::clearUndoRedoStacks(QTextDocument::Stacks stacksToClear,
+ bool emitSignals)
{
- if (undoState == undoStack.size())
- return;
-
- for (int i = undoState; i < undoStack.size(); ++i) {
- QTextUndoCommand c = undoStack[i];
- if (c.command & QTextUndoCommand::Removed) {
- // ########
-// QTextFragment *f = c.fragment_list;
-// while (f) {
-// QTextFragment *n = f->right;
-// delete f;
-// f = n;
-// }
- } else if (c.command & QTextUndoCommand::Custom) {
- delete c.custom;
+ bool undoCommandsAvailable = undoState != 0;
+ bool redoCommandsAvailable = undoState != undoStack.size();
+ if (stacksToClear == QTextDocument::UndoStack && undoCommandsAvailable) {
+ for (int i = 0; i < undoState; ++i) {
+ QTextUndoCommand c = undoStack[undoState];
+ if (c.command & QTextUndoCommand::Custom)
+ delete c.custom;
}
+ undoStack.remove(0, undoState);
+ undoStack.resize(undoStack.size() - undoState);
+ undoState = 0;
+ if (emitSignals)
+ emitUndoAvailable(false);
+ } else if (stacksToClear == QTextDocument::RedoStack
+ && redoCommandsAvailable) {
+ for (int i = undoState; i < undoStack.size(); ++i) {
+ QTextUndoCommand c = undoStack[i];
+ if (c.command & QTextUndoCommand::Custom)
+ delete c.custom;
+ }
+ undoStack.resize(undoState);
+ if (emitSignals)
+ emitRedoAvailable(false);
+ } else if (stacksToClear == QTextDocument::UndoAndRedoStacks
+ && !undoStack.isEmpty()) {
+ for (int i = 0; i < undoStack.size(); ++i) {
+ QTextUndoCommand c = undoStack[i];
+ if (c.command & QTextUndoCommand::Custom)
+ delete c.custom;
+ }
+ undoState = 0;
+ undoStack.resize(0);
+ if (emitSignals && undoCommandsAvailable)
+ emitUndoAvailable(false);
+ if (emitSignals && redoCommandsAvailable)
+ emitRedoAvailable(false);
}
- undoStack.resize(undoState);
}
void QTextDocumentPrivate::emitUndoAvailable(bool available)
@@ -1097,7 +1116,7 @@ void QTextDocumentPrivate::enableUndoRedo(bool enable)
if (!enable) {
undoState = 0;
- truncateUndoStack();
+ clearUndoRedoStacks(QTextDocument::RedoStack);
emitUndoAvailable(false);
emitRedoAvailable(false);
}
diff --git a/src/gui/text/qtextdocument_p.h b/src/gui/text/qtextdocument_p.h
index 4ecc2fa6cf..ac5ed3c86e 100644
--- a/src/gui/text/qtextdocument_p.h
+++ b/src/gui/text/qtextdocument_p.h
@@ -252,10 +252,11 @@ public:
inline QFont defaultFont() const { return formats.defaultFont(); }
inline void setDefaultFont(const QFont &f) { formats.setDefaultFont(f); }
+ void clearUndoRedoStacks(QTextDocument::Stacks stacksToClear, bool emitSignals = false);
+
private:
bool split(int pos);
bool unite(uint f);
- void truncateUndoStack();
void insert_string(int pos, uint strPos, uint length, int format, QTextUndoCommand::Operation op);
int insert_block(int pos, uint strPos, int format, int blockformat, QTextUndoCommand::Operation op, int command);
diff --git a/src/gui/util/qcompleter.cpp b/src/gui/util/qcompleter.cpp
index cefdb27c6d..b7be967c3e 100644
--- a/src/gui/util/qcompleter.cpp
+++ b/src/gui/util/qcompleter.cpp
@@ -62,7 +62,7 @@
\snippet doc/src/snippets/code/src_gui_util_qcompleter.cpp 0
- A QDirModel can be used to provide auto completion of file names.
+ A QFileSystemModel can be used to provide auto completion of file names.
For example:
\snippet doc/src/snippets/code/src_gui_util_qcompleter.cpp 1
@@ -120,7 +120,7 @@
completion is then performed one level at a time.
Let's take the example of a user typing in a file system path.
- The model is a (hierarchical) QDirModel. The completion
+ The model is a (hierarchical) QFileSystemModel. The completion
occurs for every element in the path. For example, if the current
text is \c C:\Wind, QCompleter might suggest \c Windows to
complete the current path element. Similarly, if the current text
@@ -130,12 +130,12 @@
split the path into a list of strings that are matched at each level.
For \c C:\Windows\Sy, it needs to be split as "C:", "Windows" and "Sy".
The default implementation of splitPath(), splits the completionPrefix
- using QDir::separator() if the model is a QDirModel.
+ using QDir::separator() if the model is a QFileSystemModel.
To provide completions, QCompleter needs to know the path from an index.
This is provided by pathFromIndex(). The default implementation of
pathFromIndex(), returns the data for the \l{Qt::EditRole}{edit role}
- for list models and the absolute file path if the mode is a QDirModel.
+ for list models and the absolute file path if the mode is a QFileSystemModel.
\sa QAbstractItemModel, QLineEdit, QComboBox, {Completer Example}
*/
@@ -147,6 +147,7 @@
#include "QtGui/qscrollbar.h"
#include "QtGui/qstringlistmodel.h"
#include "QtGui/qdirmodel.h"
+#include "QtGui/qfilesystemmodel.h"
#include "QtGui/qheaderview.h"
#include "QtGui/qlistview.h"
#include "QtGui/qapplication.h"
@@ -470,9 +471,13 @@ QMatchData QCompletionEngine::filterHistory()
QAbstractItemModel *source = c->proxy->sourceModel();
if (curParts.count() <= 1 || c->proxy->showAll || !source)
return QMatchData();
- bool dirModel = false;
+ bool isDirModel = false;
+ bool isFsModel = false;
#ifndef QT_NO_DIRMODEL
- dirModel = (qobject_cast<QDirModel *>(source) != 0);
+ isDirModel = (qobject_cast<QDirModel *>(source) != 0);
+#endif
+#ifndef QT_NO_FILESYSTEMMODEL
+ isFsModel = (qobject_cast<QFileSystemModel *>(source) != 0);
#endif
QVector<int> v;
QIndexMapper im(v);
@@ -482,7 +487,7 @@ QMatchData QCompletionEngine::filterHistory()
QString str = source->index(i, c->column).data().toString();
if (str.startsWith(c->prefix, c->cs)
#if (!defined(Q_OS_WIN) || defined(Q_OS_WINCE)) && !defined(Q_OS_SYMBIAN)
- && (!dirModel || QDir::toNativeSeparators(str) != QDir::separator())
+ && ((!isFsModel && !isDirModel) || QDir::toNativeSeparators(str) != QDir::separator())
#endif
)
m.indices.append(i);
@@ -838,6 +843,13 @@ void QCompleterPrivate::_q_complete(QModelIndex index, bool highlighted)
completion += QDir::separator();
}
#endif
+#ifndef QT_NO_FILESYSTEMMODEL
+ // add a trailing separator in inline
+ if (mode == QCompleter::InlineCompletion) {
+ if (qobject_cast<QFileSystemModel *>(proxy->sourceModel()) && QFileInfo(completion).isDir())
+ completion += QDir::separator();
+ }
+#endif
}
if (highlighted) {
@@ -891,6 +903,14 @@ void QCompleterPrivate::showPopup(const QRect& rect)
popup->show();
}
+void QCompleterPrivate::_q_fileSystemModelDirectoryLoaded(const QString &path)
+{
+ Q_Q(QCompleter);
+ //the path given by QFileSystemModel does not end with /
+ if (q->completionPrefix() != path + QLatin1Char('/'))
+ q->complete();
+}
+
/*!
Constructs a completer object with the given \a parent.
*/
@@ -971,7 +991,7 @@ QWidget *QCompleter::widget() const
be list model or a tree model. If a model has been already previously set
and it has the QCompleter as its parent, it is deleted.
- For convenience, if \a model is a QDirModel, QCompleter switches its
+ For convenience, if \a model is a QFileSystemModel, QCompleter switches its
caseSensitivity to Qt::CaseInsensitive on Windows and Qt::CaseSensitive
on other platforms.
@@ -995,6 +1015,18 @@ void QCompleter::setModel(QAbstractItemModel *model)
#endif
}
#endif // QT_NO_DIRMODEL
+#ifndef QT_NO_FILESYSTEMMODEL
+ QFileSystemModel *fsModel = qobject_cast<QFileSystemModel *>(model);
+ if (fsModel) {
+#if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN)
+ setCaseSensitivity(Qt::CaseInsensitive);
+#else
+ setCaseSensitivity(Qt::CaseSensitive);
+#endif
+ setCompletionRole(QFileSystemModel::FileNameRole);
+ connect(fsModel, SIGNAL(directoryLoaded(QString)), this, SLOT(_q_fileSystemModelDirectoryLoaded(QString)));
+ }
+#endif // QT_NO_FILESYSTEMMODEL
}
/*!
@@ -1626,10 +1658,11 @@ QAbstractItemModel *QCompleter::completionModel() const
The default implementation returns the \l{Qt::EditRole}{edit role} of the
item for list models. It returns the absolute file path if the model is a
- QDirModel.
+ QFileSystemModel.
\sa splitPath()
*/
+
QString QCompleter::pathFromIndex(const QModelIndex& index) const
{
Q_D(const QCompleter);
@@ -1639,16 +1672,25 @@ QString QCompleter::pathFromIndex(const QModelIndex& index) const
QAbstractItemModel *sourceModel = d->proxy->sourceModel();
if (!sourceModel)
return QString();
+ bool isDirModel = false;
+ bool isFsModel = false;
#ifndef QT_NO_DIRMODEL
- QDirModel *dirModel = qobject_cast<QDirModel *>(sourceModel);
- if (!dirModel)
+ isDirModel = qobject_cast<QDirModel *>(d->proxy->sourceModel()) != 0;
+#endif
+#ifndef QT_NO_FILESYSTEMMODEL
+ isFsModel = qobject_cast<QFileSystemModel *>(d->proxy->sourceModel()) != 0;
#endif
+ if (!isDirModel && !isFsModel)
return sourceModel->data(index, d->role).toString();
QModelIndex idx = index;
QStringList list;
do {
- QString t = sourceModel->data(idx, Qt::EditRole).toString();
+ QString t;
+ if (isDirModel)
+ t = sourceModel->data(idx, Qt::EditRole).toString();
+ else
+ t = sourceModel->data(idx, QFileSystemModel::FileNameRole).toString();
list.prepend(t);
QModelIndex parent = idx.parent();
idx = parent.sibling(parent.row(), index.column());
@@ -1668,7 +1710,7 @@ QString QCompleter::pathFromIndex(const QModelIndex& index) const
in the model().
The default implementation of splitPath() splits a file system path based on
- QDir::separator() when the sourceModel() is a QDirModel.
+ QDir::separator() when the sourceModel() is a QFileSystemModel.
When used with list models, the first item in the returned list is used for
matching.
@@ -1678,12 +1720,19 @@ QString QCompleter::pathFromIndex(const QModelIndex& index) const
QStringList QCompleter::splitPath(const QString& path) const
{
bool isDirModel = false;
+ bool isFsModel = false;
#ifndef QT_NO_DIRMODEL
Q_D(const QCompleter);
isDirModel = qobject_cast<QDirModel *>(d->proxy->sourceModel()) != 0;
#endif
+#ifndef QT_NO_FILESYSTEMMODEL
+#ifdef QT_NO_DIRMODEL
+ Q_D(const QCompleter);
+#endif
+ isFsModel = qobject_cast<QFileSystemModel *>(d->proxy->sourceModel()) != 0;
+#endif
- if (!isDirModel || path.isEmpty())
+ if ((!isDirModel && !isFsModel) || path.isEmpty())
return QStringList(completionPrefix());
QString pathCopy = QDir::toNativeSeparators(path);
diff --git a/src/gui/util/qcompleter.h b/src/gui/util/qcompleter.h
index 5123a40432..0cef9be3bc 100644
--- a/src/gui/util/qcompleter.h
+++ b/src/gui/util/qcompleter.h
@@ -159,6 +159,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_complete(QModelIndex))
Q_PRIVATE_SLOT(d_func(), void _q_completionSelected(const QItemSelection&))
Q_PRIVATE_SLOT(d_func(), void _q_autoResizePopup())
+ Q_PRIVATE_SLOT(d_func(), void _q_fileSystemModelDirectoryLoaded(const QString&))
};
#endif // QT_NO_COMPLETER
diff --git a/src/gui/util/qcompleter_p.h b/src/gui/util/qcompleter_p.h
index 44be4c0204..8f00793856 100644
--- a/src/gui/util/qcompleter_p.h
+++ b/src/gui/util/qcompleter_p.h
@@ -98,6 +98,7 @@ public:
void _q_complete(QModelIndex, bool = false);
void _q_completionSelected(const QItemSelection&);
void _q_autoResizePopup();
+ void _q_fileSystemModelDirectoryLoaded(const QString &path);
void setCurrentIndex(QModelIndex, bool = true);
};
diff --git a/src/gui/util/qdesktopservices_win.cpp b/src/gui/util/qdesktopservices_win.cpp
index 9f3b6e1e9e..aab7e16631 100644
--- a/src/gui/util/qdesktopservices_win.cpp
+++ b/src/gui/util/qdesktopservices_win.cpp
@@ -59,7 +59,7 @@
# endif
#endif
-#if defined(Q_CC_MINGW) && !defined(CSIDL_MYMUSIC)
+#ifndef CSIDL_MYMUSIC
#define CSIDL_MYMUSIC 13
#define CSIDL_MYVIDEO 14
#endif
@@ -97,19 +97,19 @@ static bool launchWebBrowser(const QUrl &url)
if (url.scheme() == QLatin1String("mailto")) {
//Retrieve the commandline for the default mail client
//the default key used below is the command line for the mailto: shell command
- DWORD bufferSize = 2 * MAX_PATH;
+ DWORD bufferSize = sizeof(wchar_t) * MAX_PATH;
long returnValue = -1;
QString command;
HKEY handle;
LONG res;
- wchar_t keyValue[2 * MAX_PATH] = {0};
+ wchar_t keyValue[MAX_PATH] = {0};
QString keyName(QLatin1String("mailto"));
//Check if user has set preference, otherwise use default.
- res = RegOpenKeyExW(HKEY_CURRENT_USER,
- L"Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\mailto\\UserChoice",
- 0, KEY_READ, &handle);
+ res = RegOpenKeyEx(HKEY_CURRENT_USER,
+ L"Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\mailto\\UserChoice",
+ 0, KEY_READ, &handle);
if (res == ERROR_SUCCESS) {
returnValue = RegQueryValueEx(handle, L"Progid", 0, 0, reinterpret_cast<unsigned char*>(keyValue), &bufferSize);
if (!returnValue)
@@ -121,8 +121,8 @@ static bool launchWebBrowser(const QUrl &url)
if (res != ERROR_SUCCESS)
return false;
- bufferSize = 2 * MAX_PATH;
- returnValue = RegQueryValueExW(handle, L"", 0, 0, reinterpret_cast<unsigned char*>(keyValue), &bufferSize);
+ bufferSize = sizeof(wchar_t) * MAX_PATH;
+ returnValue = RegQueryValueEx(handle, L"", 0, 0, reinterpret_cast<unsigned char*>(keyValue), &bufferSize);
if (!returnValue)
command = QString::fromRawData((QChar*)keyValue, bufferSize);
RegCloseKey(handle);
diff --git a/src/gui/util/qsystemtrayicon_win.cpp b/src/gui/util/qsystemtrayicon_win.cpp
index 6db158e94c..8e482e050c 100644
--- a/src/gui/util/qsystemtrayicon_win.cpp
+++ b/src/gui/util/qsystemtrayicon_win.cpp
@@ -53,7 +53,6 @@
#include <qt_windows.h>
#include <commctrl.h>
-#include <shlwapi.h>
#include <QBitmap>
#include <QLibrary>
#include <QApplication>
@@ -326,8 +325,6 @@ bool QSystemTrayIconSys::winEvent( MSG *m, long *result )
q->contextMenu()->move(gpos);
}
#endif
- q->contextMenu()->activateWindow();
- //Must be activated for proper keyboardfocus and menu closing on windows:
}
emit q->activated(QSystemTrayIcon::Context);
break;
diff --git a/src/gui/widgets/qcocoamenu_mac.mm b/src/gui/widgets/qcocoamenu_mac.mm
index a7e0b7960f..ce859191a7 100644
--- a/src/gui/widgets/qcocoamenu_mac.mm
+++ b/src/gui/widgets/qcocoamenu_mac.mm
@@ -46,6 +46,7 @@
#import <private/qcocoamenuloader_mac_p.h>
#include <private/qt_cocoa_helpers_mac_p.h>
#include <private/qapplication_p.h>
+#include <private/qaction_p.h>
#include <QtGui/QMenu>
@@ -70,6 +71,7 @@ QT_USE_NAMESPACE
self = [super init];
if (self) {
qmenu = menu;
+ previousAction = 0;
[self setAutoenablesItems:NO];
[self setDelegate:self];
}
@@ -81,13 +83,20 @@ QT_USE_NAMESPACE
Q_UNUSED(menu);
if (!item) {
- // ### According to the docs everything will be highlighted. Not sure what we should do in
- // Qt, so just return.
+ if (previousAction) {
+ qt_mac_clear_status_text(previousAction);
+ previousAction = 0;
+ }
return;
}
- if (QAction *action = reinterpret_cast<QAction *>([item tag]))
+ if (QAction *action = reinterpret_cast<QAction *>([item tag])) {
+ QMenu *qtmenu = static_cast<QT_MANGLE_NAMESPACE(QCocoaMenu) *>(menu)->qmenu;
+ previousAction = action;
action->activate(QAction::Hover);
+ qt_mac_menu_emit_hovered(qtmenu, action);
+ action->showStatusText(0); // 0 widget -> action's parent
+ }
}
- (void)menuWillOpen:(NSMenu*)menu;
@@ -100,9 +109,13 @@ QT_USE_NAMESPACE
qt_mac_menu_collapseSeparators(menu, qtmenu->separatorsCollapsible());
}
-- (void)menuWillClose:(NSMenu*)menu;
+- (void)menuDidClose:(NSMenu*)menu;
{
qt_mac_emit_menuSignals(((QT_MANGLE_NAMESPACE(QCocoaMenu) *)menu)->qmenu, false);
+ if (previousAction) {
+ qt_mac_clear_status_text(previousAction);
+ previousAction = 0;
+ }
}
- (BOOL)hasShortcut:(NSMenu *)menu forKey:(NSString *)key forModifiers:(NSUInteger)modifier
@@ -194,6 +207,18 @@ void qt_mac_emit_menuSignals(QMenu *menu, bool show)
}
qt_mac_menus_open_count += delta;
}
+
+void qt_mac_clear_status_text(QAction *action)
+{
+ action->d_func()->showStatusText(0, QString());
+}
+
+void qt_mac_menu_emit_hovered(QMenu *menu, QAction *action)
+{
+ emit menu->hovered(action);
+}
+
+
QT_END_NAMESPACE
#endif
diff --git a/src/gui/widgets/qcocoamenu_mac_p.h b/src/gui/widgets/qcocoamenu_mac_p.h
index 9f50c40875..d6ac8c59ab 100644
--- a/src/gui/widgets/qcocoamenu_mac_p.h
+++ b/src/gui/widgets/qcocoamenu_mac_p.h
@@ -55,13 +55,14 @@
#import <Cocoa/Cocoa.h>
QT_FORWARD_DECLARE_CLASS(QMenu)
+QT_FORWARD_DECLARE_CLASS(QAction)
#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
@protocol NSMenuDelegate <NSObject>
- (void)menu:(NSMenu*)menu willHighlightItem:(NSMenuItem*)item;
- (void)menuWillOpen:(NSMenu*)menu;
-- (void)menuWillClose:(NSMenu*)menu;
+- (void)menuDidClose:(NSMenu*)menu;
- (BOOL)hasShortcut:(NSMenu *)menu forKey:(NSString *)key forModifiers:(NSUInteger)modifier
whichItem:(NSMenuItem**)outItem;
@end
@@ -71,6 +72,7 @@ QT_FORWARD_DECLARE_CLASS(QMenu)
@interface QT_MANGLE_NAMESPACE(QCocoaMenu) : NSMenu <NSMenuDelegate>
{
QMenu *qmenu;
+ QAction *previousAction;
}
- (id)initWithQMenu:(QMenu*)menu;
- (BOOL)menuHasKeyEquivalent:(NSMenu *)menu forEvent:(NSEvent *)event target:(id *)target action:(SEL *)action;
diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp
index 72f32dc1e0..be20a3862d 100644
--- a/src/gui/widgets/qcombobox.cpp
+++ b/src/gui/widgets/qcombobox.cpp
@@ -1268,7 +1268,8 @@ QComboBox::~QComboBox()
By default, this property has a value of 10.
- \note This property is ignored for non-editable comboboxes in Mac style.
+ \note This property is ignored for non-editable comboboxes in styles that returns
+ false for QStyle::SH_ComboBox_Popup such as the Mac style or the Gtk+ Style.
*/
int QComboBox::maxVisibleItems() const
{
@@ -2348,7 +2349,7 @@ void QComboBox::showPopup()
toCheck.push(idx);
#endif
++count;
- if (!usePopup && count > d->maxVisibleItems) {
+ if (!usePopup && count >= d->maxVisibleItems) {
toCheck.clear();
break;
}
diff --git a/src/gui/widgets/qdatetimeedit.cpp b/src/gui/widgets/qdatetimeedit.cpp
index 762db864c4..50fa9c9b49 100644
--- a/src/gui/widgets/qdatetimeedit.cpp
+++ b/src/gui/widgets/qdatetimeedit.cpp
@@ -1175,7 +1175,7 @@ void QDateTimeEdit::keyPressEvent(QKeyEvent *event)
return; }
}
QAbstractSpinBox::keyPressEvent(event);
- if (select && !(event->modifiers() & Qt::ShiftModifier) && !d->edit->hasSelectedText()) {
+ if (select && !d->edit->hasSelectedText()) {
if (inserted && d->sectionAt(d->edit->cursorPosition()) == QDateTimeParser::NoSectionIndex) {
QString str = d->displayText();
int pos = d->edit->cursorPosition();
diff --git a/src/gui/widgets/qdockarealayout.cpp b/src/gui/widgets/qdockarealayout.cpp
index d754800a2a..13f31df733 100644
--- a/src/gui/widgets/qdockarealayout.cpp
+++ b/src/gui/widgets/qdockarealayout.cpp
@@ -220,15 +220,17 @@ static quintptr tabId(const QDockAreaLayoutItem &item)
}
#endif
+static const int zero = 0;
+
QDockAreaLayoutInfo::QDockAreaLayoutInfo()
- : sep(0), dockPos(QInternal::LeftDock), o(Qt::Horizontal), mainWindow(0)
+ : sep(&zero), dockPos(QInternal::LeftDock), o(Qt::Horizontal), mainWindow(0)
#ifndef QT_NO_TABBAR
, tabbed(false), tabBar(0), tabBarShape(QTabBar::RoundedSouth), tabBarVisible(false)
#endif
{
}
-QDockAreaLayoutInfo::QDockAreaLayoutInfo(int _sep, QInternal::DockPosition _dockPos,
+QDockAreaLayoutInfo::QDockAreaLayoutInfo(const int *_sep, QInternal::DockPosition _dockPos,
Qt::Orientation _o, int tbshape,
QMainWindow *window)
: sep(_sep), dockPos(_dockPos), o(_o), mainWindow(window)
@@ -281,7 +283,7 @@ QSize QDockAreaLayoutInfo::minimumSize() const
#endif
{
if (!first)
- a += sep;
+ a += *sep;
a += pick(o, min_size);
}
b = qMax(b, perp(o, min_size));
@@ -349,7 +351,7 @@ QSize QDockAreaLayoutInfo::maximumSize() const
#endif
{
if (!first)
- a += sep;
+ a += *sep;
a += pick(o, max_size);
}
b = qMin(b, perp(o, max_size));
@@ -415,7 +417,7 @@ QSize QDockAreaLayoutInfo::sizeHint() const
{
if (previous && !gap && !(previous->flags & QDockAreaLayoutItem::GapItem)
&& !previous->hasFixedSize(o)) {
- a += sep;
+ a += *sep;
}
a += gap ? item.size : pick(o, size_hint);
}
@@ -491,7 +493,7 @@ static int realMinSize(const QDockAreaLayoutInfo &info)
min = pick(info.o, item.minimumSize());
if (!first)
- result += info.sep;
+ result += *info.sep;
result += min;
first = false;
@@ -516,7 +518,7 @@ static int realMaxSize(const QDockAreaLayoutInfo &info)
max = pick(info.o, item.maximumSize());
if (!first)
- result += info.sep;
+ result += *info.sep;
result += max;
if (result >= QWIDGETSIZE_MAX)
@@ -555,7 +557,7 @@ void QDockAreaLayoutInfo::fitItems()
if (!(previous->flags & QDockAreaLayoutItem::GapItem)) {
QLayoutStruct &ls = layout_struct_list[j++];
ls.init();
- ls.minimumSize = ls.maximumSize = ls.sizeHint = previous->hasFixedSize(o) ? 0 : sep;
+ ls.minimumSize = ls.maximumSize = ls.sizeHint = previous->hasFixedSize(o) ? 0 : *sep;
ls.empty = false;
}
}
@@ -938,7 +940,7 @@ int QDockAreaLayoutInfo::separatorMove(int index, int delta)
if (item.skip()) {
ls.empty = true;
} else {
- const int separatorSpace = item.hasFixedSize(o) ? 0 : sep;
+ const int separatorSpace = item.hasFixedSize(o) ? 0 : *sep;
ls.empty = false;
ls.pos = item.pos;
ls.size = item.size + separatorSpace;
@@ -956,7 +958,7 @@ int QDockAreaLayoutInfo::separatorMove(int index, int delta)
if (item.skip())
continue;
QLayoutStruct &ls = list[i];
- const int separatorSpace = item.hasFixedSize(o) ? 0 : sep;
+ const int separatorSpace = item.hasFixedSize(o) ? 0 : *sep;
item.size = ls.size - separatorSpace;
item.pos = ls.pos;
if (item.subinfo != 0) {
@@ -1041,11 +1043,11 @@ QLayoutItem *QDockAreaLayoutInfo::plug(const QList<int> &path)
int next = this->next(index);
if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) {
- item.pos += sep;
- item.size -= sep;
+ item.pos += *sep;
+ item.size -= *sep;
}
if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
- item.size -= sep;
+ item.size -= *sep;
QPoint pos;
rpick(o, pos) = item.pos;
@@ -1083,11 +1085,11 @@ QLayoutItem *QDockAreaLayoutInfo::unplug(const QList<int> &path)
#endif
{
if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) {
- item.pos -= sep;
- item.size += sep;
+ item.pos -= *sep;
+ item.size += *sep;
}
if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
- item.size += sep;
+ item.size += *sep;
}
return item.widgetItem;
@@ -1255,9 +1257,9 @@ bool QDockAreaLayoutInfo::insertGap(const QList<int> &path, QLayoutItem *dockWid
QRect r = dockedGeometry(dockWidgetItem->widget());
gap_size = pick(o, r.size());
if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem))
- sep_size += sep;
+ sep_size += *sep;
if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
- sep_size += sep;
+ sep_size += *sep;
}
if (gap_size + sep_size > space)
gap_size = pick(o, gap_item.minimumSize());
@@ -1364,7 +1366,7 @@ QRect QDockAreaLayoutInfo::separatorRect(int index) const
QPoint pos = rect.topLeft();
rpick(o, pos) = item.pos + item.size;
QSize s = rect.size();
- rpick(o, s) = sep;
+ rpick(o, s) = *sep;
return QRect(pos, s);
}
@@ -1413,7 +1415,7 @@ QList<int> QDockAreaLayoutInfo::findSeparator(const QPoint &_pos) const
continue;
QRect sepRect = separatorRect(i);
- if (!sepRect.isNull() && sep == 1)
+ if (!sepRect.isNull() && *sep == 1)
sepRect.adjust(-2, -2, 2, 2);
//we also make sure we don't find a separator that's not there
if (sepRect.contains(_pos) && !item.hasFixedSize(o)) {
@@ -1560,7 +1562,7 @@ void QDockAreaLayoutInfo::apply(bool animate)
}
}
#ifndef QT_NO_TABBAR
- if (sep == 1)
+ if (*sep == 1)
updateSeparatorWidgets();
#endif //QT_NO_TABBAR
}
@@ -2010,7 +2012,7 @@ bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*>
updateTabBar();
setCurrentTabId(tabId(item_list.at(index)));
}
- if (!testing && sep == 1)
+ if (!testing && *sep == 1)
updateSeparatorWidgets();
#endif
@@ -2273,13 +2275,13 @@ QDockAreaLayout::QDockAreaLayout(QMainWindow *win) : fallbackToSizeHints(true)
const int tabShape = 0;
#endif
docks[QInternal::LeftDock]
- = QDockAreaLayoutInfo(sep, QInternal::LeftDock, Qt::Vertical, tabShape, win);
+ = QDockAreaLayoutInfo(&sep, QInternal::LeftDock, Qt::Vertical, tabShape, win);
docks[QInternal::RightDock]
- = QDockAreaLayoutInfo(sep, QInternal::RightDock, Qt::Vertical, tabShape, win);
+ = QDockAreaLayoutInfo(&sep, QInternal::RightDock, Qt::Vertical, tabShape, win);
docks[QInternal::TopDock]
- = QDockAreaLayoutInfo(sep, QInternal::TopDock, Qt::Horizontal, tabShape, win);
+ = QDockAreaLayoutInfo(&sep, QInternal::TopDock, Qt::Horizontal, tabShape, win);
docks[QInternal::BottomDock]
- = QDockAreaLayoutInfo(sep, QInternal::BottomDock, Qt::Horizontal, tabShape, win);
+ = QDockAreaLayoutInfo(&sep, QInternal::BottomDock, Qt::Horizontal, tabShape, win);
centralWidgetItem = 0;
@@ -3028,7 +3030,7 @@ void QDockAreaLayout::addDockWidget(QInternal::DockPosition pos, QDockWidget *do
#else
int tbshape = 0;
#endif
- QDockAreaLayoutInfo new_info(sep, pos, orientation, tbshape, mainWindow);
+ QDockAreaLayoutInfo new_info(&sep, pos, orientation, tbshape, mainWindow);
new_info.item_list.append(new QDockAreaLayoutInfo(info));
new_info.item_list.append(dockWidgetItem);
info = new_info;
@@ -3324,6 +3326,12 @@ void QDockAreaLayout::keepSize(QDockWidget *w)
item.flags |= QDockAreaLayoutItem::KeepSize;
}
+void QDockAreaLayout::styleChangedEvent()
+{
+ sep = mainWindow->style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent, 0, mainWindow);
+ fitLayout();
+}
+
QT_END_NAMESPACE
#endif // QT_NO_DOCKWIDGET
diff --git a/src/gui/widgets/qdockarealayout_p.h b/src/gui/widgets/qdockarealayout_p.h
index 0bc1aa9eee..0088f0053b 100644
--- a/src/gui/widgets/qdockarealayout_p.h
+++ b/src/gui/widgets/qdockarealayout_p.h
@@ -128,7 +128,7 @@ class Q_AUTOTEST_EXPORT QDockAreaLayoutInfo
{
public:
QDockAreaLayoutInfo();
- QDockAreaLayoutInfo(int _sep, QInternal::DockPosition _dockPos, Qt::Orientation _o,
+ QDockAreaLayoutInfo(const int *_sep, QInternal::DockPosition _dockPos, Qt::Orientation _o,
int tbhape, QMainWindow *window);
QSize minimumSize() const;
@@ -189,7 +189,7 @@ public:
QMainWindowLayout *mainWindowLayout() const;
- int sep;
+ const int *sep;
mutable QVector<QWidget*> separatorWidgets;
QInternal::DockPosition dockPos;
Qt::Orientation o;
@@ -300,6 +300,7 @@ public:
QSet<QTabBar*> usedTabBars() const;
QSet<QWidget*> usedSeparatorWidgets() const;
#endif //QT_NO_TABBAR
+ void styleChangedEvent();
};
QT_END_NAMESPACE
diff --git a/src/gui/widgets/qfocusframe.cpp b/src/gui/widgets/qfocusframe.cpp
index d9cd5bb6fc..4f20bce001 100644
--- a/src/gui/widgets/qfocusframe.cpp
+++ b/src/gui/widgets/qfocusframe.cpp
@@ -53,11 +53,14 @@ class QFocusFramePrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QFocusFrame)
QWidget *widget;
-
+ QWidget *frameParent;
+ bool showFrameAboveWidget;
public:
QFocusFramePrivate() {
widget = 0;
+ frameParent = 0;
sendChildEvents = false;
+ showFrameAboveWidget = false;
}
void updateSize();
void update();
@@ -66,10 +69,10 @@ public:
void QFocusFramePrivate::update()
{
Q_Q(QFocusFrame);
- q->setParent(widget->parentWidget());
+ q->setParent(frameParent);
updateSize();
if (q->parentWidget()->rect().intersects(q->geometry())) {
- if (q->style()->styleHint(QStyle::SH_FocusFrame_AboveWidget, 0, q))
+ if (showFrameAboveWidget)
q->raise();
else
q->stackUnder(widget);
@@ -84,7 +87,10 @@ void QFocusFramePrivate::updateSize()
Q_Q(QFocusFrame);
int vmargin = q->style()->pixelMetric(QStyle::PM_FocusFrameVMargin),
hmargin = q->style()->pixelMetric(QStyle::PM_FocusFrameHMargin);
- QRect geom(widget->x()-hmargin, widget->y()-vmargin,
+ QPoint pos(widget->x(), widget->y());
+ if (q->parentWidget() != widget->parentWidget())
+ pos = widget->parentWidget()->mapTo(q->parentWidget(), pos);
+ QRect geom(pos.x()-hmargin, pos.y()-vmargin,
widget->width()+(hmargin*2), widget->height()+(vmargin*2));
if(q->geometry() == geom)
return;
@@ -176,14 +182,52 @@ void
QFocusFrame::setWidget(QWidget *widget)
{
Q_D(QFocusFrame);
- if(widget == d->widget)
- return;
- if(d->widget)
- d->widget->removeEventFilter(this);
- if(widget && !widget->isWindow() && widget->parentWidget()->windowType() != Qt::SubWindow) {
+ if (style()->styleHint(QStyle::SH_FocusFrame_AboveWidget, 0, this))
+ d->showFrameAboveWidget = true;
+ else
+ d->showFrameAboveWidget = false;
+
+ if (widget == d->widget)
+ return;
+ if (d->widget) {
+ // Remove event filters from the widget hierarchy.
+ QWidget *p = d->widget;
+ do {
+ p->removeEventFilter(this);
+ if (!d->showFrameAboveWidget || p == d->frameParent)
+ break;
+ p = p->parentWidget();
+ }while (p);
+ }
+ if (widget && !widget->isWindow() && widget->parentWidget()->windowType() != Qt::SubWindow) {
d->widget = widget;
- widget->installEventFilter(this);
+ d->widget->installEventFilter(this);
+ QWidget *p = widget->parentWidget();
+ QWidget *prev = 0;
+ if (d->showFrameAboveWidget) {
+ // Find the right parent for the focus frame.
+ while (p) {
+ // Traverse the hirerarchy of the 'widget' for setting event filter.
+ // During this if come across toolbar or a top level, use that
+ // as the parent for the focus frame. If we find a scroll area
+ // use its viewport as the parent.
+ bool isScrollArea = false;
+ if (p->isWindow() || p->inherits("QToolBar") || (isScrollArea = p->inherits("QAbstractScrollArea"))) {
+ d->frameParent = p;
+ // The previous one in the hierarchy will be the viewport.
+ if (prev && isScrollArea)
+ d->frameParent = prev;
+ break;
+ } else {
+ p->installEventFilter(this);
+ prev = p;
+ p = p->parentWidget();
+ }
+ }
+ } else {
+ d->frameParent = p;
+ }
d->update();
} else {
d->widget = 0;
@@ -210,9 +254,15 @@ QFocusFrame::widget() const
void
QFocusFrame::paintEvent(QPaintEvent *)
{
+ Q_D(QFocusFrame);
QStylePainter p(this);
QStyleOption option;
initStyleOption(&option);
+ int vmargin = style()->pixelMetric(QStyle::PM_FocusFrameVMargin);
+ int hmargin = style()->pixelMetric(QStyle::PM_FocusFrameHMargin);
+ QWidgetPrivate *wd = qt_widget_private(d->widget);
+ QRect rect = wd->clipRect().adjusted(0, 0, hmargin*2, vmargin*2);
+ p.setClipRect(rect);
p.drawControl(QStyle::CE_FocusFrame, option);
}
@@ -233,7 +283,13 @@ QFocusFrame::eventFilter(QObject *o, QEvent *e)
hide();
break;
case QEvent::ParentChange:
- d->update();
+ if (d->showFrameAboveWidget) {
+ QWidget *w = d->widget;
+ setWidget(0);
+ setWidget(w);
+ } else {
+ d->update();
+ }
break;
case QEvent::Show:
d->update();
@@ -254,6 +310,19 @@ QFocusFrame::eventFilter(QObject *o, QEvent *e)
default:
break;
}
+ } else if (d->showFrameAboveWidget) {
+ // Handle changes in the parent widgets we are monitoring.
+ switch(e->type()) {
+ case QEvent::Move:
+ case QEvent::Resize:
+ d->updateSize();
+ break;
+ case QEvent::ZOrderChange:
+ raise();
+ break;
+ default:
+ break;
+ }
}
return false;
}
diff --git a/src/gui/widgets/qlabel.cpp b/src/gui/widgets/qlabel.cpp
index 8428ad7ca5..b81f04fec6 100644
--- a/src/gui/widgets/qlabel.cpp
+++ b/src/gui/widgets/qlabel.cpp
@@ -781,6 +781,95 @@ Qt::TextInteractionFlags QLabel::textInteractionFlags() const
return d->textInteractionFlags;
}
+/*!
+ Selects text from position \a start and for \a length characters.
+
+ \sa selectedText()
+
+ \bold{Note:} The textInteractionFlags set on the label need to include
+ either TextSelectableByMouse or TextSelectableByKeyboard.
+
+ \since 4.7
+*/
+void QLabel::setSelection(int start, int length)
+{
+ Q_D(QLabel);
+ if (d->control) {
+ d->ensureTextPopulated();
+ QTextCursor cursor = d->control->textCursor();
+ cursor.setPosition(start);
+ cursor.setPosition(start + length, QTextCursor::KeepAnchor);
+ d->control->setTextCursor(cursor);
+ }
+}
+
+/*!
+ \property QLabel::hasSelectedText
+ \brief whether there is any text selected
+
+ hasSelectedText() returns true if some or all of the text has been
+ selected by the user; otherwise returns false.
+
+ By default, this property is false.
+
+ \sa selectedText()
+
+ \bold{Note:} The textInteractionFlags set on the label need to include
+ either TextSelectableByMouse or TextSelectableByKeyboard.
+
+ \since 4.7
+*/
+bool QLabel::hasSelectedText() const
+{
+ Q_D(const QLabel);
+ if (d->control)
+ return d->control->textCursor().hasSelection();
+ return false;
+}
+
+/*!
+ \property QLabel::selectedText
+ \brief the selected text
+
+ If there is no selected text this property's value is
+ an empty string.
+
+ By default, this property contains an empty string.
+
+ \sa hasSelectedText()
+
+ \bold{Note:} The textInteractionFlags set on the label need to include
+ either TextSelectableByMouse or TextSelectableByKeyboard.
+
+ \since 4.7
+*/
+QString QLabel::selectedText() const
+{
+ Q_D(const QLabel);
+ if (d->control)
+ return d->control->textCursor().selectedText();
+ return QString();
+}
+
+/*!
+ selectionStart() returns the index of the first selected character in the
+ label or -1 if no text is selected.
+
+ \sa selectedText()
+
+ \bold{Note:} The textInteractionFlags set on the label need to include
+ either TextSelectableByMouse or TextSelectableByKeyboard.
+
+ \since 4.7
+*/
+int QLabel::selectionStart() const
+{
+ Q_D(const QLabel);
+ if (d->control && d->control->textCursor().hasSelection())
+ return d->control->textCursor().selectionStart();
+ return -1;
+}
+
/*!\reimp
*/
QSize QLabel::sizeHint() const
@@ -862,8 +951,8 @@ void QLabel::contextMenuEvent(QContextMenuEvent *ev)
return;
}
ev->accept();
- menu->exec(ev->globalPos());
- delete menu;
+ menu->setAttribute(Qt::WA_DeleteOnClose);
+ menu->popup(ev->globalPos());
#endif
}
diff --git a/src/gui/widgets/qlabel.h b/src/gui/widgets/qlabel.h
index d916078da6..54babb1564 100644
--- a/src/gui/widgets/qlabel.h
+++ b/src/gui/widgets/qlabel.h
@@ -65,6 +65,8 @@ class Q_GUI_EXPORT QLabel : public QFrame
Q_PROPERTY(int indent READ indent WRITE setIndent)
Q_PROPERTY(bool openExternalLinks READ openExternalLinks WRITE setOpenExternalLinks)
Q_PROPERTY(Qt::TextInteractionFlags textInteractionFlags READ textInteractionFlags WRITE setTextInteractionFlags)
+ Q_PROPERTY(bool hasSelectedText READ hasSelectedText)
+ Q_PROPERTY(QString selectedText READ selectedText)
public:
explicit QLabel(QWidget *parent=0, Qt::WindowFlags f=0);
@@ -111,6 +113,11 @@ public:
void setTextInteractionFlags(Qt::TextInteractionFlags flags);
Qt::TextInteractionFlags textInteractionFlags() const;
+ void setSelection(int, int);
+ bool hasSelectedText() const;
+ QString selectedText() const;
+ int selectionStart() const;
+
public Q_SLOTS:
void setText(const QString &);
void setPixmap(const QPixmap &);
diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp
index 2d2df92278..141f844ada 100644
--- a/src/gui/widgets/qlineedit.cpp
+++ b/src/gui/widgets/qlineedit.cpp
@@ -2046,9 +2046,9 @@ void QLineEdit::dropEvent(QDropEvent* e)
*/
void QLineEdit::contextMenuEvent(QContextMenuEvent *event)
{
- QPointer<QMenu> menu = createStandardContextMenu();
- menu->exec(event->globalPos());
- delete menu;
+ QMenu *menu = createStandardContextMenu();
+ menu->setAttribute(Qt::WA_DeleteOnClose);
+ menu->popup(event->globalPos());
}
#if defined(Q_WS_WIN)
diff --git a/src/gui/widgets/qmainwindow.cpp b/src/gui/widgets/qmainwindow.cpp
index 269cd122eb..a63f3bf955 100644
--- a/src/gui/widgets/qmainwindow.cpp
+++ b/src/gui/widgets/qmainwindow.cpp
@@ -1393,6 +1393,7 @@ bool QMainWindow::event(QEvent *event)
#endif // QT_NO_STATUSTIP
case QEvent::StyleChange:
+ d->layout->layoutState.dockAreaLayout.styleChangedEvent();
if (!d->explicitIconSize)
setIconSize(QSize());
break;
@@ -1554,11 +1555,15 @@ void QMainWindow::contextMenuEvent(QContextMenuEvent *event)
#ifndef QT_NO_MENU
QMenu *popup = createPopupMenu();
- if (popup && !popup->isEmpty()) {
- popup->exec(event->globalPos());
- event->accept();
+ if (popup) {
+ if (!popup->isEmpty()) {
+ popup->setAttribute(Qt::WA_DeleteOnClose);
+ popup->popup(event->globalPos());
+ event->accept();
+ } else {
+ delete popup;
+ }
}
- delete popup;
#endif
}
#endif // QT_NO_CONTEXTMENU
diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp
index 8ce7cc0006..08960dae5c 100644
--- a/src/gui/widgets/qmenu.cpp
+++ b/src/gui/widgets/qmenu.cpp
@@ -2302,9 +2302,7 @@ void QMenu::mouseReleaseEvent(QMouseEvent *e)
QAction *action = d->actionAt(e->pos());
if (action && action == d->currentAction) {
- if (action->menu())
- action->menu()->d_func()->setFirstActionActive();
- else {
+ if (!action->menu()){
#if defined(Q_WS_WIN)
//On Windows only context menus can be activated with the right button
if (e->button() == Qt::LeftButton || d->topCausedWidget() == 0)
diff --git a/src/gui/widgets/qmenu.h b/src/gui/widgets/qmenu.h
index 5a6a5c786f..28bd859caa 100644
--- a/src/gui/widgets/qmenu.h
+++ b/src/gui/widgets/qmenu.h
@@ -415,6 +415,7 @@ private:
friend OSStatus qt_mac_menu_event(EventHandlerCallRef, EventRef, void *);
friend bool qt_mac_activate_action(OSMenuRef, uint, QAction::ActionEvent, bool);
friend void qt_mac_emit_menuSignals(QMenu *, bool);
+ friend void qt_mac_menu_emit_hovered(QMenu *menu, QAction *action);
#endif
};
diff --git a/src/gui/widgets/qmenu_mac.mm b/src/gui/widgets/qmenu_mac.mm
index 7e4bbb51ad..658a020859 100644
--- a/src/gui/widgets/qmenu_mac.mm
+++ b/src/gui/widgets/qmenu_mac.mm
@@ -247,7 +247,7 @@ bool qt_mac_activate_action(MenuRef menu, uint command, QAction::ActionEvent act
//now walk up firing for each "caused" widget (like in the platform independent menu)
QWidget *caused = 0;
- if (GetMenuItemProperty(menu, 0, kMenuCreatorQt, kMenuPropertyCausedQWidget, sizeof(caused), 0, &caused) == noErr) {
+ if (action_e == QAction::Hover && GetMenuItemProperty(menu, 0, kMenuCreatorQt, kMenuPropertyCausedQWidget, sizeof(caused), 0, &caused) == noErr) {
MenuRef caused_menu = 0;
if (QMenu *qmenu2 = qobject_cast<QMenu*>(caused))
caused_menu = qmenu2->macMenu();
@@ -260,25 +260,17 @@ bool qt_mac_activate_action(MenuRef menu, uint command, QAction::ActionEvent act
QWidget *widget = 0;
GetMenuItemProperty(caused_menu, 0, kMenuCreatorQt, kMenuPropertyQWidget, sizeof(widget), 0, &widget);
if (QMenu *qmenu = qobject_cast<QMenu*>(widget)) {
- if (action_e == QAction::Trigger) {
- emit qmenu->triggered(action->action);
- } else if (action_e == QAction::Hover) {
- action->action->showStatusText(widget);
- emit qmenu->hovered(action->action);
- }
+ action->action->showStatusText(widget);
+ emit qmenu->hovered(action->action);
} else if (QMenuBar *qmenubar = qobject_cast<QMenuBar*>(widget)) {
- if (action_e == QAction::Trigger) {
- emit qmenubar->triggered(action->action);
- } else if (action_e == QAction::Hover) {
- action->action->showStatusText(widget);
- emit qmenubar->hovered(action->action);
- }
+ action->action->showStatusText(widget);
+ emit qmenubar->hovered(action->action);
break; //nothing more..
}
//walk up
if (GetMenuItemProperty(caused_menu, 0, kMenuCreatorQt, kMenuPropertyCausedQWidget,
- sizeof(caused), 0, &caused) != noErr)
+ sizeof(caused), 0, &caused) != noErr)
break;
if (QMenu *qmenu2 = qobject_cast<QMenu*>(caused))
caused_menu = qmenu2->macMenu();
@@ -649,7 +641,7 @@ static NSMenuItem *createNSMenuItem(const QString &title)
NSMenuItem *item = [[NSMenuItem alloc]
initWithTitle:qt_mac_QStringToNSString(title)
action:@selector(qtDispatcherToQAction:) keyEquivalent:@""];
- [item setTarget:getMenuLoader()];
+ [item setTarget:nil];
return item;
}
#endif
@@ -749,32 +741,6 @@ bool qt_mac_menubar_is_open()
return qt_mac_menus_open_count > 0;
}
-void qt_mac_clear_menubar()
-{
- if (QApplication::testAttribute(Qt::AA_MacPluginApplication))
- return;
-
-#ifndef QT_MAC_USE_COCOA
- MenuRef clear_menu = 0;
- if (CreateNewMenu(0, 0, &clear_menu) == noErr) {
- SetRootMenu(clear_menu);
- ReleaseMenu(clear_menu);
- } else {
- qWarning("QMenu: Internal error at %s:%d", __FILE__, __LINE__);
- }
- ClearMenuBar();
- qt_mac_command_set_enabled(0, kHICommandPreferences, false);
- InvalMenuBar();
-#else
- QMacCocoaAutoReleasePool pool;
- QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader();
- NSMenu *menu = [loader menu];
- [loader ensureAppMenuInMenu:menu];
- [NSApp setMainMenu:menu];
-#endif
-}
-
-
QMacMenuAction::~QMacMenuAction()
{
#ifdef QT_MAC_USE_COCOA
@@ -1130,7 +1096,7 @@ QMenuPrivate::QMacMenuPrivate::addAction(QMacMenuAction *action, QMacMenuAction
action->menu = merge;
[cmd retain];
[cmd setAction:@selector(qtDispatcherToQAction:)];
- [cmd setTarget:getMenuLoader()];
+ [cmd setTarget:nil];
[action->menuItem release];
action->menuItem = cmd;
QMenuMergeList *list = QMenuPrivate::mergeMenuItemsHash.value(merge);
@@ -1936,43 +1902,53 @@ static bool qt_mac_is_ancestor(QWidget* possibleAncestor, QWidget *child)
Returns true if the entries of menuBar should be disabled,
based on the modality type of modalWidget.
*/
-static bool qt_mac_should_disable_menu(QMenuBar *menuBar, QWidget *modalWidget)
+static bool qt_mac_should_disable_menu(QMenuBar *menuBar)
{
- if (modalWidget == 0 || menuBar == 0)
+ QWidget *modalWidget = qApp->activeModalWidget();
+ if (!modalWidget)
+ return false;
+
+ if (menuBar && menuBar == menubars()->value(modalWidget))
+ // The menu bar is owned by the modal widget.
+ // In that case we should enable it:
return false;
- // If there is an application modal window on
- // screen, the entries of the menubar should be disabled:
+ // When there is an application modal window on screen, the entries of
+ // the menubar should be disabled. The exception in Qt is that if the
+ // modal window is the only window on screen, then we enable the menu bar.
QWidget *w = modalWidget;
+ QWidgetList topLevelWidgets = QApplication::topLevelWidgets();
while (w) {
- if (w->isVisible() && w->windowModality() == Qt::ApplicationModal)
- return true;
+ 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]) {
+ // INVARIANT: we found another visible window
+ // on screen other than our modalWidget. We therefore
+ // disable the menu bar to follow normal modality logic:
+ return true;
+ }
+ }
+ // INVARIANT: We have only one window on screen that happends
+ // to be application modal. We choose to enable the menu bar
+ // in that case to e.g. enable the quit menu item.
+ return false;
+ }
w = w->parentWidget();
}
// INVARIANT: modalWidget is window modal. Disable menu entries
- // if the menu bar belongs to an ancestor of modalWidget:
- return qt_mac_is_ancestor(menuBar->parentWidget(), modalWidget);
+ // if the menu bar belongs to an ancestor of modalWidget. If menuBar
+ // is nil, we understand it as the default menu bar set by the nib:
+ return menuBar ? qt_mac_is_ancestor(menuBar->parentWidget(), modalWidget) : false;
}
-/*!
- \internal
-
- This function will update the current menu bar and set it as the
- active menu bar in the Menu Manager.
-
- \warning This function is not portable.
-
- \sa QMenu::macMenu(), QMenuBar::macMenu()
-*/
-bool QMenuBar::macUpdateMenuBar()
+static QWidget *findWindowThatShouldDisplayMenubar()
{
- cancelAllMenuTracking();
- QMenuBar *mb = 0;
- //find a menu bar
QWidget *w = qApp->activeWindow();
-
if (!w) {
+ // We have no active window on screen. Try to
+ // find a window from the list of top levels:
QWidgetList tlws = QApplication::topLevelWidgets();
for(int i = 0; i < tlws.size(); ++i) {
QWidget *tlw = tlws.at(i);
@@ -1983,6 +1959,12 @@ bool QMenuBar::macUpdateMenuBar()
}
}
}
+ return w;
+}
+
+static QMenuBar *findMenubarForWindow(QWidget *w)
+{
+ QMenuBar *mb = 0;
if (w) {
mb = menubars()->value(w);
#ifndef QT_NO_MAINWINDOW
@@ -1996,11 +1978,65 @@ bool QMenuBar::macUpdateMenuBar()
while(w && !mb)
mb = menubars()->value((w = w->parentWidget()));
}
- if (!mb)
+
+ if (!mb) {
+ // We could not find a menu bar for the window. Lets
+ // check if we have a global (parentless) menu bar instead:
mb = fallback;
- //now set it
+ }
+
+ return mb;
+}
+
+void qt_mac_clear_menubar()
+{
+ if (QApplication::testAttribute(Qt::AA_MacPluginApplication))
+ return;
+
+#ifndef QT_MAC_USE_COCOA
+ MenuRef clear_menu = 0;
+ if (CreateNewMenu(0, 0, &clear_menu) == noErr) {
+ SetRootMenu(clear_menu);
+ ReleaseMenu(clear_menu);
+ } else {
+ qWarning("QMenu: Internal error at %s:%d", __FILE__, __LINE__);
+ }
+ ClearMenuBar();
+ qt_mac_command_set_enabled(0, kHICommandPreferences, false);
+ InvalMenuBar();
+#else
+ QMacCocoaAutoReleasePool pool;
+ QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *loader = getMenuLoader();
+ NSMenu *menu = [loader menu];
+ [loader ensureAppMenuInMenu:menu];
+ [NSApp setMainMenu:menu];
+ const bool modal = qt_mac_should_disable_menu(0);
+ if (qt_mac_current_menubar.qmenubar || modal != qt_mac_current_menubar.modal)
+ qt_mac_set_modal_state(menu, modal);
+ qt_mac_current_menubar.qmenubar = 0;
+ qt_mac_current_menubar.modal = modal;
+#endif
+}
+
+/*!
+ \internal
+
+ This function will update the current menu bar and set it as the
+ active menu bar in the Menu Manager.
+
+ \warning This function is not portable.
+
+ \sa QMenu::macMenu(), QMenuBar::macMenu()
+*/
+bool QMenuBar::macUpdateMenuBar()
+{
bool ret = false;
+ cancelAllMenuTracking();
+ QWidget *w = findWindowThatShouldDisplayMenubar();
+ QMenuBar *mb = findMenubarForWindow(w);
+
if (mb && mb->isNativeMenuBar()) {
+ bool modal = QApplicationPrivate::modalState();
#ifdef QT_MAC_USE_COCOA
QMacCocoaAutoReleasePool pool;
#endif
@@ -2030,16 +2066,18 @@ bool QMenuBar::macUpdateMenuBar()
}
}
#endif
- QWidget *modalWidget = qApp->activeModalWidget();
- if (mb != menubars()->value(modalWidget)) {
- qt_mac_set_modal_state(menu, qt_mac_should_disable_menu(mb, modalWidget));
- }
+ // Check if menu is modally shaddowed and should be disabled:
+ modal = qt_mac_should_disable_menu(mb);
+ if (mb != qt_mac_current_menubar.qmenubar || modal != qt_mac_current_menubar.modal)
+ qt_mac_set_modal_state(menu, modal);
}
qt_mac_current_menubar.qmenubar = mb;
- qt_mac_current_menubar.modal = QApplicationPrivate::modalState();
+ qt_mac_current_menubar.modal = modal;
ret = true;
} else if (qt_mac_current_menubar.qmenubar && qt_mac_current_menubar.qmenubar->isNativeMenuBar()) {
- const bool modal = QApplicationPrivate::modalState();
+ // INVARIANT: The currently active menu bar (if any) is not native. But we do have a
+ // native menu bar from before. So we need to decide whether or not is should be enabled:
+ const bool modal = qt_mac_should_disable_menu(qt_mac_current_menubar.qmenubar);
if (modal != qt_mac_current_menubar.modal) {
ret = true;
if (OSMenuRef menu = qt_mac_current_menubar.qmenubar->macMenu()) {
@@ -2051,14 +2089,12 @@ bool QMenuBar::macUpdateMenuBar()
[NSApp setMainMenu:menu];
syncMenuBarItemsVisiblity(qt_mac_current_menubar.qmenubar->d_func()->mac_menubar);
#endif
- QWidget *modalWidget = qApp->activeModalWidget();
- if (qt_mac_current_menubar.qmenubar != menubars()->value(modalWidget)) {
- qt_mac_set_modal_state(menu, qt_mac_should_disable_menu(mb, modalWidget));
- }
+ qt_mac_set_modal_state(menu, modal);
}
qt_mac_current_menubar.modal = modal;
}
}
+
if(!ret)
qt_mac_clear_menubar();
return ret;
diff --git a/src/gui/widgets/qplaintextedit.cpp b/src/gui/widgets/qplaintextedit.cpp
index ab598d9121..02ffe13668 100644
--- a/src/gui/widgets/qplaintextedit.cpp
+++ b/src/gui/widgets/qplaintextedit.cpp
@@ -911,6 +911,7 @@ void QPlainTextEditPrivate::pageUpDown(QTextCursor::MoveOperation op, QTextCurso
setTopBlock(block.blockNumber(), line);
if (moveCursor) {
+ cursor.setVisualNavigation(true);
// move using movePosition to keep the cursor's x
lastY += verticalOffset();
bool moved = false;
diff --git a/src/gui/widgets/qtabbar.cpp b/src/gui/widgets/qtabbar.cpp
index 22e825561b..7559311db6 100644
--- a/src/gui/widgets/qtabbar.cpp
+++ b/src/gui/widgets/qtabbar.cpp
@@ -1947,7 +1947,8 @@ void QTabBar::changeEvent(QEvent *event)
{
Q_D(QTabBar);
if (event->type() == QEvent::StyleChange) {
- d->elideMode = Qt::TextElideMode(style()->styleHint(QStyle::SH_TabBar_ElideMode, 0, this));
+ if (!d->elideModeSetByUser)
+ d->elideMode = Qt::TextElideMode(style()->styleHint(QStyle::SH_TabBar_ElideMode, 0, this));
if (!d->useScrollButtonsSetByUser)
d->useScrollButtons = !style()->styleHint(QStyle::SH_TabBar_PreferNoArrows, 0, this);
d->refresh();
@@ -1980,6 +1981,7 @@ void QTabBar::setElideMode(Qt::TextElideMode mode)
{
Q_D(QTabBar);
d->elideMode = mode;
+ d->elideModeSetByUser = true;
d->refresh();
}
diff --git a/src/gui/widgets/qtabbar_p.h b/src/gui/widgets/qtabbar_p.h
index 7588035961..83636e6b13 100644
--- a/src/gui/widgets/qtabbar_p.h
+++ b/src/gui/widgets/qtabbar_p.h
@@ -75,7 +75,7 @@ class QTabBarPrivate : public QWidgetPrivate
public:
QTabBarPrivate()
:currentIndex(-1), pressedIndex(-1), shape(QTabBar::RoundedNorth), layoutDirty(false),
- drawBase(true), scrollOffset(0), useScrollButtonsSetByUser(false) , expanding(true), closeButtonOnTabs(false),
+ drawBase(true), scrollOffset(0), elideModeSetByUser(false), useScrollButtonsSetByUser(false), expanding(true), closeButtonOnTabs(false),
selectionBehaviorOnRemove(QTabBar::SelectRightTab), paintWithOffsets(true), movable(false),
dragInProgress(false), documentMode(false), movingTab(0)
#ifdef Q_WS_MAC
@@ -186,6 +186,7 @@ public:
void makeVisible(int index);
QSize iconSize;
Qt::TextElideMode elideMode;
+ bool elideModeSetByUser;
bool useScrollButtons;
bool useScrollButtonsSetByUser;
diff --git a/src/gui/widgets/qtoolbar.cpp b/src/gui/widgets/qtoolbar.cpp
index 8beda554b1..7ed27ea33d 100644
--- a/src/gui/widgets/qtoolbar.cpp
+++ b/src/gui/widgets/qtoolbar.cpp
@@ -533,6 +533,14 @@ void QToolBarPrivate::plug(const QRect &r)
/*!
+ \fn void QToolBar::visibilityChanged(bool visible)
+ \since 4.7
+
+ This signal is emitted when the toolbar becomes \a visible (or
+ invisible). This happens when the widget is hidden or shown.
+*/
+
+/*!
Constructs a QToolBar with the given \a parent.
*/
QToolBar::QToolBar(QWidget *parent)
@@ -1122,6 +1130,7 @@ bool QToolBar::event(QEvent *event)
// fallthrough intended
case QEvent::Show:
d->toggleViewAction->setChecked(event->type() == QEvent::Show);
+ emit visibilityChanged(event->type() == QEvent::Show);
#if defined(Q_WS_MAC)
if (toolbarInUnifiedToolBar(this)) {
// I can static_cast because I did the qobject_cast in the if above, therefore
diff --git a/src/gui/widgets/qtoolbar.h b/src/gui/widgets/qtoolbar.h
index 90f20dd43b..b733477fd0 100644
--- a/src/gui/widgets/qtoolbar.h
+++ b/src/gui/widgets/qtoolbar.h
@@ -143,6 +143,7 @@ Q_SIGNALS:
void iconSizeChanged(const QSize &iconSize);
void toolButtonStyleChanged(Qt::ToolButtonStyle toolButtonStyle);
void topLevelChanged(bool topLevel);
+ void visibilityChanged(bool visible);
protected:
void actionEvent(QActionEvent *event);
diff --git a/src/gui/widgets/qvalidator.cpp b/src/gui/widgets/qvalidator.cpp
index a5276d38bf..0b5cc5ab10 100644
--- a/src/gui/widgets/qvalidator.cpp
+++ b/src/gui/widgets/qvalidator.cpp
@@ -400,8 +400,10 @@ QValidator::State QIntValidator::validate(QString & input, int&) const
qlonglong entered = QLocalePrivate::bytearrayToLongLong(buff.constData(), 10, &ok, &overflow);
if (overflow || !ok)
return Invalid;
- if (entered >= b && entered <= t)
- return Acceptable;
+ if (entered >= b && entered <= t) {
+ locale().toInt(input, &ok);
+ return ok ? Acceptable : Intermediate;
+ }
if (entered >= 0) {
// the -entered < b condition is necessary to allow people to type
@@ -412,6 +414,20 @@ QValidator::State QIntValidator::validate(QString & input, int&) const
}
}
+/*! \reimp */
+void QIntValidator::fixup(QString &input) const
+{
+ QByteArray buff;
+ if (!locale().d()->validateChars(input, QLocalePrivate::IntegerMode, &buff)) {
+ QLocale cl(QLocale::C);
+ if (!cl.d()->validateChars(input, QLocalePrivate::IntegerMode, &buff))
+ return;
+ }
+ bool ok, overflow;
+ qlonglong entered = QLocalePrivate::bytearrayToLongLong(buff.constData(), 10, &ok, &overflow);
+ if (ok && !overflow)
+ input = locale().toString(entered);
+}
/*!
Sets the range of the validator to only accept integers between \a
diff --git a/src/gui/widgets/qvalidator.h b/src/gui/widgets/qvalidator.h
index 30afbd6713..e996a0128d 100644
--- a/src/gui/widgets/qvalidator.h
+++ b/src/gui/widgets/qvalidator.h
@@ -105,6 +105,7 @@ public:
~QIntValidator();
QValidator::State validate(QString &, int &) const;
+ void fixup(QString &input) const;
void setBottom(int);
void setTop(int);