summaryrefslogtreecommitdiffstats
path: root/src/widgets/dialogs
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2011-05-07 00:02:01 +0200
committerLars Knoll <lars.knoll@nokia.com>2011-05-07 00:02:01 +0200
commitf67b8df3ebdba2d398b9cce686b7c644adffff08 (patch)
tree062dd469f7cf8daa01a32d3e7b767b8fbdb7573a /src/widgets/dialogs
parent32ce4fe9e6a94e77828e976776cf08da85254ff2 (diff)
library split
Diffstat (limited to 'src/widgets/dialogs')
-rw-r--r--src/widgets/dialogs/dialogs.pri106
-rw-r--r--src/widgets/dialogs/images/fit-page-24.pngbin0 -> 985 bytes
-rw-r--r--src/widgets/dialogs/images/fit-page-32.pngbin0 -> 1330 bytes
-rw-r--r--src/widgets/dialogs/images/fit-width-24.pngbin0 -> 706 bytes
-rw-r--r--src/widgets/dialogs/images/fit-width-32.pngbin0 -> 1004 bytes
-rw-r--r--src/widgets/dialogs/images/go-first-24.pngbin0 -> 796 bytes
-rw-r--r--src/widgets/dialogs/images/go-first-32.pngbin0 -> 985 bytes
-rw-r--r--src/widgets/dialogs/images/go-last-24.pngbin0 -> 792 bytes
-rw-r--r--src/widgets/dialogs/images/go-last-32.pngbin0 -> 984 bytes
-rw-r--r--src/widgets/dialogs/images/go-next-24.pngbin0 -> 782 bytes
-rw-r--r--src/widgets/dialogs/images/go-next-32.pngbin0 -> 948 bytes
-rw-r--r--src/widgets/dialogs/images/go-previous-24.pngbin0 -> 797 bytes
-rw-r--r--src/widgets/dialogs/images/go-previous-32.pngbin0 -> 945 bytes
-rw-r--r--src/widgets/dialogs/images/layout-landscape-24.pngbin0 -> 820 bytes
-rw-r--r--src/widgets/dialogs/images/layout-landscape-32.pngbin0 -> 1353 bytes
-rw-r--r--src/widgets/dialogs/images/layout-portrait-24.pngbin0 -> 817 bytes
-rw-r--r--src/widgets/dialogs/images/layout-portrait-32.pngbin0 -> 1330 bytes
-rw-r--r--src/widgets/dialogs/images/page-setup-24.pngbin0 -> 620 bytes
-rw-r--r--src/widgets/dialogs/images/page-setup-32.pngbin0 -> 1154 bytes
-rw-r--r--src/widgets/dialogs/images/print-24.pngbin0 -> 914 bytes
-rw-r--r--src/widgets/dialogs/images/print-32.pngbin0 -> 1202 bytes
-rw-r--r--src/widgets/dialogs/images/qtlogo-64.pngbin0 -> 2991 bytes
-rw-r--r--src/widgets/dialogs/images/status-color.pngbin0 -> 1475 bytes
-rw-r--r--src/widgets/dialogs/images/status-gray-scale.pngbin0 -> 1254 bytes
-rw-r--r--src/widgets/dialogs/images/view-page-multi-24.pngbin0 -> 390 bytes
-rw-r--r--src/widgets/dialogs/images/view-page-multi-32.pngbin0 -> 556 bytes
-rw-r--r--src/widgets/dialogs/images/view-page-one-24.pngbin0 -> 662 bytes
-rw-r--r--src/widgets/dialogs/images/view-page-one-32.pngbin0 -> 810 bytes
-rw-r--r--src/widgets/dialogs/images/view-page-sided-24.pngbin0 -> 700 bytes
-rw-r--r--src/widgets/dialogs/images/view-page-sided-32.pngbin0 -> 908 bytes
-rw-r--r--src/widgets/dialogs/images/zoom-in-24.pngbin0 -> 1302 bytes
-rw-r--r--src/widgets/dialogs/images/zoom-in-32.pngbin0 -> 1873 bytes
-rw-r--r--src/widgets/dialogs/images/zoom-out-24.pngbin0 -> 1247 bytes
-rw-r--r--src/widgets/dialogs/images/zoom-out-32.pngbin0 -> 1749 bytes
-rw-r--r--src/widgets/dialogs/qabstractpagesetupdialog.cpp139
-rw-r--r--src/widgets/dialogs/qabstractpagesetupdialog.h82
-rw-r--r--src/widgets/dialogs/qabstractpagesetupdialog_p.h88
-rw-r--r--src/widgets/dialogs/qabstractprintdialog.cpp499
-rw-r--r--src/widgets/dialogs/qabstractprintdialog.h130
-rw-r--r--src/widgets/dialogs/qabstractprintdialog_p.h99
-rw-r--r--src/widgets/dialogs/qcolordialog.cpp2115
-rw-r--r--src/widgets/dialogs/qcolordialog.h150
-rw-r--r--src/widgets/dialogs/qcolordialog_mac.mm500
-rw-r--r--src/widgets/dialogs/qcolordialog_p.h142
-rw-r--r--src/widgets/dialogs/qcolordialog_symbian.cpp107
-rw-r--r--src/widgets/dialogs/qdialog.cpp1272
-rw-r--r--src/widgets/dialogs/qdialog.h140
-rw-r--r--src/widgets/dialogs/qdialog_p.h113
-rw-r--r--src/widgets/dialogs/qdialogsbinarycompat_win.cpp137
-rw-r--r--src/widgets/dialogs/qerrormessage.cpp429
-rw-r--r--src/widgets/dialogs/qerrormessage.h88
-rw-r--r--src/widgets/dialogs/qfiledialog.cpp3486
-rw-r--r--src/widgets/dialogs/qfiledialog.h331
-rw-r--r--src/widgets/dialogs/qfiledialog.ui356
-rw-r--r--src/widgets/dialogs/qfiledialog_embedded.ui340
-rw-r--r--src/widgets/dialogs/qfiledialog_mac.mm1157
-rw-r--r--src/widgets/dialogs/qfiledialog_p.h427
-rw-r--r--src/widgets/dialogs/qfiledialog_symbian.cpp199
-rw-r--r--src/widgets/dialogs/qfiledialog_win.cpp825
-rw-r--r--src/widgets/dialogs/qfiledialog_win_p.h243
-rw-r--r--src/widgets/dialogs/qfileinfogatherer.cpp355
-rw-r--r--src/widgets/dialogs/qfileinfogatherer_p.h207
-rw-r--r--src/widgets/dialogs/qfilesystemmodel.cpp2027
-rw-r--r--src/widgets/dialogs/qfilesystemmodel.h180
-rw-r--r--src/widgets/dialogs/qfilesystemmodel_p.h337
-rw-r--r--src/widgets/dialogs/qfontdialog.cpp1077
-rw-r--r--src/widgets/dialogs/qfontdialog.h147
-rw-r--r--src/widgets/dialogs/qfontdialog_mac.mm699
-rw-r--r--src/widgets/dialogs/qfontdialog_p.h166
-rw-r--r--src/widgets/dialogs/qfscompleter_p.h82
-rw-r--r--src/widgets/dialogs/qinputdialog.cpp1489
-rw-r--r--src/widgets/dialogs/qinputdialog.h256
-rw-r--r--src/widgets/dialogs/qmessagebox.cpp2751
-rw-r--r--src/widgets/dialogs/qmessagebox.h365
-rw-r--r--src/widgets/dialogs/qmessagebox.qrc5
-rw-r--r--src/widgets/dialogs/qnspanelproxy_mac.mm228
-rw-r--r--src/widgets/dialogs/qpagesetupdialog.cpp240
-rw-r--r--src/widgets/dialogs/qpagesetupdialog.h112
-rw-r--r--src/widgets/dialogs/qpagesetupdialog_mac.mm315
-rw-r--r--src/widgets/dialogs/qpagesetupdialog_unix.cpp620
-rw-r--r--src/widgets/dialogs/qpagesetupdialog_unix_p.h105
-rw-r--r--src/widgets/dialogs/qpagesetupdialog_win.cpp168
-rw-r--r--src/widgets/dialogs/qpagesetupwidget.ui353
-rw-r--r--src/widgets/dialogs/qprintdialog.h174
-rw-r--r--src/widgets/dialogs/qprintdialog.qdoc58
-rw-r--r--src/widgets/dialogs/qprintdialog.qrc38
-rw-r--r--src/widgets/dialogs/qprintdialog_mac.mm429
-rw-r--r--src/widgets/dialogs/qprintdialog_unix.cpp1286
-rw-r--r--src/widgets/dialogs/qprintdialog_win.cpp316
-rw-r--r--src/widgets/dialogs/qprintpreviewdialog.cpp803
-rw-r--r--src/widgets/dialogs/qprintpreviewdialog.h107
-rw-r--r--src/widgets/dialogs/qprintpropertieswidget.ui70
-rw-r--r--src/widgets/dialogs/qprintsettingsoutput.ui363
-rw-r--r--src/widgets/dialogs/qprintwidget.ui116
-rw-r--r--src/widgets/dialogs/qprogressdialog.cpp907
-rw-r--r--src/widgets/dialogs/qprogressdialog.h145
-rw-r--r--src/widgets/dialogs/qsidebar.cpp509
-rw-r--r--src/widgets/dialogs/qsidebar_p.h158
-rw-r--r--src/widgets/dialogs/qwizard.cpp3928
-rw-r--r--src/widgets/dialogs/qwizard.h268
-rw-r--r--src/widgets/dialogs/qwizard_win.cpp759
-rw-r--r--src/widgets/dialogs/qwizard_win_p.h158
102 files changed, 36576 insertions, 0 deletions
diff --git a/src/widgets/dialogs/dialogs.pri b/src/widgets/dialogs/dialogs.pri
new file mode 100644
index 0000000000..472787a20c
--- /dev/null
+++ b/src/widgets/dialogs/dialogs.pri
@@ -0,0 +1,106 @@
+# Qt dialogs module
+
+HEADERS += \
+ dialogs/qabstractprintdialog.h \
+ dialogs/qabstractprintdialog_p.h \
+ dialogs/qabstractpagesetupdialog.h \
+ dialogs/qabstractpagesetupdialog_p.h \
+ dialogs/qcolordialog.h \
+ dialogs/qcolordialog_p.h \
+ dialogs/qfscompleter_p.h \
+ dialogs/qdialog.h \
+ dialogs/qdialog_p.h \
+ dialogs/qerrormessage.h \
+ dialogs/qfiledialog.h \
+ dialogs/qfiledialog_p.h \
+ dialogs/qfontdialog.h \
+ dialogs/qfontdialog_p.h \
+ dialogs/qinputdialog.h \
+ dialogs/qmessagebox.h \
+ dialogs/qpagesetupdialog.h \
+ dialogs/qprintdialog.h \
+ dialogs/qprogressdialog.h \
+ dialogs/qsidebar_p.h \
+ dialogs/qfilesystemmodel.h \
+ dialogs/qfilesystemmodel_p.h \
+ dialogs/qfileinfogatherer_p.h \
+ dialogs/qwizard.h \
+ dialogs/qprintpreviewdialog.h
+
+!qpa:mac {
+ OBJECTIVE_SOURCES += dialogs/qfiledialog_mac.mm \
+ dialogs/qfontdialog_mac.mm \
+ dialogs/qnspanelproxy_mac.mm \
+ dialogs/qpagesetupdialog_mac.mm \
+ dialogs/qprintdialog_mac.mm
+
+# Compile qcolordialog_mac.mm with exception support, disregarding the -no-exceptions
+# configure option. (qcolordialog_mac needs to catch exceptions thrown by cocoa)
+ EXCEPTION_SOURCES = dialogs/qcolordialog_mac.mm
+ exceptions_compiler.commands = $$QMAKE_CXX -c
+ exceptions_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT}
+ exceptions_compiler.commands += -fexceptions
+ exceptions_compiler.dependency_type = TYPE_C
+ exceptions_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)}
+ exceptions_compiler.input = EXCEPTION_SOURCES
+ exceptions_compiler.variable_out = OBJECTS
+ exceptions_compiler.name = compiling[exceptopns] ${QMAKE_FILE_IN}
+ silent:exceptions_compiler.commands = @echo compiling[exceptopns] ${QMAKE_FILE_IN} && $$exceptions_compiler.commands
+ QMAKE_EXTRA_COMPILERS += exceptions_compiler
+}
+
+win32 {
+ HEADERS += dialogs/qwizard_win_p.h \
+ dialogs/qfiledialog_win_p.h
+ SOURCES += dialogs/qdialogsbinarycompat_win.cpp \
+ dialogs/qfiledialog_win.cpp \
+ dialogs/qpagesetupdialog_win.cpp \
+ dialogs/qprintdialog_win.cpp \
+ dialogs/qwizard_win.cpp
+
+ !win32-borland:!wince*: LIBS += -lshell32 # the filedialog needs this library
+}
+
+!mac:!symbian:unix|qpa {
+ HEADERS += dialogs/qpagesetupdialog_unix_p.h
+ SOURCES += dialogs/qprintdialog_unix.cpp \
+ dialogs/qpagesetupdialog_unix.cpp
+ FORMS += dialogs/qprintsettingsoutput.ui \
+ dialogs/qprintwidget.ui \
+ dialogs/qprintpropertieswidget.ui
+}
+
+wince*|symbian: FORMS += dialogs/qfiledialog_embedded.ui
+else: FORMS += dialogs/qfiledialog.ui
+
+INCLUDEPATH += $$PWD
+SOURCES += \
+ dialogs/qabstractprintdialog.cpp \
+ dialogs/qabstractpagesetupdialog.cpp \
+ dialogs/qcolordialog.cpp \
+ dialogs/qdialog.cpp \
+ dialogs/qerrormessage.cpp \
+ dialogs/qfiledialog.cpp \
+ dialogs/qfontdialog.cpp \
+ dialogs/qinputdialog.cpp \
+ dialogs/qmessagebox.cpp \
+ dialogs/qprogressdialog.cpp \
+ dialogs/qsidebar.cpp \
+ dialogs/qfilesystemmodel.cpp \
+ dialogs/qfileinfogatherer.cpp \
+ dialogs/qpagesetupdialog.cpp \
+ dialogs/qwizard.cpp \
+ dialogs/qprintpreviewdialog.cpp
+
+symbian:contains(QT_CONFIG, s60) {
+ LIBS += -lCommonDialogs
+ SOURCES += dialogs/qfiledialog_symbian.cpp \
+ dialogs/qcolordialog_symbian.cpp
+}
+
+FORMS += dialogs/qpagesetupwidget.ui
+RESOURCES += dialogs/qprintdialog.qrc
+RESOURCES += dialogs/qmessagebox.qrc
+
+# Compensate for lack of platform defines in Symbian3
+symbian: DEFINES += SYMBIAN_VERSION_$$upper($$replace(SYMBIAN_VERSION,\\.,_))
diff --git a/src/widgets/dialogs/images/fit-page-24.png b/src/widgets/dialogs/images/fit-page-24.png
new file mode 100644
index 0000000000..c7b39d8853
--- /dev/null
+++ b/src/widgets/dialogs/images/fit-page-24.png
Binary files differ
diff --git a/src/widgets/dialogs/images/fit-page-32.png b/src/widgets/dialogs/images/fit-page-32.png
new file mode 100644
index 0000000000..98bc12d3ed
--- /dev/null
+++ b/src/widgets/dialogs/images/fit-page-32.png
Binary files differ
diff --git a/src/widgets/dialogs/images/fit-width-24.png b/src/widgets/dialogs/images/fit-width-24.png
new file mode 100644
index 0000000000..a729ffda54
--- /dev/null
+++ b/src/widgets/dialogs/images/fit-width-24.png
Binary files differ
diff --git a/src/widgets/dialogs/images/fit-width-32.png b/src/widgets/dialogs/images/fit-width-32.png
new file mode 100644
index 0000000000..470a8b45d0
--- /dev/null
+++ b/src/widgets/dialogs/images/fit-width-32.png
Binary files differ
diff --git a/src/widgets/dialogs/images/go-first-24.png b/src/widgets/dialogs/images/go-first-24.png
new file mode 100644
index 0000000000..55315ffa38
--- /dev/null
+++ b/src/widgets/dialogs/images/go-first-24.png
Binary files differ
diff --git a/src/widgets/dialogs/images/go-first-32.png b/src/widgets/dialogs/images/go-first-32.png
new file mode 100644
index 0000000000..0fe6f94b77
--- /dev/null
+++ b/src/widgets/dialogs/images/go-first-32.png
Binary files differ
diff --git a/src/widgets/dialogs/images/go-last-24.png b/src/widgets/dialogs/images/go-last-24.png
new file mode 100644
index 0000000000..81061b80f2
--- /dev/null
+++ b/src/widgets/dialogs/images/go-last-24.png
Binary files differ
diff --git a/src/widgets/dialogs/images/go-last-32.png b/src/widgets/dialogs/images/go-last-32.png
new file mode 100644
index 0000000000..887506107e
--- /dev/null
+++ b/src/widgets/dialogs/images/go-last-32.png
Binary files differ
diff --git a/src/widgets/dialogs/images/go-next-24.png b/src/widgets/dialogs/images/go-next-24.png
new file mode 100644
index 0000000000..9a55ef3d86
--- /dev/null
+++ b/src/widgets/dialogs/images/go-next-24.png
Binary files differ
diff --git a/src/widgets/dialogs/images/go-next-32.png b/src/widgets/dialogs/images/go-next-32.png
new file mode 100644
index 0000000000..6d98f50f4f
--- /dev/null
+++ b/src/widgets/dialogs/images/go-next-32.png
Binary files differ
diff --git a/src/widgets/dialogs/images/go-previous-24.png b/src/widgets/dialogs/images/go-previous-24.png
new file mode 100644
index 0000000000..2ea769eb8d
--- /dev/null
+++ b/src/widgets/dialogs/images/go-previous-24.png
Binary files differ
diff --git a/src/widgets/dialogs/images/go-previous-32.png b/src/widgets/dialogs/images/go-previous-32.png
new file mode 100644
index 0000000000..37ba0c4e8d
--- /dev/null
+++ b/src/widgets/dialogs/images/go-previous-32.png
Binary files differ
diff --git a/src/widgets/dialogs/images/layout-landscape-24.png b/src/widgets/dialogs/images/layout-landscape-24.png
new file mode 100644
index 0000000000..6f89a31cb6
--- /dev/null
+++ b/src/widgets/dialogs/images/layout-landscape-24.png
Binary files differ
diff --git a/src/widgets/dialogs/images/layout-landscape-32.png b/src/widgets/dialogs/images/layout-landscape-32.png
new file mode 100644
index 0000000000..6a94946c36
--- /dev/null
+++ b/src/widgets/dialogs/images/layout-landscape-32.png
Binary files differ
diff --git a/src/widgets/dialogs/images/layout-portrait-24.png b/src/widgets/dialogs/images/layout-portrait-24.png
new file mode 100644
index 0000000000..e0dbabc83b
--- /dev/null
+++ b/src/widgets/dialogs/images/layout-portrait-24.png
Binary files differ
diff --git a/src/widgets/dialogs/images/layout-portrait-32.png b/src/widgets/dialogs/images/layout-portrait-32.png
new file mode 100644
index 0000000000..d17468c0a4
--- /dev/null
+++ b/src/widgets/dialogs/images/layout-portrait-32.png
Binary files differ
diff --git a/src/widgets/dialogs/images/page-setup-24.png b/src/widgets/dialogs/images/page-setup-24.png
new file mode 100644
index 0000000000..4bfafdace0
--- /dev/null
+++ b/src/widgets/dialogs/images/page-setup-24.png
Binary files differ
diff --git a/src/widgets/dialogs/images/page-setup-32.png b/src/widgets/dialogs/images/page-setup-32.png
new file mode 100644
index 0000000000..2313b8fe3b
--- /dev/null
+++ b/src/widgets/dialogs/images/page-setup-32.png
Binary files differ
diff --git a/src/widgets/dialogs/images/print-24.png b/src/widgets/dialogs/images/print-24.png
new file mode 100644
index 0000000000..c6bf3e8672
--- /dev/null
+++ b/src/widgets/dialogs/images/print-24.png
Binary files differ
diff --git a/src/widgets/dialogs/images/print-32.png b/src/widgets/dialogs/images/print-32.png
new file mode 100644
index 0000000000..5830888653
--- /dev/null
+++ b/src/widgets/dialogs/images/print-32.png
Binary files differ
diff --git a/src/widgets/dialogs/images/qtlogo-64.png b/src/widgets/dialogs/images/qtlogo-64.png
new file mode 100644
index 0000000000..4f68e162de
--- /dev/null
+++ b/src/widgets/dialogs/images/qtlogo-64.png
Binary files differ
diff --git a/src/widgets/dialogs/images/status-color.png b/src/widgets/dialogs/images/status-color.png
new file mode 100644
index 0000000000..af3cbfa31c
--- /dev/null
+++ b/src/widgets/dialogs/images/status-color.png
Binary files differ
diff --git a/src/widgets/dialogs/images/status-gray-scale.png b/src/widgets/dialogs/images/status-gray-scale.png
new file mode 100644
index 0000000000..4462588809
--- /dev/null
+++ b/src/widgets/dialogs/images/status-gray-scale.png
Binary files differ
diff --git a/src/widgets/dialogs/images/view-page-multi-24.png b/src/widgets/dialogs/images/view-page-multi-24.png
new file mode 100644
index 0000000000..87241472ae
--- /dev/null
+++ b/src/widgets/dialogs/images/view-page-multi-24.png
Binary files differ
diff --git a/src/widgets/dialogs/images/view-page-multi-32.png b/src/widgets/dialogs/images/view-page-multi-32.png
new file mode 100644
index 0000000000..130885a041
--- /dev/null
+++ b/src/widgets/dialogs/images/view-page-multi-32.png
Binary files differ
diff --git a/src/widgets/dialogs/images/view-page-one-24.png b/src/widgets/dialogs/images/view-page-one-24.png
new file mode 100644
index 0000000000..4c6457b892
--- /dev/null
+++ b/src/widgets/dialogs/images/view-page-one-24.png
Binary files differ
diff --git a/src/widgets/dialogs/images/view-page-one-32.png b/src/widgets/dialogs/images/view-page-one-32.png
new file mode 100644
index 0000000000..537193984e
--- /dev/null
+++ b/src/widgets/dialogs/images/view-page-one-32.png
Binary files differ
diff --git a/src/widgets/dialogs/images/view-page-sided-24.png b/src/widgets/dialogs/images/view-page-sided-24.png
new file mode 100644
index 0000000000..2131305c41
--- /dev/null
+++ b/src/widgets/dialogs/images/view-page-sided-24.png
Binary files differ
diff --git a/src/widgets/dialogs/images/view-page-sided-32.png b/src/widgets/dialogs/images/view-page-sided-32.png
new file mode 100644
index 0000000000..e4d63f9992
--- /dev/null
+++ b/src/widgets/dialogs/images/view-page-sided-32.png
Binary files differ
diff --git a/src/widgets/dialogs/images/zoom-in-24.png b/src/widgets/dialogs/images/zoom-in-24.png
new file mode 100644
index 0000000000..d29b142b6c
--- /dev/null
+++ b/src/widgets/dialogs/images/zoom-in-24.png
Binary files differ
diff --git a/src/widgets/dialogs/images/zoom-in-32.png b/src/widgets/dialogs/images/zoom-in-32.png
new file mode 100644
index 0000000000..34d70af37b
--- /dev/null
+++ b/src/widgets/dialogs/images/zoom-in-32.png
Binary files differ
diff --git a/src/widgets/dialogs/images/zoom-out-24.png b/src/widgets/dialogs/images/zoom-out-24.png
new file mode 100644
index 0000000000..19703474f8
--- /dev/null
+++ b/src/widgets/dialogs/images/zoom-out-24.png
Binary files differ
diff --git a/src/widgets/dialogs/images/zoom-out-32.png b/src/widgets/dialogs/images/zoom-out-32.png
new file mode 100644
index 0000000000..b832206612
--- /dev/null
+++ b/src/widgets/dialogs/images/zoom-out-32.png
Binary files differ
diff --git a/src/widgets/dialogs/qabstractpagesetupdialog.cpp b/src/widgets/dialogs/qabstractpagesetupdialog.cpp
new file mode 100644
index 0000000000..080ddeaa85
--- /dev/null
+++ b/src/widgets/dialogs/qabstractpagesetupdialog.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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 "qabstractpagesetupdialog.h"
+#include "qabstractpagesetupdialog_p.h"
+
+#ifndef QT_NO_PRINTDIALOG
+
+#include <QtCore/qcoreapplication.h>
+#include <QtGui/qprinter.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+ \class QAbstractPageSetupDialog
+
+ \brief The QAbstractPageSetupDialog class provides a base for
+ implementations of page setup dialogs.
+*/
+
+/*!
+ Constructs the page setup dialog for the printer \a printer with
+ \a parent as parent widget.
+*/
+QAbstractPageSetupDialog::QAbstractPageSetupDialog(QPrinter *printer, QWidget *parent)
+ : QDialog(*(new QAbstractPageSetupDialogPrivate), parent)
+{
+ Q_D(QAbstractPageSetupDialog);
+ setWindowTitle(QCoreApplication::translate("QPrintPreviewDialog", "Page Setup"));
+ d->setPrinter(printer);
+}
+
+/*!
+ \internal
+*/
+QAbstractPageSetupDialog::QAbstractPageSetupDialog(QAbstractPageSetupDialogPrivate &ptr,
+ QPrinter *printer, QWidget *parent)
+ : QDialog(ptr, parent)
+{
+ Q_D(QAbstractPageSetupDialog);
+ setWindowTitle(QCoreApplication::translate("QPrintPreviewDialog", "Page Setup"));
+ d->setPrinter(printer);
+}
+
+QAbstractPageSetupDialog::~QAbstractPageSetupDialog()
+{
+ Q_D(QAbstractPageSetupDialog);
+ if (d->opts & QPageSetupDialog::OwnsPrinter)
+ delete d->printer;
+}
+
+/*!
+ Returns the printer that this page setup dialog is operating on.
+*/
+QPrinter *QAbstractPageSetupDialog::printer()
+{
+ Q_D(QAbstractPageSetupDialog);
+ return d->printer;
+}
+
+void QAbstractPageSetupDialogPrivate::setPrinter(QPrinter *newPrinter)
+{
+ if (newPrinter) {
+ printer = newPrinter;
+ } else {
+ printer = new QPrinter;
+ opts |= QPageSetupDialog::OwnsPrinter;
+ }
+#ifndef Q_WS_X11
+ if (printer->outputFormat() != QPrinter::NativeFormat)
+ qWarning("QPageSetupDialog: Cannot be used on non-native printers");
+#endif
+}
+
+/*!
+ \fn int QAbstractPageSetupDialog::exec()
+
+ This virtual function is called to pop up the dialog. It must be
+ reimplemented in subclasses.
+*/
+
+/*!
+ \reimp
+*/
+void QAbstractPageSetupDialog::done(int result)
+{
+ Q_D(QAbstractPageSetupDialog);
+ QDialog::done(result);
+ if (d->receiverToDisconnectOnClose) {
+ disconnect(this, SIGNAL(accepted()),
+ d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);
+ d->receiverToDisconnectOnClose = 0;
+ }
+ d->memberToDisconnectOnClose.clear();
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_PRINTDIALOG
diff --git a/src/widgets/dialogs/qabstractpagesetupdialog.h b/src/widgets/dialogs/qabstractpagesetupdialog.h
new file mode 100644
index 0000000000..ac3ffa5451
--- /dev/null
+++ b/src/widgets/dialogs/qabstractpagesetupdialog.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTPAGESETUPDIALOG_H
+#define QABSTRACTPAGESETUPDIALOG_H
+
+#include <QtGui/qdialog.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_PRINTDIALOG
+
+class QAbstractPageSetupDialogPrivate;
+class QPrinter;
+
+// ### Qt 5: Remove this class
+class Q_GUI_EXPORT QAbstractPageSetupDialog : public QDialog
+{
+ Q_DECLARE_PRIVATE(QAbstractPageSetupDialog)
+ Q_OBJECT
+
+public:
+ explicit QAbstractPageSetupDialog(QPrinter *printer, QWidget *parent = 0);
+ QAbstractPageSetupDialog(QAbstractPageSetupDialogPrivate &ptr,
+ QPrinter *printer, QWidget *parent = 0);
+ ~QAbstractPageSetupDialog();
+
+ virtual int exec() = 0;
+ void done(int result);
+
+ QPrinter *printer();
+};
+
+#endif // QT_NO_PRINTDIALOG
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QABSTRACTPAGESETUPDIALOG_H
diff --git a/src/widgets/dialogs/qabstractpagesetupdialog_p.h b/src/widgets/dialogs/qabstractpagesetupdialog_p.h
new file mode 100644
index 0000000000..3dbfdd5e26
--- /dev/null
+++ b/src/widgets/dialogs/qabstractpagesetupdialog_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTPAGESETUPDIALOG_P_H
+#define QABSTRACTPAGESETUPDIALOG_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+//
+
+#include "private/qdialog_p.h"
+
+#ifndef QT_NO_PRINTDIALOG
+
+#include "qbytearray.h"
+#include "qpagesetupdialog.h"
+#include "qpointer.h"
+
+QT_BEGIN_NAMESPACE
+
+class QPrinter;
+
+class QAbstractPageSetupDialogPrivate : public QDialogPrivate
+{
+ Q_DECLARE_PUBLIC(QAbstractPageSetupDialog)
+
+public:
+ QAbstractPageSetupDialogPrivate() : printer(0) {}
+
+ void setPrinter(QPrinter *newPrinter);
+
+ QPrinter *printer;
+ QPageSetupDialog::PageSetupDialogOptions opts;
+ QPointer<QObject> receiverToDisconnectOnClose;
+ QByteArray memberToDisconnectOnClose;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_PRINTDIALOG
+
+#endif // QABSTRACTPAGESETUPDIALOG_P_H
diff --git a/src/widgets/dialogs/qabstractprintdialog.cpp b/src/widgets/dialogs/qabstractprintdialog.cpp
new file mode 100644
index 0000000000..004f6877e4
--- /dev/null
+++ b/src/widgets/dialogs/qabstractprintdialog.cpp
@@ -0,0 +1,499 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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 "qabstractprintdialog_p.h"
+#include "qcoreapplication.h"
+#include "qprintdialog.h"
+#include "qprinter.h"
+#include "private/qprinter_p.h"
+
+#ifndef QT_NO_PRINTDIALOG
+
+QT_BEGIN_NAMESPACE
+
+// hack
+class QPrintDialogPrivate : public QAbstractPrintDialogPrivate
+{
+};
+
+/*!
+ \class QAbstractPrintDialog
+ \brief The QAbstractPrintDialog class provides a base implementation for
+ print dialogs used to configure printers.
+
+ \ingroup printing
+
+ This class implements getter and setter functions that are used to
+ customize settings shown in print dialogs, but it is not used directly.
+ Use QPrintDialog to display a print dialog in your application.
+
+ In Symbian, there is no support for printing. Hence, this dialog should not
+ be used in Symbian.
+
+ \sa QPrintDialog, QPrinter, {Printing with Qt}
+*/
+
+/*!
+ \enum QAbstractPrintDialog::PrintRange
+
+ Used to specify the print range selection option.
+
+ \value AllPages All pages should be printed.
+ \value Selection Only the selection should be printed.
+ \value PageRange The specified page range should be printed.
+ \value CurrentPage Only the currently visible page should be printed.
+
+ \sa QPrinter::PrintRange
+*/
+
+/*!
+ \enum QAbstractPrintDialog::PrintDialogOption
+
+ Used to specify which parts of the print dialog should be visible.
+
+ \value None None of the options are enabled.
+ \value PrintToFile The print to file option is enabled.
+ \value PrintSelection The print selection option is enabled.
+ \value PrintPageRange The page range selection option is enabled.
+ \value PrintShowPageSize Show the page size + margins page only if this is enabled.
+ \value PrintCollateCopies The collate copies option is enabled
+ \value PrintCurrentPage The print current page option is enabled
+
+ This value is obsolete and does nothing since Qt 4.5:
+
+ \value DontUseSheet In previous versions of Qt, exec() the print dialog
+ would create a sheet by default the dialog was given a parent.
+ This is no longer supported in Qt 4.5. If you want to use sheets, use
+ QPrintDialog::open() instead.
+*/
+
+/*!
+ Constructs an abstract print dialog for \a printer with \a parent
+ as parent widget.
+*/
+QAbstractPrintDialog::QAbstractPrintDialog(QPrinter *printer, QWidget *parent)
+ : QDialog(*(new QAbstractPrintDialogPrivate), parent)
+{
+ Q_D(QAbstractPrintDialog);
+ setWindowTitle(QCoreApplication::translate("QPrintDialog", "Print"));
+ d->setPrinter(printer);
+}
+
+/*!
+ \internal
+*/
+QAbstractPrintDialog::QAbstractPrintDialog(QAbstractPrintDialogPrivate &ptr,
+ QPrinter *printer,
+ QWidget *parent)
+ : QDialog(ptr, parent)
+{
+ Q_D(QAbstractPrintDialog);
+ setWindowTitle(QCoreApplication::translate("QPrintDialog", "Print"));
+ d->setPrinter(printer);
+}
+
+/*!
+ \internal
+*/
+QAbstractPrintDialog::~QAbstractPrintDialog()
+{
+ Q_D(QAbstractPrintDialog);
+ if (d->ownsPrinter)
+ delete d->printer;
+}
+
+/*!
+ Sets the given \a option to be enabled if \a on is true;
+ otherwise, clears the given \a option.
+
+ \sa options, testOption()
+*/
+void QPrintDialog::setOption(PrintDialogOption option, bool on)
+{
+ Q_D(QPrintDialog);
+ if (!(d->options & option) != !on)
+ setOptions(d->options ^ option);
+}
+
+/*!
+ Returns true if the given \a option is enabled; otherwise, returns
+ false.
+
+ \sa options, setOption()
+*/
+bool QPrintDialog::testOption(PrintDialogOption option) const
+{
+ Q_D(const QPrintDialog);
+ return (d->options & option) != 0;
+}
+
+/*!
+ \property QPrintDialog::options
+ \brief the various options that affect the look and feel of the dialog
+ \since 4.5
+
+ By default, all options are disabled.
+
+ Options should be set before showing the dialog. Setting them while the
+ dialog is visible is not guaranteed to have an immediate effect on the
+ dialog (depending on the option and on the platform).
+
+ \sa setOption(), testOption()
+*/
+void QPrintDialog::setOptions(PrintDialogOptions options)
+{
+ Q_D(QPrintDialog);
+
+ PrintDialogOptions changed = (options ^ d->options);
+ if (!changed)
+ return;
+
+ d->options = options;
+}
+
+QPrintDialog::PrintDialogOptions QPrintDialog::options() const
+{
+ Q_D(const QPrintDialog);
+ return d->options;
+}
+
+/*!
+ \obsolete
+
+ Use QPrintDialog::setOptions() instead.
+*/
+void QAbstractPrintDialog::setEnabledOptions(PrintDialogOptions options)
+{
+ Q_D(QAbstractPrintDialog);
+ d->options = options;
+}
+
+/*!
+ \obsolete
+
+ Use QPrintDialog::setOption(\a option, true) instead.
+*/
+void QAbstractPrintDialog::addEnabledOption(PrintDialogOption option)
+{
+ Q_D(QAbstractPrintDialog);
+ d->options |= option;
+}
+
+/*!
+ \obsolete
+
+ Use QPrintDialog::options() instead.
+*/
+QAbstractPrintDialog::PrintDialogOptions QAbstractPrintDialog::enabledOptions() const
+{
+ Q_D(const QAbstractPrintDialog);
+ return d->options;
+}
+
+/*!
+ \obsolete
+
+ Use QPrintDialog::testOption(\a option) instead.
+*/
+bool QAbstractPrintDialog::isOptionEnabled(PrintDialogOption option) const
+{
+ Q_D(const QAbstractPrintDialog);
+ return d->options & option;
+}
+
+/*!
+ Sets the print range option in to be \a range.
+ */
+void QAbstractPrintDialog::setPrintRange(PrintRange range)
+{
+ Q_D(QAbstractPrintDialog);
+ d->pd->printRange = QPrinter::PrintRange(range);
+}
+
+/*!
+ Returns the print range.
+*/
+QAbstractPrintDialog::PrintRange QAbstractPrintDialog::printRange() const
+{
+ Q_D(const QAbstractPrintDialog);
+ return QAbstractPrintDialog::PrintRange(d->pd->printRange);
+}
+
+/*!
+ Sets the page range in this dialog to be from \a min to \a max. This also
+ enables the PrintPageRange option.
+*/
+void QAbstractPrintDialog::setMinMax(int min, int max)
+{
+ Q_D(QAbstractPrintDialog);
+ Q_ASSERT_X(min <= max, "QAbstractPrintDialog::setMinMax",
+ "'min' must be less than or equal to 'max'");
+ d->pd->minPage = min;
+ d->pd->maxPage = max;
+ d->options |= PrintPageRange;
+}
+
+/*!
+ Returns the minimum page in the page range.
+ By default, this value is set to 1.
+*/
+int QAbstractPrintDialog::minPage() const
+{
+ Q_D(const QAbstractPrintDialog);
+ return d->pd->minPage;
+}
+
+/*!
+ Returns the maximum page in the page range. As of Qt 4.4, this
+ function returns INT_MAX by default. Previous versions returned 1
+ by default.
+*/
+int QAbstractPrintDialog::maxPage() const
+{
+ Q_D(const QAbstractPrintDialog);
+ return d->pd->maxPage;
+}
+
+/*!
+ Sets the range in the print dialog to be from \a from to \a to.
+*/
+void QAbstractPrintDialog::setFromTo(int from, int to)
+{
+ Q_D(QAbstractPrintDialog);
+ Q_ASSERT_X(from <= to, "QAbstractPrintDialog::setFromTo",
+ "'from' must be less than or equal to 'to'");
+ d->pd->fromPage = from;
+ d->pd->toPage = to;
+
+ if (d->pd->minPage == 0 && d->pd->maxPage == 0)
+ setMinMax(1, to);
+}
+
+/*!
+ Returns the first page to be printed
+ By default, this value is set to 0.
+*/
+int QAbstractPrintDialog::fromPage() const
+{
+ Q_D(const QAbstractPrintDialog);
+ return d->pd->fromPage;
+}
+
+/*!
+ Returns the last page to be printed.
+ By default, this value is set to 0.
+*/
+int QAbstractPrintDialog::toPage() const
+{
+ Q_D(const QAbstractPrintDialog);
+ return d->pd->toPage;
+}
+
+
+/*!
+ Returns the printer that this printer dialog operates
+ on.
+*/
+QPrinter *QAbstractPrintDialog::printer() const
+{
+ Q_D(const QAbstractPrintDialog);
+ return d->printer;
+}
+
+void QAbstractPrintDialogPrivate::setPrinter(QPrinter *newPrinter)
+{
+ if (newPrinter) {
+ printer = newPrinter;
+ ownsPrinter = false;
+ if (printer->fromPage() || printer->toPage())
+ options |= QAbstractPrintDialog::PrintPageRange;
+ } else {
+ printer = new QPrinter;
+ ownsPrinter = true;
+ }
+ pd = printer->d_func();
+}
+
+/*!
+ \fn int QAbstractPrintDialog::exec()
+
+ This virtual function is called to pop up the dialog. It must be
+ reimplemented in subclasses.
+*/
+
+/*!
+ \class QPrintDialog
+
+ \brief The QPrintDialog class provides a dialog for specifying
+ the printer's configuration.
+
+ \ingroup standard-dialogs
+ \ingroup printing
+
+ The dialog allows users to change document-related settings, such
+ as the paper size and orientation, type of print (color or
+ grayscale), range of pages, and number of copies to print.
+
+ Controls are also provided to enable users to choose from the
+ printers available, including any configured network printers.
+
+ Typically, QPrintDialog objects are constructed with a QPrinter
+ object, and executed using the exec() function.
+
+ \snippet doc/src/snippets/code/src_gui_dialogs_qabstractprintdialog.cpp 0
+
+ If the dialog is accepted by the user, the QPrinter object is
+ correctly configured for printing.
+
+ \table
+ \row
+ \o \inlineimage plastique-printdialog.png
+ \o \inlineimage plastique-printdialog-properties.png
+ \endtable
+
+ The printer dialog (shown above in Plastique style) enables access to common
+ printing properties. On X11 platforms that use the CUPS printing system, the
+ settings for each available printer can be modified via the dialog's
+ \gui{Properties} push button.
+
+ On Windows and Mac OS X, the native print dialog is used, which means that
+ some QWidget and QDialog properties set on the dialog won't be respected.
+ The native print dialog on Mac OS X does not support setting printer options,
+ i.e. setOptions() and setOption() have no effect.
+
+ In Qt 4.4, it was possible to use the static functions to show a sheet on
+ Mac OS X. This is no longer supported in Qt 4.5. If you want this
+ functionality, use QPrintDialog::open().
+
+ \sa QPageSetupDialog, QPrinter, {Pixelator Example}, {Order Form Example},
+ {Image Viewer Example}, {Scribble Example}
+*/
+
+/*!
+ \fn QPrintDialog::QPrintDialog(QPrinter *printer, QWidget *parent)
+
+ Constructs a new modal printer dialog for the given \a printer
+ with the given \a parent.
+*/
+
+/*!
+ \fn QPrintDialog::~QPrintDialog()
+
+ Destroys the print dialog.
+*/
+
+/*!
+ \fn int QPrintDialog::exec()
+ \reimp
+*/
+
+/*!
+ \since 4.4
+
+ Set a list of widgets as \a tabs to be shown on the print dialog, if supported.
+
+ Currently this option is only supported on X11.
+
+ Setting the option tabs will transfer their ownership to the print dialog.
+*/
+void QAbstractPrintDialog::setOptionTabs(const QList<QWidget*> &tabs)
+{
+ Q_D(QAbstractPrintDialog);
+ d->setTabs(tabs);
+}
+
+/*!
+
+ \fn void QPrintDialog::accepted(QPrinter *printer)
+
+ This signal is emitted when the user accepts the values set in the print dialog.
+ The \a printer parameter includes the printer that the settings were applied to.
+*/
+
+/*!
+ \fn QPrinter *QPrintDialog::printer()
+
+ Returns the printer that this printer dialog operates
+ on. This can be useful when using the QPrintDialog::open() method.
+*/
+
+/*!
+ Closes the dialog and sets its result code to \a result. If this dialog
+ is shown with exec(), done() causes the local event loop to finish,
+ and exec() to return \a result.
+
+ \sa QDialog::done()
+*/
+void QPrintDialog::done(int result)
+{
+ Q_D(QPrintDialog);
+ QDialog::done(result);
+ if (result == Accepted)
+ emit accepted(printer());
+ if (d->receiverToDisconnectOnClose) {
+ disconnect(this, SIGNAL(accepted(QPrinter*)),
+ d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);
+ d->receiverToDisconnectOnClose = 0;
+ }
+ d->memberToDisconnectOnClose.clear();
+}
+
+/*!
+ \since 4.5
+ \overload
+
+ Opens the dialog and connects its accepted() signal to the slot specified
+ by \a receiver and \a member.
+
+ The signal will be disconnected from the slot when the dialog is closed.
+*/
+void QPrintDialog::open(QObject *receiver, const char *member)
+{
+ Q_D(QPrintDialog);
+ connect(this, SIGNAL(accepted(QPrinter*)), receiver, member);
+ d->receiverToDisconnectOnClose = receiver;
+ d->memberToDisconnectOnClose = member;
+ QDialog::open();
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_PRINTDIALOG
diff --git a/src/widgets/dialogs/qabstractprintdialog.h b/src/widgets/dialogs/qabstractprintdialog.h
new file mode 100644
index 0000000000..b9ac05ccff
--- /dev/null
+++ b/src/widgets/dialogs/qabstractprintdialog.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTPRINTDIALOG_H
+#define QABSTRACTPRINTDIALOG_H
+
+#include <QtGui/qdialog.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_PRINTER
+
+class QAbstractPrintDialogPrivate;
+class QPrinter;
+
+// ### Qt 5: remove this class
+class Q_GUI_EXPORT QAbstractPrintDialog : public QDialog
+{
+ Q_DECLARE_PRIVATE(QAbstractPrintDialog)
+ Q_OBJECT
+
+public:
+ // Keep in sync with QPrinter::PrintRange
+ enum PrintRange {
+ AllPages,
+ Selection,
+ PageRange,
+ CurrentPage
+ };
+
+ enum PrintDialogOption {
+ None = 0x0000, // obsolete
+ PrintToFile = 0x0001,
+ PrintSelection = 0x0002,
+ PrintPageRange = 0x0004,
+ PrintShowPageSize = 0x0008,
+ PrintCollateCopies = 0x0010,
+ DontUseSheet = 0x0020,
+ PrintCurrentPage = 0x0040
+ };
+
+ Q_DECLARE_FLAGS(PrintDialogOptions, PrintDialogOption)
+
+#ifndef QT_NO_PRINTDIALOG
+ explicit QAbstractPrintDialog(QPrinter *printer, QWidget *parent = 0);
+ ~QAbstractPrintDialog();
+
+ virtual int exec() = 0;
+
+ // obsolete
+ void addEnabledOption(PrintDialogOption option);
+ void setEnabledOptions(PrintDialogOptions options);
+ PrintDialogOptions enabledOptions() const;
+ bool isOptionEnabled(PrintDialogOption option) const;
+
+ void setOptionTabs(const QList<QWidget*> &tabs);
+
+ void setPrintRange(PrintRange range);
+ PrintRange printRange() const;
+
+ void setMinMax(int min, int max);
+ int minPage() const;
+ int maxPage() const;
+
+ void setFromTo(int fromPage, int toPage);
+ int fromPage() const;
+ int toPage() const;
+
+ QPrinter *printer() const;
+
+protected:
+ QAbstractPrintDialog(QAbstractPrintDialogPrivate &ptr, QPrinter *printer, QWidget *parent = 0);
+
+private:
+ Q_DISABLE_COPY(QAbstractPrintDialog)
+
+#endif // QT_NO_PRINTDIALOG
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QAbstractPrintDialog::PrintDialogOptions)
+
+#endif // QT_NO_PRINTER
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QABSTRACTPRINTDIALOG_H
diff --git a/src/widgets/dialogs/qabstractprintdialog_p.h b/src/widgets/dialogs/qabstractprintdialog_p.h
new file mode 100644
index 0000000000..1b5fa599f0
--- /dev/null
+++ b/src/widgets/dialogs/qabstractprintdialog_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTPRINTDIALOG_P_H
+#define QABSTRACTPRINTDIALOG_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qdialog_p.h"
+
+#ifndef QT_NO_PRINTDIALOG
+
+#include "QtGui/qabstractprintdialog.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_PRINTER
+
+class QPrinter;
+class QPrinterPrivate;
+
+class QAbstractPrintDialogPrivate : public QDialogPrivate
+{
+ Q_DECLARE_PUBLIC(QAbstractPrintDialog)
+
+public:
+ QAbstractPrintDialogPrivate()
+ : printer(0), pd(0), ownsPrinter(false)
+ , options(QAbstractPrintDialog::PrintToFile | QAbstractPrintDialog::PrintPageRange |
+ QAbstractPrintDialog::PrintCollateCopies | QAbstractPrintDialog::PrintShowPageSize)
+ {
+ }
+
+ QPrinter *printer;
+ QPrinterPrivate *pd;
+ bool ownsPrinter;
+ QPointer<QObject> receiverToDisconnectOnClose;
+ QByteArray memberToDisconnectOnClose;
+
+ QAbstractPrintDialog::PrintDialogOptions options;
+
+ virtual void setTabs(const QList<QWidget *> &) {}
+ void setPrinter(QPrinter *newPrinter);
+};
+
+#endif //QT_NO_PRINTER
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_PRINTDIALOG
+
+#endif // QABSTRACTPRINTDIALOG_P_H
diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp
new file mode 100644
index 0000000000..f99e6c2621
--- /dev/null
+++ b/src/widgets/dialogs/qcolordialog.cpp
@@ -0,0 +1,2115 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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 "qcolordialog_p.h"
+
+#ifndef QT_NO_COLORDIALOG
+
+#include "qapplication.h"
+#include "qdesktopwidget.h"
+#include "qdrawutil.h"
+#include "qevent.h"
+#include "qimage.h"
+#include "qdrag.h"
+#include "qlabel.h"
+#include "qlayout.h"
+#include "qlineedit.h"
+#include "qmenu.h"
+#include "qpainter.h"
+#include "qpixmap.h"
+#include "qpushbutton.h"
+#include "qsettings.h"
+#include "qstyle.h"
+#include "qstyleoption.h"
+#include "qvalidator.h"
+#include "qmime.h"
+#include "qspinbox.h"
+#include "qdialogbuttonbox.h"
+#include "private/qguiplatformplugin_p.h"
+
+#ifdef Q_WS_S60
+#include "private/qt_s60_p.h"
+#endif
+
+#if defined(Q_WS_S60) || defined(Q_WS_MAEMO_5)
+# define QT_SMALL_COLORDIALOG
+#endif
+
+QT_BEGIN_NAMESPACE
+
+//////////// QWellArray BEGIN
+
+struct QWellArrayData;
+
+class QWellArray : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(int selectedColumn READ selectedColumn)
+ Q_PROPERTY(int selectedRow READ selectedRow)
+
+public:
+ QWellArray(int rows, int cols, QWidget* parent=0);
+ ~QWellArray() {}
+ QString cellContent(int row, int col) const;
+
+ int selectedColumn() const { return selCol; }
+ int selectedRow() const { return selRow; }
+
+ virtual void setCurrent(int row, int col);
+ virtual void setSelected(int row, int col);
+
+ QSize sizeHint() const;
+
+ virtual void setCellBrush(int row, int col, const QBrush &);
+ QBrush cellBrush(int row, int col);
+
+ inline int cellWidth() const
+ { return cellw; }
+
+ inline int cellHeight() const
+ { return cellh; }
+
+ inline int rowAt(int y) const
+ { return y / cellh; }
+
+ inline int columnAt(int x) const
+ { if (isRightToLeft()) return ncols - (x / cellw) - 1; return x / cellw; }
+
+ inline int rowY(int row) const
+ { return cellh * row; }
+
+ inline int columnX(int column) const
+ { if (isRightToLeft()) return cellw * (ncols - column - 1); return cellw * column; }
+
+ inline int numRows() const
+ { return nrows; }
+
+ inline int numCols() const
+ {return ncols; }
+
+ inline QRect cellRect() const
+ { return QRect(0, 0, cellw, cellh); }
+
+ inline QSize gridSize() const
+ { return QSize(ncols * cellw, nrows * cellh); }
+
+ QRect cellGeometry(int row, int column)
+ {
+ QRect r;
+ if (row >= 0 && row < nrows && column >= 0 && column < ncols)
+ r.setRect(columnX(column), rowY(row), cellw, cellh);
+ return r;
+ }
+
+ inline void updateCell(int row, int column) { update(cellGeometry(row, column)); }
+
+signals:
+ void selected(int row, int col);
+
+protected:
+ virtual void paintCell(QPainter *, int row, int col, const QRect&);
+ virtual void paintCellContents(QPainter *, int row, int col, const QRect&);
+
+ void mousePressEvent(QMouseEvent*);
+ void mouseReleaseEvent(QMouseEvent*);
+ void keyPressEvent(QKeyEvent*);
+ void focusInEvent(QFocusEvent*);
+ void focusOutEvent(QFocusEvent*);
+ void paintEvent(QPaintEvent *);
+
+private:
+ Q_DISABLE_COPY(QWellArray)
+
+ int nrows;
+ int ncols;
+ int cellw;
+ int cellh;
+ int curRow;
+ int curCol;
+ int selRow;
+ int selCol;
+ QWellArrayData *d;
+};
+
+void QWellArray::paintEvent(QPaintEvent *e)
+{
+ QRect r = e->rect();
+ int cx = r.x();
+ int cy = r.y();
+ int ch = r.height();
+ int cw = r.width();
+ int colfirst = columnAt(cx);
+ int collast = columnAt(cx + cw);
+ int rowfirst = rowAt(cy);
+ int rowlast = rowAt(cy + ch);
+
+ if (isRightToLeft()) {
+ int t = colfirst;
+ colfirst = collast;
+ collast = t;
+ }
+
+ QPainter painter(this);
+ QPainter *p = &painter;
+ QRect rect(0, 0, cellWidth(), cellHeight());
+
+
+ if (collast < 0 || collast >= ncols)
+ collast = ncols-1;
+ if (rowlast < 0 || rowlast >= nrows)
+ rowlast = nrows-1;
+
+ // Go through the rows
+ for (int r = rowfirst; r <= rowlast; ++r) {
+ // get row position and height
+ int rowp = rowY(r);
+
+ // Go through the columns in the row r
+ // if we know from where to where, go through [colfirst, collast],
+ // else go through all of them
+ for (int c = colfirst; c <= collast; ++c) {
+ // get position and width of column c
+ int colp = columnX(c);
+ // Translate painter and draw the cell
+ rect.translate(colp, rowp);
+ paintCell(p, r, c, rect);
+ rect.translate(-colp, -rowp);
+ }
+ }
+}
+
+struct QWellArrayData {
+ QBrush *brush;
+};
+
+QWellArray::QWellArray(int rows, int cols, QWidget *parent)
+ : QWidget(parent)
+ ,nrows(rows), ncols(cols)
+{
+ d = 0;
+ setFocusPolicy(Qt::StrongFocus);
+ cellw = 28;
+ cellh = 24;
+ curCol = 0;
+ curRow = 0;
+ selCol = -1;
+ selRow = -1;
+}
+
+QSize QWellArray::sizeHint() const
+{
+ ensurePolished();
+ return gridSize().boundedTo(QSize(640, 480));
+}
+
+
+void QWellArray::paintCell(QPainter* p, int row, int col, const QRect &rect)
+{
+ int b = 3; //margin
+
+ const QPalette & g = palette();
+ QStyleOptionFrame opt;
+ int dfw = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
+ opt.lineWidth = dfw;
+ opt.midLineWidth = 1;
+ opt.rect = rect.adjusted(b, b, -b, -b);
+ opt.palette = g;
+ opt.state = QStyle::State_Enabled | QStyle::State_Sunken;
+ style()->drawPrimitive(QStyle::PE_Frame, &opt, p, this);
+ b += dfw;
+
+ if ((row == curRow) && (col == curCol)) {
+ if (hasFocus()) {
+ QStyleOptionFocusRect opt;
+ opt.palette = g;
+ opt.rect = rect;
+ opt.state = QStyle::State_None | QStyle::State_KeyboardFocusChange;
+ style()->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, p, this);
+ }
+ }
+ paintCellContents(p, row, col, opt.rect.adjusted(dfw, dfw, -dfw, -dfw));
+}
+
+/*!
+ Reimplement this function to change the contents of the well array.
+ */
+void QWellArray::paintCellContents(QPainter *p, int row, int col, const QRect &r)
+{
+ if (d) {
+ p->fillRect(r, d->brush[row*numCols()+col]);
+ } else {
+ p->fillRect(r, Qt::white);
+ p->setPen(Qt::black);
+ p->drawLine(r.topLeft(), r.bottomRight());
+ p->drawLine(r.topRight(), r.bottomLeft());
+ }
+}
+
+void QWellArray::mousePressEvent(QMouseEvent *e)
+{
+ // The current cell marker is set to the cell the mouse is pressed in
+ QPoint pos = e->pos();
+ setCurrent(rowAt(pos.y()), columnAt(pos.x()));
+}
+
+void QWellArray::mouseReleaseEvent(QMouseEvent * /* event */)
+{
+ // The current cell marker is set to the cell the mouse is clicked in
+ setSelected(curRow, curCol);
+}
+
+
+/*
+ Sets the cell currently having the focus. This is not necessarily
+ the same as the currently selected cell.
+*/
+
+void QWellArray::setCurrent(int row, int col)
+{
+ if ((curRow == row) && (curCol == col))
+ return;
+
+ if (row < 0 || col < 0)
+ row = col = -1;
+
+ int oldRow = curRow;
+ int oldCol = curCol;
+
+ curRow = row;
+ curCol = col;
+
+ updateCell(oldRow, oldCol);
+ updateCell(curRow, curCol);
+}
+
+/*
+ Sets the currently selected cell to \a row, \a column. If \a row or
+ \a column are less than zero, the current cell is unselected.
+
+ Does not set the position of the focus indicator.
+*/
+void QWellArray::setSelected(int row, int col)
+{
+ int oldRow = selRow;
+ int oldCol = selCol;
+
+ if (row < 0 || col < 0)
+ row = col = -1;
+
+ selCol = col;
+ selRow = row;
+
+ updateCell(oldRow, oldCol);
+ updateCell(selRow, selCol);
+ if (row >= 0)
+ emit selected(row, col);
+
+#ifndef QT_NO_MENU
+ if (isVisible() && qobject_cast<QMenu*>(parentWidget()))
+ parentWidget()->close();
+#endif
+}
+
+void QWellArray::focusInEvent(QFocusEvent*)
+{
+ updateCell(curRow, curCol);
+}
+
+void QWellArray::setCellBrush(int row, int col, const QBrush &b)
+{
+ if (!d) {
+ d = new QWellArrayData;
+ int i = numRows()*numCols();
+ d->brush = new QBrush[i];
+ }
+ if (row >= 0 && row < numRows() && col >= 0 && col < numCols())
+ d->brush[row*numCols()+col] = b;
+}
+
+/*
+ Returns the brush set for the cell at \a row, \a column. If no brush is
+ set, Qt::NoBrush is returned.
+*/
+
+QBrush QWellArray::cellBrush(int row, int col)
+{
+ if (d && row >= 0 && row < numRows() && col >= 0 && col < numCols())
+ return d->brush[row*numCols()+col];
+ return Qt::NoBrush;
+}
+
+
+
+/*!\reimp
+*/
+
+void QWellArray::focusOutEvent(QFocusEvent*)
+{
+ updateCell(curRow, curCol);
+}
+
+/*\reimp
+*/
+void QWellArray::keyPressEvent(QKeyEvent* e)
+{
+ switch(e->key()) { // Look at the key code
+ case Qt::Key_Left: // If 'left arrow'-key,
+ if(curCol > 0) // and cr't not in leftmost col
+ setCurrent(curRow, curCol - 1); // set cr't to next left column
+ break;
+ case Qt::Key_Right: // Correspondingly...
+ if(curCol < numCols()-1)
+ setCurrent(curRow, curCol + 1);
+ break;
+ case Qt::Key_Up:
+ if(curRow > 0)
+ setCurrent(curRow - 1, curCol);
+ break;
+ case Qt::Key_Down:
+ if(curRow < numRows()-1)
+ setCurrent(curRow + 1, curCol);
+ break;
+#if 0
+ // bad idea that shouldn't have been implemented; very counterintuitive
+ case Qt::Key_Return:
+ case Qt::Key_Enter:
+ /*
+ ignore the key, so that the dialog get it, but still select
+ the current row/col
+ */
+ e->ignore();
+ // fallthrough intended
+#endif
+ case Qt::Key_Space:
+ setSelected(curRow, curCol);
+ break;
+ default: // If not an interesting key,
+ e->ignore(); // we don't accept the event
+ return;
+ }
+
+}
+
+//////////// QWellArray END
+
+static bool initrgb = false;
+static QRgb stdrgb[6*8];
+static QRgb cusrgb[2*8];
+static bool customSet = false;
+
+
+static void initRGB()
+{
+ if (initrgb)
+ return;
+ initrgb = true;
+ int i = 0;
+ for (int g = 0; g < 4; g++)
+ for (int r = 0; r < 4; r++)
+ for (int b = 0; b < 3; b++)
+ stdrgb[i++] = qRgb(r * 255 / 3, g * 255 / 3, b * 255 / 2);
+
+ for (i = 0; i < 2*8; i++)
+ cusrgb[i] = 0xffffffff;
+}
+
+/*!
+ Returns the number of custom colors supported by QColorDialog. All
+ color dialogs share the same custom colors.
+*/
+int QColorDialog::customCount()
+{
+ return 2 * 8;
+}
+
+/*!
+ \since 4.5
+
+ Returns the custom color at the given \a index as a QRgb value.
+*/
+QRgb QColorDialog::customColor(int index)
+{
+ if (uint(index) >= uint(customCount()))
+ return qRgb(255, 255, 255);
+ initRGB();
+ return cusrgb[index];
+}
+
+/*!
+ Sets the custom color at \a index to the QRgb \a color value.
+
+ \note This function does not apply to the Native Color Dialog on the Mac
+ OS X platform. If you still require this function, use the
+ QColorDialog::DontUseNativeDialog option.
+*/
+void QColorDialog::setCustomColor(int index, QRgb color)
+{
+ if (uint(index) >= uint(customCount()))
+ return;
+ initRGB();
+ customSet = true;
+ cusrgb[index] = color;
+}
+
+/*!
+ Sets the standard color at \a index to the QRgb \a color value.
+
+ \note This function does not apply to the Native Color Dialog on the Mac
+ OS X platform. If you still require this function, use the
+ QColorDialog::DontUseNativeDialog option.
+*/
+
+void QColorDialog::setStandardColor(int index, QRgb color)
+{
+ if (uint(index) >= uint(6 * 8))
+ return;
+ initRGB();
+ stdrgb[index] = color;
+}
+
+static inline void rgb2hsv(QRgb rgb, int &h, int &s, int &v)
+{
+ QColor c;
+ c.setRgb(rgb);
+ c.getHsv(&h, &s, &v);
+}
+
+class QColorWell : public QWellArray
+{
+public:
+ QColorWell(QWidget *parent, int r, int c, QRgb *vals)
+ :QWellArray(r, c, parent), values(vals), mousePressed(false), oldCurrent(-1, -1)
+ { setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum)); }
+
+protected:
+ void paintCellContents(QPainter *, int row, int col, const QRect&);
+ void mousePressEvent(QMouseEvent *e);
+ void mouseMoveEvent(QMouseEvent *e);
+ void mouseReleaseEvent(QMouseEvent *e);
+#ifndef QT_NO_DRAGANDDROP
+ void dragEnterEvent(QDragEnterEvent *e);
+ void dragLeaveEvent(QDragLeaveEvent *e);
+ void dragMoveEvent(QDragMoveEvent *e);
+ void dropEvent(QDropEvent *e);
+#endif
+
+private:
+ QRgb *values;
+ bool mousePressed;
+ QPoint pressPos;
+ QPoint oldCurrent;
+
+};
+
+void QColorWell::paintCellContents(QPainter *p, int row, int col, const QRect &r)
+{
+ int i = row + col*numRows();
+ p->fillRect(r, QColor(values[i]));
+}
+
+void QColorWell::mousePressEvent(QMouseEvent *e)
+{
+ oldCurrent = QPoint(selectedRow(), selectedColumn());
+ QWellArray::mousePressEvent(e);
+ mousePressed = true;
+ pressPos = e->pos();
+}
+
+void QColorWell::mouseMoveEvent(QMouseEvent *e)
+{
+ QWellArray::mouseMoveEvent(e);
+#ifndef QT_NO_DRAGANDDROP
+ if (!mousePressed)
+ return;
+ if ((pressPos - e->pos()).manhattanLength() > QApplication::startDragDistance()) {
+ setCurrent(oldCurrent.x(), oldCurrent.y());
+ int i = rowAt(pressPos.y()) + columnAt(pressPos.x()) * numRows();
+ QColor col(values[i]);
+ QMimeData *mime = new QMimeData;
+ mime->setColorData(col);
+ QPixmap pix(cellWidth(), cellHeight());
+ pix.fill(col);
+ QPainter p(&pix);
+ p.drawRect(0, 0, pix.width() - 1, pix.height() - 1);
+ p.end();
+ QDrag *drg = new QDrag(this);
+ drg->setMimeData(mime);
+ drg->setPixmap(pix);
+ mousePressed = false;
+ drg->start();
+ }
+#endif
+}
+
+#ifndef QT_NO_DRAGANDDROP
+void QColorWell::dragEnterEvent(QDragEnterEvent *e)
+{
+ if (qvariant_cast<QColor>(e->mimeData()->colorData()).isValid())
+ e->accept();
+ else
+ e->ignore();
+}
+
+void QColorWell::dragLeaveEvent(QDragLeaveEvent *)
+{
+ if (hasFocus())
+ parentWidget()->setFocus();
+}
+
+void QColorWell::dragMoveEvent(QDragMoveEvent *e)
+{
+ if (qvariant_cast<QColor>(e->mimeData()->colorData()).isValid()) {
+ setCurrent(rowAt(e->pos().y()), columnAt(e->pos().x()));
+ e->accept();
+ } else {
+ e->ignore();
+ }
+}
+
+void QColorWell::dropEvent(QDropEvent *e)
+{
+ QColor col = qvariant_cast<QColor>(e->mimeData()->colorData());
+ if (col.isValid()) {
+ int i = rowAt(e->pos().y()) + columnAt(e->pos().x()) * numRows();
+ values[i] = col.rgb();
+ update();
+ e->accept();
+ } else {
+ e->ignore();
+ }
+}
+
+#endif // QT_NO_DRAGANDDROP
+
+void QColorWell::mouseReleaseEvent(QMouseEvent *e)
+{
+ if (!mousePressed)
+ return;
+ QWellArray::mouseReleaseEvent(e);
+ mousePressed = false;
+}
+
+class QColorPicker : public QFrame
+{
+ Q_OBJECT
+public:
+ QColorPicker(QWidget* parent);
+ ~QColorPicker();
+
+public slots:
+ void setCol(int h, int s);
+
+signals:
+ void newCol(int h, int s);
+
+protected:
+ QSize sizeHint() const;
+ void paintEvent(QPaintEvent*);
+ void mouseMoveEvent(QMouseEvent *);
+ void mousePressEvent(QMouseEvent *);
+ void resizeEvent(QResizeEvent *);
+
+private:
+ int hue;
+ int sat;
+
+ QPoint colPt();
+ int huePt(const QPoint &pt);
+ int satPt(const QPoint &pt);
+ void setCol(const QPoint &pt);
+
+ QPixmap pix;
+};
+
+static int pWidth = 220;
+static int pHeight = 200;
+
+class QColorLuminancePicker : public QWidget
+{
+ Q_OBJECT
+public:
+ QColorLuminancePicker(QWidget* parent=0);
+ ~QColorLuminancePicker();
+
+public slots:
+ void setCol(int h, int s, int v);
+ void setCol(int h, int s);
+
+signals:
+ void newHsv(int h, int s, int v);
+
+protected:
+ void paintEvent(QPaintEvent*);
+ void mouseMoveEvent(QMouseEvent *);
+ void mousePressEvent(QMouseEvent *);
+
+private:
+ enum { foff = 3, coff = 4 }; //frame and contents offset
+ int val;
+ int hue;
+ int sat;
+
+ int y2val(int y);
+ int val2y(int val);
+ void setVal(int v);
+
+ QPixmap *pix;
+};
+
+
+int QColorLuminancePicker::y2val(int y)
+{
+ int d = height() - 2*coff - 1;
+ return 255 - (y - coff)*255/d;
+}
+
+int QColorLuminancePicker::val2y(int v)
+{
+ int d = height() - 2*coff - 1;
+ return coff + (255-v)*d/255;
+}
+
+QColorLuminancePicker::QColorLuminancePicker(QWidget* parent)
+ :QWidget(parent)
+{
+ hue = 100; val = 100; sat = 100;
+ pix = 0;
+ // setAttribute(WA_NoErase, true);
+}
+
+QColorLuminancePicker::~QColorLuminancePicker()
+{
+ delete pix;
+}
+
+void QColorLuminancePicker::mouseMoveEvent(QMouseEvent *m)
+{
+ setVal(y2val(m->y()));
+}
+void QColorLuminancePicker::mousePressEvent(QMouseEvent *m)
+{
+ setVal(y2val(m->y()));
+}
+
+void QColorLuminancePicker::setVal(int v)
+{
+ if (val == v)
+ return;
+ val = qMax(0, qMin(v,255));
+ delete pix; pix=0;
+ repaint();
+ emit newHsv(hue, sat, val);
+}
+
+//receives from a hue,sat chooser and relays.
+void QColorLuminancePicker::setCol(int h, int s)
+{
+ setCol(h, s, val);
+ emit newHsv(h, s, val);
+}
+
+void QColorLuminancePicker::paintEvent(QPaintEvent *)
+{
+ int w = width() - 5;
+
+ QRect r(0, foff, w, height() - 2*foff);
+ int wi = r.width() - 2;
+ int hi = r.height() - 2;
+ if (!pix || pix->height() != hi || pix->width() != wi) {
+ delete pix;
+ QImage img(wi, hi, QImage::Format_RGB32);
+ int y;
+ uint *pixel = (uint *) img.scanLine(0);
+ for (y = 0; y < hi; y++) {
+ const uint *end = pixel + wi;
+ while (pixel < end) {
+ QColor c;
+ c.setHsv(hue, sat, y2val(y+coff));
+ *pixel = c.rgb();
+ ++pixel;
+ }
+ }
+ pix = new QPixmap(QPixmap::fromImage(img));
+ }
+ QPainter p(this);
+ p.drawPixmap(1, coff, *pix);
+ const QPalette &g = palette();
+ qDrawShadePanel(&p, r, g, true);
+ p.setPen(g.foreground().color());
+ p.setBrush(g.foreground());
+ QPolygon a;
+ int y = val2y(val);
+ a.setPoints(3, w, y, w+5, y+5, w+5, y-5);
+ p.eraseRect(w, 0, 5, height());
+ p.drawPolygon(a);
+}
+
+void QColorLuminancePicker::setCol(int h, int s , int v)
+{
+ val = v;
+ hue = h;
+ sat = s;
+ delete pix; pix=0;
+ repaint();
+}
+
+QPoint QColorPicker::colPt()
+{
+ QRect r = contentsRect();
+ return QPoint((360 - hue) * (r.width() - 1) / 360, (255 - sat) * (r.height() - 1) / 255);
+}
+
+int QColorPicker::huePt(const QPoint &pt)
+{
+ QRect r = contentsRect();
+ return 360 - pt.x() * 360 / (r.width() - 1);
+}
+
+int QColorPicker::satPt(const QPoint &pt)
+{
+ QRect r = contentsRect();
+ return 255 - pt.y() * 255 / (r.height() - 1);
+}
+
+void QColorPicker::setCol(const QPoint &pt)
+{
+ setCol(huePt(pt), satPt(pt));
+}
+
+QColorPicker::QColorPicker(QWidget* parent)
+ : QFrame(parent)
+{
+ hue = 0; sat = 0;
+ setCol(150, 255);
+
+ setAttribute(Qt::WA_NoSystemBackground);
+ setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed) );
+}
+
+QColorPicker::~QColorPicker()
+{
+}
+
+QSize QColorPicker::sizeHint() const
+{
+ return QSize(pWidth + 2*frameWidth(), pHeight + 2*frameWidth());
+}
+
+void QColorPicker::setCol(int h, int s)
+{
+ int nhue = qMin(qMax(0,h), 359);
+ int nsat = qMin(qMax(0,s), 255);
+ if (nhue == hue && nsat == sat)
+ return;
+
+ QRect r(colPt(), QSize(20,20));
+ hue = nhue; sat = nsat;
+ r = r.united(QRect(colPt(), QSize(20,20)));
+ r.translate(contentsRect().x()-9, contentsRect().y()-9);
+ // update(r);
+ repaint(r);
+}
+
+void QColorPicker::mouseMoveEvent(QMouseEvent *m)
+{
+ QPoint p = m->pos() - contentsRect().topLeft();
+ setCol(p);
+ emit newCol(hue, sat);
+}
+
+void QColorPicker::mousePressEvent(QMouseEvent *m)
+{
+ QPoint p = m->pos() - contentsRect().topLeft();
+ setCol(p);
+ emit newCol(hue, sat);
+}
+
+void QColorPicker::paintEvent(QPaintEvent* )
+{
+ QPainter p(this);
+ drawFrame(&p);
+ QRect r = contentsRect();
+
+ p.drawPixmap(r.topLeft(), pix);
+ QPoint pt = colPt() + r.topLeft();
+ p.setPen(Qt::black);
+
+ p.fillRect(pt.x()-9, pt.y(), 20, 2, Qt::black);
+ p.fillRect(pt.x(), pt.y()-9, 2, 20, Qt::black);
+
+}
+
+void QColorPicker::resizeEvent(QResizeEvent *ev)
+{
+ QFrame::resizeEvent(ev);
+
+ int w = width() - frameWidth() * 2;
+ int h = height() - frameWidth() * 2;
+ QImage img(w, h, QImage::Format_RGB32);
+ int x, y;
+ uint *pixel = (uint *) img.scanLine(0);
+ for (y = 0; y < h; y++) {
+ const uint *end = pixel + w;
+ x = 0;
+ while (pixel < end) {
+ QPoint p(x, y);
+ QColor c;
+ c.setHsv(huePt(p), satPt(p), 200);
+ *pixel = c.rgb();
+ ++pixel;
+ ++x;
+ }
+ }
+ pix = QPixmap::fromImage(img);
+}
+
+
+class QColSpinBox : public QSpinBox
+{
+public:
+ QColSpinBox(QWidget *parent)
+ : QSpinBox(parent) { setRange(0, 255); }
+ void setValue(int i) {
+ bool block = signalsBlocked();
+ blockSignals(true);
+ QSpinBox::setValue(i);
+ blockSignals(block);
+ }
+};
+
+class QColorShowLabel;
+
+class QColorShower : public QWidget
+{
+ Q_OBJECT
+public:
+ QColorShower(QColorDialog *parent);
+
+ //things that don't emit signals
+ void setHsv(int h, int s, int v);
+
+ int currentAlpha() const
+ { return (colorDialog->options() & QColorDialog::ShowAlphaChannel) ? alphaEd->value() : 255; }
+ void setCurrentAlpha(int a) { alphaEd->setValue(a); rgbEd(); }
+ void showAlpha(bool b);
+ bool isAlphaVisible() const;
+
+ QRgb currentColor() const { return curCol; }
+ QColor currentQColor() const { return curQColor; }
+ void retranslateStrings();
+ void updateQColor();
+
+public slots:
+ void setRgb(QRgb rgb);
+
+signals:
+ void newCol(QRgb rgb);
+ void currentColorChanged(const QColor &color);
+
+private slots:
+ void rgbEd();
+ void hsvEd();
+private:
+ void showCurrentColor();
+ int hue, sat, val;
+ QRgb curCol;
+ QColor curQColor;
+ QLabel *lblHue;
+ QLabel *lblSat;
+ QLabel *lblVal;
+ QLabel *lblRed;
+ QLabel *lblGreen;
+ QLabel *lblBlue;
+ QColSpinBox *hEd;
+ QColSpinBox *sEd;
+ QColSpinBox *vEd;
+ QColSpinBox *rEd;
+ QColSpinBox *gEd;
+ QColSpinBox *bEd;
+ QColSpinBox *alphaEd;
+ QLabel *alphaLab;
+ QColorShowLabel *lab;
+ bool rgbOriginal;
+ QColorDialog *colorDialog;
+
+ friend class QColorDialog;
+ friend class QColorDialogPrivate;
+};
+
+class QColorShowLabel : public QFrame
+{
+ Q_OBJECT
+
+public:
+ QColorShowLabel(QWidget *parent) : QFrame(parent) {
+ setFrameStyle(QFrame::Panel|QFrame::Sunken);
+ setAcceptDrops(true);
+ mousePressed = false;
+ }
+ void setColor(QColor c) { col = c; }
+
+signals:
+ void colorDropped(QRgb);
+
+protected:
+ void paintEvent(QPaintEvent *);
+ void mousePressEvent(QMouseEvent *e);
+ void mouseMoveEvent(QMouseEvent *e);
+ void mouseReleaseEvent(QMouseEvent *e);
+#ifndef QT_NO_DRAGANDDROP
+ void dragEnterEvent(QDragEnterEvent *e);
+ void dragLeaveEvent(QDragLeaveEvent *e);
+ void dropEvent(QDropEvent *e);
+#endif
+
+private:
+ QColor col;
+ bool mousePressed;
+ QPoint pressPos;
+};
+
+void QColorShowLabel::paintEvent(QPaintEvent *e)
+{
+ QPainter p(this);
+ drawFrame(&p);
+ p.fillRect(contentsRect()&e->rect(), col);
+}
+
+void QColorShower::showAlpha(bool b)
+{
+ alphaLab->setVisible(b);
+ alphaEd->setVisible(b);
+}
+
+inline bool QColorShower::isAlphaVisible() const
+{
+ return alphaLab->isVisible();
+}
+
+void QColorShowLabel::mousePressEvent(QMouseEvent *e)
+{
+ mousePressed = true;
+ pressPos = e->pos();
+}
+
+void QColorShowLabel::mouseMoveEvent(QMouseEvent *e)
+{
+#ifdef QT_NO_DRAGANDDROP
+ Q_UNUSED(e);
+#else
+ if (!mousePressed)
+ return;
+ if ((pressPos - e->pos()).manhattanLength() > QApplication::startDragDistance()) {
+ QMimeData *mime = new QMimeData;
+ mime->setColorData(col);
+ QPixmap pix(30, 20);
+ pix.fill(col);
+ QPainter p(&pix);
+ p.drawRect(0, 0, pix.width() - 1, pix.height() - 1);
+ p.end();
+ QDrag *drg = new QDrag(this);
+ drg->setMimeData(mime);
+ drg->setPixmap(pix);
+ mousePressed = false;
+ drg->start();
+ }
+#endif
+}
+
+#ifndef QT_NO_DRAGANDDROP
+void QColorShowLabel::dragEnterEvent(QDragEnterEvent *e)
+{
+ if (qvariant_cast<QColor>(e->mimeData()->colorData()).isValid())
+ e->accept();
+ else
+ e->ignore();
+}
+
+void QColorShowLabel::dragLeaveEvent(QDragLeaveEvent *)
+{
+}
+
+void QColorShowLabel::dropEvent(QDropEvent *e)
+{
+ QColor color = qvariant_cast<QColor>(e->mimeData()->colorData());
+ if (color.isValid()) {
+ col = color;
+ repaint();
+ emit colorDropped(col.rgb());
+ e->accept();
+ } else {
+ e->ignore();
+ }
+}
+#endif // QT_NO_DRAGANDDROP
+
+void QColorShowLabel::mouseReleaseEvent(QMouseEvent *)
+{
+ if (!mousePressed)
+ return;
+ mousePressed = false;
+}
+
+QColorShower::QColorShower(QColorDialog *parent)
+ : QWidget(parent)
+{
+ colorDialog = parent;
+
+ curCol = qRgb(255, 255, 255);
+ curQColor = Qt::white;
+
+ QGridLayout *gl = new QGridLayout(this);
+ gl->setMargin(gl->spacing());
+ lab = new QColorShowLabel(this);
+
+#ifdef QT_SMALL_COLORDIALOG
+# ifdef Q_WS_S60
+ const bool nonTouchUI = !S60->hasTouchscreen;
+# elif defined Q_WS_MAEMO_5
+ const bool nonTouchUI = false;
+# endif
+#endif
+
+#ifndef Q_WS_WINCE
+#ifdef QT_SMALL_COLORDIALOG
+ lab->setMinimumHeight(60);
+#endif
+ lab->setMinimumWidth(60);
+#else
+ lab->setMinimumWidth(20);
+#endif
+
+// In S60, due to small screen and different screen layouts need to re-arrange the widgets.
+// For QVGA screens only the comboboxes and color label are visible.
+// For nHD screens only color and luminence pickers and color label are visible.
+#if !defined(QT_SMALL_COLORDIALOG)
+ gl->addWidget(lab, 0, 0, -1, 1);
+#else
+ if (nonTouchUI)
+ gl->addWidget(lab, 0, 0, 1, -1);
+ else
+ gl->addWidget(lab, 0, 0, -1, 1);
+#endif
+ connect(lab, SIGNAL(colorDropped(QRgb)), this, SIGNAL(newCol(QRgb)));
+ connect(lab, SIGNAL(colorDropped(QRgb)), this, SLOT(setRgb(QRgb)));
+
+ hEd = new QColSpinBox(this);
+ hEd->setRange(0, 359);
+ lblHue = new QLabel(this);
+#ifndef QT_NO_SHORTCUT
+ lblHue->setBuddy(hEd);
+#endif
+ lblHue->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
+#if !defined(QT_SMALL_COLORDIALOG)
+ gl->addWidget(lblHue, 0, 1);
+ gl->addWidget(hEd, 0, 2);
+#else
+ if (nonTouchUI) {
+ gl->addWidget(lblHue, 1, 0);
+ gl->addWidget(hEd, 2, 0);
+ } else {
+ lblHue->hide();
+ hEd->hide();
+ }
+#endif
+
+ sEd = new QColSpinBox(this);
+ lblSat = new QLabel(this);
+#ifndef QT_NO_SHORTCUT
+ lblSat->setBuddy(sEd);
+#endif
+ lblSat->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
+#if !defined(QT_SMALL_COLORDIALOG)
+ gl->addWidget(lblSat, 1, 1);
+ gl->addWidget(sEd, 1, 2);
+#else
+ if (nonTouchUI) {
+ gl->addWidget(lblSat, 1, 1);
+ gl->addWidget(sEd, 2, 1);
+ } else {
+ lblSat->hide();
+ sEd->hide();
+ }
+#endif
+
+ vEd = new QColSpinBox(this);
+ lblVal = new QLabel(this);
+#ifndef QT_NO_SHORTCUT
+ lblVal->setBuddy(vEd);
+#endif
+ lblVal->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
+#if !defined(QT_SMALL_COLORDIALOG)
+ gl->addWidget(lblVal, 2, 1);
+ gl->addWidget(vEd, 2, 2);
+#else
+ if (nonTouchUI) {
+ gl->addWidget(lblVal, 1, 2);
+ gl->addWidget(vEd, 2, 2);
+ } else {
+ lblVal->hide();
+ vEd->hide();
+ }
+#endif
+
+ rEd = new QColSpinBox(this);
+ lblRed = new QLabel(this);
+#ifndef QT_NO_SHORTCUT
+ lblRed->setBuddy(rEd);
+#endif
+ lblRed->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
+#if !defined(QT_SMALL_COLORDIALOG)
+ gl->addWidget(lblRed, 0, 3);
+ gl->addWidget(rEd, 0, 4);
+#else
+ if (nonTouchUI) {
+ gl->addWidget(lblRed, 3, 0);
+ gl->addWidget(rEd, 4, 0);
+ } else {
+ lblRed->hide();
+ rEd->hide();
+ }
+#endif
+
+ gEd = new QColSpinBox(this);
+ lblGreen = new QLabel(this);
+#ifndef QT_NO_SHORTCUT
+ lblGreen->setBuddy(gEd);
+#endif
+ lblGreen->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
+#if !defined(QT_SMALL_COLORDIALOG)
+ gl->addWidget(lblGreen, 1, 3);
+ gl->addWidget(gEd, 1, 4);
+#else
+ if (nonTouchUI) {
+ gl->addWidget(lblGreen, 3, 1);
+ gl->addWidget(gEd, 4, 1);
+ } else {
+ lblGreen->hide();
+ gEd->hide();
+ }
+#endif
+
+ bEd = new QColSpinBox(this);
+ lblBlue = new QLabel(this);
+#ifndef QT_NO_SHORTCUT
+ lblBlue->setBuddy(bEd);
+#endif
+ lblBlue->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
+#if !defined(QT_SMALL_COLORDIALOG)
+ gl->addWidget(lblBlue, 2, 3);
+ gl->addWidget(bEd, 2, 4);
+#else
+ if (nonTouchUI) {
+ gl->addWidget(lblBlue, 3, 2);
+ gl->addWidget(bEd, 4, 2);
+ } else {
+ lblBlue->hide();
+ bEd->hide();
+ }
+#endif
+
+ alphaEd = new QColSpinBox(this);
+ alphaLab = new QLabel(this);
+#ifndef QT_NO_SHORTCUT
+ alphaLab->setBuddy(alphaEd);
+#endif
+ alphaLab->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
+#if !defined(QT_SMALL_COLORDIALOG)
+ gl->addWidget(alphaLab, 3, 1, 1, 3);
+ gl->addWidget(alphaEd, 3, 4);
+#else
+ if (nonTouchUI) {
+ gl->addWidget(alphaLab, 1, 3, 3, 1);
+ gl->addWidget(alphaEd, 4, 3);
+ } else {
+ alphaLab->hide();
+ alphaEd->hide();
+ }
+#endif
+ alphaEd->hide();
+ alphaLab->hide();
+
+ connect(hEd, SIGNAL(valueChanged(int)), this, SLOT(hsvEd()));
+ connect(sEd, SIGNAL(valueChanged(int)), this, SLOT(hsvEd()));
+ connect(vEd, SIGNAL(valueChanged(int)), this, SLOT(hsvEd()));
+
+ connect(rEd, SIGNAL(valueChanged(int)), this, SLOT(rgbEd()));
+ connect(gEd, SIGNAL(valueChanged(int)), this, SLOT(rgbEd()));
+ connect(bEd, SIGNAL(valueChanged(int)), this, SLOT(rgbEd()));
+ connect(alphaEd, SIGNAL(valueChanged(int)), this, SLOT(rgbEd()));
+
+ retranslateStrings();
+}
+
+inline QRgb QColorDialogPrivate::currentColor() const { return cs->currentColor(); }
+inline int QColorDialogPrivate::currentAlpha() const { return cs->currentAlpha(); }
+inline void QColorDialogPrivate::setCurrentAlpha(int a) { cs->setCurrentAlpha(a); }
+inline void QColorDialogPrivate::showAlpha(bool b) { cs->showAlpha(b); }
+inline bool QColorDialogPrivate::isAlphaVisible() const { return cs->isAlphaVisible(); }
+
+QColor QColorDialogPrivate::currentQColor() const
+{
+ return cs->currentQColor();
+}
+
+void QColorShower::showCurrentColor()
+{
+ lab->setColor(currentColor());
+ lab->repaint();
+}
+
+void QColorShower::rgbEd()
+{
+ rgbOriginal = true;
+ curCol = qRgba(rEd->value(), gEd->value(), bEd->value(), currentAlpha());
+
+ rgb2hsv(currentColor(), hue, sat, val);
+
+ hEd->setValue(hue);
+ sEd->setValue(sat);
+ vEd->setValue(val);
+
+ showCurrentColor();
+ emit newCol(currentColor());
+ updateQColor();
+}
+
+void QColorShower::hsvEd()
+{
+ rgbOriginal = false;
+ hue = hEd->value();
+ sat = sEd->value();
+ val = vEd->value();
+
+ QColor c;
+ c.setHsv(hue, sat, val);
+ curCol = c.rgb();
+
+ rEd->setValue(qRed(currentColor()));
+ gEd->setValue(qGreen(currentColor()));
+ bEd->setValue(qBlue(currentColor()));
+
+ showCurrentColor();
+ emit newCol(currentColor());
+ updateQColor();
+}
+
+void QColorShower::setRgb(QRgb rgb)
+{
+ rgbOriginal = true;
+ curCol = rgb;
+
+ rgb2hsv(currentColor(), hue, sat, val);
+
+ hEd->setValue(hue);
+ sEd->setValue(sat);
+ vEd->setValue(val);
+
+ rEd->setValue(qRed(currentColor()));
+ gEd->setValue(qGreen(currentColor()));
+ bEd->setValue(qBlue(currentColor()));
+
+ showCurrentColor();
+ updateQColor();
+}
+
+void QColorShower::setHsv(int h, int s, int v)
+{
+ if (h < -1 || (uint)s > 255 || (uint)v > 255)
+ return;
+
+ rgbOriginal = false;
+ hue = h; val = v; sat = s;
+ QColor c;
+ c.setHsv(hue, sat, val);
+ curCol = c.rgb();
+
+ hEd->setValue(hue);
+ sEd->setValue(sat);
+ vEd->setValue(val);
+
+ rEd->setValue(qRed(currentColor()));
+ gEd->setValue(qGreen(currentColor()));
+ bEd->setValue(qBlue(currentColor()));
+
+ showCurrentColor();
+ updateQColor();
+}
+
+void QColorShower::retranslateStrings()
+{
+ lblHue->setText(QColorDialog::tr("Hu&e:"));
+ lblSat->setText(QColorDialog::tr("&Sat:"));
+ lblVal->setText(QColorDialog::tr("&Val:"));
+ lblRed->setText(QColorDialog::tr("&Red:"));
+ lblGreen->setText(QColorDialog::tr("&Green:"));
+ lblBlue->setText(QColorDialog::tr("Bl&ue:"));
+ alphaLab->setText(QColorDialog::tr("A&lpha channel:"));
+}
+
+void QColorShower::updateQColor()
+{
+ QColor oldQColor(curQColor);
+ curQColor.setRgba(qRgba(qRed(curCol), qGreen(curCol), qBlue(curCol), currentAlpha()));
+ if (curQColor != oldQColor)
+ emit currentColorChanged(curQColor);
+}
+
+//sets all widgets to display h,s,v
+void QColorDialogPrivate::_q_newHsv(int h, int s, int v)
+{
+ cs->setHsv(h, s, v);
+ cp->setCol(h, s);
+ lp->setCol(h, s, v);
+}
+
+//sets all widgets to display rgb
+void QColorDialogPrivate::setCurrentColor(QRgb rgb)
+{
+ cs->setRgb(rgb);
+ _q_newColorTypedIn(rgb);
+}
+
+// hack; doesn't keep curCol in sync, so use with care
+void QColorDialogPrivate::setCurrentQColor(const QColor &color)
+{
+ Q_Q(QColorDialog);
+ if (cs->curQColor != color) {
+ cs->curQColor = color;
+ emit q->currentColorChanged(color);
+ }
+}
+
+bool QColorDialogPrivate::selectColor(const QColor &col)
+{
+ QRgb color = col.rgb();
+ int i = 0, j = 0;
+ // Check standard colors
+ if (standard) {
+ for (i = 0; i < 6; i++) {
+ for (j = 0; j < 8; j++) {
+ if (color == stdrgb[i + j*6]) {
+ _q_newStandard(i, j);
+ standard->setCurrent(i, j);
+ standard->setSelected(i, j);
+ standard->setFocus();
+ return true;
+ }
+ }
+ }
+ }
+ // Check custom colors
+ if (custom) {
+ for (i = 0; i < 2; i++) {
+ for (j = 0; j < 8; j++) {
+ if (color == cusrgb[i + j*2]) {
+ _q_newCustom(i, j);
+ custom->setCurrent(i, j);
+ custom->setSelected(i, j);
+ custom->setFocus();
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+//sets all widgets except cs to display rgb
+void QColorDialogPrivate::_q_newColorTypedIn(QRgb rgb)
+{
+ int h, s, v;
+ rgb2hsv(rgb, h, s, v);
+ cp->setCol(h, s);
+ lp->setCol(h, s, v);
+}
+
+void QColorDialogPrivate::_q_newCustom(int r, int c)
+{
+ int i = r+2*c;
+ setCurrentColor(cusrgb[i]);
+ nextCust = i;
+ if (standard)
+ standard->setSelected(-1,-1);
+}
+
+void QColorDialogPrivate::_q_newStandard(int r, int c)
+{
+ setCurrentColor(stdrgb[r+c*6]);
+ if (custom)
+ custom->setSelected(-1,-1);
+}
+
+void QColorDialogPrivate::init(const QColor &initial)
+{
+ Q_Q(QColorDialog);
+
+ q->setSizeGripEnabled(false);
+ q->setWindowTitle(QColorDialog::tr("Select Color"));
+
+ nativeDialogInUse = false;
+
+ nextCust = 0;
+ QVBoxLayout *mainLay = new QVBoxLayout(q);
+ // there's nothing in this dialog that benefits from sizing up
+ mainLay->setSizeConstraint(QLayout::SetFixedSize);
+
+ QHBoxLayout *topLay = new QHBoxLayout();
+ mainLay->addLayout(topLay);
+
+ leftLay = 0;
+
+#if defined(Q_WS_WINCE) || defined(QT_SMALL_COLORDIALOG)
+ smallDisplay = true;
+ const int lumSpace = 20;
+#else
+ // small displays (e.g. PDAs) cannot fit the full color dialog,
+ // so just use the color picker.
+ smallDisplay = (QApplication::desktop()->width() < 480 || QApplication::desktop()->height() < 350);
+ const int lumSpace = topLay->spacing() / 2;
+#endif
+
+ if (!smallDisplay) {
+ leftLay = new QVBoxLayout;
+ topLay->addLayout(leftLay);
+ }
+
+ initRGB();
+
+#ifndef QT_NO_SETTINGS
+ if (!customSet) {
+ QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
+ for (int i = 0; i < 2*8; ++i) {
+ QVariant v = settings.value(QLatin1String("Qt/customColors/") + QString::number(i));
+ if (v.isValid()) {
+ QRgb rgb = v.toUInt();
+ cusrgb[i] = rgb;
+ }
+ }
+ }
+#endif
+
+#if defined(QT_SMALL_COLORDIALOG)
+# if defined(Q_WS_S60)
+ const bool nonTouchUI = !S60->hasTouchscreen;
+# elif defined(Q_WS_MAEMO_5)
+ const bool nonTouchUI = false;
+# endif
+#endif
+
+ if (!smallDisplay) {
+ standard = new QColorWell(q, 6, 8, stdrgb);
+ lblBasicColors = new QLabel(q);
+#ifndef QT_NO_SHORTCUT
+ lblBasicColors->setBuddy(standard);
+#endif
+ q->connect(standard, SIGNAL(selected(int,int)), SLOT(_q_newStandard(int,int)));
+ leftLay->addWidget(lblBasicColors);
+ leftLay->addWidget(standard);
+
+#if !defined(Q_WS_WINCE)
+ leftLay->addStretch();
+#endif
+
+ custom = new QColorWell(q, 2, 8, cusrgb);
+ custom->setAcceptDrops(true);
+
+ q->connect(custom, SIGNAL(selected(int,int)), SLOT(_q_newCustom(int,int)));
+ lblCustomColors = new QLabel(q);
+#ifndef QT_NO_SHORTCUT
+ lblCustomColors->setBuddy(custom);
+#endif
+ leftLay->addWidget(lblCustomColors);
+ leftLay->addWidget(custom);
+
+ addCusBt = new QPushButton(q);
+ QObject::connect(addCusBt, SIGNAL(clicked()), q, SLOT(_q_addCustom()));
+ leftLay->addWidget(addCusBt);
+ } else {
+ // better color picker size for small displays
+#if defined(QT_SMALL_COLORDIALOG)
+ QSize screenSize = QApplication::desktop()->availableGeometry(QCursor::pos()).size();
+ pWidth = pHeight = qMin(screenSize.width(), screenSize.height());
+ pHeight -= 20;
+ if(screenSize.height() > screenSize.width())
+ pWidth -= 20;
+#else
+ pWidth = 150;
+ pHeight = 100;
+#endif
+ custom = 0;
+ standard = 0;
+ }
+
+ QVBoxLayout *rightLay = new QVBoxLayout;
+ topLay->addLayout(rightLay);
+
+ QHBoxLayout *pickLay = new QHBoxLayout;
+ rightLay->addLayout(pickLay);
+
+ QVBoxLayout *cLay = new QVBoxLayout;
+ pickLay->addLayout(cLay);
+ cp = new QColorPicker(q);
+
+ cp->setFrameStyle(QFrame::Panel + QFrame::Sunken);
+
+#if defined(QT_SMALL_COLORDIALOG)
+ if (!nonTouchUI) {
+ pickLay->addWidget(cp);
+ cLay->addSpacing(lumSpace);
+ } else {
+ cp->hide();
+ }
+#else
+ cLay->addSpacing(lumSpace);
+ cLay->addWidget(cp);
+#endif
+ cLay->addSpacing(lumSpace);
+
+ lp = new QColorLuminancePicker(q);
+#if defined(QT_SMALL_COLORDIALOG)
+ QSize screenSize = QApplication::desktop()->availableGeometry(QCursor::pos()).size();
+ const int minDimension = qMin(screenSize.height(), screenSize.width());
+ //set picker to be finger-usable
+ int pickerWidth = !nonTouchUI ? minDimension/9 : minDimension/12;
+ lp->setFixedWidth(pickerWidth);
+ if (!nonTouchUI)
+ pickLay->addWidget(lp);
+ else
+ lp->hide();
+#else
+ lp->setFixedWidth(20);
+ pickLay->addWidget(lp);
+#endif
+
+ QObject::connect(cp, SIGNAL(newCol(int,int)), lp, SLOT(setCol(int,int)));
+ QObject::connect(lp, SIGNAL(newHsv(int,int,int)), q, SLOT(_q_newHsv(int,int,int)));
+
+ rightLay->addStretch();
+
+ cs = new QColorShower(q);
+ QObject::connect(cs, SIGNAL(newCol(QRgb)), q, SLOT(_q_newColorTypedIn(QRgb)));
+ QObject::connect(cs, SIGNAL(currentColorChanged(QColor)),
+ q, SIGNAL(currentColorChanged(QColor)));
+#if defined(QT_SMALL_COLORDIALOG)
+ if (!nonTouchUI)
+ pWidth -= cp->size().width();
+ topLay->addWidget(cs);
+#else
+ rightLay->addWidget(cs);
+#endif
+
+ buttons = new QDialogButtonBox(q);
+ mainLay->addWidget(buttons);
+
+ ok = buttons->addButton(QDialogButtonBox::Ok);
+ QObject::connect(ok, SIGNAL(clicked()), q, SLOT(accept()));
+ ok->setDefault(true);
+ cancel = buttons->addButton(QDialogButtonBox::Cancel);
+ QObject::connect(cancel, SIGNAL(clicked()), q, SLOT(reject()));
+
+ retranslateStrings();
+
+#ifdef Q_WS_MAC
+ delegate = 0;
+#endif
+
+ q->setCurrentColor(initial);
+}
+
+void QColorDialogPrivate::_q_addCustom()
+{
+ cusrgb[nextCust] = cs->currentColor();
+ if (custom)
+ custom->update();
+ nextCust = (nextCust+1) % 16;
+}
+
+void QColorDialogPrivate::retranslateStrings()
+{
+ if (!smallDisplay) {
+ lblBasicColors->setText(QColorDialog::tr("&Basic colors"));
+ lblCustomColors->setText(QColorDialog::tr("&Custom colors"));
+ addCusBt->setText(QColorDialog::tr("&Add to Custom Colors"));
+ }
+
+ cs->retranslateStrings();
+}
+
+static const Qt::WindowFlags DefaultWindowFlags =
+ Qt::Dialog | Qt::WindowTitleHint | Qt::MSWindowsFixedSizeDialogHint
+ | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
+
+/*!
+ \class QColorDialog
+ \brief The QColorDialog class provides a dialog widget for specifying colors.
+
+ \ingroup standard-dialogs
+
+ The color dialog's function is to allow users to choose colors.
+ For example, you might use this in a drawing program to allow the
+ user to set the brush color.
+
+ The static functions provide modal color dialogs.
+ \omit
+ If you require a modeless dialog, use the QColorDialog constructor.
+ \endomit
+
+ The static getColor() function shows the dialog, and allows the user to
+ specify a color. This function can also be used to let users choose a
+ color with a level of transparency: pass the ShowAlphaChannel option as
+ an additional argument.
+
+ The user can store customCount() different custom colors. The
+ custom colors are shared by all color dialogs, and remembered
+ during the execution of the program. Use setCustomColor() to set
+ the custom colors, and use customColor() to get them.
+
+ Additional widgets that allow users to pick colors are available
+ as \l{Qt Solutions}.
+
+ The \l{dialogs/standarddialogs}{Standard Dialogs} example shows
+ how to use QColorDialog as well as other built-in Qt dialogs.
+
+ \image plastique-colordialog.png A color dialog in the Plastique widget style.
+
+ \sa QColor, QFileDialog, QPrintDialog, QFontDialog, {Standard Dialogs Example}
+*/
+
+/*!
+ \since 4.5
+
+ Constructs a color dialog with the given \a parent.
+*/
+QColorDialog::QColorDialog(QWidget *parent)
+ : QDialog(*new QColorDialogPrivate, parent, DefaultWindowFlags)
+{
+ Q_D(QColorDialog);
+ d->init(Qt::white);
+}
+
+/*!
+ \since 4.5
+
+ Constructs a color dialog with the given \a parent and specified
+ \a initial color.
+*/
+QColorDialog::QColorDialog(const QColor &initial, QWidget *parent)
+ : QDialog(*new QColorDialogPrivate, parent, DefaultWindowFlags)
+{
+ Q_D(QColorDialog);
+ d->init(initial);
+}
+
+/*!
+ \property QColorDialog::currentColor
+ \brief the currently selected color in the dialog
+*/
+
+void QColorDialog::setCurrentColor(const QColor &color)
+{
+ Q_D(QColorDialog);
+ d->setCurrentColor(color.rgb());
+ d->selectColor(color);
+ d->setCurrentAlpha(color.alpha());
+
+#ifdef Q_WS_MAC
+ d->setCurrentQColor(color);
+ d->setCocoaPanelColor(color);
+#endif
+ if (d->nativeDialogInUse)
+ qt_guiPlatformPlugin()->colorDialogSetCurrentColor(this, color);
+}
+
+QColor QColorDialog::currentColor() const
+{
+ Q_D(const QColorDialog);
+ return d->currentQColor();
+}
+
+
+/*!
+ Returns the color that the user selected by clicking the \gui{OK}
+ or equivalent button.
+
+ \note This color is not always the same as the color held by the
+ \l currentColor property since the user can choose different colors
+ before finally selecting the one to use.
+*/
+QColor QColorDialog::selectedColor() const
+{
+ Q_D(const QColorDialog);
+ return d->selectedQColor;
+}
+
+/*!
+ Sets the given \a option to be enabled if \a on is true;
+ otherwise, clears the given \a option.
+
+ \sa options, testOption()
+*/
+void QColorDialog::setOption(ColorDialogOption option, bool on)
+{
+ Q_D(QColorDialog);
+ if (!(d->opts & option) != !on)
+ setOptions(d->opts ^ option);
+}
+
+/*!
+ \since 4.5
+
+ Returns true if the given \a option is enabled; otherwise, returns
+ false.
+
+ \sa options, setOption()
+*/
+bool QColorDialog::testOption(ColorDialogOption option) const
+{
+ Q_D(const QColorDialog);
+ return (d->opts & option) != 0;
+}
+
+/*!
+ \property QColorDialog::options
+ \brief the various options that affect the look and feel of the dialog
+
+ By default, all options are disabled.
+
+ Options should be set before showing the dialog. Setting them while the
+ dialog is visible is not guaranteed to have an immediate effect on the
+ dialog (depending on the option and on the platform).
+
+ \sa setOption(), testOption()
+*/
+void QColorDialog::setOptions(ColorDialogOptions options)
+{
+ Q_D(QColorDialog);
+
+ ColorDialogOptions changed = (options ^ d->opts);
+ if (!changed)
+ return;
+
+ d->opts = options;
+ d->buttons->setVisible(!(options & NoButtons));
+ d->showAlpha(options & ShowAlphaChannel);
+}
+
+QColorDialog::ColorDialogOptions QColorDialog::options() const
+{
+ Q_D(const QColorDialog);
+ return d->opts;
+}
+
+/*!
+ \enum QColorDialog::ColorDialogOption
+
+ \since 4.5
+
+ This enum specifies various options that affect the look and feel
+ of a color dialog.
+
+ \value ShowAlphaChannel Allow the user to select the alpha component of a color.
+ \value NoButtons Don't display \gui{OK} and \gui{Cancel} buttons. (Useful for "live dialogs".)
+ \value DontUseNativeDialog Use Qt's standard color dialog on the Mac instead of Apple's
+ native color panel.
+
+ \sa options, setOption(), testOption(), windowModality()
+*/
+
+/*!
+ \fn void QColorDialog::currentColorChanged(const QColor &color)
+
+ This signal is emitted whenever the current color changes in the dialog.
+ The current color is specified by \a color.
+
+ \sa color, colorSelected()
+*/
+
+#ifdef Q_WS_MAC
+// can only have one Cocoa color panel active
+bool QColorDialogPrivate::sharedColorPanelAvailable = true;
+#endif
+
+/*!
+ \fn void QColorDialog::colorSelected(const QColor &color);
+
+ This signal is emitted just after the user has clicked \gui{OK} to
+ select a color to use. The chosen color is specified by \a color.
+
+ \sa color, currentColorChanged()
+*/
+
+/*!
+ Changes the visibility of the dialog. If \a visible is true, the dialog
+ is shown; otherwise, it is hidden.
+*/
+void QColorDialog::setVisible(bool visible)
+{
+ Q_D(QColorDialog);
+
+ if (visible){
+ if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden))
+ return;
+ } else if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden))
+ return;
+
+ if (visible)
+ d->selectedQColor = QColor();
+
+#if defined(Q_WS_MAC)
+ if (visible) {
+ if (d->delegate || (QColorDialogPrivate::sharedColorPanelAvailable &&
+ !(testAttribute(Qt::WA_DontShowOnScreen) || (d->opts & DontUseNativeDialog)))){
+ d->openCocoaColorPanel(currentColor(), parentWidget(), windowTitle(), options());
+ QColorDialogPrivate::sharedColorPanelAvailable = false;
+ setAttribute(Qt::WA_DontShowOnScreen);
+ }
+ setWindowFlags(windowModality() == Qt::WindowModal ? Qt::Sheet : DefaultWindowFlags);
+ } else {
+ if (d->delegate) {
+ d->closeCocoaColorPanel();
+ setAttribute(Qt::WA_DontShowOnScreen, false);
+ }
+ }
+#else
+
+ if (!(d->opts & DontUseNativeDialog) && qt_guiPlatformPlugin()->colorDialogSetVisible(this, visible)) {
+ d->nativeDialogInUse = true;
+ // Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below
+ // updates the state correctly, but skips showing the non-native version:
+ setAttribute(Qt::WA_DontShowOnScreen);
+ } else {
+ d->nativeDialogInUse = false;
+ setAttribute(Qt::WA_DontShowOnScreen, false);
+ }
+#endif
+
+ QDialog::setVisible(visible);
+}
+
+/*!
+ \overload
+ \since 4.5
+
+ Opens the dialog and connects its colorSelected() signal to the slot specified
+ by \a receiver and \a member.
+
+ The signal will be disconnected from the slot when the dialog is closed.
+*/
+void QColorDialog::open(QObject *receiver, const char *member)
+{
+ Q_D(QColorDialog);
+ connect(this, SIGNAL(colorSelected(QColor)), receiver, member);
+ d->receiverToDisconnectOnClose = receiver;
+ d->memberToDisconnectOnClose = member;
+ QDialog::open();
+}
+
+/*!
+ \fn QColorDialog::open()
+
+ \since 4.5
+ Shows the dialog as a \l{QDialog#Modal Dialogs}{window modal dialog},
+ returning immediately.
+
+ \sa QDialog::open()
+*/
+
+/*
+ For Symbian color dialogs
+*/
+#ifdef Q_WS_S60
+extern QColor qtSymbianGetColor(const QColor &initial);
+#endif
+/*!
+ \since 4.5
+
+ Pops up a modal color dialog with the given window \a title (or "Select Color" if none is
+ specified), lets the user choose a color, and returns that color. The color is initially set
+ to \a initial. The dialog is a child of \a parent. It returns an invalid (see
+ QColor::isValid()) color if the user cancels the dialog.
+
+ The \a options argument allows you to customize the dialog.
+
+ On Symbian, this static function will use the native color dialog and not a QColorDialog.
+ On Symbian the parameters \a title and \a parent has no relevance and the
+ \a options parameter is only used to define if the native color dialog is
+ used or not.
+*/
+QColor QColorDialog::getColor(const QColor &initial, QWidget *parent, const QString &title,
+ ColorDialogOptions options)
+{
+#ifdef Q_WS_S60
+ if (!(options & DontUseNativeDialog))
+ return qtSymbianGetColor(initial);
+#endif
+ QColorDialog dlg(parent);
+ if (!title.isEmpty())
+ dlg.setWindowTitle(title);
+ dlg.setOptions(options);
+ dlg.setCurrentColor(initial);
+ dlg.exec();
+ return dlg.selectedColor();
+}
+
+/*!
+ Pops up a modal color dialog, lets the user choose a color, and
+ returns that color. The color is initially set to \a initial. The
+ dialog is a child of \a parent. It returns an invalid (see
+ QColor::isValid()) color if the user cancels the dialog.
+
+ On Symbian, this static function will use the native
+ color dialog and not a QColorDialog.
+*/
+
+QColor QColorDialog::getColor(const QColor &initial, QWidget *parent)
+{
+#ifdef Q_WS_S60
+ return qtSymbianGetColor(initial);
+#endif
+ return getColor(initial, parent, QString(), ColorDialogOptions(0));
+}
+
+
+/*!
+ \obsolete
+
+ Pops up a modal color dialog to allow the user to choose a color
+ and an alpha channel (transparency) value. The color+alpha is
+ initially set to \a initial. The dialog is a child of \a parent.
+
+ If \a ok is non-null, \e *\a ok is set to true if the user clicked
+ \gui{OK}, and to false if the user clicked Cancel.
+
+ If the user clicks Cancel, the \a initial value is returned.
+
+ Use QColorDialog::getColor() instead, passing the
+ QColorDialog::ShowAlphaChannel option.
+*/
+
+QRgb QColorDialog::getRgba(QRgb initial, bool *ok, QWidget *parent)
+{
+ QColor color(getColor(QColor(initial), parent, QString(), ShowAlphaChannel));
+ QRgb result = color.isValid() ? color.rgba() : initial;
+ if (ok)
+ *ok = color.isValid();
+ return result;
+}
+
+/*!
+ Destroys the color dialog.
+*/
+
+QColorDialog::~QColorDialog()
+{
+ Q_D(QColorDialog);
+#if defined(Q_WS_MAC)
+ if (d->delegate) {
+ d->releaseCocoaColorPanelDelegate();
+ QColorDialogPrivate::sharedColorPanelAvailable = true;
+ }
+#endif
+
+#ifndef QT_NO_SETTINGS
+ if (!customSet) {
+ QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
+ for (int i = 0; i < 2*8; ++i)
+ settings.setValue(QLatin1String("Qt/customColors/") + QString::number(i), cusrgb[i]);
+ }
+#endif
+ if (d->nativeDialogInUse)
+ qt_guiPlatformPlugin()->colorDialogDelete(this);
+
+}
+
+
+/*!
+ \reimp
+*/
+void QColorDialog::changeEvent(QEvent *e)
+{
+ Q_D(QColorDialog);
+ if (e->type() == QEvent::LanguageChange)
+ d->retranslateStrings();
+ QDialog::changeEvent(e);
+}
+
+/*!
+ Closes the dialog and sets its result code to \a result. If this dialog
+ is shown with exec(), done() causes the local event loop to finish,
+ and exec() to return \a result.
+
+ \sa QDialog::done()
+*/
+void QColorDialog::done(int result)
+{
+ Q_D(QColorDialog);
+ QDialog::done(result);
+ if (result == Accepted) {
+ d->selectedQColor = d->currentQColor();
+ emit colorSelected(d->selectedQColor);
+ } else {
+ d->selectedQColor = QColor();
+ }
+ if (d->receiverToDisconnectOnClose) {
+ disconnect(this, SIGNAL(colorSelected(QColor)),
+ d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);
+ d->receiverToDisconnectOnClose = 0;
+ }
+ d->memberToDisconnectOnClose.clear();
+}
+
+QT_END_NAMESPACE
+
+#include "qcolordialog.moc"
+#include "moc_qcolordialog.cpp"
+
+#endif // QT_NO_COLORDIALOG
+
+/*!
+ \fn QColor QColorDialog::getColor(const QColor &init, QWidget *parent, const char *name)
+ \compat
+*/
+
+/*!
+ \fn QRgb QColorDialog::getRgba(QRgb rgba, bool *ok, QWidget *parent, const char *name)
+ \compat
+*/
diff --git a/src/widgets/dialogs/qcolordialog.h b/src/widgets/dialogs/qcolordialog.h
new file mode 100644
index 0000000000..80a893d568
--- /dev/null
+++ b/src/widgets/dialogs/qcolordialog.h
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOLORDIALOG_H
+#define QCOLORDIALOG_H
+
+#include <QtGui/qdialog.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_COLORDIALOG
+
+class QColorDialogPrivate;
+
+class Q_GUI_EXPORT QColorDialog : public QDialog
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QColorDialog)
+ Q_ENUMS(ColorDialogOption)
+ Q_PROPERTY(QColor currentColor READ currentColor WRITE setCurrentColor
+ NOTIFY currentColorChanged)
+ Q_PROPERTY(ColorDialogOptions options READ options WRITE setOptions)
+
+public:
+ enum ColorDialogOption {
+ ShowAlphaChannel = 0x00000001,
+ NoButtons = 0x00000002,
+ DontUseNativeDialog = 0x00000004
+ };
+
+ Q_DECLARE_FLAGS(ColorDialogOptions, ColorDialogOption)
+
+ explicit QColorDialog(QWidget *parent = 0);
+ explicit QColorDialog(const QColor &initial, QWidget *parent = 0);
+ ~QColorDialog();
+
+ void setCurrentColor(const QColor &color);
+ QColor currentColor() const;
+
+ QColor selectedColor() const;
+
+ void setOption(ColorDialogOption option, bool on = true);
+ bool testOption(ColorDialogOption option) const;
+ void setOptions(ColorDialogOptions options);
+ ColorDialogOptions options() const;
+
+#ifdef Q_NO_USING_KEYWORD
+ void open() { QDialog::open(); }
+#else
+ using QDialog::open;
+#endif
+ void open(QObject *receiver, const char *member);
+
+ void setVisible(bool visible);
+
+ // ### Qt 5: merge overloads with title = QString()
+ static QColor getColor(const QColor &initial, QWidget *parent, const QString &title,
+ ColorDialogOptions options = 0);
+ static QColor getColor(const QColor &initial = Qt::white, QWidget *parent = 0);
+
+ // obsolete
+ static QRgb getRgba(QRgb rgba = 0xffffffff, bool *ok = 0, QWidget *parent = 0);
+
+ // ### Qt 5: use QColor in signatures
+ static int customCount();
+ static QRgb customColor(int index);
+ static void setCustomColor(int index, QRgb color);
+ static void setStandardColor(int index, QRgb color);
+
+#ifdef QT3_SUPPORT
+ static QColor getColor(const QColor &init, QWidget *parent, const char *name)
+ { Q_UNUSED(name); return getColor(init, parent); }
+ static QRgb getRgba(QRgb rgba, bool *ok, QWidget *parent, const char *name)
+ { Q_UNUSED(name); return getRgba(rgba, ok, parent); }
+#endif
+
+Q_SIGNALS:
+ void currentColorChanged(const QColor &color);
+ void colorSelected(const QColor &color);
+
+protected:
+ void changeEvent(QEvent *event);
+ void done(int result);
+
+private:
+ Q_DISABLE_COPY(QColorDialog)
+
+ Q_PRIVATE_SLOT(d_func(), void _q_addCustom())
+ Q_PRIVATE_SLOT(d_func(), void _q_newHsv(int h, int s, int v))
+ Q_PRIVATE_SLOT(d_func(), void _q_newColorTypedIn(QRgb rgb))
+ Q_PRIVATE_SLOT(d_func(), void _q_newCustom(int, int))
+ Q_PRIVATE_SLOT(d_func(), void _q_newStandard(int, int))
+#if defined(Q_WS_MAC)
+ Q_PRIVATE_SLOT(d_func(), void _q_macRunNativeAppModalPanel())
+#endif
+
+ friend class QColorShower;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QColorDialog::ColorDialogOptions)
+
+#endif // QT_NO_COLORDIALOG
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QCOLORDIALOG_H
diff --git a/src/widgets/dialogs/qcolordialog_mac.mm b/src/widgets/dialogs/qcolordialog_mac.mm
new file mode 100644
index 0000000000..ee9b19ad99
--- /dev/null
+++ b/src/widgets/dialogs/qcolordialog_mac.mm
@@ -0,0 +1,500 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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 "qcolordialog_p.h"
+#if !defined(QT_NO_COLORDIALOG) && defined(Q_WS_MAC)
+#include <qapplication.h>
+#include <qtimer.h>
+#include <qdialogbuttonbox.h>
+#include <qabstracteventdispatcher.h>
+#include <private/qapplication_p.h>
+#include <private/qt_mac_p.h>
+#include <qdebug.h>
+#import <AppKit/AppKit.h>
+#import <Foundation/Foundation.h>
+
+#if !CGFLOAT_DEFINED
+typedef float CGFloat; // Should only not be defined on 32-bit platforms
+#endif
+
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
+@protocol NSWindowDelegate <NSObject>
+- (void)windowDidResize:(NSNotification *)notification;
+- (BOOL)windowShouldClose:(id)window;
+@end
+#endif
+
+QT_USE_NAMESPACE
+
+@class QT_MANGLE_NAMESPACE(QCocoaColorPanelDelegate);
+
+@interface QT_MANGLE_NAMESPACE(QCocoaColorPanelDelegate) : NSObject<NSWindowDelegate> {
+ NSColorPanel *mColorPanel;
+ NSView *mStolenContentView;
+ NSButton *mOkButton;
+ NSButton *mCancelButton;
+ QColorDialogPrivate *mPriv;
+ QColor *mQtColor;
+ CGFloat mMinWidth; // currently unused
+ CGFloat mExtraHeight; // currently unused
+ BOOL mHackedPanel;
+ NSInteger mResultCode;
+ BOOL mDialogIsExecuting;
+ BOOL mResultSet;
+}
+- (id)initWithColorPanel:(NSColorPanel *)panel
+ stolenContentView:(NSView *)stolenContentView
+ okButton:(NSButton *)okButton
+ cancelButton:(NSButton *)cancelButton
+ priv:(QColorDialogPrivate *)priv;
+- (void)colorChanged:(NSNotification *)notification;
+- (void)relayout;
+- (void)onOkClicked;
+- (void)onCancelClicked;
+- (void)updateQtColor;
+- (NSColorPanel *)colorPanel;
+- (QColor)qtColor;
+- (void)finishOffWithCode:(NSInteger)result;
+- (void)showColorPanel;
+- (void)exec;
+- (void)setResultSet:(BOOL)result;
+@end
+
+@implementation QT_MANGLE_NAMESPACE(QCocoaColorPanelDelegate)
+- (id)initWithColorPanel:(NSColorPanel *)panel
+ stolenContentView:(NSView *)stolenContentView
+ okButton:(NSButton *)okButton
+ cancelButton:(NSButton *)cancelButton
+ priv:(QColorDialogPrivate *)priv
+{
+ self = [super init];
+
+ mColorPanel = panel;
+ mStolenContentView = stolenContentView;
+ mOkButton = okButton;
+ mCancelButton = cancelButton;
+ mPriv = priv;
+ mMinWidth = 0.0;
+ mExtraHeight = 0.0;
+ mHackedPanel = (okButton != 0);
+ mResultCode = NSCancelButton;
+ mDialogIsExecuting = false;
+ mResultSet = false;
+
+ if (mHackedPanel) {
+ [self relayout];
+
+ [okButton setAction:@selector(onOkClicked)];
+ [okButton setTarget:self];
+
+ [cancelButton setAction:@selector(onCancelClicked)];
+ [cancelButton setTarget:self];
+ }
+
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(colorChanged:)
+ name:NSColorPanelColorDidChangeNotification
+ object:mColorPanel];
+
+ mQtColor = new QColor();
+ return self;
+}
+
+- (void)dealloc
+{
+ QMacCocoaAutoReleasePool pool;
+ if (mHackedPanel) {
+ NSView *ourContentView = [mColorPanel contentView];
+
+ // return stolen stuff to its rightful owner
+ [mStolenContentView removeFromSuperview];
+ [mColorPanel setContentView:mStolenContentView];
+
+ [mOkButton release];
+ [mCancelButton release];
+ [ourContentView release];
+ }
+ [mColorPanel setDelegate:nil];
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+ delete mQtColor;
+ [super dealloc];
+}
+
+- (void)setResultSet:(BOOL)result
+{
+ mResultSet = result;
+}
+
+- (BOOL)windowShouldClose:(id)window
+{
+ Q_UNUSED(window);
+ if (!mHackedPanel)
+ [self updateQtColor];
+ if (mDialogIsExecuting) {
+ [self finishOffWithCode:NSCancelButton];
+ } else {
+ mResultSet = true;
+ mPriv->colorDialog()->reject();
+ }
+ return true;
+}
+
+- (void)windowDidResize:(NSNotification *)notification
+{
+ Q_UNUSED(notification);
+ if (mHackedPanel)
+ [self relayout];
+}
+
+- (void)colorChanged:(NSNotification *)notification
+{
+ Q_UNUSED(notification);
+ [self updateQtColor];
+}
+
+- (void)relayout
+{
+ Q_ASSERT(mHackedPanel);
+
+ NSRect rect = [[mStolenContentView superview] frame];
+
+ // should a priori be kept in sync with qfontdialog_mac.mm
+ const CGFloat ButtonMinWidth = 78.0; // 84.0 for Carbon
+ const CGFloat ButtonMinHeight = 32.0;
+ const CGFloat ButtonSpacing = 0.0;
+ const CGFloat ButtonTopMargin = 0.0;
+ const CGFloat ButtonBottomMargin = 7.0;
+ const CGFloat ButtonSideMargin = 9.0;
+
+ [mOkButton sizeToFit];
+ NSSize okSizeHint = [mOkButton frame].size;
+
+ [mCancelButton sizeToFit];
+ NSSize cancelSizeHint = [mCancelButton frame].size;
+
+ const CGFloat ButtonWidth = qMin(qMax(ButtonMinWidth,
+ qMax(okSizeHint.width, cancelSizeHint.width)),
+ CGFloat((rect.size.width - 2.0 * ButtonSideMargin - ButtonSpacing) * 0.5));
+ const CGFloat ButtonHeight = qMax(ButtonMinHeight,
+ qMax(okSizeHint.height, cancelSizeHint.height));
+
+ NSRect okRect = { { rect.size.width - ButtonSideMargin - ButtonWidth,
+ ButtonBottomMargin },
+ { ButtonWidth, ButtonHeight } };
+ [mOkButton setFrame:okRect];
+ [mOkButton setNeedsDisplay:YES];
+
+ NSRect cancelRect = { { okRect.origin.x - ButtonSpacing - ButtonWidth,
+ ButtonBottomMargin },
+ { ButtonWidth, ButtonHeight } };
+ [mCancelButton setFrame:cancelRect];
+ [mCancelButton setNeedsDisplay:YES];
+
+ const CGFloat Y = ButtonBottomMargin + ButtonHeight + ButtonTopMargin;
+ NSRect stolenCVRect = { { 0.0, Y },
+ { rect.size.width, rect.size.height - Y } };
+ [mStolenContentView setFrame:stolenCVRect];
+ [mStolenContentView setNeedsDisplay:YES];
+
+ [[mStolenContentView superview] setNeedsDisplay:YES];
+ mMinWidth = 2 * ButtonSideMargin + ButtonSpacing + 2 * ButtonWidth;
+ mExtraHeight = Y;
+}
+
+- (void)onOkClicked
+{
+ Q_ASSERT(mHackedPanel);
+ [[mStolenContentView window] close];
+ [self updateQtColor];
+ [self finishOffWithCode:NSOKButton];
+}
+
+- (void)onCancelClicked
+{
+ if (mHackedPanel) {
+ [[mStolenContentView window] close];
+ delete mQtColor;
+ mQtColor = new QColor();
+ [self finishOffWithCode:NSCancelButton];
+ }
+}
+
+- (void)updateQtColor
+{
+ delete mQtColor;
+ mQtColor = new QColor();
+ NSColor *color = [mColorPanel color];
+ NSString *colorSpaceName = [color colorSpaceName];
+ if (colorSpaceName == NSDeviceCMYKColorSpace) {
+ CGFloat cyan = 0, magenta = 0, yellow = 0, black = 0, alpha = 0;
+ [color getCyan:&cyan magenta:&magenta yellow:&yellow black:&black alpha:&alpha];
+ mQtColor->setCmykF(cyan, magenta, yellow, black, alpha);
+ } else if (colorSpaceName == NSCalibratedRGBColorSpace || colorSpaceName == NSDeviceRGBColorSpace) {
+ CGFloat red = 0, green = 0, blue = 0, alpha = 0;
+ [color getRed:&red green:&green blue:&blue alpha:&alpha];
+ mQtColor->setRgbF(red, green, blue, alpha);
+ } else if (colorSpaceName == NSNamedColorSpace) {
+ NSColor *tmpColor = [color colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
+ CGFloat red = 0, green = 0, blue = 0, alpha = 0;
+ [tmpColor getRed:&red green:&green blue:&blue alpha:&alpha];
+ mQtColor->setRgbF(red, green, blue, alpha);
+ } else {
+ NSColorSpace *colorSpace = [color colorSpace];
+ if ([colorSpace colorSpaceModel] == NSCMYKColorSpaceModel && [color numberOfComponents] == 5){
+ CGFloat components[5];
+ [color getComponents:components];
+ mQtColor->setCmykF(components[0], components[1], components[2], components[3], components[4]);
+ } else {
+ NSColor *tmpColor = [color colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
+ CGFloat red = 0, green = 0, blue = 0, alpha = 0;
+ [tmpColor getRed:&red green:&green blue:&blue alpha:&alpha];
+ mQtColor->setRgbF(red, green, blue, alpha);
+ }
+ }
+
+ mPriv->setCurrentQColor(*mQtColor);
+}
+
+- (NSColorPanel *)colorPanel
+{
+ return mColorPanel;
+}
+
+- (QColor)qtColor
+{
+ return *mQtColor;
+}
+
+- (void)finishOffWithCode:(NSInteger)code
+{
+ mResultCode = code;
+ if (mDialogIsExecuting) {
+ // We stop the current modal event loop. The control
+ // will then return inside -(void)exec below.
+ // It's important that the modal event loop is stopped before
+ // we accept/reject QColorDialog, since QColorDialog has its
+ // own event loop that needs to be stopped last.
+ [NSApp stopModalWithCode:code];
+ } else {
+ // Since we are not in a modal event loop, we can safely close
+ // down QColorDialog
+ // Calling accept() or reject() can in turn call closeCocoaColorPanel.
+ // This check will prevent any such recursion.
+ if (!mResultSet) {
+ mResultSet = true;
+ if (mResultCode == NSCancelButton) {
+ mPriv->colorDialog()->reject();
+ } else {
+ mPriv->colorDialog()->accept();
+ }
+ }
+ }
+}
+
+- (void)showColorPanel
+{
+ mDialogIsExecuting = false;
+ [mColorPanel makeKeyAndOrderFront:mColorPanel];
+}
+
+- (void)exec
+{
+ QBoolBlocker nativeDialogOnTop(QApplicationPrivate::native_modal_dialog_active);
+ QMacCocoaAutoReleasePool pool;
+ mDialogIsExecuting = true;
+ bool modalEnded = false;
+ while (!modalEnded) {
+ @try {
+ [NSApp runModalForWindow:mColorPanel];
+ modalEnded = true;
+ } @catch (NSException *) {
+ // For some reason, NSColorPanel throws an exception when
+ // clicking on 'SelectedMenuItemColor' from the 'Developer'
+ // palette (tab three).
+ }
+ }
+
+ QAbstractEventDispatcher::instance()->interrupt();
+ if (mResultCode == NSCancelButton)
+ mPriv->colorDialog()->reject();
+ else
+ mPriv->colorDialog()->accept();
+}
+
+@end
+
+QT_BEGIN_NAMESPACE
+
+extern void macStartInterceptNSPanelCtor();
+extern void macStopInterceptNSPanelCtor();
+extern NSButton *macCreateButton(const char *text, NSView *superview);
+
+void QColorDialogPrivate::openCocoaColorPanel(const QColor &initial,
+ QWidget *parent, const QString &title, QColorDialog::ColorDialogOptions options)
+{
+ Q_UNUSED(parent); // we would use the parent if only NSColorPanel could be a sheet
+ QMacCocoaAutoReleasePool pool;
+
+ if (!delegate) {
+ /*
+ The standard Cocoa color panel has no OK or Cancel button and
+ is created as a utility window, whereas we want something like
+ the Carbon color panel. We need to take the following steps:
+
+ 1. Intercept the color panel constructor to turn off the
+ NSUtilityWindowMask flag. This is done by temporarily
+ replacing initWithContentRect:styleMask:backing:defer:
+ in NSPanel by our own method.
+
+ 2. Modify the color panel so that its content view is part
+ of a new content view that contains it as well as two
+ buttons (OK and Cancel).
+
+ 3. Lay out the original content view and the buttons when
+ the color panel is shown and whenever it is resized.
+
+ 4. Clean up after ourselves.
+ */
+
+ bool hackColorPanel = !(options & QColorDialog::NoButtons);
+
+ if (hackColorPanel)
+ macStartInterceptNSPanelCtor();
+ NSColorPanel *colorPanel = [NSColorPanel sharedColorPanel];
+ if (hackColorPanel)
+ macStopInterceptNSPanelCtor();
+
+ [colorPanel setHidesOnDeactivate:false];
+
+ // set up the Cocoa color panel
+ [colorPanel setShowsAlpha:options & QColorDialog::ShowAlphaChannel];
+ [colorPanel setTitle:(NSString*)(CFStringRef)QCFString(title)];
+
+ NSView *stolenContentView = 0;
+ NSButton *okButton = 0;
+ NSButton *cancelButton = 0;
+
+ if (hackColorPanel) {
+ // steal the color panel's contents view
+ stolenContentView = [colorPanel contentView];
+ [stolenContentView retain];
+ [colorPanel setContentView:0];
+
+ // create a new content view and add the stolen one as a subview
+ NSRect frameRect = { { 0.0, 0.0 }, { 0.0, 0.0 } };
+ NSView *ourContentView = [[NSView alloc] initWithFrame:frameRect];
+ [ourContentView addSubview:stolenContentView];
+
+ // create OK and Cancel buttons and add these as subviews
+ okButton = macCreateButton("&OK", ourContentView);
+ cancelButton = macCreateButton("Cancel", ourContentView);
+
+ [colorPanel setContentView:ourContentView];
+ [colorPanel setDefaultButtonCell:[okButton cell]];
+ }
+
+ delegate = [[QT_MANGLE_NAMESPACE(QCocoaColorPanelDelegate) alloc] initWithColorPanel:colorPanel
+ stolenContentView:stolenContentView
+ okButton:okButton
+ cancelButton:cancelButton
+ priv:this];
+ [colorPanel setDelegate:static_cast<QT_MANGLE_NAMESPACE(QCocoaColorPanelDelegate) *>(delegate)];
+ }
+ [static_cast<QT_MANGLE_NAMESPACE(QCocoaColorPanelDelegate) *>(delegate) setResultSet:NO];
+ setCocoaPanelColor(initial);
+ [static_cast<QT_MANGLE_NAMESPACE(QCocoaColorPanelDelegate) *>(delegate) showColorPanel];
+}
+
+void QColorDialogPrivate::closeCocoaColorPanel()
+{
+ [static_cast<QT_MANGLE_NAMESPACE(QCocoaColorPanelDelegate) *>(delegate) onCancelClicked];
+}
+
+void QColorDialogPrivate::releaseCocoaColorPanelDelegate()
+{
+ [static_cast<QT_MANGLE_NAMESPACE(QCocoaColorPanelDelegate) *>(delegate) release];
+}
+
+void QColorDialogPrivate::mac_nativeDialogModalHelp()
+{
+ // Do a queued meta-call to open the native modal dialog so it opens after the new
+ // event loop has started to execute (in QDialog::exec). Using a timer rather than
+ // a queued meta call is intentional to ensure that the call is only delivered when
+ // [NSApp run] runs (timers are handeled special in cocoa). If NSApp is not
+ // running (which is the case if e.g a top-most QEventLoop has been
+ // interrupted, and the second-most event loop has not yet been reactivated (regardless
+ // if [NSApp run] is still on the stack)), showing a native modal dialog will fail.
+ if (delegate){
+ Q_Q(QColorDialog);
+ QTimer::singleShot(1, q, SLOT(_q_macRunNativeAppModalPanel()));
+ }
+}
+
+void QColorDialogPrivate::_q_macRunNativeAppModalPanel()
+{
+ [static_cast<QT_MANGLE_NAMESPACE(QCocoaColorPanelDelegate) *>(delegate) exec];
+}
+
+void QColorDialogPrivate::setCocoaPanelColor(const QColor &color)
+{
+ QMacCocoaAutoReleasePool pool;
+ QT_MANGLE_NAMESPACE(QCocoaColorPanelDelegate) *theDelegate = static_cast<QT_MANGLE_NAMESPACE(QCocoaColorPanelDelegate) *>(delegate);
+ NSColor *nsColor;
+ const QColor::Spec spec = color.spec();
+ if (spec == QColor::Cmyk) {
+ nsColor = [NSColor colorWithDeviceCyan:color.cyanF()
+ magenta:color.magentaF()
+ yellow:color.yellowF()
+ black:color.blackF()
+ alpha:color.alphaF()];
+ } else {
+ nsColor = [NSColor colorWithCalibratedRed:color.redF()
+ green:color.greenF()
+ blue:color.blueF()
+ alpha:color.alphaF()];
+ }
+ [[theDelegate colorPanel] setColor:nsColor];
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/widgets/dialogs/qcolordialog_p.h b/src/widgets/dialogs/qcolordialog_p.h
new file mode 100644
index 0000000000..243e7277c5
--- /dev/null
+++ b/src/widgets/dialogs/qcolordialog_p.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOLORDIALOG_P_H
+#define QCOLORDIALOG_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+//
+
+#include "private/qdialog_p.h"
+#include "qcolordialog.h"
+
+#ifndef QT_NO_COLORDIALOG
+
+QT_BEGIN_NAMESPACE
+
+class QColorLuminancePicker;
+class QColorPicker;
+class QColorShower;
+class QDialogButtonBox;
+class QLabel;
+class QVBoxLayout;
+class QPushButton;
+class QWellArray;
+
+class QColorDialogPrivate : public QDialogPrivate
+{
+ Q_DECLARE_PUBLIC(QColorDialog)
+
+public:
+ void init(const QColor &initial);
+ QRgb currentColor() const;
+ QColor currentQColor() const;
+ void setCurrentColor(QRgb rgb);
+ void setCurrentQColor(const QColor &color);
+ bool selectColor(const QColor &color);
+
+ int currentAlpha() const;
+ void setCurrentAlpha(int a);
+ void showAlpha(bool b);
+ bool isAlphaVisible() const;
+ void retranslateStrings();
+
+ void _q_addCustom();
+
+ void _q_newHsv(int h, int s, int v);
+ void _q_newColorTypedIn(QRgb rgb);
+ void _q_newCustom(int, int);
+ void _q_newStandard(int, int);
+
+ QWellArray *custom;
+ QWellArray *standard;
+
+ QDialogButtonBox *buttons;
+ QVBoxLayout *leftLay;
+ QColorPicker *cp;
+ QColorLuminancePicker *lp;
+ QColorShower *cs;
+ QLabel *lblBasicColors;
+ QLabel *lblCustomColors;
+ QPushButton *ok;
+ QPushButton *cancel;
+ QPushButton *addCusBt;
+ QColor selectedQColor;
+ int nextCust;
+ bool smallDisplay;
+ QColorDialog::ColorDialogOptions opts;
+ QPointer<QObject> receiverToDisconnectOnClose;
+ QByteArray memberToDisconnectOnClose;
+ bool nativeDialogInUse;
+
+#ifdef Q_WS_MAC
+ void openCocoaColorPanel(const QColor &initial,
+ QWidget *parent, const QString &title, QColorDialog::ColorDialogOptions options);
+ void closeCocoaColorPanel();
+ void releaseCocoaColorPanelDelegate();
+ void setCocoaPanelColor(const QColor &color);
+
+ inline void done(int result) { q_func()->done(result); }
+ inline QColorDialog *colorDialog() { return q_func(); }
+
+ void *delegate;
+
+ static bool sharedColorPanelAvailable;
+
+ void _q_macRunNativeAppModalPanel();
+ void mac_nativeDialogModalHelp();
+#endif
+};
+
+#endif // QT_NO_COLORDIALOG
+
+QT_END_NAMESPACE
+
+#endif // QCOLORDIALOG_P_H
diff --git a/src/widgets/dialogs/qcolordialog_symbian.cpp b/src/widgets/dialogs/qcolordialog_symbian.cpp
new file mode 100644
index 0000000000..3dbb5c11a9
--- /dev/null
+++ b/src/widgets/dialogs/qcolordialog_symbian.cpp
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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 "qcolordialog_p.h"
+
+#ifndef QT_NO_COLORDIALOG
+
+
+#include "qcolor.h"
+#include "private/qguiplatformplugin_p.h"
+
+#ifdef Q_WS_S60
+#include <AknColourSelectionGrid.h>
+#endif
+
+#include "private/qt_s60_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QColor launchSymbianColorDialog(QColor initial)
+{
+ QColor currentColor = QColor::Invalid;
+#ifdef Q_WS_S60
+ QT_TRAP_THROWING(
+ CArrayFixFlat<TRgb>* array = new( ELeave ) CArrayFixFlat<TRgb>(17);
+ CleanupStack::PushL(array);
+ array->AppendL(KRgbBlack);
+ array->AppendL(KRgbDarkGray);
+ array->AppendL(KRgbDarkRed);
+ array->AppendL(KRgbDarkGreen);
+ array->AppendL(KRgbDarkYellow);
+ array->AppendL(KRgbDarkBlue);
+ array->AppendL(KRgbDarkMagenta);
+ array->AppendL(KRgbDarkCyan);
+ array->AppendL(KRgbRed);
+ array->AppendL(KRgbGreen);
+ array->AppendL(KRgbYellow);
+ array->AppendL(KRgbBlue);
+ array->AppendL(KRgbMagenta);
+ array->AppendL(KRgbCyan);
+ array->AppendL(KRgbGray);
+ array->AppendL(KRgbWhite);
+
+ TRgb initialColour(initial.red(), initial.green(), initial.blue(), initial.alpha());
+
+ TBool noneChosen = EFalse; // If true shows the default colour button
+ CAknColourSelectionGrid* colourSelectionGrid =
+ CAknColourSelectionGrid::NewL(array, EFalse, noneChosen, initialColour);
+ CleanupStack::PushL(colourSelectionGrid);
+
+ if (colourSelectionGrid->ExecuteLD()) {
+ currentColor.setRgb(initialColour.Red(), initialColour.Green(),
+ initialColour.Blue(), initialColour.Alpha());
+ }
+ CleanupStack::Pop(colourSelectionGrid);
+ CleanupStack::PopAndDestroy(array);
+ );
+#endif
+ return currentColor;
+}
+
+QColor qtSymbianGetColor(const QColor &initial)
+{
+ return launchSymbianColorDialog(initial);
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_COLORDIALOG
diff --git a/src/widgets/dialogs/qdialog.cpp b/src/widgets/dialogs/qdialog.cpp
new file mode 100644
index 0000000000..6838d927a8
--- /dev/null
+++ b/src/widgets/dialogs/qdialog.cpp
@@ -0,0 +1,1272 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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 "qdialog.h"
+
+
+#include "qevent.h"
+#include "qdesktopwidget.h"
+#include "qpushbutton.h"
+#include "qapplication.h"
+#include "qlayout.h"
+#include "qsizegrip.h"
+#include "qwhatsthis.h"
+#include "qmenu.h"
+#include "qcursor.h"
+#include "private/qdialog_p.h"
+#ifndef QT_NO_ACCESSIBILITY
+#include "qaccessible.h"
+#endif
+#if defined(Q_WS_WINCE)
+#include "qt_windows.h"
+#include "qmenubar.h"
+#include "qpointer.h"
+#include "qguifunctions_wince.h"
+extern bool qt_wince_is_mobile(); //defined in qguifunctions_wce.cpp
+extern bool qt_wince_is_smartphone(); //is defined in qguifunctions_wce.cpp
+#elif defined(Q_WS_X11)
+# include "../kernel/qt_x11_p.h"
+#elif defined(Q_OS_SYMBIAN)
+# include "qfiledialog.h"
+# include "qfontdialog.h"
+# include "qwizard.h"
+# include "private/qt_s60_p.h"
+#endif
+
+#if defined(Q_WS_S60)
+#include <AknUtils.h> // AknLayoutUtils
+#endif
+
+#ifndef SPI_GETSNAPTODEFBUTTON
+# define SPI_GETSNAPTODEFBUTTON 95
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QDialog
+ \brief The QDialog class is the base class of dialog windows.
+
+ \ingroup dialog-classes
+ \ingroup abstractwidgets
+
+
+ A dialog window is a top-level window mostly used for short-term
+ tasks and brief communications with the user. QDialogs may be
+ modal or modeless. QDialogs can
+ provide a \link #return return
+ value\endlink, and they can have \link #default default
+ buttons\endlink. QDialogs can also have a QSizeGrip in their
+ lower-right corner, using setSizeGripEnabled().
+
+ Note that QDialog (an any other widget that has type Qt::Dialog) uses
+ the parent widget slightly differently from other classes in Qt. A
+ dialog is always a top-level widget, but if it has a parent, its
+ default location is centered on top of the parent's top-level widget
+ (if it is not top-level itself). It will also share the parent's
+ taskbar entry.
+
+ Use the overload of the QWidget::setParent() function to change
+ the ownership of a QDialog widget. This function allows you to
+ explicitly set the window flags of the reparented widget; using
+ the overloaded function will clear the window flags specifying the
+ window-system properties for the widget (in particular it will
+ reset the Qt::Dialog flag).
+
+ \section1 Modal Dialogs
+
+ A \bold{modal} dialog is a dialog that blocks input to other
+ visible windows in the same application. Dialogs that are used to
+ request a file name from the user or that are used to set
+ application preferences are usually modal. Dialogs can be
+ \l{Qt::ApplicationModal}{application modal} (the default) or
+ \l{Qt::WindowModal}{window modal}.
+
+ When an application modal dialog is opened, the user must finish
+ interacting with the dialog and close it before they can access
+ any other window in the application. Window modal dialogs only
+ block access to the window associated with the dialog, allowing
+ the user to continue to use other windows in an application.
+
+ The most common way to display a modal dialog is to call its
+ exec() function. When the user closes the dialog, exec() will
+ provide a useful \link #return return value\endlink. Typically,
+ to get the dialog to close and return the appropriate value, we
+ connect a default button, e.g. \gui OK, to the accept() slot and a
+ \gui Cancel button to the reject() slot.
+ Alternatively you can call the done() slot with \c Accepted or
+ \c Rejected.
+
+ An alternative is to call setModal(true) or setWindowModality(),
+ then show(). Unlike exec(), show() returns control to the caller
+ immediately. Calling setModal(true) is especially useful for
+ progress dialogs, where the user must have the ability to interact
+ with the dialog, e.g. to cancel a long running operation. If you
+ use show() and setModal(true) together to perform a long operation,
+ you must call QApplication::processEvents() periodically during
+ processing to enable the user to interact with the dialog. (See
+ QProgressDialog.)
+
+ \section1 Modeless Dialogs
+
+ A \bold{modeless} dialog is a dialog that operates
+ independently of other windows in the same application. Find and
+ replace dialogs in word-processors are often modeless to allow the
+ user to interact with both the application's main window and with
+ the dialog.
+
+ Modeless dialogs are displayed using show(), which returns control
+ to the caller immediately.
+
+ If you invoke the \l{QWidget::show()}{show()} function after hiding
+ a dialog, the dialog will be displayed in its original position. This is
+ because the window manager decides the position for windows that
+ have not been explicitly placed by the programmer. To preserve the
+ position of a dialog that has been moved by the user, save its position
+ in your \l{QWidget::closeEvent()}{closeEvent()} handler and then
+ move the dialog to that position, before showing it again.
+
+ \target default
+ \section1 Default Button
+
+ A dialog's \e default button is the button that's pressed when the
+ user presses Enter (Return). This button is used to signify that
+ the user accepts the dialog's settings and wants to close the
+ dialog. Use QPushButton::setDefault(), QPushButton::isDefault()
+ and QPushButton::autoDefault() to set and control the dialog's
+ default button.
+
+ \target escapekey
+ \section1 Escape Key
+
+ If the user presses the Esc key in a dialog, QDialog::reject()
+ will be called. This will cause the window to close: The \link
+ QCloseEvent close event \endlink cannot be \link
+ QCloseEvent::ignore() ignored \endlink.
+
+ \section1 Extensibility
+
+ Extensibility is the ability to show the dialog in two ways: a
+ partial dialog that shows the most commonly used options, and a
+ full dialog that shows all the options. Typically an extensible
+ dialog will initially appear as a partial dialog, but with a
+ \gui More toggle button. If the user presses the \gui More button down,
+ the dialog is expanded. The \l{Extension Example} shows how to achieve
+ extensible dialogs using Qt.
+
+ \target return
+ \section1 Return Value (Modal Dialogs)
+
+ Modal dialogs are often used in situations where a return value is
+ required, e.g. to indicate whether the user pressed \gui OK or
+ \gui Cancel. A dialog can be closed by calling the accept() or the
+ reject() slots, and exec() will return \c Accepted or \c Rejected
+ as appropriate. The exec() call returns the result of the dialog.
+ The result is also available from result() if the dialog has not
+ been destroyed.
+
+ In order to modify your dialog's close behavior, you can reimplement
+ the functions accept(), reject() or done(). The
+ \l{QWidget::closeEvent()}{closeEvent()} function should only be
+ reimplemented to preserve the dialog's position or to override the
+ standard close or reject behavior.
+
+ \target examples
+ \section1 Code Examples
+
+ A modal dialog:
+
+ \snippet doc/src/snippets/dialogs/dialogs.cpp 1
+
+ A modeless dialog:
+
+ \snippet doc/src/snippets/dialogs/dialogs.cpp 0
+
+ \sa QDialogButtonBox, QTabWidget, QWidget, QProgressDialog,
+ {fowler}{GUI Design Handbook: Dialogs, Standard}, {Extension Example},
+ {Standard Dialogs Example}
+*/
+
+/*! \enum QDialog::DialogCode
+
+ The value returned by a modal dialog.
+
+ \value Accepted
+ \value Rejected
+*/
+
+/*!
+ \property QDialog::sizeGripEnabled
+ \brief whether the size grip is enabled
+
+ A QSizeGrip is placed in the bottom-right corner of the dialog when this
+ property is enabled. By default, the size grip is disabled.
+*/
+
+
+/*!
+ Constructs a dialog with parent \a parent.
+
+ A dialog is always a top-level widget, but if it has a parent, its
+ default location is centered on top of the parent. It will also
+ share the parent's taskbar entry.
+
+ The widget flags \a f are passed on to the QWidget constructor.
+ If, for example, you don't want a What's This button in the title bar
+ of the dialog, pass Qt::WindowTitleHint | Qt::WindowSystemMenuHint in \a f.
+
+ \sa QWidget::setWindowFlags()
+*/
+
+QDialog::QDialog(QWidget *parent, Qt::WindowFlags f)
+ : QWidget(*new QDialogPrivate, parent,
+ f | ((f & Qt::WindowType_Mask) == 0 ? Qt::Dialog : Qt::WindowType(0)))
+{
+#ifdef Q_WS_WINCE
+ if (!qt_wince_is_smartphone())
+ setWindowFlags(windowFlags() | Qt::WindowOkButtonHint | QFlag(qt_wince_is_mobile() ? 0 : Qt::WindowCancelButtonHint));
+#endif
+
+#ifdef Q_WS_S60
+ if (S60->avkonComponentsSupportTransparency) {
+ bool noSystemBackground = testAttribute(Qt::WA_NoSystemBackground);
+ setAttribute(Qt::WA_TranslucentBackground); // also sets WA_NoSystemBackground
+ setAttribute(Qt::WA_NoSystemBackground, noSystemBackground); // restore system background attribute
+ }
+#endif
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ \overload
+ \obsolete
+*/
+QDialog::QDialog(QWidget *parent, const char *name, bool modal, Qt::WindowFlags f)
+ : QWidget(*new QDialogPrivate, parent,
+ f
+ | QFlag(modal ? Qt::WShowModal : Qt::WindowType(0))
+ | QFlag((f & Qt::WindowType_Mask) == 0 ? Qt::Dialog : Qt::WindowType(0))
+ )
+{
+ setObjectName(QString::fromAscii(name));
+}
+#endif
+
+/*!
+ \overload
+ \internal
+*/
+QDialog::QDialog(QDialogPrivate &dd, QWidget *parent, Qt::WindowFlags f)
+ : QWidget(dd, parent, f | ((f & Qt::WindowType_Mask) == 0 ? Qt::Dialog : Qt::WindowType(0)))
+{
+#ifdef Q_WS_WINCE
+ if (!qt_wince_is_smartphone())
+ setWindowFlags(windowFlags() | Qt::WindowOkButtonHint | QFlag(qt_wince_is_mobile() ? 0 : Qt::WindowCancelButtonHint));
+#endif
+
+#ifdef Q_WS_S60
+ if (S60->avkonComponentsSupportTransparency) {
+ bool noSystemBackground = testAttribute(Qt::WA_NoSystemBackground);
+ setAttribute(Qt::WA_TranslucentBackground); // also sets WA_NoSystemBackground
+ setAttribute(Qt::WA_NoSystemBackground, noSystemBackground); // restore system background attribute
+ }
+#endif
+}
+
+/*!
+ Destroys the QDialog, deleting all its children.
+*/
+
+QDialog::~QDialog()
+{
+ QT_TRY {
+ // Need to hide() here, as our (to-be) overridden hide()
+ // will not be called in ~QWidget.
+ hide();
+ } QT_CATCH(...) {
+ // we're in the destructor - just swallow the exception
+ }
+}
+
+/*!
+ \internal
+ This function is called by the push button \a pushButton when it
+ becomes the default button. If \a pushButton is 0, the dialogs
+ default default button becomes the default button. This is what a
+ push button calls when it loses focus.
+*/
+void QDialogPrivate::setDefault(QPushButton *pushButton)
+{
+ Q_Q(QDialog);
+ bool hasMain = false;
+ QList<QPushButton*> list = q->findChildren<QPushButton*>();
+ for (int i=0; i<list.size(); ++i) {
+ QPushButton *pb = list.at(i);
+ if (pb->window() == q) {
+ if (pb == mainDef)
+ hasMain = true;
+ if (pb != pushButton)
+ pb->setDefault(false);
+ }
+ }
+ if (!pushButton && hasMain)
+ mainDef->setDefault(true);
+ if (!hasMain)
+ mainDef = pushButton;
+}
+
+/*!
+ \internal
+ This function sets the default default push button to \a pushButton.
+ This function is called by QPushButton::setDefault().
+*/
+void QDialogPrivate::setMainDefault(QPushButton *pushButton)
+{
+ mainDef = 0;
+ setDefault(pushButton);
+}
+
+/*!
+ \internal
+ Hides the default button indicator. Called when non auto-default
+ push button get focus.
+ */
+void QDialogPrivate::hideDefault()
+{
+ Q_Q(QDialog);
+ QList<QPushButton*> list = q->findChildren<QPushButton*>();
+ for (int i=0; i<list.size(); ++i) {
+ list.at(i)->setDefault(false);
+ }
+}
+
+void QDialogPrivate::resetModalitySetByOpen()
+{
+ Q_Q(QDialog);
+ if (resetModalityTo != -1 && !q->testAttribute(Qt::WA_SetWindowModality)) {
+ // open() changed the window modality and the user didn't touch it afterwards; restore it
+ q->setWindowModality(Qt::WindowModality(resetModalityTo));
+ q->setAttribute(Qt::WA_SetWindowModality, wasModalitySet);
+#ifdef Q_WS_MAC
+ Q_ASSERT(resetModalityTo != Qt::WindowModal);
+ q->setParent(q->parentWidget(), Qt::Dialog);
+#endif
+ }
+ resetModalityTo = -1;
+}
+
+#if defined(Q_WS_WINCE) || defined(Q_OS_SYMBIAN)
+#ifdef Q_WS_WINCE_WM
+void QDialogPrivate::_q_doneAction()
+{
+ //Done...
+ QApplication::postEvent(q_func(), new QEvent(QEvent::OkRequest));
+}
+#endif
+
+/*!
+ \reimp
+*/
+bool QDialog::event(QEvent *e)
+{
+ bool result = QWidget::event(e);
+#ifdef Q_WS_WINCE
+ if (e->type() == QEvent::OkRequest) {
+ accept();
+ result = true;
+ }
+#elif defined(Q_WS_S60)
+ if ((e->type() == QEvent::StyleChange) || (e->type() == QEvent::Resize )) {
+ if (!testAttribute(Qt::WA_Moved)) {
+ Qt::WindowStates state = windowState();
+ adjustPosition(parentWidget());
+ setAttribute(Qt::WA_Moved, false); // not really an explicit position
+ if (state != windowState())
+ setWindowState(state);
+ }
+ }
+ // TODO is Symbian, non-S60 behaviour required?
+#endif
+ return result;
+}
+#endif
+
+/*!
+ Returns the modal dialog's result code, \c Accepted or \c Rejected.
+
+ Do not call this function if the dialog was constructed with the
+ Qt::WA_DeleteOnClose attribute.
+*/
+int QDialog::result() const
+{
+ Q_D(const QDialog);
+ return d->rescode;
+}
+
+/*!
+ \fn void QDialog::setResult(int i)
+
+ Sets the modal dialog's result code to \a i.
+
+ \note We recommend that you use one of the values defined by
+ QDialog::DialogCode.
+*/
+void QDialog::setResult(int r)
+{
+ Q_D(QDialog);
+ d->rescode = r;
+}
+
+/*!
+ \since 4.5
+
+ Shows the dialog as a \l{QDialog#Modal Dialogs}{window modal dialog},
+ returning immediately.
+
+ \sa exec(), show(), result(), setWindowModality()
+*/
+void QDialog::open()
+{
+ Q_D(QDialog);
+
+ Qt::WindowModality modality = windowModality();
+ if (modality != Qt::WindowModal) {
+ d->resetModalityTo = modality;
+ d->wasModalitySet = testAttribute(Qt::WA_SetWindowModality);
+ setWindowModality(Qt::WindowModal);
+ setAttribute(Qt::WA_SetWindowModality, false);
+#ifdef Q_WS_MAC
+ setParent(parentWidget(), Qt::Sheet);
+#endif
+ }
+
+ setResult(0);
+ show();
+}
+
+/*!
+ Shows the dialog as a \l{QDialog#Modal Dialogs}{modal dialog},
+ blocking until the user closes it. The function returns a \l
+ DialogCode result.
+
+ If the dialog is \l{Qt::ApplicationModal}{application modal}, users cannot
+ interact with any other window in the same application until they close
+ the dialog. If the dialog is \l{Qt::ApplicationModal}{window modal}, only
+ interaction with the parent window is blocked while the dialog is open.
+ By default, the dialog is application modal.
+
+ \sa open(), show(), result(), setWindowModality()
+*/
+
+int QDialog::exec()
+{
+ Q_D(QDialog);
+
+ if (d->eventLoop) {
+ qWarning("QDialog::exec: Recursive call detected");
+ return -1;
+ }
+
+ bool deleteOnClose = testAttribute(Qt::WA_DeleteOnClose);
+ setAttribute(Qt::WA_DeleteOnClose, false);
+
+ d->resetModalitySetByOpen();
+
+ bool wasShowModal = testAttribute(Qt::WA_ShowModal);
+ setAttribute(Qt::WA_ShowModal, true);
+ setResult(0);
+
+//On Windows Mobile we create an empty menu to hide the current menu
+#ifdef Q_WS_WINCE_WM
+#ifndef QT_NO_MENUBAR
+ QMenuBar *menuBar = 0;
+ if (!findChild<QMenuBar *>())
+ menuBar = new QMenuBar(this);
+ if (qt_wince_is_smartphone()) {
+ QAction *doneAction = new QAction(tr("Done"), this);
+ menuBar->setDefaultAction(doneAction);
+ connect(doneAction, SIGNAL(triggered()), this, SLOT(_q_doneAction()));
+ }
+#endif //QT_NO_MENUBAR
+#endif //Q_WS_WINCE_WM
+
+ bool showSystemDialogFullScreen = false;
+#ifdef Q_OS_SYMBIAN
+ if (qobject_cast<QFileDialog *>(this) || qobject_cast<QFontDialog *>(this) ||
+ qobject_cast<QWizard *>(this)) {
+ showSystemDialogFullScreen = true;
+ }
+#endif // Q_OS_SYMBIAN
+
+ if (showSystemDialogFullScreen) {
+ setWindowFlags(windowFlags() | Qt::WindowSoftkeysVisibleHint);
+ setWindowState(Qt::WindowFullScreen);
+ }
+ show();
+
+#ifdef Q_WS_MAC
+ d->mac_nativeDialogModalHelp();
+#endif
+
+ QEventLoop eventLoop;
+ d->eventLoop = &eventLoop;
+ QPointer<QDialog> guard = this;
+ (void) eventLoop.exec(QEventLoop::DialogExec);
+ if (guard.isNull())
+ return QDialog::Rejected;
+ d->eventLoop = 0;
+
+ setAttribute(Qt::WA_ShowModal, wasShowModal);
+
+ int res = result();
+ if (deleteOnClose)
+ delete this;
+#ifdef Q_WS_WINCE_WM
+#ifndef QT_NO_MENUBAR
+ else if (menuBar)
+ delete menuBar;
+#endif //QT_NO_MENUBAR
+#endif //Q_WS_WINCE_WM
+ return res;
+}
+
+
+/*!
+ Closes the dialog and sets its result code to \a r. If this dialog
+ is shown with exec(), done() causes the local event loop to finish,
+ and exec() to return \a r.
+
+ As with QWidget::close(), done() deletes the dialog if the
+ Qt::WA_DeleteOnClose flag is set. If the dialog is the application's
+ main widget, the application terminates. If the dialog is the
+ last window closed, the QApplication::lastWindowClosed() signal is
+ emitted.
+
+ \sa accept(), reject(), QApplication::activeWindow(), QApplication::quit()
+*/
+
+void QDialog::done(int r)
+{
+ Q_D(QDialog);
+ hide();
+ setResult(r);
+
+ d->close_helper(QWidgetPrivate::CloseNoEvent);
+ d->resetModalitySetByOpen();
+
+ emit finished(r);
+ if (r == Accepted)
+ emit accepted();
+ else if (r == Rejected)
+ emit rejected();
+}
+
+/*!
+ Hides the modal dialog and sets the result code to \c Accepted.
+
+ \sa reject() done()
+*/
+
+void QDialog::accept()
+{
+ done(Accepted);
+}
+
+/*!
+ Hides the modal dialog and sets the result code to \c Rejected.
+
+ \sa accept() done()
+*/
+
+void QDialog::reject()
+{
+ done(Rejected);
+}
+
+/*! \reimp */
+bool QDialog::eventFilter(QObject *o, QEvent *e)
+{
+ return QWidget::eventFilter(o, e);
+}
+
+/*****************************************************************************
+ Event handlers
+ *****************************************************************************/
+
+#ifndef QT_NO_CONTEXTMENU
+/*! \reimp */
+void QDialog::contextMenuEvent(QContextMenuEvent *e)
+{
+#if defined(QT_NO_WHATSTHIS) || defined(QT_NO_MENU)
+ Q_UNUSED(e);
+#else
+ QWidget *w = childAt(e->pos());
+ if (!w) {
+ w = rect().contains(e->pos()) ? this : 0;
+ if (!w)
+ return;
+ }
+ while (w && w->whatsThis().size() == 0 && !w->testAttribute(Qt::WA_CustomWhatsThis))
+ w = w->isWindow() ? 0 : w->parentWidget();
+ if (w) {
+ 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
+}
+#endif // QT_NO_CONTEXTMENU
+
+/*! \reimp */
+void QDialog::keyPressEvent(QKeyEvent *e)
+{
+ // Calls reject() if Escape is pressed. Simulates a button
+ // click for the default button if Enter is pressed. Move focus
+ // for the arrow keys. Ignore the rest.
+#ifdef Q_WS_MAC
+ if(e->modifiers() == Qt::ControlModifier && e->key() == Qt::Key_Period) {
+ reject();
+ } else
+#endif
+ if (!e->modifiers() || (e->modifiers() & Qt::KeypadModifier && e->key() == Qt::Key_Enter)) {
+ switch (e->key()) {
+ case Qt::Key_Enter:
+ case Qt::Key_Return: {
+ QList<QPushButton*> list = findChildren<QPushButton*>();
+ for (int i=0; i<list.size(); ++i) {
+ QPushButton *pb = list.at(i);
+ if (pb->isDefault() && pb->isVisible()) {
+ if (pb->isEnabled())
+ pb->click();
+ return;
+ }
+ }
+ }
+ break;
+ case Qt::Key_Escape:
+ reject();
+ break;
+ default:
+ e->ignore();
+ return;
+ }
+ } else {
+ e->ignore();
+ }
+}
+
+/*! \reimp */
+void QDialog::closeEvent(QCloseEvent *e)
+{
+#ifndef QT_NO_WHATSTHIS
+ if (isModal() && QWhatsThis::inWhatsThisMode())
+ QWhatsThis::leaveWhatsThisMode();
+#endif
+ if (isVisible()) {
+ QPointer<QObject> that = this;
+ reject();
+ if (that && isVisible())
+ e->ignore();
+ } else {
+ e->accept();
+ }
+}
+
+/*****************************************************************************
+ Geometry management.
+ *****************************************************************************/
+
+/*! \reimp
+*/
+
+void QDialog::setVisible(bool visible)
+{
+ Q_D(QDialog);
+ if (visible) {
+ if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden))
+ return;
+
+ if (!testAttribute(Qt::WA_Moved)) {
+ Qt::WindowStates state = windowState();
+ adjustPosition(parentWidget());
+ setAttribute(Qt::WA_Moved, false); // not really an explicit position
+ if (state != windowState())
+ setWindowState(state);
+ }
+ QWidget::setVisible(visible);
+ showExtension(d->doShowExtension);
+ QWidget *fw = window()->focusWidget();
+ if (!fw)
+ fw = this;
+
+ /*
+ The following block is to handle a special case, and does not
+ really follow propper logic in concern of autoDefault and TAB
+ order. However, it's here to ease usage for the users. If a
+ dialog has a default QPushButton, and first widget in the TAB
+ order also is a QPushButton, then we give focus to the main
+ default QPushButton. This simplifies code for the developers,
+ and actually catches most cases... If not, then they simply
+ have to use [widget*]->setFocus() themselves...
+ */
+ if (d->mainDef && fw->focusPolicy() == Qt::NoFocus) {
+ QWidget *first = fw;
+ while ((first = first->nextInFocusChain()) != fw && first->focusPolicy() == Qt::NoFocus)
+ ;
+ if (first != d->mainDef && qobject_cast<QPushButton*>(first))
+ d->mainDef->setFocus();
+ }
+ if (!d->mainDef && isWindow()) {
+ QWidget *w = fw;
+ while ((w = w->nextInFocusChain()) != fw) {
+ QPushButton *pb = qobject_cast<QPushButton *>(w);
+ if (pb && pb->autoDefault() && pb->focusPolicy() != Qt::NoFocus) {
+ pb->setDefault(true);
+ break;
+ }
+ }
+ }
+ if (fw && !fw->hasFocus()) {
+ QFocusEvent e(QEvent::FocusIn, Qt::TabFocusReason);
+ QApplication::sendEvent(fw, &e);
+ }
+
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::updateAccessibility(this, 0, QAccessible::DialogStart);
+#endif
+
+ } else {
+ if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden))
+ return;
+
+#ifndef QT_NO_ACCESSIBILITY
+ if (isVisible())
+ QAccessible::updateAccessibility(this, 0, QAccessible::DialogEnd);
+#endif
+
+ // Reimplemented to exit a modal event loop when the dialog is hidden.
+ QWidget::setVisible(visible);
+ if (d->eventLoop)
+ d->eventLoop->exit();
+ }
+#ifdef Q_WS_WIN
+ if (d->mainDef && isActiveWindow()) {
+ BOOL snapToDefault = false;
+ if (SystemParametersInfo(SPI_GETSNAPTODEFBUTTON, 0, &snapToDefault, 0)) {
+ if (snapToDefault)
+ QCursor::setPos(d->mainDef->mapToGlobal(d->mainDef->rect().center()));
+ }
+ }
+#endif
+}
+
+/*!\reimp */
+void QDialog::showEvent(QShowEvent *event)
+{
+ if (!event->spontaneous() && !testAttribute(Qt::WA_Moved)) {
+ Qt::WindowStates state = windowState();
+ adjustPosition(parentWidget());
+ setAttribute(Qt::WA_Moved, false); // not really an explicit position
+ if (state != windowState())
+ setWindowState(state);
+ }
+}
+
+/*! \internal */
+void QDialog::adjustPosition(QWidget* w)
+{
+#ifdef Q_WS_X11
+ // if the WM advertises that it will place the windows properly for us, let it do it :)
+ if (X11->isSupportedByWM(ATOM(_NET_WM_FULL_PLACEMENT)))
+ return;
+#endif
+
+#ifdef Q_OS_SYMBIAN
+ if (symbianAdjustedPosition())
+ //dialog has already been positioned
+ return;
+#endif
+
+ QPoint p(0, 0);
+ int extraw = 0, extrah = 0, scrn = 0;
+ if (w)
+ w = w->window();
+ QRect desk;
+ if (w) {
+ scrn = QApplication::desktop()->screenNumber(w);
+ } else if (QApplication::desktop()->isVirtualDesktop()) {
+ scrn = QApplication::desktop()->screenNumber(QCursor::pos());
+ } else {
+ scrn = QApplication::desktop()->screenNumber(this);
+ }
+ desk = QApplication::desktop()->availableGeometry(scrn);
+
+ QWidgetList list = QApplication::topLevelWidgets();
+ for (int i = 0; (extraw == 0 || extrah == 0) && i < list.size(); ++i) {
+ QWidget * current = list.at(i);
+ if (current->isVisible()) {
+ int framew = current->geometry().x() - current->x();
+ int frameh = current->geometry().y() - current->y();
+
+ extraw = qMax(extraw, framew);
+ extrah = qMax(extrah, frameh);
+ }
+ }
+
+ // sanity check for decoration frames. With embedding, we
+ // might get extraordinary values
+ if (extraw == 0 || extrah == 0 || extraw >= 10 || extrah >= 40) {
+ extrah = 40;
+ extraw = 10;
+ }
+
+
+ if (w) {
+ // Use mapToGlobal rather than geometry() in case w might
+ // be embedded in another application
+ QPoint pp = w->mapToGlobal(QPoint(0,0));
+ p = QPoint(pp.x() + w->width()/2,
+ pp.y() + w->height()/ 2);
+ } else {
+ // p = middle of the desktop
+ p = QPoint(desk.x() + desk.width()/2, desk.y() + desk.height()/2);
+ }
+
+ // p = origin of this
+ p = QPoint(p.x()-width()/2 - extraw,
+ p.y()-height()/2 - extrah);
+
+
+ if (p.x() + extraw + width() > desk.x() + desk.width())
+ p.setX(desk.x() + desk.width() - width() - extraw);
+ if (p.x() < desk.x())
+ p.setX(desk.x());
+
+ if (p.y() + extrah + height() > desk.y() + desk.height())
+ p.setY(desk.y() + desk.height() - height() - extrah);
+ if (p.y() < desk.y())
+ p.setY(desk.y());
+
+ move(p);
+}
+
+#if defined(Q_OS_SYMBIAN)
+/*! \internal */
+bool QDialog::symbianAdjustedPosition()
+{
+#if defined(Q_WS_S60)
+ QPoint p;
+ QPoint oldPos = pos();
+ if (isFullScreen()) {
+ p.setX(0);
+ p.setY(0);
+ } else if (isMaximized()) {
+ TRect statusPaneRect = TRect();
+ if (S60->screenHeightInPixels > S60->screenWidthInPixels) {
+ AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EStatusPane, statusPaneRect);
+ } else {
+ AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EStaconTop, statusPaneRect);
+ }
+
+ p.setX(0);
+ p.setY(statusPaneRect.Height());
+ } else {
+ // naive way to deduce screen orientation
+ if (S60->screenHeightInPixels > S60->screenWidthInPixels) {
+ int cbaHeight;
+ TRect rect;
+ AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EControlPane, rect);
+ cbaHeight = rect.Height();
+ p.setY(S60->screenHeightInPixels - height() - cbaHeight);
+ p.setX(0);
+ } else {
+ const int scrollbarWidth = style()->pixelMetric(QStyle::PM_ScrollBarExtent);
+ TRect staConTopRect = TRect();
+ AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EStaconTop, staConTopRect);
+ if (staConTopRect.IsEmpty()) {
+ TRect cbaRect = TRect();
+ AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EControlPane, cbaRect);
+ AknLayoutUtils::TAknCbaLocation cbaLocation = AknLayoutUtils::CbaLocation();
+ switch (cbaLocation) {
+ case AknLayoutUtils::EAknCbaLocationBottom:
+ p.setY(S60->screenHeightInPixels - height() - cbaRect.Height());
+ p.setX((S60->screenWidthInPixels - width()) >> 1);
+ break;
+ case AknLayoutUtils::EAknCbaLocationRight:
+ p.setY((S60->screenHeightInPixels - height()) >> 1);
+ p.setX(qMax(0,S60->screenWidthInPixels - width() - scrollbarWidth - cbaRect.Width()));
+ break;
+ case AknLayoutUtils::EAknCbaLocationLeft:
+ p.setY((S60->screenHeightInPixels - height()) >> 1);
+ p.setX(qMax(0,scrollbarWidth + cbaRect.Width()));
+ break;
+ }
+ } else {
+ p.setY((S60->screenHeightInPixels - height()) >> 1);
+ p.setX(qMax(0,S60->screenWidthInPixels - width()));
+ }
+ }
+ }
+ if (oldPos != p || p.y() < 0)
+ move(p);
+ return true;
+#else
+ // TODO - check positioning requirement for Symbian, non-s60
+ return false;
+#endif
+}
+#endif
+
+/*!
+ \obsolete
+
+ If \a orientation is Qt::Horizontal, the extension will be displayed
+ to the right of the dialog's main area. If \a orientation is
+ Qt::Vertical, the extension will be displayed below the dialog's main
+ area.
+
+ Instead of using this functionality, we recommend that you simply call
+ show() or hide() on the part of the dialog that you want to use as an
+ extension. See the \l{Extension Example} for details.
+
+ \sa setExtension()
+*/
+void QDialog::setOrientation(Qt::Orientation orientation)
+{
+ Q_D(QDialog);
+ d->orientation = orientation;
+}
+
+/*!
+ \obsolete
+
+ Returns the dialog's extension orientation.
+
+ Instead of using this functionality, we recommend that you simply call
+ show() or hide() on the part of the dialog that you want to use as an
+ extension. See the \l{Extension Example} for details.
+
+ \sa extension()
+*/
+Qt::Orientation QDialog::orientation() const
+{
+ Q_D(const QDialog);
+ return d->orientation;
+}
+
+/*!
+ \obsolete
+
+ Sets the widget, \a extension, to be the dialog's extension,
+ deleting any previous extension. The dialog takes ownership of the
+ extension. Note that if 0 is passed any existing extension will be
+ deleted. This function must only be called while the dialog is hidden.
+
+ Instead of using this functionality, we recommend that you simply call
+ show() or hide() on the part of the dialog that you want to use as an
+ extension. See the \l{Extension Example} for details.
+
+ \sa showExtension(), setOrientation()
+*/
+void QDialog::setExtension(QWidget* extension)
+{
+ Q_D(QDialog);
+ delete d->extension;
+ d->extension = extension;
+
+ if (!extension)
+ return;
+
+ if (extension->parentWidget() != this)
+ extension->setParent(this);
+ extension->hide();
+}
+
+/*!
+ \obsolete
+
+ Returns the dialog's extension or 0 if no extension has been
+ defined.
+
+ Instead of using this functionality, we recommend that you simply call
+ show() or hide() on the part of the dialog that you want to use as an
+ extension. See the \l{Extension Example} for details.
+
+ \sa showExtension(), setOrientation()
+*/
+QWidget* QDialog::extension() const
+{
+ Q_D(const QDialog);
+ return d->extension;
+}
+
+
+/*!
+ \obsolete
+
+ If \a showIt is true, the dialog's extension is shown; otherwise the
+ extension is hidden.
+
+ Instead of using this functionality, we recommend that you simply call
+ show() or hide() on the part of the dialog that you want to use as an
+ extension. See the \l{Extension Example} for details.
+
+ \sa show(), setExtension(), setOrientation()
+*/
+void QDialog::showExtension(bool showIt)
+{
+ Q_D(QDialog);
+ d->doShowExtension = showIt;
+ if (!d->extension)
+ return;
+ if (!testAttribute(Qt::WA_WState_Visible))
+ return;
+ if (d->extension->isVisible() == showIt)
+ return;
+
+ if (showIt) {
+ d->size = size();
+ d->min = minimumSize();
+ d->max = maximumSize();
+ if (layout())
+ layout()->setEnabled(false);
+ QSize s(d->extension->sizeHint()
+ .expandedTo(d->extension->minimumSize())
+ .boundedTo(d->extension->maximumSize()));
+ if (d->orientation == Qt::Horizontal) {
+ int h = qMax(height(), s.height());
+ d->extension->setGeometry(width(), 0, s.width(), h);
+ setFixedSize(width() + s.width(), h);
+ } else {
+ int w = qMax(width(), s.width());
+ d->extension->setGeometry(0, height(), w, s.height());
+ setFixedSize(w, height() + s.height());
+ }
+ d->extension->show();
+#ifndef QT_NO_SIZEGRIP
+ const bool sizeGripEnabled = isSizeGripEnabled();
+ setSizeGripEnabled(false);
+ d->sizeGripEnabled = sizeGripEnabled;
+#endif
+ } else {
+ d->extension->hide();
+ // workaround for CDE window manager that won't shrink with (-1,-1)
+ setMinimumSize(d->min.expandedTo(QSize(1, 1)));
+ setMaximumSize(d->max);
+ resize(d->size);
+ if (layout())
+ layout()->setEnabled(true);
+#ifndef QT_NO_SIZEGRIP
+ setSizeGripEnabled(d->sizeGripEnabled);
+#endif
+ }
+}
+
+
+/*! \reimp */
+QSize QDialog::sizeHint() const
+{
+ Q_D(const QDialog);
+ if (d->extension) {
+ if (d->orientation == Qt::Horizontal)
+ return QSize(QWidget::sizeHint().width(),
+ qMax(QWidget::sizeHint().height(),d->extension->sizeHint().height()));
+ else
+ return QSize(qMax(QWidget::sizeHint().width(), d->extension->sizeHint().width()),
+ QWidget::sizeHint().height());
+ }
+#if defined(Q_WS_S60)
+ // if size is not fixed, try to adjust it according to S60 layoutting
+ if (minimumSize() != maximumSize()) {
+ // In S60, dialogs are always the width of screen (in portrait, regardless of current layout)
+ return QSize(qMin(S60->screenHeightInPixels, S60->screenWidthInPixels), QWidget::sizeHint().height());
+ } else {
+ return QWidget::sizeHint();
+ }
+#else
+ return QWidget::sizeHint();
+#endif //Q_WS_S60
+}
+
+
+/*! \reimp */
+QSize QDialog::minimumSizeHint() const
+{
+ Q_D(const QDialog);
+ if (d->extension) {
+ if (d->orientation == Qt::Horizontal)
+ return QSize(QWidget::minimumSizeHint().width(),
+ qMax(QWidget::minimumSizeHint().height(), d->extension->minimumSizeHint().height()));
+ else
+ return QSize(qMax(QWidget::minimumSizeHint().width(), d->extension->minimumSizeHint().width()),
+ QWidget::minimumSizeHint().height());
+ }
+
+ return QWidget::minimumSizeHint();
+}
+
+/*!
+ \property QDialog::modal
+ \brief whether show() should pop up the dialog as modal or modeless
+
+ By default, this property is false and show() pops up the dialog
+ as modeless. Setting his property to true is equivalent to setting
+ QWidget::windowModality to Qt::ApplicationModal.
+
+ exec() ignores the value of this property and always pops up the
+ dialog as modal.
+
+ \sa QWidget::windowModality, show(), exec()
+*/
+
+void QDialog::setModal(bool modal)
+{
+ setAttribute(Qt::WA_ShowModal, modal);
+}
+
+
+bool QDialog::isSizeGripEnabled() const
+{
+#ifndef QT_NO_SIZEGRIP
+ Q_D(const QDialog);
+ return !!d->resizer;
+#else
+ return false;
+#endif
+}
+
+
+void QDialog::setSizeGripEnabled(bool enabled)
+{
+#ifdef QT_NO_SIZEGRIP
+ Q_UNUSED(enabled);
+#else
+ Q_D(QDialog);
+#ifndef QT_NO_SIZEGRIP
+ d->sizeGripEnabled = enabled;
+ if (enabled && d->doShowExtension)
+ return;
+#endif
+ if (!enabled != !d->resizer) {
+ if (enabled) {
+ d->resizer = new QSizeGrip(this);
+ // adjustSize() processes all events, which is suboptimal
+ d->resizer->resize(d->resizer->sizeHint());
+ if (isRightToLeft())
+ d->resizer->move(rect().bottomLeft() -d->resizer->rect().bottomLeft());
+ else
+ d->resizer->move(rect().bottomRight() -d->resizer->rect().bottomRight());
+ d->resizer->raise();
+ d->resizer->show();
+ } else {
+ delete d->resizer;
+ d->resizer = 0;
+ }
+ }
+#endif //QT_NO_SIZEGRIP
+}
+
+
+
+/*! \reimp */
+void QDialog::resizeEvent(QResizeEvent *)
+{
+#ifndef QT_NO_SIZEGRIP
+ Q_D(QDialog);
+ if (d->resizer) {
+ if (isRightToLeft())
+ d->resizer->move(rect().bottomLeft() -d->resizer->rect().bottomLeft());
+ else
+ d->resizer->move(rect().bottomRight() -d->resizer->rect().bottomRight());
+ d->resizer->raise();
+ }
+#endif
+}
+
+/*! \fn void QDialog::finished(int result)
+ \since 4.1
+
+ This signal is emitted when the dialog's \a result code has been
+ set, either by the user or by calling done(), accept(), or
+ reject().
+
+ Note that this signal is \e not emitted when hiding the dialog
+ with hide() or setVisible(false). This includes deleting the
+ dialog while it is visible.
+
+ \sa accepted(), rejected()
+*/
+
+/*! \fn void QDialog::accepted()
+ \since 4.1
+
+ This signal is emitted when the dialog has been accepted either by
+ the user or by calling accept() or done() with the
+ QDialog::Accepted argument.
+
+ Note that this signal is \e not emitted when hiding the dialog
+ with hide() or setVisible(false). This includes deleting the
+ dialog while it is visible.
+
+ \sa finished(), rejected()
+*/
+
+/*! \fn void QDialog::rejected()
+ \since 4.1
+
+ This signal is emitted when the dialog has been rejected either by
+ the user or by calling reject() or done() with the
+ QDialog::Rejected argument.
+
+ Note that this signal is \e not emitted when hiding the dialog
+ with hide() or setVisible(false). This includes deleting the
+ dialog while it is visible.
+
+ \sa finished(), accepted()
+*/
+
+QT_END_NAMESPACE
+#include "moc_qdialog.cpp"
diff --git a/src/widgets/dialogs/qdialog.h b/src/widgets/dialogs/qdialog.h
new file mode 100644
index 0000000000..ee23b7bf87
--- /dev/null
+++ b/src/widgets/dialogs/qdialog.h
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDIALOG_H
+#define QDIALOG_H
+
+#include <QtGui/qwidget.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QPushButton;
+class QDialogPrivate;
+
+class Q_GUI_EXPORT QDialog : public QWidget
+{
+ Q_OBJECT
+ friend class QPushButton;
+
+ Q_PROPERTY(bool sizeGripEnabled READ isSizeGripEnabled WRITE setSizeGripEnabled)
+ Q_PROPERTY(bool modal READ isModal WRITE setModal)
+
+public:
+ explicit QDialog(QWidget *parent = 0, Qt::WindowFlags f = 0);
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QDialog(QWidget *parent, const char *name, bool modal = false,
+ Qt::WindowFlags f = 0);
+#endif
+ ~QDialog();
+
+ enum DialogCode { Rejected, Accepted };
+
+ int result() const;
+
+ void setVisible(bool visible);
+
+ void setOrientation(Qt::Orientation orientation);
+ Qt::Orientation orientation() const;
+
+ void setExtension(QWidget* extension);
+ QWidget* extension() const;
+
+ QSize sizeHint() const;
+ QSize minimumSizeHint() const;
+
+ void setSizeGripEnabled(bool);
+ bool isSizeGripEnabled() const;
+
+ void setModal(bool modal);
+ void setResult(int r);
+
+Q_SIGNALS:
+ void finished(int result);
+ void accepted();
+ void rejected();
+
+public Q_SLOTS:
+ void open();
+ int exec();
+ virtual void done(int);
+ virtual void accept();
+ virtual void reject();
+
+ void showExtension(bool);
+
+protected:
+ QDialog(QDialogPrivate &, QWidget *parent, Qt::WindowFlags f = 0);
+
+#if defined(Q_WS_WINCE) || defined(Q_OS_SYMBIAN)
+ bool event(QEvent *e);
+#endif
+ void keyPressEvent(QKeyEvent *);
+ void closeEvent(QCloseEvent *);
+ void showEvent(QShowEvent *);
+ void resizeEvent(QResizeEvent *);
+#ifndef QT_NO_CONTEXTMENU
+ void contextMenuEvent(QContextMenuEvent *);
+#endif
+ bool eventFilter(QObject *, QEvent *);
+ void adjustPosition(QWidget*);
+private:
+ Q_DECLARE_PRIVATE(QDialog)
+ Q_DISABLE_COPY(QDialog)
+
+#if defined(Q_OS_SYMBIAN)
+ bool symbianAdjustedPosition();
+#endif
+
+
+#ifdef Q_WS_WINCE_WM
+ Q_PRIVATE_SLOT(d_func(), void _q_doneAction())
+#endif
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDIALOG_H
diff --git a/src/widgets/dialogs/qdialog_p.h b/src/widgets/dialogs/qdialog_p.h
new file mode 100644
index 0000000000..a2a948e951
--- /dev/null
+++ b/src/widgets/dialogs/qdialog_p.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDIALOG_P_H
+#define QDIALOG_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qwidget_p.h"
+#include "QtCore/qeventloop.h"
+#include "QtCore/qpointer.h"
+#include "QtGui/qdialog.h"
+#include "QtGui/qpushbutton.h"
+
+QT_BEGIN_NAMESPACE
+
+class QSizeGrip;
+
+class QDialogPrivate : public QWidgetPrivate
+{
+ Q_DECLARE_PUBLIC(QDialog)
+public:
+
+ QDialogPrivate()
+ : mainDef(0), orientation(Qt::Horizontal),extension(0), doShowExtension(false),
+#ifndef QT_NO_SIZEGRIP
+ resizer(0),
+ sizeGripEnabled(false),
+#endif
+ rescode(0), resetModalityTo(-1), wasModalitySet(true), eventLoop(0)
+ {}
+
+ QPointer<QPushButton> mainDef;
+ Qt::Orientation orientation;
+ QWidget *extension;
+ bool doShowExtension;
+ QSize size, min, max;
+#ifndef QT_NO_SIZEGRIP
+ QSizeGrip *resizer;
+ bool sizeGripEnabled;
+#endif
+ QPoint lastRMBPress;
+
+ void setDefault(QPushButton *);
+ void setMainDefault(QPushButton *);
+ void hideDefault();
+ void resetModalitySetByOpen();
+
+#ifdef Q_WS_WINCE_WM
+ void _q_doneAction();
+#endif
+
+#ifdef Q_WS_MAC
+ virtual void mac_nativeDialogModalHelp() {}
+#endif
+
+ int rescode;
+ int resetModalityTo;
+ bool wasModalitySet;
+
+ QPointer<QEventLoop> eventLoop;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDIALOG_P_H
diff --git a/src/widgets/dialogs/qdialogsbinarycompat_win.cpp b/src/widgets/dialogs/qdialogsbinarycompat_win.cpp
new file mode 100644
index 0000000000..beec2cd29c
--- /dev/null
+++ b/src/widgets/dialogs/qdialogsbinarycompat_win.cpp
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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 <qglobal.h>
+
+// ### Qt 5: eliminate this file
+
+/*
+ This is evil. MSVC doesn't let us remove private symbols, nor change their
+ visibility; yet there are some symbols we really needed to make public, e.g.,
+ ~QColorDialog(), and then there were some totally needless symbols in our
+ header files, e.g., setSelectedAlpha(). So we define a new version of
+ QColorDialog & Co. with only the private symbols that we removed from the
+ public header files. The friends are there only to prevent potential compiler
+ warnings.
+
+ It would have been nicer to export the missing symbols as mangled "C" symbols
+ instead but unfortunately MSVC uses out-of-reach characters like @ and . in
+ their mangled C++ symbols.
+*/
+
+#if QT_VERSION < 0x050000 && defined(Q_CC_MSVC)
+
+QT_BEGIN_NAMESPACE
+
+#include <QtGui/QColor>
+#include <QtGui/QFont>
+
+class QColorDialogPrivate;
+class QFontDialogPrivate;
+class QInputDialogPrivate;
+class QWidget;
+
+class Q_GUI_EXPORT QColorDialog
+{
+private:
+ explicit QColorDialog(QWidget *, bool);
+ ~QColorDialog();
+
+ void setColor(const QColor &);
+ QColor color() const;
+ bool selectColor(const QColor &);
+ void setSelectedAlpha(int);
+ int selectedAlpha() const;
+
+ friend class QColorDialogPrivate;
+};
+
+QColorDialog::QColorDialog(QWidget *, bool) {}
+QColorDialog::~QColorDialog() {}
+void QColorDialog::setColor(const QColor &) {}
+QColor QColorDialog::color() const { return QColor(); }
+bool QColorDialog::selectColor(const QColor &) { return false; }
+void QColorDialog::setSelectedAlpha(int) {}
+int QColorDialog::selectedAlpha() const { return 0; }
+
+class Q_GUI_EXPORT QFontDialog
+{
+private:
+ explicit QFontDialog(QWidget *, bool, Qt::WindowFlags);
+ ~QFontDialog();
+
+ QFont font() const;
+ void setFont(const QFont &);
+ void updateFamilies();
+ void updateStyles();
+ void updateSizes();
+
+ static QFont getFont(bool *, const QFont *, QWidget *);
+
+ friend class QFontDialogPrivate;
+};
+
+QFontDialog::QFontDialog(QWidget *, bool, Qt::WindowFlags) {}
+QFontDialog::~QFontDialog() {}
+QFont QFontDialog::font() const { return QFont(); }
+void QFontDialog::setFont(const QFont &) { }
+void QFontDialog::updateFamilies() {}
+void QFontDialog::updateStyles() {}
+void QFontDialog::updateSizes() {}
+QFont QFontDialog::getFont(bool *, const QFont *, QWidget *) { return QFont(); }
+
+class Q_GUI_EXPORT QInputDialog
+{
+private:
+ enum Type { LineEdit, SpinBox, DoubleSpinBox, ComboBox, EditableComboBox };
+
+ QInputDialog(const QString &, QWidget *, Type, Qt::WindowFlags);
+ QInputDialog(const QString &, const QString &, QWidget *, QWidget *, Qt::WindowFlags);
+ ~QInputDialog();
+};
+
+QInputDialog::QInputDialog(const QString &, QWidget *, Type, Qt::WindowFlags) {}
+QInputDialog::QInputDialog(const QString &, const QString &, QWidget *, QWidget *, Qt::WindowFlags) {}
+QInputDialog::~QInputDialog() {}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/widgets/dialogs/qerrormessage.cpp b/src/widgets/dialogs/qerrormessage.cpp
new file mode 100644
index 0000000000..6d474cc4f9
--- /dev/null
+++ b/src/widgets/dialogs/qerrormessage.cpp
@@ -0,0 +1,429 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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 "qerrormessage.h"
+
+#ifndef QT_NO_ERRORMESSAGE
+
+#include "qapplication.h"
+#include "qcheckbox.h"
+#include "qlabel.h"
+#include "qlayout.h"
+#include "qmessagebox.h"
+#include "qpushbutton.h"
+#include "qstringlist.h"
+#include "qtextedit.h"
+#include "qdialog_p.h"
+#include "qpixmap.h"
+#include "qmetaobject.h"
+#include "qthread.h"
+#include "qqueue.h"
+#include "qset.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef Q_WS_WINCE
+extern bool qt_wince_is_mobile(); //defined in qguifunctions_wince.cpp
+extern bool qt_wince_is_high_dpi(); //defined in qguifunctions_wince.cpp
+
+#include "qguifunctions_wince.h"
+#endif
+
+#if defined(QT_SOFTKEYS_ENABLED)
+#include <qaction.h>
+#endif
+#ifdef Q_WS_S60
+#include "private/qt_s60_p.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QErrorMessagePrivate : public QDialogPrivate
+{
+ Q_DECLARE_PUBLIC(QErrorMessage)
+public:
+ QPushButton * ok;
+ QCheckBox * again;
+ QTextEdit * errors;
+ QLabel * icon;
+#ifdef QT_SOFTKEYS_ENABLED
+ QAction *okAction;
+#endif
+ QQueue<QPair<QString, QString> > pending;
+ QSet<QString> doNotShow;
+ QSet<QString> doNotShowType;
+ QString currentMessage;
+ QString currentType;
+
+ bool nextPending();
+ void retranslateStrings();
+};
+
+class QErrorMessageTextView : public QTextEdit
+{
+public:
+ QErrorMessageTextView(QWidget *parent)
+ : QTextEdit(parent) { setReadOnly(true); }
+
+ virtual QSize minimumSizeHint() const;
+ virtual QSize sizeHint() const;
+};
+
+QSize QErrorMessageTextView::minimumSizeHint() const
+{
+#ifdef Q_WS_WINCE
+ if (qt_wince_is_mobile())
+ if (qt_wince_is_high_dpi())
+ return QSize(200, 200);
+ else
+ return QSize(100, 100);
+ else
+ return QSize(70, 70);
+#else
+ return QSize(50, 50);
+#endif
+}
+
+QSize QErrorMessageTextView::sizeHint() const
+{
+#ifdef Q_WS_WINCE
+ if (qt_wince_is_mobile())
+ if (qt_wince_is_high_dpi())
+ return QSize(400, 200);
+ else
+ return QSize(320, 120);
+ else
+ return QSize(300, 100);
+#else
+
+#ifdef Q_WS_S60
+ const int smallerDimension = qMin(S60->screenHeightInPixels, S60->screenWidthInPixels);
+ // In S60 layout data, error messages seem to be one third of the screen height (in portrait) minus two.
+ return QSize(smallerDimension, smallerDimension/3-2);
+#else
+ return QSize(250, 75);
+#endif //Q_WS_S60
+#endif //Q_WS_WINCE
+}
+
+/*!
+ \class QErrorMessage
+
+ \brief The QErrorMessage class provides an error message display dialog.
+
+ \ingroup standard-dialog
+
+ An error message widget consists of a text label and a checkbox. The
+ checkbox lets the user control whether the same error message will be
+ displayed again in the future, typically displaying the text,
+ "Show this message again" translated into the appropriate local
+ language.
+
+ For production applications, the class can be used to display messages which
+ the user only needs to see once. To use QErrorMessage like this, you create
+ the dialog in the usual way, and show it by calling the showMessage() slot or
+ connecting signals to it.
+
+ The static qtHandler() function installs a message handler
+ using qInstallMsgHandler() and creates a QErrorMessage that displays
+ qDebug(), qWarning() and qFatal() messages. This is most useful in
+ environments where no console is available to display warnings and
+ error messages.
+
+ In both cases QErrorMessage will queue pending messages and display
+ them in order, with each new message being shown as soon as the user
+ has accepted the previous message. Once the user has specified that a
+ message is not to be shown again it is automatically skipped, and the
+ dialog will show the next appropriate message in the queue.
+
+ The \l{dialogs/standarddialogs}{Standard Dialogs} example shows
+ how to use QErrorMessage as well as other built-in Qt dialogs.
+
+ \img qerrormessage.png
+
+ \sa QMessageBox, QStatusBar::showMessage(), {Standard Dialogs Example}
+*/
+
+static QErrorMessage * qtMessageHandler = 0;
+
+static void deleteStaticcQErrorMessage() // post-routine
+{
+ if (qtMessageHandler) {
+ delete qtMessageHandler;
+ qtMessageHandler = 0;
+ }
+}
+
+static bool metFatal = false;
+
+static void jump(QtMsgType t, const char * m)
+{
+ if (!qtMessageHandler)
+ return;
+
+ QString rich;
+
+ switch (t) {
+ case QtDebugMsg:
+ default:
+ rich = QErrorMessage::tr("Debug Message:");
+ break;
+ case QtWarningMsg:
+ rich = QErrorMessage::tr("Warning:");
+ break;
+ case QtFatalMsg:
+ rich = QErrorMessage::tr("Fatal Error:");
+ }
+ rich = QString::fromLatin1("<p><b>%1</b></p>").arg(rich);
+ rich += Qt::convertFromPlainText(QLatin1String(m), Qt::WhiteSpaceNormal);
+
+ // ### work around text engine quirk
+ if (rich.endsWith(QLatin1String("</p>")))
+ rich.chop(4);
+
+ if (!metFatal) {
+ if (QThread::currentThread() == qApp->thread()) {
+ qtMessageHandler->showMessage(rich);
+ } else {
+ QMetaObject::invokeMethod(qtMessageHandler,
+ "showMessage",
+ Qt::QueuedConnection,
+ Q_ARG(QString, rich));
+ }
+ metFatal = (t == QtFatalMsg);
+ }
+}
+
+
+/*!
+ Constructs and installs an error handler window with the given \a
+ parent.
+*/
+
+QErrorMessage::QErrorMessage(QWidget * parent)
+ : QDialog(*new QErrorMessagePrivate, parent)
+{
+ Q_D(QErrorMessage);
+ QGridLayout * grid = new QGridLayout(this);
+ d->icon = new QLabel(this);
+#ifndef QT_NO_MESSAGEBOX
+ d->icon->setPixmap(QMessageBox::standardIcon(QMessageBox::Information));
+ d->icon->setAlignment(Qt::AlignHCenter | Qt::AlignTop);
+#endif
+ grid->addWidget(d->icon, 0, 0, Qt::AlignTop);
+ d->errors = new QErrorMessageTextView(this);
+ grid->addWidget(d->errors, 0, 1);
+ d->again = new QCheckBox(this);
+ d->again->setChecked(true);
+ grid->addWidget(d->again, 1, 1, Qt::AlignTop);
+ d->ok = new QPushButton(this);
+#ifdef QT_SOFTKEYS_ENABLED
+ d->okAction = new QAction(d->ok);
+ d->okAction->setSoftKeyRole(QAction::PositiveSoftKey);
+ connect(d->okAction, SIGNAL(triggered()), this, SLOT(accept()));
+ addAction(d->okAction);
+#endif
+
+
+#if defined(Q_WS_WINCE) || defined(Q_WS_S60)
+ d->ok->setFixedSize(0,0);
+#endif
+ connect(d->ok, SIGNAL(clicked()), this, SLOT(accept()));
+ d->ok->setFocus();
+ grid->addWidget(d->ok, 2, 0, 1, 2, Qt::AlignCenter);
+ grid->setColumnStretch(1, 42);
+ grid->setRowStretch(0, 42);
+ d->retranslateStrings();
+}
+
+
+/*!
+ Destroys the error message dialog.
+*/
+
+QErrorMessage::~QErrorMessage()
+{
+ if (this == qtMessageHandler) {
+ qtMessageHandler = 0;
+ QtMsgHandler tmp = qInstallMsgHandler(0);
+ // in case someone else has later stuck in another...
+ if (tmp != jump)
+ qInstallMsgHandler(tmp);
+ }
+}
+
+
+/*! \reimp */
+
+void QErrorMessage::done(int a)
+{
+ Q_D(QErrorMessage);
+ if (!d->again->isChecked() && !d->currentMessage.isEmpty() && d->currentType.isEmpty()) {
+ d->doNotShow.insert(d->currentMessage);
+ }
+ if (!d->again->isChecked() && !d->currentType.isEmpty()) {
+ d->doNotShowType.insert(d->currentType);
+ }
+ d->currentMessage.clear();
+ d->currentType.clear();
+ if (!d->nextPending()) {
+ QDialog::done(a);
+ if (this == qtMessageHandler && metFatal)
+ exit(1);
+ }
+}
+
+
+/*!
+ Returns a pointer to a QErrorMessage object that outputs the
+ default Qt messages. This function creates such an object, if there
+ isn't one already.
+*/
+
+QErrorMessage * QErrorMessage::qtHandler()
+{
+ if (!qtMessageHandler) {
+ qtMessageHandler = new QErrorMessage(0);
+ qAddPostRoutine(deleteStaticcQErrorMessage); // clean up
+ qtMessageHandler->setWindowTitle(QApplication::applicationName());
+ qInstallMsgHandler(jump);
+ }
+ return qtMessageHandler;
+}
+
+
+/*! \internal */
+
+bool QErrorMessagePrivate::nextPending()
+{
+ while (!pending.isEmpty()) {
+ QPair<QString,QString> pendingMessage = pending.dequeue();
+ QString message = pendingMessage.first;
+ QString type = pendingMessage.second;
+ if (!message.isEmpty() && ((type.isEmpty() && !doNotShow.contains(message)) || (!type.isEmpty() && !doNotShowType.contains(type)))) {
+#ifndef QT_NO_TEXTHTMLPARSER
+ errors->setHtml(message);
+#else
+ errors->setPlainText(message);
+#endif
+ currentMessage = message;
+ currentType = type;
+ return true;
+ }
+ }
+ return false;
+}
+
+
+/*!
+ Shows the given message, \a message, and returns immediately. If the user
+ has requested for the message not to be shown again, this function does
+ nothing.
+
+ Normally, the message is displayed immediately. However, if there are
+ pending messages, it will be queued to be displayed later.
+*/
+
+void QErrorMessage::showMessage(const QString &message)
+{
+ Q_D(QErrorMessage);
+ if (d->doNotShow.contains(message))
+ return;
+ d->pending.enqueue(qMakePair(message,QString()));
+ if (!isVisible() && d->nextPending())
+ show();
+}
+
+/*!
+ \since 4.5
+ \overload
+
+ Shows the given message, \a message, and returns immediately. If the user
+ has requested for messages of type, \a type, not to be shown again, this
+ function does nothing.
+
+ Normally, the message is displayed immediately. However, if there are
+ pending messages, it will be queued to be displayed later.
+
+ \sa showMessage()
+*/
+
+void QErrorMessage::showMessage(const QString &message, const QString &type)
+{
+ Q_D(QErrorMessage);
+ if (d->doNotShow.contains(message) && d->doNotShowType.contains(type))
+ return;
+ d->pending.push_back(qMakePair(message,type));
+ if (!isVisible() && d->nextPending())
+ show();
+}
+
+/*!
+ \reimp
+*/
+void QErrorMessage::changeEvent(QEvent *e)
+{
+ Q_D(QErrorMessage);
+ if (e->type() == QEvent::LanguageChange) {
+ d->retranslateStrings();
+ }
+ QDialog::changeEvent(e);
+}
+
+void QErrorMessagePrivate::retranslateStrings()
+{
+ again->setText(QErrorMessage::tr("&Show this message again"));
+ ok->setText(QErrorMessage::tr("&OK"));
+#ifdef QT_SOFTKEYS_ENABLED
+ okAction->setText(ok->text());
+#endif
+}
+
+/*!
+ \fn void QErrorMessage::message(const QString & message)
+
+ Use showMessage(\a message) instead.
+*/
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ERRORMESSAGE
diff --git a/src/widgets/dialogs/qerrormessage.h b/src/widgets/dialogs/qerrormessage.h
new file mode 100644
index 0000000000..500482c722
--- /dev/null
+++ b/src/widgets/dialogs/qerrormessage.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QERRORMESSAGE_H
+#define QERRORMESSAGE_H
+
+#include <QtGui/qdialog.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_ERRORMESSAGE
+
+class QErrorMessagePrivate;
+
+class Q_GUI_EXPORT QErrorMessage: public QDialog
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QErrorMessage)
+public:
+ explicit QErrorMessage(QWidget* parent = 0);
+ ~QErrorMessage();
+
+ static QErrorMessage * qtHandler();
+
+public Q_SLOTS:
+ void showMessage(const QString &message);
+ void showMessage(const QString &message, const QString &type);
+#ifdef QT3_SUPPORT
+ inline QT_MOC_COMPAT void message(const QString &text) { showMessage(text); }
+#endif
+
+protected:
+ void done(int);
+ void changeEvent(QEvent *e);
+
+private:
+ Q_DISABLE_COPY(QErrorMessage)
+};
+
+#endif // QT_NO_ERRORMESSAGE
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QERRORMESSAGE_H
diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp
new file mode 100644
index 0000000000..897a9164a2
--- /dev/null
+++ b/src/widgets/dialogs/qfiledialog.cpp
@@ -0,0 +1,3486 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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 <qvariant.h>
+#include <private/qwidgetitemdata_p.h>
+#include "qfiledialog.h"
+
+#ifndef QT_NO_FILEDIALOG
+#include "qfiledialog_p.h"
+#include <qfontmetrics.h>
+#include <qaction.h>
+#include <qheaderview.h>
+#include <qshortcut.h>
+#include <qgridlayout.h>
+#include <qmenu.h>
+#include <qmessagebox.h>
+#include <qinputdialog.h>
+#include <stdlib.h>
+#include <qsettings.h>
+#include <qdebug.h>
+#include <qapplication.h>
+#include <qstylepainter.h>
+#if !defined(Q_WS_WINCE) && !defined(Q_OS_SYMBIAN)
+#include "ui_qfiledialog.h"
+#else
+#define Q_EMBEDDED_SMALLSCREEN
+#include "ui_qfiledialog_embedded.h"
+#if defined(Q_OS_WINCE)
+extern bool qt_priv_ptr_valid;
+#endif
+#endif
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC(QString, lastVisitedDir)
+
+/*
+ \internal
+
+ Exported hooks that can be used to customize the static functions.
+ */
+typedef QString (*_qt_filedialog_existing_directory_hook)(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options);
+Q_GUI_EXPORT _qt_filedialog_existing_directory_hook qt_filedialog_existing_directory_hook = 0;
+
+typedef QString (*_qt_filedialog_open_filename_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
+Q_GUI_EXPORT _qt_filedialog_open_filename_hook qt_filedialog_open_filename_hook = 0;
+
+typedef QStringList (*_qt_filedialog_open_filenames_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
+Q_GUI_EXPORT _qt_filedialog_open_filenames_hook qt_filedialog_open_filenames_hook = 0;
+
+typedef QString (*_qt_filedialog_save_filename_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
+Q_GUI_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook = 0;
+
+/*!
+ \class QFileDialog
+ \brief The QFileDialog class provides a dialog that allow users to select files or directories.
+ \ingroup standard-dialogs
+
+
+ The QFileDialog class enables a user to traverse the file system in
+ order to select one or many files or a directory.
+
+ The easiest way to create a QFileDialog is to use the static
+ functions. On Windows, Mac OS X, KDE and GNOME, these static functions will
+ call the native file dialog when possible.
+
+ \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 0
+
+ In the above example, a modal QFileDialog is created using a static
+ function. The dialog initially displays the contents of the "/home/jana"
+ directory, and displays files matching the patterns given in the
+ string "Image Files (*.png *.jpg *.bmp)". The parent of the file dialog
+ is set to \e this, and the window title is set to "Open Image".
+
+ If you want to use multiple filters, separate each one with
+ \e two semicolons. For example:
+
+ \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 1
+
+ You can create your own QFileDialog without using the static
+ functions. By calling setFileMode(), you can specify what the user must
+ select in the dialog:
+
+ \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 2
+
+ In the above example, the mode of the file dialog is set to
+ AnyFile, meaning that the user can select any file, or even specify a
+ file that doesn't exist. This mode is useful for creating a
+ "Save As" file dialog. Use ExistingFile if the user must select an
+ existing file, or \l Directory if only a directory may be selected.
+ See the \l QFileDialog::FileMode enum for the complete list of modes.
+
+ The fileMode property contains the mode of operation for the dialog;
+ this indicates what types of objects the user is expected to select.
+ Use setNameFilter() to set the dialog's file filter. For example:
+
+ \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 3
+
+ In the above example, the filter is set to \c{"Images (*.png *.xpm *.jpg)"},
+ this means that only files with the extension \c png, \c xpm,
+ or \c jpg will be shown in the QFileDialog. You can apply
+ several filters by using setNameFilters(). Use selectNameFilter() to select
+ one of the filters you've given as the file dialog's default filter.
+
+ The file dialog has two view modes: \l{QFileDialog::}{List} and
+ \l{QFileDialog::}{Detail}.
+ \l{QFileDialog::}{List} presents the contents of the current directory
+ as a list of file and directory names. \l{QFileDialog::}{Detail} also
+ displays a list of file and directory names, but provides additional
+ information alongside each name, such as the file size and modification
+ date. Set the mode with setViewMode():
+
+ \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 4
+
+ The last important function you will need to use when creating your
+ own file dialog is selectedFiles().
+
+ \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 5
+
+ In the above example, a modal file dialog is created and shown. If
+ the user clicked OK, the file they selected is put in \c fileName.
+
+ The dialog's working directory can be set with setDirectory().
+ Each file in the current directory can be selected using
+ the selectFile() function.
+
+ The \l{dialogs/standarddialogs}{Standard Dialogs} example shows
+ how to use QFileDialog as well as other built-in Qt dialogs.
+
+ \sa QDir, QFileInfo, QFile, QPrintDialog, QColorDialog, QFontDialog, {Standard Dialogs Example},
+ {Application Example}
+*/
+
+/*!
+ \enum QFileDialog::AcceptMode
+
+ \value AcceptOpen
+ \value AcceptSave
+*/
+
+/*!
+ \enum QFileDialog::ViewMode
+
+ This enum describes the view mode of the file dialog; i.e. what
+ information about each file will be displayed.
+
+ \value Detail Displays an icon, a name, and details for each item in
+ the directory.
+ \value List Displays only an icon and a name for each item in the
+ directory.
+
+ \sa setViewMode()
+*/
+
+/*!
+ \enum QFileDialog::FileMode
+
+ This enum is used to indicate what the user may select in the file
+ dialog; i.e. what the dialog will return if the user clicks OK.
+
+ \value AnyFile The name of a file, whether it exists or not.
+ \value ExistingFile The name of a single existing file.
+ \value Directory The name of a directory. Both files and
+ directories are displayed.
+ \value ExistingFiles The names of zero or more existing files.
+
+ This value is obsolete since Qt 4.5:
+
+ \value DirectoryOnly Use \c Directory and setOption(ShowDirsOnly, true) instead.
+
+ \sa setFileMode()
+*/
+
+/*!
+ \enum QFileDialog::Option
+
+ \value ShowDirsOnly Only show directories in the file dialog. By
+ default both files and directories are shown. (Valid only in the
+ \l Directory file mode.)
+
+ \value DontResolveSymlinks Don't resolve symlinks in the file
+ dialog. By default symlinks are resolved.
+
+ \value DontConfirmOverwrite Don't ask for confirmation if an
+ existing file is selected. By default confirmation is requested.
+
+ \value DontUseNativeDialog Don't use the native file dialog. By
+ default, the native file dialog is used unless you use a subclass
+ of QFileDialog that contains the Q_OBJECT macro.
+
+ \value ReadOnly Indicates that the model is readonly.
+
+ \value HideNameFilterDetails Indicates if the file name filter details are
+ hidden or not.
+
+ \value DontUseSheet In previous versions of Qt, the static
+ functions would create a sheet by default if the static function
+ was given a parent. This is no longer supported and does nothing in Qt 4.5, The
+ static functions will always be an application modal dialog. If
+ you want to use sheets, use QFileDialog::open() instead.
+
+*/
+
+/*!
+ \enum QFileDialog::DialogLabel
+
+ \value LookIn
+ \value FileName
+ \value FileType
+ \value Accept
+ \value Reject
+*/
+
+/*!
+ \fn void QFileDialog::filesSelected(const QStringList &selected)
+
+ When the selection changes and the dialog is accepted, this signal is
+ emitted with the (possibly empty) list of \a selected files.
+
+ \sa currentChanged(), QDialog::Accepted
+*/
+
+
+/*!
+ \fn void QFileDialog::fileSelected(const QString &file)
+
+ When the selection changes and the dialog is accepted, this signal is
+ emitted with the (possibly empty) selected \a file.
+
+ \sa currentChanged(), QDialog::Accepted
+*/
+
+
+/*!
+ \fn void QFileDialog::currentChanged(const QString &path)
+
+ When the current file changes, this signal is emitted with the
+ new file name as the \a path parameter.
+
+ \sa filesSelected()
+*/
+
+/*!
+ \fn void QFileDialog::directoryEntered(const QString &directory)
+ \since 4.3
+
+ This signal is emitted when the user enters a \a directory.
+*/
+
+/*!
+ \fn void QFileDialog::filterSelected(const QString &filter)
+ \since 4.3
+
+ This signal is emitted when the user selects a \a filter.
+*/
+
+#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
+bool Q_GUI_EXPORT qt_use_native_dialogs = true; // for the benefit of testing tools, until we have a proper API
+#endif
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#ifdef Q_WS_WIN
+#include <qwindowsstyle.h>
+#endif
+#include <qshortcut.h>
+#ifdef Q_WS_MAC
+#include <qmacstyle_mac.h>
+#endif
+QT_END_INCLUDE_NAMESPACE
+
+/*!
+ \fn QFileDialog::QFileDialog(QWidget *parent, Qt::WindowFlags flags)
+
+ Constructs a file dialog with the given \a parent and widget \a flags.
+*/
+QFileDialog::QFileDialog(QWidget *parent, Qt::WindowFlags f)
+ : QDialog(*new QFileDialogPrivate, parent, f)
+{
+ Q_D(QFileDialog);
+ d->init();
+ d->lineEdit()->selectAll();
+}
+
+/*!
+ Constructs a file dialog with the given \a parent and \a caption that
+ initially displays the contents of the specified \a directory.
+ The contents of the directory are filtered before being shown in the
+ dialog, using a semicolon-separated list of filters specified by
+ \a filter.
+*/
+QFileDialog::QFileDialog(QWidget *parent,
+ const QString &caption,
+ const QString &directory,
+ const QString &filter)
+ : QDialog(*new QFileDialogPrivate, parent, 0)
+{
+ Q_D(QFileDialog);
+ d->init(directory, filter, caption);
+ d->lineEdit()->selectAll();
+}
+
+/*!
+ \internal
+*/
+QFileDialog::QFileDialog(const QFileDialogArgs &args)
+ : QDialog(*new QFileDialogPrivate, args.parent, 0)
+{
+ Q_D(QFileDialog);
+ d->init(args.directory, args.filter, args.caption);
+ setFileMode(args.mode);
+ setOptions(args.options);
+ selectFile(args.selection);
+ d->lineEdit()->selectAll();
+}
+
+/*!
+ Destroys the file dialog.
+*/
+QFileDialog::~QFileDialog()
+{
+ Q_D(QFileDialog);
+#ifndef QT_NO_SETTINGS
+ QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
+ settings.beginGroup(QLatin1String("Qt"));
+ settings.setValue(QLatin1String("filedialog"), saveState());
+#endif
+ d->deleteNativeDialog_sys();
+}
+
+/*!
+ \since 4.3
+ Sets the \a urls that are located in the sidebar.
+
+ For instance:
+
+ \snippet doc/src/snippets/filedialogurls.cpp 0
+
+ The file dialog will then look like this:
+
+ \image filedialogurls.png
+
+ \sa sidebarUrls()
+*/
+void QFileDialog::setSidebarUrls(const QList<QUrl> &urls)
+{
+ Q_D(QFileDialog);
+ d->qFileDialogUi->sidebar->setUrls(urls);
+}
+
+/*!
+ \since 4.3
+ Returns a list of urls that are currently in the sidebar
+*/
+QList<QUrl> QFileDialog::sidebarUrls() const
+{
+ Q_D(const QFileDialog);
+ return d->qFileDialogUi->sidebar->urls();
+}
+
+static const qint32 QFileDialogMagic = 0xbe;
+
+const char *qt_file_dialog_filter_reg_exp =
+"^(.*)\\(([a-zA-Z0-9_.*? +;#\\-\\[\\]@\\{\\}/!<>\\$%&=^~:\\|]*)\\)$";
+
+/*!
+ \since 4.3
+ Saves the state of the dialog's layout, history and current directory.
+
+ Typically this is used in conjunction with QSettings to remember the size
+ for a future session. A version number is stored as part of the data.
+*/
+QByteArray QFileDialog::saveState() const
+{
+ Q_D(const QFileDialog);
+ int version = 3;
+ QByteArray data;
+ QDataStream stream(&data, QIODevice::WriteOnly);
+
+ stream << qint32(QFileDialogMagic);
+ stream << qint32(version);
+ stream << d->qFileDialogUi->splitter->saveState();
+ stream << d->qFileDialogUi->sidebar->urls();
+ stream << history();
+ stream << *lastVisitedDir();
+ stream << d->qFileDialogUi->treeView->header()->saveState();
+ stream << qint32(viewMode());
+ return data;
+}
+
+/*!
+ \since 4.3
+ Restores the dialogs's layout, history and current directory to the \a state specified.
+
+ Typically this is used in conjunction with QSettings to restore the size
+ from a past session.
+
+ Returns false if there are errors
+*/
+bool QFileDialog::restoreState(const QByteArray &state)
+{
+ Q_D(QFileDialog);
+ int version = 3;
+ QByteArray sd = state;
+ QDataStream stream(&sd, QIODevice::ReadOnly);
+ if (stream.atEnd())
+ return false;
+ QByteArray splitterState;
+ QByteArray headerData;
+ QList<QUrl> bookmarks;
+ QStringList history;
+ QString currentDirectory;
+ qint32 marker;
+ qint32 v;
+ qint32 viewMode;
+ stream >> marker;
+ stream >> v;
+ if (marker != QFileDialogMagic || v != version)
+ return false;
+
+ stream >> splitterState
+ >> bookmarks
+ >> history
+ >> currentDirectory
+ >> headerData
+ >> viewMode;
+
+ if (!d->qFileDialogUi->splitter->restoreState(splitterState))
+ return false;
+ QList<int> list = d->qFileDialogUi->splitter->sizes();
+ if (list.count() >= 2 && list.at(0) == 0 && list.at(1) == 0) {
+ for (int i = 0; i < list.count(); ++i)
+ list[i] = d->qFileDialogUi->splitter->widget(i)->sizeHint().width();
+ d->qFileDialogUi->splitter->setSizes(list);
+ }
+
+ d->qFileDialogUi->sidebar->setUrls(bookmarks);
+ while (history.count() > 5)
+ history.pop_front();
+ setHistory(history);
+ setDirectory(lastVisitedDir()->isEmpty() ? currentDirectory : *lastVisitedDir());
+ if (!d->qFileDialogUi->treeView->header()->restoreState(headerData))
+ return false;
+
+ setViewMode(ViewMode(viewMode));
+ return true;
+}
+
+/*!
+ \reimp
+*/
+void QFileDialog::changeEvent(QEvent *e)
+{
+ Q_D(QFileDialog);
+ if (e->type() == QEvent::LanguageChange) {
+ d->retranslateWindowTitle();
+ d->retranslateStrings();
+ }
+ QDialog::changeEvent(e);
+}
+
+QFileDialogPrivate::QFileDialogPrivate()
+ :
+#ifndef QT_NO_PROXYMODEL
+ proxyModel(0),
+#endif
+ model(0),
+ fileMode(QFileDialog::AnyFile),
+ acceptMode(QFileDialog::AcceptOpen),
+ currentHistoryLocation(-1),
+ renameAction(0),
+ deleteAction(0),
+ showHiddenAction(0),
+ useDefaultCaption(true),
+ defaultFileTypes(true),
+ fileNameLabelExplicitlySat(false),
+ nativeDialogInUse(false),
+#ifdef Q_WS_MAC
+ mDelegate(0),
+#ifndef QT_MAC_USE_COCOA
+ mDialog(0),
+ mDialogStarted(false),
+ mDialogClosed(true),
+#endif
+#endif
+ qFileDialogUi(0)
+{
+}
+
+QFileDialogPrivate::~QFileDialogPrivate()
+{
+}
+
+void QFileDialogPrivate::retranslateWindowTitle()
+{
+ Q_Q(QFileDialog);
+ if (!useDefaultCaption || setWindowTitle != q->windowTitle())
+ return;
+ if (acceptMode == QFileDialog::AcceptOpen) {
+ if (fileMode == QFileDialog::DirectoryOnly || fileMode == QFileDialog::Directory)
+ q->setWindowTitle(QFileDialog::tr("Find Directory"));
+ else
+ q->setWindowTitle(QFileDialog::tr("Open"));
+ } else
+ q->setWindowTitle(QFileDialog::tr("Save As"));
+
+ setWindowTitle = q->windowTitle();
+}
+
+void QFileDialogPrivate::setLastVisitedDirectory(const QString &dir)
+{
+ *lastVisitedDir() = dir;
+}
+
+void QFileDialogPrivate::retranslateStrings()
+{
+ Q_Q(QFileDialog);
+ /* WIDGETS */
+ if (defaultFileTypes)
+ q->setNameFilter(QFileDialog::tr("All Files (*)"));
+
+ QList<QAction*> actions = qFileDialogUi->treeView->header()->actions();
+ QAbstractItemModel *abstractModel = model;
+#ifndef QT_NO_PROXYMODEL
+ if (proxyModel)
+ abstractModel = proxyModel;
+#endif
+ int total = qMin(abstractModel->columnCount(QModelIndex()), actions.count() + 1);
+ for (int i = 1; i < total; ++i) {
+ actions.at(i - 1)->setText(QFileDialog::tr("Show ") + abstractModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString());
+ }
+
+ /* MENU ACTIONS */
+ renameAction->setText(QFileDialog::tr("&Rename"));
+ deleteAction->setText(QFileDialog::tr("&Delete"));
+ showHiddenAction->setText(QFileDialog::tr("Show &hidden files"));
+ newFolderAction->setText(QFileDialog::tr("&New Folder"));
+ qFileDialogUi->retranslateUi(q);
+
+ if (!fileNameLabelExplicitlySat){
+ if (fileMode == QFileDialog::DirectoryOnly || fileMode == QFileDialog::Directory) {
+ q->setLabelText(QFileDialog::FileName, QFileDialog::tr("Directory:"));
+ } else {
+ q->setLabelText(QFileDialog::FileName, QFileDialog::tr("File &name:"));
+ }
+ fileNameLabelExplicitlySat = false;
+ }
+}
+
+void QFileDialogPrivate::emitFilesSelected(const QStringList &files)
+{
+ Q_Q(QFileDialog);
+ emit q->filesSelected(files);
+ if (files.count() == 1)
+ emit q->fileSelected(files.first());
+}
+
+bool QFileDialogPrivate::canBeNativeDialog()
+{
+ Q_Q(QFileDialog);
+ if (nativeDialogInUse)
+ return true;
+ if (q->testAttribute(Qt::WA_DontShowOnScreen))
+ return false;
+ if (opts & QFileDialog::DontUseNativeDialog)
+ return false;
+
+ QLatin1String staticName(QFileDialog::staticMetaObject.className());
+ QLatin1String dynamicName(q->metaObject()->className());
+ return (staticName == dynamicName);
+}
+
+/*!
+ \since 4.5
+ Sets the given \a option to be enabled if \a on is true; otherwise,
+ clears the given \a option.
+
+ \sa options, testOption()
+*/
+void QFileDialog::setOption(Option option, bool on)
+{
+ Q_D(QFileDialog);
+ if (!(d->opts & option) != !on)
+ setOptions(d->opts ^ option);
+}
+
+/*!
+ \since 4.5
+
+ Returns true if the given \a option is enabled; otherwise, returns
+ false.
+
+ \sa options, setOption()
+*/
+bool QFileDialog::testOption(Option option) const
+{
+ Q_D(const QFileDialog);
+ return (d->opts & option) != 0;
+}
+
+/*!
+ \property QFileDialog::options
+ \brief the various options that affect the look and feel of the dialog
+ \since 4.5
+
+ By default, all options are disabled.
+
+ Options should be set before showing the dialog. Setting them while the
+ dialog is visible is not guaranteed to have an immediate effect on the
+ dialog (depending on the option and on the platform).
+
+ \sa setOption(), testOption()
+*/
+void QFileDialog::setOptions(Options options)
+{
+ Q_D(QFileDialog);
+
+ Options changed = (options ^ d->opts);
+ if (!changed)
+ return;
+
+ d->opts = options;
+ if (changed & DontResolveSymlinks)
+ d->model->setResolveSymlinks(!(options & DontResolveSymlinks));
+ if (changed & ReadOnly) {
+ bool ro = (options & ReadOnly);
+ d->model->setReadOnly(ro);
+ d->qFileDialogUi->newFolderButton->setEnabled(!ro);
+ d->renameAction->setEnabled(!ro);
+ d->deleteAction->setEnabled(!ro);
+ }
+ if (changed & HideNameFilterDetails)
+ setNameFilters(d->nameFilters);
+
+ if (changed & ShowDirsOnly)
+ setFilter((options & ShowDirsOnly) ? filter() & ~QDir::Files : filter() | QDir::Files);
+}
+
+QFileDialog::Options QFileDialog::options() const
+{
+ Q_D(const QFileDialog);
+ return d->opts;
+}
+
+/*!
+ \overload
+
+ \since 4.5
+
+ This function connects one of its signals to the slot specified by \a receiver
+ and \a member. The specific signal depends is filesSelected() if fileMode is
+ ExistingFiles and fileSelected() if fileMode is anything else.
+
+ The signal will be disconnected from the slot when the dialog is closed.
+*/
+void QFileDialog::open(QObject *receiver, const char *member)
+{
+ Q_D(QFileDialog);
+ const char *signal = (fileMode() == ExistingFiles) ? SIGNAL(filesSelected(QStringList))
+ : SIGNAL(fileSelected(QString));
+ connect(this, signal, receiver, member);
+ d->signalToDisconnectOnClose = signal;
+ d->receiverToDisconnectOnClose = receiver;
+ d->memberToDisconnectOnClose = member;
+
+ QDialog::open();
+}
+
+
+/*!
+ \reimp
+*/
+void QFileDialog::setVisible(bool visible)
+{
+ Q_D(QFileDialog);
+ if (visible){
+ if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden))
+ return;
+ } else if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden))
+ return;
+
+ if (d->canBeNativeDialog()){
+ if (d->setVisible_sys(visible)){
+ d->nativeDialogInUse = true;
+ // Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below
+ // updates the state correctly, but skips showing the non-native version:
+ setAttribute(Qt::WA_DontShowOnScreen);
+#ifndef QT_NO_FSCOMPLETER
+ //So the completer don't try to complete and therefore to show a popup
+ d->completer->setModel(0);
+#endif
+ } else {
+ d->nativeDialogInUse = false;
+ setAttribute(Qt::WA_DontShowOnScreen, false);
+#ifndef QT_NO_FSCOMPLETER
+ if (d->proxyModel != 0)
+ d->completer->setModel(d->proxyModel);
+ else
+ d->completer->setModel(d->model);
+#endif
+ }
+ }
+
+ if (!d->nativeDialogInUse)
+ d->qFileDialogUi->fileNameEdit->setFocus();
+
+ QDialog::setVisible(visible);
+}
+
+/*!
+ \internal
+ set the directory to url
+*/
+void QFileDialogPrivate::_q_goToUrl(const QUrl &url)
+{
+ //The shortcut in the side bar may have a parent that is not fetched yet (e.g. an hidden file)
+ //so we force the fetching
+ QFileSystemModelPrivate::QFileSystemNode *node = model->d_func()->node(url.toLocalFile(), true);
+ QModelIndex idx = model->d_func()->index(node);
+ _q_enterDirectory(idx);
+}
+
+/*!
+ \fn void QFileDialog::setDirectory(const QDir &directory)
+
+ \overload
+*/
+
+/*!
+ Sets the file dialog's current \a directory.
+*/
+void QFileDialog::setDirectory(const QString &directory)
+{
+ Q_D(QFileDialog);
+ QString newDirectory = directory;
+ QFileInfo info(directory);
+ //we remove .. and . from the given path if exist
+ if (!directory.isEmpty())
+ newDirectory = QDir::cleanPath(directory);
+
+ if (!directory.isEmpty() && newDirectory.isEmpty())
+ return;
+
+ d->setLastVisitedDirectory(newDirectory);
+
+ if (d->nativeDialogInUse){
+ d->setDirectory_sys(newDirectory);
+ return;
+ }
+ if (d->rootPath() == newDirectory)
+ return;
+ QModelIndex root = d->model->setRootPath(newDirectory);
+ d->qFileDialogUi->newFolderButton->setEnabled(d->model->flags(root) & Qt::ItemIsDropEnabled);
+ if (root != d->rootIndex()) {
+#ifndef QT_NO_FSCOMPLETER
+ if (directory.endsWith(QLatin1Char('/')))
+ d->completer->setCompletionPrefix(newDirectory);
+ else
+ d->completer->setCompletionPrefix(newDirectory + QLatin1Char('/'));
+#endif
+ d->setRootIndex(root);
+ }
+ d->qFileDialogUi->listView->selectionModel()->clear();
+}
+
+/*!
+ Returns the directory currently being displayed in the dialog.
+*/
+QDir QFileDialog::directory() const
+{
+ Q_D(const QFileDialog);
+ return QDir(d->nativeDialogInUse ? d->directory_sys() : d->rootPath());
+}
+
+/*!
+ Selects the given \a filename in the file dialog.
+
+ \sa selectedFiles()
+*/
+void QFileDialog::selectFile(const QString &filename)
+{
+ Q_D(QFileDialog);
+ if (filename.isEmpty())
+ return;
+
+ if (d->nativeDialogInUse){
+ d->selectFile_sys(filename);
+ return;
+ }
+
+ if (!QDir::isRelativePath(filename)) {
+ QFileInfo info(filename);
+ QString filenamePath = info.absoluteDir().path();
+
+ if (d->model->rootPath() != filenamePath)
+ setDirectory(filenamePath);
+ }
+
+ QModelIndex index = d->model->index(filename);
+ QString file;
+ if (!index.isValid()) {
+ // save as dialog where we want to input a default value
+ QString text = filename;
+ if (QFileInfo(filename).isAbsolute()) {
+ QString current = d->rootPath();
+ text.remove(current);
+ if (text.at(0) == QDir::separator()
+#ifdef Q_OS_WIN
+ //On Windows both cases can happen
+ || text.at(0) == QLatin1Char('/')
+#endif
+ )
+ text = text.remove(0,1);
+ }
+ file = text;
+ } else {
+ file = index.data().toString();
+ }
+ d->qFileDialogUi->listView->selectionModel()->clear();
+ if (!isVisible() || !d->lineEdit()->hasFocus())
+ d->lineEdit()->setText(file);
+}
+
+/**
+ Returns the text in the line edit which can be one or more file names
+ */
+QStringList QFileDialogPrivate::typedFiles() const
+{
+ QStringList files;
+ QString editText = lineEdit()->text();
+ if (!editText.contains(QLatin1Char('"')))
+ files << editText;
+ else {
+ // " is used to separate files like so: "file1" "file2" "file3" ...
+ // ### need escape character for filenames with quotes (")
+ QStringList tokens = editText.split(QLatin1Char('\"'));
+ for (int i=0; i<tokens.size(); ++i) {
+ if ((i % 2) == 0)
+ continue; // Every even token is a separator
+ files << toInternal(tokens.at(i));
+ }
+ }
+ return addDefaultSuffixToFiles(files);
+}
+
+QStringList QFileDialogPrivate::addDefaultSuffixToFiles(const QStringList filesToFix) const
+{
+ QStringList files;
+ for (int i=0; i<filesToFix.size(); ++i) {
+ QString name = toInternal(filesToFix.at(i));
+ QFileInfo info(name);
+ // if the filename has no suffix, add the default suffix
+ if (!defaultSuffix.isEmpty() && !info.isDir() && name.lastIndexOf(QLatin1Char('.')) == -1)
+ name += QLatin1Char('.') + defaultSuffix;
+ if (info.isAbsolute()) {
+ files.append(name);
+ } else {
+ // at this point the path should only have Qt path separators.
+ // This check is needed since we might be at the root directory
+ // and on Windows it already ends with slash.
+ QString path = rootPath();
+ if (!path.endsWith(QLatin1Char('/')))
+ path += QLatin1Char('/');
+ path += name;
+ files.append(path);
+ }
+ }
+ return files;
+}
+
+
+/*!
+ Returns a list of strings containing the absolute paths of the
+ selected files in the dialog. If no files are selected, or
+ the mode is not ExistingFiles or ExistingFile, selectedFiles() contains the current path in the viewport.
+
+ \sa selectedNameFilter(), selectFile()
+*/
+QStringList QFileDialog::selectedFiles() const
+{
+ Q_D(const QFileDialog);
+ if (d->nativeDialogInUse)
+ return d->addDefaultSuffixToFiles(d->selectedFiles_sys());
+
+ QModelIndexList indexes = d->qFileDialogUi->listView->selectionModel()->selectedRows();
+ QStringList files;
+ for (int i = 0; i < indexes.count(); ++i)
+ files.append(indexes.at(i).data(QFileSystemModel::FilePathRole).toString());
+
+ if (files.isEmpty() && !d->lineEdit()->text().isEmpty())
+ files = d->typedFiles();
+
+ if (files.isEmpty() && !(d->fileMode == ExistingFile || d->fileMode == ExistingFiles))
+ files.append(d->rootIndex().data(QFileSystemModel::FilePathRole).toString());
+ return files;
+}
+
+/*
+ Makes a list of filters from ;;-separated text.
+ Used by the mac and windows implementations
+*/
+QStringList qt_make_filter_list(const QString &filter)
+{
+ QString f(filter);
+
+ if (f.isEmpty())
+ return QStringList();
+
+ QString sep(QLatin1String(";;"));
+ int i = f.indexOf(sep, 0);
+ if (i == -1) {
+ if (f.indexOf(QLatin1Char('\n'), 0) != -1) {
+ sep = QLatin1Char('\n');
+ i = f.indexOf(sep, 0);
+ }
+ }
+
+ return f.split(sep);
+}
+
+/*!
+ \since 4.4
+
+ Sets the filter used in the file dialog to the given \a filter.
+
+ If \a filter contains a pair of parentheses containing one or more
+ of \bold{anything*something}, separated by spaces, then only the
+ text contained in the parentheses is used as the filter. This means
+ that these calls are all equivalent:
+
+ \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 6
+
+ \sa setNameFilters()
+*/
+void QFileDialog::setNameFilter(const QString &filter)
+{
+ setNameFilters(qt_make_filter_list(filter));
+}
+
+/*!
+ \obsolete
+
+ Use setNameFilter() instead.
+*/
+void QFileDialog::setFilter(const QString &filter)
+{
+ setNameFilter(filter);
+}
+
+/*!
+ \property QFileDialog::nameFilterDetailsVisible
+ \obsolete
+ \brief This property holds whether the filter details is shown or not.
+ \since 4.4
+
+ When this property is true (the default), the filter details are shown
+ in the combo box. When the property is set to false, these are hidden.
+
+ Use setOption(HideNameFilterDetails, !\e enabled) or
+ !testOption(HideNameFilterDetails).
+*/
+void QFileDialog::setNameFilterDetailsVisible(bool enabled)
+{
+ setOption(HideNameFilterDetails, !enabled);
+}
+
+bool QFileDialog::isNameFilterDetailsVisible() const
+{
+ return !testOption(HideNameFilterDetails);
+}
+
+
+/*
+ Strip the filters by removing the details, e.g. (*.*).
+*/
+QStringList qt_strip_filters(const QStringList &filters)
+{
+ QStringList strippedFilters;
+ QRegExp r(QString::fromLatin1(qt_file_dialog_filter_reg_exp));
+ for (int i = 0; i < filters.count(); ++i) {
+ QString filterName;
+ int index = r.indexIn(filters[i]);
+ if (index >= 0)
+ filterName = r.cap(1);
+ strippedFilters.append(filterName.simplified());
+ }
+ return strippedFilters;
+}
+
+
+/*!
+ \since 4.4
+
+ Sets the \a filters used in the file dialog.
+
+ \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 7
+*/
+void QFileDialog::setNameFilters(const QStringList &filters)
+{
+ Q_D(QFileDialog);
+ d->defaultFileTypes = (filters == QStringList(QFileDialog::tr("All Files (*)")));
+ QStringList cleanedFilters;
+ for (int i = 0; i < filters.count(); ++i) {
+ cleanedFilters << filters[i].simplified();
+ }
+ d->nameFilters = cleanedFilters;
+
+ if (d->nativeDialogInUse){
+ d->setNameFilters_sys(cleanedFilters);
+ return;
+ }
+
+ d->qFileDialogUi->fileTypeCombo->clear();
+ if (cleanedFilters.isEmpty())
+ return;
+
+ if (testOption(HideNameFilterDetails))
+ d->qFileDialogUi->fileTypeCombo->addItems(qt_strip_filters(cleanedFilters));
+ else
+ d->qFileDialogUi->fileTypeCombo->addItems(cleanedFilters);
+
+ d->_q_useNameFilter(0);
+}
+
+/*!
+ \obsolete
+
+ Use setNameFilters() instead.
+*/
+void QFileDialog::setFilters(const QStringList &filters)
+{
+ setNameFilters(filters);
+}
+
+/*!
+ \since 4.4
+
+ Returns the file type filters that are in operation on this file
+ dialog.
+*/
+QStringList QFileDialog::nameFilters() const
+{
+ return d_func()->nameFilters;
+}
+
+/*!
+ \obsolete
+
+ Use nameFilters() instead.
+*/
+
+QStringList QFileDialog::filters() const
+{
+ return nameFilters();
+}
+
+/*!
+ \since 4.4
+
+ Sets the current file type \a filter. Multiple filters can be
+ passed in \a filter by separating them with semicolons or spaces.
+
+ \sa setNameFilter(), setNameFilters(), selectedNameFilter()
+*/
+void QFileDialog::selectNameFilter(const QString &filter)
+{
+ Q_D(QFileDialog);
+ if (d->nativeDialogInUse) {
+ d->selectNameFilter_sys(filter);
+ return;
+ }
+ int i;
+ if (testOption(HideNameFilterDetails)) {
+ i = d->qFileDialogUi->fileTypeCombo->findText(qt_strip_filters(qt_make_filter_list(filter)).first());
+ } else {
+ i = d->qFileDialogUi->fileTypeCombo->findText(filter);
+ }
+ if (i >= 0) {
+ d->qFileDialogUi->fileTypeCombo->setCurrentIndex(i);
+ d->_q_useNameFilter(d->qFileDialogUi->fileTypeCombo->currentIndex());
+ }
+}
+
+/*!
+ \obsolete
+
+ Use selectNameFilter() instead.
+*/
+
+void QFileDialog::selectFilter(const QString &filter)
+{
+ selectNameFilter(filter);
+}
+
+/*!
+ \since 4.4
+
+ Returns the filter that the user selected in the file dialog.
+
+ \sa selectedFiles()
+*/
+QString QFileDialog::selectedNameFilter() const
+{
+ Q_D(const QFileDialog);
+ if (d->nativeDialogInUse)
+ return d->selectedNameFilter_sys();
+
+ return d->qFileDialogUi->fileTypeCombo->currentText();
+}
+
+/*!
+ \obsolete
+
+ Use selectedNameFilter() instead.
+*/
+QString QFileDialog::selectedFilter() const
+{
+ return selectedNameFilter();
+}
+
+/*!
+ \since 4.4
+
+ Returns the filter that is used when displaying files.
+
+ \sa setFilter()
+*/
+QDir::Filters QFileDialog::filter() const
+{
+ Q_D(const QFileDialog);
+ return d->model->filter();
+}
+
+/*!
+ \since 4.4
+
+ Sets the filter used by the model to \a filters. The filter is used
+ to specify the kind of files that should be shown.
+
+ \sa filter()
+*/
+
+void QFileDialog::setFilter(QDir::Filters filters)
+{
+ Q_D(QFileDialog);
+ d->model->setFilter(filters);
+ if (d->nativeDialogInUse){
+ d->setFilter_sys();
+ return;
+ }
+
+ d->showHiddenAction->setChecked((filters & QDir::Hidden));
+}
+
+/*!
+ \property QFileDialog::viewMode
+ \brief the way files and directories are displayed in the dialog
+
+ By default, the \c Detail mode is used to display information about
+ files and directories.
+
+ \sa ViewMode
+*/
+void QFileDialog::setViewMode(QFileDialog::ViewMode mode)
+{
+ Q_D(QFileDialog);
+ if (mode == Detail)
+ d->_q_showDetailsView();
+ else
+ d->_q_showListView();
+}
+
+QFileDialog::ViewMode QFileDialog::viewMode() const
+{
+ Q_D(const QFileDialog);
+ return (d->qFileDialogUi->stackedWidget->currentWidget() == d->qFileDialogUi->listView->parent() ? QFileDialog::List : QFileDialog::Detail);
+}
+
+/*!
+ \property QFileDialog::fileMode
+ \brief the file mode of the dialog
+
+ The file mode defines the number and type of items that the user is
+ expected to select in the dialog.
+
+ By default, this property is set to AnyFile.
+
+ This function will set the labels for the FileName and
+ \l{QFileDialog::}{Accept} \l{DialogLabel}s. It is possible to set
+ custom text after the call to setFileMode().
+
+ \sa FileMode
+*/
+void QFileDialog::setFileMode(QFileDialog::FileMode mode)
+{
+ Q_D(QFileDialog);
+ d->fileMode = mode;
+ d->retranslateWindowTitle();
+
+ // keep ShowDirsOnly option in sync with fileMode (BTW, DirectoryOnly is obsolete)
+ setOption(ShowDirsOnly, mode == DirectoryOnly);
+
+ // set selection mode and behavior
+ QAbstractItemView::SelectionMode selectionMode;
+ if (mode == QFileDialog::ExistingFiles)
+ selectionMode = QAbstractItemView::ExtendedSelection;
+ else
+ selectionMode = QAbstractItemView::SingleSelection;
+ d->qFileDialogUi->listView->setSelectionMode(selectionMode);
+ d->qFileDialogUi->treeView->setSelectionMode(selectionMode);
+ // set filter
+ d->model->setFilter(d->filterForMode(filter()));
+ // setup file type for directory
+ QString buttonText = (d->acceptMode == AcceptOpen ? tr("&Open") : tr("&Save"));
+ if (mode == DirectoryOnly || mode == Directory) {
+ d->qFileDialogUi->fileTypeCombo->clear();
+ d->qFileDialogUi->fileTypeCombo->addItem(tr("Directories"));
+ d->qFileDialogUi->fileTypeCombo->setEnabled(false);
+
+ if (!d->fileNameLabelExplicitlySat){
+ setLabelText(FileName, tr("Directory:"));
+ d->fileNameLabelExplicitlySat = false;
+ }
+ buttonText = tr("&Choose");
+ } else {
+ if (!d->fileNameLabelExplicitlySat){
+ setLabelText(FileName, tr("File &name:"));
+ d->fileNameLabelExplicitlySat = false;
+ }
+ }
+ setLabelText(Accept, buttonText);
+ if (d->nativeDialogInUse){
+ d->setFilter_sys();
+ return;
+ }
+
+ d->qFileDialogUi->fileTypeCombo->setEnabled(!testOption(ShowDirsOnly));
+ d->_q_updateOkButton();
+}
+
+QFileDialog::FileMode QFileDialog::fileMode() const
+{
+ Q_D(const QFileDialog);
+ return d->fileMode;
+}
+
+/*!
+ \property QFileDialog::acceptMode
+ \brief the accept mode of the dialog
+
+ The action mode defines whether the dialog is for opening or saving files.
+
+ By default, this property is set to \l{AcceptOpen}.
+
+ \sa AcceptMode
+*/
+void QFileDialog::setAcceptMode(QFileDialog::AcceptMode mode)
+{
+ Q_D(QFileDialog);
+ d->acceptMode = mode;
+ bool directoryMode = (d->fileMode == Directory || d->fileMode == DirectoryOnly);
+ QDialogButtonBox::StandardButton button = (mode == AcceptOpen ? QDialogButtonBox::Open : QDialogButtonBox::Save);
+ d->qFileDialogUi->buttonBox->setStandardButtons(button | QDialogButtonBox::Cancel);
+ d->qFileDialogUi->buttonBox->button(button)->setEnabled(false);
+ d->_q_updateOkButton();
+ if (mode == AcceptOpen && directoryMode)
+ setLabelText(Accept, tr("&Choose"));
+ else
+ setLabelText(Accept, (mode == AcceptOpen ? tr("&Open") : tr("&Save")));
+ if (mode == AcceptSave) {
+ d->qFileDialogUi->lookInCombo->setEditable(false);
+ }
+ d->retranslateWindowTitle();
+#if defined(Q_WS_MAC)
+ d->deleteNativeDialog_sys();
+ setAttribute(Qt::WA_DontShowOnScreen, false);
+#endif
+}
+
+/*
+ Returns the file system model index that is the root index in the
+ views
+*/
+QModelIndex QFileDialogPrivate::rootIndex() const {
+ return mapToSource(qFileDialogUi->listView->rootIndex());
+}
+
+QAbstractItemView *QFileDialogPrivate::currentView() const {
+ if (!qFileDialogUi->stackedWidget)
+ return 0;
+ if (qFileDialogUi->stackedWidget->currentWidget() == qFileDialogUi->listView->parent())
+ return qFileDialogUi->listView;
+ return qFileDialogUi->treeView;
+}
+
+QLineEdit *QFileDialogPrivate::lineEdit() const {
+ return (QLineEdit*)qFileDialogUi->fileNameEdit;
+}
+
+/*
+ Sets the view root index to be the file system model index
+*/
+void QFileDialogPrivate::setRootIndex(const QModelIndex &index) const {
+ Q_ASSERT(index.isValid() ? index.model() == model : true);
+ QModelIndex idx = mapFromSource(index);
+ qFileDialogUi->treeView->setRootIndex(idx);
+ qFileDialogUi->listView->setRootIndex(idx);
+}
+/*
+ Select a file system model index
+ returns the index that was selected (or not depending upon sortfilterproxymodel)
+*/
+QModelIndex QFileDialogPrivate::select(const QModelIndex &index) const {
+ Q_ASSERT(index.isValid() ? index.model() == model : true);
+
+ QModelIndex idx = mapFromSource(index);
+ if (idx.isValid() && !qFileDialogUi->listView->selectionModel()->isSelected(idx))
+ qFileDialogUi->listView->selectionModel()->select(idx,
+ QItemSelectionModel::Select | QItemSelectionModel::Rows);
+ return idx;
+}
+
+QFileDialog::AcceptMode QFileDialog::acceptMode() const
+{
+ Q_D(const QFileDialog);
+ return d->acceptMode;
+}
+
+/*!
+ \property QFileDialog::readOnly
+ \obsolete
+ \brief Whether the filedialog is read-only
+
+ If this property is set to false, the file dialog will allow renaming,
+ and deleting of files and directories and creating directories.
+
+ Use setOption(ReadOnly, \e enabled) or testOption(ReadOnly) instead.
+*/
+void QFileDialog::setReadOnly(bool enabled)
+{
+ setOption(ReadOnly, enabled);
+}
+
+bool QFileDialog::isReadOnly() const
+{
+ return testOption(ReadOnly);
+}
+
+/*!
+ \property QFileDialog::resolveSymlinks
+ \obsolete
+ \brief whether the filedialog should resolve shortcuts
+
+ If this property is set to true, the file dialog will resolve
+ shortcuts or symbolic links.
+
+ Use setOption(DontResolveSymlinks, !\a enabled) or
+ !testOption(DontResolveSymlinks).
+*/
+void QFileDialog::setResolveSymlinks(bool enabled)
+{
+ setOption(DontResolveSymlinks, !enabled);
+}
+
+bool QFileDialog::resolveSymlinks() const
+{
+ return !testOption(DontResolveSymlinks);
+}
+
+/*!
+ \property QFileDialog::confirmOverwrite
+ \obsolete
+ \brief whether the filedialog should ask before accepting a selected file,
+ when the accept mode is AcceptSave
+
+ Use setOption(DontConfirmOverwrite, !\e enabled) or
+ !testOption(DontConfirmOverwrite) instead.
+*/
+void QFileDialog::setConfirmOverwrite(bool enabled)
+{
+ setOption(DontConfirmOverwrite, !enabled);
+}
+
+bool QFileDialog::confirmOverwrite() const
+{
+ return !testOption(DontConfirmOverwrite);
+}
+
+/*!
+ \property QFileDialog::defaultSuffix
+ \brief suffix added to the filename if no other suffix was specified
+
+ This property specifies a string that will be added to the
+ filename if it has no suffix already. The suffix is typically
+ used to indicate the file type (e.g. "txt" indicates a text
+ file).
+*/
+void QFileDialog::setDefaultSuffix(const QString &suffix)
+{
+ Q_D(QFileDialog);
+ d->defaultSuffix = suffix;
+}
+
+QString QFileDialog::defaultSuffix() const
+{
+ Q_D(const QFileDialog);
+ return d->defaultSuffix;
+}
+
+/*!
+ Sets the browsing history of the filedialog to contain the given
+ \a paths.
+*/
+void QFileDialog::setHistory(const QStringList &paths)
+{
+ Q_D(QFileDialog);
+ d->qFileDialogUi->lookInCombo->setHistory(paths);
+}
+
+void QFileDialogComboBox::setHistory(const QStringList &paths)
+{
+ m_history = paths;
+ // Only populate the first item, showPopup will populate the rest if needed
+ QList<QUrl> list;
+ QModelIndex idx = d_ptr->model->index(d_ptr->rootPath());
+ //On windows the popup display the "C:\", convert to nativeSeparators
+ QUrl url = QUrl::fromLocalFile(QDir::toNativeSeparators(idx.data(QFileSystemModel::FilePathRole).toString()));
+ if (url.isValid())
+ list.append(url);
+ urlModel->setUrls(list);
+}
+
+/*!
+ Returns the browsing history of the filedialog as a list of paths.
+*/
+QStringList QFileDialog::history() const
+{
+ Q_D(const QFileDialog);
+ QStringList currentHistory = d->qFileDialogUi->lookInCombo->history();
+ //On windows the popup display the "C:\", convert to nativeSeparators
+ QString newHistory = QDir::toNativeSeparators(d->rootIndex().data(QFileSystemModel::FilePathRole).toString());
+ if (!currentHistory.contains(newHistory))
+ currentHistory << newHistory;
+ return currentHistory;
+}
+
+/*!
+ Sets the item delegate used to render items in the views in the
+ file dialog to the given \a delegate.
+
+ \warning You should not share the same instance of a delegate between views.
+ Doing so can cause incorrect or unintuitive editing behavior since each
+ view connected to a given delegate may receive the \l{QAbstractItemDelegate::}{closeEditor()}
+ signal, and attempt to access, modify or close an editor that has already been closed.
+
+ Note that the model used is QFileSystemModel. It has custom item data roles, which is
+ described by the \l{QFileSystemModel::}{Roles} enum. You can use a QFileIconProvider if
+ you only want custom icons.
+
+ \sa itemDelegate(), setIconProvider(), QFileSystemModel
+*/
+void QFileDialog::setItemDelegate(QAbstractItemDelegate *delegate)
+{
+ Q_D(QFileDialog);
+ d->qFileDialogUi->listView->setItemDelegate(delegate);
+ d->qFileDialogUi->treeView->setItemDelegate(delegate);
+}
+
+/*!
+ Returns the item delegate used to render the items in the views in the filedialog.
+*/
+QAbstractItemDelegate *QFileDialog::itemDelegate() const
+{
+ Q_D(const QFileDialog);
+ return d->qFileDialogUi->listView->itemDelegate();
+}
+
+/*!
+ Sets the icon provider used by the filedialog to the specified \a provider.
+*/
+void QFileDialog::setIconProvider(QFileIconProvider *provider)
+{
+ Q_D(QFileDialog);
+ d->model->setIconProvider(provider);
+ //It forces the refresh of all entries in the side bar, then we can get new icons
+ d->qFileDialogUi->sidebar->setUrls(d->qFileDialogUi->sidebar->urls());
+}
+
+/*!
+ Returns the icon provider used by the filedialog.
+*/
+QFileIconProvider *QFileDialog::iconProvider() const
+{
+ Q_D(const QFileDialog);
+ return d->model->iconProvider();
+}
+
+/*!
+ Sets the \a text shown in the filedialog in the specified \a label.
+*/
+void QFileDialog::setLabelText(DialogLabel label, const QString &text)
+{
+ Q_D(QFileDialog);
+ QPushButton *button;
+ switch (label) {
+ case LookIn:
+ d->qFileDialogUi->lookInLabel->setText(text);
+ break;
+ case FileName:
+ d->qFileDialogUi->fileNameLabel->setText(text);
+ d->fileNameLabelExplicitlySat = true;
+ break;
+ case FileType:
+ d->qFileDialogUi->fileTypeLabel->setText(text);
+ break;
+ case Accept:
+ d->acceptLabel = text;
+ if (acceptMode() == AcceptOpen)
+ button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Open);
+ else
+ button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Save);
+ if (button)
+ button->setText(text);
+ break;
+ case Reject:
+ button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Cancel);
+ if (button)
+ button->setText(text);
+ break;
+ }
+}
+
+/*!
+ Returns the text shown in the filedialog in the specified \a label.
+*/
+QString QFileDialog::labelText(DialogLabel label) const
+{
+ QPushButton *button;
+ Q_D(const QFileDialog);
+ switch (label) {
+ case LookIn:
+ return d->qFileDialogUi->lookInLabel->text();
+ case FileName:
+ return d->qFileDialogUi->fileNameLabel->text();
+ case FileType:
+ return d->qFileDialogUi->fileTypeLabel->text();
+ case Accept:
+ if (acceptMode() == AcceptOpen)
+ button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Open);
+ else
+ button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Save);
+ if (button)
+ return button->text();
+ case Reject:
+ button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Cancel);
+ if (button)
+ return button->text();
+ }
+ return QString();
+}
+
+/*
+ For the native file dialogs
+*/
+
+#if defined(Q_WS_WIN)
+extern QString qt_win_get_open_file_name(const QFileDialogArgs &args,
+ QString *initialDirectory,
+ QString *selectedFilter);
+
+extern QString qt_win_get_save_file_name(const QFileDialogArgs &args,
+ QString *initialDirectory,
+ QString *selectedFilter);
+
+extern QStringList qt_win_get_open_file_names(const QFileDialogArgs &args,
+ QString *initialDirectory,
+ QString *selectedFilter);
+
+extern QString qt_win_get_existing_directory(const QFileDialogArgs &args);
+#endif
+
+/*
+ For Symbian file dialogs
+*/
+#if defined(Q_WS_S60)
+extern QString qtSymbianGetOpenFileName(const QString &caption,
+ const QString &dir,
+ const QString &filter);
+
+extern QStringList qtSymbianGetOpenFileNames(const QString &caption,
+ const QString &dir,
+ const QString &filter);
+
+extern QString qtSymbianGetSaveFileName(const QString &caption,
+ const QString &dir);
+
+extern QString qtSymbianGetExistingDirectory(const QString &caption,
+ const QString &dir);
+#endif
+
+/*!
+ This is a convenience static function that returns an existing file
+ selected by the user. If the user presses Cancel, it returns a null string.
+
+ \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 8
+
+ The function creates a modal file dialog with the given \a parent widget.
+ If \a parent is not 0, the dialog will be shown centered over the parent
+ widget.
+
+ The file dialog's working directory will be set to \a dir. If \a dir
+ includes a file name, the file will be selected. Only files that match the
+ given \a filter are shown. The filter selected is set to \a selectedFilter.
+ The parameters \a dir, \a selectedFilter, and \a filter may be empty
+ strings. If you want multiple filters, separate them with ';;', for
+ example:
+
+ \code
+ "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)"
+ \endcode
+
+ The \a options argument holds various options about how to run the dialog,
+ see the QFileDialog::Option enum for more information on the flags you can
+ pass.
+
+ The dialog's caption is set to \a caption. If \a caption is not specified
+ then a default caption will be used.
+
+ On Windows, Mac OS X and Symbian^3, this static function will use the
+ native file dialog and not a QFileDialog.
+
+ On Windows the dialog will spin a blocking modal event loop that will not
+ dispatch any QTimers, and if \a parent is not 0 then it will position the
+ dialog just below the parent's title bar.
+
+ On Unix/X11, the normal behavior of the file dialog is to resolve and
+ follow symlinks. For example, if \c{/usr/tmp} is a symlink to \c{/var/tmp},
+ the file dialog will change to \c{/var/tmp} after entering \c{/usr/tmp}. If
+ \a options includes DontResolveSymlinks, the file dialog will treat
+ symlinks as regular directories.
+
+ On Symbian^3 the parameter \a selectedFilter has no meaning and the
+ \a options parameter is only used to define if the native file dialog is
+ used.
+
+ \warning Do not delete \a parent during the execution of the dialog. If you
+ want to do this, you should create the dialog yourself using one of the
+ QFileDialog constructors.
+
+ \sa getOpenFileNames(), getSaveFileName(), getExistingDirectory()
+*/
+QString QFileDialog::getOpenFileName(QWidget *parent,
+ const QString &caption,
+ const QString &dir,
+ const QString &filter,
+ QString *selectedFilter,
+ Options options)
+{
+ if (qt_filedialog_open_filename_hook && !(options & DontUseNativeDialog))
+ return qt_filedialog_open_filename_hook(parent, caption, dir, filter, selectedFilter, options);
+#if defined(Q_WS_S60)
+ if (QSysInfo::s60Version() > QSysInfo::SV_S60_5_0 && !(options & DontUseNativeDialog))
+ return qtSymbianGetOpenFileName(caption, dir, filter);
+#endif
+ QFileDialogArgs args;
+ args.parent = parent;
+ args.caption = caption;
+ args.directory = QFileDialogPrivate::workingDirectory(dir);
+ args.selection = QFileDialogPrivate::initialSelection(dir);
+ args.filter = filter;
+ args.mode = ExistingFile;
+ args.options = options;
+#if defined(Q_WS_WIN)
+ if (qt_use_native_dialogs && !(args.options & DontUseNativeDialog)) {
+ return qt_win_get_open_file_name(args, &(args.directory), selectedFilter);
+ }
+#endif
+
+ // create a qt dialog
+ QFileDialog dialog(args);
+ if (selectedFilter)
+ dialog.selectNameFilter(*selectedFilter);
+ if (dialog.exec() == QDialog::Accepted) {
+ if (selectedFilter)
+ *selectedFilter = dialog.selectedFilter();
+ return dialog.selectedFiles().value(0);
+ }
+ return QString();
+}
+
+/*!
+ This is a convenience static function that will return one or more existing
+ files selected by the user.
+
+ \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 9
+
+ This function creates a modal file dialog with the given \a parent widget.
+ If \a parent is not 0, the dialog will be shown centered over the parent
+ widget.
+
+ The file dialog's working directory will be set to \a dir. If \a dir
+ includes a file name, the file will be selected. The filter is set to
+ \a filter so that only those files which match the filter are shown. The
+ filter selected is set to \a selectedFilter. The parameters \a dir,
+ \a selectedFilter and \a filter may be empty strings. If you need multiple
+ filters, separate them with ';;', for instance:
+
+ \code
+ "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)"
+ \endcode
+
+ The dialog's caption is set to \a caption. If \a caption is not specified
+ then a default caption will be used.
+
+ On Windows, Mac OS X and Symbian^3, this static function will use the
+ native file dialog and not a QFileDialog.
+
+ On Windows the dialog will spin a blocking modal event loop that will not
+ dispatch any QTimers, and if \a parent is not 0 then it will position the
+ dialog just below the parent's title bar.
+
+ On Unix/X11, the normal behavior of the file dialog is to resolve and
+ follow symlinks. For example, if \c{/usr/tmp} is a symlink to \c{/var/tmp},
+ the file dialog will change to \c{/var/tmp} after entering \c{/usr/tmp}.
+ The \a options argument holds various options about how to run the dialog,
+ see the QFileDialog::Option enum for more information on the flags you can
+ pass.
+
+ \note If you want to iterate over the list of files, you should iterate
+ over a copy. For example:
+
+ \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 10
+
+ On Symbian^3 the parameter \a selectedFilter has no meaning and the
+ \a options parameter is only used to define if the native file dialog is
+ used. On Symbian^3, this function can only return a single filename.
+
+ \warning Do not delete \a parent during the execution of the dialog. If you
+ want to do this, you should create the dialog yourself using one of the
+ QFileDialog constructors.
+
+ \sa getOpenFileName(), getSaveFileName(), getExistingDirectory()
+*/
+QStringList QFileDialog::getOpenFileNames(QWidget *parent,
+ const QString &caption,
+ const QString &dir,
+ const QString &filter,
+ QString *selectedFilter,
+ Options options)
+{
+ if (qt_filedialog_open_filenames_hook && !(options & DontUseNativeDialog))
+ return qt_filedialog_open_filenames_hook(parent, caption, dir, filter, selectedFilter, options);
+#if defined(Q_WS_S60)
+ if (QSysInfo::s60Version() > QSysInfo::SV_S60_5_0 && !(options & DontUseNativeDialog))
+ return qtSymbianGetOpenFileNames(caption, dir, filter);
+#endif
+ QFileDialogArgs args;
+ args.parent = parent;
+ args.caption = caption;
+ args.directory = QFileDialogPrivate::workingDirectory(dir);
+ args.selection = QFileDialogPrivate::initialSelection(dir);
+ args.filter = filter;
+ args.mode = ExistingFiles;
+ args.options = options;
+
+#if defined(Q_WS_WIN)
+ if (qt_use_native_dialogs && !(args.options & DontUseNativeDialog)) {
+ return qt_win_get_open_file_names(args, &(args.directory), selectedFilter);
+ }
+#endif
+
+ // create a qt dialog
+ QFileDialog dialog(args);
+ if (selectedFilter)
+ dialog.selectNameFilter(*selectedFilter);
+ if (dialog.exec() == QDialog::Accepted) {
+ if (selectedFilter)
+ *selectedFilter = dialog.selectedFilter();
+ return dialog.selectedFiles();
+ }
+ return QStringList();
+}
+
+/*!
+ This is a convenience static function that will return a file name selected
+ by the user. The file does not have to exist.
+
+ It creates a modal file dialog with the given \a parent widget. If
+ \a parent is not 0, the dialog will be shown centered over the parent
+ widget.
+
+ \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 11
+
+ The file dialog's working directory will be set to \a dir. If \a dir
+ includes a file name, the file will be selected. Only files that match the
+ \a filter are shown. The filter selected is set to \a selectedFilter. The
+ parameters \a dir, \a selectedFilter, and \a filter may be empty strings.
+ Multiple filters are separated with ';;'. For instance:
+
+ \code
+ "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)"
+ \endcode
+
+ The \a options argument holds various options about how to run the dialog,
+ see the QFileDialog::Option enum for more information on the flags you can
+ pass.
+
+ The default filter can be chosen by setting \a selectedFilter to the
+ desired value.
+
+ The dialog's caption is set to \a caption. If \a caption is not specified,
+ a default caption will be used.
+
+ On Windows, Mac OS X and Symbian^3, this static function will use the
+ native file dialog and not a QFileDialog.
+
+ On Windows the dialog will spin a blocking modal event loop that will not
+ dispatch any QTimers, and if \a parent is not 0 then it will position the
+ dialog just below the parent's title bar. On Mac OS X, with its native file
+ dialog, the filter argument is ignored.
+
+ On Unix/X11, the normal behavior of the file dialog is to resolve and
+ follow symlinks. For example, if \c{/usr/tmp} is a symlink to \c{/var/tmp},
+ the file dialog will change to \c{/var/tmp} after entering \c{/usr/tmp}. If
+ \a options includes DontResolveSymlinks the file dialog will treat symlinks
+ as regular directories.
+
+ On Symbian^3 the parameters \a filter and \a selectedFilter have no
+ meaning. The \a options parameter is only used to define if the native file
+ dialog is used.
+
+ \warning Do not delete \a parent during the execution of the dialog. If you
+ want to do this, you should create the dialog yourself using one of the
+ QFileDialog constructors.
+
+ \sa getOpenFileName(), getOpenFileNames(), getExistingDirectory()
+*/
+QString QFileDialog::getSaveFileName(QWidget *parent,
+ const QString &caption,
+ const QString &dir,
+ const QString &filter,
+ QString *selectedFilter,
+ Options options)
+{
+ if (qt_filedialog_save_filename_hook && !(options & DontUseNativeDialog))
+ return qt_filedialog_save_filename_hook(parent, caption, dir, filter, selectedFilter, options);
+#if defined(Q_WS_S60)
+ if (QSysInfo::s60Version() > QSysInfo::SV_S60_5_0 && !(options & DontUseNativeDialog))
+ return qtSymbianGetSaveFileName(caption, dir);
+#endif
+ QFileDialogArgs args;
+ args.parent = parent;
+ args.caption = caption;
+ args.directory = QFileDialogPrivate::workingDirectory(dir);
+ args.selection = QFileDialogPrivate::initialSelection(dir);
+ args.filter = filter;
+ args.mode = AnyFile;
+ args.options = options;
+
+#if defined(Q_WS_WIN)
+ if (qt_use_native_dialogs && !(args.options & DontUseNativeDialog)) {
+ return qt_win_get_save_file_name(args, &(args.directory), selectedFilter);
+ }
+#endif
+
+ // create a qt dialog
+ QFileDialog dialog(args);
+ dialog.setAcceptMode(AcceptSave);
+ if (selectedFilter)
+ dialog.selectNameFilter(*selectedFilter);
+ if (dialog.exec() == QDialog::Accepted) {
+ if (selectedFilter)
+ *selectedFilter = dialog.selectedFilter();
+ return dialog.selectedFiles().value(0);
+ }
+
+ return QString();
+}
+
+/*!
+ This is a convenience static function that will return an existing
+ directory selected by the user.
+
+ \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 12
+
+ This function creates a modal file dialog with the given \a parent widget.
+ If \a parent is not 0, the dialog will be shown centered over the parent
+ widget.
+
+ The dialog's working directory is set to \a dir, and the caption is set to
+ \a caption. Either of these may be an empty string in which case the
+ current directory and a default caption will be used respectively.
+
+ The \a options argument holds various options about how to run the dialog,
+ see the QFileDialog::Option enum for more information on the flags you can
+ pass. To ensure a native file dialog, \l{QFileDialog::}{ShowDirsOnly} must
+ be set.
+
+ On Windows, Mac OS X and Symbian^3, this static function will use the
+ native file dialog and not a QFileDialog. On Windows CE, if the device has
+ no native file dialog, a QFileDialog will be used.
+
+ On Unix/X11, the normal behavior of the file dialog is to resolve and
+ follow symlinks. For example, if \c{/usr/tmp} is a symlink to \c{/var/tmp},
+ the file dialog will change to \c{/var/tmp} after entering \c{/usr/tmp}. If
+ \a options includes DontResolveSymlinks, the file dialog will treat
+ symlinks as regular directories.
+
+ On Windows the dialog will spin a blocking modal event loop that will not
+ dispatch any QTimers, and if \a parent is not 0 then it will position the
+ dialog just below the parent's title bar.
+
+ On Symbian^3 the \a options parameter is only used to define if the native
+ file dialog is used.
+
+ \warning Do not delete \a parent during the execution of the dialog. If you
+ want to do this, you should create the dialog yourself using one of the
+ QFileDialog constructors.
+
+ \sa getOpenFileName(), getOpenFileNames(), getSaveFileName()
+*/
+QString QFileDialog::getExistingDirectory(QWidget *parent,
+ const QString &caption,
+ const QString &dir,
+ Options options)
+{
+ if (qt_filedialog_existing_directory_hook && !(options & DontUseNativeDialog))
+ return qt_filedialog_existing_directory_hook(parent, caption, dir, options);
+#if defined(Q_WS_S60)
+ if (QSysInfo::s60Version() > QSysInfo::SV_S60_5_0 && !(options & DontUseNativeDialog))
+ return qtSymbianGetExistingDirectory(caption, dir);
+#endif
+ QFileDialogArgs args;
+ args.parent = parent;
+ args.caption = caption;
+ args.directory = QFileDialogPrivate::workingDirectory(dir);
+ args.mode = (options & ShowDirsOnly ? DirectoryOnly : Directory);
+ args.options = options;
+
+#if defined(Q_WS_WIN)
+ if (qt_use_native_dialogs && !(args.options & DontUseNativeDialog) && (options & ShowDirsOnly)
+#if defined(Q_WS_WINCE)
+ && qt_priv_ptr_valid
+#endif
+ ) {
+ return qt_win_get_existing_directory(args);
+ }
+#endif
+
+ // create a qt dialog
+ QFileDialog dialog(args);
+ if (dialog.exec() == QDialog::Accepted) {
+ return dialog.selectedFiles().value(0);
+ }
+ return QString();
+}
+
+inline static QString _qt_get_directory(const QString &path)
+{
+ QFileInfo info = QFileInfo(QDir::current(), path);
+ if (info.exists() && info.isDir())
+ return QDir::cleanPath(info.absoluteFilePath());
+ info.setFile(info.absolutePath());
+ if (info.exists() && info.isDir())
+ return info.absoluteFilePath();
+ return QString();
+}
+/*
+ Get the initial directory path
+
+ \sa initialSelection()
+ */
+QString QFileDialogPrivate::workingDirectory(const QString &path)
+{
+ if (!path.isEmpty()) {
+ QString directory = _qt_get_directory(path);
+ if (!directory.isEmpty())
+ return directory;
+ }
+ QString directory = _qt_get_directory(*lastVisitedDir());
+ if (!directory.isEmpty())
+ return directory;
+ return QDir::currentPath();
+}
+
+/*
+ Get the initial selection given a path. The initial directory
+ can contain both the initial directory and initial selection
+ /home/user/foo.txt
+
+ \sa workingDirectory()
+ */
+QString QFileDialogPrivate::initialSelection(const QString &path)
+{
+ if (!path.isEmpty()) {
+ QFileInfo info(path);
+ if (!info.isDir())
+ return info.fileName();
+ }
+ return QString();
+}
+
+/*!
+ \reimp
+*/
+void QFileDialog::done(int result)
+{
+ Q_D(QFileDialog);
+
+ QDialog::done(result);
+
+ if (d->receiverToDisconnectOnClose) {
+ disconnect(this, d->signalToDisconnectOnClose,
+ d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);
+ d->receiverToDisconnectOnClose = 0;
+ }
+ d->memberToDisconnectOnClose.clear();
+ d->signalToDisconnectOnClose.clear();
+}
+
+/*!
+ \reimp
+*/
+void QFileDialog::accept()
+{
+ Q_D(QFileDialog);
+ QStringList files = selectedFiles();
+ if (files.isEmpty())
+ return;
+ if (d->nativeDialogInUse){
+ d->emitFilesSelected(files);
+ QDialog::accept();
+ return;
+ }
+
+ QString lineEditText = d->lineEdit()->text();
+ // "hidden feature" type .. and then enter, and it will move up a dir
+ // special case for ".."
+ if (lineEditText == QLatin1String("..")) {
+ d->_q_navigateToParent();
+ bool block = d->qFileDialogUi->fileNameEdit->blockSignals(true);
+ d->lineEdit()->selectAll();
+ d->qFileDialogUi->fileNameEdit->blockSignals(block);
+ return;
+ }
+
+ switch (d->fileMode) {
+ case DirectoryOnly:
+ case Directory: {
+ QString fn = files.first();
+ QFileInfo info(fn);
+ if (!info.exists())
+ info = QFileInfo(d->getEnvironmentVariable(fn));
+ if (!info.exists()) {
+#ifndef QT_NO_MESSAGEBOX
+ QString message = tr("%1\nDirectory not found.\nPlease verify the "
+ "correct directory name was given.");
+ QMessageBox::warning(this, windowTitle(), message.arg(info.fileName()));
+#endif // QT_NO_MESSAGEBOX
+ return;
+ }
+ if (info.isDir()) {
+ d->emitFilesSelected(files);
+ QDialog::accept();
+ }
+ return;
+ }
+
+ case AnyFile: {
+ QString fn = files.first();
+ QFileInfo info(fn);
+ if (info.isDir()) {
+ setDirectory(info.absoluteFilePath());
+ return;
+ }
+
+ if (!info.exists()) {
+ int maxNameLength = d->maxNameLength(info.path());
+ if (maxNameLength >= 0 && info.fileName().length() > maxNameLength)
+ return;
+ }
+
+ // check if we have to ask for permission to overwrite the file
+ if (!info.exists() || !confirmOverwrite() || acceptMode() == AcceptOpen) {
+ d->emitFilesSelected(QStringList(fn));
+ QDialog::accept();
+#ifndef QT_NO_MESSAGEBOX
+ } else {
+ if (QMessageBox::warning(this, windowTitle(),
+ tr("%1 already exists.\nDo you want to replace it?")
+ .arg(info.fileName()),
+ QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
+ == QMessageBox::Yes) {
+ d->emitFilesSelected(QStringList(fn));
+ QDialog::accept();
+ }
+#endif
+ }
+ return;
+ }
+
+ case ExistingFile:
+ case ExistingFiles:
+ for (int i = 0; i < files.count(); ++i) {
+ QFileInfo info(files.at(i));
+ if (!info.exists())
+ info = QFileInfo(d->getEnvironmentVariable(files.at(i)));
+ if (!info.exists()) {
+#ifndef QT_NO_MESSAGEBOX
+ QString message = tr("%1\nFile not found.\nPlease verify the "
+ "correct file name was given.");
+ QMessageBox::warning(this, windowTitle(), message.arg(info.fileName()));
+#endif // QT_NO_MESSAGEBOX
+ return;
+ }
+ if (info.isDir()) {
+ setDirectory(info.absoluteFilePath());
+ d->lineEdit()->clear();
+ return;
+ }
+ }
+ d->emitFilesSelected(files);
+ QDialog::accept();
+ return;
+ }
+}
+
+/*!
+ \internal
+
+ Create widgets, layout and set default values
+*/
+void QFileDialogPrivate::init(const QString &directory, const QString &nameFilter,
+ const QString &caption)
+{
+ Q_Q(QFileDialog);
+ if (!caption.isEmpty()) {
+ useDefaultCaption = false;
+ setWindowTitle = caption;
+ q->setWindowTitle(caption);
+ }
+
+ createWidgets();
+ createMenuActions();
+ retranslateStrings();
+ q->setFileMode(fileMode);
+
+#ifndef QT_NO_SETTINGS
+ QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
+ settings.beginGroup(QLatin1String("Qt"));
+ if (!directory.isEmpty())
+ setLastVisitedDirectory(workingDirectory(directory));
+ q->restoreState(settings.value(QLatin1String("filedialog")).toByteArray());
+#endif
+
+#if defined(Q_EMBEDDED_SMALLSCREEN)
+ qFileDialogUi->lookInLabel->setVisible(false);
+ qFileDialogUi->fileNameLabel->setVisible(false);
+ qFileDialogUi->fileTypeLabel->setVisible(false);
+ qFileDialogUi->sidebar->hide();
+#endif
+ // Default case
+ if (!nameFilter.isEmpty())
+ q->setNameFilter(nameFilter);
+ q->setAcceptMode(QFileDialog::AcceptOpen);
+ q->setDirectory(workingDirectory(directory));
+ q->selectFile(initialSelection(directory));
+
+ _q_updateOkButton();
+ q->resize(q->sizeHint());
+}
+
+/*!
+ \internal
+
+ Create the widgets, set properties and connections
+*/
+void QFileDialogPrivate::createWidgets()
+{
+ Q_Q(QFileDialog);
+ model = new QFileSystemModel(q);
+ model->setObjectName(QLatin1String("qt_filesystem_model"));
+#ifdef Q_WS_MAC
+ model->setNameFilterDisables(true);
+#else
+ model->setNameFilterDisables(false);
+#endif
+ model->d_func()->disableRecursiveSort = true;
+ QFileDialog::connect(model, SIGNAL(fileRenamed(QString,QString,QString)), q, SLOT(_q_fileRenamed(QString,QString,QString)));
+ QFileDialog::connect(model, SIGNAL(rootPathChanged(QString)),
+ q, SLOT(_q_pathChanged(QString)));
+ QFileDialog::connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
+ q, SLOT(_q_rowsInserted(QModelIndex)));
+ model->setReadOnly(false);
+
+ qFileDialogUi.reset(new Ui_QFileDialog());
+ qFileDialogUi->setupUi(q);
+
+ QList<QUrl> initialBookmarks;
+ initialBookmarks << QUrl::fromLocalFile(QLatin1String(""))
+ << QUrl::fromLocalFile(QDir::homePath());
+ qFileDialogUi->sidebar->init(model, initialBookmarks);
+ QFileDialog::connect(qFileDialogUi->sidebar, SIGNAL(goToUrl(QUrl)),
+ q, SLOT(_q_goToUrl(QUrl)));
+
+ QObject::connect(qFileDialogUi->buttonBox, SIGNAL(accepted()), q, SLOT(accept()));
+ QObject::connect(qFileDialogUi->buttonBox, SIGNAL(rejected()), q, SLOT(reject()));
+
+
+ qFileDialogUi->lookInCombo->init(this);
+ QObject::connect(qFileDialogUi->lookInCombo, SIGNAL(activated(QString)), q, SLOT(_q_goToDirectory(QString)));
+
+ qFileDialogUi->lookInCombo->setInsertPolicy(QComboBox::NoInsert);
+ qFileDialogUi->lookInCombo->setDuplicatesEnabled(false);
+
+ // filename
+ qFileDialogUi->fileNameEdit->init(this);
+#ifndef QT_NO_SHORTCUT
+ qFileDialogUi->fileNameLabel->setBuddy(qFileDialogUi->fileNameEdit);
+#endif
+#ifndef QT_NO_FSCOMPLETER
+ completer = new QFSCompleter(model, q);
+ qFileDialogUi->fileNameEdit->setCompleter(completer);
+#endif // QT_NO_FSCOMPLETER
+ QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(textChanged(QString)),
+ q, SLOT(_q_autoCompleteFileName(QString)));
+ QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(textChanged(QString)),
+ q, SLOT(_q_updateOkButton()));
+
+ QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(returnPressed()), q, SLOT(accept()));
+
+ // filetype
+ qFileDialogUi->fileTypeCombo->setDuplicatesEnabled(false);
+ qFileDialogUi->fileTypeCombo->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength);
+ qFileDialogUi->fileTypeCombo->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ QObject::connect(qFileDialogUi->fileTypeCombo, SIGNAL(activated(int)),
+ q, SLOT(_q_useNameFilter(int)));
+ QObject::connect(qFileDialogUi->fileTypeCombo, SIGNAL(activated(QString)),
+ q, SIGNAL(filterSelected(QString)));
+
+ qFileDialogUi->listView->init(this);
+ qFileDialogUi->listView->setModel(model);
+ QObject::connect(qFileDialogUi->listView, SIGNAL(activated(QModelIndex)),
+ q, SLOT(_q_enterDirectory(QModelIndex)));
+ QObject::connect(qFileDialogUi->listView, SIGNAL(customContextMenuRequested(QPoint)),
+ q, SLOT(_q_showContextMenu(QPoint)));
+#ifndef QT_NO_SHORTCUT
+ QShortcut *shortcut = new QShortcut(qFileDialogUi->listView);
+ shortcut->setKey(QKeySequence(QLatin1String("Delete")));
+ QObject::connect(shortcut, SIGNAL(activated()), q, SLOT(_q_deleteCurrent()));
+#endif
+
+ qFileDialogUi->treeView->init(this);
+ qFileDialogUi->treeView->setModel(model);
+ QHeaderView *treeHeader = qFileDialogUi->treeView->header();
+ QFontMetrics fm(q->font());
+ treeHeader->resizeSection(0, fm.width(QLatin1String("wwwwwwwwwwwwwwwwwwwwwwwwww")));
+ treeHeader->resizeSection(1, fm.width(QLatin1String("128.88 GB")));
+ treeHeader->resizeSection(2, fm.width(QLatin1String("mp3Folder")));
+ treeHeader->resizeSection(3, fm.width(QLatin1String("10/29/81 02:02PM")));
+ treeHeader->setContextMenuPolicy(Qt::ActionsContextMenu);
+
+ QActionGroup *showActionGroup = new QActionGroup(q);
+ showActionGroup->setExclusive(false);
+ QObject::connect(showActionGroup, SIGNAL(triggered(QAction*)),
+ q, SLOT(_q_showHeader(QAction*)));;
+
+ QAbstractItemModel *abstractModel = model;
+#ifndef QT_NO_PROXYMODEL
+ if (proxyModel)
+ abstractModel = proxyModel;
+#endif
+ for (int i = 1; i < abstractModel->columnCount(QModelIndex()); ++i) {
+ QAction *showHeader = new QAction(showActionGroup);
+ showHeader->setCheckable(true);
+ showHeader->setChecked(true);
+ treeHeader->addAction(showHeader);
+ }
+
+ QScopedPointer<QItemSelectionModel> selModel(qFileDialogUi->treeView->selectionModel());
+ qFileDialogUi->treeView->setSelectionModel(qFileDialogUi->listView->selectionModel());
+
+ QObject::connect(qFileDialogUi->treeView, SIGNAL(activated(QModelIndex)),
+ q, SLOT(_q_enterDirectory(QModelIndex)));
+ QObject::connect(qFileDialogUi->treeView, SIGNAL(customContextMenuRequested(QPoint)),
+ q, SLOT(_q_showContextMenu(QPoint)));
+#ifndef QT_NO_SHORTCUT
+ shortcut = new QShortcut(qFileDialogUi->treeView);
+ shortcut->setKey(QKeySequence(QLatin1String("Delete")));
+ QObject::connect(shortcut, SIGNAL(activated()), q, SLOT(_q_deleteCurrent()));
+#endif
+
+ // Selections
+ QItemSelectionModel *selections = qFileDialogUi->listView->selectionModel();
+ QObject::connect(selections, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
+ q, SLOT(_q_selectionChanged()));
+ QObject::connect(selections, SIGNAL(currentChanged(QModelIndex,QModelIndex)),
+ q, SLOT(_q_currentChanged(QModelIndex)));
+ qFileDialogUi->splitter->setStretchFactor(qFileDialogUi->splitter->indexOf(qFileDialogUi->splitter->widget(1)), QSizePolicy::Expanding);
+
+ createToolButtons();
+}
+
+void QFileDialogPrivate::_q_showHeader(QAction *action)
+{
+ Q_Q(QFileDialog);
+ QActionGroup *actionGroup = qobject_cast<QActionGroup*>(q->sender());
+ qFileDialogUi->treeView->header()->setSectionHidden(actionGroup->actions().indexOf(action) + 1, !action->isChecked());
+}
+
+#ifndef QT_NO_PROXYMODEL
+/*!
+ \since 4.3
+
+ Sets the model for the views to the given \a proxyModel. This is useful if you
+ want to modify the underlying model; for example, to add columns, filter
+ data or add drives.
+
+ Any existing proxy model will be removed, but not deleted. The file dialog
+ will take ownership of the \a proxyModel.
+
+ \sa proxyModel()
+*/
+void QFileDialog::setProxyModel(QAbstractProxyModel *proxyModel)
+{
+ Q_D(QFileDialog);
+ if ((!proxyModel && !d->proxyModel)
+ || (proxyModel == d->proxyModel))
+ return;
+
+ QModelIndex idx = d->rootIndex();
+ if (d->proxyModel) {
+ disconnect(d->proxyModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
+ this, SLOT(_q_rowsInserted(QModelIndex)));
+ } else {
+ disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
+ this, SLOT(_q_rowsInserted(QModelIndex)));
+ }
+
+ if (proxyModel != 0) {
+ proxyModel->setParent(this);
+ d->proxyModel = proxyModel;
+ proxyModel->setSourceModel(d->model);
+ d->qFileDialogUi->listView->setModel(d->proxyModel);
+ d->qFileDialogUi->treeView->setModel(d->proxyModel);
+#ifndef QT_NO_FSCOMPLETER
+ d->completer->setModel(d->proxyModel);
+ d->completer->proxyModel = d->proxyModel;
+#endif
+ connect(d->proxyModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
+ this, SLOT(_q_rowsInserted(QModelIndex)));
+ } else {
+ d->proxyModel = 0;
+ d->qFileDialogUi->listView->setModel(d->model);
+ d->qFileDialogUi->treeView->setModel(d->model);
+#ifndef QT_NO_FSCOMPLETER
+ d->completer->setModel(d->model);
+ d->completer->sourceModel = d->model;
+ d->completer->proxyModel = 0;
+#endif
+ connect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
+ this, SLOT(_q_rowsInserted(QModelIndex)));
+ }
+ QScopedPointer<QItemSelectionModel> selModel(d->qFileDialogUi->treeView->selectionModel());
+ d->qFileDialogUi->treeView->setSelectionModel(d->qFileDialogUi->listView->selectionModel());
+
+ d->setRootIndex(idx);
+
+ // reconnect selection
+ QItemSelectionModel *selections = d->qFileDialogUi->listView->selectionModel();
+ QObject::connect(selections, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
+ this, SLOT(_q_selectionChanged()));
+ QObject::connect(selections, SIGNAL(currentChanged(QModelIndex,QModelIndex)),
+ this, SLOT(_q_currentChanged(QModelIndex)));
+}
+
+/*!
+ Returns the proxy model used by the file dialog. By default no proxy is set.
+
+ \sa setProxyModel()
+*/
+QAbstractProxyModel *QFileDialog::proxyModel() const
+{
+ Q_D(const QFileDialog);
+ return d->proxyModel;
+}
+#endif // QT_NO_PROXYMODEL
+
+/*!
+ \internal
+
+ Create tool buttons, set properties and connections
+*/
+void QFileDialogPrivate::createToolButtons()
+{
+ Q_Q(QFileDialog);
+ qFileDialogUi->backButton->setIcon(q->style()->standardIcon(QStyle::SP_ArrowBack, 0, q));
+ qFileDialogUi->backButton->setAutoRaise(true);
+ qFileDialogUi->backButton->setEnabled(false);
+ QObject::connect(qFileDialogUi->backButton, SIGNAL(clicked()), q, SLOT(_q_navigateBackward()));
+
+ qFileDialogUi->forwardButton->setIcon(q->style()->standardIcon(QStyle::SP_ArrowForward, 0, q));
+ qFileDialogUi->forwardButton->setAutoRaise(true);
+ qFileDialogUi->forwardButton->setEnabled(false);
+ QObject::connect(qFileDialogUi->forwardButton, SIGNAL(clicked()), q, SLOT(_q_navigateForward()));
+
+ qFileDialogUi->toParentButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogToParent, 0, q));
+ qFileDialogUi->toParentButton->setAutoRaise(true);
+ qFileDialogUi->toParentButton->setEnabled(false);
+ QObject::connect(qFileDialogUi->toParentButton, SIGNAL(clicked()), q, SLOT(_q_navigateToParent()));
+
+ qFileDialogUi->listModeButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogListView, 0, q));
+ qFileDialogUi->listModeButton->setAutoRaise(true);
+ qFileDialogUi->listModeButton->setDown(true);
+ QObject::connect(qFileDialogUi->listModeButton, SIGNAL(clicked()), q, SLOT(_q_showListView()));
+
+ qFileDialogUi->detailModeButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogDetailedView, 0, q));
+ qFileDialogUi->detailModeButton->setAutoRaise(true);
+ QObject::connect(qFileDialogUi->detailModeButton, SIGNAL(clicked()), q, SLOT(_q_showDetailsView()));
+
+ QSize toolSize(qFileDialogUi->fileNameEdit->sizeHint().height(), qFileDialogUi->fileNameEdit->sizeHint().height());
+ qFileDialogUi->backButton->setFixedSize(toolSize);
+ qFileDialogUi->listModeButton->setFixedSize(toolSize);
+ qFileDialogUi->detailModeButton->setFixedSize(toolSize);
+ qFileDialogUi->forwardButton->setFixedSize(toolSize);
+ qFileDialogUi->toParentButton->setFixedSize(toolSize);
+
+ qFileDialogUi->newFolderButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogNewFolder, 0, q));
+ qFileDialogUi->newFolderButton->setFixedSize(toolSize);
+ qFileDialogUi->newFolderButton->setAutoRaise(true);
+ qFileDialogUi->newFolderButton->setEnabled(false);
+ QObject::connect(qFileDialogUi->newFolderButton, SIGNAL(clicked()), q, SLOT(_q_createDirectory()));
+}
+
+/*!
+ \internal
+
+ Create actions which will be used in the right click.
+*/
+void QFileDialogPrivate::createMenuActions()
+{
+ Q_Q(QFileDialog);
+
+ QAction *goHomeAction = new QAction(q);
+#ifndef QT_NO_SHORTCUT
+ goHomeAction->setShortcut(Qt::CTRL + Qt::Key_H + Qt::SHIFT);
+#endif
+ QObject::connect(goHomeAction, SIGNAL(triggered()), q, SLOT(_q_goHome()));
+ q->addAction(goHomeAction);
+
+ // ### TODO add Desktop & Computer actions
+
+ QAction *goToParent = new QAction(q);
+ goToParent->setObjectName(QLatin1String("qt_goto_parent_action"));
+#ifndef QT_NO_SHORTCUT
+ goToParent->setShortcut(Qt::CTRL + Qt::UpArrow);
+#endif
+ QObject::connect(goToParent, SIGNAL(triggered()), q, SLOT(_q_navigateToParent()));
+ q->addAction(goToParent);
+
+ renameAction = new QAction(q);
+ renameAction->setEnabled(false);
+ renameAction->setObjectName(QLatin1String("qt_rename_action"));
+ QObject::connect(renameAction, SIGNAL(triggered()), q, SLOT(_q_renameCurrent()));
+
+ deleteAction = new QAction(q);
+ deleteAction->setEnabled(false);
+ deleteAction->setObjectName(QLatin1String("qt_delete_action"));
+ QObject::connect(deleteAction, SIGNAL(triggered()), q, SLOT(_q_deleteCurrent()));
+
+ showHiddenAction = new QAction(q);
+ showHiddenAction->setObjectName(QLatin1String("qt_show_hidden_action"));
+ showHiddenAction->setCheckable(true);
+ QObject::connect(showHiddenAction, SIGNAL(triggered()), q, SLOT(_q_showHidden()));
+
+ newFolderAction = new QAction(q);
+ newFolderAction->setObjectName(QLatin1String("qt_new_folder_action"));
+ QObject::connect(newFolderAction, SIGNAL(triggered()), q, SLOT(_q_createDirectory()));
+}
+
+void QFileDialogPrivate::_q_goHome()
+{
+ Q_Q(QFileDialog);
+ q->setDirectory(QDir::homePath());
+}
+
+/*!
+ \internal
+
+ Update history with new path, buttons, and combo
+*/
+void QFileDialogPrivate::_q_pathChanged(const QString &newPath)
+{
+ Q_Q(QFileDialog);
+ QDir dir(model->rootDirectory());
+ qFileDialogUi->toParentButton->setEnabled(dir.exists());
+ qFileDialogUi->sidebar->selectUrl(QUrl::fromLocalFile(newPath));
+ q->setHistory(qFileDialogUi->lookInCombo->history());
+
+ if (currentHistoryLocation < 0 || currentHistory.value(currentHistoryLocation) != QDir::toNativeSeparators(newPath)) {
+ while (currentHistoryLocation >= 0 && currentHistoryLocation + 1 < currentHistory.count()) {
+ currentHistory.removeLast();
+ }
+ currentHistory.append(QDir::toNativeSeparators(newPath));
+ ++currentHistoryLocation;
+ }
+ qFileDialogUi->forwardButton->setEnabled(currentHistory.size() - currentHistoryLocation > 1);
+ qFileDialogUi->backButton->setEnabled(currentHistoryLocation > 0);
+}
+
+/*!
+ \internal
+
+ Navigates to the last directory viewed in the dialog.
+*/
+void QFileDialogPrivate::_q_navigateBackward()
+{
+ Q_Q(QFileDialog);
+ if (!currentHistory.isEmpty() && currentHistoryLocation > 0) {
+ --currentHistoryLocation;
+ QString previousHistory = currentHistory.at(currentHistoryLocation);
+ q->setDirectory(previousHistory);
+ }
+}
+
+/*!
+ \internal
+
+ Navigates to the last directory viewed in the dialog.
+*/
+void QFileDialogPrivate::_q_navigateForward()
+{
+ Q_Q(QFileDialog);
+ if (!currentHistory.isEmpty() && currentHistoryLocation < currentHistory.size() - 1) {
+ ++currentHistoryLocation;
+ QString nextHistory = currentHistory.at(currentHistoryLocation);
+ q->setDirectory(nextHistory);
+ }
+}
+
+/*!
+ \internal
+
+ Navigates to the parent directory of the currently displayed directory
+ in the dialog.
+*/
+void QFileDialogPrivate::_q_navigateToParent()
+{
+ Q_Q(QFileDialog);
+ QDir dir(model->rootDirectory());
+ QString newDirectory;
+ if (dir.isRoot()) {
+ newDirectory = model->myComputer().toString();
+ } else {
+ dir.cdUp();
+ newDirectory = dir.absolutePath();
+ }
+ q->setDirectory(newDirectory);
+ emit q->directoryEntered(newDirectory);
+}
+
+/*!
+ \internal
+
+ Creates a new directory, first asking the user for a suitable name.
+*/
+void QFileDialogPrivate::_q_createDirectory()
+{
+ Q_Q(QFileDialog);
+ qFileDialogUi->listView->clearSelection();
+
+ QString newFolderString = QFileDialog::tr("New Folder");
+ QString folderName = newFolderString;
+ QString prefix = q->directory().absolutePath() + QDir::separator();
+ if (QFile::exists(prefix + folderName)) {
+ qlonglong suffix = 2;
+ while (QFile::exists(prefix + folderName)) {
+ folderName = newFolderString + QString::number(suffix++);
+ }
+ }
+
+ QModelIndex parent = rootIndex();
+ QModelIndex index = model->mkdir(parent, folderName);
+ if (!index.isValid())
+ return;
+
+ index = select(index);
+ if (index.isValid()) {
+ qFileDialogUi->treeView->setCurrentIndex(index);
+ currentView()->edit(index);
+ }
+}
+
+void QFileDialogPrivate::_q_showListView()
+{
+ qFileDialogUi->listModeButton->setDown(true);
+ qFileDialogUi->detailModeButton->setDown(false);
+ qFileDialogUi->treeView->hide();
+ qFileDialogUi->listView->show();
+ qFileDialogUi->stackedWidget->setCurrentWidget(qFileDialogUi->listView->parentWidget());
+ qFileDialogUi->listView->doItemsLayout();
+}
+
+void QFileDialogPrivate::_q_showDetailsView()
+{
+ qFileDialogUi->listModeButton->setDown(false);
+ qFileDialogUi->detailModeButton->setDown(true);
+ qFileDialogUi->listView->hide();
+ qFileDialogUi->treeView->show();
+ qFileDialogUi->stackedWidget->setCurrentWidget(qFileDialogUi->treeView->parentWidget());
+ qFileDialogUi->treeView->doItemsLayout();
+}
+
+/*!
+ \internal
+
+ Show the context menu for the file/dir under position
+*/
+void QFileDialogPrivate::_q_showContextMenu(const QPoint &position)
+{
+#ifdef QT_NO_MENU
+ Q_UNUSED(position);
+#else
+ Q_Q(QFileDialog);
+ QAbstractItemView *view = 0;
+ if (q->viewMode() == QFileDialog::Detail)
+ view = qFileDialogUi->treeView;
+ else
+ view = qFileDialogUi->listView;
+ QModelIndex index = view->indexAt(position);
+ index = mapToSource(index.sibling(index.row(), 0));
+
+ QMenu menu(view);
+ if (index.isValid()) {
+ // file context menu
+ QFile::Permissions p(index.parent().data(QFileSystemModel::FilePermissions).toInt());
+ renameAction->setEnabled(p & QFile::WriteUser);
+ menu.addAction(renameAction);
+ deleteAction->setEnabled(p & QFile::WriteUser);
+ menu.addAction(deleteAction);
+ menu.addSeparator();
+ }
+ menu.addAction(showHiddenAction);
+ if (qFileDialogUi->newFolderButton->isVisible()) {
+ newFolderAction->setEnabled(qFileDialogUi->newFolderButton->isEnabled());
+ menu.addAction(newFolderAction);
+ }
+ menu.exec(view->viewport()->mapToGlobal(position));
+#endif // QT_NO_MENU
+}
+
+/*!
+ \internal
+*/
+void QFileDialogPrivate::_q_renameCurrent()
+{
+ Q_Q(QFileDialog);
+ QModelIndex index = qFileDialogUi->listView->currentIndex();
+ index = index.sibling(index.row(), 0);
+ if (q->viewMode() == QFileDialog::List)
+ qFileDialogUi->listView->edit(index);
+ else
+ qFileDialogUi->treeView->edit(index);
+}
+
+bool QFileDialogPrivate::removeDirectory(const QString &path)
+{
+ QModelIndex modelIndex = model->index(path);
+ return model->remove(modelIndex);
+}
+
+/*!
+ \internal
+
+ Deletes the currently selected item in the dialog.
+*/
+void QFileDialogPrivate::_q_deleteCurrent()
+{
+ if (model->isReadOnly())
+ return;
+
+ QModelIndexList list = qFileDialogUi->listView->selectionModel()->selectedRows();
+ for (int i = list.count() - 1; i >= 0; --i) {
+ QModelIndex index = list.at(i);
+ if (index == qFileDialogUi->listView->rootIndex())
+ continue;
+
+ index = mapToSource(index.sibling(index.row(), 0));
+ if (!index.isValid())
+ continue;
+
+ QString fileName = index.data(QFileSystemModel::FileNameRole).toString();
+ QString filePath = index.data(QFileSystemModel::FilePathRole).toString();
+ bool isDir = model->isDir(index);
+
+ QFile::Permissions p(index.parent().data(QFileSystemModel::FilePermissions).toInt());
+#ifndef QT_NO_MESSAGEBOX
+ Q_Q(QFileDialog);
+ if (!(p & QFile::WriteUser) && (QMessageBox::warning(q_func(), q_func()->windowTitle(),
+ QFileDialog::tr("'%1' is write protected.\nDo you want to delete it anyway?")
+ .arg(fileName),
+ QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No))
+ return;
+ else if (QMessageBox::warning(q_func(), q_func()->windowTitle(),
+ QFileDialog::tr("Are sure you want to delete '%1'?")
+ .arg(fileName),
+ QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No)
+ return;
+
+#else
+ if (!(p & QFile::WriteUser))
+ return;
+#endif // QT_NO_MESSAGEBOX
+
+ // the event loop has run, we can NOT reuse index because the model might have removed it.
+ if (isDir) {
+ if (!removeDirectory(filePath)) {
+#ifndef QT_NO_MESSAGEBOX
+ QMessageBox::warning(q, q->windowTitle(),
+ QFileDialog::tr("Could not delete directory."));
+#endif
+ }
+ } else {
+ model->remove(index);
+ }
+ }
+}
+
+void QFileDialogPrivate::_q_autoCompleteFileName(const QString &text)
+{
+ if (text.startsWith(QLatin1String("//")) || text.startsWith(QLatin1Char('\\'))) {
+ qFileDialogUi->listView->selectionModel()->clearSelection();
+ return;
+ }
+
+ QStringList multipleFiles = typedFiles();
+ if (multipleFiles.count() > 0) {
+ QModelIndexList oldFiles = qFileDialogUi->listView->selectionModel()->selectedRows();
+ QModelIndexList newFiles;
+ for (int i = 0; i < multipleFiles.count(); ++i) {
+ QModelIndex idx = model->index(multipleFiles.at(i));
+ if (oldFiles.contains(idx))
+ oldFiles.removeAll(idx);
+ else
+ newFiles.append(idx);
+ }
+ for (int i = 0; i < newFiles.count(); ++i)
+ select(newFiles.at(i));
+ if (lineEdit()->hasFocus())
+ for (int i = 0; i < oldFiles.count(); ++i)
+ qFileDialogUi->listView->selectionModel()->select(oldFiles.at(i),
+ QItemSelectionModel::Toggle | QItemSelectionModel::Rows);
+ }
+}
+
+/*!
+ \internal
+*/
+void QFileDialogPrivate::_q_updateOkButton()
+{
+ Q_Q(QFileDialog);
+ QPushButton *button = qFileDialogUi->buttonBox->button((acceptMode == QFileDialog::AcceptOpen)
+ ? QDialogButtonBox::Open : QDialogButtonBox::Save);
+ if (!button)
+ return;
+
+ bool enableButton = true;
+ bool isOpenDirectory = false;
+
+ QStringList files = q->selectedFiles();
+ QString lineEditText = lineEdit()->text();
+
+ if (lineEditText.startsWith(QLatin1String("//")) || lineEditText.startsWith(QLatin1Char('\\'))) {
+ button->setEnabled(true);
+ if (acceptMode == QFileDialog::AcceptSave)
+ button->setText(acceptLabel);
+ return;
+ }
+
+ if (files.isEmpty()) {
+ enableButton = false;
+ } else if (lineEditText == QLatin1String("..")) {
+ isOpenDirectory = true;
+ } else {
+ switch (fileMode) {
+ case QFileDialog::DirectoryOnly:
+ case QFileDialog::Directory: {
+ QString fn = files.first();
+ QModelIndex idx = model->index(fn);
+ if (!idx.isValid())
+ idx = model->index(getEnvironmentVariable(fn));
+ if (!idx.isValid() || !model->isDir(idx))
+ enableButton = false;
+ break;
+ }
+ case QFileDialog::AnyFile: {
+ QString fn = files.first();
+ QFileInfo info(fn);
+ QModelIndex idx = model->index(fn);
+ QString fileDir;
+ QString fileName;
+ if (info.isDir()) {
+ fileDir = info.canonicalFilePath();
+ } else {
+ fileDir = fn.mid(0, fn.lastIndexOf(QLatin1Char('/')));
+ fileName = fn.mid(fileDir.length() + 1);
+ }
+ if (lineEditText.contains(QLatin1String(".."))) {
+ fileDir = info.canonicalFilePath();
+ fileName = info.fileName();
+ }
+
+ if (fileDir == q->directory().canonicalPath() && fileName.isEmpty()) {
+ enableButton = false;
+ break;
+ }
+ if (idx.isValid() && model->isDir(idx)) {
+ isOpenDirectory = true;
+ enableButton = true;
+ break;
+ }
+ if (!idx.isValid()) {
+ int maxLength = maxNameLength(fileDir);
+ enableButton = maxLength < 0 || fileName.length() <= maxLength;
+ }
+ break;
+ }
+ case QFileDialog::ExistingFile:
+ case QFileDialog::ExistingFiles:
+ for (int i = 0; i < files.count(); ++i) {
+ QModelIndex idx = model->index(files.at(i));
+ if (!idx.isValid())
+ idx = model->index(getEnvironmentVariable(files.at(i)));
+ if (!idx.isValid()) {
+ enableButton = false;
+ break;
+ }
+ if (idx.isValid() && model->isDir(idx)) {
+ isOpenDirectory = true;
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ button->setEnabled(enableButton);
+ if (acceptMode == QFileDialog::AcceptSave)
+ button->setText(isOpenDirectory ? QFileDialog::tr("&Open") : acceptLabel);
+}
+
+/*!
+ \internal
+*/
+void QFileDialogPrivate::_q_currentChanged(const QModelIndex &index)
+{
+ _q_updateOkButton();
+ emit q_func()->currentChanged(index.data(QFileSystemModel::FilePathRole).toString());
+}
+
+/*!
+ \internal
+
+ This is called when the user double clicks on a file with the corresponding
+ model item \a index.
+*/
+void QFileDialogPrivate::_q_enterDirectory(const QModelIndex &index)
+{
+ Q_Q(QFileDialog);
+ // My Computer or a directory
+ QModelIndex sourceIndex = index.model() == proxyModel ? mapToSource(index) : index;
+ QString path = sourceIndex.data(QFileSystemModel::FilePathRole).toString();
+ if (path.isEmpty() || model->isDir(sourceIndex)) {
+ q->setDirectory(path);
+ emit q->directoryEntered(path);
+ if (fileMode == QFileDialog::Directory
+ || fileMode == QFileDialog::DirectoryOnly) {
+ // ### find out why you have to do both of these.
+ lineEdit()->setText(QString());
+ lineEdit()->clear();
+ }
+ } else {
+ q->accept();
+ }
+}
+
+/*!
+ \internal
+
+ Changes the file dialog's current directory to the one specified
+ by \a path.
+*/
+void QFileDialogPrivate::_q_goToDirectory(const QString &path)
+{
+ #ifndef QT_NO_MESSAGEBOX
+ Q_Q(QFileDialog);
+#endif
+ QModelIndex index = qFileDialogUi->lookInCombo->model()->index(qFileDialogUi->lookInCombo->currentIndex(),
+ qFileDialogUi->lookInCombo->modelColumn(),
+ qFileDialogUi->lookInCombo->rootModelIndex());
+ QString path2 = path;
+ if (!index.isValid())
+ index = mapFromSource(model->index(getEnvironmentVariable(path)));
+ else {
+ path2 = index.data(UrlRole).toUrl().toLocalFile();
+ index = mapFromSource(model->index(path2));
+ }
+ QDir dir(path2);
+ if (!dir.exists())
+ dir = getEnvironmentVariable(path2);
+
+ if (dir.exists() || path2.isEmpty() || path2 == model->myComputer().toString()) {
+ _q_enterDirectory(index);
+#ifndef QT_NO_MESSAGEBOX
+ } else {
+ QString message = QFileDialog::tr("%1\nDirectory not found.\nPlease verify the "
+ "correct directory name was given.");
+ QMessageBox::warning(q, q->windowTitle(), message.arg(path2));
+#endif // QT_NO_MESSAGEBOX
+ }
+}
+
+// Makes a list of filters from a normal filter string "Image Files (*.png *.jpg)"
+QStringList qt_clean_filter_list(const QString &filter)
+{
+ QRegExp regexp(QString::fromLatin1(qt_file_dialog_filter_reg_exp));
+ QString f = filter;
+ int i = regexp.indexIn(f);
+ if (i >= 0)
+ f = regexp.cap(2);
+ return f.split(QLatin1Char(' '), QString::SkipEmptyParts);
+}
+
+/*!
+ \internal
+
+ Sets the current name filter to be nameFilter and
+ update the qFileDialogUi->fileNameEdit when in AcceptSave mode with the new extension.
+*/
+void QFileDialogPrivate::_q_useNameFilter(int index)
+{
+ if (index == nameFilters.size()) {
+ QAbstractItemModel *comboModel = qFileDialogUi->fileTypeCombo->model();
+ nameFilters.append(comboModel->index(comboModel->rowCount() - 1, 0).data().toString());
+ }
+
+ QString nameFilter = nameFilters.at(index);
+ QStringList newNameFilters = qt_clean_filter_list(nameFilter);
+ if (acceptMode == QFileDialog::AcceptSave) {
+ QString newNameFilterExtension;
+ if (newNameFilters.count() > 0)
+ newNameFilterExtension = QFileInfo(newNameFilters.at(0)).suffix();
+
+ QString fileName = lineEdit()->text();
+ const QString fileNameExtension = QFileInfo(fileName).suffix();
+ if (!fileNameExtension.isEmpty() && !newNameFilterExtension.isEmpty()) {
+ const int fileNameExtensionLength = fileNameExtension.count();
+ fileName.replace(fileName.count() - fileNameExtensionLength,
+ fileNameExtensionLength, newNameFilterExtension);
+ qFileDialogUi->listView->clearSelection();
+ lineEdit()->setText(fileName);
+ }
+ }
+
+ model->setNameFilters(newNameFilters);
+}
+
+/*!
+ \internal
+
+ This is called when the model index corresponding to the current file is changed
+ from \a index to \a current.
+*/
+void QFileDialogPrivate::_q_selectionChanged()
+{
+ QModelIndexList indexes = qFileDialogUi->listView->selectionModel()->selectedRows();
+ bool stripDirs = (fileMode != QFileDialog::DirectoryOnly && fileMode != QFileDialog::Directory);
+
+ QStringList allFiles;
+ for (int i = 0; i < indexes.count(); ++i) {
+ if (stripDirs && model->isDir(mapToSource(indexes.at(i))))
+ continue;
+ allFiles.append(indexes.at(i).data().toString());
+ }
+ if (allFiles.count() > 1)
+ for (int i = 0; i < allFiles.count(); ++i) {
+ allFiles.replace(i, QString(QLatin1Char('"') + allFiles.at(i) + QLatin1Char('"')));
+ }
+
+ QString finalFiles = allFiles.join(QLatin1String(" "));
+ if (!finalFiles.isEmpty() && !lineEdit()->hasFocus() && lineEdit()->isVisible())
+ lineEdit()->setText(finalFiles);
+ else
+ _q_updateOkButton();
+}
+
+/*!
+ \internal
+
+ Includes hidden files and directories in the items displayed in the dialog.
+*/
+void QFileDialogPrivate::_q_showHidden()
+{
+ Q_Q(QFileDialog);
+ QDir::Filters dirFilters = q->filter();
+ if (showHiddenAction->isChecked())
+ dirFilters |= QDir::Hidden;
+ else
+ dirFilters &= ~QDir::Hidden;
+ q->setFilter(dirFilters);
+}
+
+/*!
+ \internal
+
+ When parent is root and rows have been inserted when none was there before
+ then select the first one.
+*/
+void QFileDialogPrivate::_q_rowsInserted(const QModelIndex &parent)
+{
+ if (!qFileDialogUi->treeView
+ || parent != qFileDialogUi->treeView->rootIndex()
+ || !qFileDialogUi->treeView->selectionModel()
+ || qFileDialogUi->treeView->selectionModel()->hasSelection()
+ || qFileDialogUi->treeView->model()->rowCount(parent) == 0)
+ return;
+}
+
+void QFileDialogPrivate::_q_fileRenamed(const QString &path, const QString oldName, const QString newName)
+{
+ if (fileMode == QFileDialog::Directory || fileMode == QFileDialog::DirectoryOnly) {
+ if (path == rootPath() && lineEdit()->text() == oldName)
+ lineEdit()->setText(newName);
+ }
+}
+
+/*!
+ \internal
+
+ For the list and tree view watch keys to goto parent and back in the history
+
+ returns true if handled
+*/
+bool QFileDialogPrivate::itemViewKeyboardEvent(QKeyEvent *event) {
+
+ Q_Q(QFileDialog);
+ switch (event->key()) {
+ case Qt::Key_Backspace:
+ _q_navigateToParent();
+ return true;
+ case Qt::Key_Back:
+#ifdef QT_KEYPAD_NAVIGATION
+ if (QApplication::keypadNavigationEnabled())
+ return false;
+#endif
+ case Qt::Key_Left:
+ if (event->key() == Qt::Key_Back || event->modifiers() == Qt::AltModifier) {
+ _q_navigateBackward();
+ return true;
+ }
+ break;
+ case Qt::Key_Escape:
+ q->hide();
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+QString QFileDialogPrivate::getEnvironmentVariable(const QString &string)
+{
+#ifdef Q_OS_UNIX
+ if (string.size() > 1 && string.startsWith(QLatin1Char('$'))) {
+ return QString::fromLocal8Bit(getenv(string.mid(1).toLatin1().constData()));
+ }
+#else
+ if (string.size() > 2 && string.startsWith(QLatin1Char('%')) && string.endsWith(QLatin1Char('%'))) {
+ return QString::fromLocal8Bit(qgetenv(string.mid(1, string.size() - 2).toLatin1().constData()));
+ }
+#endif
+ return string;
+}
+
+void QFileDialogComboBox::init(QFileDialogPrivate *d_pointer) {
+ d_ptr = d_pointer;
+ urlModel = new QUrlModel(this);
+ urlModel->showFullPath = true;
+ urlModel->setFileSystemModel(d_ptr->model);
+ setModel(urlModel);
+}
+
+void QFileDialogComboBox::showPopup()
+{
+ if (model()->rowCount() > 1)
+ QComboBox::showPopup();
+
+ urlModel->setUrls(QList<QUrl>());
+ QList<QUrl> list;
+ QModelIndex idx = d_ptr->model->index(d_ptr->rootPath());
+ while (idx.isValid()) {
+ QUrl url = QUrl::fromLocalFile(idx.data(QFileSystemModel::FilePathRole).toString());
+ if (url.isValid())
+ list.append(url);
+ idx = idx.parent();
+ }
+ // add "my computer"
+ list.append(QUrl::fromLocalFile(QLatin1String("")));
+ urlModel->addUrls(list, 0);
+ idx = model()->index(model()->rowCount() - 1, 0);
+
+ // append history
+ QList<QUrl> urls;
+ for (int i = 0; i < m_history.count(); ++i) {
+ QUrl path = QUrl::fromLocalFile(m_history.at(i));
+ if (!urls.contains(path))
+ urls.prepend(path);
+ }
+ if (urls.count() > 0) {
+ model()->insertRow(model()->rowCount());
+ idx = model()->index(model()->rowCount()-1, 0);
+ // ### TODO maybe add a horizontal line before this
+ model()->setData(idx, QFileDialog::tr("Recent Places"));
+ QStandardItemModel *m = qobject_cast<QStandardItemModel*>(model());
+ if (m) {
+ Qt::ItemFlags flags = m->flags(idx);
+ flags &= ~Qt::ItemIsEnabled;
+ m->item(idx.row(), idx.column())->setFlags(flags);
+ }
+ urlModel->addUrls(urls, -1, false);
+ }
+ setCurrentIndex(0);
+
+ QComboBox::showPopup();
+}
+
+// Exact same as QComboBox::paintEvent(), except we elide the text.
+void QFileDialogComboBox::paintEvent(QPaintEvent *)
+{
+ QStylePainter painter(this);
+ painter.setPen(palette().color(QPalette::Text));
+
+ // draw the combobox frame, focusrect and selected etc.
+ QStyleOptionComboBox opt;
+ initStyleOption(&opt);
+
+ QRect editRect = style()->subControlRect(QStyle::CC_ComboBox, &opt,
+ QStyle::SC_ComboBoxEditField, this);
+ int size = editRect.width() - opt.iconSize.width() - 4;
+ opt.currentText = opt.fontMetrics.elidedText(opt.currentText, Qt::ElideMiddle, size);
+ painter.drawComplexControl(QStyle::CC_ComboBox, opt);
+
+ // draw the icon and text
+ painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
+}
+
+QFileDialogListView::QFileDialogListView(QWidget *parent) : QListView(parent)
+{
+}
+
+void QFileDialogListView::init(QFileDialogPrivate *d_pointer)
+{
+ d_ptr = d_pointer;
+ setSelectionBehavior(QAbstractItemView::SelectRows);
+ setWrapping(true);
+ setResizeMode(QListView::Adjust);
+ setEditTriggers(QAbstractItemView::EditKeyPressed);
+ setContextMenuPolicy(Qt::CustomContextMenu);
+#ifndef QT_NO_DRAGANDDROP
+ setDragDropMode(QAbstractItemView::InternalMove);
+#endif
+}
+
+QSize QFileDialogListView::sizeHint() const
+{
+ int height = qMax(10, sizeHintForRow(0));
+ return QSize(QListView::sizeHint().width() * 2, height * 30);
+}
+
+void QFileDialogListView::keyPressEvent(QKeyEvent *e)
+{
+#ifdef QT_KEYPAD_NAVIGATION
+ if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
+ QListView::keyPressEvent(e);
+ return;
+ }
+#endif // QT_KEYPAD_NAVIGATION
+
+ if (!d_ptr->itemViewKeyboardEvent(e))
+ QListView::keyPressEvent(e);
+ e->accept();
+}
+
+QFileDialogTreeView::QFileDialogTreeView(QWidget *parent) : QTreeView(parent)
+{
+}
+
+void QFileDialogTreeView::init(QFileDialogPrivate *d_pointer)
+{
+ d_ptr = d_pointer;
+ setSelectionBehavior(QAbstractItemView::SelectRows);
+ setRootIsDecorated(false);
+ setItemsExpandable(false);
+ setSortingEnabled(true);
+ header()->setSortIndicator(0, Qt::AscendingOrder);
+ header()->setStretchLastSection(false);
+ setTextElideMode(Qt::ElideMiddle);
+ setEditTriggers(QAbstractItemView::EditKeyPressed);
+ setContextMenuPolicy(Qt::CustomContextMenu);
+#ifndef QT_NO_DRAGANDDROP
+ setDragDropMode(QAbstractItemView::InternalMove);
+#endif
+}
+
+void QFileDialogTreeView::keyPressEvent(QKeyEvent *e)
+{
+#ifdef QT_KEYPAD_NAVIGATION
+ if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
+ QTreeView::keyPressEvent(e);
+ return;
+ }
+#endif // QT_KEYPAD_NAVIGATION
+
+ if (!d_ptr->itemViewKeyboardEvent(e))
+ QTreeView::keyPressEvent(e);
+ e->accept();
+}
+
+QSize QFileDialogTreeView::sizeHint() const
+{
+ int height = qMax(10, sizeHintForRow(0));
+ QSize sizeHint = header()->sizeHint();
+ return QSize(sizeHint.width() * 4, height * 30);
+}
+
+/*!
+ // FIXME: this is a hack to avoid propagating key press events
+ // to the dialog and from there to the "Ok" button
+*/
+void QFileDialogLineEdit::keyPressEvent(QKeyEvent *e)
+{
+#ifdef QT_KEYPAD_NAVIGATION
+ if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
+ QLineEdit::keyPressEvent(e);
+ return;
+ }
+#endif // QT_KEYPAD_NAVIGATION
+
+ int key = e->key();
+ QLineEdit::keyPressEvent(e);
+ if (key != Qt::Key_Escape)
+ e->accept();
+ if (hideOnEsc && (key == Qt::Key_Escape || key == Qt::Key_Return || key == Qt::Key_Enter)) {
+ e->accept();
+ hide();
+ d_ptr->currentView()->setFocus(Qt::ShortcutFocusReason);
+ }
+}
+
+#ifndef QT_NO_FSCOMPLETER
+
+QString QFSCompleter::pathFromIndex(const QModelIndex &index) const
+{
+ const QFileSystemModel *dirModel;
+ if (proxyModel)
+ dirModel = qobject_cast<const QFileSystemModel *>(proxyModel->sourceModel());
+ else
+ dirModel = sourceModel;
+ QString currentLocation = dirModel->rootPath();
+ QString path = index.data(QFileSystemModel::FilePathRole).toString();
+ if (!currentLocation.isEmpty() && path.startsWith(currentLocation)) {
+#if defined(Q_OS_UNIX) || defined(Q_OS_WINCE)
+ if (currentLocation == QDir::separator())
+ return path.mid(currentLocation.length());
+#endif
+ if (currentLocation.endsWith(QLatin1Char('/')))
+ return path.mid(currentLocation.length());
+ else
+ return path.mid(currentLocation.length()+1);
+ }
+ return index.data(QFileSystemModel::FilePathRole).toString();
+}
+
+QStringList QFSCompleter::splitPath(const QString &path) const
+{
+ if (path.isEmpty())
+ return QStringList(completionPrefix());
+
+ QString pathCopy = QDir::toNativeSeparators(path);
+ QString sep = QDir::separator();
+#if defined(Q_OS_SYMBIAN)
+ if (pathCopy == QLatin1String("\\"))
+ return QStringList(pathCopy);
+#elif defined(Q_OS_WIN)
+ if (pathCopy == QLatin1String("\\") || pathCopy == QLatin1String("\\\\"))
+ return QStringList(pathCopy);
+ QString doubleSlash(QLatin1String("\\\\"));
+ if (pathCopy.startsWith(doubleSlash))
+ pathCopy = pathCopy.mid(2);
+ else
+ doubleSlash.clear();
+#endif
+
+ QRegExp re(QLatin1Char('[') + QRegExp::escape(sep) + QLatin1Char(']'));
+
+#if defined(Q_OS_SYMBIAN)
+ QStringList parts = pathCopy.split(re, QString::SkipEmptyParts);
+ if (pathCopy.endsWith(sep))
+ parts.append(QString());
+#elif defined(Q_OS_WIN)
+ QStringList parts = pathCopy.split(re, QString::SkipEmptyParts);
+ if (!doubleSlash.isEmpty() && !parts.isEmpty())
+ parts[0].prepend(doubleSlash);
+ if (pathCopy.endsWith(sep))
+ parts.append(QString());
+#else
+ QStringList parts = pathCopy.split(re);
+ if (path[0] == sep[0]) // read the "/" at the beginning as the split removed it
+ parts[0] = sep[0];
+#endif
+
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ bool startsFromRoot = !parts.isEmpty() && parts[0].endsWith(QLatin1Char(':'));
+#else
+ bool startsFromRoot = path[0] == sep[0];
+#endif
+ if (parts.count() == 1 || (parts.count() > 1 && !startsFromRoot)) {
+ const QFileSystemModel *dirModel;
+ if (proxyModel)
+ dirModel = qobject_cast<const QFileSystemModel *>(proxyModel->sourceModel());
+ else
+ dirModel = sourceModel;
+ QString currentLocation = QDir::toNativeSeparators(dirModel->rootPath());
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ if (currentLocation.endsWith(QLatin1Char(':')))
+ currentLocation.append(sep);
+#endif
+ if (currentLocation.contains(sep) && path != currentLocation) {
+ QStringList currentLocationList = splitPath(currentLocation);
+ while (!currentLocationList.isEmpty()
+ && parts.count() > 0
+ && parts.at(0) == QLatin1String("..")) {
+ parts.removeFirst();
+ currentLocationList.removeLast();
+ }
+ if (!currentLocationList.isEmpty() && currentLocationList.last().isEmpty())
+ currentLocationList.removeLast();
+ return currentLocationList + parts;
+ }
+ }
+ return parts;
+}
+
+#endif // QT_NO_COMPLETER
+
+#ifdef QT3_SUPPORT
+/*!
+ Use selectedFiles() instead.
+
+ \oldcode
+ QString selected = dialog->selectedFile();
+ \newcode
+ QStringList files = dialog->selectedFiles();
+ QString selected;
+ if (!files.isEmpty())
+ selected = files[0];
+ \endcode
+*/
+QString QFileDialog::selectedFile() const
+{
+ QStringList files = selectedFiles();
+ return files.size() ? files.at(0) : QString();
+}
+
+/*!
+ \typedef QFileDialog::Mode
+
+ Use QFileDialog::FileMode instead.
+*/
+
+/*!
+ \fn void QFileDialog::setMode(FileMode m)
+
+ Use setFileMode() instead.
+*/
+
+/*!
+ \fn FileMode QFileDialog::mode() const
+
+ Use fileMode() instead.
+*/
+
+/*!
+ \fn void QFileDialog::setDir(const QString &directory)
+
+ Use setDirectory() instead.
+*/
+
+/*!
+ \fn void QFileDialog::setDir( const QDir &directory )
+
+ Use setDirectory() instead.
+*/
+
+/*!
+ \fn QStringList QFileDialog::getOpenFileNames(const QString &filter,
+ const QString &dir, QWidget *parent, const char* name,
+ const QString &caption, QString *selectedFilter, bool resolveSymlinks)
+
+ Use the getOpenFileNames() overload that takes \a parent as the first
+ argument instead.
+*/
+
+/*!
+ \fn QString QFileDialog::getOpenFileName(const QString &dir,
+ const QString &filter, QWidget *parent = 0, const char *name,
+ const QString &caption, QString *selectedFilter, bool resolveSymlinks)
+
+ Use the getOpenFileName() overload that takes \a parent as the first
+ argument instead.
+*/
+
+/*!
+ \fn QString QFileDialog::getSaveFileName(const QString &dir,
+ const QString &filter, QWidget *parent, const char *name,
+ const QString &caption, QString *selectedFilter, bool resolveSymlinks)
+
+ Use the getSaveFileName() overload that takes \a parent as the first
+ argument instead.
+*/
+
+/*!
+ \fn QString QFileDialog::getExistingDirectory(const QString &dir,
+ QWidget *parent, const char *name, const QString &caption,
+ bool dirOnly, bool resolveSymlinks)
+
+ Use the getExistingDirectory() overload that takes \a parent as
+ the first argument instead.
+*/
+
+#endif // QT3_SUPPORT
+
+QT_END_NAMESPACE
+
+#include "moc_qfiledialog.cpp"
+
+#endif // QT_NO_FILEDIALOG
diff --git a/src/widgets/dialogs/qfiledialog.h b/src/widgets/dialogs/qfiledialog.h
new file mode 100644
index 0000000000..fabb575a5a
--- /dev/null
+++ b/src/widgets/dialogs/qfiledialog.h
@@ -0,0 +1,331 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFILEDIALOG_H
+#define QFILEDIALOG_H
+
+#include <QtCore/qdir.h>
+#include <QtCore/qstring.h>
+#include <QtGui/qdialog.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_FILEDIALOG
+
+class QModelIndex;
+class QItemSelection;
+struct QFileDialogArgs;
+class QFileIconProvider;
+class QFileDialogPrivate;
+class QAbstractItemDelegate;
+class QAbstractProxyModel;
+class QUrl;
+
+class Q_GUI_EXPORT QFileDialog : public QDialog
+{
+ Q_OBJECT
+ Q_ENUMS(ViewMode FileMode AcceptMode Option)
+ Q_FLAGS(Options)
+ Q_PROPERTY(ViewMode viewMode READ viewMode WRITE setViewMode)
+ Q_PROPERTY(FileMode fileMode READ fileMode WRITE setFileMode)
+ Q_PROPERTY(AcceptMode acceptMode READ acceptMode WRITE setAcceptMode)
+ Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly DESIGNABLE false)
+ Q_PROPERTY(bool resolveSymlinks READ resolveSymlinks WRITE setResolveSymlinks DESIGNABLE false)
+ Q_PROPERTY(bool confirmOverwrite READ confirmOverwrite WRITE setConfirmOverwrite DESIGNABLE false)
+ Q_PROPERTY(QString defaultSuffix READ defaultSuffix WRITE setDefaultSuffix)
+ Q_PROPERTY(bool nameFilterDetailsVisible READ isNameFilterDetailsVisible
+ WRITE setNameFilterDetailsVisible DESIGNABLE false)
+ Q_PROPERTY(Options options READ options WRITE setOptions)
+
+public:
+ enum ViewMode { Detail, List };
+ enum FileMode { AnyFile, ExistingFile, Directory, ExistingFiles, DirectoryOnly };
+ enum AcceptMode { AcceptOpen, AcceptSave };
+ enum DialogLabel { LookIn, FileName, FileType, Accept, Reject };
+
+ // ### Rename to FileDialogOption and FileDialogOptions for Qt 5.0
+ enum Option
+ {
+ ShowDirsOnly = 0x00000001,
+ DontResolveSymlinks = 0x00000002,
+ DontConfirmOverwrite = 0x00000004,
+ DontUseSheet = 0x00000008,
+ DontUseNativeDialog = 0x00000010,
+ ReadOnly = 0x00000020,
+ HideNameFilterDetails = 0x00000040
+ };
+ Q_DECLARE_FLAGS(Options, Option)
+
+ QFileDialog(QWidget *parent, Qt::WindowFlags f);
+ explicit QFileDialog(QWidget *parent = 0,
+ const QString &caption = QString(),
+ const QString &directory = QString(),
+ const QString &filter = QString());
+ ~QFileDialog();
+
+ void setDirectory(const QString &directory);
+ inline void setDirectory(const QDir &directory);
+ QDir directory() const;
+
+ void selectFile(const QString &filename);
+ QStringList selectedFiles() const;
+
+#ifdef QT_DEPRECATED
+ QT_DEPRECATED void setFilter(const QString &filter);
+ QT_DEPRECATED void setFilters(const QStringList &filters);
+ QT_DEPRECATED QStringList filters() const;
+ QT_DEPRECATED void selectFilter(const QString &filter);
+ QT_DEPRECATED QString selectedFilter() const;
+#endif
+ void setNameFilterDetailsVisible(bool enabled);
+ bool isNameFilterDetailsVisible() const;
+
+ void setNameFilter(const QString &filter);
+ void setNameFilters(const QStringList &filters);
+ QStringList nameFilters() const;
+ void selectNameFilter(const QString &filter);
+ QString selectedNameFilter() const;
+
+ QDir::Filters filter() const;
+ void setFilter(QDir::Filters filters);
+
+ void setViewMode(ViewMode mode);
+ ViewMode viewMode() const;
+
+ void setFileMode(FileMode mode);
+ FileMode fileMode() const;
+
+ void setAcceptMode(AcceptMode mode);
+ AcceptMode acceptMode() const;
+
+ void setReadOnly(bool enabled);
+ bool isReadOnly() const;
+
+ void setResolveSymlinks(bool enabled);
+ bool resolveSymlinks() const;
+
+ void setSidebarUrls(const QList<QUrl> &urls);
+ QList<QUrl> sidebarUrls() const;
+
+ QByteArray saveState() const;
+ bool restoreState(const QByteArray &state);
+
+ void setConfirmOverwrite(bool enabled);
+ bool confirmOverwrite() const;
+
+ void setDefaultSuffix(const QString &suffix);
+ QString defaultSuffix() const;
+
+ void setHistory(const QStringList &paths);
+ QStringList history() const;
+
+ void setItemDelegate(QAbstractItemDelegate *delegate);
+ QAbstractItemDelegate *itemDelegate() const;
+
+ void setIconProvider(QFileIconProvider *provider);
+ QFileIconProvider *iconProvider() const;
+
+ void setLabelText(DialogLabel label, const QString &text);
+ QString labelText(DialogLabel label) const;
+
+#ifndef QT_NO_PROXYMODEL
+ void setProxyModel(QAbstractProxyModel *model);
+ QAbstractProxyModel *proxyModel() const;
+#endif
+
+ void setOption(Option option, bool on = true);
+ bool testOption(Option option) const;
+ void setOptions(Options options);
+ Options options() const;
+
+#ifdef Q_NO_USING_KEYWORD
+#ifndef Q_QDOC
+ void open() { QDialog::open(); }
+#endif
+#else
+ using QDialog::open;
+#endif
+ void open(QObject *receiver, const char *member);
+ void setVisible(bool visible);
+
+Q_SIGNALS:
+ void fileSelected(const QString &file);
+ void filesSelected(const QStringList &files);
+ void currentChanged(const QString &path);
+ void directoryEntered(const QString &directory);
+ void filterSelected(const QString &filter);
+
+public:
+#ifdef QT3_SUPPORT
+ typedef FileMode Mode;
+ inline QT3_SUPPORT void setMode(FileMode m) { setFileMode(m); }
+ inline QT3_SUPPORT FileMode mode() const { return fileMode(); }
+ inline QT3_SUPPORT void setDir(const QString &directory) { setDirectory(directory); }
+ inline QT3_SUPPORT void setDir( const QDir &directory ) { setDirectory(directory); }
+ QT3_SUPPORT QString selectedFile() const;
+#endif
+
+ static QString getOpenFileName(QWidget *parent = 0,
+ const QString &caption = QString(),
+ const QString &dir = QString(),
+ const QString &filter = QString(),
+ QString *selectedFilter = 0,
+ Options options = 0);
+
+ static QString getSaveFileName(QWidget *parent = 0,
+ const QString &caption = QString(),
+ const QString &dir = QString(),
+ const QString &filter = QString(),
+ QString *selectedFilter = 0,
+ Options options = 0);
+
+ static QString getExistingDirectory(QWidget *parent = 0,
+ const QString &caption = QString(),
+ const QString &dir = QString(),
+ Options options = ShowDirsOnly);
+
+ static QStringList getOpenFileNames(QWidget *parent = 0,
+ const QString &caption = QString(),
+ const QString &dir = QString(),
+ const QString &filter = QString(),
+ QString *selectedFilter = 0,
+ Options options = 0);
+
+#ifdef QT3_SUPPORT
+ inline static QString QT3_SUPPORT getOpenFileName(const QString &dir,
+ const QString &filter = QString(),
+ QWidget *parent = 0, const char* name = 0,
+ const QString &caption = QString(),
+ QString *selectedFilter = 0,
+ bool resolveSymlinks = true)
+ { Q_UNUSED(name);
+ return getOpenFileName(parent, caption, dir, filter, selectedFilter,
+ resolveSymlinks ? Option(0) : DontResolveSymlinks); }
+
+ inline static QString QT3_SUPPORT getSaveFileName(const QString &dir,
+ const QString &filter = QString(),
+ QWidget *parent = 0, const char* name = 0,
+ const QString &caption = QString(),
+ QString *selectedFilter = 0,
+ bool resolveSymlinks = true)
+ { Q_UNUSED(name);
+ return getSaveFileName(parent, caption, dir, filter, selectedFilter,
+ resolveSymlinks ? Option(0) : DontResolveSymlinks); }
+
+ inline static QString QT3_SUPPORT getExistingDirectory(const QString &dir,
+ QWidget *parent = 0,
+ const char* name = 0,
+ const QString &caption = QString(),
+ bool dirOnly = true,
+ bool resolveSymlinks = true)
+ { Q_UNUSED(name);
+ return getExistingDirectory(parent, caption, dir,
+ Options((resolveSymlinks ? Option(0) : DontResolveSymlinks)
+ | (dirOnly ? ShowDirsOnly : Option(0)))); }
+
+ inline static QStringList QT3_SUPPORT getOpenFileNames(const QString &filter,
+ const QString &dir = QString(),
+ QWidget *parent = 0,
+ const char* name = 0,
+ const QString &caption = QString(),
+ QString *selectedFilter = 0,
+ bool resolveSymlinks = true)
+ { Q_UNUSED(name);
+ return getOpenFileNames(parent, caption, dir, filter, selectedFilter,
+ resolveSymlinks ? Option(0) : DontResolveSymlinks); }
+#endif // QT3_SUPPORT
+
+protected:
+ QFileDialog(const QFileDialogArgs &args);
+ void done(int result);
+ void accept();
+ void changeEvent(QEvent *e);
+
+private:
+ Q_DECLARE_PRIVATE(QFileDialog)
+ Q_DISABLE_COPY(QFileDialog)
+
+ Q_PRIVATE_SLOT(d_func(), void _q_pathChanged(const QString &))
+
+ Q_PRIVATE_SLOT(d_func(), void _q_navigateBackward())
+ Q_PRIVATE_SLOT(d_func(), void _q_navigateForward())
+ Q_PRIVATE_SLOT(d_func(), void _q_navigateToParent())
+ Q_PRIVATE_SLOT(d_func(), void _q_createDirectory())
+ Q_PRIVATE_SLOT(d_func(), void _q_showListView())
+ Q_PRIVATE_SLOT(d_func(), void _q_showDetailsView())
+ Q_PRIVATE_SLOT(d_func(), void _q_showContextMenu(const QPoint &))
+ Q_PRIVATE_SLOT(d_func(), void _q_renameCurrent())
+ Q_PRIVATE_SLOT(d_func(), void _q_deleteCurrent())
+ Q_PRIVATE_SLOT(d_func(), void _q_showHidden())
+ Q_PRIVATE_SLOT(d_func(), void _q_updateOkButton())
+ Q_PRIVATE_SLOT(d_func(), void _q_currentChanged(const QModelIndex &index))
+ Q_PRIVATE_SLOT(d_func(), void _q_enterDirectory(const QModelIndex &index))
+ Q_PRIVATE_SLOT(d_func(), void _q_goToDirectory(const QString &path))
+ Q_PRIVATE_SLOT(d_func(), void _q_useNameFilter(int index))
+ Q_PRIVATE_SLOT(d_func(), void _q_selectionChanged())
+ Q_PRIVATE_SLOT(d_func(), void _q_goToUrl(const QUrl &url))
+ Q_PRIVATE_SLOT(d_func(), void _q_goHome())
+ Q_PRIVATE_SLOT(d_func(), void _q_showHeader(QAction *))
+ Q_PRIVATE_SLOT(d_func(), void _q_autoCompleteFileName(const QString &text))
+ Q_PRIVATE_SLOT(d_func(), void _q_rowsInserted(const QModelIndex & parent))
+ Q_PRIVATE_SLOT(d_func(), void _q_fileRenamed(const QString &path,
+ const QString oldName, const QString newName))
+#if defined(Q_WS_MAC)
+ Q_PRIVATE_SLOT(d_func(), void _q_macRunNativeAppModalPanel())
+#endif
+};
+
+inline void QFileDialog::setDirectory(const QDir &adirectory)
+{ setDirectory(adirectory.absolutePath()); }
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QFileDialog::Options)
+
+#endif // QT_NO_FILEDIALOG
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFILEDIALOG_H
diff --git a/src/widgets/dialogs/qfiledialog.ui b/src/widgets/dialogs/qfiledialog.ui
new file mode 100644
index 0000000000..dcb08114e2
--- /dev/null
+++ b/src/widgets/dialogs/qfiledialog.ui
@@ -0,0 +1,356 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2011 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$
+**
+*********************************************************************</comment>
+ <class>QFileDialog</class>
+ <widget class="QDialog" name="QFileDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>521</width>
+ <height>316</height>
+ </rect>
+ </property>
+ <property name="sizeGripEnabled" >
+ <bool>true</bool>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QLabel" name="lookInLabel" >
+ <property name="text" >
+ <string>Look in:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" colspan="2" >
+ <layout class="QHBoxLayout" >
+ <item>
+ <widget class="QFileDialogComboBox" name="lookInCombo" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Ignored" >
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize" >
+ <size>
+ <width>50</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="backButton" >
+ <property name="toolTip" >
+ <string>Back</string>
+ </property>
+ <property name="accessibleName">
+ <string>Back</string>
+ </property>
+ <property name="accessibleDescription">
+ <string>Go back</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="forwardButton" >
+ <property name="toolTip" >
+ <string>Forward</string>
+ </property>
+ <property name="accessibleName">
+ <string>Forward</string>
+ </property>
+ <property name="accessibleDescription">
+ <string>Go forward</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="toParentButton" >
+ <property name="toolTip" >
+ <string>Parent Directory</string>
+ </property>
+ <property name="accessibleName">
+ <string>Parent Directory</string>
+ </property>
+ <property name="accessibleDescription">
+ <string>Go to the parent directory</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="newFolderButton" >
+ <property name="toolTip" >
+ <string>Create New Folder</string>
+ </property>
+ <property name="accessibleName">
+ <string>Create New Folder</string>
+ </property>
+ <property name="accessibleDescription">
+ <string>Create a New Folder</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="listModeButton" >
+ <property name="toolTip" >
+ <string>List View</string>
+ </property>
+ <property name="accessibleName">
+ <string>List View</string>
+ </property>
+ <property name="accessibleDescription">
+ <string>Change to list view mode</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="detailModeButton" >
+ <property name="toolTip" >
+ <string>Detail View</string>
+ </property>
+ <property name="accessibleName">
+ <string>Detail View</string>
+ </property>
+ <property name="accessibleDescription">
+ <string>Change to detail view mode</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="0" colspan="3" >
+ <widget class="QSplitter" name="splitter" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <widget class="QSidebar" name="sidebar" />
+ <widget class="QFrame" name="frame" >
+ <property name="frameShape" >
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="spacing" >
+ <number>0</number>
+ </property>
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QStackedWidget" name="stackedWidget" >
+ <property name="currentIndex" >
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="page" >
+ <layout class="QVBoxLayout" >
+ <property name="spacing" >
+ <number>0</number>
+ </property>
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QFileDialogListView" name="listView" />
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="page_2" >
+ <layout class="QVBoxLayout" >
+ <property name="spacing" >
+ <number>0</number>
+ </property>
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QFileDialogTreeView" name="treeView" />
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <widget class="QLabel" name="fileNameLabel" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Minimum" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize" >
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <widget class="QFileDialogLineEdit" name="fileNameEdit" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item rowspan="2" row="2" column="2" >
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" >
+ <widget class="QLabel" name="fileTypeLabel" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Files of type:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" >
+ <widget class="QComboBox" name="fileTypeCombo" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QFileDialogTreeView</class>
+ <extends>QTreeView</extends>
+ <header>qfiledialog_p.h</header>
+ </customwidget>
+ <customwidget>
+ <class>QFileDialogListView</class>
+ <extends>QListView</extends>
+ <header>qfiledialog_p.h</header>
+ </customwidget>
+ <customwidget>
+ <class>QSidebar</class>
+ <extends>QListWidget</extends>
+ <header>qsidebar_p.h</header>
+ </customwidget>
+ <customwidget>
+ <class>QFileDialogLineEdit</class>
+ <extends>QLineEdit</extends>
+ <header>qfiledialog_p.h</header>
+ </customwidget>
+ <customwidget>
+ <class>QFileDialogComboBox</class>
+ <extends>QComboBox</extends>
+ <header>qfiledialog_p.h</header>
+ </customwidget>
+ </customwidgets>
+ <tabstops>
+ <tabstop>lookInCombo</tabstop>
+ <tabstop>backButton</tabstop>
+ <tabstop>forwardButton</tabstop>
+ <tabstop>toParentButton</tabstop>
+ <tabstop>newFolderButton</tabstop>
+ <tabstop>listModeButton</tabstop>
+ <tabstop>detailModeButton</tabstop>
+ <tabstop>sidebar</tabstop>
+ <tabstop>listView</tabstop>
+ <tabstop>fileNameEdit</tabstop>
+ <tabstop>fileTypeCombo</tabstop>
+ <tabstop>buttonBox</tabstop>
+ <tabstop>treeView</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/widgets/dialogs/qfiledialog_embedded.ui b/src/widgets/dialogs/qfiledialog_embedded.ui
new file mode 100644
index 0000000000..e8de400cab
--- /dev/null
+++ b/src/widgets/dialogs/qfiledialog_embedded.ui
@@ -0,0 +1,340 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2011 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$
+**
+*********************************************************************</comment>
+ <class>QFileDialog</class>
+ <widget class="QDialog" name="QFileDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>240</width>
+ <height>320</height>
+ </rect>
+ </property>
+ <property name="sizeGripEnabled" >
+ <bool>true</bool>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QFileDialogComboBox" name="lookInCombo" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <item>
+ <widget class="QToolButton" name="backButton" >
+ <property name="toolTip" >
+ <string>Back</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="forwardButton" >
+ <property name="toolTip" >
+ <string>Forward</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="toParentButton" >
+ <property name="toolTip" >
+ <string>Parent Directory</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="newFolderButton" >
+ <property name="toolTip" >
+ <string>Create New Folder</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="listModeButton" >
+ <property name="toolTip" >
+ <string>List View</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="detailModeButton" >
+ <property name="toolTip" >
+ <string>Detail View</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QSplitter" name="splitter" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <widget class="QSidebar" name="sidebar" />
+ <widget class="QFrame" name="frame" >
+ <property name="frameShape" >
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="spacing" >
+ <number>0</number>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QStackedWidget" name="stackedWidget" >
+ <property name="currentIndex" >
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="page" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>108</width>
+ <height>164</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="spacing" >
+ <number>0</number>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QFileDialogListView" name="listView" />
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="page_2" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>100</width>
+ <height>30</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="spacing" >
+ <number>0</number>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QFileDialogTreeView" name="treeView" />
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QFileDialogLineEdit" name="fileNameEdit" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item rowspan="2" row="0" column="1" >
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QComboBox" name="fileTypeCombo" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QLabel" name="fileNameLabel" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize" >
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize" >
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="fileTypeLabel" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize" >
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text" >
+ <string>Files of type:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="lookInLabel" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize" >
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text" >
+ <string>Look in:</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QFileDialogTreeView</class>
+ <extends>QTreeView</extends>
+ <header>qfiledialog_p.h</header>
+ </customwidget>
+ <customwidget>
+ <class>QFileDialogListView</class>
+ <extends>QListView</extends>
+ <header>qfiledialog_p.h</header>
+ </customwidget>
+ <customwidget>
+ <class>QSidebar</class>
+ <extends>QListWidget</extends>
+ <header>qsidebar_p.h</header>
+ </customwidget>
+ <customwidget>
+ <class>QFileDialogLineEdit</class>
+ <extends>QLineEdit</extends>
+ <header>qfiledialog_p.h</header>
+ </customwidget>
+ <customwidget>
+ <class>QFileDialogComboBox</class>
+ <extends>QComboBox</extends>
+ <header>qfiledialog_p.h</header>
+ </customwidget>
+ </customwidgets>
+ <tabstops>
+ <tabstop>lookInCombo</tabstop>
+ <tabstop>backButton</tabstop>
+ <tabstop>forwardButton</tabstop>
+ <tabstop>toParentButton</tabstop>
+ <tabstop>newFolderButton</tabstop>
+ <tabstop>listModeButton</tabstop>
+ <tabstop>detailModeButton</tabstop>
+ <tabstop>sidebar</tabstop>
+ <tabstop>listView</tabstop>
+ <tabstop>fileNameEdit</tabstop>
+ <tabstop>fileTypeCombo</tabstop>
+ <tabstop>buttonBox</tabstop>
+ <tabstop>treeView</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/widgets/dialogs/qfiledialog_mac.mm b/src/widgets/dialogs/qfiledialog_mac.mm
new file mode 100644
index 0000000000..832f9bfaf8
--- /dev/null
+++ b/src/widgets/dialogs/qfiledialog_mac.mm
@@ -0,0 +1,1157 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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 "qfiledialog.h"
+
+#ifndef QT_NO_FILEDIALOG
+
+/*****************************************************************************
+ QFileDialog debug facilities
+ *****************************************************************************/
+//#define DEBUG_FILEDIALOG_FILTERS
+
+#include <qapplication.h>
+#include <private/qapplication_p.h>
+#include <private/qfiledialog_p.h>
+#include <private/qt_mac_p.h>
+#include <private/qt_cocoa_helpers_mac_p.h>
+#include <qregexp.h>
+#include <qbuffer.h>
+#include <qdebug.h>
+#include <qstringlist.h>
+#include <qaction.h>
+#include <qtextcodec.h>
+#include <qvarlengtharray.h>
+#include <qdesktopwidget.h>
+#include <stdlib.h>
+#include <qabstracteventdispatcher.h>
+#import <AppKit/NSSavePanel.h>
+#include "ui_qfiledialog.h"
+
+QT_BEGIN_NAMESPACE
+
+extern QStringList qt_make_filter_list(const QString &filter); // qfiledialog.cpp
+extern QStringList qt_clean_filter_list(const QString &filter); // qfiledialog.cpp
+extern const char *qt_file_dialog_filter_reg_exp; // qfiledialog.cpp
+extern bool qt_mac_is_macsheet(const QWidget *w); // qwidget_mac.mm
+
+QT_END_NAMESPACE
+
+QT_FORWARD_DECLARE_CLASS(QFileDialogPrivate)
+QT_FORWARD_DECLARE_CLASS(QString)
+QT_FORWARD_DECLARE_CLASS(QStringList)
+QT_FORWARD_DECLARE_CLASS(QWidget)
+QT_FORWARD_DECLARE_CLASS(QAction)
+QT_FORWARD_DECLARE_CLASS(QFileInfo)
+QT_USE_NAMESPACE
+
+@class QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate);
+
+@interface QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate)
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+ : NSObject<NSOpenSavePanelDelegate>
+#else
+ : NSObject
+#endif
+{
+ @public
+ NSOpenPanel *mOpenPanel;
+ NSSavePanel *mSavePanel;
+ NSView *mAccessoryView;
+ NSPopUpButton *mPopUpButton;
+ NSTextField *mTextField;
+ QFileDialogPrivate *mPriv;
+ NSString *mCurrentDir;
+ bool mConfirmOverwrite;
+ int mReturnCode;
+
+ QT_PREPEND_NAMESPACE(QFileDialog::AcceptMode) mAcceptMode;
+ QT_PREPEND_NAMESPACE(QDir::Filters) *mQDirFilter;
+ QT_PREPEND_NAMESPACE(QFileDialog::FileMode) mFileMode;
+ QT_PREPEND_NAMESPACE(QFileDialog::Options) *mFileOptions;
+
+ QString *mLastFilterCheckPath;
+ QString *mCurrentSelection;
+ QStringList *mQDirFilterEntryList;
+ QStringList *mNameFilterDropDownList;
+ QStringList *mSelectedNameFilter;
+}
+
+- (NSString *)strip:(const QString &)label;
+- (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename;
+- (void)filterChanged:(id)sender;
+- (void)showModelessPanel;
+- (BOOL)runApplicationModalPanel;
+- (void)showWindowModalSheet:(QWidget *)docWidget;
+- (void)updateProperties;
+- (QStringList)acceptableExtensionsForSave;
+- (QString)removeExtensions:(const QString &)filter;
+- (void)createTextField;
+- (void)createPopUpButton:(const QString &)selectedFilter hideDetails:(BOOL)hideDetails;
+- (QStringList)findStrippedFilterWithVisualFilterName:(QString)name;
+- (void)createAccessory;
+
+@end
+
+@implementation QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate)
+
+- (id)initWithAcceptMode:(QT_PREPEND_NAMESPACE(QFileDialog::AcceptMode))acceptMode
+ title:(const QString &)title
+ hideNameFilterDetails:(bool)hideNameFilterDetails
+ qDirFilter:(QT_PREPEND_NAMESPACE(QDir::Filters))qDirFilter
+ fileOptions:(QT_PREPEND_NAMESPACE(QFileDialog::Options))fileOptions
+ fileMode:(QT_PREPEND_NAMESPACE(QFileDialog::FileMode))fileMode
+ selectFile:(const QString &)selectFile
+ confirmOverwrite:(bool)confirm
+ priv:(QFileDialogPrivate *)priv
+{
+ self = [super init];
+
+ mAcceptMode = acceptMode;
+ if (mAcceptMode == QT_PREPEND_NAMESPACE(QFileDialog::AcceptOpen)){
+ mOpenPanel = [NSOpenPanel openPanel];
+ mSavePanel = mOpenPanel;
+ } else {
+ mSavePanel = [NSSavePanel savePanel];
+ mOpenPanel = 0;
+ }
+
+ [mSavePanel setLevel:NSModalPanelWindowLevel];
+ [mSavePanel setDelegate:self];
+ mQDirFilter = new QT_PREPEND_NAMESPACE(QDir::Filters)(qDirFilter);
+ mFileOptions = new QT_PREPEND_NAMESPACE(QFileDialog::Options)(fileOptions);
+ mFileMode = fileMode;
+ mConfirmOverwrite = confirm;
+ mReturnCode = -1;
+ mPriv = priv;
+ mLastFilterCheckPath = new QString;
+ mQDirFilterEntryList = new QStringList;
+ mNameFilterDropDownList = new QStringList(priv->nameFilters);
+ QString selectedVisualNameFilter = priv->qFileDialogUi->fileTypeCombo->currentText();
+ mSelectedNameFilter = new QStringList([self findStrippedFilterWithVisualFilterName:selectedVisualNameFilter]);
+
+ QFileInfo sel(selectFile);
+ if (sel.isDir()){
+ mCurrentDir = [qt_mac_QStringToNSString(sel.absoluteFilePath()) retain];
+ mCurrentSelection = new QString;
+ } else {
+ mCurrentDir = [qt_mac_QStringToNSString(sel.absolutePath()) retain];
+ mCurrentSelection = new QString(sel.absoluteFilePath());
+ }
+
+ [mSavePanel setTitle:qt_mac_QStringToNSString(title)];
+ [self createPopUpButton:selectedVisualNameFilter hideDetails:hideNameFilterDetails];
+ [self createTextField];
+ [self createAccessory];
+ [mSavePanel setAccessoryView:mNameFilterDropDownList->size() > 1 ? mAccessoryView : nil];
+
+ if (mPriv){
+ [mSavePanel setPrompt:[self strip:mPriv->acceptLabel]];
+ if (mPriv->fileNameLabelExplicitlySat)
+ [mSavePanel setNameFieldLabel:[self strip:mPriv->qFileDialogUi->fileNameLabel->text()]];
+ }
+
+ [self updateProperties];
+ [mSavePanel retain];
+ return self;
+}
+
+- (void)dealloc
+{
+ delete mQDirFilter;
+ delete mFileOptions;
+ delete mLastFilterCheckPath;
+ delete mQDirFilterEntryList;
+ delete mNameFilterDropDownList;
+ delete mSelectedNameFilter;
+ delete mCurrentSelection;
+
+ [mSavePanel orderOut:mSavePanel];
+ [mSavePanel setAccessoryView:nil];
+ [mPopUpButton release];
+ [mTextField release];
+ [mAccessoryView release];
+ [mSavePanel setDelegate:nil];
+ [mSavePanel release];
+ [mCurrentDir release];
+ [super dealloc];
+}
+
+- (NSString *)strip:(const QString &)label
+{
+ QAction a(label, 0);
+ return qt_mac_QStringToNSString(a.iconText());
+}
+
+- (void)closePanel
+{
+ *mCurrentSelection = QT_PREPEND_NAMESPACE(qt_mac_NSStringToQString)([mSavePanel filename]);
+ [mSavePanel close];
+}
+
+- (void)showModelessPanel
+{
+ if (mOpenPanel){
+ QFileInfo info(*mCurrentSelection);
+ NSString *filename = QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(info.fileName());
+ NSString *filepath = QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(info.filePath());
+ bool selectable = (mAcceptMode == QFileDialog::AcceptSave)
+ || [self panel:nil shouldShowFilename:filepath];
+ [mOpenPanel
+ beginForDirectory:mCurrentDir
+ file:selectable ? filename : nil
+ types:nil
+ modelessDelegate:self
+ didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:)
+ contextInfo:nil];
+ }
+}
+
+- (BOOL)runApplicationModalPanel
+{
+ QFileInfo info(*mCurrentSelection);
+ NSString *filename = QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(info.fileName());
+ NSString *filepath = QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(info.filePath());
+ bool selectable = (mAcceptMode == QFileDialog::AcceptSave)
+ || [self panel:nil shouldShowFilename:filepath];
+ mReturnCode = [mSavePanel
+ runModalForDirectory:mCurrentDir
+ file:selectable ? filename : @"untitled"];
+
+ QAbstractEventDispatcher::instance()->interrupt();
+ return (mReturnCode == NSOKButton);
+}
+
+- (QT_PREPEND_NAMESPACE(QDialog::DialogCode))dialogResultCode
+{
+ return (mReturnCode == NSOKButton) ? QT_PREPEND_NAMESPACE(QDialog::Accepted) : QT_PREPEND_NAMESPACE(QDialog::Rejected);
+}
+
+- (void)showWindowModalSheet:(QWidget *)docWidget
+{
+ Q_UNUSED(docWidget);
+ QFileInfo info(*mCurrentSelection);
+ NSString *filename = QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(info.fileName());
+ NSString *filepath = QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(info.filePath());
+ bool selectable = (mAcceptMode == QFileDialog::AcceptSave)
+ || [self panel:nil shouldShowFilename:filepath];
+ [mSavePanel
+ beginSheetForDirectory:mCurrentDir
+ file:selectable ? filename : nil
+#ifdef QT_MAC_USE_COCOA
+ modalForWindow:QT_PREPEND_NAMESPACE(qt_mac_window_for)(docWidget)
+#else
+ modalForWindow:nil
+#endif
+ modalDelegate:self
+ didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:)
+ contextInfo:nil];
+}
+
+- (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename
+{
+ Q_UNUSED(sender);
+
+ if ([filename length] == 0)
+ return NO;
+
+ // Always accept directories regardless of their names (unless it is a bundle):
+ BOOL isDir;
+ if ([[NSFileManager defaultManager] fileExistsAtPath:filename isDirectory:&isDir] && isDir) {
+ if ([mSavePanel treatsFilePackagesAsDirectories] == NO) {
+ if ([[NSWorkspace sharedWorkspace] isFilePackageAtPath:filename] == NO)
+ return YES;
+ }
+ }
+
+ QString qtFileName = QT_PREPEND_NAMESPACE(qt_mac_NSStringToQString)(filename);
+ QFileInfo info(qtFileName.normalized(QT_PREPEND_NAMESPACE(QString::NormalizationForm_C)));
+ QString path = info.absolutePath();
+ if (path != *mLastFilterCheckPath){
+ *mLastFilterCheckPath = path;
+ *mQDirFilterEntryList = info.dir().entryList(*mQDirFilter);
+ }
+ // Check if the QDir filter accepts the file:
+ if (!mQDirFilterEntryList->contains(info.fileName()))
+ return NO;
+
+ // No filter means accept everything
+ if (mSelectedNameFilter->isEmpty())
+ return YES;
+ // Check if the current file name filter accepts the file:
+ for (int i=0; i<mSelectedNameFilter->size(); ++i) {
+ if (QDir::match(mSelectedNameFilter->at(i), qtFileName))
+ return YES;
+ }
+ return NO;
+}
+
+- (NSString *)panel:(id)sender userEnteredFilename:(NSString *)filename confirmed:(BOOL)okFlag
+{
+ Q_UNUSED(sender);
+ if (!okFlag)
+ return filename;
+ if (mConfirmOverwrite)
+ return filename;
+
+ // User has clicked save, and no overwrite confirmation should occur.
+ // To get the latter, we need to change the name we return (hence the prefix):
+ return [@"___qt_very_unlikely_prefix_" stringByAppendingString:filename];
+}
+
+- (void)setNameFilters:(const QStringList &)filters hideDetails:(BOOL)hideDetails
+{
+ [mPopUpButton removeAllItems];
+ *mNameFilterDropDownList = filters;
+ if (filters.size() > 0){
+ for (int i=0; i<filters.size(); ++i) {
+ QString filter = hideDetails ? [self removeExtensions:filters.at(i)] : filters.at(i);
+ [mPopUpButton addItemWithTitle:QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(filter)];
+ }
+ [mPopUpButton selectItemAtIndex:0];
+ [mSavePanel setAccessoryView:mAccessoryView];
+ } else
+ [mSavePanel setAccessoryView:nil];
+
+ [self filterChanged:self];
+}
+
+- (void)filterChanged:(id)sender
+{
+ // This mDelegate function is called when the _name_ filter changes.
+ Q_UNUSED(sender);
+ QString selection = mNameFilterDropDownList->value([mPopUpButton indexOfSelectedItem]);
+ *mSelectedNameFilter = [self findStrippedFilterWithVisualFilterName:selection];
+ [mSavePanel validateVisibleColumns];
+ [self updateProperties];
+ if (mPriv)
+ mPriv->QNSOpenSavePanelDelegate_filterSelected([mPopUpButton indexOfSelectedItem]);
+}
+
+- (QString)currentNameFilter
+{
+ return mNameFilterDropDownList->value([mPopUpButton indexOfSelectedItem]);
+}
+
+- (QStringList)selectedFiles
+{
+ if (mOpenPanel)
+ return QT_PREPEND_NAMESPACE(qt_mac_NSArrayToQStringList)([mOpenPanel filenames]);
+ else{
+ QStringList result;
+ QString filename = QT_PREPEND_NAMESPACE(qt_mac_NSStringToQString)([mSavePanel filename]);
+ result << filename.remove(QLatin1String("___qt_very_unlikely_prefix_"));
+ return result;
+ }
+}
+
+- (void)updateProperties
+{
+ // Call this functions if mFileMode, mFileOptions,
+ // mNameFilterDropDownList or mQDirFilter changes.
+ // The savepanel does not contain the neccessary functions for this.
+ bool chooseFilesOnly = mFileMode == QT_PREPEND_NAMESPACE(QFileDialog::ExistingFile)
+ || mFileMode == QT_PREPEND_NAMESPACE(QFileDialog::ExistingFiles);
+ bool chooseDirsOnly = mFileMode == QT_PREPEND_NAMESPACE(QFileDialog::Directory)
+ || mFileMode == QT_PREPEND_NAMESPACE(QFileDialog::DirectoryOnly)
+ || *mFileOptions & QT_PREPEND_NAMESPACE(QFileDialog::ShowDirsOnly);
+
+ [mOpenPanel setCanChooseFiles:!chooseDirsOnly];
+ [mOpenPanel setCanChooseDirectories:!chooseFilesOnly];
+ [mSavePanel setCanCreateDirectories:!(*mFileOptions & QT_PREPEND_NAMESPACE(QFileDialog::ReadOnly))];
+ [mOpenPanel setAllowsMultipleSelection:(mFileMode == QT_PREPEND_NAMESPACE(QFileDialog::ExistingFiles))];
+ [mOpenPanel setResolvesAliases:!(*mFileOptions & QT_PREPEND_NAMESPACE(QFileDialog::DontResolveSymlinks))];
+
+ QStringList ext = [self acceptableExtensionsForSave];
+ if (mPriv && !ext.isEmpty() && !mPriv->defaultSuffix.isEmpty())
+ ext.prepend(mPriv->defaultSuffix);
+ [mSavePanel setAllowedFileTypes:ext.isEmpty() ? nil : QT_PREPEND_NAMESPACE(qt_mac_QStringListToNSMutableArray(ext))];
+
+ if ([mSavePanel isVisible])
+ [mOpenPanel validateVisibleColumns];
+}
+
+- (void)panelSelectionDidChange:(id)sender
+{
+ Q_UNUSED(sender);
+ if (mPriv) {
+ QString selection = QT_PREPEND_NAMESPACE(qt_mac_NSStringToQString([mSavePanel filename]));
+ if (selection != mCurrentSelection) {
+ *mCurrentSelection = selection;
+ mPriv->QNSOpenSavePanelDelegate_selectionChanged(selection);
+ }
+ }
+}
+
+- (void)openPanelDidEnd:(NSOpenPanel *)panel returnCode:(int)returnCode contextInfo:(void *)contextInfo
+{
+ Q_UNUSED(panel);
+ Q_UNUSED(contextInfo);
+ mReturnCode = returnCode;
+ if (mPriv)
+ mPriv->QNSOpenSavePanelDelegate_panelClosed(returnCode == NSOKButton);
+}
+
+- (void)panel:(id)sender directoryDidChange:(NSString *)path
+{
+ Q_UNUSED(sender);
+ if (!mPriv)
+ return;
+ if ([path isEqualToString:mCurrentDir])
+ return;
+
+ [mCurrentDir release];
+ mCurrentDir = [path retain];
+ mPriv->QNSOpenSavePanelDelegate_directoryEntered(QT_PREPEND_NAMESPACE(qt_mac_NSStringToQString(mCurrentDir)));
+}
+
+/*
+ Returns a list of extensions (e.g. "png", "jpg", "gif")
+ for the current name filter. If a filter do not conform
+ to the format *.xyz or * or *.*, an empty list
+ is returned meaning accept everything.
+*/
+- (QStringList)acceptableExtensionsForSave
+{
+ QStringList result;
+ for (int i=0; i<mSelectedNameFilter->count(); ++i) {
+ const QString &filter = mSelectedNameFilter->at(i);
+ if (filter.startsWith(QLatin1String("*."))
+ && !filter.contains(QLatin1Char('?'))
+ && filter.count(QLatin1Char('*')) == 1) {
+ result += filter.mid(2);
+ } else {
+ return QStringList(); // Accept everything
+ }
+ }
+ return result;
+}
+
+- (QString)removeExtensions:(const QString &)filter
+{
+ QRegExp regExp(QT_PREPEND_NAMESPACE(QString::fromLatin1)(QT_PREPEND_NAMESPACE(qt_file_dialog_filter_reg_exp)));
+ if (regExp.indexIn(filter) != -1)
+ return regExp.cap(1).trimmed();
+ return filter;
+}
+
+- (void)createTextField
+{
+ NSRect textRect = { { 0.0, 3.0 }, { 100.0, 25.0 } };
+ mTextField = [[NSTextField alloc] initWithFrame:textRect];
+ [[mTextField cell] setFont:[NSFont systemFontOfSize:
+ [NSFont systemFontSizeForControlSize:NSRegularControlSize]]];
+ [mTextField setAlignment:NSRightTextAlignment];
+ [mTextField setEditable:false];
+ [mTextField setSelectable:false];
+ [mTextField setBordered:false];
+ [mTextField setDrawsBackground:false];
+ if (mPriv){
+ [mTextField setStringValue:[self strip:mPriv->qFileDialogUi->fileTypeLabel->text()]];
+ } else
+ [mTextField setStringValue:QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(QT_PREPEND_NAMESPACE(QFileDialog::tr)("Files of type:"))];
+}
+
+- (void)createPopUpButton:(const QString &)selectedFilter hideDetails:(BOOL)hideDetails
+{
+ NSRect popUpRect = { { 100.0, 5.0 }, { 250.0, 25.0 } };
+ mPopUpButton = [[NSPopUpButton alloc] initWithFrame:popUpRect pullsDown:NO];
+ [mPopUpButton setTarget:self];
+ [mPopUpButton setAction:@selector(filterChanged:)];
+
+ QStringList *filters = mNameFilterDropDownList;
+ if (filters->size() > 0){
+ for (int i=0; i<mNameFilterDropDownList->size(); ++i) {
+ QString filter = hideDetails ? [self removeExtensions:filters->at(i)] : filters->at(i);
+ [mPopUpButton addItemWithTitle:QT_PREPEND_NAMESPACE(qt_mac_QStringToNSString)(filter)];
+ if (filters->at(i).startsWith(selectedFilter))
+ [mPopUpButton selectItemAtIndex:i];
+ }
+ }
+}
+
+- (QStringList) findStrippedFilterWithVisualFilterName:(QString)name
+{
+ for (int i=0; i<mNameFilterDropDownList->size(); ++i) {
+ if (mNameFilterDropDownList->at(i).startsWith(name))
+ return qt_clean_filter_list(mNameFilterDropDownList->at(i));
+ }
+ return QStringList();
+}
+
+- (void)createAccessory
+{
+ NSRect accessoryRect = { { 0.0, 0.0 }, { 450.0, 33.0 } };
+ mAccessoryView = [[NSView alloc] initWithFrame:accessoryRect];
+ [mAccessoryView addSubview:mTextField];
+ [mAccessoryView addSubview:mPopUpButton];
+}
+
+@end
+
+QT_BEGIN_NAMESPACE
+
+void QFileDialogPrivate::QNSOpenSavePanelDelegate_selectionChanged(const QString &newPath)
+{
+ emit q_func()->currentChanged(newPath);
+}
+
+void QFileDialogPrivate::QNSOpenSavePanelDelegate_panelClosed(bool accepted)
+{
+ if (accepted)
+ q_func()->accept();
+ else
+ q_func()->reject();
+}
+
+void QFileDialogPrivate::QNSOpenSavePanelDelegate_directoryEntered(const QString &newDir)
+{
+ setLastVisitedDirectory(newDir);
+ emit q_func()->directoryEntered(newDir);
+}
+
+void QFileDialogPrivate::QNSOpenSavePanelDelegate_filterSelected(int menuIndex)
+{
+ emit q_func()->filterSelected(nameFilters.at(menuIndex));
+}
+
+extern OSErr qt_mac_create_fsref(const QString &, FSRef *); // qglobal.cpp
+extern void qt_mac_to_pascal_string(QString s, Str255 str, TextEncoding encoding=0, int len=-1); // qglobal.cpp
+
+void QFileDialogPrivate::setDirectory_sys(const QString &directory)
+{
+#ifndef QT_MAC_USE_COCOA
+ if (directory == mCurrentLocation)
+ return;
+ mCurrentLocation = directory;
+ emit q_func()->directoryEntered(mCurrentLocation);
+
+ FSRef fsRef;
+ if (qt_mac_create_fsref(directory, &fsRef) == noErr) {
+ AEDesc desc;
+ if (AECreateDesc(typeFSRef, &fsRef, sizeof(FSRef), &desc) == noErr)
+ NavCustomControl(mDialog, kNavCtlSetLocation, (void*)&desc);
+ }
+#else
+ QMacCocoaAutoReleasePool pool;
+ QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ [delegate->mSavePanel setDirectory:qt_mac_QStringToNSString(directory)];
+#endif
+}
+
+QString QFileDialogPrivate::directory_sys() const
+{
+#ifndef QT_MAC_USE_COCOA
+ return mCurrentLocation;
+#else
+ QMacCocoaAutoReleasePool pool;
+ QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ return qt_mac_NSStringToQString([delegate->mSavePanel directory]);
+#endif
+}
+
+void QFileDialogPrivate::selectFile_sys(const QString &filename)
+{
+ QString filePath = filename;
+ if (QDir::isRelativePath(filePath))
+ filePath = QFileInfo(directory_sys(), filePath).filePath();
+
+#ifndef QT_MAC_USE_COCOA
+ // Update the selection list immidiatly, so
+ // subsequent calls to selectedFiles() gets correct:
+ mCurrentSelectionList.clear();
+ mCurrentSelectionList << filename;
+ if (mCurrentSelection != filename){
+ mCurrentSelection = filename;
+ emit q_func()->currentChanged(mCurrentSelection);
+ }
+
+ AEDescList descList;
+ if (AECreateList(0, 0, false, &descList) != noErr)
+ return;
+
+ FSRef fsRef;
+ if (qt_mac_create_fsref(filePath, &fsRef) == noErr) {
+ AEDesc desc;
+ if (AECreateDesc(typeFSRef, &fsRef, sizeof(FSRef), &desc) == noErr){
+ if (AEPutDesc(&descList, 0, &desc) == noErr)
+ NavCustomControl(mDialog, kNavCtlSetSelection, (void*)&descList);
+ }
+ }
+
+ // Type the file name into the save dialog's text field:
+ UInt8 *strBuffer = (UInt8 *)malloc(1024);
+ qt_mac_to_pascal_string(QFileInfo(filename).fileName(), strBuffer);
+ NavCustomControl(mDialog, kNavCtlSetEditFileName, strBuffer);
+ free(strBuffer);
+#else
+ // There seems to no way to select a file once the dialog is running.
+ // So do the next best thing, set the file's directory:
+ setDirectory_sys(QFileInfo(filePath).absolutePath());
+#endif
+}
+
+QStringList QFileDialogPrivate::selectedFiles_sys() const
+{
+#ifndef QT_MAC_USE_COCOA
+ if (q_func()->acceptMode() == QFileDialog::AcceptOpen){
+ return mCurrentSelectionList;
+ } else {
+ return QStringList() << mCurrentLocation + QLatin1Char('/')
+ + QCFString::toQString(NavDialogGetSaveFileName(mDialog));
+ }
+#else
+ QMacCocoaAutoReleasePool pool;
+ QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ return [delegate selectedFiles];
+#endif
+}
+
+void QFileDialogPrivate::setNameFilters_sys(const QStringList &filters)
+{
+#ifndef QT_MAC_USE_COCOA
+ Q_UNUSED(filters);
+#else
+ QMacCocoaAutoReleasePool pool;
+ QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ bool hideDetails = q_func()->testOption(QFileDialog::HideNameFilterDetails);
+ [delegate setNameFilters:filters hideDetails:hideDetails];
+#endif
+}
+
+void QFileDialogPrivate::setFilter_sys()
+{
+#ifndef QT_MAC_USE_COCOA
+#else
+ Q_Q(QFileDialog);
+ QMacCocoaAutoReleasePool pool;
+ QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ *(delegate->mQDirFilter) = model->filter();
+ delegate->mFileMode = fileMode;
+ [delegate->mSavePanel setTitle:qt_mac_QStringToNSString(q->windowTitle())];
+ [delegate->mSavePanel setPrompt:[delegate strip:acceptLabel]];
+ if (fileNameLabelExplicitlySat)
+ [delegate->mSavePanel setNameFieldLabel:[delegate strip:qFileDialogUi->fileNameLabel->text()]];
+
+ [delegate updateProperties];
+#endif
+}
+
+void QFileDialogPrivate::selectNameFilter_sys(const QString &filter)
+{
+ int index = nameFilters.indexOf(filter);
+ if (index != -1) {
+#ifndef QT_MAC_USE_COCOA
+ NavMenuItemSpec navSpec;
+ bzero(&navSpec, sizeof(NavMenuItemSpec));
+ navSpec.menuType = index;
+ NavCustomControl(mDialog, kNavCtlSelectCustomType, &navSpec);
+#else
+ QMacCocoaAutoReleasePool pool;
+ QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ [delegate->mPopUpButton selectItemAtIndex:index];
+ [delegate filterChanged:nil];
+#endif
+ }
+}
+
+QString QFileDialogPrivate::selectedNameFilter_sys() const
+{
+#ifndef QT_MAC_USE_COCOA
+ int index = filterInfo.currentSelection;
+#else
+ QMacCocoaAutoReleasePool pool;
+ QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ int index = [delegate->mPopUpButton indexOfSelectedItem];
+#endif
+ return index != -1 ? nameFilters.at(index) : QString();
+}
+
+void QFileDialogPrivate::deleteNativeDialog_sys()
+{
+#ifndef QT_MAC_USE_COCOA
+ if (mDialog)
+ NavDialogDispose(mDialog);
+ mDialog = 0;
+ mDialogStarted = false;
+#else
+ QMacCocoaAutoReleasePool pool;
+ [reinterpret_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate) release];
+ mDelegate = 0;
+#endif
+ nativeDialogInUse = false;
+}
+
+bool QFileDialogPrivate::setVisible_sys(bool visible)
+{
+ Q_Q(QFileDialog);
+ if (!visible == q->isHidden())
+ return false;
+
+ if (q->windowFlags() & Qt::WindowStaysOnTopHint) {
+ // The native file dialog tries all it can to stay
+ // on the NSModalPanel level. And it might also show
+ // its own "create directory" dialog that we cannot control.
+ // So we need to use the non-native version in this case...
+ return false;
+ }
+
+#ifndef QT_MAC_USE_COCOA
+ return visible ? showCarbonNavServicesDialog() : hideCarbonNavServicesDialog();
+#else
+ return visible ? showCocoaFilePanel() : hideCocoaFilePanel();
+#endif
+}
+
+#ifndef QT_MAC_USE_COCOA
+Boolean QFileDialogPrivate::qt_mac_filedialog_filter_proc(AEDesc *theItem, void *info,
+ void *data, NavFilterModes)
+{
+ QFileDialogPrivate *fileDialogPrivate = static_cast<QFileDialogPrivate *>(data);
+
+ if (!fileDialogPrivate || fileDialogPrivate->filterInfo.filters.isEmpty()
+ || (fileDialogPrivate->filterInfo.currentSelection < 0
+ && fileDialogPrivate->filterInfo.currentSelection
+ >= fileDialogPrivate->filterInfo.filters.size()))
+ return true;
+
+ NavFileOrFolderInfo *theInfo = static_cast<NavFileOrFolderInfo *>(info);
+ QString file;
+ QString path;
+ const QtMacFilterName &fn
+ = fileDialogPrivate->filterInfo.filters.at(fileDialogPrivate->filterInfo.currentSelection);
+ if (theItem->descriptorType == typeFSRef) {
+ FSRef ref;
+ AEGetDescData(theItem, &ref, sizeof(ref));
+ UInt8 str_buffer[1024];
+ FSRefMakePath(&ref, str_buffer, 1024);
+ path = QString::fromUtf8(reinterpret_cast<const char *>(str_buffer));
+ int slsh = path.lastIndexOf(QLatin1Char('/'));
+ if (slsh != -1)
+ file = path.right(path.length() - slsh - 1);
+ else
+ file = path;
+ }
+ QStringList reg = fn.regexp.split(QLatin1String(";"));
+ for (QStringList::const_iterator it = reg.constBegin(); it != reg.constEnd(); ++it) {
+ QRegExp rg(*it, Qt::CaseInsensitive, QRegExp::Wildcard);
+#ifdef DEBUG_FILEDIALOG_FILTERS
+ qDebug("QFileDialogPrivate::qt_mac_filedialog_filter_proc:%d, asked to filter.. %s (%s)", __LINE__,
+ qPrintable(file), qPrintable(*it));
+#endif
+ if (rg.exactMatch(file))
+ return true;
+ }
+
+ if (theInfo->isFolder) {
+ if ([[NSWorkspace sharedWorkspace] isFilePackageAtPath:qt_mac_QStringToNSString(path)])
+ return false;
+ return true;
+ }
+ return false;
+}
+
+void QFileDialogPrivate::qt_mac_filedialog_event_proc(const NavEventCallbackMessage msg,
+ NavCBRecPtr p, NavCallBackUserData data)
+{
+ QFileDialogPrivate *fileDialogPrivate = static_cast<QFileDialogPrivate *>(data);
+
+ switch(msg) {
+ case kNavCBPopupMenuSelect: {
+ NavMenuItemSpec *s = static_cast<NavMenuItemSpec *>(p->eventData.eventDataParms.param);
+ if (int(s->menuType) != fileDialogPrivate->filterInfo.currentSelection) {
+ fileDialogPrivate->filterInfo.currentSelection = s->menuType;
+ emit fileDialogPrivate->q_func()->filterSelected(fileDialogPrivate->nameFilters.at(s->menuType));
+ }
+ if (fileDialogPrivate->acceptMode == QFileDialog::AcceptSave) {
+ QString base = QCFString::toQString(NavDialogGetSaveFileName(p->context));
+ QFileInfo fi(base);
+ base = fi.completeBaseName();
+ const QtMacFilterName &fn = fileDialogPrivate->filterInfo.filters.at(
+ fileDialogPrivate->filterInfo.currentSelection);
+ QStringList reg = fn.regexp.split(QLatin1String(";"), QString::SkipEmptyParts);
+ if (reg.count()) {
+ QString r = reg.first();
+ r = r.right(r.length()-1); // Strip the *
+ base += r; //"." + QString::number(s->menuType);
+ }
+ NavDialogSetSaveFileName(p->context, QCFString::toCFStringRef(base));
+ }
+#ifdef DEBUG_FILEDIALOG_FILTERS
+ qDebug("QFileDialogPrivate::qt_mac_filedialog_event_proc:%d - Selected a filter: %ld", __LINE__, s->menuType);
+#endif
+ break; }
+ case kNavCBStart:{
+ fileDialogPrivate->mDialogStarted = true;
+ // Set selected file:
+ QModelIndexList indexes = fileDialogPrivate->qFileDialogUi->listView->selectionModel()->selectedRows();
+ QString selected;
+ if (!indexes.isEmpty())
+ selected = indexes.at(0).data(QFileSystemModel::FilePathRole).toString();
+ else
+ selected = fileDialogPrivate->typedFiles().value(0);
+ fileDialogPrivate->selectFile_sys(selected);
+ fileDialogPrivate->selectNameFilter_sys(fileDialogPrivate->qFileDialogUi->fileTypeCombo->currentText());
+ break; }
+ case kNavCBSelectEntry:{
+ // Event: Current selection has changed.
+ QStringList prevSelectionList = fileDialogPrivate->mCurrentSelectionList;
+ fileDialogPrivate->mCurrentSelectionList.clear();
+ QString fileNameToEmit;
+
+ AEDescList *descList = (AEDescList *)p->eventData.eventDataParms.param;
+ // Get the number of files selected:
+ UInt8 strBuffer[1024];
+ long count;
+ OSErr err = AECountItems(descList, &count);
+ if (err != noErr || !count)
+ break;
+
+ for (long index=1; index<=count; ++index) {
+ FSRef ref;
+ err = AEGetNthPtr(descList, index, typeFSRef, 0, 0, &ref, sizeof(ref), 0);
+ if (err != noErr)
+ break;
+ FSRefMakePath(&ref, strBuffer, 1024);
+ QString selected = QString::fromUtf8((const char *)strBuffer);
+ fileDialogPrivate->mCurrentSelectionList << selected;
+ if (!prevSelectionList.contains(selected))
+ fileNameToEmit = selected;
+ }
+
+ if (!fileNameToEmit.isEmpty() && fileNameToEmit != fileDialogPrivate->mCurrentSelection)
+ emit fileDialogPrivate->q_func()->currentChanged(fileNameToEmit);
+ fileDialogPrivate->mCurrentSelection = fileNameToEmit;
+ break; }
+ case kNavCBShowDesktop:
+ case kNavCBNewLocation:{
+ // Event: Current directory has changed.
+ AEDesc *desc = (AEDesc *)p->eventData.eventDataParms.param;
+ FSRef ref;
+ AEGetDescData(desc, &ref, sizeof(ref));
+ UInt8 *strBuffer = (UInt8 *)malloc(1024);
+ FSRefMakePath(&ref, strBuffer, 1024);
+ QString newLocation = QString::fromUtf8((const char *)strBuffer);
+ free(strBuffer);
+ if (fileDialogPrivate->mCurrentLocation != newLocation){
+ fileDialogPrivate->mCurrentLocation = newLocation;
+ QFileDialog::FileMode mode = fileDialogPrivate->fileMode;
+ if (mode == QFileDialog::AnyFile || mode == QFileDialog::ExistingFile
+ || mode == QFileDialog::ExistingFiles){
+ // When changing directory, the current selection is cleared if
+ // we are supposed to be selecting files only:
+ if (!fileDialogPrivate->mCurrentSelection.isEmpty()){
+ fileDialogPrivate->mCurrentSelectionList.clear();
+ fileDialogPrivate->mCurrentSelection.clear();
+ emit fileDialogPrivate->q_func()->currentChanged(fileDialogPrivate->mCurrentSelection);
+ }
+ }
+ fileDialogPrivate->setLastVisitedDirectory(newLocation);
+ emit fileDialogPrivate->q_func()->directoryEntered(newLocation);
+ }
+ break; }
+ case kNavCBAccept:
+ fileDialogPrivate->mDialogClosed = true;
+ fileDialogPrivate->q_func()->accept();
+ break;
+ case kNavCBCancel:
+ fileDialogPrivate->mDialogClosed = true;
+ fileDialogPrivate->q_func()->reject();
+ break;
+ }
+}
+
+static QFileDialogPrivate::QtMacFilterName qt_mac_extract_filter(const QString &rawFilter, bool showDetails)
+{
+ QFileDialogPrivate::QtMacFilterName ret;
+ ret.filter = rawFilter;
+ QString result = rawFilter;
+ QRegExp r(QString::fromLatin1(qt_file_dialog_filter_reg_exp));
+ int index = r.indexIn(result);
+ if (index >= 0)
+ result = r.cap(2);
+
+ if (showDetails) {
+ ret.description = rawFilter;
+ } else {
+ if (index >= 0)
+ ret.description = r.cap(1).trimmed();
+ if (ret.description.isEmpty())
+ ret.description = result;
+ }
+ ret.regexp = result.replace(QLatin1Char(' '), QLatin1Char(';'));
+ return ret;
+}
+
+static QList<QFileDialogPrivate::QtMacFilterName> qt_mac_make_filters_list(const QString &filter, bool showDetails)
+{
+#ifdef DEBUG_FILEDIALOG_FILTERS
+ qDebug("QFileDialog:%d - Got filter (%s)", __LINE__, filter.latin1());
+#endif
+
+ QList<QFileDialogPrivate::QtMacFilterName> ret;
+ QString f(filter);
+ if (f.isEmpty())
+ f = QFileDialog::tr("All Files (*)");
+ if (f.isEmpty())
+ return ret;
+ QStringList filts = qt_make_filter_list(f);
+ for (QStringList::const_iterator it = filts.constBegin(); it != filts.constEnd(); ++it) {
+ QFileDialogPrivate::QtMacFilterName filter = qt_mac_extract_filter(*it, showDetails);
+#ifdef DEBUG_FILEDIALOG_FILTERS
+ qDebug("QFileDialog:%d Split out filter (%d) '%s' '%s' [%s]", __LINE__, ret.count(),
+ filter->regxp.latin1(), filter->description.latin1(), (*it).latin1());
+#endif
+ ret.append(filter);
+ }
+ return ret;
+}
+
+void QFileDialogPrivate::createNavServicesDialog()
+{
+ Q_Q(QFileDialog);
+ if (mDialog)
+ deleteNativeDialog_sys();
+
+ NavDialogCreationOptions navOptions;
+ NavGetDefaultDialogCreationOptions(&navOptions);
+
+ // Translate QFileDialog settings into NavDialog options:
+ if (qt_mac_is_macsheet(q)) {
+ navOptions.modality = kWindowModalityWindowModal;
+ navOptions.parentWindow = qt_mac_window_for(q->parentWidget());
+ } else if (q->windowModality() == Qt::ApplicationModal)
+ navOptions.modality = kWindowModalityAppModal;
+ else
+ navOptions.modality = kWindowModalityNone;
+ navOptions.optionFlags |= kNavSupportPackages;
+ if (q->testOption(QFileDialog::DontConfirmOverwrite))
+ navOptions.optionFlags |= kNavDontConfirmReplacement;
+ if (fileMode != QFileDialog::ExistingFiles)
+ navOptions.optionFlags &= ~kNavAllowMultipleFiles;
+
+ navOptions.windowTitle = QCFString::toCFStringRef(q->windowTitle());
+
+ navOptions.location.h = -1;
+ navOptions.location.v = -1;
+
+ QWidget *parent = q->parentWidget();
+ if (parent && parent->isVisible()) {
+ WindowClass wclass;
+ GetWindowClass(qt_mac_window_for(parent), &wclass);
+ parent = parent->window();
+ QString s = parent->windowTitle();
+ navOptions.clientName = QCFString::toCFStringRef(s);
+ }
+
+ filterInfo.currentSelection = 0;
+ filterInfo.filters = qt_mac_make_filters_list(nameFilters.join(QLatin1String(";;")), q->isNameFilterDetailsVisible());
+ QCFType<CFArrayRef> filterArray;
+ if (filterInfo.filters.size() > 1) {
+ int i = 0;
+ CFStringRef *cfstringArray = static_cast<CFStringRef *>(malloc(sizeof(CFStringRef)
+ * filterInfo.filters.size()));
+ for (i = 0; i < filterInfo.filters.size(); ++i) {
+ cfstringArray[i] = QCFString::toCFStringRef(filterInfo.filters.at(i).description);
+ }
+ filterArray = CFArrayCreate(kCFAllocatorDefault,
+ reinterpret_cast<const void **>(cfstringArray), filterInfo.filters.size(),
+ &kCFTypeArrayCallBacks);
+ navOptions.popupExtension = filterArray;
+ free(cfstringArray);
+ }
+
+ if (q->acceptMode() == QFileDialog::AcceptSave) {
+ if (NavCreatePutFileDialog(&navOptions, 'cute', kNavGenericSignature,
+ QFileDialogPrivate::qt_mac_filedialog_event_proc, this, &mDialog)) {
+ qDebug("Shouldn't happen %s:%d", __FILE__, __LINE__);
+ return;
+ }
+ } else if (fileMode == QFileDialog::DirectoryOnly || fileMode == QFileDialog::Directory) {
+ if (NavCreateChooseFolderDialog(&navOptions,
+ QFileDialogPrivate::qt_mac_filedialog_event_proc, 0, this, &mDialog)) {
+ qDebug("Shouldn't happen %s:%d", __FILE__, __LINE__);
+ return;
+ }
+ } else {
+ if (NavCreateGetFileDialog(&navOptions, 0,
+ QFileDialogPrivate::qt_mac_filedialog_event_proc, 0,
+ QFileDialogPrivate::qt_mac_filedialog_filter_proc, this, &mDialog)) {
+ qDebug("Shouldn't happen %s:%d", __FILE__, __LINE__);
+ return;
+ }
+ }
+
+ // Set start-up directory:
+ if (mCurrentLocation.isEmpty())
+ mCurrentLocation = rootPath();
+ FSRef fsRef;
+ if (qt_mac_create_fsref(mCurrentLocation, &fsRef) == noErr) {
+ AEDesc desc;
+ if (AECreateDesc(typeFSRef, &fsRef, sizeof(FSRef), &desc) == noErr)
+ NavCustomControl(mDialog, kNavCtlSetLocation, (void*)&desc);
+ }
+}
+
+bool QFileDialogPrivate::showCarbonNavServicesDialog()
+{
+ Q_Q(QFileDialog);
+ if (q->acceptMode() == QFileDialog::AcceptSave && q->windowModality() == Qt::NonModal)
+ return false; // cannot do native no-modal save dialogs.
+ createNavServicesDialog();
+ mDialogClosed = false;
+ if (q->windowModality() != Qt::ApplicationModal)
+ NavDialogRun(mDialog);
+ return true;
+}
+
+bool QFileDialogPrivate::hideCarbonNavServicesDialog()
+{
+ if (!mDialogClosed){
+ mDialogClosed = true;
+ NavCustomControl(mDialog, kNavCtlCancel, 0);
+ }
+ return true;
+}
+
+#else // Cocoa
+
+void QFileDialogPrivate::createNSOpenSavePanelDelegate()
+{
+ Q_Q(QFileDialog);
+ if (mDelegate)
+ return;
+
+ bool selectDir = q->selectedFiles().isEmpty();
+ QString selection(selectDir ? q->directory().absolutePath() : q->selectedFiles().value(0));
+ QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = [[QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) alloc]
+ initWithAcceptMode:acceptMode
+ title:q->windowTitle()
+ hideNameFilterDetails:q->testOption(QFileDialog::HideNameFilterDetails)
+ qDirFilter:model->filter()
+ fileOptions:opts
+ fileMode:fileMode
+ selectFile:selection
+ confirmOverwrite:!q->testOption(QFileDialog::DontConfirmOverwrite)
+ priv:this];
+
+ mDelegate = delegate;
+}
+
+bool QFileDialogPrivate::showCocoaFilePanel()
+{
+ Q_Q(QFileDialog);
+ QMacCocoaAutoReleasePool pool;
+ createNSOpenSavePanelDelegate();
+ QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ if (qt_mac_is_macsheet(q))
+ [delegate showWindowModalSheet:q->parentWidget()];
+ else
+ [delegate showModelessPanel];
+ return true;
+}
+
+bool QFileDialogPrivate::hideCocoaFilePanel()
+{
+ if (!mDelegate){
+ // Nothing to do. We return false to leave the question
+ // open regarding whether or not to go native:
+ return false;
+ } else {
+ QMacCocoaAutoReleasePool pool;
+ QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ [delegate closePanel];
+ // Even when we hide it, we are still using a
+ // native dialog, so return true:
+ return true;
+ }
+}
+
+#endif
+
+void QFileDialogPrivate::mac_nativeDialogModalHelp()
+{
+ // Do a queued meta-call to open the native modal dialog so it opens after the new
+ // event loop has started to execute (in QDialog::exec). Using a timer rather than
+ // a queued meta call is intentional to ensure that the call is only delivered when
+ // [NSApp run] runs (timers are handeled special in cocoa). If NSApp is not
+ // running (which is the case if e.g a top-most QEventLoop has been
+ // interrupted, and the second-most event loop has not yet been reactivated (regardless
+ // if [NSApp run] is still on the stack)), showing a native modal dialog will fail.
+ if (nativeDialogInUse){
+ Q_Q(QFileDialog);
+ QTimer::singleShot(1, q, SLOT(_q_macRunNativeAppModalPanel()));
+ }
+}
+
+void QFileDialogPrivate::_q_macRunNativeAppModalPanel()
+{
+ QBoolBlocker nativeDialogOnTop(QApplicationPrivate::native_modal_dialog_active);
+#ifndef QT_MAC_USE_COCOA
+ NavDialogRun(mDialog);
+#else
+ Q_Q(QFileDialog);
+ QMacCocoaAutoReleasePool pool;
+ QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ [delegate runApplicationModalPanel];
+ dialogResultCode_sys() == QDialog::Accepted ? q->accept() : q->reject();
+#endif
+}
+
+QDialog::DialogCode QFileDialogPrivate::dialogResultCode_sys()
+{
+#ifndef QT_MAC_USE_COCOA
+ NavUserAction result = NavDialogGetUserAction(mDialog);
+ if (result == kNavUserActionCancel || result == kNavUserActionNone)
+ return QDialog::Rejected;
+ else
+ return QDialog::Accepted;
+#else
+ QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *>(mDelegate);
+ return [delegate dialogResultCode];
+#endif
+}
+
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_FILEDIALOG
+
diff --git a/src/widgets/dialogs/qfiledialog_p.h b/src/widgets/dialogs/qfiledialog_p.h
new file mode 100644
index 0000000000..882acdd758
--- /dev/null
+++ b/src/widgets/dialogs/qfiledialog_p.h
@@ -0,0 +1,427 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFILEDIALOG_P_H
+#define QFILEDIALOG_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QT_NO_FILEDIALOG
+
+#include "qfiledialog.h"
+#include "private/qdialog_p.h"
+#include "qplatformdefs.h"
+
+#include "qfilesystemmodel_p.h"
+#include <qlistview.h>
+#include <qtreeview.h>
+#include <qcombobox.h>
+#include <qtoolbutton.h>
+#include <qlabel.h>
+#include <qevent.h>
+#include <qlineedit.h>
+#include <qurl.h>
+#include <qstackedwidget.h>
+#include <qdialogbuttonbox.h>
+#include <qabstractproxymodel.h>
+#include <qcompleter.h>
+#include <qpointer.h>
+#include <qdebug.h>
+#include "qsidebar_p.h"
+#include "qfscompleter_p.h"
+#include "private/qguiplatformplugin_p.h"
+
+
+#if defined (Q_OS_UNIX)
+#include <unistd.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QFileDialogListView;
+class QFileDialogTreeView;
+class QFileDialogLineEdit;
+class QGridLayout;
+class QCompleter;
+class QHBoxLayout;
+class Ui_QFileDialog;
+
+
+struct QFileDialogArgs
+{
+ QFileDialogArgs() : parent(0), mode(QFileDialog::AnyFile) {}
+
+ QWidget *parent;
+ QString caption;
+ QString directory;
+ QString selection;
+ QString filter;
+ QFileDialog::FileMode mode;
+ QFileDialog::Options options;
+};
+
+#define UrlRole (Qt::UserRole + 1)
+
+class Q_AUTOTEST_EXPORT QFileDialogPrivate : public QDialogPrivate
+{
+ Q_DECLARE_PUBLIC(QFileDialog)
+
+public:
+ QFileDialogPrivate();
+
+ void createToolButtons();
+ void createMenuActions();
+ void createWidgets();
+
+ void init(const QString &directory = QString(), const QString &nameFilter = QString(),
+ const QString &caption = QString());
+ bool itemViewKeyboardEvent(QKeyEvent *event);
+ QString getEnvironmentVariable(const QString &string);
+ static QString workingDirectory(const QString &path);
+ static QString initialSelection(const QString &path);
+ QStringList typedFiles() const;
+ QStringList addDefaultSuffixToFiles(const QStringList filesToFix) const;
+ bool removeDirectory(const QString &path);
+
+ inline QModelIndex mapToSource(const QModelIndex &index) const;
+ inline QModelIndex mapFromSource(const QModelIndex &index) const;
+ inline QModelIndex rootIndex() const;
+ inline void setRootIndex(const QModelIndex &index) const;
+ inline QModelIndex select(const QModelIndex &index) const;
+ inline QString rootPath() const;
+
+ QLineEdit *lineEdit() const;
+
+ int maxNameLength(const QString &path) {
+#if defined(Q_OS_UNIX)
+ return ::pathconf(QFile::encodeName(path).data(), _PC_NAME_MAX);
+#elif defined(Q_OS_WIN)
+#ifndef Q_OS_WINCE
+ DWORD maxLength;
+ QString drive = path.left(3);
+ if (::GetVolumeInformation(reinterpret_cast<const wchar_t *>(drive.utf16()), NULL, 0, NULL, &maxLength, NULL, NULL, 0) == FALSE)
+ return -1;
+ return maxLength;
+#else
+ Q_UNUSED(path);
+ return MAX_PATH;
+#endif //Q_OS_WINCE
+#else
+ Q_UNUSED(path);
+#endif
+ return -1;
+ }
+
+ QString basename(const QString &path) const
+ {
+ int separator = QDir::toNativeSeparators(path).lastIndexOf(QDir::separator());
+ if (separator != -1)
+ return path.mid(separator + 1);
+ return path;
+ }
+
+ QDir::Filters filterForMode(QDir::Filters filters) const
+ {
+ if (fileMode == QFileDialog::DirectoryOnly) {
+ filters |= QDir::Drives | QDir::AllDirs | QDir::Dirs;
+ filters &= ~QDir::Files;
+ } else {
+ filters |= QDir::Drives | QDir::AllDirs | QDir::Files | QDir::Dirs;
+ }
+ return filters;
+ }
+
+ QAbstractItemView *currentView() const;
+
+ static inline QString toInternal(const QString &path)
+ {
+#if defined(Q_FS_FAT) || defined(Q_OS_OS2EMX) || defined(Q_OS_SYMBIAN)
+ QString n(path);
+ for (int i = 0; i < (int)n.length(); ++i)
+ if (n[i] == QLatin1Char('\\')) n[i] = QLatin1Char('/');
+#if defined(Q_OS_WINCE)
+ if ((n.size() > 1) && (n.startsWith(QLatin1String("//"))))
+ n = n.mid(1);
+#endif
+ return n;
+#else // the compile should optimize away this
+ return path;
+#endif
+ }
+
+ void setLastVisitedDirectory(const QString &dir);
+ void retranslateWindowTitle();
+ void retranslateStrings();
+ void emitFilesSelected(const QStringList &files);
+
+ void _q_goHome();
+ void _q_pathChanged(const QString &);
+ void _q_navigateBackward();
+ void _q_navigateForward();
+ void _q_navigateToParent();
+ void _q_createDirectory();
+ void _q_showListView();
+ void _q_showDetailsView();
+ void _q_showContextMenu(const QPoint &position);
+ void _q_renameCurrent();
+ void _q_deleteCurrent();
+ void _q_showHidden();
+ void _q_showHeader(QAction *);
+ void _q_updateOkButton();
+ void _q_currentChanged(const QModelIndex &index);
+ void _q_enterDirectory(const QModelIndex &index);
+ void _q_goToDirectory(const QString &);
+ void _q_useNameFilter(int index);
+ void _q_selectionChanged();
+ void _q_goToUrl(const QUrl &url);
+ void _q_autoCompleteFileName(const QString &);
+ void _q_rowsInserted(const QModelIndex & parent);
+ void _q_fileRenamed(const QString &path, const QString oldName, const QString newName);
+
+ // layout
+#ifndef QT_NO_PROXYMODEL
+ QAbstractProxyModel *proxyModel;
+#endif
+
+ // data
+ QStringList watching;
+ QFileSystemModel *model;
+
+#ifndef QT_NO_FSCOMPLETER
+ QFSCompleter *completer;
+#endif //QT_NO_FSCOMPLETER
+
+ QFileDialog::FileMode fileMode;
+ QFileDialog::AcceptMode acceptMode;
+ bool confirmOverwrite;
+ QString defaultSuffix;
+ QString setWindowTitle;
+
+ QStringList currentHistory;
+ int currentHistoryLocation;
+
+ QAction *renameAction;
+ QAction *deleteAction;
+ QAction *showHiddenAction;
+ QAction *newFolderAction;
+
+ bool useDefaultCaption;
+ bool defaultFileTypes;
+ bool fileNameLabelExplicitlySat;
+ QStringList nameFilters;
+
+ // Members for using native dialogs:
+ bool nativeDialogInUse;
+ // setVisible_sys returns true if it ends up showing a native
+ // dialog. Returning false means that a non-native dialog must be
+ // used instead.
+ bool canBeNativeDialog();
+ bool setVisible_sys(bool visible);
+ void deleteNativeDialog_sys();
+ QDialog::DialogCode dialogResultCode_sys();
+
+ void setDirectory_sys(const QString &directory);
+ QString directory_sys() const;
+ void selectFile_sys(const QString &filename);
+ QStringList selectedFiles_sys() const;
+ void setFilter_sys();
+ void setNameFilters_sys(const QStringList &filters);
+ void selectNameFilter_sys(const QString &filter);
+ QString selectedNameFilter_sys() const;
+ //////////////////////////////////////////////
+
+#if defined(Q_WS_MAC)
+ void *mDelegate;
+#ifndef QT_MAC_USE_COCOA
+ NavDialogRef mDialog;
+ bool mDialogStarted;
+ bool mDialogClosed;
+ QString mCurrentLocation;
+ QString mCurrentSelection;
+ QStringList mCurrentSelectionList;
+
+ struct QtMacFilterName {
+ QString description;
+ QString regexp;
+ QString filter;
+ };
+ struct QtMacNavFilterInfo {
+ QtMacNavFilterInfo() : currentSelection(-1) {}
+ int currentSelection;
+ QList<QtMacFilterName> filters;
+ } filterInfo;
+
+ static void qt_mac_filedialog_event_proc(const NavEventCallbackMessage msg, NavCBRecPtr p,
+ NavCallBackUserData data);
+ static Boolean qt_mac_filedialog_filter_proc(AEDesc *theItem, void *info, void *data,
+ NavFilterModes);
+ bool showCarbonNavServicesDialog();
+ bool hideCarbonNavServicesDialog();
+ void createNavServicesDialog();
+#else
+ bool showCocoaFilePanel();
+ bool hideCocoaFilePanel();
+#endif
+ void createNSOpenSavePanelDelegate();
+ void QNSOpenSavePanelDelegate_selectionChanged(const QString &newPath);
+ void QNSOpenSavePanelDelegate_panelClosed(bool accepted);
+ void QNSOpenSavePanelDelegate_directoryEntered(const QString &newDir);
+ void QNSOpenSavePanelDelegate_filterSelected(int menuIndex);
+ void _q_macRunNativeAppModalPanel();
+ void mac_nativeDialogModalHelp();
+#endif
+
+ QScopedPointer<Ui_QFileDialog> qFileDialogUi;
+
+ QString acceptLabel;
+
+ QPointer<QObject> receiverToDisconnectOnClose;
+ QByteArray memberToDisconnectOnClose;
+ QByteArray signalToDisconnectOnClose;
+
+ QFileDialog::Options opts;
+
+ ~QFileDialogPrivate();
+
+private:
+ Q_DISABLE_COPY(QFileDialogPrivate)
+};
+
+class QFileDialogLineEdit : public QLineEdit
+{
+public:
+ QFileDialogLineEdit(QWidget *parent = 0) : QLineEdit(parent), hideOnEsc(false), d_ptr(0){}
+ void init(QFileDialogPrivate *d_pointer) {d_ptr = d_pointer; }
+ void keyPressEvent(QKeyEvent *e);
+ bool hideOnEsc;
+private:
+ QFileDialogPrivate *d_ptr;
+};
+
+class QFileDialogComboBox : public QComboBox
+{
+public:
+ QFileDialogComboBox(QWidget *parent = 0) : QComboBox(parent), urlModel(0) {}
+ void init(QFileDialogPrivate *d_pointer);
+ void showPopup();
+ void setHistory(const QStringList &paths);
+ QStringList history() const { return m_history; }
+ void paintEvent(QPaintEvent *);
+
+private:
+ QUrlModel *urlModel;
+ QFileDialogPrivate *d_ptr;
+ QStringList m_history;
+};
+
+class QFileDialogListView : public QListView
+{
+public:
+ QFileDialogListView(QWidget *parent = 0);
+ void init(QFileDialogPrivate *d_pointer);
+ QSize sizeHint() const;
+protected:
+ void keyPressEvent(QKeyEvent *e);
+private:
+ QFileDialogPrivate *d_ptr;
+};
+
+class QFileDialogTreeView : public QTreeView
+{
+public:
+ QFileDialogTreeView(QWidget *parent);
+ void init(QFileDialogPrivate *d_pointer);
+ QSize sizeHint() const;
+
+protected:
+ void keyPressEvent(QKeyEvent *e);
+private:
+ QFileDialogPrivate *d_ptr;
+};
+
+inline QModelIndex QFileDialogPrivate::mapToSource(const QModelIndex &index) const {
+#ifdef QT_NO_PROXYMODEL
+ return index;
+#else
+ return proxyModel ? proxyModel->mapToSource(index) : index;
+#endif
+}
+inline QModelIndex QFileDialogPrivate::mapFromSource(const QModelIndex &index) const {
+#ifdef QT_NO_PROXYMODEL
+ return index;
+#else
+ return proxyModel ? proxyModel->mapFromSource(index) : index;
+#endif
+}
+
+inline QString QFileDialogPrivate::rootPath() const {
+ return model->rootPath();
+}
+
+#ifndef Q_WS_MAC
+ // Dummies for platforms that don't use native dialogs:
+ inline void QFileDialogPrivate::deleteNativeDialog_sys() { qt_guiPlatformPlugin()->fileDialogDelete(q_func()); }
+ inline bool QFileDialogPrivate::setVisible_sys(bool visible) { return qt_guiPlatformPlugin()->fileDialogSetVisible(q_func(), visible); }
+ inline QDialog::DialogCode QFileDialogPrivate::dialogResultCode_sys(){ return qt_guiPlatformPlugin()->fileDialogResultCode(q_func()); }
+ inline void QFileDialogPrivate::setDirectory_sys(const QString &directory) { qt_guiPlatformPlugin()->fileDialogSetDirectory(q_func(), directory); }
+ inline QString QFileDialogPrivate::directory_sys() const { return qt_guiPlatformPlugin()->fileDialogDirectory(q_func()); }
+ inline void QFileDialogPrivate::selectFile_sys(const QString &filename) { qt_guiPlatformPlugin()->fileDialogSelectFile(q_func(), filename); }
+ inline QStringList QFileDialogPrivate::selectedFiles_sys() const { return qt_guiPlatformPlugin()->fileDialogSelectedFiles(q_func()); }
+ inline void QFileDialogPrivate::setFilter_sys() { qt_guiPlatformPlugin()->fileDialogSetFilter(q_func()); }
+ inline void QFileDialogPrivate::setNameFilters_sys(const QStringList &filters) { qt_guiPlatformPlugin()->fileDialogSetNameFilters(q_func(), filters); }
+ inline void QFileDialogPrivate::selectNameFilter_sys(const QString &filter) { qt_guiPlatformPlugin()->fileDialogSelectNameFilter(q_func(), filter); }
+ inline QString QFileDialogPrivate::selectedNameFilter_sys() const { return qt_guiPlatformPlugin()->fileDialogSelectedNameFilter(q_func()); }
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_FILEDIALOG
+
+#endif // QFILEDIALOG_P_H
diff --git a/src/widgets/dialogs/qfiledialog_symbian.cpp b/src/widgets/dialogs/qfiledialog_symbian.cpp
new file mode 100644
index 0000000000..ed9895019f
--- /dev/null
+++ b/src/widgets/dialogs/qfiledialog_symbian.cpp
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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 "qfiledialog.h"
+
+#ifndef QT_NO_FILEDIALOG
+
+#include <private/qfiledialog_p.h>
+#if defined(Q_WS_S60) && defined(SYMBIAN_VERSION_SYMBIAN3)
+#include <driveinfo.h>
+#include <AknCommonDialogsDynMem.h>
+#include <CAknMemorySelectionDialogMultiDrive.h>
+#include <MAknFileFilter.h>
+#endif
+#include "private/qcore_symbian_p.h"
+
+QT_BEGIN_NAMESPACE
+
+extern QStringList qt_make_filter_list(const QString &filter); // defined in qfiledialog.cpp
+extern QStringList qt_clean_filter_list(const QString &filter); // defined in qfiledialog.cpp
+
+enum DialogMode { DialogOpen, DialogSave, DialogFolder };
+#if defined(Q_WS_S60) && defined(SYMBIAN_VERSION_SYMBIAN3)
+class CExtensionFilter : public MAknFileFilter
+{
+public:
+ void setFilter(const QString filter)
+ {
+ QStringList unparsedFiltersList = qt_make_filter_list(filter);
+ QStringList filterList;
+ filterRxList.clear();
+
+ foreach (QString unparsedFilter, unparsedFiltersList) {
+ filterList << qt_clean_filter_list(unparsedFilter);
+ }
+ foreach (QString currentFilter, filterList) {
+ QRegExp filterRx(currentFilter, Qt::CaseInsensitive, QRegExp::Wildcard);
+ filterRxList << filterRx;
+ }
+ }
+
+ TBool Accept(const TDesC &/*aDriveAndPath*/, const TEntry &aEntry) const
+ {
+ //If no filter for files, all can be accepted
+ if (filterRxList.isEmpty())
+ return ETrue;
+
+ if (aEntry.IsDir())
+ return ETrue;
+
+ foreach (QRegExp rx, filterRxList) {
+ QString fileName = qt_TDesC2QString(aEntry.iName);
+ if (rx.exactMatch(fileName))
+ return ETrue;
+ }
+
+ return EFalse;
+ }
+
+private:
+ QList<QRegExp> filterRxList;
+};
+#endif
+
+static QString launchSymbianDialog(const QString dialogCaption, const QString startDirectory,
+ const QString filter, DialogMode dialogMode)
+{
+ QString selection;
+#if defined(Q_WS_S60) && defined(SYMBIAN_VERSION_SYMBIAN3)
+ TFileName startFolder;
+ if (!startDirectory.isEmpty()) {
+ QString dir = QDir::toNativeSeparators(QFileDialogPrivate::workingDirectory(startDirectory));
+ startFolder = qt_QString2TPtrC(dir);
+ }
+ TInt types = AknCommonDialogsDynMem::EMemoryTypeMMCExternal|
+ AknCommonDialogsDynMem::EMemoryTypeInternalMassStorage|
+ AknCommonDialogsDynMem::EMemoryTypePhone;
+
+ TPtrC titlePtr(qt_QString2TPtrC(dialogCaption));
+ TFileName target;
+ bool select = false;
+ int tryCount = 2;
+ while (tryCount--) {
+ TInt err(KErrNone);
+ TRAP(err,
+ if (dialogMode == DialogOpen) {
+ CExtensionFilter* extensionFilter = new (ELeave) CExtensionFilter;
+ CleanupStack::PushL(extensionFilter);
+ extensionFilter->setFilter(filter);
+ select = AknCommonDialogsDynMem::RunSelectDlgLD(types, target,
+ startFolder, 0, 0, titlePtr, extensionFilter);
+ CleanupStack::Pop(extensionFilter);
+ } else if (dialogMode == DialogSave) {
+ QString defaultFileName = QFileDialogPrivate::initialSelection(startDirectory);
+ target = qt_QString2TPtrC(defaultFileName);
+ select = AknCommonDialogsDynMem::RunSaveDlgLD(types, target,
+ startFolder, 0, 0, titlePtr);
+ } else if (dialogMode == DialogFolder) {
+ select = AknCommonDialogsDynMem::RunFolderSelectDlgLD(types, target, startFolder,
+ 0, 0, titlePtr, NULL, NULL);
+ }
+ );
+
+ if (err == KErrNone) {
+ tryCount = 0;
+ } else {
+ // Symbian native file dialog doesn't allow accessing files outside C:/Data
+ // It will always leave in that case, so default into QDir::rootPath() in error cases.
+ QString dir = QDir::toNativeSeparators(QDir::rootPath());
+ startFolder = qt_QString2TPtrC(dir);
+ }
+ }
+ if (select) {
+ QFileInfo fi(qt_TDesC2QString(target));
+ selection = fi.absoluteFilePath();
+ }
+#endif
+ return selection;
+}
+
+QString qtSymbianGetOpenFileName(const QString &caption,
+ const QString &dir,
+ const QString &filter)
+{
+ return launchSymbianDialog(caption, dir, filter, DialogOpen);
+}
+
+QStringList qtSymbianGetOpenFileNames(const QString &caption,
+ const QString &dir,
+ const QString &filter)
+{
+ QString fileName;
+ fileName.append(launchSymbianDialog(caption, dir, filter, DialogOpen));
+ QStringList fileList;
+ fileList << fileName;
+
+ return fileList;
+}
+
+QString qtSymbianGetSaveFileName(const QString &caption,
+ const QString &dir)
+{
+ return launchSymbianDialog(caption, dir, QString(), DialogSave);
+}
+
+QString qtSymbianGetExistingDirectory(const QString &caption,
+ const QString &dir)
+{
+ QString folderCaption;
+ if (!caption.isEmpty()) {
+ folderCaption.append(caption);
+ } else {
+ // Title for folder selection dialog is mandatory
+ folderCaption.append(QFileDialog::tr("Find Directory"));
+ }
+ return launchSymbianDialog(folderCaption, dir, QString(), DialogFolder);
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/widgets/dialogs/qfiledialog_win.cpp b/src/widgets/dialogs/qfiledialog_win.cpp
new file mode 100644
index 0000000000..114f4bedbc
--- /dev/null
+++ b/src/widgets/dialogs/qfiledialog_win.cpp
@@ -0,0 +1,825 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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 "qfiledialog.h"
+
+#ifndef QT_NO_FILEDIALOG
+
+#include <private/qfiledialog_p.h>
+#include <qapplication.h>
+#include <private/qapplication_p.h>
+#include <qt_windows.h>
+#include <qglobal.h>
+#include <qregexp.h>
+#include <qbuffer.h>
+#include <qdir.h>
+#include <qstringlist.h>
+#include <private/qsystemlibrary_p.h>
+#include "qfiledialog_win_p.h"
+
+#ifndef QT_NO_THREAD
+# include <private/qmutexpool_p.h>
+#endif
+
+#ifdef Q_WS_WINCE
+#include <commdlg.h>
+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
+
+
+typedef qt_LPITEMIDLIST (WINAPI *PtrSHBrowseForFolder)(qt_BROWSEINFO*);
+static PtrSHBrowseForFolder ptrSHBrowseForFolder = 0;
+typedef BOOL (WINAPI *PtrSHGetPathFromIDList)(qt_LPITEMIDLIST, LPWSTR);
+static PtrSHGetPathFromIDList ptrSHGetPathFromIDList = 0;
+typedef HRESULT (WINAPI *PtrSHGetMalloc)(LPMALLOC *);
+static PtrSHGetMalloc ptrSHGetMalloc = 0;
+
+
+QT_BEGIN_NAMESPACE
+
+static void qt_win_resolve_libs()
+{
+ static bool triedResolve = false;
+
+ if (!triedResolve) {
+#ifndef QT_NO_THREAD
+ // protect initialization
+ QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve));
+ // check triedResolve again, since another thread may have already
+ // done the initialization
+ if (triedResolve) {
+ // another thread did initialize the security function pointers,
+ // so we shouldn't do it again.
+ return;
+ }
+#endif
+
+ triedResolve = true;
+#if !defined(Q_WS_WINCE)
+ QSystemLibrary lib(L"shell32");
+ ptrSHBrowseForFolder = (PtrSHBrowseForFolder)lib.resolve("SHBrowseForFolderW");
+ ptrSHGetPathFromIDList = (PtrSHGetPathFromIDList)lib.resolve("SHGetPathFromIDListW");
+ ptrSHGetMalloc = (PtrSHGetMalloc)lib.resolve("SHGetMalloc");
+#else
+ // CE stores them in a different lib and does not use unicode version
+ HINSTANCE handle = LoadLibrary(L"Ceshell");
+ ptrSHBrowseForFolder = (PtrSHBrowseForFolder)GetProcAddress(handle, L"SHBrowseForFolder");
+ ptrSHGetPathFromIDList = (PtrSHGetPathFromIDList)GetProcAddress(handle, L"SHGetPathFromIDList");
+ ptrSHGetMalloc = (PtrSHGetMalloc)GetProcAddress(handle, L"SHGetMalloc");
+ if (ptrSHBrowseForFolder && ptrSHGetPathFromIDList && ptrSHGetMalloc)
+ qt_priv_ptr_valid = true;
+#endif
+ }
+}
+
+extern const char* qt_file_dialog_filter_reg_exp; // defined in qfiledialog.cpp
+extern QStringList qt_make_filter_list(const QString &filter);
+
+const int maxNameLen = 1023;
+const int maxMultiLen = 65535;
+
+// Returns the wildcard part of a filter.
+static QString qt_win_extract_filter(const QString &rawFilter)
+{
+ QString result = rawFilter;
+ QRegExp r(QString::fromLatin1(qt_file_dialog_filter_reg_exp));
+ int index = r.indexIn(result);
+ if (index >= 0)
+ result = r.cap(2);
+ QStringList list = result.split(QLatin1Char(' '));
+ for(QStringList::iterator it = list.begin(); it < list.end(); ++it) {
+ if (*it == QLatin1String("*")) {
+ *it = QLatin1String("*.*");
+ break;
+ }
+ }
+ return list.join(QLatin1String(";"));
+}
+
+static QStringList qt_win_make_filters_list(const QString &filter)
+{
+ QString f(filter);
+
+ if (f.isEmpty())
+ f = QFileDialog::tr("All Files (*.*)");
+
+ return qt_make_filter_list(f);
+}
+
+// Makes a NUL-oriented Windows filter from a Qt filter.
+static QString qt_win_filter(const QString &filter, bool hideFiltersDetails)
+{
+ QStringList filterLst = qt_win_make_filters_list(filter);
+ QStringList::Iterator it = filterLst.begin();
+ QString winfilters;
+ QRegExp r(QString::fromLatin1(qt_file_dialog_filter_reg_exp));
+ for (; it != filterLst.end(); ++it) {
+ QString subfilter = *it;
+ if (!subfilter.isEmpty()) {
+ if (hideFiltersDetails) {
+ int index = r.indexIn(subfilter);
+ if (index >= 0)
+ winfilters += r.cap(1);
+ } else {
+ winfilters += subfilter;
+ }
+ winfilters += QChar();
+ winfilters += qt_win_extract_filter(subfilter);
+ winfilters += QChar();
+ }
+ }
+ winfilters += QChar();
+ return winfilters;
+}
+
+static QString qt_win_selected_filter(const QString &filter, DWORD idx)
+{
+ return qt_win_make_filters_list(filter).at((int)idx - 1);
+}
+
+static QString tFilters, tTitle, tInitDir;
+
+static OPENFILENAME* qt_win_make_OFN(QWidget *parent,
+ const QString& initialSelection,
+ const QString& initialDirectory,
+ const QString& title,
+ const QString& filters,
+ QFileDialog::FileMode mode,
+ QFileDialog::Options options)
+{
+ if (parent)
+ parent = parent->window();
+ else
+ parent = QApplication::activeWindow();
+
+ tInitDir = QDir::toNativeSeparators(initialDirectory);
+ tFilters = filters;
+ tTitle = title;
+ QString initSel = QDir::toNativeSeparators(initialSelection);
+ if (!initSel.isEmpty()) {
+ initSel.remove(QLatin1Char('<'));
+ initSel.remove(QLatin1Char('>'));
+ initSel.remove(QLatin1Char('\"'));
+ initSel.remove(QLatin1Char('|'));
+ }
+
+ int maxLen = mode == QFileDialog::ExistingFiles ? maxMultiLen : maxNameLen;
+ wchar_t *tInitSel = new wchar_t[maxLen + 1];
+ if (initSel.length() > 0 && initSel.length() <= maxLen)
+ memcpy(tInitSel, initSel.utf16(), (initSel.length()+1)*sizeof(QChar));
+ else
+ tInitSel[0] = 0;
+
+ OPENFILENAME* ofn = new OPENFILENAME;
+ memset(ofn, 0, sizeof(OPENFILENAME));
+
+ ofn->lStructSize = sizeof(OPENFILENAME);
+ ofn->hwndOwner = parent ? parent->winId() : 0;
+ ofn->lpstrFilter = (wchar_t*)tFilters.utf16();
+ ofn->lpstrFile = tInitSel;
+ ofn->nMaxFile = maxLen;
+ ofn->lpstrInitialDir = (wchar_t*)tInitDir.utf16();
+ ofn->lpstrTitle = (wchar_t*)tTitle.utf16();
+ ofn->Flags = (OFN_NOCHANGEDIR | OFN_HIDEREADONLY | OFN_EXPLORER | OFN_PATHMUSTEXIST);
+ if (mode == QFileDialog::ExistingFile ||
+ mode == QFileDialog::ExistingFiles)
+ ofn->Flags |= (OFN_FILEMUSTEXIST);
+ if (mode == QFileDialog::ExistingFiles)
+ ofn->Flags |= (OFN_ALLOWMULTISELECT);
+ if (!(options & QFileDialog::DontConfirmOverwrite))
+ ofn->Flags |= OFN_OVERWRITEPROMPT;
+
+ return ofn;
+}
+
+static void qt_win_clean_up_OFN(OPENFILENAME **ofn)
+{
+ delete [] (*ofn)->lpstrFile;
+ delete *ofn;
+ *ofn = 0;
+}
+
+extern void qt_win_eatMouseMove();
+
+QString qt_win_get_open_file_name(const QFileDialogArgs &args,
+ QString *initialDirectory,
+ QString *selectedFilter)
+{
+ QString result;
+
+ QString isel = args.selection;
+
+ if (initialDirectory && initialDirectory->left(5) == QLatin1String("file:"))
+ initialDirectory->remove(0, 5);
+ QFileInfo fi(*initialDirectory);
+
+ if (initialDirectory && !fi.isDir()) {
+ *initialDirectory = fi.absolutePath();
+ if (isel.isEmpty())
+ isel = fi.fileName();
+ }
+
+ if (!fi.exists())
+ *initialDirectory = QDir::homePath();
+
+ DWORD selFilIdx = 0;
+
+ int idx = 0;
+ if (selectedFilter) {
+ QStringList filterLst = qt_win_make_filters_list(args.filter);
+ idx = filterLst.indexOf(*selectedFilter);
+ }
+
+ QDialog modal_widget;
+ modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true);
+ modal_widget.setParent(args.parent, Qt::Window);
+ QApplicationPrivate::enterModal(&modal_widget);
+
+ bool hideFiltersDetails = args.options & QFileDialog::HideNameFilterDetails;
+ OPENFILENAME* ofn = qt_win_make_OFN(args.parent, args.selection,
+ args.directory, args.caption,
+ qt_win_filter(args.filter, hideFiltersDetails),
+ QFileDialog::ExistingFile,
+ args.options);
+ if (idx)
+ ofn->nFilterIndex = idx + 1;
+ if (GetOpenFileName(ofn)) {
+ result = QString::fromWCharArray(ofn->lpstrFile);
+ selFilIdx = ofn->nFilterIndex;
+ }
+ qt_win_clean_up_OFN(&ofn);
+
+ QApplicationPrivate::leaveModal(&modal_widget);
+
+ qt_win_eatMouseMove();
+
+ if (result.isEmpty())
+ return result;
+
+ fi = result;
+ *initialDirectory = fi.path();
+ if (selectedFilter)
+ *selectedFilter = qt_win_selected_filter(args.filter, selFilIdx);
+ return fi.absoluteFilePath();
+}
+
+QString qt_win_get_save_file_name(const QFileDialogArgs &args,
+ QString *initialDirectory,
+ QString *selectedFilter)
+{
+ QString result;
+
+ QString isel = args.selection;
+ if (initialDirectory && initialDirectory->left(5) == QLatin1String("file:"))
+ initialDirectory->remove(0, 5);
+ QFileInfo fi(*initialDirectory);
+
+ if (initialDirectory && !fi.isDir()) {
+ *initialDirectory = fi.absolutePath();
+ if (isel.isEmpty())
+ isel = fi.fileName();
+ }
+
+ if (!fi.exists())
+ *initialDirectory = QDir::homePath();
+
+ DWORD selFilIdx = 0;
+
+ int idx = 0;
+ if (selectedFilter) {
+ QStringList filterLst = qt_win_make_filters_list(args.filter);
+ idx = filterLst.indexOf(*selectedFilter);
+ }
+
+ QDialog modal_widget;
+ modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true);
+ modal_widget.setParent(args.parent, Qt::Window);
+ QApplicationPrivate::enterModal(&modal_widget);
+ bool hideFiltersDetails = args.options & QFileDialog::HideNameFilterDetails;
+ // This block is used below for the lpstrDefExt member.
+ // Note that the current MSDN docs document this member wrong.
+ // It should rather be documented as "the default extension if no extension was given and if the
+ // current filter does not have a extension (e.g (*)). If the current filter have an extension, use
+ // the extension of the current filter"
+ QString defaultSaveExt;
+ if (selectedFilter && !selectedFilter->isEmpty()) {
+ defaultSaveExt = qt_win_extract_filter(*selectedFilter);
+ // make sure we only have the extension
+ int firstDot = defaultSaveExt.indexOf(QLatin1Char('.'));
+ if (firstDot != -1) {
+ defaultSaveExt.remove(0, firstDot + 1);
+ } else {
+ defaultSaveExt.clear();
+ }
+ }
+
+ OPENFILENAME *ofn = qt_win_make_OFN(args.parent, args.selection,
+ args.directory, args.caption,
+ qt_win_filter(args.filter, hideFiltersDetails),
+ QFileDialog::AnyFile,
+ args.options);
+
+ ofn->lpstrDefExt = (wchar_t*)defaultSaveExt.utf16();
+
+ if (idx)
+ ofn->nFilterIndex = idx + 1;
+ if (GetSaveFileName(ofn)) {
+ result = QString::fromWCharArray(ofn->lpstrFile);
+ selFilIdx = ofn->nFilterIndex;
+ }
+ qt_win_clean_up_OFN(&ofn);
+
+#if defined(Q_WS_WINCE)
+ int semIndex = result.indexOf(QLatin1Char(';'));
+ if (semIndex >= 0)
+ result = result.left(semIndex);
+#endif
+
+ QApplicationPrivate::leaveModal(&modal_widget);
+
+ qt_win_eatMouseMove();
+
+ if (result.isEmpty())
+ return result;
+
+ fi = result;
+ *initialDirectory = fi.path();
+ if (selectedFilter)
+ *selectedFilter = qt_win_selected_filter(args.filter, selFilIdx);
+ return fi.absoluteFilePath();
+}
+
+
+#ifndef Q_WS_WINCE
+
+typedef HRESULT (WINAPI *PtrSHCreateItemFromParsingName)(PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv);
+static PtrSHCreateItemFromParsingName pSHCreateItemFromParsingName = 0;
+
+static bool qt_win_set_IFileDialogOptions(IFileDialog *pfd,
+ const QString& initialSelection,
+ const QString& initialDirectory,
+ const QString& title,
+ const QStringList& filterLst,
+ QFileDialog::FileMode mode,
+ QFileDialog::Options options)
+{
+ if (!pSHCreateItemFromParsingName) {
+ // This function is available only in Vista & above.
+ QSystemLibrary shellLib(QLatin1String("Shell32"));
+ pSHCreateItemFromParsingName = (PtrSHCreateItemFromParsingName)
+ shellLib.resolve("SHCreateItemFromParsingName");
+ if (!pSHCreateItemFromParsingName)
+ return false;
+ }
+ HRESULT hr;
+ QString winfilters;
+ int numFilters = 0;
+ quint32 currentOffset = 0;
+ QList<quint32> offsets;
+ QStringList::ConstIterator it = filterLst.begin();
+ // Create the native filter string and save offset to each entry.
+ for (; it != filterLst.end(); ++it) {
+ QString subfilter = *it;
+ if (!subfilter.isEmpty()) {
+ offsets<<currentOffset;
+ //Here the COMMON_ITEM_DIALOG API always add the details for the filter (e.g. *.txt)
+ //so we don't need to handle the flag HideNameFilterDetails.
+ winfilters += subfilter; // The name of the filter.
+ winfilters += QChar();
+ currentOffset += subfilter.size()+1;
+ offsets<<currentOffset;
+ QString spec = qt_win_extract_filter(subfilter);
+ winfilters += spec; // The actual filter spec.
+ winfilters += QChar();
+ currentOffset += spec.size()+1;
+ numFilters++;
+ }
+ }
+ // Add the filters to the file dialog.
+ if (numFilters) {
+ wchar_t *szData = (wchar_t*)winfilters.utf16();
+ 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];
+ }
+ hr = pfd->SetFileTypes(numFilters, filterSpec);
+ delete []filterSpec;
+ }
+ // Set the starting folder.
+ tInitDir = QDir::toNativeSeparators(initialDirectory);
+ if (!tInitDir.isEmpty()) {
+ IShellItem *psiDefaultFolder;
+ hr = pSHCreateItemFromParsingName((wchar_t*)tInitDir.utf16(), NULL, QT_IID_IShellItem,
+ reinterpret_cast<void**>(&psiDefaultFolder));
+
+ if (SUCCEEDED(hr)) {
+ hr = pfd->SetFolder(psiDefaultFolder);
+ psiDefaultFolder->Release();
+ }
+ }
+ // Set the currently selected file.
+ QString initSel = QDir::toNativeSeparators(initialSelection);
+ if (!initSel.isEmpty()) {
+ initSel.remove(QLatin1Char('<'));
+ initSel.remove(QLatin1Char('>'));
+ initSel.remove(QLatin1Char('\"'));
+ initSel.remove(QLatin1Char('|'));
+ }
+ if (!initSel.isEmpty()) {
+ hr = pfd->SetFileName((wchar_t*)initSel.utf16());
+ }
+ // Set the title for the file dialog.
+ if (!title.isEmpty()) {
+ hr = pfd->SetTitle((wchar_t*)title.utf16());
+ }
+ // Set other flags for the dialog.
+ DWORD newOptions;
+ hr = pfd->GetOptions(&newOptions);
+ if (SUCCEEDED(hr)) {
+ newOptions |= FOS_NOCHANGEDIR;
+ if (mode == QFileDialog::ExistingFile ||
+ mode == QFileDialog::ExistingFiles)
+ newOptions |= (FOS_FILEMUSTEXIST | FOS_PATHMUSTEXIST);
+ if (mode == QFileDialog::ExistingFiles)
+ newOptions |= FOS_ALLOWMULTISELECT;
+ if (!(options & QFileDialog::DontConfirmOverwrite))
+ newOptions |= FOS_OVERWRITEPROMPT;
+ hr = pfd->SetOptions(newOptions);
+ }
+ return SUCCEEDED(hr);
+}
+
+static QStringList qt_win_CID_get_open_file_names(const QFileDialogArgs &args,
+ QString *initialDirectory,
+ const QStringList &filterList,
+ QString *selectedFilter,
+ int selectedFilterIndex)
+{
+ QStringList result;
+ QDialog modal_widget;
+ modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true);
+ modal_widget.setParent(args.parent, Qt::Window);
+ QApplicationPrivate::enterModal(&modal_widget);
+ // Multiple selection is allowed only in IFileOpenDialog.
+ IFileOpenDialog *pfd = 0;
+ HRESULT hr = CoCreateInstance(QT_CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, QT_IID_IFileOpenDialog,
+ reinterpret_cast<void**>(&pfd));
+
+ if (SUCCEEDED(hr)) {
+ qt_win_set_IFileDialogOptions(pfd, args.selection,
+ args.directory, args.caption,
+ filterList, QFileDialog::ExistingFiles,
+ args.options);
+ // Set the currently selected filter (one-based index).
+ hr = pfd->SetFileTypeIndex(selectedFilterIndex+1);
+ QWidget *parentWindow = args.parent;
+ if (parentWindow)
+ parentWindow = parentWindow->window();
+ else
+ parentWindow = QApplication::activeWindow();
+ // Show the file dialog.
+ hr = pfd->Show(parentWindow ? parentWindow->winId() : 0);
+ if (SUCCEEDED(hr)) {
+ // Retrieve the results.
+ IShellItemArray *psiaResults;
+ hr = pfd->GetResults(&psiaResults);
+ if (SUCCEEDED(hr)) {
+ DWORD numItems = 0;
+ psiaResults->GetCount(&numItems);
+ for (DWORD i = 0; i<numItems; i++) {
+ IShellItem *psi = 0;
+ hr = psiaResults->GetItemAt(i, &psi);
+ if (SUCCEEDED(hr)) {
+ // Retrieve the file name from shell item.
+ wchar_t *pszPath;
+ hr = psi->GetDisplayName(SIGDN_FILESYSPATH, &pszPath);
+ if (SUCCEEDED(hr)) {
+ QString fileName = QString::fromWCharArray(pszPath);
+ result.append(fileName);
+ CoTaskMemFree(pszPath);
+ }
+ psi->Release(); // Free the current item.
+ }
+ }
+ psiaResults->Release(); // Free the array of items.
+ }
+ }
+ }
+ QApplicationPrivate::leaveModal(&modal_widget);
+
+ qt_win_eatMouseMove();
+
+ if (!result.isEmpty()) {
+ // Retrieve the current folder name.
+ IShellItem *psi = 0;
+ hr = pfd->GetFolder(&psi);
+ if (SUCCEEDED(hr)) {
+ wchar_t *pszPath;
+ hr = psi->GetDisplayName(SIGDN_FILESYSPATH, &pszPath);
+ if (SUCCEEDED(hr)) {
+ *initialDirectory = QString::fromWCharArray(pszPath);
+ CoTaskMemFree(pszPath);
+ }
+ psi->Release();
+ }
+ // Retrieve the currently selected filter.
+ if (selectedFilter) {
+ quint32 filetype = 0;
+ hr = pfd->GetFileTypeIndex(&filetype);
+ if (SUCCEEDED(hr) && filetype && filetype <= (quint32)filterList.length()) {
+ // This is a one-based index, not zero-based.
+ *selectedFilter = filterList[filetype-1];
+ }
+ }
+ }
+ if (pfd)
+ pfd->Release();
+ return result;
+}
+
+QString qt_win_CID_get_existing_directory(const QFileDialogArgs &args)
+{
+ QString result;
+ QDialog modal_widget;
+ modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true);
+ modal_widget.setParent(args.parent, Qt::Window);
+ QApplicationPrivate::enterModal(&modal_widget);
+
+ IFileOpenDialog *pfd = 0;
+ HRESULT hr = CoCreateInstance(QT_CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER,
+ QT_IID_IFileOpenDialog, reinterpret_cast<void**>(&pfd));
+
+ if (SUCCEEDED(hr)) {
+ qt_win_set_IFileDialogOptions(pfd, args.selection,
+ args.directory, args.caption,
+ QStringList(), QFileDialog::ExistingFiles,
+ args.options);
+
+ // Set the FOS_PICKFOLDERS flag
+ DWORD newOptions;
+ hr = pfd->GetOptions(&newOptions);
+ newOptions |= (FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM);
+ if (SUCCEEDED(hr) && SUCCEEDED((hr = pfd->SetOptions(newOptions)))) {
+ QWidget *parentWindow = args.parent;
+ if (parentWindow)
+ parentWindow = parentWindow->window();
+ else
+ parentWindow = QApplication::activeWindow();
+
+ // Show the file dialog.
+ hr = pfd->Show(parentWindow ? parentWindow->winId() : 0);
+ if (SUCCEEDED(hr)) {
+ // Retrieve the result
+ IShellItem *psi = 0;
+ hr = pfd->GetResult(&psi);
+ if (SUCCEEDED(hr)) {
+ // Retrieve the file name from shell item.
+ wchar_t *pszPath;
+ hr = psi->GetDisplayName(SIGDN_FILESYSPATH, &pszPath);
+ if (SUCCEEDED(hr)) {
+ result = QString::fromWCharArray(pszPath);
+ CoTaskMemFree(pszPath);
+ }
+ psi->Release(); // Free the current item.
+ }
+ }
+ }
+ }
+ QApplicationPrivate::leaveModal(&modal_widget);
+
+ qt_win_eatMouseMove();
+
+ if (pfd)
+ pfd->Release();
+ return result;
+}
+
+#endif
+
+QStringList qt_win_get_open_file_names(const QFileDialogArgs &args,
+ QString *initialDirectory,
+ QString *selectedFilter)
+{
+ QFileInfo fi;
+ QDir dir;
+
+ if (initialDirectory && initialDirectory->left(5) == QLatin1String("file:"))
+ initialDirectory->remove(0, 5);
+ fi = QFileInfo(*initialDirectory);
+
+ if (initialDirectory && !fi.isDir()) {
+ *initialDirectory = fi.absolutePath();
+ }
+
+ if (!fi.exists())
+ *initialDirectory = QDir::homePath();
+
+ DWORD selFilIdx = 0;
+
+ QStringList filterLst = qt_win_make_filters_list(args.filter);
+ int idx = 0;
+ if (selectedFilter) {
+ idx = filterLst.indexOf(*selectedFilter);
+ }
+ // Windows Vista (& above) allows users to search from file dialogs. If user selects
+ // 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.
+#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
+
+ QStringList result;
+ QDialog modal_widget;
+ modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true);
+ modal_widget.setParent(args.parent, Qt::Window);
+ QApplicationPrivate::enterModal(&modal_widget);
+
+ bool hideFiltersDetails = args.options & QFileDialog::HideNameFilterDetails;
+ OPENFILENAME* ofn = qt_win_make_OFN(args.parent, args.selection,
+ args.directory, args.caption,
+ qt_win_filter(args.filter, hideFiltersDetails),
+ QFileDialog::ExistingFiles,
+ args.options);
+ if (idx)
+ ofn->nFilterIndex = idx + 1;
+ if (GetOpenFileName(ofn)) {
+ QString fileOrDir = QString::fromWCharArray(ofn->lpstrFile);
+ selFilIdx = ofn->nFilterIndex;
+ int offset = fileOrDir.length() + 1;
+ if (ofn->lpstrFile[offset] == 0) {
+ // Only one file selected; has full path
+ fi.setFile(fileOrDir);
+ QString res = fi.absoluteFilePath();
+ if (!res.isEmpty())
+ result.append(res);
+ }
+ else {
+ // Several files selected; first string is path
+ dir.setPath(fileOrDir);
+ QString f;
+ while(!(f = QString::fromWCharArray(ofn->lpstrFile + offset)).isEmpty()) {
+ fi.setFile(dir, f);
+ QString res = fi.absoluteFilePath();
+ if (!res.isEmpty())
+ result.append(res);
+ offset += f.length() + 1;
+ }
+ }
+ }
+ qt_win_clean_up_OFN(&ofn);
+
+ QApplicationPrivate::leaveModal(&modal_widget);
+
+ qt_win_eatMouseMove();
+
+ if (!result.isEmpty()) {
+ *initialDirectory = fi.path(); // only save the path if there is a result
+ if (selectedFilter)
+ *selectedFilter = qt_win_selected_filter(args.filter, selFilIdx);
+ }
+ return result;
+}
+
+// MFC Directory Dialog. Contrib: Steve Williams (minor parts from Scott Powers)
+
+static int __stdcall winGetExistDirCallbackProc(HWND hwnd,
+ UINT uMsg,
+ LPARAM lParam,
+ LPARAM lpData)
+{
+ if (uMsg == BFFM_INITIALIZED && lpData != 0) {
+ QString *initDir = (QString *)(lpData);
+ if (!initDir->isEmpty()) {
+ SendMessage(hwnd, BFFM_SETSELECTION, TRUE, LPARAM(initDir->utf16()));
+ }
+ } else if (uMsg == BFFM_SELCHANGED) {
+ qt_win_resolve_libs();
+ if (ptrSHGetPathFromIDList) {
+ wchar_t path[MAX_PATH];
+ ptrSHGetPathFromIDList(qt_LPITEMIDLIST(lParam), path);
+ QString tmpStr = QString::fromWCharArray(path);
+ if (!tmpStr.isEmpty())
+ SendMessage(hwnd, BFFM_ENABLEOK, 1, 1);
+ else
+ SendMessage(hwnd, BFFM_ENABLEOK, 0, 0);
+ SendMessage(hwnd, BFFM_SETSTATUSTEXT, 1, LPARAM(path));
+ }
+ }
+ return 0;
+}
+
+QString qt_win_get_existing_directory(const QFileDialogArgs &args)
+{
+#ifndef Q_WS_WINCE
+ if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)
+ return qt_win_CID_get_existing_directory(args);
+#endif
+
+ QString currentDir = QDir::currentPath();
+ QString result;
+ QWidget *parent = args.parent;
+ if (parent)
+ parent = parent->window();
+ else
+ parent = QApplication::activeWindow();
+ if (parent)
+ parent->createWinId();
+
+ QDialog modal_widget;
+ modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true);
+ modal_widget.setParent(parent, Qt::Window);
+ QApplicationPrivate::enterModal(&modal_widget);
+
+ QString initDir = QDir::toNativeSeparators(args.directory);
+ wchar_t path[MAX_PATH];
+ wchar_t initPath[MAX_PATH];
+ initPath[0] = 0;
+ path[0] = 0;
+ tTitle = args.caption;
+
+ qt_BROWSEINFO bi;
+
+ Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created));
+ bi.hwndOwner = (parent ? parent->winId() : 0);
+ bi.pidlRoot = NULL;
+ //### This does not seem to be respected? - the dialog always displays "Browse for folder"
+ bi.lpszTitle = (wchar_t*)tTitle.utf16();
+ bi.pszDisplayName = initPath;
+ bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_NEWDIALOGSTYLE;
+ bi.lpfn = winGetExistDirCallbackProc;
+ bi.lParam = LPARAM(&initDir);
+
+ qt_win_resolve_libs();
+ if (ptrSHBrowseForFolder) {
+ qt_LPITEMIDLIST pItemIDList = ptrSHBrowseForFolder(&bi);
+ if (pItemIDList) {
+ ptrSHGetPathFromIDList(pItemIDList, path);
+ IMalloc *pMalloc;
+ if (ptrSHGetMalloc(&pMalloc) == NOERROR) {
+ pMalloc->Free(pItemIDList);
+ pMalloc->Release();
+ result = QString::fromWCharArray(path);
+ }
+ }
+ }
+ tTitle = QString();
+
+ QApplicationPrivate::leaveModal(&modal_widget);
+
+ qt_win_eatMouseMove();
+
+ if (!result.isEmpty())
+ result.replace(QLatin1Char('\\'), QLatin1Char('/'));
+ return result;
+}
+
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/widgets/dialogs/qfiledialog_win_p.h b/src/widgets/dialogs/qfiledialog_win_p.h
new file mode 100644
index 0000000000..7580f0ad6b
--- /dev/null
+++ b/src/widgets/dialogs/qfiledialog_win_p.h
@@ -0,0 +1,243 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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 (QT_WIN_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/widgets/dialogs/qfileinfogatherer.cpp b/src/widgets/dialogs/qfileinfogatherer.cpp
new file mode 100644
index 0000000000..b36b21e63d
--- /dev/null
+++ b/src/widgets/dialogs/qfileinfogatherer.cpp
@@ -0,0 +1,355 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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 "qfileinfogatherer_p.h"
+#include <qdebug.h>
+#include <qfsfileengine.h>
+#include <qdiriterator.h>
+#ifndef Q_OS_WIN
+# include <unistd.h>
+# include <sys/types.h>
+#endif
+#if defined(Q_OS_VXWORKS)
+# include "qplatformdefs.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_FILESYSTEMMODEL
+
+#ifdef QT_BUILD_INTERNAL
+static bool fetchedRoot = false;
+Q_AUTOTEST_EXPORT void qt_test_resetFetchedRoot()
+{
+ fetchedRoot = false;
+}
+
+Q_AUTOTEST_EXPORT bool qt_test_isFetchedRoot()
+{
+ return fetchedRoot;
+}
+#endif
+
+/*!
+ Creates thread
+*/
+QFileInfoGatherer::QFileInfoGatherer(QObject *parent)
+ : QThread(parent), abort(false),
+#ifndef QT_NO_FILESYSTEMWATCHER
+ watcher(0),
+#endif
+ m_resolveSymlinks(false), m_iconProvider(&defaultProvider)
+{
+#ifdef Q_OS_WIN
+ m_resolveSymlinks = true;
+#elif !defined(Q_OS_INTEGRITY)
+ userId = getuid();
+ groupId = getgid();
+#endif
+#ifndef QT_NO_FILESYSTEMWATCHER
+ watcher = new QFileSystemWatcher(this);
+ connect(watcher, SIGNAL(directoryChanged(QString)), this, SLOT(list(QString)));
+ connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(updateFile(QString)));
+#endif
+ start(LowPriority);
+}
+
+/*!
+ Destroys thread
+*/
+QFileInfoGatherer::~QFileInfoGatherer()
+{
+ QMutexLocker locker(&mutex);
+ abort = true;
+ condition.wakeOne();
+ locker.unlock();
+ wait();
+}
+
+void QFileInfoGatherer::setResolveSymlinks(bool enable)
+{
+ Q_UNUSED(enable);
+#ifdef Q_OS_WIN
+ QMutexLocker locker(&mutex);
+ m_resolveSymlinks = enable;
+#endif
+}
+
+bool QFileInfoGatherer::resolveSymlinks() const
+{
+ return m_resolveSymlinks;
+}
+
+void QFileInfoGatherer::setIconProvider(QFileIconProvider *provider)
+{
+ QMutexLocker locker(&mutex);
+ m_iconProvider = provider;
+}
+
+QFileIconProvider *QFileInfoGatherer::iconProvider() const
+{
+ return m_iconProvider;
+}
+
+/*!
+ Fetch extended information for all \a files in \a path
+
+ \sa updateFile(), update(), resolvedName()
+*/
+void QFileInfoGatherer::fetchExtendedInformation(const QString &path, const QStringList &files)
+{
+ QMutexLocker locker(&mutex);
+ // See if we already have this dir/file in our que
+ int loc = this->path.lastIndexOf(path);
+ while (loc > 0) {
+ if (this->files.at(loc) == files) {
+ return;
+ }
+ loc = this->path.lastIndexOf(path, loc - 1);
+ }
+ this->path.push(path);
+ this->files.push(files);
+ condition.wakeAll();
+}
+
+/*!
+ Fetch extended information for all \a filePath
+
+ \sa fetchExtendedInformation()
+*/
+void QFileInfoGatherer::updateFile(const QString &filePath)
+{
+ QString dir = filePath.mid(0, filePath.lastIndexOf(QDir::separator()));
+ QString fileName = filePath.mid(dir.length() + 1);
+ fetchExtendedInformation(dir, QStringList(fileName));
+}
+
+/*
+ List all files in \a directoryPath
+
+ \sa listed()
+*/
+void QFileInfoGatherer::clear()
+{
+#ifndef QT_NO_FILESYSTEMWATCHER
+ QMutexLocker locker(&mutex);
+ watcher->removePaths(watcher->files());
+ watcher->removePaths(watcher->directories());
+#endif
+}
+
+/*
+ Remove a \a path from the watcher
+
+ \sa listed()
+*/
+void QFileInfoGatherer::removePath(const QString &path)
+{
+#ifndef QT_NO_FILESYSTEMWATCHER
+ QMutexLocker locker(&mutex);
+ watcher->removePath(path);
+#endif
+}
+
+/*
+ List all files in \a directoryPath
+
+ \sa listed()
+*/
+void QFileInfoGatherer::list(const QString &directoryPath)
+{
+ fetchExtendedInformation(directoryPath, QStringList());
+}
+
+/*
+ Until aborted wait to fetch a directory or files
+*/
+void QFileInfoGatherer::run()
+{
+ forever {
+ bool updateFiles = false;
+ QMutexLocker locker(&mutex);
+ if (abort) {
+ return;
+ }
+ if (this->path.isEmpty())
+ condition.wait(&mutex);
+ QString path;
+ QStringList list;
+ if (!this->path.isEmpty()) {
+ path = this->path.first();
+ list = this->files.first();
+ this->path.pop_front();
+ this->files.pop_front();
+ updateFiles = true;
+ }
+ locker.unlock();
+ if (updateFiles)
+ getFileInfos(path, list);
+ }
+}
+
+QExtendedInformation QFileInfoGatherer::getInfo(const QFileInfo &fileInfo) const
+{
+ QExtendedInformation info(fileInfo);
+ info.icon = m_iconProvider->icon(fileInfo);
+ info.displayType = m_iconProvider->type(fileInfo);
+#ifndef QT_NO_FILESYSTEMWATCHER
+ // ### Not ready to listen all modifications
+ #if 0
+ // Enable the next two commented out lines to get updates when the file sizes change...
+ if (!fileInfo.exists() && !fileInfo.isSymLink()) {
+ info.size = -1;
+ //watcher->removePath(fileInfo.absoluteFilePath());
+ } else {
+ if (!fileInfo.absoluteFilePath().isEmpty() && fileInfo.exists() && fileInfo.isReadable()
+ && !watcher->files().contains(fileInfo.absoluteFilePath())) {
+ //watcher->addPath(fileInfo.absoluteFilePath());
+ }
+ }
+ #endif
+#endif
+
+ if (fileInfo.isSymLink() && m_resolveSymlinks) {
+ QFileInfo resolvedInfo(fileInfo.symLinkTarget());
+ resolvedInfo = resolvedInfo.canonicalFilePath();
+ if (resolvedInfo.exists()) {
+ emit nameResolved(fileInfo.filePath(), resolvedInfo.fileName());
+ }
+ }
+ return info;
+}
+
+QString QFileInfoGatherer::translateDriveName(const QFileInfo &drive) const
+{
+ QString driveName = drive.absoluteFilePath();
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ if (driveName.startsWith(QLatin1Char('/'))) // UNC host
+ return drive.fileName();
+#endif
+#if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN)
+ if (driveName.endsWith(QLatin1Char('/')))
+ driveName.chop(1);
+#endif
+ return driveName;
+}
+
+/*
+ Get specific file info's, batch the files so update when we have 100
+ items and every 200ms after that
+ */
+void QFileInfoGatherer::getFileInfos(const QString &path, const QStringList &files)
+{
+#ifndef QT_NO_FILESYSTEMWATCHER
+ if (files.isEmpty()
+ && !watcher->directories().contains(path)
+ && !path.isEmpty()
+ && !path.startsWith(QLatin1String("//")) /*don't watch UNC path*/) {
+ watcher->addPath(path);
+ }
+#endif
+
+ // List drives
+ if (path.isEmpty()) {
+#ifdef QT_BUILD_INTERNAL
+ fetchedRoot = true;
+#endif
+ QFileInfoList infoList;
+ if (files.isEmpty()) {
+ infoList = QDir::drives();
+ } else {
+ for (int i = 0; i < files.count(); ++i)
+ infoList << QFileInfo(files.at(i));
+ }
+ for (int i = infoList.count() - 1; i >= 0; --i) {
+ QString driveName = translateDriveName(infoList.at(i));
+ QList<QPair<QString,QFileInfo> > updatedFiles;
+ updatedFiles.append(QPair<QString,QFileInfo>(driveName, infoList.at(i)));
+ emit updates(path, updatedFiles);
+ }
+ return;
+ }
+
+ QElapsedTimer base;
+ base.start();
+ QFileInfo fileInfo;
+ bool firstTime = true;
+ QList<QPair<QString, QFileInfo> > updatedFiles;
+ QStringList filesToCheck = files;
+
+ QString itPath = QDir::fromNativeSeparators(files.isEmpty() ? path : QLatin1String(""));
+ QDirIterator dirIt(itPath, QDir::AllEntries | QDir::System | QDir::Hidden);
+ QStringList allFiles;
+ while(!abort && dirIt.hasNext()) {
+ dirIt.next();
+ fileInfo = dirIt.fileInfo();
+ allFiles.append(fileInfo.fileName());
+ fetch(fileInfo, base, firstTime, updatedFiles, path);
+ }
+ if (!allFiles.isEmpty())
+ emit newListOfFiles(path, allFiles);
+
+ QStringList::const_iterator filesIt = filesToCheck.constBegin();
+ while(!abort && filesIt != filesToCheck.constEnd()) {
+ fileInfo.setFile(path + QDir::separator() + *filesIt);
+ ++filesIt;
+ fetch(fileInfo, base, firstTime, updatedFiles, path);
+ }
+ if (!updatedFiles.isEmpty())
+ emit updates(path, updatedFiles);
+ emit directoryLoaded(path);
+}
+
+void QFileInfoGatherer::fetch(const QFileInfo &fileInfo, QElapsedTimer &base, bool &firstTime, QList<QPair<QString, QFileInfo> > &updatedFiles, const QString &path) {
+ updatedFiles.append(QPair<QString, QFileInfo>(fileInfo.fileName(), fileInfo));
+ QElapsedTimer current;
+ current.start();
+ if ((firstTime && updatedFiles.count() > 100) || base.msecsTo(current) > 1000) {
+ emit updates(path, updatedFiles);
+ updatedFiles.clear();
+ base = current;
+ firstTime = false;
+ }
+}
+
+#endif // QT_NO_FILESYSTEMMODEL
+
+QT_END_NAMESPACE
diff --git a/src/widgets/dialogs/qfileinfogatherer_p.h b/src/widgets/dialogs/qfileinfogatherer_p.h
new file mode 100644
index 0000000000..db308ef57e
--- /dev/null
+++ b/src/widgets/dialogs/qfileinfogatherer_p.h
@@ -0,0 +1,207 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFILEINFOGATHERER_H
+#define QFILEINFOGATHERER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qthread.h>
+#include <qmutex.h>
+#include <qwaitcondition.h>
+#include <qfilesystemwatcher.h>
+#include <qfileiconprovider.h>
+#include <qfsfileengine.h>
+#include <qpair.h>
+#include <qstack.h>
+#include <qdatetime.h>
+#include <qdir.h>
+#include <qelapsedtimer.h>
+
+QT_BEGIN_NAMESPACE
+
+class QExtendedInformation {
+public:
+ enum Type { Dir, File, System };
+
+ QExtendedInformation() {}
+ QExtendedInformation(const QFileInfo &info) : mFileInfo(info) {}
+
+ inline bool isDir() { return type() == Dir; }
+ inline bool isFile() { return type() == File; }
+ inline bool isSystem() { return type() == System; }
+
+ bool operator ==(const QExtendedInformation &fileInfo) const {
+ return mFileInfo == fileInfo.mFileInfo
+ && displayType == fileInfo.displayType
+ && permissions() == fileInfo.permissions();
+ }
+
+#ifndef QT_NO_FSFILEENGINE
+ bool isCaseSensitive() const {
+ QFSFileEngine fe(mFileInfo.absoluteFilePath());
+ return fe.caseSensitive();
+ }
+#endif
+
+ QFile::Permissions permissions() const {
+ return mFileInfo.permissions();
+ }
+
+ Type type() const {
+ if (mFileInfo.isDir()) {
+ return QExtendedInformation::Dir;
+ }
+ if (mFileInfo.isFile()) {
+ return QExtendedInformation::File;
+ }
+ if (!mFileInfo.exists() && mFileInfo.isSymLink()) {
+ return QExtendedInformation::System;
+ }
+ return QExtendedInformation::System;
+ }
+
+ bool isSymLink() const {
+ return mFileInfo.isSymLink();
+ }
+
+ bool isHidden() const {
+ return mFileInfo.isHidden();
+ }
+
+ QFileInfo fileInfo() const {
+ return mFileInfo;
+ }
+
+ QDateTime lastModified() const {
+ return mFileInfo.lastModified();
+ }
+
+ qint64 size() const {
+ qint64 size = -1;
+ if (type() == QExtendedInformation::Dir)
+ size = 0;
+ if (type() == QExtendedInformation::File)
+ size = mFileInfo.size();
+ if (!mFileInfo.exists() && !mFileInfo.isSymLink())
+ size = -1;
+ return size;
+ }
+
+ QString displayType;
+ QIcon icon;
+
+private :
+ QFileInfo mFileInfo;
+};
+
+class QFileIconProvider;
+
+#ifndef QT_NO_FILESYSTEMMODEL
+
+class Q_AUTOTEST_EXPORT QFileInfoGatherer : public QThread
+{
+Q_OBJECT
+
+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);
+ ~QFileInfoGatherer();
+
+ void clear();
+ void removePath(const QString &path);
+ QExtendedInformation getInfo(const QFileInfo &info) const;
+
+public Q_SLOTS:
+ void list(const QString &directoryPath);
+ void fetchExtendedInformation(const QString &path, const QStringList &files);
+ void updateFile(const QString &path);
+ void setResolveSymlinks(bool enable);
+ bool resolveSymlinks() const;
+ void setIconProvider(QFileIconProvider *provider);
+ QFileIconProvider *iconProvider() const;
+
+protected:
+ void run();
+ void getFileInfos(const QString &path, const QStringList &files);
+
+private:
+ void fetch(const QFileInfo &info, QElapsedTimer &base, bool &firstTime, QList<QPair<QString, QFileInfo> > &updatedFiles, const QString &path);
+ QString translateDriveName(const QFileInfo &drive) const;
+
+ QMutex mutex;
+ QWaitCondition condition;
+ volatile bool abort;
+
+ QStack<QString> path;
+ QStack<QStringList> files;
+
+#ifndef QT_NO_FILESYSTEMWATCHER
+ QFileSystemWatcher *watcher;
+#endif
+ bool m_resolveSymlinks;
+ QFileIconProvider *m_iconProvider;
+ QFileIconProvider defaultProvider;
+#ifndef Q_OS_WIN
+ uint userId;
+ uint groupId;
+#endif
+};
+#endif // QT_NO_FILESYSTEMMODEL
+
+
+QT_END_NAMESPACE
+#endif // QFILEINFOGATHERER_H
+
diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp
new file mode 100644
index 0000000000..cb8eb6ad66
--- /dev/null
+++ b/src/widgets/dialogs/qfilesystemmodel.cpp
@@ -0,0 +1,2027 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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 "qfilesystemmodel_p.h"
+#include "qfilesystemmodel.h"
+#include <qlocale.h>
+#include <qmime.h>
+#include <qurl.h>
+#include <qdebug.h>
+#include <qmessagebox.h>
+#include <qapplication.h>
+
+#ifdef Q_OS_WIN
+#include <qt_windows.h>
+#endif
+#ifdef Q_OS_WIN32
+#include <QtCore/QVarLengthArray>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_FILESYSTEMMODEL
+
+/*!
+ \enum QFileSystemModel::Roles
+ \value FileIconRole
+ \value FilePathRole
+ \value FileNameRole
+ \value FilePermissions
+*/
+
+/*!
+ \class QFileSystemModel
+ \since 4.4
+
+ \brief The QFileSystemModel class provides a data model for the local filesystem.
+
+ \ingroup model-view
+
+ This class provides access to the local filesystem, providing functions
+ for renaming and removing files and directories, and for creating new
+ directories. In the simplest case, it can be used with a suitable display
+ widget as part of a browser or filter.
+
+ QFileSystemModel can be accessed using the standard interface provided by
+ QAbstractItemModel, but it also provides some convenience functions that are
+ specific to a directory model.
+ The fileInfo(), isDir(), name(), and path() functions provide information
+ about the underlying files and directories related to items in the model.
+ Directories can be created and removed using mkdir(), rmdir().
+
+ \note QFileSystemModel requires an instance of a GUI application.
+
+ \section1 Example Usage
+
+ A directory model that displays the contents of a default directory
+ is usually constructed with a parent object:
+
+ \snippet doc/src/snippets/shareddirmodel/main.cpp 2
+
+ A tree view can be used to display the contents of the model
+
+ \snippet doc/src/snippets/shareddirmodel/main.cpp 4
+
+ and the contents of a particular directory can be displayed by
+ setting the tree view's root index:
+
+ \snippet doc/src/snippets/shareddirmodel/main.cpp 7
+
+ The view's root index can be used to control how much of a
+ hierarchical model is displayed. QDirModel provides a convenience
+ function that returns a suitable model index for a path to a
+ directory within the model.
+
+ \section1 Caching and Performance
+
+ QFileSystemModel will not fetch any files or directories until setRootPath()
+ is called. This will prevent any unnecessary querying on the file system
+ until that point such as listing the drives on Windows.
+
+ Unlike QDirModel, QFileSystemModel uses a separate thread to populate
+ itself so it will not cause the main thread to hang as the file system
+ is being queried. Calls to rowCount() will return 0 until the model
+ populates a directory.
+
+ QFileSystemModel keeps a cache with file information. The cache is
+ automatically kept up to date using the QFileSystemWatcher.
+
+ \sa {Model Classes}
+*/
+
+/*!
+ \fn bool QFileSystemModel::rmdir(const QModelIndex &index) const
+
+ Removes the directory corresponding to the model item \a index in the
+ file system model and \bold{deletes the corresponding directory from the
+ file system}, returning true if successful. If the directory cannot be
+ removed, false is returned.
+
+ \warning This function deletes directories from the file system; it does
+ \bold{not} move them to a location where they can be recovered.
+
+ \sa remove()
+*/
+
+/*!
+ \fn QIcon QFileSystemModel::fileName(const QModelIndex &index) const
+
+ Returns the file name for the item stored in the model under the given
+ \a index.
+*/
+
+/*!
+ \fn QIcon QFileSystemModel::fileIcon(const QModelIndex &index) const
+
+ Returns the icon for the item stored in the model under the given
+ \a index.
+*/
+
+/*!
+ \fn QFileInfo QFileSystemModel::fileInfo(const QModelIndex &index) const
+
+ Returns the QFileInfo for the item stored in the model under the given
+ \a index.
+*/
+
+/*!
+ \fn void QFileSystemModel::rootPathChanged(const QString &newPath);
+
+ This signal is emitted whenever the root path has been changed to a \a newPath.
+*/
+
+/*!
+ \fn void QFileSystemModel::fileRenamed(const QString &path, const QString &oldName, const QString &newName)
+
+ This signal is emitted whenever a file with the \a oldName is successfully
+ renamed to \a newName. The file is located in in the directory \a path.
+*/
+
+/*!
+ \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
+ corresponding file from the file system}, returning true if successful. If the
+ item cannot be removed, false is returned.
+
+ \warning This function deletes files from the file system; it does \bold{not}
+ move them to a location where they can be recovered.
+
+ \sa rmdir()
+*/
+
+bool QFileSystemModel::remove(const QModelIndex &aindex) const
+{
+ //### TODO optim
+ QString path = filePath(aindex);
+ QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func());
+ d->fileInfoGatherer.removePath(path);
+ QDirIterator it(path,
+ QDir::AllDirs | QDir:: Files | QDir::NoDotAndDotDot,
+ QDirIterator::Subdirectories);
+ QStringList children;
+ while (it.hasNext())
+ children.prepend(it.next());
+ children.append(path);
+
+ bool error = false;
+ for (int i = 0; i < children.count(); ++i) {
+ QFileInfo info(children.at(i));
+ QModelIndex modelIndex = index(children.at(i));
+ if (info.isDir()) {
+ QDir dir;
+ if (children.at(i) != path)
+ error |= remove(modelIndex);
+ error |= rmdir(modelIndex);
+ } else {
+ error |= QFile::remove(filePath(modelIndex));
+ }
+ }
+ return error;
+}
+
+/*!
+ Constructs a file system model with the given \a parent.
+*/
+QFileSystemModel::QFileSystemModel(QObject *parent)
+ : QAbstractItemModel(*new QFileSystemModelPrivate, parent)
+{
+ Q_D(QFileSystemModel);
+ d->init();
+}
+
+/*!
+ \internal
+*/
+QFileSystemModel::QFileSystemModel(QFileSystemModelPrivate &dd, QObject *parent)
+ : QAbstractItemModel(dd, parent)
+{
+ Q_D(QFileSystemModel);
+ d->init();
+}
+
+/*!
+ Destroys this file system model.
+*/
+QFileSystemModel::~QFileSystemModel()
+{
+}
+
+/*!
+ \reimp
+*/
+QModelIndex QFileSystemModel::index(int row, int column, const QModelIndex &parent) const
+{
+ Q_D(const QFileSystemModel);
+ if (row < 0 || column < 0 || row >= rowCount(parent) || column >= columnCount(parent))
+ return QModelIndex();
+
+ // get the parent node
+ QFileSystemModelPrivate::QFileSystemNode *parentNode = (d->indexValid(parent) ? d->node(parent) :
+ const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&d->root));
+ Q_ASSERT(parentNode);
+
+ // now get the internal pointer for the index
+ QString childName = parentNode->visibleChildren[d->translateVisibleLocation(parentNode, row)];
+ const QFileSystemModelPrivate::QFileSystemNode *indexNode = parentNode->children.value(childName);
+ Q_ASSERT(indexNode);
+
+ return createIndex(row, column, const_cast<QFileSystemModelPrivate::QFileSystemNode*>(indexNode));
+}
+
+/*!
+ \overload
+
+ Returns the model item index for the given \a path and \a column.
+*/
+QModelIndex QFileSystemModel::index(const QString &path, int column) const
+{
+ Q_D(const QFileSystemModel);
+ QFileSystemModelPrivate::QFileSystemNode *node = d->node(path, false);
+ QModelIndex idx = d->index(node);
+ if (idx.column() != column)
+ idx = idx.sibling(idx.row(), column);
+ return idx;
+}
+
+/*!
+ \internal
+
+ Return the QFileSystemNode that goes to index.
+ */
+QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return const_cast<QFileSystemNode*>(&root);
+ QFileSystemModelPrivate::QFileSystemNode *indexNode = static_cast<QFileSystemModelPrivate::QFileSystemNode*>(index.internalPointer());
+ Q_ASSERT(indexNode);
+ return indexNode;
+}
+
+#ifdef Q_OS_WIN32
+static QString qt_GetLongPathName(const QString &strShortPath)
+{
+ if (strShortPath.isEmpty()
+ || strShortPath == QLatin1String(".") || strShortPath == QLatin1String(".."))
+ return strShortPath;
+ 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
+
+/*!
+ \internal
+
+ Given a path return the matching QFileSystemNode or &root if invalid
+*/
+QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QString &path, bool fetch) const
+{
+ Q_Q(const QFileSystemModel);
+ Q_UNUSED(q);
+ if (path.isEmpty() || path == myComputer() || path.startsWith(QLatin1Char(':')))
+ return const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&root);
+
+ // Construct the nodes up to the new root path if they need to be built
+ QString absolutePath;
+#ifdef Q_OS_WIN32
+ QString longPath = qt_GetLongPathName(path);
+#else
+ QString longPath = path;
+#endif
+ if (longPath == rootDir.path())
+ absolutePath = rootDir.absolutePath();
+ else
+ absolutePath = QDir(longPath).absolutePath();
+
+ // ### TODO can we use bool QAbstractFileEngine::caseSensitive() const?
+ QStringList pathElements = absolutePath.split(QLatin1Char('/'), QString::SkipEmptyParts);
+ if ((pathElements.isEmpty())
+#if (!defined(Q_OS_WIN) || defined(Q_OS_WINCE)) && !defined(Q_OS_SYMBIAN)
+ && QDir::fromNativeSeparators(longPath) != QLatin1String("/")
+#endif
+ )
+ return const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&root);
+ QModelIndex index = QModelIndex(); // start with "My Computer"
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ if (absolutePath.startsWith(QLatin1String("//"))) { // UNC path
+ QString host = QLatin1String("\\\\") + pathElements.first();
+ if (absolutePath == QDir::fromNativeSeparators(host))
+ absolutePath.append(QLatin1Char('/'));
+ if (longPath.endsWith(QLatin1Char('/')) && !absolutePath.endsWith(QLatin1Char('/')))
+ absolutePath.append(QLatin1Char('/'));
+ int r = 0;
+ QFileSystemModelPrivate::QFileSystemNode *rootNode = const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&root);
+ if (!root.children.contains(host.toLower())) {
+ if (pathElements.count() == 1 && !absolutePath.endsWith(QLatin1Char('/')))
+ return rootNode;
+ QFileInfo info(host);
+ if (!info.exists())
+ return rootNode;
+ QFileSystemModelPrivate *p = const_cast<QFileSystemModelPrivate*>(this);
+ p->addNode(rootNode, host,info);
+ p->addVisibleFiles(rootNode, QStringList(host));
+ }
+ r = rootNode->visibleLocation(host);
+ r = translateVisibleLocation(rootNode, r);
+ index = q->index(r, 0, QModelIndex());
+ pathElements.pop_front();
+ } else
+#endif
+
+#if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN)
+ {
+ if (!pathElements.at(0).contains(QLatin1String(":"))) {
+ // The reason we express it like this instead of with anonymous, temporary
+ // variables, is to workaround a compiler crash with Q_CC_NOKIAX86.
+ QString rootPath = QDir(longPath).rootPath();
+ pathElements.prepend(rootPath);
+ }
+ if (pathElements.at(0).endsWith(QLatin1Char('/')))
+ pathElements[0].chop(1);
+ }
+#else
+ // add the "/" item, since it is a valid path element on Unix
+ if (absolutePath[0] == QLatin1Char('/'))
+ pathElements.prepend(QLatin1String("/"));
+#endif
+
+ QFileSystemModelPrivate::QFileSystemNode *parent = node(index);
+
+ for (int i = 0; i < pathElements.count(); ++i) {
+ QString element = pathElements.at(i);
+#ifdef Q_OS_WIN
+ // On Windows, "filename......." and "filename" are equivalent Task #133928
+ while (element.endsWith(QLatin1Char('.')))
+ element.chop(1);
+#endif
+ bool alreadyExisted = parent->children.contains(element);
+
+ // we couldn't find the path element, we create a new node since we
+ // _know_ that the path is valid
+ if (alreadyExisted) {
+ if ((parent->children.count() == 0)
+ || (parent->caseSensitive()
+ && parent->children.value(element)->fileName != element)
+ || (!parent->caseSensitive()
+ && parent->children.value(element)->fileName.toLower() != element.toLower()))
+ alreadyExisted = false;
+ }
+
+ QFileSystemModelPrivate::QFileSystemNode *node;
+ if (!alreadyExisted) {
+ // Someone might call ::index("file://cookie/monster/doesn't/like/veggies"),
+ // a path that doesn't exists, I.E. don't blindly create directories.
+ QFileInfo info(absolutePath);
+ if (!info.exists())
+ return const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&root);
+ QFileSystemModelPrivate *p = const_cast<QFileSystemModelPrivate*>(this);
+ node = p->addNode(parent, element,info);
+#ifndef QT_NO_FILESYSTEMWATCHER
+ node->populate(fileInfoGatherer.getInfo(info));
+#endif
+ } else {
+ node = parent->children.value(element);
+ }
+
+ Q_ASSERT(node);
+ if (!node->isVisible) {
+ // It has been filtered out
+ if (alreadyExisted && node->hasInformation() && !fetch)
+ return const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&root);
+
+ QFileSystemModelPrivate *p = const_cast<QFileSystemModelPrivate*>(this);
+ p->addVisibleFiles(parent, QStringList(element));
+ if (!p->bypassFilters.contains(node))
+ p->bypassFilters[node] = 1;
+ QString dir = q->filePath(this->index(parent));
+ if (!node->hasInformation() && fetch) {
+ Fetching f;
+ f.dir = dir;
+ f.file = element;
+ f.node = node;
+ p->toFetch.append(f);
+ p->fetchingTimer.start(0, const_cast<QFileSystemModel*>(q));
+ }
+ }
+ parent = node;
+ }
+
+ return parent;
+}
+
+/*!
+ \reimp
+*/
+void QFileSystemModel::timerEvent(QTimerEvent *event)
+{
+ Q_D(QFileSystemModel);
+ if (event->timerId() == d->fetchingTimer.timerId()) {
+ d->fetchingTimer.stop();
+#ifndef QT_NO_FILESYSTEMWATCHER
+ for (int i = 0; i < d->toFetch.count(); ++i) {
+ const QFileSystemModelPrivate::QFileSystemNode *node = d->toFetch.at(i).node;
+ if (!node->hasInformation()) {
+ d->fileInfoGatherer.fetchExtendedInformation(d->toFetch.at(i).dir,
+ QStringList(d->toFetch.at(i).file));
+ } else {
+ // qDebug() << "yah!, you saved a little gerbil soul";
+ }
+ }
+#endif
+ d->toFetch.clear();
+ }
+}
+
+/*!
+ Returns true if the model item \a index represents a directory;
+ otherwise returns false.
+*/
+bool QFileSystemModel::isDir(const QModelIndex &index) const
+{
+ // This function is for public usage only because it could create a file info
+ Q_D(const QFileSystemModel);
+ if (!index.isValid())
+ return true;
+ QFileSystemModelPrivate::QFileSystemNode *n = d->node(index);
+ if (n->hasInformation())
+ return n->isDir();
+ return fileInfo(index).isDir();
+}
+
+/*!
+ Returns the size in bytes of \a index. If the file does not exist, 0 is returned.
+ */
+qint64 QFileSystemModel::size(const QModelIndex &index) const
+{
+ Q_D(const QFileSystemModel);
+ if (!index.isValid())
+ return 0;
+ return d->node(index)->size();
+}
+
+/*!
+ Returns the type of file \a index such as "Directory" or "JPEG file".
+ */
+QString QFileSystemModel::type(const QModelIndex &index) const
+{
+ Q_D(const QFileSystemModel);
+ if (!index.isValid())
+ return QString();
+ return d->node(index)->type();
+}
+
+/*!
+ Returns the date and time when \a index was last modified.
+ */
+QDateTime QFileSystemModel::lastModified(const QModelIndex &index) const
+{
+ Q_D(const QFileSystemModel);
+ if (!index.isValid())
+ return QDateTime();
+ return d->node(index)->lastModified();
+}
+
+/*!
+ \reimp
+*/
+QModelIndex QFileSystemModel::parent(const QModelIndex &index) const
+{
+ Q_D(const QFileSystemModel);
+ if (!d->indexValid(index))
+ return QModelIndex();
+
+ QFileSystemModelPrivate::QFileSystemNode *indexNode = d->node(index);
+ Q_ASSERT(indexNode != 0);
+ QFileSystemModelPrivate::QFileSystemNode *parentNode = (indexNode ? indexNode->parent : 0);
+ if (parentNode == 0 || parentNode == &d->root)
+ return QModelIndex();
+
+ // get the parent's row
+ QFileSystemModelPrivate::QFileSystemNode *grandParentNode = parentNode->parent;
+ Q_ASSERT(grandParentNode->children.contains(parentNode->fileName));
+ int visualRow = d->translateVisibleLocation(grandParentNode, grandParentNode->visibleLocation(grandParentNode->children.value(parentNode->fileName)->fileName));
+ if (visualRow == -1)
+ return QModelIndex();
+ return createIndex(visualRow, 0, parentNode);
+}
+
+/*
+ \internal
+
+ return the index for node
+*/
+QModelIndex QFileSystemModelPrivate::index(const QFileSystemModelPrivate::QFileSystemNode *node) const
+{
+ Q_Q(const QFileSystemModel);
+ QFileSystemModelPrivate::QFileSystemNode *parentNode = (node ? node->parent : 0);
+ if (node == &root || !parentNode)
+ return QModelIndex();
+
+ // get the parent's row
+ Q_ASSERT(node);
+ if (!node->isVisible)
+ return QModelIndex();
+
+ int visualRow = translateVisibleLocation(parentNode, parentNode->visibleLocation(node->fileName));
+ return q->createIndex(visualRow, 0, const_cast<QFileSystemNode*>(node));
+}
+
+/*!
+ \reimp
+*/
+bool QFileSystemModel::hasChildren(const QModelIndex &parent) const
+{
+ Q_D(const QFileSystemModel);
+ if (parent.column() > 0)
+ return false;
+
+ if (!parent.isValid()) // drives
+ return true;
+
+ const QFileSystemModelPrivate::QFileSystemNode *indexNode = d->node(parent);
+ Q_ASSERT(indexNode);
+ return (indexNode->isDir());
+}
+
+/*!
+ \reimp
+ */
+bool QFileSystemModel::canFetchMore(const QModelIndex &parent) const
+{
+ Q_D(const QFileSystemModel);
+ const QFileSystemModelPrivate::QFileSystemNode *indexNode = d->node(parent);
+ return (!indexNode->populatedChildren);
+}
+
+/*!
+ \reimp
+ */
+void QFileSystemModel::fetchMore(const QModelIndex &parent)
+{
+ Q_D(QFileSystemModel);
+ if (!d->setRootPath)
+ return;
+ QFileSystemModelPrivate::QFileSystemNode *indexNode = d->node(parent);
+ if (indexNode->populatedChildren)
+ return;
+ indexNode->populatedChildren = true;
+ d->fileInfoGatherer.list(filePath(parent));
+}
+
+/*!
+ \reimp
+*/
+int QFileSystemModel::rowCount(const QModelIndex &parent) const
+{
+ Q_D(const QFileSystemModel);
+ if (parent.column() > 0)
+ return 0;
+
+ if (!parent.isValid())
+ return d->root.visibleChildren.count();
+
+ const QFileSystemModelPrivate::QFileSystemNode *parentNode = d->node(parent);
+ return parentNode->visibleChildren.count();
+}
+
+/*!
+ \reimp
+*/
+int QFileSystemModel::columnCount(const QModelIndex &parent) const
+{
+ return (parent.column() > 0) ? 0 : 4;
+}
+
+/*!
+ Returns the data stored under the given \a role for the item "My Computer".
+
+ \sa Qt::ItemDataRole
+ */
+QVariant QFileSystemModel::myComputer(int role) const
+{
+ Q_D(const QFileSystemModel);
+ switch (role) {
+ case Qt::DisplayRole:
+ return d->myComputer();
+ case Qt::DecorationRole:
+ return d->fileInfoGatherer.iconProvider()->icon(QFileIconProvider::Computer);
+ }
+ return QVariant();
+}
+
+/*!
+ \reimp
+*/
+QVariant QFileSystemModel::data(const QModelIndex &index, int role) const
+{
+ Q_D(const QFileSystemModel);
+ if (!index.isValid() || index.model() != this)
+ return QVariant();
+
+ switch (role) {
+ case Qt::EditRole:
+ case Qt::DisplayRole:
+ switch (index.column()) {
+ case 0: return d->displayName(index);
+ case 1: return d->size(index);
+ case 2: return d->type(index);
+ case 3: return d->time(index);
+ default:
+ qWarning("data: invalid display value column %d", index.column());
+ break;
+ }
+ break;
+ case FilePathRole:
+ return filePath(index);
+ case FileNameRole:
+ return d->name(index);
+ case Qt::DecorationRole:
+ if (index.column() == 0) {
+ QIcon icon = d->icon(index);
+ if (icon.isNull()) {
+ if (d->node(index)->isDir())
+ icon = d->fileInfoGatherer.iconProvider()->icon(QFileIconProvider::Folder);
+ else
+ icon = d->fileInfoGatherer.iconProvider()->icon(QFileIconProvider::File);
+ }
+ return icon;
+ }
+ break;
+ case Qt::TextAlignmentRole:
+ if (index.column() == 1)
+ return Qt::AlignRight;
+ break;
+ case FilePermissions:
+ int p = permissions(index);
+ return p;
+ }
+
+ return QVariant();
+}
+
+/*!
+ \internal
+*/
+QString QFileSystemModelPrivate::size(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return QString();
+ const QFileSystemNode *n = node(index);
+ if (n->isDir()) {
+#ifdef Q_OS_MAC
+ return QLatin1String("--");
+#else
+ return QLatin1String("");
+#endif
+ // Windows - ""
+ // OS X - "--"
+ // Konqueror - "4 KB"
+ // Nautilus - "9 items" (the number of children)
+ }
+ return size(n->size());
+}
+
+QString QFileSystemModelPrivate::size(qint64 bytes)
+{
+ // According to the Si standard KB is 1000 bytes, KiB is 1024
+ // but on windows sizes are calculated by dividing by 1024 so we do what they do.
+ const qint64 kb = 1024;
+ const qint64 mb = 1024 * kb;
+ const qint64 gb = 1024 * mb;
+ const qint64 tb = 1024 * gb;
+ if (bytes >= tb)
+ return QFileSystemModel::tr("%1 TB").arg(QLocale().toString(qreal(bytes) / tb, 'f', 3));
+ if (bytes >= gb)
+ return QFileSystemModel::tr("%1 GB").arg(QLocale().toString(qreal(bytes) / gb, 'f', 2));
+ if (bytes >= mb)
+ return QFileSystemModel::tr("%1 MB").arg(QLocale().toString(qreal(bytes) / mb, 'f', 1));
+ if (bytes >= kb)
+ return QFileSystemModel::tr("%1 KB").arg(QLocale().toString(bytes / kb));
+ return QFileSystemModel::tr("%1 bytes").arg(QLocale().toString(bytes));
+}
+
+/*!
+ \internal
+*/
+QString QFileSystemModelPrivate::time(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return QString();
+#ifndef QT_NO_DATESTRING
+ return node(index)->lastModified().toString(Qt::SystemLocaleDate);
+#else
+ Q_UNUSED(index);
+ return QString();
+#endif
+}
+
+/*
+ \internal
+*/
+QString QFileSystemModelPrivate::type(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return QString();
+ return node(index)->type();
+}
+
+/*!
+ \internal
+*/
+QString QFileSystemModelPrivate::name(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return QString();
+ QFileSystemNode *dirNode = node(index);
+ if (dirNode->isSymLink() && fileInfoGatherer.resolveSymlinks()) {
+ QString fullPath = QDir::fromNativeSeparators(filePath(index));
+ if (resolvedSymLinks.contains(fullPath))
+ return resolvedSymLinks[fullPath];
+ }
+ 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())
+ return QIcon();
+ return node(index)->icon();
+}
+
+/*!
+ \reimp
+*/
+bool QFileSystemModel::setData(const QModelIndex &idx, const QVariant &value, int role)
+{
+ Q_D(QFileSystemModel);
+ if (!idx.isValid()
+ || idx.column() != 0
+ || role != Qt::EditRole
+ || (flags(idx) & Qt::ItemIsEditable) == 0) {
+ return false;
+ }
+
+ QString newName = value.toString();
+ QString oldName = idx.data().toString();
+ if (newName == idx.data().toString())
+ return true;
+
+ if (newName.isEmpty()
+ || newName.contains(QDir::separator())
+ || !QDir(filePath(parent(idx))).rename(oldName, newName)) {
+#ifndef QT_NO_MESSAGEBOX
+ QMessageBox::information(0, QFileSystemModel::tr("Invalid filename"),
+ QFileSystemModel::tr("<b>The name \"%1\" can not be used.</b><p>Try using another name, with fewer characters or no punctuations marks.")
+ .arg(newName),
+ QMessageBox::Ok);
+#endif // QT_NO_MESSAGEBOX
+ return false;
+ } else {
+ /*
+ *After re-naming something we don't want the selection to change*
+ - can't remove rows and later insert
+ - can't quickly remove and insert
+ - index pointer can't change because treeview doesn't use persistant index's
+
+ - if this get any more complicated think of changing it to just
+ use layoutChanged
+ */
+
+ QFileSystemModelPrivate::QFileSystemNode *indexNode = d->node(idx);
+ QFileSystemModelPrivate::QFileSystemNode *parentNode = indexNode->parent;
+ int visibleLocation = parentNode->visibleLocation(parentNode->children.value(indexNode->fileName)->fileName);
+
+ d->addNode(parentNode, newName,indexNode->info->fileInfo());
+ parentNode->visibleChildren.removeAt(visibleLocation);
+ QFileSystemModelPrivate::QFileSystemNode * oldValue = parentNode->children.value(oldName);
+ parentNode->children[newName] = oldValue;
+ QFileInfo info(d->rootDir, newName);
+ oldValue->fileName = newName;
+ oldValue->parent = parentNode;
+ oldValue->populate(d->fileInfoGatherer.getInfo(info));
+ oldValue->isVisible = true;
+
+ parentNode->children.remove(oldName);
+ parentNode->visibleChildren.insert(visibleLocation, newName);
+
+ d->delayedSort();
+ emit fileRenamed(filePath(idx.parent()), oldName, newName);
+ }
+ return true;
+}
+
+/*!
+ \reimp
+*/
+QVariant QFileSystemModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ switch (role) {
+ case Qt::DecorationRole:
+ if (section == 0) {
+ // ### TODO oh man this is ugly and doesn't even work all the way!
+ // it is still 2 pixels off
+ QImage pixmap(16, 1, QImage::Format_Mono);
+ pixmap.fill(0);
+ pixmap.setAlphaChannel(pixmap.createAlphaMask());
+ return pixmap;
+ }
+ break;
+ case Qt::TextAlignmentRole:
+ return Qt::AlignLeft;
+ }
+
+ if (orientation != Qt::Horizontal || role != Qt::DisplayRole)
+ return QAbstractItemModel::headerData(section, orientation, role);
+
+ QString returnValue;
+ switch (section) {
+ case 0: returnValue = tr("Name");
+ break;
+ case 1: returnValue = tr("Size");
+ break;
+ case 2: returnValue =
+#ifdef Q_OS_MAC
+ tr("Kind", "Match OS X Finder");
+#else
+ tr("Type", "All other platforms");
+#endif
+ break;
+ // Windows - Type
+ // OS X - Kind
+ // Konqueror - File Type
+ // Nautilus - Type
+ case 3: returnValue = tr("Date Modified");
+ break;
+ default: return QVariant();
+ }
+ return returnValue;
+}
+
+/*!
+ \reimp
+*/
+Qt::ItemFlags QFileSystemModel::flags(const QModelIndex &index) const
+{
+ Q_D(const QFileSystemModel);
+ Qt::ItemFlags flags = QAbstractItemModel::flags(index);
+ if (!index.isValid())
+ return flags;
+
+ QFileSystemModelPrivate::QFileSystemNode *indexNode = d->node(index);
+ if (d->nameFilterDisables && !d->passNameFilters(indexNode)) {
+ flags &= ~Qt::ItemIsEnabled;
+ // ### TODO you shouldn't be able to set this as the current item, task 119433
+ return flags;
+ }
+
+ flags |= Qt::ItemIsDragEnabled;
+ if (d->readOnly)
+ return flags;
+ if ((index.column() == 0) && indexNode->permissions() & QFile::WriteUser) {
+ flags |= Qt::ItemIsEditable;
+ if (indexNode->isDir())
+ flags |= Qt::ItemIsDropEnabled;
+ }
+ return flags;
+}
+
+/*!
+ \internal
+*/
+void QFileSystemModelPrivate::_q_performDelayedSort()
+{
+ Q_Q(QFileSystemModel);
+ q->sort(sortColumn, sortOrder);
+}
+
+static inline QChar getNextChar(const QString &s, int location)
+{
+ return (location < s.length()) ? s.at(location) : QChar();
+}
+
+/*!
+ Natural number sort, skips spaces.
+
+ Examples:
+ 1, 2, 10, 55, 100
+ 01.jpg, 2.jpg, 10.jpg
+
+ Note on the algorithm:
+ Only as many characters as necessary are looked at and at most they all
+ are looked at once.
+
+ Slower then QString::compare() (of course)
+ */
+int QFileSystemModelPrivate::naturalCompare(const QString &s1, const QString &s2, Qt::CaseSensitivity cs)
+{
+ for (int l1 = 0, l2 = 0; l1 <= s1.count() && l2 <= s2.count(); ++l1, ++l2) {
+ // skip spaces, tabs and 0's
+ QChar c1 = getNextChar(s1, l1);
+ while (c1.isSpace())
+ c1 = getNextChar(s1, ++l1);
+ QChar c2 = getNextChar(s2, l2);
+ while (c2.isSpace())
+ c2 = getNextChar(s2, ++l2);
+
+ if (c1.isDigit() && c2.isDigit()) {
+ while (c1.digitValue() == 0)
+ c1 = getNextChar(s1, ++l1);
+ while (c2.digitValue() == 0)
+ c2 = getNextChar(s2, ++l2);
+
+ int lookAheadLocation1 = l1;
+ int lookAheadLocation2 = l2;
+ int currentReturnValue = 0;
+ // find the last digit, setting currentReturnValue as we go if it isn't equal
+ for (
+ QChar lookAhead1 = c1, lookAhead2 = c2;
+ (lookAheadLocation1 <= s1.length() && lookAheadLocation2 <= s2.length());
+ lookAhead1 = getNextChar(s1, ++lookAheadLocation1),
+ lookAhead2 = getNextChar(s2, ++lookAheadLocation2)
+ ) {
+ bool is1ADigit = !lookAhead1.isNull() && lookAhead1.isDigit();
+ bool is2ADigit = !lookAhead2.isNull() && lookAhead2.isDigit();
+ if (!is1ADigit && !is2ADigit)
+ break;
+ if (!is1ADigit)
+ return -1;
+ if (!is2ADigit)
+ return 1;
+ if (currentReturnValue == 0) {
+ if (lookAhead1 < lookAhead2) {
+ currentReturnValue = -1;
+ } else if (lookAhead1 > lookAhead2) {
+ currentReturnValue = 1;
+ }
+ }
+ }
+ if (currentReturnValue != 0)
+ return currentReturnValue;
+ }
+
+ if (cs == Qt::CaseInsensitive) {
+ if (!c1.isLower()) c1 = c1.toLower();
+ if (!c2.isLower()) c2 = c2.toLower();
+ }
+ int r = QString::localeAwareCompare(c1, c2);
+ if (r < 0)
+ return -1;
+ if (r > 0)
+ return 1;
+ }
+ // The two strings are the same (02 == 2) so fall back to the normal sort
+ return QString::compare(s1, s2, cs);
+}
+
+/*
+ \internal
+ Helper functor used by sort()
+*/
+class QFileSystemModelSorter
+{
+public:
+ inline QFileSystemModelSorter(int column) : sortColumn(column) {}
+
+ bool compareNodes(const QFileSystemModelPrivate::QFileSystemNode *l,
+ const QFileSystemModelPrivate::QFileSystemNode *r) const
+ {
+ switch (sortColumn) {
+ case 0: {
+#ifndef Q_OS_MAC
+ // place directories before files
+ bool left = l->isDir();
+ bool right = r->isDir();
+ if (left ^ right)
+ return left;
+#endif
+ return QFileSystemModelPrivate::naturalCompare(l->fileName,
+ r->fileName, Qt::CaseInsensitive) < 0;
+ }
+ case 1:
+ // Directories go first
+ if (l->isDir() && !r->isDir())
+ return true;
+ return l->size() < r->size();
+ case 2:
+ return l->type() < r->type();
+ case 3:
+ return l->lastModified() < r->lastModified();
+ }
+ Q_ASSERT(false);
+ return false;
+ }
+
+ bool operator()(const QPair<QFileSystemModelPrivate::QFileSystemNode*, int> &l,
+ const QPair<QFileSystemModelPrivate::QFileSystemNode*, int> &r) const
+ {
+ return compareNodes(l.first, r.first);
+ }
+
+
+private:
+ int sortColumn;
+};
+
+/*
+ \internal
+
+ Sort all of the children of parent
+*/
+void QFileSystemModelPrivate::sortChildren(int column, const QModelIndex &parent)
+{
+ Q_Q(QFileSystemModel);
+ QFileSystemModelPrivate::QFileSystemNode *indexNode = node(parent);
+ if (indexNode->children.count() == 0)
+ return;
+
+ QList<QPair<QFileSystemModelPrivate::QFileSystemNode*, int> > values;
+ QHash<QString, QFileSystemNode *>::const_iterator iterator;
+ int i = 0;
+ for(iterator = indexNode->children.begin() ; iterator != indexNode->children.end() ; ++iterator) {
+ if (filtersAcceptsNode(iterator.value())) {
+ values.append(QPair<QFileSystemModelPrivate::QFileSystemNode*, int>((iterator.value()), i));
+ } else {
+ iterator.value()->isVisible = false;
+ }
+ i++;
+ }
+ QFileSystemModelSorter ms(column);
+ qStableSort(values.begin(), values.end(), ms);
+ // First update the new visible list
+ indexNode->visibleChildren.clear();
+ //No more dirty item we reset our internal dirty index
+ indexNode->dirtyChildrenIndex = -1;
+ for (int i = 0; i < values.count(); ++i) {
+ indexNode->visibleChildren.append(values.at(i).first->fileName);
+ values.at(i).first->isVisible = true;
+ }
+
+ if (!disableRecursiveSort) {
+ for (int i = 0; i < q->rowCount(parent); ++i) {
+ const QModelIndex childIndex = q->index(i, 0, parent);
+ QFileSystemModelPrivate::QFileSystemNode *indexNode = node(childIndex);
+ //Only do a recursive sort on visible nodes
+ if (indexNode->isVisible)
+ sortChildren(column, childIndex);
+ }
+ }
+}
+
+/*!
+ \reimp
+*/
+void QFileSystemModel::sort(int column, Qt::SortOrder order)
+{
+ Q_D(QFileSystemModel);
+ if (d->sortOrder == order && d->sortColumn == column && !d->forceSort)
+ return;
+
+ emit layoutAboutToBeChanged();
+ QModelIndexList oldList = persistentIndexList();
+ QList<QPair<QFileSystemModelPrivate::QFileSystemNode*, int> > oldNodes;
+ for (int i = 0; i < oldList.count(); ++i) {
+ QPair<QFileSystemModelPrivate::QFileSystemNode*, int> pair(d->node(oldList.at(i)), oldList.at(i).column());
+ oldNodes.append(pair);
+ }
+
+ if (!(d->sortColumn == column && d->sortOrder != order && !d->forceSort)) {
+ //we sort only from where we are, don't need to sort all the model
+ d->sortChildren(column, index(rootPath()));
+ d->sortColumn = column;
+ d->forceSort = false;
+ }
+ d->sortOrder = order;
+
+ QModelIndexList newList;
+ for (int i = 0; i < oldNodes.count(); ++i) {
+ QModelIndex idx = d->index(oldNodes.at(i).first);
+ idx = idx.sibling(idx.row(), oldNodes.at(i).second);
+ newList.append(idx);
+ }
+ changePersistentIndexList(oldList, newList);
+ emit layoutChanged();
+}
+
+/*!
+ Returns a list of MIME types that can be used to describe a list of items
+ in the model.
+*/
+QStringList QFileSystemModel::mimeTypes() const
+{
+ return QStringList(QLatin1String("text/uri-list"));
+}
+
+/*!
+ Returns an object that contains a serialized description of the specified
+ \a indexes. The format used to describe the items corresponding to the
+ indexes is obtained from the mimeTypes() function.
+
+ If the list of indexes is empty, 0 is returned rather than a serialized
+ empty list.
+*/
+QMimeData *QFileSystemModel::mimeData(const QModelIndexList &indexes) const
+{
+ QList<QUrl> urls;
+ QList<QModelIndex>::const_iterator it = indexes.begin();
+ for (; it != indexes.end(); ++it)
+ if ((*it).column() == 0)
+ urls << QUrl::fromLocalFile(filePath(*it));
+ QMimeData *data = new QMimeData();
+ data->setUrls(urls);
+ return data;
+}
+
+/*!
+ Handles the \a data supplied by a drag and drop operation that ended with
+ the given \a action over the row in the model specified by the \a row and
+ \a column and by the \a parent index.
+
+ \sa supportedDropActions()
+*/
+bool QFileSystemModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent)
+{
+ Q_UNUSED(row);
+ Q_UNUSED(column);
+ if (!parent.isValid() || isReadOnly())
+ return false;
+
+ bool success = true;
+ QString to = filePath(parent) + QDir::separator();
+
+ QList<QUrl> urls = data->urls();
+ QList<QUrl>::const_iterator it = urls.constBegin();
+
+ switch (action) {
+ case Qt::CopyAction:
+ for (; it != urls.constEnd(); ++it) {
+ QString path = (*it).toLocalFile();
+ success = QFile::copy(path, to + QFileInfo(path).fileName()) && success;
+ }
+ break;
+ case Qt::LinkAction:
+ for (; it != urls.constEnd(); ++it) {
+ QString path = (*it).toLocalFile();
+ success = QFile::link(path, to + QFileInfo(path).fileName()) && success;
+ }
+ break;
+ case Qt::MoveAction:
+ for (; it != urls.constEnd(); ++it) {
+ QString path = (*it).toLocalFile();
+ success = QFile::rename(path, to + QFileInfo(path).fileName()) && success;
+ }
+ break;
+ default:
+ return false;
+ }
+
+ return success;
+}
+
+/*!
+ \reimp
+*/
+Qt::DropActions QFileSystemModel::supportedDropActions() const
+{
+ return Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
+}
+
+/*!
+ Returns the path of the item stored in the model under the
+ \a index given.
+*/
+QString QFileSystemModel::filePath(const QModelIndex &index) const
+{
+ Q_D(const QFileSystemModel);
+ QString fullPath = d->filePath(index);
+ QFileSystemModelPrivate::QFileSystemNode *dirNode = d->node(index);
+ if (dirNode->isSymLink() && d->fileInfoGatherer.resolveSymlinks()
+ && d->resolvedSymLinks.contains(fullPath)
+ && dirNode->isDir()) {
+ QFileInfo resolvedInfo(fullPath);
+ resolvedInfo = resolvedInfo.canonicalFilePath();
+ if (resolvedInfo.exists())
+ return resolvedInfo.filePath();
+ }
+ return fullPath;
+}
+
+QString QFileSystemModelPrivate::filePath(const QModelIndex &index) const
+{
+ Q_Q(const QFileSystemModel);
+ Q_UNUSED(q);
+ if (!index.isValid())
+ return QString();
+ Q_ASSERT(index.model() == q);
+
+ QStringList path;
+ QModelIndex idx = index;
+ while (idx.isValid()) {
+ QFileSystemModelPrivate::QFileSystemNode *dirNode = node(idx);
+ if (dirNode)
+ path.prepend(dirNode->fileName);
+ idx = idx.parent();
+ }
+ QString fullPath = QDir::fromNativeSeparators(path.join(QDir::separator()));
+#if !defined(Q_OS_WIN) || defined(Q_OS_WINCE)
+ if ((fullPath.length() > 2) && fullPath[0] == QLatin1Char('/') && fullPath[1] == QLatin1Char('/'))
+ fullPath = fullPath.mid(1);
+#endif
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ if (fullPath.length() == 2 && fullPath.endsWith(QLatin1Char(':')))
+ fullPath.append(QLatin1Char('/'));
+#endif
+ return fullPath;
+}
+
+/*!
+ Create a directory with the \a name in the \a parent model index.
+*/
+QModelIndex QFileSystemModel::mkdir(const QModelIndex &parent, const QString &name)
+{
+ Q_D(QFileSystemModel);
+ if (!parent.isValid())
+ return parent;
+
+ QDir dir(filePath(parent));
+ if (!dir.mkdir(name))
+ return QModelIndex();
+ QFileSystemModelPrivate::QFileSystemNode *parentNode = d->node(parent);
+ d->addNode(parentNode, name, QFileInfo());
+ Q_ASSERT(parentNode->children.contains(name));
+ QFileSystemModelPrivate::QFileSystemNode *node = parentNode->children[name];
+ node->populate(d->fileInfoGatherer.getInfo(QFileInfo(dir.absolutePath() + QDir::separator() + name)));
+ d->addVisibleFiles(parentNode, QStringList(name));
+ return d->index(node);
+}
+
+/*!
+ Returns the complete OR-ed together combination of QFile::Permission for the \a index.
+ */
+QFile::Permissions QFileSystemModel::permissions(const QModelIndex &index) const
+{
+ Q_D(const QFileSystemModel);
+ QFile::Permissions p = d->node(index)->permissions();
+ if (d->readOnly) {
+ p ^= (QFile::WriteOwner | QFile::WriteUser
+ | QFile::WriteGroup | QFile::WriteOther);
+ }
+ return p;
+}
+
+/*!
+ Sets the directory that is being watched by the model to \a newPath by
+ installing a \l{QFileSystemWatcher}{file system watcher} on it. Any
+ changes to files and directories within this directory will be
+ reflected in the model.
+
+ If the path is changed, the rootPathChanged() signal will be emitted.
+
+ \note This function does not change the structure of the model or
+ modify the data available to views. In other words, the "root" of
+ the model is \e not changed to include only files and directories
+ within the directory specified by \a newPath in the file system.
+ */
+QModelIndex QFileSystemModel::setRootPath(const QString &newPath)
+{
+ Q_D(QFileSystemModel);
+#ifdef Q_OS_WIN
+#ifdef Q_OS_WIN32
+ QString longNewPath = qt_GetLongPathName(newPath);
+#else
+ QString longNewPath = QDir::fromNativeSeparators(newPath);
+#endif
+#else
+ QString longNewPath = newPath;
+#endif
+ QDir newPathDir(longNewPath);
+ //we remove .. and . from the given path if exist
+ if (!newPath.isEmpty()) {
+ longNewPath = QDir::cleanPath(longNewPath);
+ newPathDir.setPath(longNewPath);
+ }
+
+ d->setRootPath = true;
+
+ //user don't ask for the root path ("") but the conversion failed
+ if (!newPath.isEmpty() && longNewPath.isEmpty())
+ return d->index(rootPath());
+
+ if (d->rootDir.path() == longNewPath)
+ return d->index(rootPath());
+
+ bool showDrives = (longNewPath.isEmpty() || longNewPath == d->myComputer());
+ if (!showDrives && !newPathDir.exists())
+ return d->index(rootPath());
+
+ //We remove the watcher on the previous path
+ if (!rootPath().isEmpty() && rootPath() != QLatin1String(".")) {
+ //This remove the watcher for the old rootPath
+ d->fileInfoGatherer.removePath(rootPath());
+ //This line "marks" the node as dirty, so the next fetchMore
+ //call on the path will ask the gatherer to install a watcher again
+ //But it doesn't re-fetch everything
+ d->node(rootPath())->populatedChildren = false;
+ }
+
+ // We have a new valid root path
+ d->rootDir = newPathDir;
+ QModelIndex newRootIndex;
+ if (showDrives) {
+ // otherwise dir will become '.'
+ d->rootDir.setPath(QLatin1String(""));
+ } else {
+ newRootIndex = d->index(newPathDir.path());
+ }
+ fetchMore(newRootIndex);
+ emit rootPathChanged(longNewPath);
+ d->forceSort = true;
+ d->delayedSort();
+ return newRootIndex;
+}
+
+/*!
+ The currently set root path
+
+ \sa rootDirectory()
+*/
+QString QFileSystemModel::rootPath() const
+{
+ Q_D(const QFileSystemModel);
+ return d->rootDir.path();
+}
+
+/*!
+ The currently set directory
+
+ \sa rootPath()
+*/
+QDir QFileSystemModel::rootDirectory() const
+{
+ Q_D(const QFileSystemModel);
+ QDir dir(d->rootDir);
+ dir.setNameFilters(nameFilters());
+ dir.setFilter(filter());
+ return dir;
+}
+
+/*!
+ Sets the \a provider of file icons for the directory model.
+*/
+void QFileSystemModel::setIconProvider(QFileIconProvider *provider)
+{
+ Q_D(QFileSystemModel);
+ d->fileInfoGatherer.setIconProvider(provider);
+ d->root.updateIcon(provider, QString());
+}
+
+/*!
+ Returns the file icon provider for this directory model.
+*/
+QFileIconProvider *QFileSystemModel::iconProvider() const
+{
+ Q_D(const QFileSystemModel);
+ return d->fileInfoGatherer.iconProvider();
+}
+
+/*!
+ Sets the directory model's filter to that specified by \a filters.
+
+ Note that the filter you set should always include the QDir::AllDirs enum value,
+ otherwise QFileSystemModel won't be able to read the directory structure.
+
+ \sa QDir::Filters
+*/
+void QFileSystemModel::setFilter(QDir::Filters filters)
+{
+ Q_D(QFileSystemModel);
+ if (d->filters == filters)
+ return;
+ d->filters = filters;
+ // CaseSensitivity might have changed
+ setNameFilters(nameFilters());
+ d->forceSort = true;
+ d->delayedSort();
+}
+
+/*!
+ Returns the filter specified for the directory model.
+
+ If a filter has not been set, the default filter is QDir::AllEntries |
+ QDir::NoDotAndDotDot | QDir::AllDirs.
+
+ \sa QDir::Filters
+*/
+QDir::Filters QFileSystemModel::filter() const
+{
+ Q_D(const QFileSystemModel);
+ return d->filters;
+}
+
+/*!
+ \property QFileSystemModel::resolveSymlinks
+ \brief Whether the directory model should resolve symbolic links
+
+ This is only relevant on operating systems that support symbolic links.
+
+ By default, this property is false.
+*/
+void QFileSystemModel::setResolveSymlinks(bool enable)
+{
+ Q_D(QFileSystemModel);
+ d->fileInfoGatherer.setResolveSymlinks(enable);
+}
+
+bool QFileSystemModel::resolveSymlinks() const
+{
+ Q_D(const QFileSystemModel);
+ return d->fileInfoGatherer.resolveSymlinks();
+}
+
+/*!
+ \property QFileSystemModel::readOnly
+ \brief Whether the directory model allows writing to the file system
+
+ If this property is set to false, the directory model will allow renaming, copying
+ and deleting of files and directories.
+
+ This property is true by default
+*/
+void QFileSystemModel::setReadOnly(bool enable)
+{
+ Q_D(QFileSystemModel);
+ d->readOnly = enable;
+}
+
+bool QFileSystemModel::isReadOnly() const
+{
+ Q_D(const QFileSystemModel);
+ return d->readOnly;
+}
+
+/*!
+ \property QFileSystemModel::nameFilterDisables
+ \brief Whether files that don't pass the name filter are hidden or disabled
+
+ This property is true by default
+*/
+void QFileSystemModel::setNameFilterDisables(bool enable)
+{
+ Q_D(QFileSystemModel);
+ if (d->nameFilterDisables == enable)
+ return;
+ d->nameFilterDisables = enable;
+ d->forceSort = true;
+ d->delayedSort();
+}
+
+bool QFileSystemModel::nameFilterDisables() const
+{
+ Q_D(const QFileSystemModel);
+ return d->nameFilterDisables;
+}
+
+/*!
+ Sets the name \a filters to apply against the existing files.
+*/
+void QFileSystemModel::setNameFilters(const QStringList &filters)
+{
+ // Prep the regexp's ahead of time
+#ifndef QT_NO_REGEXP
+ Q_D(QFileSystemModel);
+
+ if (!d->bypassFilters.isEmpty()) {
+ // update the bypass filter to only bypass the stuff that must be kept around
+ d->bypassFilters.clear();
+ // We guarantee that rootPath will stick around
+ QPersistentModelIndex root(index(rootPath()));
+ QModelIndexList persistantList = persistentIndexList();
+ for (int i = 0; i < persistantList.count(); ++i) {
+ QFileSystemModelPrivate::QFileSystemNode *node;
+ node = d->node(persistantList.at(i));
+ while (node) {
+ if (d->bypassFilters.contains(node))
+ break;
+ if (node->isDir())
+ d->bypassFilters[node] = true;
+ node = node->parent;
+ }
+ }
+ }
+
+ d->nameFilters.clear();
+ const Qt::CaseSensitivity caseSensitive =
+ (filter() & QDir::CaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive;
+ for (int i = 0; i < filters.size(); ++i) {
+ d->nameFilters << QRegExp(filters.at(i), caseSensitive, QRegExp::Wildcard);
+ }
+ d->forceSort = true;
+ d->delayedSort();
+#endif
+}
+
+/*!
+ Returns a list of filters applied to the names in the model.
+*/
+QStringList QFileSystemModel::nameFilters() const
+{
+ Q_D(const QFileSystemModel);
+ QStringList filters;
+#ifndef QT_NO_REGEXP
+ for (int i = 0; i < d->nameFilters.size(); ++i) {
+ filters << d->nameFilters.at(i).pattern();
+ }
+#endif
+ return filters;
+}
+
+/*!
+ \reimp
+*/
+bool QFileSystemModel::event(QEvent *event)
+{
+ Q_D(QFileSystemModel);
+ if (event->type() == QEvent::LanguageChange) {
+ d->root.retranslateStrings(d->fileInfoGatherer.iconProvider(), QString());
+ return true;
+ }
+ return QAbstractItemModel::event(event);
+}
+
+bool QFileSystemModel::rmdir(const QModelIndex &aindex) const
+{
+ QString path = filePath(aindex);
+ QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func());
+ d->fileInfoGatherer.removePath(path);
+ return QDir().rmdir(path);
+}
+
+/*!
+ \internal
+
+ Performed quick listing and see if any files have been added or removed,
+ then fetch more information on visible files.
+ */
+void QFileSystemModelPrivate::_q_directoryChanged(const QString &directory, const QStringList &files)
+{
+ QFileSystemModelPrivate::QFileSystemNode *parentNode = node(directory, false);
+ if (parentNode->children.count() == 0)
+ return;
+ QStringList toRemove;
+#if defined(Q_OS_SYMBIAN)
+ // Filename case must be exact in qBinaryFind below, so create a list of all lowercase names.
+ QStringList newFiles;
+ for(int i = 0; i < files.size(); i++) {
+ newFiles << files.at(i).toLower();
+ }
+#else
+ QStringList newFiles = files;
+#endif
+ qSort(newFiles.begin(), newFiles.end());
+ QHash<QString, QFileSystemNode*>::const_iterator i = parentNode->children.constBegin();
+ while (i != parentNode->children.constEnd()) {
+ QStringList::iterator iterator;
+ iterator = qBinaryFind(newFiles.begin(), newFiles.end(),
+#if defined(Q_OS_SYMBIAN)
+ i.value()->fileName.toLower());
+#else
+ i.value()->fileName);
+#endif
+ if (iterator == newFiles.end()) {
+ toRemove.append(i.value()->fileName);
+ }
+ ++i;
+ }
+ for (int i = 0 ; i < toRemove.count() ; ++i )
+ removeNode(parentNode, toRemove[i]);
+}
+
+/*!
+ \internal
+
+ Adds a new file to the children of parentNode
+
+ *WARNING* this will change the count of children
+*/
+QFileSystemModelPrivate::QFileSystemNode* QFileSystemModelPrivate::addNode(QFileSystemNode *parentNode, const QString &fileName, const QFileInfo& info)
+{
+ // In the common case, itemLocation == count() so check there first
+ QFileSystemModelPrivate::QFileSystemNode *node = new QFileSystemModelPrivate::QFileSystemNode(fileName, parentNode);
+#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;
+}
+
+/*!
+ \internal
+
+ File at parentNode->children(itemLocation) has been removed, remove from the lists
+ and emit signals if necessary
+
+ *WARNING* this will change the count of children and could change visibleChildren
+ */
+void QFileSystemModelPrivate::removeNode(QFileSystemModelPrivate::QFileSystemNode *parentNode, const QString& name)
+{
+ Q_Q(QFileSystemModel);
+ QModelIndex parent = index(parentNode);
+ bool indexHidden = isHiddenByFilter(parentNode, parent);
+
+ int vLocation = parentNode->visibleLocation(name);
+ if (vLocation >= 0 && !indexHidden)
+ q->beginRemoveRows(parent, translateVisibleLocation(parentNode, vLocation),
+ translateVisibleLocation(parentNode, vLocation));
+ QFileSystemNode * node = parentNode->children.take(name);
+ delete node;
+ // cleanup sort files after removing rather then re-sorting which is O(n)
+ if (vLocation >= 0)
+ parentNode->visibleChildren.removeAt(vLocation);
+ if (vLocation >= 0 && !indexHidden)
+ q->endRemoveRows();
+}
+
+/*
+ \internal
+ Helper functor used by addVisibleFiles()
+*/
+class QFileSystemModelVisibleFinder
+{
+public:
+ inline QFileSystemModelVisibleFinder(QFileSystemModelPrivate::QFileSystemNode *node, QFileSystemModelSorter *sorter) : parentNode(node), sorter(sorter) {}
+
+ bool operator()(const QString &, QString r) const
+ {
+ return sorter->compareNodes(parentNode->children.value(name), parentNode->children.value(r));
+ }
+
+ QString name;
+private:
+ QFileSystemModelPrivate::QFileSystemNode *parentNode;
+ QFileSystemModelSorter *sorter;
+};
+
+/*!
+ \internal
+
+ File at parentNode->children(itemLocation) was not visible before, but now should be
+ and emit signals if necessary.
+
+ *WARNING* this will change the visible count
+ */
+void QFileSystemModelPrivate::addVisibleFiles(QFileSystemNode *parentNode, const QStringList &newFiles)
+{
+ Q_Q(QFileSystemModel);
+ QModelIndex parent = index(parentNode);
+ bool indexHidden = isHiddenByFilter(parentNode, parent);
+ if (!indexHidden) {
+ q->beginInsertRows(parent, parentNode->visibleChildren.count() , parentNode->visibleChildren.count() + newFiles.count() - 1);
+ }
+
+ if (parentNode->dirtyChildrenIndex == -1)
+ parentNode->dirtyChildrenIndex = parentNode->visibleChildren.count();
+
+ for (int i = 0; i < newFiles.count(); ++i) {
+ parentNode->visibleChildren.append(newFiles.at(i));
+ parentNode->children[newFiles.at(i)]->isVisible = true;
+ }
+ if (!indexHidden)
+ q->endInsertRows();
+}
+
+/*!
+ \internal
+
+ File was visible before, but now should NOT be
+
+ *WARNING* this will change the visible count
+ */
+void QFileSystemModelPrivate::removeVisibleFile(QFileSystemNode *parentNode, int vLocation)
+{
+ Q_Q(QFileSystemModel);
+ if (vLocation == -1)
+ return;
+ QModelIndex parent = index(parentNode);
+ bool indexHidden = isHiddenByFilter(parentNode, parent);
+ if (!indexHidden)
+ q->beginRemoveRows(parent, translateVisibleLocation(parentNode, vLocation),
+ translateVisibleLocation(parentNode, vLocation));
+ parentNode->children[parentNode->visibleChildren.at(vLocation)]->isVisible = false;
+ parentNode->visibleChildren.removeAt(vLocation);
+ if (!indexHidden)
+ q->endRemoveRows();
+}
+
+/*!
+ \internal
+
+ The thread has received new information about files,
+ update and emit dataChanged if it has actually changed.
+ */
+void QFileSystemModelPrivate::_q_fileSystemChanged(const QString &path, const QList<QPair<QString, QFileInfo> > &updates)
+{
+ Q_Q(QFileSystemModel);
+ QVector<QString> rowsToUpdate;
+ QStringList newFiles;
+ QFileSystemModelPrivate::QFileSystemNode *parentNode = node(path, false);
+ QModelIndex parentIndex = index(parentNode);
+ for (int i = 0; i < updates.count(); ++i) {
+ QString fileName = updates.at(i).first;
+ Q_ASSERT(!fileName.isEmpty());
+ QExtendedInformation info = fileInfoGatherer.getInfo(updates.at(i).second);
+ bool previouslyHere = parentNode->children.contains(fileName);
+ if (!previouslyHere) {
+ addNode(parentNode, fileName, info.fileInfo());
+ }
+ QFileSystemModelPrivate::QFileSystemNode * node = parentNode->children.value(fileName);
+ bool isCaseSensitive = parentNode->caseSensitive();
+ if (isCaseSensitive) {
+ if (node->fileName != fileName)
+ continue;
+ } else {
+ if (QString::compare(node->fileName,fileName,Qt::CaseInsensitive) != 0)
+ continue;
+ }
+ if (isCaseSensitive) {
+ Q_ASSERT(node->fileName == fileName);
+ } else {
+ node->fileName = fileName;
+ }
+
+ if (info.size() == -1 && !info.isSymLink()) {
+ removeNode(parentNode, fileName);
+ continue;
+ }
+ if (*node != info ) {
+ node->populate(info);
+ bypassFilters.remove(node);
+ // brand new information.
+ if (filtersAcceptsNode(node)) {
+ if (!node->isVisible) {
+ newFiles.append(fileName);
+ } else {
+ rowsToUpdate.append(fileName);
+ }
+ } else {
+ if (node->isVisible) {
+ int visibleLocation = parentNode->visibleLocation(fileName);
+ removeVisibleFile(parentNode, visibleLocation);
+ } else {
+ // The file is not visible, don't do anything
+ }
+ }
+ }
+ }
+
+ // bundle up all of the changed signals into as few as possible.
+ qSort(rowsToUpdate.begin(), rowsToUpdate.end());
+ QString min;
+ QString max;
+ for (int i = 0; i < rowsToUpdate.count(); ++i) {
+ QString value = rowsToUpdate.at(i);
+ //##TODO is there a way to bundle signals with QString as the content of the list?
+ /*if (min.isEmpty()) {
+ min = value;
+ if (i != rowsToUpdate.count() - 1)
+ continue;
+ }
+ if (i != rowsToUpdate.count() - 1) {
+ if ((value == min + 1 && max.isEmpty()) || value == max + 1) {
+ max = value;
+ continue;
+ }
+ }*/
+ max = value;
+ min = value;
+ int visibleMin = parentNode->visibleLocation(min);
+ int visibleMax = parentNode->visibleLocation(max);
+ if (visibleMin >= 0
+ && visibleMin < parentNode->visibleChildren.count()
+ && parentNode->visibleChildren.at(visibleMin) == min
+ && visibleMax >= 0) {
+ QModelIndex bottom = q->index(translateVisibleLocation(parentNode, visibleMin), 0, parentIndex);
+ QModelIndex top = q->index(translateVisibleLocation(parentNode, visibleMax), 3, parentIndex);
+ emit q->dataChanged(bottom, top);
+ }
+
+ /*min = QString();
+ max = QString();*/
+ }
+
+ if (newFiles.count() > 0) {
+ addVisibleFiles(parentNode, newFiles);
+ }
+
+ if (newFiles.count() > 0 || (sortColumn != 0 && rowsToUpdate.count() > 0)) {
+ forceSort = true;
+ delayedSort();
+ }
+}
+
+/*!
+ \internal
+*/
+void QFileSystemModelPrivate::_q_resolvedName(const QString &fileName, const QString &resolvedName)
+{
+ resolvedSymLinks[fileName] = resolvedName;
+}
+
+/*!
+ \internal
+*/
+void QFileSystemModelPrivate::init()
+{
+ Q_Q(QFileSystemModel);
+ qRegisterMetaType<QList<QPair<QString,QFileInfo> > >("QList<QPair<QString,QFileInfo> >");
+ q->connect(&fileInfoGatherer, SIGNAL(newListOfFiles(QString,QStringList)),
+ q, SLOT(_q_directoryChanged(QString,QStringList)));
+ q->connect(&fileInfoGatherer, SIGNAL(updates(QString,QList<QPair<QString,QFileInfo> >)),
+ 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);
+
+ QHash<int, QByteArray> roles = q->roleNames();
+ roles.insertMulti(QFileSystemModel::FileIconRole, "fileIcon"); // == Qt::decoration
+ roles.insert(QFileSystemModel::FilePathRole, "filePath");
+ roles.insert(QFileSystemModel::FileNameRole, "fileName");
+ roles.insert(QFileSystemModel::FilePermissions, "filePermissions");
+ q->setRoleNames(roles);
+}
+
+/*!
+ \internal
+
+ Returns false if node doesn't pass the filters otherwise true
+
+ QDir::Modified is not supported
+ QDir::Drives is not supported
+*/
+bool QFileSystemModelPrivate::filtersAcceptsNode(const QFileSystemNode *node) const
+{
+ // always accept drives
+ if (node->parent == &root || bypassFilters.contains(node))
+ return true;
+
+ // If we don't know anything yet don't accept it
+ if (!node->hasInformation())
+ return false;
+
+ const bool filterPermissions = ((filters & QDir::PermissionMask)
+ && (filters & QDir::PermissionMask) != QDir::PermissionMask);
+ const bool hideDirs = !(filters & (QDir::Dirs | QDir::AllDirs));
+ const bool hideFiles = !(filters & QDir::Files);
+ const bool hideReadable = !(!filterPermissions || (filters & QDir::Readable));
+ const bool hideWritable = !(!filterPermissions || (filters & QDir::Writable));
+ const bool hideExecutable = !(!filterPermissions || (filters & QDir::Executable));
+ const bool hideHidden = !(filters & QDir::Hidden);
+ const bool hideSystem = !(filters & QDir::System);
+ const bool hideSymlinks = (filters & QDir::NoSymLinks);
+ const bool hideDotAndDotDot = (filters & QDir::NoDotAndDotDot);
+
+ // Note that we match the behavior of entryList and not QFileInfo on this and this
+ // incompatibility won't be fixed until Qt 5 at least
+ bool isDotOrDot = ( (node->fileName == QLatin1String(".")
+ || node->fileName == QLatin1String("..")));
+ if ( (hideHidden && (!isDotOrDot && node->isHidden()))
+ || (hideSystem && node->isSystem())
+ || (hideDirs && node->isDir())
+ || (hideFiles && node->isFile())
+ || (hideSymlinks && node->isSymLink())
+ || (hideReadable && node->isReadable())
+ || (hideWritable && node->isWritable())
+ || (hideExecutable && node->isExecutable())
+ || (hideDotAndDotDot && isDotOrDot))
+ return false;
+
+ return nameFilterDisables || passNameFilters(node);
+}
+
+/*
+ \internal
+
+ Returns true if node passes the name filters and should be visible.
+ */
+bool QFileSystemModelPrivate::passNameFilters(const QFileSystemNode *node) const
+{
+#ifndef QT_NO_REGEXP
+ if (nameFilters.isEmpty())
+ return true;
+
+ // Check the name regularexpression filters
+ if (!(node->isDir() && (filters & QDir::AllDirs))) {
+ for (int i = 0; i < nameFilters.size(); ++i) {
+ if (nameFilters.at(i).exactMatch(node->fileName))
+ return true;
+ }
+ return false;
+ }
+#endif
+ return true;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qfilesystemmodel.cpp"
+
+#endif // QT_NO_FILESYSTEMMODEL
diff --git a/src/widgets/dialogs/qfilesystemmodel.h b/src/widgets/dialogs/qfilesystemmodel.h
new file mode 100644
index 0000000000..8aa9875d13
--- /dev/null
+++ b/src/widgets/dialogs/qfilesystemmodel.h
@@ -0,0 +1,180 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFILESYSTEMMODEL_H
+#define QFILESYSTEMMODEL_H
+
+#include <QtCore/qabstractitemmodel.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qdir.h>
+#include <QtGui/qicon.h>
+#include <QtCore/qdiriterator.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_FILESYSTEMMODEL
+
+class ExtendedInformation;
+class QFileSystemModelPrivate;
+class QFileIconProvider;
+
+class Q_GUI_EXPORT QFileSystemModel : public QAbstractItemModel
+{
+ Q_OBJECT
+ Q_PROPERTY(bool resolveSymlinks READ resolveSymlinks WRITE setResolveSymlinks)
+ Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly)
+ Q_PROPERTY(bool nameFilterDisables READ nameFilterDisables WRITE setNameFilterDisables)
+
+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 {
+ FileIconRole = Qt::DecorationRole,
+ FilePathRole = Qt::UserRole + 1,
+ FileNameRole = Qt::UserRole + 2,
+ FilePermissions = Qt::UserRole + 3
+ };
+
+ explicit QFileSystemModel(QObject *parent = 0);
+ ~QFileSystemModel();
+
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
+ QModelIndex index(const QString &path, int column = 0) const;
+ QModelIndex parent(const QModelIndex &child) const;
+ bool hasChildren(const QModelIndex &parent = QModelIndex()) const;
+ bool canFetchMore(const QModelIndex &parent) const;
+ void fetchMore(const QModelIndex &parent);
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
+
+ QVariant myComputer(int role = Qt::DisplayRole) const;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
+
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
+
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+
+ void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
+
+ QStringList mimeTypes() const;
+ QMimeData *mimeData(const QModelIndexList &indexes) const;
+ bool dropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent);
+ Qt::DropActions supportedDropActions() const;
+
+ // QFileSystemModel specific API
+ QModelIndex setRootPath(const QString &path);
+ QString rootPath() const;
+ QDir rootDirectory() const;
+
+ void setIconProvider(QFileIconProvider *provider);
+ QFileIconProvider *iconProvider() const;
+
+ void setFilter(QDir::Filters filters);
+ QDir::Filters filter() const;
+
+ void setResolveSymlinks(bool enable);
+ bool resolveSymlinks() const;
+
+ void setReadOnly(bool enable);
+ bool isReadOnly() const;
+
+ void setNameFilterDisables(bool enable);
+ bool nameFilterDisables() const;
+
+ void setNameFilters(const QStringList &filters);
+ QStringList nameFilters() const;
+
+ QString filePath(const QModelIndex &index) const;
+ bool isDir(const QModelIndex &index) const;
+ qint64 size(const QModelIndex &index) const;
+ QString type(const QModelIndex &index) const;
+ QDateTime lastModified(const QModelIndex &index) const;
+
+ QModelIndex mkdir(const QModelIndex &parent, const QString &name);
+ bool rmdir(const QModelIndex &index) const; // ### Qt5: should not be const
+ inline QString fileName(const QModelIndex &index) const;
+ inline QIcon fileIcon(const QModelIndex &index) const;
+ QFile::Permissions permissions(const QModelIndex &index) const;
+ inline QFileInfo fileInfo(const QModelIndex &index) const;
+ bool remove(const QModelIndex &index) const;
+
+protected:
+ QFileSystemModel(QFileSystemModelPrivate &, QObject *parent = 0);
+ void timerEvent(QTimerEvent *event);
+ bool event(QEvent *event);
+
+private:
+ Q_DECLARE_PRIVATE(QFileSystemModel)
+ Q_DISABLE_COPY(QFileSystemModel)
+
+ Q_PRIVATE_SLOT(d_func(), void _q_directoryChanged(const QString &directory, const QStringList &list))
+ Q_PRIVATE_SLOT(d_func(), void _q_performDelayedSort())
+ Q_PRIVATE_SLOT(d_func(), void _q_fileSystemChanged(const QString &path, const QList<QPair<QString, QFileInfo> > &))
+ Q_PRIVATE_SLOT(d_func(), void _q_resolvedName(const QString &fileName, const QString &resolvedName))
+
+ friend class QFileDialogPrivate;
+};
+
+inline QString QFileSystemModel::fileName(const QModelIndex &aindex) const
+{ return aindex.data(Qt::DisplayRole).toString(); }
+inline QIcon QFileSystemModel::fileIcon(const QModelIndex &aindex) const
+{ return qvariant_cast<QIcon>(aindex.data(Qt::DecorationRole)); }
+inline QFileInfo QFileSystemModel::fileInfo(const QModelIndex &aindex) const
+{ return QFileInfo(filePath(aindex)); }
+
+#endif // QT_NO_FILESYSTEMMODEL
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFILESYSTEMMODEL_H
+
diff --git a/src/widgets/dialogs/qfilesystemmodel_p.h b/src/widgets/dialogs/qfilesystemmodel_p.h
new file mode 100644
index 0000000000..e83bbd11d3
--- /dev/null
+++ b/src/widgets/dialogs/qfilesystemmodel_p.h
@@ -0,0 +1,337 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFILESYSTEMMODEL_P_H
+#define QFILESYSTEMMODEL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qfilesystemmodel.h"
+
+#ifndef QT_NO_FILESYSTEMMODEL
+
+#include <private/qabstractitemmodel_p.h>
+#include <qabstractitemmodel.h>
+#include "qfileinfogatherer_p.h"
+#include <qpair.h>
+#include <qdir.h>
+#include <qicon.h>
+#include <qdir.h>
+#include <qicon.h>
+#include <qfileinfo.h>
+#include <qtimer.h>
+#include <qhash.h>
+
+QT_BEGIN_NAMESPACE
+
+class ExtendedInformation;
+class QFileSystemModelPrivate;
+class QFileIconProvider;
+
+class Q_AUTOTEST_EXPORT QFileSystemModelPrivate : public QAbstractItemModelPrivate
+{
+ Q_DECLARE_PUBLIC(QFileSystemModel)
+
+public:
+ class QFileSystemNode
+ {
+ public:
+ QFileSystemNode(const QString &filename = QString(), QFileSystemNode *p = 0)
+ : fileName(filename), populatedChildren(false), isVisible(false), dirtyChildrenIndex(-1), parent(p), info(0) {}
+ ~QFileSystemNode() {
+ QHash<QString, QFileSystemNode*>::const_iterator i = children.constBegin();
+ while (i != children.constEnd()) {
+ delete i.value();
+ ++i;
+ }
+ delete info;
+ info = 0;
+ parent = 0;
+ }
+
+ 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(""); }
+ inline QDateTime lastModified() const { if (info) return info->lastModified(); return QDateTime(); }
+ inline QFile::Permissions permissions() const { if (info) return info->permissions(); return 0; }
+ inline bool isReadable() const { return ((permissions() & QFile::ReadUser) != 0); }
+ inline bool isWritable() const { return ((permissions() & QFile::WriteUser) != 0); }
+ inline bool isExecutable() const { return ((permissions() & QFile::ExeUser) != 0); }
+ inline bool isDir() const {
+ if (info)
+ return info->isDir();
+ if (children.count() > 0)
+ return true;
+ return false;
+ }
+ inline bool isFile() const { if (info) return info->isFile(); return true; }
+ inline bool isSystem() const { if (info) return info->isSystem(); return true; }
+ inline bool isHidden() const { if (info) return info->isHidden(); return false; }
+ inline bool isSymLink() const { if (info) return info->isSymLink(); return false; }
+ inline bool caseSensitive() const { if (info) return info->isCaseSensitive(); return false; }
+ inline QIcon icon() const { if (info) return info->icon; return QIcon(); }
+
+ inline bool operator <(const QFileSystemNode &node) const {
+ if (caseSensitive() || node.caseSensitive())
+ return fileName < node.fileName;
+ return QString::compare(fileName, node.fileName, Qt::CaseInsensitive) < 0;
+ }
+ inline bool operator >(const QString &name) const {
+ if (caseSensitive())
+ return fileName > name;
+ return QString::compare(fileName, name, Qt::CaseInsensitive) > 0;
+ }
+ inline bool operator <(const QString &name) const {
+ if (caseSensitive())
+ return fileName < name;
+ return QString::compare(fileName, name, Qt::CaseInsensitive) < 0;
+ }
+ inline bool operator !=(const QExtendedInformation &fileInfo) const {
+ return !operator==(fileInfo);
+ }
+ bool operator ==(const QString &name) const {
+ if (caseSensitive())
+ return fileName == name;
+ return QString::compare(fileName, name, Qt::CaseInsensitive) == 0;
+ }
+ bool operator ==(const QExtendedInformation &fileInfo) const {
+ return info && (*info == fileInfo);
+ }
+
+ inline bool hasInformation() const { return info != 0; }
+
+ void populate(const QExtendedInformation &fileInfo) {
+ if (!info)
+ info = new QExtendedInformation(fileInfo.fileInfo());
+ (*info) = fileInfo;
+ }
+
+ // children shouldn't normally be accessed directly, use node()
+ inline int visibleLocation(QString childName) {
+ return visibleChildren.indexOf(childName);
+ }
+ void updateIcon(QFileIconProvider *iconProvider, const QString &path) {
+ if (info)
+ info->icon = iconProvider->icon(QFileInfo(path));
+ QHash<QString, QFileSystemNode *>::const_iterator iterator;
+ for(iterator = children.constBegin() ; iterator != children.constEnd() ; ++iterator) {
+ //On windows the root (My computer) has no path so we don't want to add a / for nothing (e.g. /C:/)
+ if (!path.isEmpty()) {
+ if (path.endsWith(QLatin1Char('/')))
+ iterator.value()->updateIcon(iconProvider, path + iterator.value()->fileName);
+ else
+ iterator.value()->updateIcon(iconProvider, path + QLatin1Char('/') + iterator.value()->fileName);
+ } else
+ iterator.value()->updateIcon(iconProvider, iterator.value()->fileName);
+ }
+ }
+
+ void retranslateStrings(QFileIconProvider *iconProvider, const QString &path) {
+ if (info)
+ info->displayType = iconProvider->type(QFileInfo(path));
+ QHash<QString, QFileSystemNode *>::const_iterator iterator;
+ for(iterator = children.constBegin() ; iterator != children.constEnd() ; ++iterator) {
+ //On windows the root (My computer) has no path so we don't want to add a / for nothing (e.g. /C:/)
+ if (!path.isEmpty()) {
+ if (path.endsWith(QLatin1Char('/')))
+ iterator.value()->retranslateStrings(iconProvider, path + iterator.value()->fileName);
+ else
+ iterator.value()->retranslateStrings(iconProvider, path + QLatin1Char('/') + iterator.value()->fileName);
+ } else
+ iterator.value()->retranslateStrings(iconProvider, iterator.value()->fileName);
+ }
+ }
+
+ bool populatedChildren;
+ bool isVisible;
+ QHash<QString,QFileSystemNode *> children;
+ QList<QString> visibleChildren;
+ int dirtyChildrenIndex;
+ QFileSystemNode *parent;
+
+
+ QExtendedInformation *info;
+
+ };
+
+ QFileSystemModelPrivate() :
+ forceSort(true),
+ sortColumn(0),
+ sortOrder(Qt::AscendingOrder),
+ readOnly(true),
+ setRootPath(false),
+ filters(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs),
+ nameFilterDisables(true), // false on windows, true on mac and unix
+ disableRecursiveSort(false)
+ {
+ delayedSortTimer.setSingleShot(true);
+ }
+
+ void init();
+ /*
+ \internal
+
+ Return true if index which is owned by node is hidden by the filter.
+ */
+ inline bool isHiddenByFilter(QFileSystemNode *indexNode, const QModelIndex &index) const
+ {
+ return (indexNode != &root && !index.isValid());
+ }
+ QFileSystemNode *node(const QModelIndex &index) const;
+ QFileSystemNode *node(const QString &path, bool fetch = true) const;
+ inline QModelIndex index(const QString &path) { return index(node(path)); }
+ QModelIndex index(const QFileSystemNode *node) const;
+ bool filtersAcceptsNode(const QFileSystemNode *node) const;
+ bool passNameFilters(const QFileSystemNode *node) const;
+ void removeNode(QFileSystemNode *parentNode, const QString &name);
+ QFileSystemNode* addNode(QFileSystemNode *parentNode, const QString &fileName, const QFileInfo &info);
+ void addVisibleFiles(QFileSystemNode *parentNode, const QStringList &newFiles);
+ void removeVisibleFile(QFileSystemNode *parentNode, int visibleLocation);
+ void sortChildren(int column, const QModelIndex &parent);
+
+ inline int translateVisibleLocation(QFileSystemNode *parent, int row) const {
+ if (sortOrder != Qt::AscendingOrder) {
+ if (parent->dirtyChildrenIndex == -1)
+ return parent->visibleChildren.count() - row - 1;
+
+ if (row < parent->dirtyChildrenIndex)
+ return parent->dirtyChildrenIndex - row - 1;
+ }
+
+ return row;
+ }
+
+ inline static QString myComputer() {
+ // ### TODO We should query the system to find out what the string should be
+ // XP == "My Computer",
+ // Vista == "Computer",
+ // OS X == "Computer" (sometime user generated) "Benjamin's PowerBook G4"
+#ifdef Q_OS_WIN
+ return QFileSystemModel::tr("My Computer");
+#else
+ return QFileSystemModel::tr("Computer");
+#endif
+ }
+
+ inline void delayedSort() {
+ if (!delayedSortTimer.isActive())
+ delayedSortTimer.start(0);
+ }
+
+ static bool caseInsensitiveLessThan(const QString &s1, const QString &s2)
+ {
+ return QString::compare(s1, s2, Qt::CaseInsensitive) < 0;
+ }
+
+ static bool nodeCaseInsensitiveLessThan(const QFileSystemModelPrivate::QFileSystemNode &s1, const QFileSystemModelPrivate::QFileSystemNode &s2)
+ {
+ return QString::compare(s1.fileName, s2.fileName, Qt::CaseInsensitive) < 0;
+ }
+
+ 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);
+ QString type(const QModelIndex &index) const;
+ QString time(const QModelIndex &index) const;
+
+ void _q_directoryChanged(const QString &directory, const QStringList &list);
+ void _q_performDelayedSort();
+ void _q_fileSystemChanged(const QString &path, const QList<QPair<QString, QFileInfo> > &);
+ void _q_resolvedName(const QString &fileName, const QString &resolvedName);
+
+ static int naturalCompare(const QString &s1, const QString &s2, Qt::CaseSensitivity cs);
+
+ QDir rootDir;
+#ifndef QT_NO_FILESYSTEMWATCHER
+ QFileInfoGatherer fileInfoGatherer;
+#endif
+ QTimer delayedSortTimer;
+ bool forceSort;
+ int sortColumn;
+ Qt::SortOrder sortOrder;
+ bool readOnly;
+ bool setRootPath;
+ QDir::Filters filters;
+ QHash<const QFileSystemNode*, bool> bypassFilters;
+ bool nameFilterDisables;
+ //This flag is an optimization for the QFileDialog
+ //It enable a sort which is not recursive, it means
+ //we sort only what we see.
+ bool disableRecursiveSort;
+#ifndef QT_NO_REGEXP
+ QList<QRegExp> nameFilters;
+#endif
+ // ### Qt 5: resolvedSymLinks goes away
+ QHash<QString, QString> resolvedSymLinks;
+
+ QFileSystemNode root;
+
+ QBasicTimer fetchingTimer;
+ struct Fetching {
+ QString dir;
+ QString file;
+ const QFileSystemNode *node;
+ };
+ QList<Fetching> toFetch;
+
+};
+#endif // QT_NO_FILESYSTEMMODEL
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/widgets/dialogs/qfontdialog.cpp b/src/widgets/dialogs/qfontdialog.cpp
new file mode 100644
index 0000000000..b58021d877
--- /dev/null
+++ b/src/widgets/dialogs/qfontdialog.cpp
@@ -0,0 +1,1077 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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 "qwindowdefs.h"
+
+#ifndef QT_NO_FONTDIALOG
+
+#include "qfontdialog.h"
+#include "qfontdialog_p.h"
+
+#include <qapplication.h>
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qevent.h>
+#include <qfontdatabase.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include <qstyle.h>
+#include <qdialogbuttonbox.h>
+#include <qheaderview.h>
+#include <qlistview.h>
+#include <qstringlistmodel.h>
+#include <qvalidator.h>
+#include <private/qdialog_p.h>
+#include <private/qfont_p.h>
+
+#if defined(Q_WS_S60)
+#include <QtGui/qdesktopwidget.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QFontListView : public QListView
+{
+ Q_OBJECT
+public:
+ QFontListView(QWidget *parent);
+ inline QStringListModel *model() const {
+ return static_cast<QStringListModel *>(QListView::model());
+ }
+ inline void setCurrentItem(int item) {
+ QListView::setCurrentIndex(static_cast<QAbstractListModel*>(model())->index(item));
+ }
+ inline int currentItem() const {
+ return QListView::currentIndex().row();
+ }
+ inline int count() const {
+ return model()->rowCount();
+ }
+ inline QString currentText() const {
+ int row = QListView::currentIndex().row();
+ return row < 0 ? QString() : model()->stringList().at(row);
+ }
+ void currentChanged(const QModelIndex &current, const QModelIndex &previous) {
+ QListView::currentChanged(current, previous);
+ if (current.isValid())
+ emit highlighted(current.row());
+ }
+ QString text(int i) const {
+ return model()->stringList().at(i);
+ }
+signals:
+ void highlighted(int);
+};
+
+QFontListView::QFontListView(QWidget *parent)
+ : QListView(parent)
+{
+ setModel(new QStringListModel(parent));
+ setEditTriggers(NoEditTriggers);
+}
+
+static const Qt::WindowFlags DefaultWindowFlags =
+ Qt::Dialog | Qt::WindowSystemMenuHint;
+
+/*!
+ \class QFontDialog
+ \ingroup standard-dialogs
+
+ \brief The QFontDialog class provides a dialog widget for selecting a font.
+
+ A font dialog is created through one of the static getFont()
+ functions.
+
+ Examples:
+
+ \snippet doc/src/snippets/code/src_gui_dialogs_qfontdialog.cpp 0
+
+ The dialog can also be used to set a widget's font directly:
+ \snippet doc/src/snippets/code/src_gui_dialogs_qfontdialog.cpp 1
+ If the user clicks OK the font they chose will be used for myWidget,
+ and if they click Cancel the original font is used.
+
+ \image plastique-fontdialog.png A font dialog in the Plastique widget style.
+
+ \sa QFont, QFontInfo, QFontMetrics, QColorDialog, QFileDialog, QPrintDialog,
+ {Standard Dialogs Example}
+*/
+
+/*!
+ \since 4.5
+
+ Constructs a standard font dialog.
+
+ Use setCurrentFont() to set the initial font attributes.
+
+ The \a parent parameter is passed to the QDialog constructor.
+
+ \sa getFont()
+*/
+QFontDialog::QFontDialog(QWidget *parent)
+ : QDialog(*new QFontDialogPrivate, parent, DefaultWindowFlags)
+{
+ Q_D(QFontDialog);
+ d->init();
+}
+
+/*!
+ \since 4.5
+
+ Constructs a standard font dialog with the given \a parent and specified
+ \a initial color.
+*/
+QFontDialog::QFontDialog(const QFont &initial, QWidget *parent)
+ : QDialog(*new QFontDialogPrivate, parent, DefaultWindowFlags)
+{
+ Q_D(QFontDialog);
+ d->init();
+ setCurrentFont(initial);
+}
+
+void QFontDialogPrivate::init()
+{
+ Q_Q(QFontDialog);
+
+#ifdef Q_WS_MAC
+ nativeDialogInUse = false;
+ delegate = 0;
+#endif
+
+ q->setSizeGripEnabled(true);
+ q->setWindowTitle(QFontDialog::tr("Select Font"));
+
+ // grid
+ familyEdit = new QLineEdit(q);
+ familyEdit->setReadOnly(true);
+ familyList = new QFontListView(q);
+ familyEdit->setFocusProxy(familyList);
+
+ familyAccel = new QLabel(q);
+#ifndef QT_NO_SHORTCUT
+ familyAccel->setBuddy(familyList);
+#endif
+ familyAccel->setIndent(2);
+
+ styleEdit = new QLineEdit(q);
+ styleEdit->setReadOnly(true);
+ styleList = new QFontListView(q);
+ styleEdit->setFocusProxy(styleList);
+
+ styleAccel = new QLabel(q);
+#ifndef QT_NO_SHORTCUT
+ styleAccel->setBuddy(styleList);
+#endif
+ styleAccel->setIndent(2);
+
+ sizeEdit = new QLineEdit(q);
+ sizeEdit->setFocusPolicy(Qt::ClickFocus);
+ QIntValidator *validator = new QIntValidator(1, 512, q);
+ sizeEdit->setValidator(validator);
+ sizeList = new QFontListView(q);
+
+ sizeAccel = new QLabel(q);
+#ifndef QT_NO_SHORTCUT
+ sizeAccel->setBuddy(sizeEdit);
+#endif
+ sizeAccel->setIndent(2);
+
+ // effects box
+ effects = new QGroupBox(q);
+ QVBoxLayout *vbox = new QVBoxLayout(effects);
+ strikeout = new QCheckBox(effects);
+ vbox->addWidget(strikeout);
+ underline = new QCheckBox(effects);
+ vbox->addWidget(underline);
+
+ sample = new QGroupBox(q);
+ QHBoxLayout *hbox = new QHBoxLayout(sample);
+ sampleEdit = new QLineEdit(sample);
+ sampleEdit->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored));
+ sampleEdit->setAlignment(Qt::AlignCenter);
+ // Note that the sample text is *not* translated with tr(), as the
+ // characters used depend on the charset encoding.
+ sampleEdit->setText(QLatin1String("AaBbYyZz"));
+ hbox->addWidget(sampleEdit);
+
+ writingSystemCombo = new QComboBox(q);
+
+ writingSystemAccel = new QLabel(q);
+#ifndef QT_NO_SHORTCUT
+ writingSystemAccel->setBuddy(writingSystemCombo);
+#endif
+ writingSystemAccel->setIndent(2);
+
+ size = 0;
+ smoothScalable = false;
+
+ QObject::connect(writingSystemCombo, SIGNAL(activated(int)), q, SLOT(_q_writingSystemHighlighted(int)));
+ QObject::connect(familyList, SIGNAL(highlighted(int)), q, SLOT(_q_familyHighlighted(int)));
+ QObject::connect(styleList, SIGNAL(highlighted(int)), q, SLOT(_q_styleHighlighted(int)));
+ QObject::connect(sizeList, SIGNAL(highlighted(int)), q, SLOT(_q_sizeHighlighted(int)));
+ QObject::connect(sizeEdit, SIGNAL(textChanged(QString)), q, SLOT(_q_sizeChanged(QString)));
+
+ QObject::connect(strikeout, SIGNAL(clicked()), q, SLOT(_q_updateSample()));
+ QObject::connect(underline, SIGNAL(clicked()), q, SLOT(_q_updateSample()));
+
+ for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {
+ QFontDatabase::WritingSystem ws = QFontDatabase::WritingSystem(i);
+ QString writingSystemName = QFontDatabase::writingSystemName(ws);
+ if (writingSystemName.isEmpty())
+ break;
+ writingSystemCombo->addItem(writingSystemName);
+ }
+
+ updateFamilies();
+ if (familyList->count() != 0)
+ familyList->setCurrentItem(0);
+
+ // grid layout
+ QGridLayout *mainGrid = new QGridLayout(q);
+
+ int spacing = mainGrid->spacing();
+ if (spacing >= 0) { // uniform spacing
+ mainGrid->setSpacing(0);
+
+ mainGrid->setColumnMinimumWidth(1, spacing);
+ mainGrid->setColumnMinimumWidth(3, spacing);
+
+ int margin = 0;
+ mainGrid->getContentsMargins(0, 0, 0, &margin);
+
+ mainGrid->setRowMinimumHeight(3, margin);
+ mainGrid->setRowMinimumHeight(6, 2);
+ mainGrid->setRowMinimumHeight(8, margin);
+ }
+
+ mainGrid->addWidget(familyAccel, 0, 0);
+ mainGrid->addWidget(familyEdit, 1, 0);
+ mainGrid->addWidget(familyList, 2, 0);
+
+ mainGrid->addWidget(styleAccel, 0, 2);
+ mainGrid->addWidget(styleEdit, 1, 2);
+ mainGrid->addWidget(styleList, 2, 2);
+
+ mainGrid->addWidget(sizeAccel, 0, 4);
+ mainGrid->addWidget(sizeEdit, 1, 4);
+ mainGrid->addWidget(sizeList, 2, 4);
+
+ mainGrid->setColumnStretch(0, 38);
+ mainGrid->setColumnStretch(2, 24);
+ mainGrid->setColumnStretch(4, 10);
+
+ mainGrid->addWidget(effects, 4, 0);
+
+ mainGrid->addWidget(sample, 4, 2, 4, 3);
+
+ mainGrid->addWidget(writingSystemAccel, 5, 0);
+ mainGrid->addWidget(writingSystemCombo, 7, 0);
+
+ buttonBox = new QDialogButtonBox(q);
+ mainGrid->addWidget(buttonBox, 9, 0, 1, 5);
+
+ QPushButton *button
+ = static_cast<QPushButton *>(buttonBox->addButton(QDialogButtonBox::Ok));
+ QObject::connect(buttonBox, SIGNAL(accepted()), q, SLOT(accept()));
+ button->setDefault(true);
+
+ buttonBox->addButton(QDialogButtonBox::Cancel);
+ QObject::connect(buttonBox, SIGNAL(rejected()), q, SLOT(reject()));
+
+#if defined(Q_WS_WINCE)
+ q->resize(180, 120);
+#elif defined(Q_WS_S60)
+ q->resize(QApplication::desktop()->availableGeometry(QCursor::pos()).size());
+#else
+ q->resize(500, 360);
+#endif // Q_WS_WINCE
+
+ sizeEdit->installEventFilter(q);
+ familyList->installEventFilter(q);
+ styleList->installEventFilter(q);
+ sizeList->installEventFilter(q);
+
+ familyList->setFocus();
+ retranslateStrings();
+}
+
+/*!
+ \internal
+ Destroys the font dialog and frees up its storage.
+*/
+
+QFontDialog::~QFontDialog()
+{
+#ifdef Q_WS_MAC
+ Q_D(QFontDialog);
+ if (d->delegate) {
+ d->closeCocoaFontPanel();
+ return;
+ }
+#endif
+}
+
+/*!
+ Executes a modal font dialog and returns a font.
+
+ If the user clicks \gui OK, the selected font is returned. If the user
+ clicks \gui Cancel, the \a initial font is returned.
+
+ The dialog is constructed with the given \a parent and the options specified
+ in \a options. \a title is shown as the window title of the dialog and \a
+ initial is the initially selected font. If the \a ok parameter is not-null,
+ the value it refers to is set to true if the user clicks \gui OK, and set to
+ false if the user clicks \gui Cancel.
+
+ Examples:
+ \snippet doc/src/snippets/code/src_gui_dialogs_qfontdialog.cpp 2
+
+ The dialog can also be used to set a widget's font directly:
+ \snippet doc/src/snippets/code/src_gui_dialogs_qfontdialog.cpp 3
+ In this example, if the user clicks OK the font they chose will be
+ used, and if they click Cancel the original font is used.
+
+ \warning Do not delete \a parent during the execution of the dialog.
+ If you want to do this, you should create the dialog
+ yourself using one of the QFontDialog constructors.
+*/
+QFont QFontDialog::getFont(bool *ok, const QFont &initial, QWidget *parent, const QString &title,
+ FontDialogOptions options)
+{
+ return QFontDialogPrivate::getFont(ok, initial, parent, title, options);
+}
+
+/*!
+ \overload
+ \since 4.5
+*/
+QFont QFontDialog::getFont(bool *ok, const QFont &initial, QWidget *parent, const QString &title)
+{
+ return QFontDialogPrivate::getFont(ok, initial, parent, title, 0);
+}
+
+/*!
+ \overload
+*/
+QFont QFontDialog::getFont(bool *ok, const QFont &initial, QWidget *parent)
+{
+ return QFontDialogPrivate::getFont(ok, initial, parent, QString(), 0);
+}
+
+/*!
+ \overload
+
+ Executes a modal font dialog and returns a font.
+
+ If the user clicks \gui OK, the selected font is returned. If the user
+ clicks \gui Cancel, the Qt default font is returned.
+
+ The dialog is constructed with the given \a parent.
+ If the \a ok parameter is not-null, the value it refers to is set
+ to true if the user clicks \gui OK, and false if the user clicks
+ \gui Cancel.
+
+ Example:
+ \snippet doc/src/snippets/code/src_gui_dialogs_qfontdialog.cpp 4
+
+ \warning Do not delete \a parent during the execution of the dialog.
+ If you want to do this, you should create the dialog
+ yourself using one of the QFontDialog constructors.
+*/
+QFont QFontDialog::getFont(bool *ok, QWidget *parent)
+{
+ QFont initial;
+ return QFontDialogPrivate::getFont(ok, initial, parent, QString(), 0);
+}
+
+QFont QFontDialogPrivate::getFont(bool *ok, const QFont &initial, QWidget *parent,
+ const QString &title, QFontDialog::FontDialogOptions options)
+{
+ QFontDialog dlg(parent);
+ dlg.setOptions(options);
+ dlg.setCurrentFont(initial);
+ if (!title.isEmpty())
+ dlg.setWindowTitle(title);
+
+ int ret = (dlg.exec() || (options & QFontDialog::NoButtons));
+ if (ok)
+ *ok = !!ret;
+ if (ret) {
+ return dlg.selectedFont();
+ } else {
+ return initial;
+ }
+}
+
+/*!
+ \internal
+ An event filter to make the Up, Down, PageUp and PageDown keys work
+ correctly in the line edits. The source of the event is the object
+ \a o and the event is \a e.
+*/
+
+bool QFontDialog::eventFilter(QObject *o , QEvent *e)
+{
+ Q_D(QFontDialog);
+ if (e->type() == QEvent::KeyPress) {
+ QKeyEvent *k = (QKeyEvent *)e;
+ if (o == d->sizeEdit &&
+ (k->key() == Qt::Key_Up ||
+ k->key() == Qt::Key_Down ||
+ k->key() == Qt::Key_PageUp ||
+ k->key() == Qt::Key_PageDown)) {
+
+ int ci = d->sizeList->currentItem();
+ (void)QApplication::sendEvent(d->sizeList, k);
+
+ if (ci != d->sizeList->currentItem()
+ && style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, 0, this))
+ d->sizeEdit->selectAll();
+ return true;
+ } else if ((o == d->familyList || o == d->styleList) &&
+ (k->key() == Qt::Key_Return || k->key() == Qt::Key_Enter)) {
+ k->accept();
+ accept();
+ return true;
+ }
+ } else if (e->type() == QEvent::FocusIn
+ && style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, 0, this)) {
+ if (o == d->familyList)
+ d->familyEdit->selectAll();
+ else if (o == d->styleList)
+ d->styleEdit->selectAll();
+ else if (o == d->sizeList)
+ d->sizeEdit->selectAll();
+ } else if (e->type() == QEvent::MouseButtonPress && o == d->sizeList) {
+ d->sizeEdit->setFocus();
+ }
+ return QDialog::eventFilter(o, e);
+}
+
+/*
+ Updates the contents of the "font family" list box. This
+ function can be reimplemented if you have special requirements.
+*/
+
+void QFontDialogPrivate::updateFamilies()
+{
+ Q_Q(QFontDialog);
+
+ enum match_t { MATCH_NONE = 0, MATCH_LAST_RESORT = 1, MATCH_APP = 2, MATCH_FAMILY = 3 };
+
+ QStringList familyNames = fdb.families(writingSystem);
+
+ familyList->model()->setStringList(familyNames);
+
+ QString foundryName1, familyName1, foundryName2, familyName2;
+ int bestFamilyMatch = -1;
+ match_t bestFamilyType = MATCH_NONE;
+
+ QFont f;
+
+ // ##### do the right thing for a list of family names in the font.
+ QFontDatabase::parseFontName(family, foundryName1, familyName1);
+
+ QStringList::const_iterator it = familyNames.constBegin();
+ int i = 0;
+ for(; it != familyNames.constEnd(); ++it, ++i) {
+ QFontDatabase::parseFontName(*it, foundryName2, familyName2);
+
+ //try to match...
+ if (familyName1 == familyName2) {
+ bestFamilyType = MATCH_FAMILY;
+ if (foundryName1 == foundryName2) {
+ bestFamilyMatch = i;
+ break;
+ }
+ if (bestFamilyMatch < MATCH_FAMILY)
+ bestFamilyMatch = i;
+ }
+
+ //and try some fall backs
+ match_t type = MATCH_NONE;
+ if (bestFamilyType <= MATCH_NONE && familyName2 == f.lastResortFamily())
+ type = MATCH_LAST_RESORT;
+ if (bestFamilyType <= MATCH_LAST_RESORT && familyName2 == f.family())
+ type = MATCH_APP;
+ // ### add fallback for writingSystem
+ if (type != MATCH_NONE) {
+ bestFamilyType = type;
+ bestFamilyMatch = i;
+ }
+ }
+
+ if (i != -1 && bestFamilyType != MATCH_NONE)
+ familyList->setCurrentItem(bestFamilyMatch);
+ else
+ familyList->setCurrentItem(0);
+ familyEdit->setText(familyList->currentText());
+ if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, 0, q)
+ && familyList->hasFocus())
+ familyEdit->selectAll();
+
+ updateStyles();
+}
+
+/*
+ Updates the contents of the "font style" list box. This
+ function can be reimplemented if you have special requirements.
+*/
+void QFontDialogPrivate::updateStyles()
+{
+ Q_Q(QFontDialog);
+ QStringList styles = fdb.styles(familyList->currentText());
+ styleList->model()->setStringList(styles);
+
+ if (styles.isEmpty()) {
+ styleEdit->clear();
+ smoothScalable = false;
+ } else {
+ if (!style.isEmpty()) {
+ bool found = false;
+ bool first = true;
+ QString cstyle = style;
+
+ redo:
+ for (int i = 0; i < (int)styleList->count(); i++) {
+ if (cstyle == styleList->text(i)) {
+ styleList->setCurrentItem(i);
+ found = true;
+ break;
+ }
+ }
+ if (!found && first) {
+ if (cstyle.contains(QLatin1String("Italic"))) {
+ cstyle.replace(QLatin1String("Italic"), QLatin1String("Oblique"));
+ first = false;
+ goto redo;
+ } else if (cstyle.contains(QLatin1String("Oblique"))) {
+ cstyle.replace(QLatin1String("Oblique"), QLatin1String("Italic"));
+ first = false;
+ goto redo;
+ }
+ }
+ if (!found)
+ styleList->setCurrentItem(0);
+ } else {
+ styleList->setCurrentItem(0);
+ }
+
+ styleEdit->setText(styleList->currentText());
+ if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, 0, q)
+ && styleList->hasFocus())
+ styleEdit->selectAll();
+
+ smoothScalable = fdb.isSmoothlyScalable(familyList->currentText(), styleList->currentText());
+ }
+
+ updateSizes();
+}
+
+/*!
+ \internal
+ Updates the contents of the "font size" list box. This
+ function can be reimplemented if you have special requirements.
+*/
+
+void QFontDialogPrivate::updateSizes()
+{
+ Q_Q(QFontDialog);
+
+ if (!familyList->currentText().isEmpty()) {
+ QList<int> sizes = fdb.pointSizes(familyList->currentText(), styleList->currentText());
+
+ int i = 0;
+ int current = -1;
+ QStringList str_sizes;
+ for(QList<int>::const_iterator it = sizes.constBegin(); it != sizes.constEnd(); ++it) {
+ str_sizes.append(QString::number(*it));
+ if (current == -1 && *it >= size)
+ current = i;
+ ++i;
+ }
+ sizeList->model()->setStringList(str_sizes);
+ if (current == -1) {
+ // we request a size bigger than the ones in the list, select the biggest one
+ current = sizeList->count() - 1;
+ }
+ sizeList->setCurrentItem(current);
+
+ sizeEdit->blockSignals(true);
+ sizeEdit->setText((smoothScalable ? QString::number(size) : sizeList->currentText()));
+ if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, 0, q)
+ && sizeList->hasFocus())
+ sizeEdit->selectAll();
+ sizeEdit->blockSignals(false);
+ } else {
+ sizeEdit->clear();
+ }
+
+ _q_updateSample();
+}
+
+void QFontDialogPrivate::_q_updateSample()
+{
+ // compute new font
+ int pSize = sizeEdit->text().toInt();
+ QFont newFont(fdb.font(familyList->currentText(), style, pSize));
+