# HG changeset patch
# User Torsten Lilge
# Date 1701716132 -3600
# Node ID dd5ece3664ed391db0f4e439af7d43ff4cc1e297
# Parent 97e55a21cd20b57dfd149f5b280aec44ce8d8b66
update Qt and Qsci sources for scanning text for translation
* libgui/languages/build_ts/octave-qsci/*: updated source files
from Qscintilla
* libgui/languages/build_ts/octave-qt/*.: updated source files
from Qt
* libgui/languages/build_ts/update_external_sources: script for
updating above mentioned source files from user defined directories
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qsciabstractapis.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qsciabstractapis.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qsciabstractapis.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This module defines interface to the QsciAbstractAPIs class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qsciapis.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qsciapis.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qsciapis.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This module defines interface to the QsciAPIs class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscicommand.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscicommand.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscicommand.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciCommand class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscicommandset.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscicommandset.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscicommandset.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciCommandSet class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscidocument.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscidocument.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscidocument.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciDocument class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qsciglobal.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qsciglobal.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qsciglobal.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This module defines various things common to all of the Scintilla Qt port.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
@@ -24,8 +24,14 @@
#include
-#define QSCINTILLA_VERSION 0x020b04
-#define QSCINTILLA_VERSION_STR "2.11.4"
+#define QSCINTILLA_VERSION 0x020e00
+#define QSCINTILLA_VERSION_STR "2.14.0"
+
+
+// We only support Qt v5.11 and later.
+#if QT_VERSION < 0x050b00
+#error "Qt v5.11.0 or later is required"
+#endif
// Define QSCINTILLA_MAKE_DLL to create a QScintilla shared library, or
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexer.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexer.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexer.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexer class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
@@ -318,6 +318,12 @@
//!
virtual bool writeProperties(QSettings &qs,const QString &prefix) const;
+ //! \internal Convert a QString to encoded bytes.
+ QByteArray textAsBytes(const QString &text) const;
+
+ //! \internal Convert encoded bytes to a QString.
+ QString bytesAsText(const char *bytes, int size) const;
+
private:
struct StyleData {
QFont font;
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexeravs.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexeravs.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexeravs.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerAVS class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexerbash.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerbash.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerbash.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerBash class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexerbatch.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerbatch.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerbatch.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerBatch class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexercmake.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexercmake.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexercmake.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerCMake class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexercoffeescript.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexercoffeescript.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexercoffeescript.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerCoffeeScript class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexercpp.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexercpp.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexercpp.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerCPP class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexercsharp.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexercsharp.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexercsharp.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerCSharp class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexercss.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexercss.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexercss.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerCSS class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexercustom.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexercustom.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexercustom.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerCustom class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexerd.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerd.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerd.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerD class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexerdiff.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerdiff.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerdiff.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerDiff class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexeredifact.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexeredifact.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexeredifact.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerEDIFACT class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexerfortran.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerfortran.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerfortran.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerFortran class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexerfortran77.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerfortran77.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerfortran77.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerFortran77 class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexerhtml.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerhtml.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerhtml.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerHTML class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexeridl.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexeridl.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexeridl.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerIDL class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexerjava.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerjava.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerjava.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerJava class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexerjavascript.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerjavascript.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerjavascript.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerJavaScript class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexerjson.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerjson.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerjson.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerJSON class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexerlua.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerlua.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerlua.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerLua class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexermakefile.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexermakefile.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexermakefile.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerMakefile class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexermarkdown.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexermarkdown.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexermarkdown.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerMarkdown class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexermatlab.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexermatlab.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexermatlab.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerMatlab class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexeroctave.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexeroctave.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexeroctave.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerOctave class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexerpascal.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerpascal.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerpascal.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerPascal class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexerperl.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerperl.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerperl.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerPerl class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexerpo.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerpo.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerpo.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerPO class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexerpostscript.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerpostscript.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerpostscript.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerPostScript class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexerpov.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerpov.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerpov.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerPOV class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexerproperties.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerproperties.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerproperties.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerProperties class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexerpython.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerpython.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerpython.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerPython class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexerruby.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerruby.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerruby.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerRuby class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexerspice.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerspice.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerspice.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerSpice class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexersql.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexersql.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexersql.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerSQL class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexertcl.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexertcl.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexertcl.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerTCL class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexertex.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexertex.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexertex.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerTeX class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexerverilog.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerverilog.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerverilog.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerVerilog class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexervhdl.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexervhdl.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexervhdl.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerVHDL class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexerxml.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerxml.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexerxml.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerXML class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscilexeryaml.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscilexeryaml.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscilexeryaml.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciLexerYAML class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscimacro.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscimacro.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscimacro.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This defines the interface to the QsciMacro class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qsciprinter.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qsciprinter.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qsciprinter.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This module defines interface to the QsciPrinter class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
@@ -64,7 +64,7 @@
//! area of the page that will be used to draw the text. This should be
//! modified if it is necessary to reserve space for any customised text or
//! graphics. By default the area is relative to the printable area of the
- //! page. Use QPrinter::setFullPage() because calling printRange() if you
+ //! page. Use QPrinter::setFullPage() before calling printRange() if you
//! want to try and print over the whole page. \a pagenr is the number of
//! the page. The first page is numbered 1.
virtual void formatPage(QPainter &painter, bool drawing, QRect &area,
@@ -81,11 +81,19 @@
//! \sa magnification()
virtual void setMagnification(int magnification);
- //! Print a range of lines from the Scintilla instance \a qsb. \a from is
- //! the first line to print and a negative value signifies the first line
- //! of text. \a to is the last line to print and a negative value
- //! signifies the last line of text. true is returned if there was no
- //! error.
+ //! Print a range of lines from the Scintilla instance \a qsb using the
+ //! supplied QPainter \a painter. \a from is the first line to print and a
+ //! negative value signifies the first line of text. \a to is the last
+ //! line to print and a negative value signifies the last line of text.
+ //! true is returned if there was no error.
+ virtual int printRange(QsciScintillaBase *qsb, QPainter &painter,
+ int from = -1, int to = -1);
+
+ //! Print a range of lines from the Scintilla instance \a qsb using a
+ //! default QPainter. \a from is the first line to print and a negative
+ //! value signifies the first line of text. \a to is the last line to
+ //! print and a negative value signifies the last line of text. true is
+ //! returned if there was no error.
virtual int printRange(QsciScintillaBase *qsb, int from = -1, int to = -1);
//! Return the line wrap mode used when printing. The default is
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qsciscintilla.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qsciscintilla.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qsciscintilla.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,7 +1,7 @@
// This module defines the "official" high-level API of the Qt port of
// Scintilla.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
@@ -2242,7 +2242,7 @@
QString wordAtPosition(int position) const;
- ScintillaBytes styleText(const QList &styled_text,
+ QByteArray styleText(const QList &styled_text,
char **styles, int style_offset = 0);
struct FindState
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qsciscintillabase.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qsciscintillabase.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qsciscintillabase.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This class defines the "official" low-level API.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
@@ -3845,16 +3845,15 @@
//! \internal This helps to work around some Scintilla bugs.
void setScrollBars();
- //! \internal Qt4, Qt5 portability.
- typedef QByteArray ScintillaBytes;
-
-#define ScintillaBytesConstData(b) (b).constData()
-
//! \internal Convert a QString to encoded bytes.
- ScintillaBytes textAsBytes(const QString &text) const;
+ QByteArray textAsBytes(const QString &text) const;
//! \internal Convert encoded bytes to a QString.
- QString bytesAsText(const char *bytes) const;
+ QString bytesAsText(const char *bytes, int size) const;
+
+ //! Give access to the text convertors.
+ friend class QsciAccessibleScintillaBase;
+ friend class QsciLexer;
//! \internal A helper for QsciScintilla::contextMenuEvent().
bool contextMenuNeeded(int x, int y) const;
@@ -3873,9 +3872,7 @@
int preeditPos;
int preeditNrBytes;
QString preeditString;
-#if QT_VERSION >= 0x050000
bool clickCausedFocus;
-#endif
void connectHorizontalScrollBar();
void connectVerticalScrollBar();
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscistyle.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscistyle.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscistyle.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This module defines interface to the QsciStyle class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/Qsci/qscistyledtext.h
--- a/libgui/languages/build_ts/octave-qsci/Qsci/qscistyledtext.h Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/Qsci/qscistyledtext.h Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This module defines interface to the QsciStyledText class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/qscilexer.cpp
--- a/libgui/languages/build_ts/octave-qsci/qscilexer.cpp Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/qscilexer.cpp Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This module implements the QsciLexer class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
@@ -367,7 +367,7 @@
if (description(i).isEmpty())
continue;
- key.sprintf("%s/%s/style%d/",prefix,language(),i);
+ key = QString("%1/%2/style%3/").arg(prefix).arg(language()).arg(i);
// Read the foreground colour.
full_key = key + "color";
@@ -454,7 +454,7 @@
}
// Read the properties.
- key.sprintf("%s/%s/properties/",prefix,language());
+ key = QString("%1/%2/properties/").arg(prefix).arg(language());
if (!readProperties(qs,key))
rc = false;
@@ -462,7 +462,7 @@
refreshProperties();
// Read the rest.
- key.sprintf("%s/%s/",prefix,language());
+ key = QString("%1/%2/").arg(prefix).arg(language());
// Read the default foreground colour.
full_key = key + "defaultcolor";
@@ -569,7 +569,7 @@
QColor c;
- key.sprintf("%s/%s/style%d/",prefix,language(),i);
+ key = QString("%1/%2/style%3/").arg(prefix).arg(language()).arg(i);
// Write the foreground colour.
c = color(i);
@@ -607,13 +607,13 @@
}
// Write the properties.
- key.sprintf("%s/%s/properties/",prefix,language());
+ key = QString("%1/%2/properties/").arg(prefix).arg(language());
if (!writeProperties(qs,key))
rc = false;
// Write the rest.
- key.sprintf("%s/%s/",prefix,language());
+ key = QString("%1/%2/").arg(prefix).arg(language());
// Write the default foreground colour.
num = (defColor.red() << 16) | (defColor.green() << 8) | defColor.blue();
@@ -729,3 +729,21 @@
emit paperChanged(c, QsciScintillaBase::STYLE_DEFAULT);
}
}
+
+
+// Encode a QString as bytes.
+QByteArray QsciLexer::textAsBytes(const QString &text) const
+{
+ Q_ASSERT(attached_editor);
+
+ return attached_editor->textAsBytes(text);
+}
+
+
+// Decode bytes as a QString.
+QString QsciLexer::bytesAsText(const char *bytes, int size) const
+{
+ Q_ASSERT(attached_editor);
+
+ return attached_editor->bytesAsText(bytes, size);
+}
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/qscilexerbash.cpp
--- a/libgui/languages/build_ts/octave-qsci/qscilexerbash.cpp Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/qscilexerbash.cpp Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This module implements the QsciLexerBash class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/qscilexerbatch.cpp
--- a/libgui/languages/build_ts/octave-qsci/qscilexerbatch.cpp Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/qscilexerbatch.cpp Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This module implements the QsciLexerBatch class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/qscilexercpp.cpp
--- a/libgui/languages/build_ts/octave-qsci/qscilexercpp.cpp Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/qscilexercpp.cpp Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This module implements the QsciLexerCPP class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/qscilexerdiff.cpp
--- a/libgui/languages/build_ts/octave-qsci/qscilexerdiff.cpp Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/qscilexerdiff.cpp Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This module implements the QsciLexerDiff class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/qscilexermatlab.cpp
--- a/libgui/languages/build_ts/octave-qsci/qscilexermatlab.cpp Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/qscilexermatlab.cpp Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This module implements the QsciLexerMatlab class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/qscilexeroctave.cpp
--- a/libgui/languages/build_ts/octave-qsci/qscilexeroctave.cpp Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/qscilexeroctave.cpp Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This module implements the QsciLexerOctave class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/qscilexerperl.cpp
--- a/libgui/languages/build_ts/octave-qsci/qscilexerperl.cpp Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/qscilexerperl.cpp Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This module implements the QsciLexerPerl class.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/qsciscintilla.cpp
--- a/libgui/languages/build_ts/octave-qsci/qsciscintilla.cpp Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/qsciscintilla.cpp Mon Dec 04 19:55:32 2023 +0100
@@ -2,7 +2,7 @@
// Scintilla. It is modelled on QTextEdit - a method of the same name should
// behave in the same way.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
@@ -390,8 +390,8 @@
ct = ct_entries.join("\n");
}
- ScintillaBytes ct_bytes = textAsBytes(ct);
- const char *cts = ScintillaBytesConstData(ct_bytes);
+ QByteArray ct_bytes = textAsBytes(ct);
+ const char *cts = ct_bytes.constData();
SendScintilla(SCI_CALLTIPSHOW, adjustedCallTipPosition(shift), cts);
@@ -470,7 +470,8 @@
if (ct_cursor > 0)
ct.prepend('\001');
- SendScintilla(SCI_CALLTIPSHOW, adjustedCallTipPosition(shift), ct.toLatin1().data());
+ SendScintilla(SCI_CALLTIPSHOW, adjustedCallTipPosition(shift),
+ textAsBytes(ct).constData());
}
@@ -673,8 +674,8 @@
return;
// Get the last word's raw data and length.
- ScintillaBytes s = textAsBytes(context.last());
- const char *last_data = ScintillaBytesConstData(s);
+ QByteArray s = textAsBytes(context.last());
+ const char *last_data = s.constData();
int last_len = s.length();
if (checkThresh && last_len < acThresh)
@@ -774,8 +775,8 @@
SendScintilla(SCI_AUTOCSETCHOOSESINGLE, choose_single);
SendScintilla(SCI_AUTOCSETSEPARATOR, acSeparator);
- ScintillaBytes wlist_s = textAsBytes(wlist.join(QChar(acSeparator)));
- SendScintilla(SCI_AUTOCSHOW, last_len, ScintillaBytesConstData(wlist_s));
+ SendScintilla(SCI_AUTOCSHOW, last_len,
+ textAsBytes(wlist.join(QChar(acSeparator))).constData());
}
@@ -1880,10 +1881,9 @@
SendScintilla(SCI_SETTARGETSTART, findState.startpos);
SendScintilla(SCI_SETTARGETEND, findState.endpos);
- ScintillaBytes s = textAsBytes(findState.expr);
-
- return SendScintilla(SCI_SEARCHINTARGET, s.length(),
- ScintillaBytesConstData(s));
+ QByteArray s = textAsBytes(findState.expr);
+
+ return SendScintilla(SCI_SEARCHINTARGET, s.length(), s.constData());
}
@@ -1900,8 +1900,7 @@
int cmd = (findState.flags & SCFIND_REGEXP) ? SCI_REPLACETARGETRE : SCI_REPLACETARGET;
- ScintillaBytes s = textAsBytes(replaceStr);
- long len = SendScintilla(cmd, -1, ScintillaBytesConstData(s));
+ long len = SendScintilla(cmd, -1, textAsBytes(replaceStr).constData());
// Reset the selection.
SendScintilla(SCI_SETSELECTIONSTART, start);
@@ -1911,7 +1910,10 @@
findState.endpos_orig += (len - orig_len);
if (findState.forward)
+ {
findState.startpos = start + len;
+ findState.endpos += (len - orig_len);
+ }
}
@@ -2180,8 +2182,8 @@
{
bool ro = ensureRW();
- ScintillaBytes s = textAsBytes(text);
- SendScintilla(SCI_APPENDTEXT, s.length(), ScintillaBytesConstData(s));
+ QByteArray s = textAsBytes(text);
+ SendScintilla(SCI_APPENDTEXT, s.length(), s.constData());
SendScintilla(SCI_EMPTYUNDOBUFFER);
@@ -2209,8 +2211,7 @@
bool ro = ensureRW();
SendScintilla(SCI_BEGINUNDOACTION);
- SendScintilla(SCI_INSERTTEXT, pos,
- ScintillaBytesConstData(textAsBytes(text)));
+ SendScintilla(SCI_INSERTTEXT, pos, textAsBytes(text).constData());
SendScintilla(SCI_ENDUNDOACTION);
setReadOnly(ro);
@@ -2305,7 +2306,7 @@
// Replace any selected text.
void QsciScintilla::replaceSelectedText(const QString &text)
{
- SendScintilla(SCI_REPLACESEL, ScintillaBytesConstData(textAsBytes(text)));
+ SendScintilla(SCI_REPLACESEL, textAsBytes(text).constData());
}
@@ -2315,11 +2316,12 @@
if (!selText)
return QString();
- char *buf = new char[SendScintilla(SCI_GETSELECTIONEND) - SendScintilla(SCI_GETSELECTIONSTART) + 1];
+ int size = SendScintilla(SCI_GETSELECTIONEND) - SendScintilla(SCI_GETSELECTIONSTART);
+ char *buf = new char[size + 1];
SendScintilla(SCI_GETSELTEXT, buf);
- QString qs = bytesAsText(buf);
+ QString qs = bytesAsText(buf, size);
delete[] buf;
return qs;
@@ -2329,12 +2331,14 @@
// Return the current text.
QString QsciScintilla::text() const
{
- int buflen = length() + 1;
- char *buf = new char[buflen];
-
- SendScintilla(SCI_GETTEXT, buflen, buf);
-
- QString qs = bytesAsText(buf);
+ int size = length();
+ char *buf = new char[size + 1];
+
+ // Note that the docs seem to be wrong and we need to ask for the length
+ // plus the '\0'.
+ SendScintilla(SCI_GETTEXT, size + 1, buf);
+
+ QString qs = bytesAsText(buf, size);
delete[] buf;
return qs;
@@ -2344,17 +2348,16 @@
// Return the text of a line.
QString QsciScintilla::text(int line) const
{
- int line_len = lineLength(line);
-
- if (line_len < 1)
+ int size = lineLength(line);
+
+ if (size < 1)
return QString();
- char *buf = new char[line_len + 1];
+ char *buf = new char[size];
SendScintilla(SCI_GETLINE, line, buf);
- buf[line_len] = '\0';
-
- QString qs = bytesAsText(buf);
+
+ QString qs = bytesAsText(buf, size);
delete[] buf;
return qs;
@@ -2364,9 +2367,10 @@
// Return the text between two positions.
QString QsciScintilla::text(int start, int end) const
{
- char *buf = new char[end - start + 1];
+ int size = end - start;
+ char *buf = new char[size + 1];
SendScintilla(SCI_GETTEXTRANGE, start, end, buf);
- QString text = bytesAsText(buf);
+ QString text = bytesAsText(buf, size);
delete[] buf;
return text;
@@ -2389,7 +2393,9 @@
{
bool ro = ensureRW();
- SendScintilla(SCI_SETTEXT, ScintillaBytesConstData(textAsBytes(text)));
+ SendScintilla(SCI_CLEARALL);
+ QByteArray bytes = textAsBytes(text);
+ SendScintilla(SCI_ADDTEXT, bytes.size(), bytes.constData());
SendScintilla(SCI_EMPTYUNDOBUFFER);
setReadOnly(ro);
@@ -2700,9 +2706,7 @@
{
int style_offset = SendScintilla(SCI_MARGINGETSTYLEOFFSET);
- SendScintilla(SCI_MARGINSETTEXT, line,
- ScintillaBytesConstData(textAsBytes(text)));
-
+ SendScintilla(SCI_MARGINSETTEXT, line, textAsBytes(text).constData());
SendScintilla(SCI_MARGINSETSTYLE, line, style - style_offset);
}
@@ -2729,11 +2733,10 @@
void QsciScintilla::setMarginText(int line, const QList &text)
{
char *styles;
- ScintillaBytes styled_text = styleText(text, &styles,
+ QByteArray styled_text = styleText(text, &styles,
SendScintilla(SCI_MARGINGETSTYLEOFFSET));
- SendScintilla(SCI_MARGINSETTEXT, line,
- ScintillaBytesConstData(styled_text));
+ SendScintilla(SCI_MARGINSETTEXT, line, styled_text.constData());
SendScintilla(SCI_MARGINSETSTYLES, line, styles);
delete[] styles;
@@ -2801,7 +2804,7 @@
void QsciScintilla::setMarginWidth(int margin, const QString &s)
{
int width = SendScintilla(SCI_TEXTWIDTH, STYLE_LINENUMBER,
- ScintillaBytesConstData(textAsBytes(s)));
+ textAsBytes(s).constData());
setMarginWidth(margin, width);
}
@@ -4052,8 +4055,8 @@
SendScintilla(SCI_AUTOCSETSEPARATOR, userSeparator);
- ScintillaBytes s = textAsBytes(list.join(QChar(userSeparator)));
- SendScintilla(SCI_USERLISTSHOW, id, ScintillaBytesConstData(s));
+ SendScintilla(SCI_USERLISTSHOW, id,
+ textAsBytes(list.join(QChar(userSeparator))).constData());
}
@@ -4223,9 +4226,7 @@
{
int style_offset = SendScintilla(SCI_ANNOTATIONGETSTYLEOFFSET);
- ScintillaBytes s = textAsBytes(text);
-
- SendScintilla(SCI_ANNOTATIONSETTEXT, line, ScintillaBytesConstData(s));
+ SendScintilla(SCI_ANNOTATIONSETTEXT, line, textAsBytes(text).constData());
SendScintilla(SCI_ANNOTATIONSETSTYLE, line, style - style_offset);
setScrollBars();
@@ -4254,11 +4255,10 @@
void QsciScintilla::annotate(int line, const QList &text)
{
char *styles;
- ScintillaBytes styled_text = styleText(text, &styles,
+ QByteArray styled_text = styleText(text, &styles,
SendScintilla(SCI_ANNOTATIONGETSTYLEOFFSET));
- SendScintilla(SCI_ANNOTATIONSETTEXT, line,
- ScintillaBytesConstData(styled_text));
+ SendScintilla(SCI_ANNOTATIONSETTEXT, line, styled_text.constData());
SendScintilla(SCI_ANNOTATIONSETSTYLES, line, styles);
delete[] styles;
@@ -4268,11 +4268,10 @@
// Get the annotation for a line, if any.
QString QsciScintilla::annotation(int line) const
{
- char *buf = new char[SendScintilla(SCI_ANNOTATIONGETTEXT, line, (const char *)0) + 1];
-
- buf[SendScintilla(SCI_ANNOTATIONGETTEXT, line, buf)] = '\0';
-
- QString qs = bytesAsText(buf);
+ int size = SendScintilla(SCI_ANNOTATIONGETTEXT, line, (const char *)0);
+ char *buf = new char[size + 1];
+
+ QString qs = bytesAsText(buf, size);
delete[] buf;
return qs;
@@ -4280,7 +4279,8 @@
// Convert a list of styled text to the low-level arrays.
-QsciScintillaBase::ScintillaBytes QsciScintilla::styleText(const QList &styled_text, char **styles, int style_offset)
+QByteArray QsciScintilla::styleText(const QList &styled_text,
+ char **styles, int style_offset)
{
QString text;
int i;
@@ -4295,7 +4295,7 @@
text.append(st.text());
}
- ScintillaBytes s = textAsBytes(text);
+ QByteArray s = textAsBytes(text);
// There is a style byte for every byte.
char *sp = *styles = new char[s.length()];
@@ -4303,7 +4303,7 @@
for (i = 0; i < styled_text.count(); ++i)
{
const QsciStyledText &st = styled_text[i];
- ScintillaBytes part = textAsBytes(st.text());
+ QByteArray part = textAsBytes(st.text());
int part_length = part.length();
for (int c = 0; c < part_length; ++c)
@@ -4377,7 +4377,10 @@
if ((e->modifiers() & zoom_modifier) != 0)
{
- if (e->delta() > 0)
+ QPoint ad = e->angleDelta();
+ int delta = (qAbs(ad.x()) > qAbs(ad.y())) ? ad.x() : ad.y();
+
+ if (delta > 0)
zoomIn();
else
zoomOut();
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qsci/qsciscintillabase.cpp
--- a/libgui/languages/build_ts/octave-qsci/qsciscintillabase.cpp Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qsci/qsciscintillabase.cpp Mon Dec 04 19:55:32 2023 +0100
@@ -1,6 +1,6 @@
// This module implements the "official" low-level API.
//
-// Copyright (c) 2019 Riverbank Computing Limited
+// Copyright (c) 2023 Riverbank Computing Limited
//
// This file is part of QScintilla.
//
@@ -36,7 +36,6 @@
#include
#include
#include
-#include
#include "SciAccessibility.h"
#include "ScintillaQt.h"
@@ -80,17 +79,15 @@
static const QLatin1String mimeRectangularWin("MSDEVColumnSelect");
static const QLatin1String mimeRectangular("text/x-qscintilla-rectangular");
-#if (QT_VERSION >= 0x040200 && QT_VERSION < 0x050000 && defined(Q_OS_MAC)) || (QT_VERSION >= 0x050200 && defined(Q_OS_OSX))
+#if QT_VERSION < 0x060000 && defined(Q_OS_OSX)
extern void initialiseRectangularPasteboardMime();
#endif
// The ctor.
QsciScintillaBase::QsciScintillaBase(QWidget *parent)
- : QAbstractScrollArea(parent), preeditPos(-1), preeditNrBytes(0)
-#if QT_VERSION >= 0x050000
- , clickCausedFocus(false)
-#endif
+ : QAbstractScrollArea(parent), preeditPos(-1), preeditNrBytes(0),
+ clickCausedFocus(false)
{
#if !defined(QT_NO_ACCESSIBILITY)
QsciAccessibleScintillaBase::initialise();
@@ -103,12 +100,8 @@
setFocusPolicy(Qt::WheelFocus);
setAttribute(Qt::WA_KeyCompression);
setAttribute(Qt::WA_InputMethodEnabled);
-#if QT_VERSION >= 0x050100
setInputMethodHints(
Qt::ImhNoAutoUppercase|Qt::ImhNoPredictiveText|Qt::ImhMultiLine);
-#elif QT_VERSION >= 0x040600
- setInputMethodHints(Qt::ImhNoAutoUppercase|Qt::ImhNoPredictiveText);
-#endif
viewport()->setBackgroundRole(QPalette::Base);
viewport()->setMouseTracking(true);
@@ -116,7 +109,7 @@
triple_click.setSingleShot(true);
-#if (QT_VERSION >= 0x040200 && QT_VERSION < 0x050000 && defined(Q_OS_MAC)) || (QT_VERSION >= 0x050200 && defined(Q_OS_OSX))
+#if QT_VERSION < 0x060000 && defined(Q_OS_OSX)
initialiseRectangularPasteboardMime();
#endif
@@ -321,11 +314,7 @@
void QsciScintillaBase::focusInEvent(QFocusEvent *e)
{
sci->SetFocusState(true);
-
-#if QT_VERSION >= 0x050000
clickCausedFocus = (e->reason() == Qt::MouseFocusReason);
-#endif
-
QAbstractScrollArea::focusInEvent(e);
}
@@ -400,7 +389,7 @@
if (!text.isEmpty() && text[0].isPrint())
{
- ScintillaBytes bytes = textAsBytes(text);
+ QByteArray bytes = textAsBytes(text);
sci->AddCharUTF(bytes.data(), bytes.length());
e->accept();
}
@@ -503,7 +492,7 @@
// Encode a QString as bytes.
-QsciScintillaBase::ScintillaBytes QsciScintillaBase::textAsBytes(const QString &text) const
+QByteArray QsciScintillaBase::textAsBytes(const QString &text) const
{
if (sci->IsUnicodeMode())
return text.toUtf8();
@@ -513,12 +502,12 @@
// Decode bytes as a QString.
-QString QsciScintillaBase::bytesAsText(const char *bytes) const
+QString QsciScintillaBase::bytesAsText(const char *bytes, int size) const
{
if (sci->IsUnicodeMode())
- return QString::fromUtf8(bytes);
+ return QString::fromUtf8(bytes, size);
- return QString::fromLatin1(bytes);
+ return QString::fromLatin1(bytes, size);
}
@@ -595,7 +584,7 @@
sci->RightButtonDownWithModifiers(pt, clickTime,
QsciScintillaQt::ModifierFlags(shift, ctrl, alt));
}
- else if (e->button() == Qt::MidButton)
+ else if (e->button() == Qt::MiddleButton)
{
QClipboard *cb = QApplication::clipboard();
@@ -628,7 +617,6 @@
QsciScintillaQt::ModifierFlags(false, ctrl, false));
}
-#if QT_VERSION >= 0x050000
if (!sci->pdoc->IsReadOnly() && !sci->PointInSelMargin(pt) && qApp->autoSipEnabled())
{
QStyle::RequestSoftwareInputPanel rsip = QStyle::RequestSoftwareInputPanel(style()->styleHint(QStyle::SH_RequestSoftwareInputPanel));
@@ -638,7 +626,6 @@
}
clickCausedFocus = false;
-#endif
}
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qt/qabstractprintdialog.cpp
--- a/libgui/languages/build_ts/octave-qt/qabstractprintdialog.cpp Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qt/qabstractprintdialog.cpp Mon Dec 04 19:55:32 2023 +0100
@@ -1,43 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qabstractprintdialog_p.h"
#include "qcoreapplication.h"
@@ -45,30 +7,21 @@
#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
+ \inmodule QtPrintSupport
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}
+ \sa QPrintDialog, QPrinter
*/
/*!
@@ -79,7 +32,7 @@
\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. (This value was introduced in 4.7.)
+ \value CurrentPage Only the currently visible page should be printed.
\sa QPrinter::PrintRange
*/
@@ -89,20 +42,12 @@
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 was introduced in 4.7.)
-
- 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.
+ \value PrintCurrentPage The print current page option is enabled
*/
/*!
@@ -115,6 +60,9 @@
Q_D(QAbstractPrintDialog);
setWindowTitle(QCoreApplication::translate("QPrintDialog", "Print"));
d->setPrinter(printer);
+ d->minPage = printer->fromPage();
+ int to = printer->toPage();
+ d->maxPage = to > 0 ? to : INT_MAX;
}
/*!
@@ -148,21 +96,21 @@
*/
void QPrintDialog::setOption(PrintDialogOption option, bool on)
{
- Q_D(QPrintDialog);
- if (!(d->pd->options & option) != !on)
- setOptions(d->pd->options ^ option);
+ auto *d = static_cast(d_ptr.data());
+ if (!(d->options & option) != !on)
+ setOptions(d->options ^ option);
}
/*!
- Returns true if the given \a option is enabled; otherwise, returns
+ Returns \c 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->pd->options & option) != 0;
+ auto *d = static_cast(d_ptr.data());
+ return (d->options & option) != 0;
}
/*!
@@ -180,63 +128,19 @@
*/
void QPrintDialog::setOptions(PrintDialogOptions options)
{
- Q_D(QPrintDialog);
+ auto *d = static_cast(d_ptr.data());
- PrintDialogOptions changed = (options ^ d->pd->options);
+ PrintDialogOptions changed = (options ^ d->options);
if (!changed)
return;
- d->pd->options = options;
+ d->options = options;
}
QPrintDialog::PrintDialogOptions QPrintDialog::options() const
{
- Q_D(const QPrintDialog);
- return d->pd->options;
-}
-
-/*!
- \obsolete
-
- Use QPrintDialog::setOptions() instead.
-*/
-void QAbstractPrintDialog::setEnabledOptions(PrintDialogOptions options)
-{
- Q_D(QAbstractPrintDialog);
- d->pd->options = options;
-}
-
-/*!
- \obsolete
-
- Use QPrintDialog::setOption(\a option, true) instead.
-*/
-void QAbstractPrintDialog::addEnabledOption(PrintDialogOption option)
-{
- Q_D(QAbstractPrintDialog);
- d->pd->options |= option;
-}
-
-/*!
- \obsolete
-
- Use QPrintDialog::options() instead.
-*/
-QAbstractPrintDialog::PrintDialogOptions QAbstractPrintDialog::enabledOptions() const
-{
- Q_D(const QAbstractPrintDialog);
- return d->pd->options;
-}
-
-/*!
- \obsolete
-
- Use QPrintDialog::testOption(\a option) instead.
-*/
-bool QAbstractPrintDialog::isOptionEnabled(PrintDialogOption option) const
-{
- Q_D(const QAbstractPrintDialog);
- return d->pd->options & option;
+ auto *d = static_cast(d_ptr.data());
+ return d->options;
}
/*!
@@ -245,7 +149,7 @@
void QAbstractPrintDialog::setPrintRange(PrintRange range)
{
Q_D(QAbstractPrintDialog);
- d->pd->printRange = range;
+ d->printer->setPrintRange(QPrinter::PrintRange(range));
}
/*!
@@ -254,7 +158,7 @@
QAbstractPrintDialog::PrintRange QAbstractPrintDialog::printRange() const
{
Q_D(const QAbstractPrintDialog);
- return d->pd->printRange;
+ return QAbstractPrintDialog::PrintRange(d->pd->printRange);
}
/*!
@@ -266,9 +170,9 @@
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->pd->options |= PrintPageRange;
+ d->minPage = min;
+ d->maxPage = max;
+ d->options |= PrintPageRange;
}
/*!
@@ -278,7 +182,7 @@
int QAbstractPrintDialog::minPage() const
{
Q_D(const QAbstractPrintDialog);
- return d->pd->minPage;
+ return d->minPage;
}
/*!
@@ -289,7 +193,7 @@
int QAbstractPrintDialog::maxPage() const
{
Q_D(const QAbstractPrintDialog);
- return d->pd->maxPage;
+ return d->maxPage;
}
/*!
@@ -300,10 +204,9 @@
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;
+ d->printer->setFromTo(from, to);
- if (d->pd->minPage == 0 && d->pd->maxPage == 0)
+ if (d->minPage == 0 && d->maxPage == 0)
setMinMax(1, to);
}
@@ -314,7 +217,7 @@
int QAbstractPrintDialog::fromPage() const
{
Q_D(const QAbstractPrintDialog);
- return d->pd->fromPage;
+ return d->printer->fromPage();
}
/*!
@@ -324,7 +227,7 @@
int QAbstractPrintDialog::toPage() const
{
Q_D(const QAbstractPrintDialog);
- return d->pd->toPage;
+ return d->printer->toPage();
}
@@ -343,6 +246,8 @@
if (newPrinter) {
printer = newPrinter;
ownsPrinter = false;
+ if (printer->fromPage() || printer->toPage())
+ options |= QAbstractPrintDialog::PrintPageRange;
} else {
printer = new QPrinter;
ownsPrinter = true;
@@ -351,13 +256,6 @@
}
/*!
- \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
@@ -365,6 +263,7 @@
\ingroup standard-dialogs
\ingroup printing
+ \inmodule QtPrintSupport
The dialog allows users to change document-related settings, such
as the paper size and orientation, type of print (color or
@@ -376,33 +275,32 @@
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
+ \snippet 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
+ \li \inlineimage plastique-printdialog.png
+ \li \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.
+ \uicontrol{Properties} push button.
- On Windows and Mac OS X, the native print dialog is used, which means that
+ On Windows and \macos, 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,
+ The native print dialog on \macos 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
+ \macos. 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}
+ \sa QPageSetupDialog, QPrinter
*/
/*!
@@ -459,21 +357,21 @@
and exec() to return \a result.
\note This function does not apply to the Native Print Dialog on the Mac
- OS X and Windows platforms, because the dialog is required to be modal
+ \macos and Windows platforms, because the dialog is required to be modal
and only the user can close it.
\sa QDialog::done()
*/
void QPrintDialog::done(int result)
{
- Q_D(QPrintDialog);
+ auto *d = static_cast(d_ptr.data());
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->receiverToDisconnectOnClose = nullptr;
}
d->memberToDisconnectOnClose.clear();
}
@@ -489,7 +387,7 @@
*/
void QPrintDialog::open(QObject *receiver, const char *member)
{
- Q_D(QPrintDialog);
+ auto *d = static_cast(d_ptr.data());
connect(this, SIGNAL(accepted(QPrinter*)), receiver, member);
d->receiverToDisconnectOnClose = receiver;
d->memberToDisconnectOnClose = member;
@@ -498,4 +396,4 @@
QT_END_NAMESPACE
-#endif // QT_NO_PRINTDIALOG
+#include "moc_qabstractprintdialog.cpp"
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qt/qcolordialog.cpp
--- a/libgui/languages/build_ts/octave-qt/qcolordialog.cpp Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qt/qcolordialog.cpp Mon Dec 04 19:55:32 2023 +0100
@@ -1,82 +1,165 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-#include "qcolordialog_p.h"
-
-#ifndef QT_NO_COLORDIALOG
+#include "qcolordialog.h"
#include "qapplication.h"
-#include "qdesktopwidget.h"
#include "qdrawutil.h"
#include "qevent.h"
#include "qimage.h"
+#if QT_CONFIG(draganddrop)
+#include
+#endif
#include "qlabel.h"
#include "qlayout.h"
#include "qlineedit.h"
+#if QT_CONFIG(menu)
#include "qmenu.h"
+#endif
#include "qpainter.h"
#include "qpixmap.h"
#include "qpushbutton.h"
+#if QT_CONFIG(regularexpression)
+#include
+#endif
+#if QT_CONFIG(settings)
#include "qsettings.h"
+#endif
+#include "qsharedpointer.h"
#include "qstyle.h"
#include "qstyleoption.h"
#include "qvalidator.h"
-#include "qmime.h"
+#include "qmimedata.h"
#include "qspinbox.h"
#include "qdialogbuttonbox.h"
-#include "private/qguiplatformplugin_p.h"
+#include "qscreen.h"
+#include "qcursor.h"
+#include "qtimer.h"
+#include "qwindow.h"
-#ifdef Q_WS_S60
-#include "private/qt_s60_p.h"
-#endif
+#include "private/qdialog_p.h"
-#if defined(Q_WS_S60) || defined(Q_WS_MAEMO_5)
-# define QT_SMALL_COLORDIALOG
-#endif
+#include
+#include
+#include
+
+#include
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+namespace QtPrivate {
+class QColorLuminancePicker;
+class QColorPicker;
+class QColorShower;
+class QWellArray;
+class QColorWell;
+class QColorPickingEventFilter;
+} // namespace QtPrivate
+
+using QColorLuminancePicker = QtPrivate::QColorLuminancePicker;
+using QColorPicker = QtPrivate::QColorPicker;
+using QColorShower = QtPrivate::QColorShower;
+using QWellArray = QtPrivate::QWellArray;
+using QColorWell = QtPrivate::QColorWell;
+using QColorPickingEventFilter = QtPrivate::QColorPickingEventFilter;
+
+class QColorDialogPrivate : public QDialogPrivate
+{
+ Q_DECLARE_PUBLIC(QColorDialog)
+
+public:
+ enum SetColorMode {
+ ShowColor = 0x1,
+ SelectColor = 0x2,
+ SetColorAll = ShowColor | SelectColor
+ };
+
+ QColorDialogPrivate() : options(QColorDialogOptions::create())
+#ifdef Q_OS_WIN32
+ , updateTimer(0)
+#endif
+ {}
+
+ QPlatformColorDialogHelper *platformColorDialogHelper() const
+ { return static_cast(platformHelper()); }
+
+ void init(const QColor &initial);
+ void initWidgets();
+ QRgb currentColor() const;
+ QColor currentQColor() const;
+ void setCurrentColor(const QColor &color, SetColorMode setColorMode = SetColorAll);
+ void setCurrentRgbColor(QRgb rgb);
+ void setCurrentQColor(const QColor &color);
+ bool selectColor(const QColor &color);
+ QColor grabScreenColor(const QPoint &p);
+
+ int currentAlpha() const;
+ void setCurrentAlpha(int a);
+ void showAlpha(bool b);
+ bool isAlphaVisible() const;
+ void retranslateStrings();
+ bool supportsColorPicking() const;
+
+ void _q_addCustom();
+ void _q_setCustom(int index, QRgb color);
+
+ void _q_newHsv(int h, int s, int v);
+ void _q_newColorTypedIn(QRgb rgb);
+ void _q_nextCustom(int, int);
+ void _q_newCustom(int, int);
+ void _q_newStandard(int, int);
+ void _q_pickScreenColor();
+ void _q_updateColorPicking();
+ void updateColorLabelText(const QPoint &);
+ void updateColorPicking(const QPoint &pos);
+ void releaseColorPicking();
+ bool handleColorPickingMouseMove(QMouseEvent *e);
+ bool handleColorPickingMouseButtonRelease(QMouseEvent *e);
+ bool handleColorPickingKeyPress(QKeyEvent *e);
+
+ bool canBeNativeDialog() const override;
+ void setVisible(bool visible) override;
+
+ QWellArray *custom;
+ QWellArray *standard;
+
+ QDialogButtonBox *buttons;
+ QVBoxLayout *leftLay;
+ QColorPicker *cp;
+ QColorLuminancePicker *lp;
+ QColorShower *cs;
+ QLabel *lblBasicColors;
+ QLabel *lblCustomColors;
+ QLabel *lblScreenColorInfo;
+ QPushButton *ok;
+ QPushButton *cancel;
+ QPushButton *addCusBt;
+ QPushButton *screenColorPickerButton;
+ QColor selectedQColor;
+ int nextCust;
+ bool smallDisplay;
+ bool screenColorPicking;
+ QColorPickingEventFilter *colorPickingEventFilter;
+ QRgb beforeScreenColorPicking;
+ QSharedPointer options;
+
+ QPointer receiverToDisconnectOnClose;
+ QByteArray memberToDisconnectOnClose;
+#ifdef Q_OS_WIN32
+ QTimer *updateTimer;
+ QWindow dummyTransparentWindow;
+#endif
+
+private:
+ virtual void initHelper(QPlatformDialogHelper *h) override;
+ virtual void helperPrepareShow(QPlatformDialogHelper *h) override;
+};
+
//////////// QWellArray BEGIN
-struct QWellArrayData;
+namespace QtPrivate {
class QWellArray : public QWidget
{
@@ -85,7 +168,7 @@
Q_PROPERTY(int selectedRow READ selectedRow)
public:
- QWellArray(int rows, int cols, QWidget* parent=0);
+ QWellArray(int rows, int cols, QWidget* parent=nullptr);
~QWellArray() {}
QString cellContent(int row, int col) const;
@@ -95,10 +178,7 @@
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);
+ QSize sizeHint() const override;
inline int cellWidth() const
{ return cellw; }
@@ -142,17 +222,19 @@
signals:
void selected(int row, int col);
+ void currentChanged(int row, int col);
+ void colorChanged(int index, QRgb color);
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 *);
+ void mousePressEvent(QMouseEvent*) override;
+ void mouseReleaseEvent(QMouseEvent*) override;
+ void keyPressEvent(QKeyEvent*) override;
+ void focusInEvent(QFocusEvent*) override;
+ void focusOutEvent(QFocusEvent*) override;
+ void paintEvent(QPaintEvent *) override;
private:
Q_DISABLE_COPY(QWellArray)
@@ -165,7 +247,6 @@
int curCol;
int selRow;
int selCol;
- QWellArrayData *d;
};
void QWellArray::paintEvent(QPaintEvent *e)
@@ -215,15 +296,10 @@
}
}
-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;
@@ -246,7 +322,8 @@
const QPalette & g = palette();
QStyleOptionFrame opt;
- int dfw = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
+ opt.initFrom(this);
+ int dfw = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt);
opt.lineWidth = dfw;
opt.midLineWidth = 1;
opt.rect = rect.adjusted(b, b, -b, -b);
@@ -267,25 +344,23 @@
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());
- }
+ Q_UNUSED(row);
+ Q_UNUSED(col);
+ 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();
+ QPoint pos = e->position().toPoint();
setCurrent(rowAt(pos.y()), columnAt(pos.x()));
}
@@ -317,6 +392,8 @@
updateCell(oldRow, oldCol);
updateCell(curRow, curCol);
+
+ emit currentChanged(curRow, curCol);
}
/*
@@ -341,7 +418,7 @@
if (row >= 0)
emit selected(row, col);
-#ifndef QT_NO_MENU
+#if QT_CONFIG(menu)
if (isVisible() && qobject_cast(parentWidget()))
parentWidget()->close();
#endif
@@ -350,62 +427,45 @@
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;
+ emit currentChanged(curRow, curCol);
}
-/*
- 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
+ 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)
+ if (curCol < numCols()-1)
setCurrent(curRow, curCol + 1);
break;
case Qt::Key_Up:
- if(curRow > 0)
+ if (curRow > 0)
setCurrent(curRow - 1, curCol);
break;
case Qt::Key_Down:
- if(curRow < numRows()-1)
+ 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;
@@ -414,30 +474,35 @@
return;
}
-}
+} // namespace QtPrivate
//////////// QWellArray END
-static bool initrgb = false;
-static QRgb stdrgb[6*8];
-static QRgb cusrgb[2*8];
-static bool customSet = false;
-
+// Event filter to be installed on the dialog while in color-picking mode.
+class QColorPickingEventFilter : public QObject {
+public:
+ explicit QColorPickingEventFilter(QColorDialogPrivate *dp, QObject *parent) : QObject(parent), m_dp(dp) {}
-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);
+ bool eventFilter(QObject *, QEvent *event) override
+ {
+ switch (event->type()) {
+ case QEvent::MouseMove:
+ return m_dp->handleColorPickingMouseMove(static_cast(event));
+ case QEvent::MouseButtonRelease:
+ return m_dp->handleColorPickingMouseButtonRelease(static_cast(event));
+ case QEvent::KeyPress:
+ return m_dp->handleColorPickingKeyPress(static_cast(event));
+ default:
+ break;
+ }
+ return false;
+ }
- for (i = 0; i < 2*8; i++)
- cusrgb[i] = 0xffffffff;
-}
+private:
+ QColorDialogPrivate *m_dp;
+};
+
+} // unnamed namespace
/*!
Returns the number of custom colors supported by QColorDialog. All
@@ -445,52 +510,51 @@
*/
int QColorDialog::customCount()
{
- return 2 * 8;
+ return QColorDialogOptions::customColorCount();
}
/*!
\since 4.5
- Returns the custom color at the given \a index as a QRgb value.
+ Returns the custom color at the given \a index as a QColor value.
*/
-QRgb QColorDialog::customColor(int index)
+QColor QColorDialog::customColor(int index)
{
- if (uint(index) >= uint(customCount()))
- return qRgb(255, 255, 255);
- initRGB();
- return cusrgb[index];
+ return QColor(QColorDialogOptions::customColor(index));
+}
+
+/*!
+ Sets the custom color at \a index to the QColor \a color value.
+
+ \note This function does not apply to the Native Color Dialog on the
+ \macos platform. If you still require this function, use the
+ QColorDialog::DontUseNativeDialog option.
+*/
+void QColorDialog::setCustomColor(int index, QColor color)
+{
+ QColorDialogOptions::setCustomColor(index, color.rgba());
}
/*!
- Sets the custom color at \a index to the QRgb \a color value.
+ \since 5.0
- \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.
+ Returns the standard color at the given \a index as a QColor value.
*/
-void QColorDialog::setCustomColor(int index, QRgb color)
+QColor QColorDialog::standardColor(int index)
{
- if (uint(index) >= uint(customCount()))
- return;
- initRGB();
- customSet = true;
- cusrgb[index] = color;
+ return QColor(QColorDialogOptions::standardColor(index));
}
/*!
- Sets the standard color at \a index to the QRgb \a color value.
+ Sets the standard color at \a index to the QColor \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
+ \note This function does not apply to the Native Color Dialog on the
+ \macos platform. If you still require this function, use the
QColorDialog::DontUseNativeDialog option.
*/
-
-void QColorDialog::setStandardColor(int index, QRgb color)
+void QColorDialog::setStandardColor(int index, QColor color)
{
- if (uint(index) >= uint(6 * 8))
- return;
- initRGB();
- stdrgb[index] = color;
+ QColorDialogOptions::setStandardColor(index, color.rgba());
}
static inline void rgb2hsv(QRgb rgb, int &h, int &s, int &v)
@@ -500,27 +564,29 @@
c.getHsv(&h, &s, &v);
}
+namespace QtPrivate {
+
class QColorWell : public QWellArray
{
public:
- QColorWell(QWidget *parent, int r, int c, QRgb *vals)
+ QColorWell(QWidget *parent, int r, int c, const 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);
+ void paintCellContents(QPainter *, int row, int col, const QRect&) override;
+ void mousePressEvent(QMouseEvent *e) override;
+ void mouseMoveEvent(QMouseEvent *e) override;
+ void mouseReleaseEvent(QMouseEvent *e) override;
+#if QT_CONFIG(draganddrop)
+ void dragEnterEvent(QDragEnterEvent *e) override;
+ void dragLeaveEvent(QDragLeaveEvent *e) override;
+ void dragMoveEvent(QDragMoveEvent *e) override;
+ void dropEvent(QDropEvent *e) override;
#endif
private:
- QRgb *values;
+ const QRgb *values;
bool mousePressed;
QPoint pressPos;
QPoint oldCurrent;
@@ -538,16 +604,16 @@
oldCurrent = QPoint(selectedRow(), selectedColumn());
QWellArray::mousePressEvent(e);
mousePressed = true;
- pressPos = e->pos();
+ pressPos = e->position().toPoint();
}
void QColorWell::mouseMoveEvent(QMouseEvent *e)
{
QWellArray::mouseMoveEvent(e);
-#ifndef QT_NO_DRAGANDDROP
+#if QT_CONFIG(draganddrop)
if (!mousePressed)
return;
- if ((pressPos - e->pos()).manhattanLength() > QApplication::startDragDistance()) {
+ if ((pressPos - e->position().toPoint()).manhattanLength() > QApplication::startDragDistance()) {
setCurrent(oldCurrent.x(), oldCurrent.y());
int i = rowAt(pressPos.y()) + columnAt(pressPos.x()) * numRows();
QColor col(values[i]);
@@ -562,12 +628,12 @@
drg->setMimeData(mime);
drg->setPixmap(pix);
mousePressed = false;
- drg->start();
+ drg->exec(Qt::CopyAction);
}
#endif
}
-#ifndef QT_NO_DRAGANDDROP
+#if QT_CONFIG(draganddrop)
void QColorWell::dragEnterEvent(QDragEnterEvent *e)
{
if (qvariant_cast(e->mimeData()->colorData()).isValid())
@@ -585,7 +651,7 @@
void QColorWell::dragMoveEvent(QDragMoveEvent *e)
{
if (qvariant_cast(e->mimeData()->colorData()).isValid()) {
- setCurrent(rowAt(e->pos().y()), columnAt(e->pos().x()));
+ setCurrent(rowAt(e->position().toPoint().y()), columnAt(e->position().toPoint().x()));
e->accept();
} else {
e->ignore();
@@ -596,16 +662,15 @@
{
QColor col = qvariant_cast(e->mimeData()->colorData());
if (col.isValid()) {
- int i = rowAt(e->pos().y()) + columnAt(e->pos().x()) * numRows();
- values[i] = col.rgb();
- update();
+ int i = rowAt(e->position().toPoint().y()) + columnAt(e->position().toPoint().x()) * numRows();
+ emit colorChanged(i, col.rgb());
e->accept();
} else {
e->ignore();
}
}
-#endif // QT_NO_DRAGANDDROP
+#endif // QT_CONFIG(draganddrop)
void QColorWell::mouseReleaseEvent(QMouseEvent *e)
{
@@ -622,6 +687,7 @@
QColorPicker(QWidget* parent);
~QColorPicker();
+ void setCrossVisible(bool visible);
public slots:
void setCol(int h, int s);
@@ -629,11 +695,11 @@
void newCol(int h, int s);
protected:
- QSize sizeHint() const;
- void paintEvent(QPaintEvent*);
- void mouseMoveEvent(QMouseEvent *);
- void mousePressEvent(QMouseEvent *);
- void resizeEvent(QResizeEvent *);
+ QSize sizeHint() const override;
+ void paintEvent(QPaintEvent*) override;
+ void mouseMoveEvent(QMouseEvent *) override;
+ void mousePressEvent(QMouseEvent *) override;
+ void resizeEvent(QResizeEvent *) override;
private:
int hue;
@@ -645,16 +711,21 @@
void setCol(const QPoint &pt);
QPixmap pix;
+ bool crossVisible;
};
+} // namespace QtPrivate
+
static int pWidth = 220;
static int pHeight = 200;
+namespace QtPrivate {
+
class QColorLuminancePicker : public QWidget
{
Q_OBJECT
public:
- QColorLuminancePicker(QWidget* parent=0);
+ QColorLuminancePicker(QWidget* parent=nullptr);
~QColorLuminancePicker();
public slots:
@@ -665,9 +736,9 @@
void newHsv(int h, int s, int v);
protected:
- void paintEvent(QPaintEvent*);
- void mouseMoveEvent(QMouseEvent *);
- void mousePressEvent(QMouseEvent *);
+ void paintEvent(QPaintEvent*) override;
+ void mouseMoveEvent(QMouseEvent *) override;
+ void mousePressEvent(QMouseEvent *) override;
private:
enum { foff = 3, coff = 4 }; //frame and contents offset
@@ -699,7 +770,7 @@
:QWidget(parent)
{
hue = 100; val = 100; sat = 100;
- pix = 0;
+ pix = nullptr;
// setAttribute(WA_NoErase, true);
}
@@ -710,11 +781,15 @@
void QColorLuminancePicker::mouseMoveEvent(QMouseEvent *m)
{
- setVal(y2val(m->y()));
+ if (m->buttons() == Qt::NoButton) {
+ m->ignore();
+ return;
+ }
+ setVal(y2val(m->position().toPoint().y()));
}
void QColorLuminancePicker::mousePressEvent(QMouseEvent *m)
{
- setVal(y2val(m->y()));
+ setVal(y2val(m->position().toPoint().y()));
}
void QColorLuminancePicker::setVal(int v)
@@ -722,7 +797,7 @@
if (val == v)
return;
val = qMax(0, qMin(v,255));
- delete pix; pix=0;
+ delete pix; pix=nullptr;
repaint();
emit newHsv(hue, sat, val);
}
@@ -747,13 +822,9 @@
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;
- }
+ uint *end = pixel + wi;
+ std::fill(pixel, end, QColor::fromHsv(hue, sat, y2val(y + coff)).rgb());
+ pixel = end;
}
pix = new QPixmap(QPixmap::fromImage(img));
}
@@ -761,8 +832,8 @@
p.drawPixmap(1, coff, *pix);
const QPalette &g = palette();
qDrawShadePanel(&p, r, g, true);
- p.setPen(g.foreground().color());
- p.setBrush(g.foreground());
+ p.setPen(g.windowText().color());
+ p.setBrush(g.windowText());
QPolygon a;
int y = val2y(val);
a.setPoints(3, w, y, w+5, y+5, w+5, y-5);
@@ -775,7 +846,7 @@
val = v;
hue = h;
sat = s;
- delete pix; pix=0;
+ delete pix; pix=nullptr;
repaint();
}
@@ -804,6 +875,7 @@
QColorPicker::QColorPicker(QWidget* parent)
: QFrame(parent)
+ , crossVisible(true)
{
hue = 0; sat = 0;
setCol(150, 255);
@@ -816,6 +888,14 @@
{
}
+void QColorPicker::setCrossVisible(bool visible)
+{
+ if (crossVisible != visible) {
+ crossVisible = visible;
+ update();
+ }
+}
+
QSize QColorPicker::sizeHint() const
{
return QSize(pWidth + 2*frameWidth(), pHeight + 2*frameWidth());
@@ -838,14 +918,18 @@
void QColorPicker::mouseMoveEvent(QMouseEvent *m)
{
- QPoint p = m->pos() - contentsRect().topLeft();
+ QPoint p = m->position().toPoint() - contentsRect().topLeft();
+ if (m->buttons() == Qt::NoButton) {
+ m->ignore();
+ return;
+ }
setCol(p);
emit newCol(hue, sat);
}
void QColorPicker::mousePressEvent(QMouseEvent *m)
{
- QPoint p = m->pos() - contentsRect().topLeft();
+ QPoint p = m->position().toPoint() - contentsRect().topLeft();
setCol(p);
emit newCol(hue, sat);
}
@@ -857,12 +941,13 @@
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);
-
+ if (crossVisible) {
+ 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)
@@ -896,10 +981,8 @@
QColSpinBox(QWidget *parent)
: QSpinBox(parent) { setRange(0, 255); }
void setValue(int i) {
- bool block = signalsBlocked();
- blockSignals(true);
+ const QSignalBlocker blocker(this);
QSpinBox::setValue(i);
- blockSignals(block);
}
};
@@ -935,6 +1018,8 @@
private slots:
void rgbEd();
void hsvEd();
+ void htmlEd();
+
private:
void showCurrentColor();
int hue, sat, val;
@@ -946,6 +1031,7 @@
QLabel *lblRed;
QLabel *lblGreen;
QLabel *lblBlue;
+ QLabel *lblHtml;
QColSpinBox *hEd;
QColSpinBox *sEd;
QColSpinBox *vEd;
@@ -954,12 +1040,14 @@
QColSpinBox *bEd;
QColSpinBox *alphaEd;
QLabel *alphaLab;
+ QLineEdit *htEd;
QColorShowLabel *lab;
bool rgbOriginal;
QColorDialog *colorDialog;
+ QGridLayout *gl;
- friend class QColorDialog;
- friend class QColorDialogPrivate;
+ friend class QT_PREPEND_NAMESPACE(QColorDialog);
+ friend class QT_PREPEND_NAMESPACE(QColorDialogPrivate);
};
class QColorShowLabel : public QFrame
@@ -978,14 +1066,14 @@
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);
+ void paintEvent(QPaintEvent *) override;
+ void mousePressEvent(QMouseEvent *e) override;
+ void mouseMoveEvent(QMouseEvent *e) override;
+ void mouseReleaseEvent(QMouseEvent *e) override;
+#if QT_CONFIG(draganddrop)
+ void dragEnterEvent(QDragEnterEvent *e) override;
+ void dragLeaveEvent(QDragLeaveEvent *e) override;
+ void dropEvent(QDropEvent *e) override;
#endif
private:
@@ -1015,17 +1103,17 @@
void QColorShowLabel::mousePressEvent(QMouseEvent *e)
{
mousePressed = true;
- pressPos = e->pos();
+ pressPos = e->position().toPoint();
}
void QColorShowLabel::mouseMoveEvent(QMouseEvent *e)
{
-#ifdef QT_NO_DRAGANDDROP
+#if !QT_CONFIG(draganddrop)
Q_UNUSED(e);
#else
if (!mousePressed)
return;
- if ((pressPos - e->pos()).manhattanLength() > QApplication::startDragDistance()) {
+ if ((pressPos - e->position().toPoint()).manhattanLength() > QApplication::startDragDistance()) {
QMimeData *mime = new QMimeData;
mime->setColorData(col);
QPixmap pix(30, 20);
@@ -1037,12 +1125,12 @@
drg->setMimeData(mime);
drg->setPixmap(pix);
mousePressed = false;
- drg->start();
+ drg->exec(Qt::CopyAction);
}
#endif
}
-#ifndef QT_NO_DRAGANDDROP
+#if QT_CONFIG(draganddrop)
void QColorShowLabel::dragEnterEvent(QDragEnterEvent *e)
{
if (qvariant_cast(e->mimeData()->colorData()).isValid())
@@ -1067,7 +1155,7 @@
e->ignore();
}
}
-#endif // QT_NO_DRAGANDDROP
+#endif // QT_CONFIG(draganddrop)
void QColorShowLabel::mouseReleaseEvent(QMouseEvent *)
{
@@ -1084,40 +1172,25 @@
curCol = qRgb(255, 255, 255);
curQColor = Qt::white;
- QGridLayout *gl = new QGridLayout(this);
- gl->setMargin(gl->spacing());
+ gl = new QGridLayout(this);
+ const int s = gl->spacing();
+ gl->setContentsMargins(s, s, s, s);
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);
+ 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)));
+ connect(lab, &QColorShowLabel::colorDropped, this, &QColorShower::newCol);
+ connect(lab, &QColorShowLabel::colorDropped, this, &QColorShower::setRgb);
hEd = new QColSpinBox(this);
hEd->setRange(0, 359);
@@ -1130,13 +1203,8 @@
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();
- }
+ gl->addWidget(lblHue, 1, 0);
+ gl->addWidget(hEd, 2, 0);
#endif
sEd = new QColSpinBox(this);
@@ -1149,13 +1217,8 @@
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();
- }
+ gl->addWidget(lblSat, 1, 1);
+ gl->addWidget(sEd, 2, 1);
#endif
vEd = new QColSpinBox(this);
@@ -1168,13 +1231,8 @@
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();
- }
+ gl->addWidget(lblVal, 1, 2);
+ gl->addWidget(vEd, 2, 2);
#endif
rEd = new QColSpinBox(this);
@@ -1187,13 +1245,8 @@
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();
- }
+ gl->addWidget(lblRed, 3, 0);
+ gl->addWidget(rEd, 4, 0);
#endif
gEd = new QColSpinBox(this);
@@ -1206,13 +1259,8 @@
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();
- }
+ gl->addWidget(lblGreen, 3, 1);
+ gl->addWidget(gEd, 4, 1);
#endif
bEd = new QColSpinBox(this);
@@ -1225,13 +1273,8 @@
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();
- }
+ gl->addWidget(lblBlue, 3, 2);
+ gl->addWidget(bEd, 4, 2);
#endif
alphaEd = new QColSpinBox(this);
@@ -1244,29 +1287,51 @@
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();
- }
+ gl->addWidget(alphaLab, 1, 3, 3, 1);
+ gl->addWidget(alphaEd, 4, 3);
#endif
alphaEd->hide();
alphaLab->hide();
+ lblHtml = new QLabel(this);
+ htEd = new QLineEdit(this);
+ htEd->setObjectName("qt_colorname_lineedit");
+#ifndef QT_NO_SHORTCUT
+ lblHtml->setBuddy(htEd);
+#endif
- connect(hEd, SIGNAL(valueChanged(int)), this, SLOT(hsvEd()));
- connect(sEd, SIGNAL(valueChanged(int)), this, SLOT(hsvEd()));
- connect(vEd, SIGNAL(valueChanged(int)), this, SLOT(hsvEd()));
+#if QT_CONFIG(regularexpression)
+ QRegularExpression regExp(QStringLiteral("#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})"));
+ QRegularExpressionValidator *validator = new QRegularExpressionValidator(regExp, this);
+ htEd->setValidator(validator);
+#else
+ htEd->setReadOnly(true);
+#endif
+ htEd->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
- 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()));
+ lblHtml->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
+#if defined(QT_SMALL_COLORDIALOG)
+ gl->addWidget(lblHtml, 5, 0);
+ gl->addWidget(htEd, 5, 1, 1, /*colspan=*/ 2);
+#else
+ gl->addWidget(lblHtml, 5, 1);
+ gl->addWidget(htEd, 5, 2, 1, /*colspan=*/ 3);
+#endif
+
+ connect(hEd, &QSpinBox::valueChanged, this, &QColorShower::hsvEd);
+ connect(sEd, &QSpinBox::valueChanged, this, &QColorShower::hsvEd);
+ connect(vEd, &QSpinBox::valueChanged, this, &QColorShower::hsvEd);
+
+ connect(rEd, &QSpinBox::valueChanged, this, &QColorShower::rgbEd);
+ connect(gEd, &QSpinBox::valueChanged, this, &QColorShower::rgbEd);
+ connect(bEd, &QSpinBox::valueChanged, this, &QColorShower::rgbEd);
+ connect(alphaEd, &QSpinBox::valueChanged, this, &QColorShower::rgbEd);
+ connect(htEd, &QLineEdit::textEdited, this, &QColorShower::htmlEd);
retranslateStrings();
}
+} // namespace QtPrivate
+
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); }
@@ -1275,6 +1340,8 @@
QColor QColorDialogPrivate::currentQColor() const
{
+ if (nativeDialogInUse)
+ return platformColorDialogHelper()->currentColor();
return cs->currentQColor();
}
@@ -1295,6 +1362,8 @@
sEd->setValue(sat);
vEd->setValue(val);
+ htEd->setText(QColor(curCol).name());
+
showCurrentColor();
emit newCol(currentColor());
updateQColor();
@@ -1315,6 +1384,40 @@
gEd->setValue(qGreen(currentColor()));
bEd->setValue(qBlue(currentColor()));
+ htEd->setText(c.name());
+
+ showCurrentColor();
+ emit newCol(currentColor());
+ updateQColor();
+}
+
+void QColorShower::htmlEd()
+{
+ QString t = htEd->text();
+ if (t.isEmpty())
+ return;
+
+ if (!t.startsWith(QStringLiteral("#"))) {
+ t = QStringLiteral("#") + t;
+ QSignalBlocker blocker(htEd);
+ htEd->setText(t);
+ }
+
+ QColor c = QColor::fromString(t);
+ if (!c.isValid())
+ return;
+
+ curCol = qRgba(c.red(), c.green(), c.blue(), currentAlpha());
+ rgb2hsv(curCol, 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();
emit newCol(currentColor());
updateQColor();
@@ -1335,6 +1438,8 @@
gEd->setValue(qGreen(currentColor()));
bEd->setValue(qBlue(currentColor()));
+ htEd->setText(QColor(rgb).name());
+
showCurrentColor();
updateQColor();
}
@@ -1342,7 +1447,7 @@
void QColorShower::setHsv(int h, int s, int v)
{
if (h < -1 || (uint)s > 255 || (uint)v > 255)
- return;
+ return;
rgbOriginal = false;
hue = h; val = v; sat = s;
@@ -1358,6 +1463,8 @@
gEd->setValue(qGreen(currentColor()));
bEd->setValue(qBlue(currentColor()));
+ htEd->setText(c.name());
+
showCurrentColor();
updateQColor();
}
@@ -1371,6 +1478,7 @@
lblGreen->setText(QColorDialog::tr("&Green:"));
lblBlue->setText(QColorDialog::tr("Bl&ue:"));
alphaLab->setText(QColorDialog::tr("A&lpha channel:"));
+ lblHtml->setText(QColorDialog::tr("&HTML:"));
}
void QColorShower::updateQColor()
@@ -1384,16 +1492,20 @@
//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);
+ if (!nativeDialogInUse) {
+ 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)
+void QColorDialogPrivate::setCurrentRgbColor(QRgb rgb)
{
- cs->setRgb(rgb);
- _q_newColorTypedIn(rgb);
+ if (!nativeDialogInUse) {
+ cs->setRgb(rgb);
+ _q_newColorTypedIn(rgb);
+ }
}
// hack; doesn't keep curCol in sync, so use with care
@@ -1406,66 +1518,173 @@
}
}
+// size of standard and custom color selector
+enum {
+ colorColumns = 8,
+ standardColorRows = 6,
+ customColorRows = 2
+};
+
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;
- }
- }
+ const QRgb *standardColors = QColorDialogOptions::standardColors();
+ const QRgb *standardColorsEnd = standardColors + standardColorRows * colorColumns;
+ const QRgb *match = std::find(standardColors, standardColorsEnd, color);
+ if (match != standardColorsEnd) {
+ const int index = int(match - standardColors);
+ const int column = index / standardColorRows;
+ const int row = index % standardColorRows;
+ _q_newStandard(row, column);
+ standard->setCurrent(row, column);
+ standard->setSelected(row, column);
+ 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;
- }
- }
+ const QRgb *customColors = QColorDialogOptions::customColors();
+ const QRgb *customColorsEnd = customColors + customColorRows * colorColumns;
+ const QRgb *match = std::find(customColors, customColorsEnd, color);
+ if (match != customColorsEnd) {
+ const int index = int(match - customColors);
+ const int column = index / customColorRows;
+ const int row = index % customColorRows;
+ _q_newCustom(row, column);
+ custom->setCurrent(row, column);
+ custom->setSelected(row, column);
+ custom->setFocus();
+ return true;
}
}
return false;
}
+QColor QColorDialogPrivate::grabScreenColor(const QPoint &p)
+{
+ QScreen *screen = QGuiApplication::screenAt(p);
+ if (!screen)
+ screen = QGuiApplication::primaryScreen();
+ const QRect screenRect = screen->geometry();
+ const QPixmap pixmap =
+ screen->grabWindow(0, p.x() - screenRect.x(), p.y() - screenRect.y(), 1, 1);
+ const QImage i = pixmap.toImage();
+ return i.pixel(0, 0);
+}
+
//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);
+ if (!nativeDialogInUse) {
+ int h, s, v;
+ rgb2hsv(rgb, h, s, v);
+ cp->setCol(h, s);
+ lp->setCol(h, s, v);
+ }
+}
+
+void QColorDialogPrivate::_q_nextCustom(int r, int c)
+{
+ nextCust = r + customColorRows * c;
}
void QColorDialogPrivate::_q_newCustom(int r, int c)
{
- int i = r+2*c;
- setCurrentColor(cusrgb[i]);
- nextCust = i;
+ const int i = r + customColorRows * c;
+ setCurrentRgbColor(QColorDialogOptions::customColor(i));
if (standard)
standard->setSelected(-1,-1);
}
void QColorDialogPrivate::_q_newStandard(int r, int c)
{
- setCurrentColor(stdrgb[r+c*6]);
+ setCurrentRgbColor(QColorDialogOptions::standardColor(r + c * 6));
if (custom)
custom->setSelected(-1,-1);
}
+void QColorDialogPrivate::_q_pickScreenColor()
+{
+ Q_Q(QColorDialog);
+
+ auto *platformServices = QGuiApplicationPrivate::platformIntegration()->services();
+ if (platformServices->hasCapability(QPlatformServices::Capability::ColorPicking)) {
+ if (auto *colorPicker = platformServices->colorPicker(q->windowHandle())) {
+ q->connect(colorPicker, &QPlatformServiceColorPicker::colorPicked, q,
+ [q, colorPicker](const QColor &color) {
+ colorPicker->deleteLater();
+ q->setCurrentColor(color);
+ });
+ colorPicker->pickColor();
+ return;
+ }
+ }
+
+ if (!colorPickingEventFilter)
+ colorPickingEventFilter = new QColorPickingEventFilter(this, q);
+ q->installEventFilter(colorPickingEventFilter);
+ // If user pushes Escape, the last color before picking will be restored.
+ beforeScreenColorPicking = cs->currentColor();
+#ifndef QT_NO_CURSOR
+ q->grabMouse(Qt::CrossCursor);
+#else
+ q->grabMouse();
+#endif
+
+#ifdef Q_OS_WIN32
+ // On Windows mouse tracking doesn't work over other processes's windows
+ updateTimer->start(30);
+
+ // HACK: Because mouse grabbing doesn't work across processes, we have to have a dummy,
+ // invisible window to catch the mouse click, otherwise we will click whatever we clicked
+ // and loose focus.
+ dummyTransparentWindow.show();
+#endif
+ q->grabKeyboard();
+ /* With setMouseTracking(true) the desired color can be more precisely picked up,
+ * and continuously pushing the mouse button is not necessary.
+ */
+ q->setMouseTracking(true);
+
+ addCusBt->setDisabled(true);
+ buttons->setDisabled(true);
+ if (screenColorPickerButton) {
+ screenColorPickerButton->setDisabled(true);
+ const QPoint globalPos = QCursor::pos();
+ q->setCurrentColor(grabScreenColor(globalPos));
+ updateColorLabelText(globalPos);
+ }
+}
+
+void QColorDialogPrivate::updateColorLabelText(const QPoint &globalPos)
+{
+ if (lblScreenColorInfo)
+ lblScreenColorInfo->setText(QColorDialog::tr("Cursor at %1, %2\nPress ESC to cancel")
+ .arg(globalPos.x())
+ .arg(globalPos.y()));
+}
+
+void QColorDialogPrivate::releaseColorPicking()
+{
+ Q_Q(QColorDialog);
+ cp->setCrossVisible(true);
+ q->removeEventFilter(colorPickingEventFilter);
+ q->releaseMouse();
+#ifdef Q_OS_WIN32
+ updateTimer->stop();
+ dummyTransparentWindow.setVisible(false);
+#endif
+ q->releaseKeyboard();
+ q->setMouseTracking(false);
+ lblScreenColorInfo->setText("\n"_L1);
+ addCusBt->setDisabled(false);
+ buttons->setDisabled(false);
+ screenColorPickerButton->setDisabled(false);
+}
+
void QColorDialogPrivate::init(const QColor &initial)
{
Q_Q(QColorDialog);
@@ -1473,9 +1692,25 @@
q->setSizeGripEnabled(false);
q->setWindowTitle(QColorDialog::tr("Select Color"));
- nativeDialogInUse = false;
+ // default: use the native dialog if possible. Can be overridden in setOptions()
+ nativeDialogInUse = (platformColorDialogHelper() != nullptr);
+ colorPickingEventFilter = nullptr;
+ nextCust = 0;
+
+ if (!nativeDialogInUse)
+ initWidgets();
- nextCust = 0;
+#ifdef Q_OS_WIN32
+ dummyTransparentWindow.resize(1, 1);
+ dummyTransparentWindow.setFlags(Qt::Tool | Qt::FramelessWindowHint);
+#endif
+
+ q->setCurrentColor(initial);
+}
+
+void QColorDialogPrivate::initWidgets()
+{
+ Q_Q(QColorDialog);
QVBoxLayout *mainLay = new QVBoxLayout(q);
// there's nothing in this dialog that benefits from sizing up
mainLay->setSizeConstraint(QLayout::SetFixedSize);
@@ -1483,48 +1718,23 @@
QHBoxLayout *topLay = new QHBoxLayout();
mainLay->addLayout(topLay);
- leftLay = 0;
+ leftLay = nullptr;
-#if defined(Q_WS_WINCE) || defined(QT_SMALL_COLORDIALOG)
+#if 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);
+ smallDisplay = (QGuiApplication::primaryScreen()->virtualGeometry().width() < 480 || QGuiApplication::primaryScreen()->virtualGeometry().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);
+ standard = new QColorWell(q, standardColorRows, colorColumns, QColorDialogOptions::standardColors());
lblBasicColors = new QLabel(q);
#ifndef QT_NO_SHORTCUT
lblBasicColors->setBuddy(standard);
@@ -1533,14 +1743,33 @@
leftLay->addWidget(lblBasicColors);
leftLay->addWidget(standard);
-#if !defined(Q_WS_WINCE)
- leftLay->addStretch();
+#if !defined(QT_SMALL_COLORDIALOG)
+ if (supportsColorPicking()) {
+ screenColorPickerButton = new QPushButton();
+ leftLay->addWidget(screenColorPickerButton);
+ lblScreenColorInfo = new QLabel("\n"_L1);
+ leftLay->addWidget(lblScreenColorInfo);
+ q->connect(screenColorPickerButton, SIGNAL(clicked()), SLOT(_q_pickScreenColor()));
+ } else {
+ screenColorPickerButton = nullptr;
+ lblScreenColorInfo = nullptr;
+ }
#endif
- custom = new QColorWell(q, 2, 8, cusrgb);
+ leftLay->addStretch();
+
+ custom = new QColorWell(q, customColorRows, colorColumns, QColorDialogOptions::customColors());
custom->setAcceptDrops(true);
q->connect(custom, SIGNAL(selected(int,int)), SLOT(_q_newCustom(int,int)));
+ q->connect(custom, SIGNAL(currentChanged(int,int)), SLOT(_q_nextCustom(int,int)));
+
+ q->connect(custom, &QWellArray::colorChanged, [this] (int index, QRgb color) {
+ QColorDialogOptions::setCustomColor(index, color);
+ if (custom)
+ custom->update();
+ });
+
lblCustomColors = new QLabel(q);
#ifndef QT_NO_SHORTCUT
lblCustomColors->setBuddy(custom);
@@ -1554,17 +1783,17 @@
} else {
// better color picker size for small displays
#if defined(QT_SMALL_COLORDIALOG)
- QSize screenSize = QApplication::desktop()->availableGeometry(QCursor::pos()).size();
+ QSize screenSize = QGuiApplication::screenAt(QCursor::pos())->availableGeometry().size();
pWidth = pHeight = qMin(screenSize.width(), screenSize.height());
pHeight -= 20;
- if(screenSize.height() > screenSize.width())
+ if (screenSize.height() > screenSize.width())
pWidth -= 20;
#else
pWidth = 150;
pHeight = 100;
#endif
- custom = 0;
- standard = 0;
+ custom = nullptr;
+ standard = nullptr;
}
QVBoxLayout *rightLay = new QVBoxLayout;
@@ -1577,15 +1806,10 @@
pickLay->addLayout(cLay);
cp = new QColorPicker(q);
- cp->setFrameStyle(QFrame::Panel + QFrame::Sunken);
+ cp->setFrameStyle(QFrame::Panel | QFrame::Sunken);
#if defined(QT_SMALL_COLORDIALOG)
- if (!nonTouchUI) {
- pickLay->addWidget(cp);
- cLay->addSpacing(lumSpace);
- } else {
- cp->hide();
- }
+ cp->hide();
#else
cLay->addSpacing(lumSpace);
cLay->addWidget(cp);
@@ -1594,18 +1818,12 @@
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();
+ lp->hide();
#else
lp->setFixedWidth(20);
+ pickLay->addSpacing(10);
pickLay->addWidget(lp);
+ pickLay->addStretch();
#endif
QObject::connect(cp, SIGNAL(newCol(int,int)), lp, SLOT(setCol(int,int)));
@@ -1614,15 +1832,16 @@
rightLay->addStretch();
cs = new QColorShower(q);
+ pickLay->setContentsMargins(cs->gl->contentsMargins());
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);
+ if (leftLay)
+ leftLay->addSpacing(cs->gl->contentsMargins().right());
#endif
buttons = new QDialogButtonBox(q);
@@ -1634,36 +1853,77 @@
cancel = buttons->addButton(QDialogButtonBox::Cancel);
QObject::connect(cancel, SIGNAL(clicked()), q, SLOT(reject()));
+#ifdef Q_OS_WIN32
+ updateTimer = new QTimer(q);
+ QObject::connect(updateTimer, SIGNAL(timeout()), q, SLOT(_q_updateColorPicking()));
+#endif
retranslateStrings();
+}
-#ifdef Q_WS_MAC
- delegate = 0;
-#endif
+void QColorDialogPrivate::initHelper(QPlatformDialogHelper *h)
+{
+ QColorDialog *d = q_func();
+ QObject::connect(h, SIGNAL(currentColorChanged(QColor)), d, SIGNAL(currentColorChanged(QColor)));
+ QObject::connect(h, SIGNAL(colorSelected(QColor)), d, SIGNAL(colorSelected(QColor)));
+ static_cast(h)->setOptions(options);
+}
- q->setCurrentColor(initial);
+void QColorDialogPrivate::helperPrepareShow(QPlatformDialogHelper *)
+{
+ options->setWindowTitle(q_func()->windowTitle());
}
void QColorDialogPrivate::_q_addCustom()
{
- cusrgb[nextCust] = cs->currentColor();
+ QColorDialogOptions::setCustomColor(nextCust, cs->currentColor());
if (custom)
custom->update();
- nextCust = (nextCust+1) % 16;
+ nextCust = (nextCust+1) % QColorDialogOptions::customColorCount();
}
void QColorDialogPrivate::retranslateStrings()
{
+ if (nativeDialogInUse)
+ return;
+
if (!smallDisplay) {
lblBasicColors->setText(QColorDialog::tr("&Basic colors"));
lblCustomColors->setText(QColorDialog::tr("&Custom colors"));
addCusBt->setText(QColorDialog::tr("&Add to Custom Colors"));
+#if !defined(QT_SMALL_COLORDIALOG)
+ if (screenColorPickerButton)
+ screenColorPickerButton->setText(QColorDialog::tr("&Pick Screen Color"));
+#endif
}
cs->retranslateStrings();
}
-static const Qt::WindowFlags DefaultWindowFlags =
- Qt::Dialog | Qt::WindowTitleHint | Qt::MSWindowsFixedSizeDialogHint
+bool QColorDialogPrivate::supportsColorPicking() const
+{
+ const auto integration = QGuiApplicationPrivate::platformIntegration();
+ return integration->hasCapability(QPlatformIntegration::ScreenWindowGrabbing)
+ || integration->services()->hasCapability(QPlatformServices::Capability::ColorPicking);
+}
+
+bool QColorDialogPrivate::canBeNativeDialog() const
+{
+ // Don't use Q_Q here! This function is called from ~QDialog,
+ // so Q_Q calling q_func() invokes undefined behavior (invalid cast in q_func()).
+ const QDialog * const q = static_cast(q_ptr);
+ if (nativeDialogInUse)
+ return true;
+ if (QCoreApplication::testAttribute(Qt::AA_DontUseNativeDialogs)
+ || q->testAttribute(Qt::WA_DontShowOnScreen)
+ || (options->options() & QColorDialog::DontUseNativeDialog)) {
+ return false;
+ }
+
+ return strcmp(QColorDialog::staticMetaObject.className(), q->metaObject()->className()) == 0;
+}
+
+static const Qt::WindowFlags qcd_DefaultWindowFlags =
+ Qt::Dialog | Qt::WindowTitleHint
| Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
/*!
@@ -1671,6 +1931,7 @@
\brief The QColorDialog class provides a dialog widget for specifying colors.
\ingroup standard-dialogs
+ \inmodule QtWidgets
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
@@ -1691,12 +1952,17 @@
during the execution of the program. Use setCustomColor() to set
the custom colors, and use customColor() to get them.
+ When pressing the "Pick Screen Color" button, the cursor changes to a haircross
+ and the colors on the screen are scanned. The user can pick up one by clicking
+ the mouse or the Enter button. Pressing Escape restores the last color selected
+ before entering this mode.
+
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.
+ \image fusion-colordialog.png A color dialog in the Fusion widget style.
- \sa QColor, QFileDialog, QPrintDialog, QFontDialog, {Standard Dialogs Example}
+ \sa QColor, QFileDialog, QFontDialog, {Standard Dialogs Example}
*/
/*!
@@ -1705,10 +1971,8 @@
Constructs a color dialog with the given \a parent.
*/
QColorDialog::QColorDialog(QWidget *parent)
- : QDialog(*new QColorDialogPrivate, parent, DefaultWindowFlags)
+ : QColorDialog(QColor(Qt::white), parent)
{
- Q_D(QColorDialog);
- d->init(Qt::white);
}
/*!
@@ -1718,12 +1982,27 @@
\a initial color.
*/
QColorDialog::QColorDialog(const QColor &initial, QWidget *parent)
- : QDialog(*new QColorDialogPrivate, parent, DefaultWindowFlags)
+ : QDialog(*new QColorDialogPrivate, parent, qcd_DefaultWindowFlags)
{
Q_D(QColorDialog);
d->init(initial);
}
+void QColorDialogPrivate::setCurrentColor(const QColor &color, SetColorMode setColorMode)
+{
+ if (nativeDialogInUse) {
+ platformColorDialogHelper()->setCurrentColor(color);
+ return;
+ }
+
+ if (setColorMode & ShowColor) {
+ setCurrentRgbColor(color.rgb());
+ setCurrentAlpha(color.alpha());
+ }
+ if (setColorMode & SelectColor)
+ selectColor(color);
+}
+
/*!
\property QColorDialog::currentColor
\brief the currently selected color in the dialog
@@ -1732,16 +2011,7 @@
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);
+ d->setCurrentColor(color);
}
QColor QColorDialog::currentColor() const
@@ -1750,9 +2020,8 @@
return d->currentQColor();
}
-
/*!
- Returns the color that the user selected by clicking the \gui{OK}
+ Returns the color that the user selected by clicking the \uicontrol{OK}
or equivalent button.
\note This color is not always the same as the color held by the
@@ -1773,15 +2042,15 @@
*/
void QColorDialog::setOption(ColorDialogOption option, bool on)
{
- Q_D(QColorDialog);
- if (!(d->opts & option) != !on)
- setOptions(d->opts ^ option);
+ const QColorDialog::ColorDialogOptions previousOptions = options();
+ if (!(previousOptions & option) != !on)
+ setOptions(previousOptions ^ option);
}
/*!
\since 4.5
- Returns true if the given \a option is enabled; otherwise, returns
+ Returns \c true if the given \a option is enabled; otherwise, returns
false.
\sa options, setOption()
@@ -1789,7 +2058,7 @@
bool QColorDialog::testOption(ColorDialogOption option) const
{
Q_D(const QColorDialog);
- return (d->opts & option) != 0;
+ return d->options->testOption(static_cast(option));
}
/*!
@@ -1808,19 +2077,24 @@
{
Q_D(QColorDialog);
- ColorDialogOptions changed = (options ^ d->opts);
- if (!changed)
+ if (QColorDialog::options() == options)
return;
- d->opts = options;
- d->buttons->setVisible(!(options & NoButtons));
- d->showAlpha(options & ShowAlphaChannel);
+ d->options->setOptions(QColorDialogOptions::ColorDialogOptions(int(options)));
+ if ((options & DontUseNativeDialog) && d->nativeDialogInUse) {
+ d->nativeDialogInUse = false;
+ d->initWidgets();
+ }
+ if (!d->nativeDialogInUse) {
+ d->buttons->setVisible(!(options & NoButtons));
+ d->showAlpha(options & ShowAlphaChannel);
+ }
}
QColorDialog::ColorDialogOptions QColorDialog::options() const
{
Q_D(const QColorDialog);
- return d->opts;
+ return QColorDialog::ColorDialogOptions(int(d->options->options()));
}
/*!
@@ -1832,9 +2106,9 @@
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 the operating system
- native color dialog.
+ \value NoButtons Don't display \uicontrol{OK} and \uicontrol{Cancel} buttons. (Useful for "live dialogs".)
+ \value DontUseNativeDialog Use Qt's standard color dialog instead of the operating system
+ native color dialog.
\sa options, setOption(), testOption(), windowModality()
*/
@@ -1848,15 +2122,10 @@
\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
+ This signal is emitted just after the user has clicked \uicontrol{OK} to
select a color to use. The chosen color is specified by \a color.
\sa color, currentColorChanged()
@@ -1868,51 +2137,45 @@
*/
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();
- QColorDialogPrivate::sharedColorPanelAvailable = true;
- 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
-
+ // will call QColorDialogPrivate::setVisible override
QDialog::setVisible(visible);
}
/*!
- \overload
+ \internal
+
+ The implementation of QColorDialog::setVisible() has to live here so that the call
+ to hide() in ~QDialog calls this function; it wouldn't call the override of
+ QDialog::setVisible().
+*/
+void QColorDialogPrivate::setVisible(bool visible)
+{
+ Q_Q(QColorDialog);
+ if (visible){
+ if (q->testAttribute(Qt::WA_WState_ExplicitShowHide) && !q->testAttribute(Qt::WA_WState_Hidden))
+ return;
+ } else if (q->testAttribute(Qt::WA_WState_ExplicitShowHide) && q->testAttribute(Qt::WA_WState_Hidden))
+ return;
+
+ if (visible)
+ selectedQColor = QColor();
+
+ if (nativeDialogInUse) {
+ if (setNativeDialogVisible(visible)) {
+ // Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below
+ // updates the state correctly, but skips showing the non-native version:
+ q->setAttribute(Qt::WA_DontShowOnScreen);
+ } else {
+ initWidgets();
+ }
+ } else {
+ q->setAttribute(Qt::WA_DontShowOnScreen, false);
+ }
+
+ QDialogPrivate::setVisible(visible);
+}
+
+/*!
\since 4.5
Opens the dialog and connects its colorSelected() signal to the slot specified
@@ -1930,22 +2193,6 @@
}
/*!
- \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
@@ -1954,19 +2201,10 @@
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);
@@ -1977,76 +2215,13 @@
}
/*!
- 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
*/
@@ -2058,6 +2233,67 @@
QDialog::changeEvent(e);
}
+void QColorDialogPrivate::_q_updateColorPicking()
+{
+#ifndef QT_NO_CURSOR
+ Q_Q(QColorDialog);
+ static QPoint lastGlobalPos;
+ QPoint newGlobalPos = QCursor::pos();
+ if (lastGlobalPos == newGlobalPos)
+ return;
+ lastGlobalPos = newGlobalPos;
+
+ if (!q->rect().contains(q->mapFromGlobal(newGlobalPos))) { // Inside the dialog mouse tracking works, handleColorPickingMouseMove will be called
+ updateColorPicking(newGlobalPos);
+#ifdef Q_OS_WIN32
+ dummyTransparentWindow.setPosition(newGlobalPos);
+#endif
+ }
+#endif // ! QT_NO_CURSOR
+}
+
+void QColorDialogPrivate::updateColorPicking(const QPoint &globalPos)
+{
+ const QColor color = grabScreenColor(globalPos);
+ // QTBUG-39792, do not change standard, custom color selectors while moving as
+ // otherwise it is not possible to pre-select a custom cell for assignment.
+ setCurrentColor(color, ShowColor);
+ updateColorLabelText(globalPos);
+}
+
+bool QColorDialogPrivate::handleColorPickingMouseMove(QMouseEvent *e)
+{
+ // If the cross is visible the grabbed color will be black most of the times
+ cp->setCrossVisible(!cp->geometry().contains(e->position().toPoint()));
+
+ updateColorPicking(e->globalPosition().toPoint());
+ return true;
+}
+
+bool QColorDialogPrivate::handleColorPickingMouseButtonRelease(QMouseEvent *e)
+{
+ setCurrentColor(grabScreenColor(e->globalPosition().toPoint()), SetColorAll);
+ releaseColorPicking();
+ return true;
+}
+
+bool QColorDialogPrivate::handleColorPickingKeyPress(QKeyEvent *e)
+{
+ Q_Q(QColorDialog);
+#if QT_CONFIG(shortcut)
+ if (e->matches(QKeySequence::Cancel)) {
+ releaseColorPicking();
+ q->setCurrentColor(beforeScreenColorPicking);
+ } else
+#endif
+ if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
+ q->setCurrentColor(grabScreenColor(QCursor::pos()));
+ releaseColorPicking();
+ }
+ e->accept();
+ return true;
+}
+
/*!
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,
@@ -2068,17 +2304,17 @@
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();
}
+ QDialog::done(result);
if (d->receiverToDisconnectOnClose) {
disconnect(this, SIGNAL(colorSelected(QColor)),
d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);
- d->receiverToDisconnectOnClose = 0;
+ d->receiverToDisconnectOnClose = nullptr;
}
d->memberToDisconnectOnClose.clear();
}
@@ -2087,15 +2323,3 @@
#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 -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qt/qdialog.cpp
--- a/libgui/languages/build_ts/octave-qt/qdialog.cpp Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qt/qdialog.cpp Mon Dec 04 19:55:32 2023 +0100
@@ -1,110 +1,204 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-#include "qdialog.h"
-
+#include
+#if QT_CONFIG(colordialog)
+#include "qcolordialog.h"
+#endif
+#if QT_CONFIG(fontdialog)
+#include "qfontdialog.h"
+#endif
+#if QT_CONFIG(filedialog)
+#include "qfiledialog.h"
+#endif
#include "qevent.h"
-#include "qdesktopwidget.h"
-#include "qpushbutton.h"
#include "qapplication.h"
#include "qlayout.h"
+#if QT_CONFIG(sizegrip)
#include "qsizegrip.h"
+#endif
+#if QT_CONFIG(whatsthis)
#include "qwhatsthis.h"
+#endif
+#if QT_CONFIG(menu)
#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"
-#elif defined(Q_OS_BLACKBERRY)
-# include "qmessagebox.h"
+#include "qcursor.h"
+#if QT_CONFIG(messagebox)
+#include "qmessagebox.h"
#endif
-
-#if defined(Q_WS_S60)
-#include // AknLayoutUtils
+#if QT_CONFIG(errormessage)
+#include "qerrormessage.h"
#endif
-
-#ifndef SPI_GETSNAPTODEFBUTTON
-# define SPI_GETSNAPTODEFBUTTON 95
+#include
+#include "private/qdialog_p.h"
+#include "private/qguiapplication_p.h"
+#if QT_CONFIG(accessibility)
+#include "qaccessible.h"
#endif
QT_BEGIN_NAMESPACE
+static inline int themeDialogType(const QDialog *dialog)
+{
+#if QT_CONFIG(filedialog)
+ if (qobject_cast(dialog))
+ return QPlatformTheme::FileDialog;
+#endif
+#if QT_CONFIG(colordialog)
+ if (qobject_cast(dialog))
+ return QPlatformTheme::ColorDialog;
+#endif
+#if QT_CONFIG(fontdialog)
+ if (qobject_cast(dialog))
+ return QPlatformTheme::FontDialog;
+#endif
+#if QT_CONFIG(messagebox)
+ if (qobject_cast(dialog))
+ return QPlatformTheme::MessageDialog;
+#endif
+#if QT_CONFIG(errormessage)
+ if (qobject_cast(dialog))
+ return QPlatformTheme::MessageDialog;
+#endif
+#if !QT_CONFIG(filedialog) && !QT_CONFIG(colordialog) && !QT_CONFIG(fontdialog) && \
+ !QT_CONFIG(messagebox) && !QT_CONFIG(errormessage)
+ Q_UNUSED(dialog);
+#endif
+ return -1;
+}
+
+QDialogPrivate::~QDialogPrivate()
+{
+ delete m_platformHelper;
+}
+
+QPlatformDialogHelper *QDialogPrivate::platformHelper() const
+{
+ // Delayed creation of the platform, ensuring that
+ // that qobject_cast<> on the dialog works in the plugin.
+ if (!m_platformHelperCreated && canBeNativeDialog()) {
+ m_platformHelperCreated = true;
+ QDialogPrivate *ncThis = const_cast(this);
+ QDialog *dialog = ncThis->q_func();
+ const int type = themeDialogType(dialog);
+ if (type >= 0) {
+ m_platformHelper = QGuiApplicationPrivate::platformTheme()
+ ->createPlatformDialogHelper(static_cast(type));
+ if (m_platformHelper) {
+ QObject::connect(m_platformHelper, SIGNAL(accept()), dialog, SLOT(accept()));
+ QObject::connect(m_platformHelper, SIGNAL(reject()), dialog, SLOT(reject()));
+ ncThis->initHelper(m_platformHelper);
+ }
+ }
+ }
+ return m_platformHelper;
+}
+
+bool QDialogPrivate::canBeNativeDialog() const
+{
+ if (QCoreApplication::testAttribute(Qt::AA_DontUseNativeDialogs))
+ return false;
+
+ QDialogPrivate *ncThis = const_cast(this);
+ QDialog *dialog = ncThis->q_func();
+ const int type = themeDialogType(dialog);
+ if (type >= 0)
+ return QGuiApplicationPrivate::platformTheme()
+ ->usePlatformNativeDialog(static_cast(type));
+ return false;
+}
+
+/*!
+ \internal
+
+ Properly closes dialog and sets the \a resultCode.
+ */
+void QDialogPrivate::close(int resultCode)
+{
+ Q_Q(QDialog);
+
+ q->setResult(resultCode);
+
+ if (!data.is_closing) {
+ // Until Qt 6.3 we didn't close dialogs, so they didn't receive a QCloseEvent.
+ // It is likely that subclasses implement closeEvent and handle them as rejection
+ // (like QMessageBox and QProgressDialog do), so eat those events.
+ struct CloseEventEater : QObject
+ {
+ using QObject::QObject;
+ protected:
+ bool eventFilter(QObject *o, QEvent *e) override
+ {
+ if (e->type() == QEvent::Close)
+ return true;
+ return QObject::eventFilter(o, e);
+ }
+ } closeEventEater;
+ q->installEventFilter(&closeEventEater);
+ QWidgetPrivate::close();
+ } else {
+ // If the close was initiated outside of QDialog we will end up
+ // here via QDialog::closeEvent calling reject(), in which case
+ // we need to hide the dialog to ensure QDialog::closeEvent does
+ // not ignore the close event. FIXME: Why is QDialog doing this?
+ q->hide();
+ }
+
+ resetModalitySetByOpen();
+}
+
+QWindow *QDialogPrivate::transientParentWindow() const
+{
+ Q_Q(const QDialog);
+ if (const QWidget *parent = q->nativeParentWidget())
+ return parent->windowHandle();
+ else if (q->windowHandle())
+ return q->windowHandle()->transientParent();
+ return nullptr;
+}
+
+bool QDialogPrivate::setNativeDialogVisible(bool visible)
+{
+ if (QPlatformDialogHelper *helper = platformHelper()) {
+ if (visible) {
+ Q_Q(QDialog);
+ helperPrepareShow(helper);
+ nativeDialogInUse = helper->show(q->windowFlags(), q->windowModality(), transientParentWindow());
+ } else if (nativeDialogInUse) {
+ helper->hide();
+ }
+ }
+ return nativeDialogInUse;
+}
+
+QVariant QDialogPrivate::styleHint(QPlatformDialogHelper::StyleHint hint) const
+{
+ if (const QPlatformDialogHelper *helper = platformHelper())
+ return helper->styleHint(hint);
+ return QPlatformDialogHelper::defaultStyleHint(hint);
+}
+
/*!
\class QDialog
\brief The QDialog class is the base class of dialog windows.
\ingroup dialog-classes
\ingroup abstractwidgets
-
+ \inmodule QtWidgets
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
+ provide a \l{#return}{return value}, and they can have \l{#default}{default buttons}. QDialogs can also have a QSizeGrip in their
lower-right corner, using setSizeGripEnabled().
Note that QDialog (and any other widget that has type \c 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.
+ 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
@@ -113,9 +207,16 @@
window-system properties for the widget (in particular it will
reset the Qt::Dialog flag).
+ \note The parent relationship of the dialog does \e{not} imply
+ that the dialog will always be stacked on top of the parent
+ window. To ensure that the dialog is always on top, make the
+ dialog modal. This also applies for child windows of the dialog
+ itself. To ensure that child windows of the dialog stay on top
+ of the dialog, make the child windows modal as well.
+
\section1 Modal Dialogs
- A \bold{modal} dialog is a dialog that blocks input to other
+ A \b{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
@@ -130,12 +231,11 @@
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.
+ provide a useful \l{#return}{return value}. To close the dialog
+ and return the appropriate value, you must connect a default button,
+ e.g. an \uicontrol OK button to the accept() slot and a
+ \uicontrol 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
@@ -143,13 +243,13 @@
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
+ you must call QCoreApplication::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
+ A \b{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
@@ -180,9 +280,8 @@
\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.
+ will be called. This will cause the window to close:
+ The \l{QCloseEvent}{close event} cannot be \l{QEvent::ignore()}{ignored}.
\section1 Extensibility
@@ -190,16 +289,15 @@
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.
+ \uicontrol More toggle button. If the user presses the
+ \uicontrol More button down, the dialog is expanded.
\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
+ required, e.g. to indicate whether the user pressed \uicontrol OK or
+ \uicontrol 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
@@ -216,14 +314,17 @@
A modal dialog:
- \snippet doc/src/snippets/dialogs/dialogs.cpp 1
+ \snippet dialogs/dialogs.cpp 1
A modeless dialog:
- \snippet doc/src/snippets/dialogs/dialogs.cpp 0
+ \snippet dialogs/dialogs.cpp 0
+
+ A dialog with an extension:
+
+ \snippet dialogs/dialogs.cpp extension
\sa QDialogButtonBox, QTabWidget, QWidget, QProgressDialog,
- {fowler}{GUI Design Handbook: Dialogs, Standard}, {Extension Example},
{Standard Dialogs Example}
*/
@@ -262,36 +363,8 @@
: 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
@@ -299,18 +372,6 @@
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
}
/*!
@@ -331,10 +392,11 @@
/*!
\internal
This function is called by the push button \a pushButton when it
- becomes the default button. If \a pushButton is 0, the dialogs
+ becomes the default button. If \a pushButton is \nullptr, the dialogs
default default button becomes the default button. This is what a
push button calls when it loses focus.
*/
+#if QT_CONFIG(pushbutton)
void QDialogPrivate::setDefault(QPushButton *pushButton)
{
Q_Q(QDialog);
@@ -362,7 +424,7 @@
*/
void QDialogPrivate::setMainDefault(QPushButton *pushButton)
{
- mainDef = 0;
+ mainDef = nullptr;
setDefault(pushButton);
}
@@ -379,6 +441,7 @@
list.at(i)->setDefault(false);
}
}
+#endif
void QDialogPrivate::resetModalitySetByOpen()
{
@@ -387,7 +450,7 @@
// 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
+#ifdef Q_OS_MAC
Q_ASSERT(resetModalityTo != Qt::WindowModal);
q->setParent(q->parentWidget(), Qt::Dialog);
#endif
@@ -395,46 +458,12 @@
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
+/*!
+ In general returns the modal dialog's result code, \c Accepted or
+ \c Rejected.
-/*!
- \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
-
-/*!
- In general returns the modal dialog's result code, \c Accepted or \c Rejected.
-
- \note When used from QMessageBox instance the result code type is \l QMessageBox::StandardButton
+ \note When called on a QMessageBox instance, the returned value is a
+ value of the \l QMessageBox::StandardButton enum.
Do not call this function if the dialog was constructed with the
Qt::WA_DeleteOnClose attribute.
@@ -477,7 +506,7 @@
d->wasModalitySet = testAttribute(Qt::WA_SetWindowModality);
setWindowModality(Qt::WindowModal);
setAttribute(Qt::WA_SetWindowModality, false);
-#ifdef Q_WS_MAC
+#ifdef Q_OS_MAC
setParent(parentWidget(), Qt::Sheet);
#endif
}
@@ -497,6 +526,13 @@
interaction with the parent window is blocked while the dialog is open.
By default, the dialog is application modal.
+ \note Avoid using this function; instead, use \c{open()}. Unlike exec(),
+ open() is asynchronous, and does not spin an additional event loop. This
+ prevents a series of dangerous bugs from happening (e.g. deleting the
+ dialog's parent while the dialog is open via exec()). When using open() you
+ can connect to the finished() signal of QDialog to be notified when the
+ dialog is closed.
+
\sa open(), show(), result(), setWindowModality()
*/
@@ -504,7 +540,7 @@
{
Q_D(QDialog);
- if (d->eventLoop) {
+ if (Q_UNLIKELY(d->eventLoop)) {
qWarning("QDialog::exec: Recursive call detected");
return -1;
}
@@ -518,101 +554,71 @@
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())
- 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(this) || qobject_cast(this) ||
- qobject_cast(this)) {
- showSystemDialogFullScreen = true;
- }
-#endif // Q_OS_SYMBIAN
-
-#ifdef Q_OS_BLACKBERRY
- if (!qobject_cast(this))
- showSystemDialogFullScreen = true;
-#endif // Q_OS_BLACKBERRY
-
- if (showSystemDialogFullScreen) {
- setWindowFlags(windowFlags() | Qt::WindowSoftkeysVisibleHint);
- setWindowState(Qt::WindowFullScreen);
- }
show();
-#ifdef Q_WS_MAC
- d->mac_nativeDialogModalHelp();
-#endif
-
- QEventLoop eventLoop;
- d->eventLoop = &eventLoop;
QPointer guard = this;
- () eventLoop.exec(QEventLoop::DialogExec);
+ if (d->nativeDialogInUse) {
+ d->platformHelper()->exec();
+ } else {
+ QEventLoop eventLoop;
+ d->eventLoop = &eventLoop;
+ (void) eventLoop.exec(QEventLoop::DialogExec);
+ }
if (guard.isNull())
return QDialog::Rejected;
- d->eventLoop = 0;
+ d->eventLoop = nullptr;
setAttribute(Qt::WA_ShowModal, wasShowModal);
int res = result();
+ if (d->nativeDialogInUse)
+ d->helperDone(static_cast(res), d->platformHelper());
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. The finished() signal
+ will emit \a r; if \a r is QDialog::Accepted or QDialog::Rejected, the
+ accepted() or the rejected() signals will also be emitted, respectively.
-/*!
- 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.
+ If this dialog is shown with exec(), done() also 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
+ last window closed, the QGuiApplication::lastWindowClosed() signal is
emitted.
- \sa accept(), reject(), QApplication::activeWindow(), QApplication::quit()
+ \sa accept(), reject(), QApplication::activeWindow(), QCoreApplication::quit()
*/
void QDialog::done(int r)
{
+ QPointer guard(this);
+
Q_D(QDialog);
- hide();
- setResult(r);
+ d->close(r);
+
+ if (!guard)
+ return;
- d->close_helper(QWidgetPrivate::CloseNoEvent);
- d->resetModalitySetByOpen();
+ int dialogCode = d->dialogCode();
+ if (dialogCode == QDialog::Accepted)
+ emit accepted();
+ else if (dialogCode == QDialog::Rejected)
+ emit rejected();
- emit finished(r);
- if (r == Accepted)
- emit accepted();
- else if (r == Rejected)
- emit rejected();
+ if (guard)
+ emit finished(r);
}
/*!
Hides the modal dialog and sets the result code to \c Accepted.
- \sa reject() done()
+ \sa reject(), done()
*/
void QDialog::accept()
@@ -623,7 +629,7 @@
/*!
Hides the modal dialog and sets the result code to \c Rejected.
- \sa accept() done()
+ \sa accept(), done()
*/
void QDialog::reject()
@@ -645,24 +651,24 @@
/*! \reimp */
void QDialog::contextMenuEvent(QContextMenuEvent *e)
{
-#if defined(QT_NO_WHATSTHIS) || defined(QT_NO_MENU)
+#if !QT_CONFIG(whatsthis) || !QT_CONFIG(menu)
Q_UNUSED(e);
#else
QWidget *w = childAt(e->pos());
if (!w) {
- w = rect().contains(e->pos()) ? this : 0;
+ w = rect().contains(e->pos()) ? this : nullptr;
if (!w)
return;
}
while (w && w->whatsThis().size() == 0 && !w->testAttribute(Qt::WA_CustomWhatsThis))
- w = w->isWindow() ? 0 : w->parentWidget();
+ w = w->isWindow() ? nullptr : w->parentWidget();
if (w) {
- QWeakPointer p = new QMenu(this);
+ QPointer 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);
+ QCoreApplication::sendEvent(w, &e);
}
delete p.data();
}
@@ -673,16 +679,17 @@
/*! \reimp */
void QDialog::keyPressEvent(QKeyEvent *e)
{
+#ifndef QT_NO_SHORTCUT
// 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) {
+ if (e->matches(QKeySequence::Cancel)) {
reject();
} else
#endif
if (!e->modifiers() || (e->modifiers() & Qt::KeypadModifier && e->key() == Qt::Key_Enter)) {
switch (e->key()) {
+#if QT_CONFIG(pushbutton)
case Qt::Key_Enter:
case Qt::Key_Return: {
QList list = findChildren();
@@ -696,9 +703,7 @@
}
}
break;
- case Qt::Key_Escape:
- reject();
- break;
+#endif
default:
e->ignore();
return;
@@ -711,7 +716,7 @@
/*! \reimp */
void QDialog::closeEvent(QCloseEvent *e)
{
-#ifndef QT_NO_WHATSTHIS
+#if QT_CONFIG(whatsthis)
if (isModal() && QWhatsThis::inWhatsThisMode())
QWhatsThis::leaveWhatsThisMode();
#endif
@@ -735,81 +740,109 @@
void QDialog::setVisible(bool visible)
{
Q_D(QDialog);
+ d->setVisible(visible);
+}
+
+void QDialogPrivate::setVisible(bool visible)
+{
+ Q_Q(QDialog);
+ if (!q->testAttribute(Qt::WA_DontShowOnScreen) && canBeNativeDialog() && setNativeDialogVisible(visible))
+ return;
+
+ // We should not block windows by the invisible modal dialog
+ // if a platform-specific dialog is implemented as an in-process
+ // Qt window, because in this case it will also be blocked.
+ const bool dontBlockWindows = q->testAttribute(Qt::WA_DontShowOnScreen)
+ && styleHint(QPlatformDialogHelper::DialogIsQtWindow).toBool();
+ Qt::WindowModality oldModality;
+ bool wasModalitySet;
+
+ if (dontBlockWindows) {
+ oldModality = q->windowModality();
+ wasModalitySet = q->testAttribute(Qt::WA_SetWindowModality);
+ q->setWindowModality(Qt::NonModal);
+ }
+
if (visible) {
- if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden))
+ if (q->testAttribute(Qt::WA_WState_ExplicitShowHide) && !q->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;
+ q->QWidget::setVisible(visible);
+
+ // Window activation might be prevented. We can't test isActiveWindow here,
+ // as the window will be activated asynchronously by the window manager.
+ if (!q->testAttribute(Qt::WA_ShowWithoutActivating)) {
+ QWidget *fw = q->window()->focusWidget();
+ if (!fw)
+ fw = q;
- /*
- 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(first))
- d->mainDef->setFocus();
- }
- if (!d->mainDef && isWindow()) {
- QWidget *w = fw;
- while ((w = w->nextInFocusChain()) != fw) {
- QPushButton *pb = qobject_cast(w);
- if (pb && pb->autoDefault() && pb->focusPolicy() != Qt::NoFocus) {
- pb->setDefault(true);
- break;
+ /*
+ The following block is to handle a special case, and does not
+ really follow proper 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 QT_CONFIG(pushbutton)
+ if (mainDef && fw->focusPolicy() == Qt::NoFocus) {
+ QWidget *first = fw;
+ while ((first = first->nextInFocusChain()) != fw && first->focusPolicy() == Qt::NoFocus)
+ ;
+ if (first != mainDef && qobject_cast(first))
+ mainDef->setFocus();
+ }
+ if (!mainDef && q->isWindow()) {
+ QWidget *w = fw;
+ while ((w = w->nextInFocusChain()) != fw) {
+ QPushButton *pb = qobject_cast(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);
+#endif
+ if (fw && !fw->hasFocus()) {
+ QFocusEvent e(QEvent::FocusIn, Qt::TabFocusReason);
+ QCoreApplication::sendEvent(fw, &e);
+ }
}
-#ifndef QT_NO_ACCESSIBILITY
- QAccessible::updateAccessibility(this, 0, QAccessible::DialogStart);
+#if QT_CONFIG(accessibility)
+ QAccessibleEvent event(q, QAccessible::DialogStart);
+ QAccessible::updateAccessibility(&event);
#endif
} else {
- if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden))
+ if (q->testAttribute(Qt::WA_WState_ExplicitShowHide) && q->testAttribute(Qt::WA_WState_Hidden))
return;
-#ifndef QT_NO_ACCESSIBILITY
- if (isVisible())
- QAccessible::updateAccessibility(this, 0, QAccessible::DialogEnd);
+#if QT_CONFIG(accessibility)
+ if (q->isVisible()) {
+ QAccessibleEvent event(q, QAccessible::DialogEnd);
+ QAccessible::updateAccessibility(&event);
+ }
#endif
// Reimplemented to exit a modal event loop when the dialog is hidden.
- QWidget::setVisible(visible);
- if (d->eventLoop)
- d->eventLoop->exit();
+ q->QWidget::setVisible(visible);
+ if (eventLoop)
+ 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()));
- }
+
+ if (dontBlockWindows) {
+ q->setWindowModality(oldModality);
+ q->setAttribute(Qt::WA_SetWindowModality, wasModalitySet);
}
+
+#if QT_CONFIG(pushbutton)
+ const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
+ if (mainDef && q->isActiveWindow()
+ && theme->themeHint(QPlatformTheme::DialogSnapToDefaultButton).toBool())
+ QCursor::setPos(mainDef->mapToGlobal(mainDef->rect().center()));
#endif
}
@@ -828,31 +861,31 @@
/*! \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
+ Q_D(QDialog);
-#ifdef Q_OS_SYMBIAN
- if (symbianAdjustedPosition())
- //dialog has already been positioned
- return;
-#endif
-
+ if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
+ if (theme->themeHint(QPlatformTheme::WindowAutoPlacement).toBool())
+ return;
QPoint p(0, 0);
- int extraw = 0, extrah = 0, scrn = 0;
- if (w)
- w = w->window();
- QRect desk;
+ int extraw = 0, extrah = 0;
+ const QWindow *parentWindow = nullptr;
if (w) {
- scrn = QApplication::desktop()->screenNumber(w);
- } else if (QApplication::desktop()->isVirtualDesktop()) {
- scrn = QApplication::desktop()->screenNumber(QCursor::pos());
+ w = w->window();
} else {
- scrn = QApplication::desktop()->screenNumber(this);
+ parentWindow = d->transientParentWindow();
}
- desk = QApplication::desktop()->availableGeometry(scrn);
+ QRect desk;
+ QScreen *scrn = nullptr;
+ if (w)
+ scrn = w->screen();
+ else if (parentWindow)
+ scrn = parentWindow->screen();
+ else if (QGuiApplication::primaryScreen()->virtualSiblings().size() > 1)
+ scrn = QGuiApplication::screenAt(QCursor::pos());
+ else
+ scrn = screen();
+ if (scrn)
+ desk = scrn->availableGeometry();
QWidgetList list = QApplication::topLevelWidgets();
for (int i = 0; (extraw == 0 || extrah == 0) && i < list.size(); ++i) {
@@ -875,11 +908,19 @@
if (w) {
- // Use mapToGlobal rather than geometry() in case w might
- // be embedded in another application
- QPoint pp = w->mapToGlobal(QPoint(0,0));
+ // Use pos() if the widget is embedded into a native window
+ QPoint pp;
+ if (w->windowHandle() && qvariant_cast(w->windowHandle()->property("_q_embedded_native_parent_handle")))
+ pp = w->pos();
+ else
+ pp = w->mapToGlobal(QPoint(0,0));
p = QPoint(pp.x() + w->width()/2,
pp.y() + w->height()/ 2);
+ } else if (parentWindow) {
+ // QTBUG-63406: Widget-based dialog in QML, which has no Widget parent
+ // but a transient parent window.
+ QPoint pp = parentWindow->mapToGlobal(QPoint(0, 0));
+ p = QPoint(pp.x() + parentWindow->width() / 2, pp.y() + parentWindow->height() / 2);
} else {
// p = middle of the desktop
p = QPoint(desk.x() + desk.width()/2, desk.y() + desk.height()/2);
@@ -900,226 +941,17 @@
if (p.y() < desk.y())
p.setY(desk.y());
+ // QTBUG-52735: Manually set the correct target screen since scaling in a
+ // subsequent call to QWindow::resize() may otherwise use the wrong factor
+ // if the screen changed notification is still in an event queue.
+ if (scrn) {
+ if (QWindow *window = windowHandle())
+ window->setScreen(scrn);
+ }
+
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);
- // In some native layouts, StaCon is not used. Try to fetch the status pane
- // height from StatusPane component.
- if (statusPaneRect.IsEmpty())
- AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EStatusPane, 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
{
@@ -1132,17 +964,7 @@
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
}
@@ -1166,8 +988,8 @@
\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
+ By default, this property is \c false and show() pops up the dialog
+ as modeless. Setting this property to true is equivalent to setting
QWidget::windowModality to Qt::ApplicationModal.
exec() ignores the value of this property and always pops up the
@@ -1184,7 +1006,7 @@
bool QDialog::isSizeGripEnabled() const
{
-#ifndef QT_NO_SIZEGRIP
+#if QT_CONFIG(sizegrip)
Q_D(const QDialog);
return !!d->resizer;
#else
@@ -1195,11 +1017,11 @@
void QDialog::setSizeGripEnabled(bool enabled)
{
-#ifdef QT_NO_SIZEGRIP
+#if !QT_CONFIG(sizegrip)
Q_UNUSED(enabled);
#else
Q_D(QDialog);
-#ifndef QT_NO_SIZEGRIP
+#if QT_CONFIG(sizegrip)
d->sizeGripEnabled = enabled;
if (enabled && d->doShowExtension)
return;
@@ -1217,10 +1039,10 @@
d->resizer->show();
} else {
delete d->resizer;
- d->resizer = 0;
+ d->resizer = nullptr;
}
}
-#endif //QT_NO_SIZEGRIP
+#endif // QT_CONFIG(sizegrip)
}
@@ -1228,7 +1050,7 @@
/*! \reimp */
void QDialog::resizeEvent(QResizeEvent *)
{
-#ifndef QT_NO_SIZEGRIP
+#if QT_CONFIG(sizegrip)
Q_D(QDialog);
if (d->resizer) {
if (isRightToLeft())
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qt/qdialogbuttonbox.cpp
--- a/libgui/languages/build_ts/octave-qt/qdialogbuttonbox.cpp Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qt/qdialogbuttonbox.cpp Mon Dec 04 19:55:32 2023 +0100
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include
#include
@@ -47,9 +11,10 @@
#include
#include
#include
-#include
+#include
#include "qdialogbuttonbox.h"
+#include "qdialogbuttonbox_p.h"
QT_BEGIN_NAMESPACE
@@ -89,7 +54,7 @@
the buttons (or button texts) yourself and add them to the button box,
specifying their role.
- \snippet dialogs/extension/finddialog.cpp 1
+ \snippet dialogs/dialogs.cpp buttonbox
Alternatively, QDialogButtonBox provides several standard buttons (e.g. OK, Cancel, Save)
that you can use. They exist as flags so you can OR them together in the constructor.
@@ -147,39 +112,25 @@
\sa QMessageBox, QPushButton, QDialog
*/
-
-class QDialogButtonBoxPrivate : public QWidgetPrivate
+QDialogButtonBoxPrivate::QDialogButtonBoxPrivate(Qt::Orientation orient)
+ : orientation(orient), buttonLayout(nullptr), center(false)
{
- Q_DECLARE_PUBLIC(QDialogButtonBox)
-
-public:
- QDialogButtonBoxPrivate(Qt::Orientation orient);
-
- QList buttonLists[QDialogButtonBox::NRoles];
- QHash standardButtonHash;
-
- Qt::Orientation orientation;
- QDialogButtonBox::ButtonLayout layoutPolicy;
- QBoxLayout *buttonLayout;
- bool internalRemove;
- bool center;
+ struct EventFilter : public QObject
+ {
+ EventFilter(QDialogButtonBoxPrivate *d) : d(d) {};
- void createStandardButtons(QDialogButtonBox::StandardButtons buttons);
+ bool eventFilter(QObject *obj, QEvent *event) override
+ {
+ QAbstractButton *button = qobject_cast(obj);
+ return button ? d->handleButtonShowAndHide(button, event) : false;
+ }
- void layoutButtons();
- void initLayout();
- void resetLayout();
- QPushButton *createButton(QDialogButtonBox::StandardButton button, bool doLayout = true);
- void addButton(QAbstractButton *button, QDialogButtonBox::ButtonRole role, bool doLayout = true);
- void _q_handleButtonDestroyed();
- void _q_handleButtonClicked();
- void addButtonsToLayout(const QList &buttonList, bool reverse);
- void retranslateStrings();
-};
+ private:
+ QDialogButtonBoxPrivate *d;
-QDialogButtonBoxPrivate::QDialogButtonBoxPrivate(Qt::Orientation orient)
- : orientation(orient), buttonLayout(nullptr), internalRemove(false), center(false)
-{
+ };
+
+ filter.reset(new EventFilter(this));
}
void QDialogButtonBoxPrivate::initLayout()
@@ -213,7 +164,6 @@
void QDialogButtonBoxPrivate::resetLayout()
{
- //delete buttonLayout;
initLayout();
layoutButtons();
}
@@ -221,8 +171,8 @@
void QDialogButtonBoxPrivate::addButtonsToLayout(const QList &buttonList,
bool reverse)
{
- int start = reverse ? buttonList.count() - 1 : 0;
- int end = reverse ? -1 : buttonList.count();
+ int start = reverse ? buttonList.size() - 1 : 0;
+ int end = reverse ? -1 : buttonList.size();
int step = reverse ? -1 : 1;
for (int i = start; i != end; i += step) {
@@ -237,6 +187,7 @@
Q_Q(QDialogButtonBox);
const int MacGap = 36 - 8; // 8 is the default gap between a widget and a spacer item
+ QBoolBlocker blocker(ignoreShowAndHide);
for (int i = buttonLayout->count() - 1; i >= 0; --i) {
QLayoutItem *item = buttonLayout->takeAt(i);
if (QWidget *widget = item->widget())
@@ -347,7 +298,7 @@
}
QPushButton *QDialogButtonBoxPrivate::createButton(QDialogButtonBox::StandardButton sbutton,
- bool doLayout)
+ LayoutRule layoutRule)
{
Q_Q(QDialogButtonBox);
int icon = 0;
@@ -422,7 +373,7 @@
if (Q_UNLIKELY(role == QPlatformDialogHelper::InvalidRole))
qWarning("QDialogButtonBox::createButton: Invalid ButtonRole, button not added");
else
- addButton(button, static_cast(role), doLayout);
+ addButton(button, static_cast(role), layoutRule);
#if QT_CONFIG(shortcut)
const QKeySequence standardShortcut = QGuiApplicationPrivate::platformTheme()->standardButtonShortcut(sbutton);
if (!standardShortcut.isEmpty())
@@ -432,23 +383,36 @@
}
void QDialogButtonBoxPrivate::addButton(QAbstractButton *button, QDialogButtonBox::ButtonRole role,
- bool doLayout)
+ LayoutRule layoutRule, AddRule addRule)
{
- Q_Q(QDialogButtonBox);
- QObject::connect(button, SIGNAL(clicked()), q, SLOT(_q_handleButtonClicked()));
- QObject::connect(button, SIGNAL(destroyed()), q, SLOT(_q_handleButtonDestroyed()));
buttonLists[role].append(button);
- if (doLayout)
+ switch (addRule) {
+ case AddRule::Connect:
+ QObjectPrivate::connect(button, &QAbstractButton::clicked,
+ this, &QDialogButtonBoxPrivate::handleButtonClicked);
+ QObjectPrivate::connect(button, &QAbstractButton::destroyed,
+ this, &QDialogButtonBoxPrivate::handleButtonDestroyed);
+ button->installEventFilter(filter.get());
+ break;
+ case AddRule::SkipConnect:
+ break;
+ }
+
+ switch (layoutRule) {
+ case LayoutRule::DoLayout:
layoutButtons();
+ break;
+ case LayoutRule::SkipLayout:
+ break;
+ }
}
void QDialogButtonBoxPrivate::createStandardButtons(QDialogButtonBox::StandardButtons buttons)
{
uint i = QDialogButtonBox::FirstButton;
while (i <= QDialogButtonBox::LastButton) {
- if (i & buttons) {
- createButton(QDialogButtonBox::StandardButton(i), false);
- }
+ if (i & buttons)
+ createButton(QDialogButtonBox::StandardButton(i), LayoutRule::SkipLayout);
i = i << 1;
}
layoutButtons();
@@ -456,13 +420,10 @@
void QDialogButtonBoxPrivate::retranslateStrings()
{
- typedef QHash::iterator Iterator;
-
- const Iterator end = standardButtonHash.end();
- for (Iterator it = standardButtonHash.begin(); it != end; ++it) {
- const QString text = QGuiApplicationPrivate::platformTheme()->standardButtonText(it.value());
+ for (auto &&[key, value] : std::as_const(standardButtonHash).asKeyValueRange()) {
+ const QString text = QGuiApplicationPrivate::platformTheme()->standardButtonText(value);
if (!text.isEmpty())
- it.key()->setText(text);
+ key->setText(text);
}
}
@@ -518,12 +479,20 @@
*/
QDialogButtonBox::~QDialogButtonBox()
{
+ Q_D(QDialogButtonBox);
+
+ d->ignoreShowAndHide = true;
+
+ // QObjectPrivate::connect requires explicit disconnect in destructor
+ // otherwise the connection may kick in on child destruction and reach
+ // the parent's destroyed private object
+ d->disconnectAll();
}
/*!
\enum QDialogButtonBox::ButtonRole
- \enum QMessageBox::ButtonRole
+//! [buttonrole-enum]
This enum describes the roles that can be used to describe buttons in
the button box. Combinations of these roles are as flags used to
describe different aspects of their behavior.
@@ -546,6 +515,7 @@
\omitvalue NRoles
\sa StandardButton
+//! [buttonrole-enum]
*/
/*!
@@ -671,34 +641,45 @@
d->standardButtonHash.clear();
for (int i = 0; i < NRoles; ++i) {
QList &list = d->buttonLists[i];
- while (list.count()) {
+ while (list.size()) {
QAbstractButton *button = list.takeAt(0);
- QObject::disconnect(button, SIGNAL(destroyed()), this, SLOT(_q_handleButtonDestroyed()));
+ QObjectPrivate::disconnect(button, &QAbstractButton::destroyed,
+ d, &QDialogButtonBoxPrivate::handleButtonDestroyed);
delete button;
}
}
}
/*!
- Returns a list of all the buttons that have been added to the button box.
+ Returns a list of all buttons that have been added to the button box.
\sa buttonRole(), addButton(), removeButton()
*/
QList QDialogButtonBox::buttons() const
{
Q_D(const QDialogButtonBox);
+ return d->allButtons();
+}
+
+QList QDialogButtonBoxPrivate::visibleButtons() const
+{
QList finalList;
- for (int i = 0; i < NRoles; ++i) {
- const QList &list = d->buttonLists[i];
- for (int j = 0; j < list.count(); ++j)
+ for (int i = 0; i < QDialogButtonBox::NRoles; ++i) {
+ const QList &list = buttonLists[i];
+ for (int j = 0; j < list.size(); ++j)
finalList.append(list.at(j));
}
return finalList;
}
+QList QDialogButtonBoxPrivate::allButtons() const
+{
+ return visibleButtons() << hiddenButtons.keys();
+}
+
/*!
Returns the button role for the specified \a button. This function returns
- \l InvalidRole if \a button is 0 or has not been added to the button box.
+ \l InvalidRole if \a button is \nullptr or has not been added to the button box.
\sa buttons(), addButton()
*/
@@ -707,12 +688,12 @@
Q_D(const QDialogButtonBox);
for (int i = 0; i < NRoles; ++i) {
const QList &list = d->buttonLists[i];
- for (int j = 0; j < list.count(); ++j) {
+ for (int j = 0; j < list.size(); ++j) {
if (list.at(j) == button)
return ButtonRole(i);
}
}
- return InvalidRole;
+ return d->hiddenButtons.value(button, InvalidRole);
}
/*!
@@ -723,27 +704,45 @@
void QDialogButtonBox::removeButton(QAbstractButton *button)
{
Q_D(QDialogButtonBox);
+ d->removeButton(button, QDialogButtonBoxPrivate::RemoveReason::ManualRemove);
+}
+/*!
+ \internal
+ Removes \param button.
+ \param reason determines the behavior following the removal:
+ \list
+ \li \c ManualRemove disconnects all signals and removes the button from standardButtonHash.
+ \li \c HideEvent keeps connections alive, standard buttons remain in standardButtonHash.
+ \li \c Destroyed removes the button from standardButtonHash. Signals remain untouched, because
+ the button might already be only a QObject, the destructor of which handles disconnecting.
+ \endlist
+ */
+void QDialogButtonBoxPrivate::removeButton(QAbstractButton *button, RemoveReason reason)
+{
if (!button)
return;
- // Remove it from the standard button hash first and then from the roles
- d->standardButtonHash.remove(reinterpret_cast(button));
- for (int i = 0; i < NRoles; ++i) {
- QList &list = d->buttonLists[i];
- for (int j = 0; j < list.count(); ++j) {
- if (list.at(j) == button) {
- list.takeAt(j);
- if (!d->internalRemove) {
- disconnect(button, SIGNAL(clicked()), this, SLOT(_q_handleButtonClicked()));
- disconnect(button, SIGNAL(destroyed()), this, SLOT(_q_handleButtonDestroyed()));
- }
- break;
- }
- }
+ // Remove button from hidden buttons and roles
+ hiddenButtons.remove(button);
+ for (int i = 0; i < QDialogButtonBox::NRoles; ++i)
+ buttonLists[i].removeOne(button);
+
+ switch (reason) {
+ case RemoveReason::ManualRemove:
+ button->setParent(nullptr);
+ QObjectPrivate::disconnect(button, &QAbstractButton::clicked,
+ this, &QDialogButtonBoxPrivate::handleButtonClicked);
+ QObjectPrivate::disconnect(button, &QAbstractButton::destroyed,
+ this, &QDialogButtonBoxPrivate::handleButtonDestroyed);
+ button->removeEventFilter(filter.get());
+ Q_FALLTHROUGH();
+ case RemoveReason::Destroyed:
+ standardButtonHash.remove(reinterpret_cast(button));
+ break;
+ case RemoveReason::HideEvent:
+ break;
}
- if (!d->internalRemove)
- button->setParent(nullptr);
}
/*!
@@ -813,7 +812,7 @@
{
Q_D(QDialogButtonBox);
// Clear out all the old standard buttons, then recreate them.
- qDeleteAll(d->standardButtonHash.keys());
+ qDeleteAll(d->standardButtonHash.keyBegin(), d->standardButtonHash.keyEnd());
d->standardButtonHash.clear();
d->createStandardButtons(buttons);
@@ -855,7 +854,7 @@
return d->standardButtonHash.value(static_cast(button));
}
-void QDialogButtonBoxPrivate::_q_handleButtonClicked()
+void QDialogButtonBoxPrivate::handleButtonClicked()
{
Q_Q(QDialogButtonBox);
if (QAbstractButton *button = qobject_cast(q->sender())) {
@@ -889,20 +888,51 @@
}
}
-void QDialogButtonBoxPrivate::_q_handleButtonDestroyed()
+void QDialogButtonBoxPrivate::handleButtonDestroyed()
+{
+ Q_Q(QDialogButtonBox);
+ if (QObject *object = q->sender())
+ removeButton(reinterpret_cast(object), RemoveReason::Destroyed);
+}
+
+bool QDialogButtonBoxPrivate::handleButtonShowAndHide(QAbstractButton *button, QEvent *event)
{
Q_Q(QDialogButtonBox);
- if (QObject *object = q->sender()) {
- QBoolBlocker skippy(internalRemove);
- q->removeButton(reinterpret_cast(object));
+
+ const QEvent::Type type = event->type();
+
+ if ((type != QEvent::HideToParent && type != QEvent::ShowToParent) || ignoreShowAndHide)
+ return false;
+
+ switch (type) {
+ case QEvent::HideToParent: {
+ const QDialogButtonBox::ButtonRole role = q->buttonRole(button);
+ if (role != QDialogButtonBox::ButtonRole::InvalidRole) {
+ removeButton(button, RemoveReason::HideEvent);
+ hiddenButtons.insert(button, role);
+ layoutButtons();
+ }
+ break;
}
+ case QEvent::ShowToParent:
+ if (hiddenButtons.contains(button)) {
+ const auto role = hiddenButtons.take(button);
+ addButton(button, role, LayoutRule::DoLayout, AddRule::SkipConnect);
+ if (role == QDialogButtonBox::AcceptRole)
+ ensureFirstAcceptIsDefault();
+ }
+ break;
+ default: break;
+ }
+
+ return false;
}
/*!
\property QDialogButtonBox::centerButtons
\brief whether the buttons in the button box are centered
- By default, this property is \c false. This behavior is appopriate
+ By default, this property is \c false. This behavior is appropriate
for most types of dialogs. A notable exception is message boxes
on most platforms (e.g. Windows), where the button box is
centered horizontally.
@@ -953,36 +983,78 @@
}
}
+void QDialogButtonBoxPrivate::ensureFirstAcceptIsDefault()
+{
+ Q_Q(QDialogButtonBox);
+ const QList &acceptRoleList = buttonLists[QDialogButtonBox::AcceptRole];
+ QPushButton *firstAcceptButton = acceptRoleList.isEmpty()
+ ? nullptr
+ : qobject_cast(acceptRoleList.at(0));
+
+ if (!firstAcceptButton)
+ return;
+
+ bool hasDefault = false;
+ QWidget *dialog = nullptr;
+ QWidget *p = q;
+ while (p && !p->isWindow()) {
+ p = p->parentWidget();
+ if ((dialog = qobject_cast(p)))
+ break;
+ }
+
+ QWidget *parent = dialog ? dialog : q;
+ Q_ASSERT(parent);
+
+ const auto pushButtons = parent->findChildren();
+ for (QPushButton *pushButton : pushButtons) {
+ if (pushButton->isDefault() && pushButton != firstAcceptButton) {
+ hasDefault = true;
+ break;
+ }
+ }
+ if (!hasDefault && firstAcceptButton) {
+ firstAcceptButton->setDefault(true);
+ // When the QDialogButtonBox is focused, and it doesn't have an
+ // explicit focus widget, it will transfer focus to its focus
+ // proxy, which is the first button in the layout. This behavior,
+ // combined with the behavior that QPushButtons in a QDialog will
+ // by default have their autoDefault set to true, results in the
+ // focus proxy/first button stealing the default button status
+ // immediately when the button box is focused, which is not what
+ // we want. Account for this by explicitly making the firstAcceptButton
+ // focused as well, unless an explicit focus widget has been set.
+ if (dialog && !dialog->focusWidget())
+ firstAcceptButton->setFocus();
+ }
+}
+
+void QDialogButtonBoxPrivate::disconnectAll()
+{
+ Q_Q(QDialogButtonBox);
+ const auto buttons = q->findChildren();
+ for (auto *button : buttons)
+ button->disconnect(q);
+}
+
/*!
\reimp
*/
bool QDialogButtonBox::event(QEvent *event)
{
Q_D(QDialogButtonBox);
- if (event->type() == QEvent::Show) {
- QList acceptRoleList = d->buttonLists[AcceptRole];
- QPushButton *firstAcceptButton = acceptRoleList.isEmpty() ? 0 : qobject_cast(acceptRoleList.at(0));
- bool hasDefault = false;
- QWidget *dialog = nullptr;
- QWidget *p = this;
- while (p && !p->isWindow()) {
- p = p->parentWidget();
- if ((dialog = qobject_cast(p)))
- break;
- }
+ switch (event->type()) {
+ case QEvent::Show:
+ d->ensureFirstAcceptIsDefault();
+ break;
- const auto pbs = (dialog ? dialog : this)->findChildren();
- for (QPushButton *pb : pbs) {
- if (pb->isDefault() && pb != firstAcceptButton) {
- hasDefault = true;
- break;
- }
- }
- if (!hasDefault && firstAcceptButton)
- firstAcceptButton->setDefault(true);
- }else if (event->type() == QEvent::LanguageChange) {
+ case QEvent::LanguageChange:
d->retranslateStrings();
+ break;
+
+ default: break;
}
+
return QWidget::event(event);
}
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qt/qerrormessage.cpp
--- a/libgui/languages/build_ts/octave-qt/qerrormessage.cpp Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qt/qerrormessage.cpp Mon Dec 04 19:55:32 2023 +0100
@@ -1,53 +1,15 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qerrormessage.h"
-#ifndef QT_NO_ERRORMESSAGE
-
#include "qapplication.h"
#include "qcheckbox.h"
#include "qlabel.h"
#include "qlayout.h"
+#if QT_CONFIG(messagebox)
#include "qmessagebox.h"
+#endif
#include "qpushbutton.h"
#include "qstringlist.h"
#include "qtextedit.h"
@@ -55,94 +17,99 @@
#include "qpixmap.h"
#include "qmetaobject.h"
#include "qthread.h"
-#include "qqueue.h"
#include "qset.h"
+#include
+
#include
#include
-#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
+QT_BEGIN_NAMESPACE
-#if defined(QT_SOFTKEYS_ENABLED)
-#include
-#endif
-#ifdef Q_WS_S60
-#include "private/qt_s60_p.h"
-#endif
-
-QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
class QErrorMessagePrivate : public QDialogPrivate
{
Q_DECLARE_PUBLIC(QErrorMessage)
public:
+ struct Message {
+ QString content;
+ QString type;
+ };
+
QPushButton * ok;
QCheckBox * again;
QTextEdit * errors;
QLabel * icon;
-#ifdef QT_SOFTKEYS_ENABLED
- QAction *okAction;
-#endif
- QQueue > pending;
+ std::queue pending;
QSet doNotShow;
QSet doNotShowType;
QString currentMessage;
QString currentType;
+ bool isMessageToBeShown(const QString &message, const QString &type) const;
bool nextPending();
void retranslateStrings();
+
+ void setVisible(bool) override;
+
+private:
+ void initHelper(QPlatformDialogHelper *) override;
+ void helperPrepareShow(QPlatformDialogHelper *) override;
};
+
+void QErrorMessagePrivate::initHelper(QPlatformDialogHelper *helper)
+{
+ Q_Q(QErrorMessage);
+ auto *messageDialogHelper = static_cast(helper);
+ QObject::connect(messageDialogHelper, &QPlatformMessageDialogHelper::checkBoxStateChanged, q,
+ [this](Qt::CheckState state) {
+ again->setCheckState(state);
+ }
+ );
+ QObject::connect(messageDialogHelper, &QPlatformMessageDialogHelper::clicked, q,
+ [this](QPlatformDialogHelper::StandardButton, QPlatformDialogHelper::ButtonRole) {
+ Q_Q(QErrorMessage);
+ q->accept();
+ }
+ );
+}
+
+void QErrorMessagePrivate::helperPrepareShow(QPlatformDialogHelper *helper)
+{
+ Q_Q(QErrorMessage);
+ auto *messageDialogHelper = static_cast(helper);
+ QSharedPointer options = QMessageDialogOptions::create();
+ options->setText(currentMessage);
+ options->setWindowTitle(q->windowTitle());
+ options->setText(QErrorMessage::tr("An error occurred"));
+ options->setInformativeText(currentMessage);
+ options->setStandardIcon(QMessageDialogOptions::Critical);
+ options->setCheckBox(again->text(), again->checkState());
+ messageDialogHelper->setOptions(options);
+}
+
+namespace {
class QErrorMessageTextView : public QTextEdit
{
public:
QErrorMessageTextView(QWidget *parent)
: QTextEdit(parent) { setReadOnly(true); }
- virtual QSize minimumSizeHint() const;
- virtual QSize sizeHint() const;
+ virtual QSize minimumSizeHint() const override;
+ virtual QSize sizeHint() const override;
};
+} // unnamed namespace
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
}
/*!
@@ -151,6 +118,7 @@
\brief The QErrorMessage class provides an error message display dialog.
\ingroup standard-dialog
+ \inmodule QtWidgets
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
@@ -164,7 +132,7 @@
connecting signals to it.
The static qtHandler() function installs a message handler
- using qInstallMsgHandler() and creates a QErrorMessage that displays
+ using qInstallMessageHandler() 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.
@@ -178,46 +146,67 @@
The \l{dialogs/standarddialogs}{Standard Dialogs} example shows
how to use QErrorMessage as well as other built-in Qt dialogs.
- \img qerrormessage.png
+ \image qerrormessage.png
\sa QMessageBox, QStatusBar::showMessage(), {Standard Dialogs Example}
*/
-static QErrorMessage * qtMessageHandler = 0;
+static QErrorMessage * qtMessageHandler = nullptr;
static void deleteStaticcQErrorMessage() // post-routine
{
if (qtMessageHandler) {
delete qtMessageHandler;
- qtMessageHandler = 0;
+ qtMessageHandler = nullptr;
}
}
static bool metFatal = false;
-static void jump(QtMsgType t, const char * m)
+static QString msgType2i18nString(QtMsgType t)
{
+ static_assert(QtDebugMsg == 0);
+ static_assert(QtWarningMsg == 1);
+ static_assert(QtCriticalMsg == 2);
+ static_assert(QtFatalMsg == 3);
+ static_assert(QtInfoMsg == 4);
+
+ // adjust the array below if any of the above fire...
+
+ const char * const messages[] = {
+ QT_TRANSLATE_NOOP("QErrorMessage", "Debug Message:"),
+ QT_TRANSLATE_NOOP("QErrorMessage", "Warning:"),
+ QT_TRANSLATE_NOOP("QErrorMessage", "Critical Error:"),
+ QT_TRANSLATE_NOOP("QErrorMessage", "Fatal Error:"),
+ QT_TRANSLATE_NOOP("QErrorMessage", "Information:"),
+ };
+ Q_ASSERT(size_t(t) < sizeof messages / sizeof *messages);
+
+ return QCoreApplication::translate("QErrorMessage", messages[t]);
+}
+
+static QtMessageHandler originalMessageHandler = nullptr;
+
+static void jump(QtMsgType t, const QMessageLogContext &context, const QString &m)
+{
+ const auto forwardToOriginalHandler = qScopeGuard([&] {
+ if (originalMessageHandler)
+ originalMessageHandler(t, context, m);
+ });
+
if (!qtMessageHandler)
return;
- QString rich;
+ auto *defaultCategory = QLoggingCategory::defaultCategory();
+ if (context.category && defaultCategory
+ && qstrcmp(context.category, defaultCategory->categoryName()) != 0)
+ return;
- 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("%1
").arg(rich);
- rich += Qt::convertFromPlainText(QLatin1String(m), Qt::WhiteSpaceNormal);
+ QString rich = ""_L1 + msgType2i18nString(t) + "
"_L1
+ + Qt::convertFromPlainText(m, Qt::WhiteSpaceNormal);
// ### work around text engine quirk
- if (rich.endsWith(QLatin1String("
")))
+ if (rich.endsWith(""_L1))
rich.chop(4);
if (!metFatal) {
@@ -237,49 +226,43 @@
/*!
Constructs and installs an error handler window with the given \a
parent.
+
+ The default \l{Qt::WindowModality} {window modality} of the dialog
+ depends on the platform. The window modality can be overridden via
+ setWindowModality() before calling showMessage().
*/
QErrorMessage::QErrorMessage(QWidget * parent)
: QDialog(*new QErrorMessagePrivate, parent)
{
Q_D(QErrorMessage);
- QGridLayout * grid = new QGridLayout(this);
+
+#if defined(Q_OS_MACOS)
+ setWindowModality(parent ? Qt::WindowModal : Qt::ApplicationModal);
+#endif
+
d->icon = new QLabel(this);
-#ifndef QT_NO_MESSAGEBOX
- d->icon->setPixmap(QMessageBox::standardIcon(QMessageBox::Information));
+ d->errors = new QErrorMessageTextView(this);
+ d->again = new QCheckBox(this);
+ d->ok = new QPushButton(this);
+ QGridLayout * grid = new QGridLayout(this);
+
+ connect(d->ok, SIGNAL(clicked()), this, SLOT(accept()));
+
+ grid->addWidget(d->icon, 0, 0, Qt::AlignTop);
+ grid->addWidget(d->errors, 0, 1);
+ grid->addWidget(d->again, 1, 1, Qt::AlignTop);
+ grid->addWidget(d->ok, 2, 0, 1, 2, Qt::AlignCenter);
+ grid->setColumnStretch(1, 42);
+ grid->setRowStretch(0, 42);
+
+#if QT_CONFIG(messagebox)
+ d->icon->setPixmap(style()->standardPixmap(QStyle::SP_MessageBoxInformation));
d->icon->setAlignment(Qt::AlignHCenter | Qt::AlignTop);
#endif
-#ifdef Q_WS_S60
- //In Symbian, messagebox icons are in LtR UIs on right. Thus, layout needs to switch icon and text columns.
- const int preferredIconColumn = (QApplication::layoutDirection() == Qt::LeftToRight) ? 1 : 0;
- const int preferredTextColumn = (QApplication::layoutDirection() == Qt::LeftToRight) ? 0 : 1;
-#else
- const int preferredIconColumn = 0;
- const int preferredTextColumn = 1;
-#endif
- grid->addWidget(d->icon, 0, preferredIconColumn, Qt::AlignTop);
- d->errors = new QErrorMessageTextView(this);
- grid->addWidget(d->errors, 0, preferredTextColumn);
- d->again = new QCheckBox(this);
d->again->setChecked(true);
- grid->addWidget(d->again, 1, preferredTextColumn, 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
+ d->ok->setFocus();
-
-#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(preferredTextColumn, 42);
- grid->setRowStretch(0, 42);
d->retranslateStrings();
}
@@ -291,11 +274,13 @@
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);
+ qtMessageHandler = nullptr;
+ QtMessageHandler currentMessagHandler = qInstallMessageHandler(nullptr);
+ if (currentMessagHandler != jump)
+ qInstallMessageHandler(currentMessagHandler);
+ else
+ qInstallMessageHandler(originalMessageHandler);
+ originalMessageHandler = nullptr;
}
}
@@ -305,16 +290,22 @@
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);
+ if (!d->again->isChecked()) {
+ if (d->currentType.isEmpty()) {
+ if (!d->currentMessage.isEmpty())
+ d->doNotShow.insert(d->currentMessage);
+ } else {
+ d->doNotShowType.insert(d->currentType);
+ }
}
d->currentMessage.clear();
d->currentType.clear();
- if (!d->nextPending()) {
- QDialog::done(a);
+
+ QDialog::done(a);
+
+ if (d->nextPending()) {
+ show();
+ } else {
if (this == qtMessageHandler && metFatal)
exit(1);
}
@@ -325,15 +316,21 @@
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.
+
+ The object will only output log messages of QLoggingCategory::defaultCategory().
+
+ The object will forward all messages to the original message handler.
+
+ \sa qInstallMessageHandler
*/
QErrorMessage * QErrorMessage::qtHandler()
{
if (!qtMessageHandler) {
- qtMessageHandler = new QErrorMessage(0);
+ qtMessageHandler = new QErrorMessage(nullptr);
qAddPostRoutine(deleteStaticcQErrorMessage); // clean up
- qtMessageHandler->setWindowTitle(QApplication::applicationName());
- qInstallMsgHandler(jump);
+ qtMessageHandler->setWindowTitle(QCoreApplication::applicationName());
+ originalMessageHandler = qInstallMessageHandler(jump);
}
return qtMessageHandler;
}
@@ -341,20 +338,27 @@
/*! \internal */
+bool QErrorMessagePrivate::isMessageToBeShown(const QString &message, const QString &type) const
+{
+ return !message.isEmpty()
+ && (type.isEmpty() ? !doNotShow.contains(message) : !doNotShowType.contains(type));
+}
+
bool QErrorMessagePrivate::nextPending()
{
- while (!pending.isEmpty()) {
- QPair pendingMessage = pending.dequeue();
- QString message = pendingMessage.first;
- QString type = pendingMessage.second;
- if (!message.isEmpty() && ((type.isEmpty() && !doNotShow.contains(message)) || (!type.isEmpty() && !doNotShowType.contains(type)))) {
+ while (!pending.empty()) {
+ QString message = std::move(pending.front().content);
+ QString type = std::move(pending.front().type);
+ pending.pop();
+ if (isMessageToBeShown(message, type)) {
#ifndef QT_NO_TEXTHTMLPARSER
errors->setHtml(message);
#else
errors->setPlainText(message);
#endif
- currentMessage = message;
- currentType = type;
+ currentMessage = std::move(message);
+ currentType = std::move(type);
+ again->setChecked(true);
return true;
}
}
@@ -373,12 +377,7 @@
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();
+ showMessage(message, QString());
}
/*!
@@ -398,13 +397,30 @@
void QErrorMessage::showMessage(const QString &message, const QString &type)
{
Q_D(QErrorMessage);
- if (d->doNotShow.contains(message) && d->doNotShowType.contains(type))
+ if (!d->isMessageToBeShown(message, type))
return;
- d->pending.push_back(qMakePair(message,type));
+ d->pending.push({message, type});
if (!isVisible() && d->nextPending())
show();
}
+void QErrorMessagePrivate::setVisible(bool visible)
+{
+ Q_Q(QErrorMessage);
+ if (q->testAttribute(Qt::WA_WState_ExplicitShowHide) && q->testAttribute(Qt::WA_WState_Hidden) != visible)
+ return;
+
+ if (canBeNativeDialog())
+ setNativeDialogVisible(visible);
+
+ // Update WA_DontShowOnScreen based on whether the native dialog was shown,
+ // so that QDialog::setVisible(visible) below updates the QWidget state correctly,
+ // but skips showing the non-native version.
+ q->setAttribute(Qt::WA_DontShowOnScreen, nativeDialogInUse);
+
+ QDialogPrivate::setVisible(visible);
+}
+
/*!
\reimp
*/
@@ -421,17 +437,8 @@
{
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
+#include "moc_qerrormessage.cpp"
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qt/qfiledialog.cpp
--- a/libgui/languages/build_ts/octave-qt/qfiledialog.cpp Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qt/qfiledialog.cpp Mon Dec 04 19:55:32 2023 +0100
@@ -1,112 +1,73 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#define QT_NO_URL_CAST_FROM_STRING
#include
#include
#include "qfiledialog.h"
-#ifndef QT_NO_FILEDIALOG
#include "qfiledialog_p.h"
+#include
+#include
#include
#include
+#include
#include
-#include
+#if QT_CONFIG(shortcut)
+# include
+#endif
#include
+#if QT_CONFIG(menu)
#include
+#endif
+#if QT_CONFIG(messagebox)
#include
-#include
+#endif
#include
+#if QT_CONFIG(settings)
#include
+#endif
#include
+#if QT_CONFIG(mimetype)
+#include
+#endif
+#if QT_CONFIG(regularexpression)
+#include
+#endif
#include
#include
-#include
-#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
#if defined(Q_OS_UNIX)
#include
+#include // for pathconf() on OS X
+#elif defined(Q_OS_WIN)
+# include
#endif
+#if defined(Q_OS_WASM)
+#include
#endif
+#include
+
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;
+using namespace Qt::StringLiterals;
+
+Q_GLOBAL_STATIC(QUrl, lastVisitedDir)
/*!
\class QFileDialog
\brief The QFileDialog class provides a dialog that allow users to select files or directories.
\ingroup standard-dialogs
-
+ \inmodule QtWidgets
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
+ The easiest way to create a QFileDialog is to use the static functions.
+
+ \snippet 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"
@@ -117,13 +78,13 @@
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
+ \snippet 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
+ \snippet 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
@@ -136,7 +97,7 @@
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
+ \snippet 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,
@@ -152,12 +113,12 @@
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
+ \snippet 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
+ \snippet 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.
@@ -169,8 +130,15 @@
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}
+ By default, a platform-native file dialog will be used if the platform has
+ one. In that case, the widgets which would otherwise be used to construct the
+ dialog will not be instantiated, so related accessors such as layout() and
+ itemDelegate() will return null. Also, not all platforms show file dialogs
+ with a title bar, so be aware that the caption text might not be visible to
+ the user. You can set the \l DontUseNativeDialog option to ensure that the
+ widget-based implementation will be used instead of the native dialog.
+
+ \sa QDir, QFileInfo, QFile, QColorDialog, QFontDialog, {Standard Dialogs Example}
*/
/*!
@@ -203,13 +171,11 @@
\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.
+ directories are displayed. However, the native Windows
+ file dialog does not support displaying files in the
+ directory chooser.
\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()
*/
@@ -226,25 +192,27 @@
\value DontConfirmOverwrite Don't ask for confirmation if an
existing file is selected. By default confirmation is requested.
+ Note: This option is not supported on macOS when using the
+ native file dialog.
+
\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.
+ of QFileDialog that contains the Q_OBJECT macro, or the platform
+ does not have a native dialog of the type that you require.
+
+ \b{Note:} This option must be set before changing dialog properties
+ or showing the dialog.
\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.
-
\value DontUseCustomDirectoryIcons Always use the default directory icon.
Some platforms allow the user to set a different icon. Custom icon lookup
- cause a big performance impact over network or removable drives. Setting this
- will affect the behavior of the icon provider. This enum value was added in Qt 4.8.6.
+ cause a big performance impact over network or removable drives.
+ Setting this will enable the QFileIconProvider::DontUseCustomDirectoryIcons
+ option in the icon provider. This enum value was added in Qt 5.2.
*/
/*!
@@ -260,37 +228,76 @@
/*!
\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.
+ When the selection changes for local operations 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::urlsSelected(const QList &urls)
+
+ When the selection changes and the dialog is accepted, this signal is
+ emitted with the (possibly empty) list of selected \a urls.
+
+ \sa currentUrlChanged(), QDialog::Accepted
+ \since 5.2
+*/
/*!
\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.
+ When the selection changes for local operations and the dialog is
+ accepted, this signal is emitted with the (possibly empty)
+ selected \a file.
\sa currentChanged(), QDialog::Accepted
*/
+/*!
+ \fn void QFileDialog::urlSelected(const QUrl &url)
+
+ When the selection changes and the dialog is accepted, this signal is
+ emitted with the (possibly empty) selected \a url.
+
+ \sa currentUrlChanged(), QDialog::Accepted
+ \since 5.2
+*/
/*!
\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.
+ When the current file changes for local operations, this signal is
+ emitted with the new file name as the \a path parameter.
\sa filesSelected()
*/
/*!
+ \fn void QFileDialog::currentUrlChanged(const QUrl &url)
+
+ When the current file changes, this signal is emitted with the
+ new file URL as the \a url parameter.
+
+ \sa urlsSelected()
+ \since 5.2
+*/
+
+/*!
\fn void QFileDialog::directoryEntered(const QString &directory)
\since 4.3
+ This signal is emitted for local operations when the user enters
+ a \a directory.
+*/
+
+/*!
+ \fn void QFileDialog::directoryUrlEntered(const QUrl &directory)
+
This signal is emitted when the user enters a \a directory.
+
+ \since 5.2
*/
/*!
@@ -300,17 +307,10 @@
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
-#endif
-#include
-#ifdef Q_WS_MAC
-#include
+#include
+#if QT_CONFIG(shortcut)
+# include
#endif
QT_END_INCLUDE_NAMESPACE
@@ -323,8 +323,8 @@
: QDialog(*new QFileDialogPrivate, parent, f)
{
Q_D(QFileDialog);
- d->init();
- d->lineEdit()->selectAll();
+ QFileDialogArgs args;
+ d->init(args);
}
/*!
@@ -338,25 +338,26 @@
const QString &caption,
const QString &directory,
const QString &filter)
- : QDialog(*new QFileDialogPrivate, parent, 0)
+ : QDialog(*new QFileDialogPrivate, parent, { })
{
Q_D(QFileDialog);
- d->init(directory, filter, caption);
- d->lineEdit()->selectAll();
+ QFileDialogArgs args(QUrl::fromLocalFile(directory));
+ args.filter = filter;
+ args.caption = caption;
+ d->init(args);
}
/*!
\internal
*/
QFileDialog::QFileDialog(const QFileDialogArgs &args)
- : QDialog(*new QFileDialogPrivate, args.parent, 0)
+ : QDialog(*new QFileDialogPrivate, args.parent, { })
{
Q_D(QFileDialog);
- d->init(args.directory, args.filter, args.caption);
+ d->init(args);
setFileMode(args.mode);
setOptions(args.options);
selectFile(args.selection);
- d->lineEdit()->selectAll();
}
/*!
@@ -364,13 +365,10 @@
*/
QFileDialog::~QFileDialog()
{
+#if QT_CONFIG(settings)
Q_D(QFileDialog);
-#ifndef QT_NO_SETTINGS
- QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
- settings.beginGroup(QLatin1String("Qt"));
- settings.setValue(QLatin1String("filedialog"), saveState());
+ d->saveSettings();
#endif
- d->deleteNativeDialog_sys();
}
/*!
@@ -379,7 +377,7 @@
For instance:
- \snippet doc/src/snippets/filedialogurls.cpp 0
+ \snippet filedialogurls/filedialogurls.cpp 0
The file dialog will then look like this:
@@ -390,7 +388,8 @@
void QFileDialog::setSidebarUrls(const QList &urls)
{
Q_D(QFileDialog);
- d->qFileDialogUi->sidebar->setUrls(urls);
+ if (!d->nativeDialogInUse)
+ d->qFileDialogUi->sidebar->setUrls(urls);
}
/*!
@@ -400,14 +399,11 @@
QList QFileDialog::sidebarUrls() const
{
Q_D(const QFileDialog);
- return d->qFileDialogUi->sidebar->urls();
+ return (d->nativeDialogInUse ? QList() : 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.
@@ -418,17 +414,26 @@
QByteArray QFileDialog::saveState() const
{
Q_D(const QFileDialog);
- int version = 3;
+ int version = 4;
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
+ stream.setVersion(QDataStream::Qt_5_0);
stream << qint32(QFileDialogMagic);
stream << qint32(version);
- stream << d->qFileDialogUi->splitter->saveState();
- stream << d->qFileDialogUi->sidebar->urls();
+ if (d->usingWidgets()) {
+ stream << d->qFileDialogUi->splitter->saveState();
+ stream << d->qFileDialogUi->sidebar->urls();
+ } else {
+ stream << d->splitterState;
+ stream << d->sidebarUrls;
+ }
stream << history();
stream << *lastVisitedDir();
- stream << d->qFileDialogUi->treeView->header()->saveState();
+ if (d->usingWidgets())
+ stream << d->qFileDialogUi->treeView->header()->saveState();
+ else
+ stream << d->headerData;
stream << qint32(viewMode());
return data;
}
@@ -440,66 +445,47 @@
Typically this is used in conjunction with QSettings to restore the size
from a past session.
- Returns false if there are errors
+ Returns \c 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);
+ stream.setVersion(QDataStream::Qt_5_0);
if (stream.atEnd())
return false;
- QByteArray splitterState;
- QByteArray headerData;
- QList bookmarks;
QStringList history;
- QString currentDirectory;
+ QUrl currentDirectory;
qint32 marker;
qint32 v;
qint32 viewMode;
stream >> marker;
stream >> v;
- if (marker != QFileDialogMagic || v != version)
+ // the code below only supports versions 3 and 4
+ if (marker != QFileDialogMagic || (v != 3 && v != 4))
return false;
- stream >> splitterState
- >> bookmarks
- >> history
- >> currentDirectory
- >> headerData
- >> viewMode;
-
- if (!d->qFileDialogUi->splitter->restoreState(splitterState))
- return false;
- QList 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);
+ stream >> d->splitterState
+ >> d->sidebarUrls
+ >> history;
+ if (v == 3) {
+ QString currentDirectoryString;
+ stream >> currentDirectoryString;
+ currentDirectory = QUrl::fromLocalFile(currentDirectoryString);
+ } else {
+ stream >> currentDirectory;
}
-
- d->qFileDialogUi->sidebar->setUrls(bookmarks);
- while (history.count() > 5)
- history.pop_front();
- setHistory(history);
- setDirectory(lastVisitedDir()->isEmpty() ? currentDirectory : *lastVisitedDir());
- QHeaderView *headerView = d->qFileDialogUi->treeView->header();
- if (!headerView->restoreState(headerData))
- return false;
-
- QList actions = headerView->actions();
- QAbstractItemModel *abstractModel = d->model;
-#ifndef QT_NO_PROXYMODEL
- if (d->proxyModel)
- abstractModel = d->proxyModel;
-#endif
- int total = qMin(abstractModel->columnCount(QModelIndex()), actions.count() + 1);
- for (int i = 1; i < total; ++i)
- actions.at(i - 1)->setChecked(!headerView->isSectionHidden(i));
-
- setViewMode(ViewMode(viewMode));
- return true;
+ stream >> d->headerData
+ >> viewMode;
+
+ setDirectoryUrl(lastVisitedDir()->isEmpty() ? currentDirectory : *lastVisitedDir());
+ setViewMode(static_cast(viewMode));
+
+ if (!d->usingWidgets())
+ return true;
+
+ return d->restoreWidgetState(history, -1);
}
/*!
@@ -517,29 +503,17 @@
QFileDialogPrivate::QFileDialogPrivate()
:
-#ifndef QT_NO_PROXYMODEL
- proxyModel(0),
+#if QT_CONFIG(proxymodel)
+ proxyModel(nullptr),
#endif
- model(0),
- fileMode(QFileDialog::AnyFile),
- acceptMode(QFileDialog::AcceptOpen),
+ model(nullptr),
currentHistoryLocation(-1),
- renameAction(0),
- deleteAction(0),
- showHiddenAction(0),
+ renameAction(nullptr),
+ deleteAction(nullptr),
+ showHiddenAction(nullptr),
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)
+ qFileDialogUi(nullptr),
+ options(QFileDialogOptions::create())
{
}
@@ -547,13 +521,48 @@
{
}
+void QFileDialogPrivate::initHelper(QPlatformDialogHelper *h)
+{
+ QFileDialog *d = q_func();
+ QObject::connect(h, SIGNAL(fileSelected(QUrl)), d, SLOT(_q_emitUrlSelected(QUrl)));
+ QObject::connect(h, SIGNAL(filesSelected(QList)), d, SLOT(_q_emitUrlsSelected(QList)));
+ QObject::connect(h, SIGNAL(currentChanged(QUrl)), d, SLOT(_q_nativeCurrentChanged(QUrl)));
+ QObject::connect(h, SIGNAL(directoryEntered(QUrl)), d, SLOT(_q_nativeEnterDirectory(QUrl)));
+ QObject::connect(h, SIGNAL(filterSelected(QString)), d, SIGNAL(filterSelected(QString)));
+ static_cast(h)->setOptions(options);
+}
+
+void QFileDialogPrivate::helperPrepareShow(QPlatformDialogHelper *)
+{
+ Q_Q(QFileDialog);
+ options->setWindowTitle(q->windowTitle());
+ options->setHistory(q->history());
+ if (usingWidgets())
+ options->setSidebarUrls(qFileDialogUi->sidebar->urls());
+ if (options->initiallySelectedNameFilter().isEmpty())
+ options->setInitiallySelectedNameFilter(q->selectedNameFilter());
+ if (options->initiallySelectedFiles().isEmpty())
+ options->setInitiallySelectedFiles(userSelectedFiles());
+}
+
+void QFileDialogPrivate::helperDone(QDialog::DialogCode code, QPlatformDialogHelper *)
+{
+ if (code == QDialog::Accepted) {
+ Q_Q(QFileDialog);
+ q->setViewMode(static_cast(options->viewMode()));
+ q->setSidebarUrls(options->sidebarUrls());
+ q->setHistory(options->history());
+ }
+}
+
void QFileDialogPrivate::retranslateWindowTitle()
{
Q_Q(QFileDialog);
if (!useDefaultCaption || setWindowTitle != q->windowTitle())
return;
- if (acceptMode == QFileDialog::AcceptOpen) {
- if (fileMode == QFileDialog::DirectoryOnly || fileMode == QFileDialog::Directory)
+ if (q->acceptMode() == QFileDialog::AcceptOpen) {
+ const QFileDialog::FileMode fileMode = q->fileMode();
+ if (fileMode == QFileDialog::Directory)
q->setWindowTitle(QFileDialog::tr("Find Directory"));
else
q->setWindowTitle(QFileDialog::tr("Open"));
@@ -563,25 +572,85 @@
setWindowTitle = q->windowTitle();
}
-void QFileDialogPrivate::setLastVisitedDirectory(const QString &dir)
+void QFileDialogPrivate::setLastVisitedDirectory(const QUrl &dir)
{
*lastVisitedDir() = dir;
}
+void QFileDialogPrivate::updateLookInLabel()
+{
+ if (options->isLabelExplicitlySet(QFileDialogOptions::LookIn))
+ setLabelTextControl(QFileDialog::LookIn, options->labelText(QFileDialogOptions::LookIn));
+}
+
+void QFileDialogPrivate::updateFileNameLabel()
+{
+ if (options->isLabelExplicitlySet(QFileDialogOptions::FileName)) {
+ setLabelTextControl(QFileDialog::FileName, options->labelText(QFileDialogOptions::FileName));
+ } else {
+ switch (q_func()->fileMode()) {
+ case QFileDialog::Directory:
+ setLabelTextControl(QFileDialog::FileName, QFileDialog::tr("Directory:"));
+ break;
+ default:
+ setLabelTextControl(QFileDialog::FileName, QFileDialog::tr("File &name:"));
+ break;
+ }
+ }
+}
+
+void QFileDialogPrivate::updateFileTypeLabel()
+{
+ if (options->isLabelExplicitlySet(QFileDialogOptions::FileType))
+ setLabelTextControl(QFileDialog::FileType, options->labelText(QFileDialogOptions::FileType));
+}
+
+void QFileDialogPrivate::updateOkButtonText(bool saveAsOnFolder)
+{
+ Q_Q(QFileDialog);
+ // 'Save as' at a folder: Temporarily change to "Open".
+ if (saveAsOnFolder) {
+ setLabelTextControl(QFileDialog::Accept, QFileDialog::tr("&Open"));
+ } else if (options->isLabelExplicitlySet(QFileDialogOptions::Accept)) {
+ setLabelTextControl(QFileDialog::Accept, options->labelText(QFileDialogOptions::Accept));
+ return;
+ } else {
+ switch (q->fileMode()) {
+ case QFileDialog::Directory:
+ setLabelTextControl(QFileDialog::Accept, QFileDialog::tr("&Choose"));
+ break;
+ default:
+ setLabelTextControl(QFileDialog::Accept,
+ q->acceptMode() == QFileDialog::AcceptOpen ?
+ QFileDialog::tr("&Open") :
+ QFileDialog::tr("&Save"));
+ break;
+ }
+ }
+}
+
+void QFileDialogPrivate::updateCancelButtonText()
+{
+ if (options->isLabelExplicitlySet(QFileDialogOptions::Reject))
+ setLabelTextControl(QFileDialog::Reject, options->labelText(QFileDialogOptions::Reject));
+}
+
void QFileDialogPrivate::retranslateStrings()
{
Q_Q(QFileDialog);
/* WIDGETS */
- if (defaultFileTypes)
- q->setNameFilter(QFileDialog::tr("All Files (*)"));
+ if (options->useDefaultNameFilters())
+ q->setNameFilter(QFileDialogOptions::defaultNameFilterString());
+ if (!usingWidgets())
+ return;
QList actions = qFileDialogUi->treeView->header()->actions();
QAbstractItemModel *abstractModel = model;
-#ifndef QT_NO_PROXYMODEL
+#if QT_CONFIG(proxymodel)
if (proxyModel)
abstractModel = proxyModel;
#endif
- int total = qMin(abstractModel->columnCount(QModelIndex()), actions.count() + 1);
+ const int total = qMin(abstractModel->columnCount(QModelIndex()), int(actions.size() + 1));
for (int i = 1; i < total; ++i) {
actions.at(i - 1)->setText(QFileDialog::tr("Show ") + abstractModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString());
}
@@ -592,38 +661,39 @@
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;
- }
+ updateLookInLabel();
+ updateFileNameLabel();
+ updateFileTypeLabel();
+ updateCancelButtonText();
}
void QFileDialogPrivate::emitFilesSelected(const QStringList &files)
{
Q_Q(QFileDialog);
emit q->filesSelected(files);
- if (files.count() == 1)
+ if (files.size() == 1)
emit q->fileSelected(files.first());
}
-bool QFileDialogPrivate::canBeNativeDialog()
+bool QFileDialogPrivate::canBeNativeDialog() const
{
- Q_Q(QFileDialog);
+ // Don't use Q_Q here! This function is called from ~QDialog,
+ // so Q_Q calling q_func() invokes undefined behavior (invalid cast in q_func()).
+ const QDialog * const q = static_cast(q_ptr);
if (nativeDialogInUse)
return true;
- if (q->testAttribute(Qt::WA_DontShowOnScreen))
- return false;
- if (opts & QFileDialog::DontUseNativeDialog)
+ if (QCoreApplication::testAttribute(Qt::AA_DontUseNativeDialogs)
+ || q->testAttribute(Qt::WA_DontShowOnScreen)
+ || (options->options() & QFileDialog::DontUseNativeDialog)) {
return false;
-
- QLatin1String staticName(QFileDialog::staticMetaObject.className());
- QLatin1String dynamicName(q->metaObject()->className());
- return (staticName == dynamicName);
+ }
+
+ return strcmp(QFileDialog::staticMetaObject.className(), q->metaObject()->className()) == 0;
+}
+
+bool QFileDialogPrivate::usingWidgets() const
+{
+ return !nativeDialogInUse && qFileDialogUi;
}
/*!
@@ -631,19 +701,29 @@
Sets the given \a option to be enabled if \a on is true; otherwise,
clears the given \a option.
+ Options (particularly the DontUseNativeDialogs option) should be set
+ before changing dialog properties or showing the dialog.
+
+ Setting options while the dialog is visible is not guaranteed to have
+ an immediate effect on the dialog (depending on the option and on the
+ platform).
+
+ Setting options after changing other properties may cause these
+ values to have no effect.
+
\sa options, testOption()
*/
void QFileDialog::setOption(Option option, bool on)
{
- Q_D(QFileDialog);
- if (!(d->opts & option) != !on)
- setOptions(d->opts ^ option);
+ const QFileDialog::Options previousOptions = options();
+ if (!(previousOptions & option) != !on)
+ setOptions(previousOptions ^ option);
}
/*!
\since 4.5
- Returns true if the given \a option is enabled; otherwise, returns
+ Returns \c true if the given \a option is enabled; otherwise, returns
false.
\sa options, setOption()
@@ -651,7 +731,7 @@
bool QFileDialog::testOption(Option option) const
{
Q_D(const QFileDialog);
- return (d->opts & option) != 0;
+ return d->options->testOption(static_cast(option));
}
/*!
@@ -661,9 +741,15 @@
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).
+ Options (particularly the DontUseNativeDialogs option) should be set
+ before changing dialog properties or showing the dialog.
+
+ Setting options while the dialog is visible is not guaranteed to have
+ an immediate effect on the dialog (depending on the option and on the
+ platform).
+
+ Setting options after changing other properties may cause these
+ values to have no effect.
\sa setOption(), testOption()
*/
@@ -671,39 +757,57 @@
{
Q_D(QFileDialog);
- Options changed = (options ^ d->opts);
+ Options changed = (options ^ QFileDialog::options());
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);
+ d->options->setOptions(QFileDialogOptions::FileDialogOptions(int(options)));
+
+ if (options & DontUseNativeDialog) {
+ d->nativeDialogInUse = false;
+ d->createWidgets();
}
+
+ if (d->usingWidgets()) {
+ 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 & DontUseCustomDirectoryIcons) {
+ QFileIconProvider::Options providerOptions = iconProvider()->options();
+ providerOptions.setFlag(QFileIconProvider::DontUseCustomDirectoryIcons,
+ options & DontUseCustomDirectoryIcons);
+ iconProvider()->setOptions(providerOptions);
+ }
+ }
+
if (changed & HideNameFilterDetails)
- setNameFilters(d->nameFilters);
+ setNameFilters(d->options->nameFilters());
if (changed & ShowDirsOnly)
setFilter((options & ShowDirsOnly) ? filter() & ~QDir::Files : filter() | QDir::Files);
-
- if (changed & DontUseCustomDirectoryIcons)
- iconProvider()->d_ptr->setUseCustomDirectoryIcons(!(options & DontUseCustomDirectoryIcons));
}
QFileDialog::Options QFileDialog::options() const
{
Q_D(const QFileDialog);
- return d->opts;
+ static_assert((int)QFileDialog::ShowDirsOnly == (int)QFileDialogOptions::ShowDirsOnly);
+ static_assert((int)QFileDialog::DontResolveSymlinks == (int)QFileDialogOptions::DontResolveSymlinks);
+ static_assert((int)QFileDialog::DontConfirmOverwrite == (int)QFileDialogOptions::DontConfirmOverwrite);
+ static_assert((int)QFileDialog::DontUseNativeDialog == (int)QFileDialogOptions::DontUseNativeDialog);
+ static_assert((int)QFileDialog::ReadOnly == (int)QFileDialogOptions::ReadOnly);
+ static_assert((int)QFileDialog::HideNameFilterDetails == (int)QFileDialogOptions::HideNameFilterDetails);
+ static_assert((int)QFileDialog::DontUseCustomDirectoryIcons == (int)QFileDialogOptions::DontUseCustomDirectoryIcons);
+ return QFileDialog::Options(int(d->options->options()));
}
/*!
- \overload
-
\since 4.5
This function connects one of its signals to the slot specified by \a receiver
@@ -731,39 +835,53 @@
*/
void QFileDialog::setVisible(bool visible)
{
- Q_D(QFileDialog);
+ // will call QFileDialogPrivate::setVisible override
+ QDialog::setVisible(visible);
+}
+
+/*!
+ \internal
+
+ The logic has to live here so that the call to hide() in ~QDialog calls
+ this function; it wouldn't call an override of QDialog::setVisible().
+*/
+void QFileDialogPrivate::setVisible(bool visible)
+{
+ Q_Q(QFileDialog);
if (visible){
- if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden))
+ if (q->testAttribute(Qt::WA_WState_ExplicitShowHide) && !q->testAttribute(Qt::WA_WState_Hidden))
return;
- } else if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden))
+ } else if (q->testAttribute(Qt::WA_WState_ExplicitShowHide) && q->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
+ if (canBeNativeDialog()){
+ if (setNativeDialogVisible(visible)){
+ // Set WA_DontShowOnScreen so that QDialogPrivate::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);
+ q->setAttribute(Qt::WA_DontShowOnScreen);
+#if QT_CONFIG(fscompleter)
+ // So the completer doesn't try to complete and therefore show a popup
+ if (!nativeDialogInUse)
+ completer->setModel(nullptr);
#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);
+ createWidgets();
+ q->setAttribute(Qt::WA_DontShowOnScreen, false);
+#if QT_CONFIG(fscompleter)
+ if (!nativeDialogInUse) {
+ if (proxyModel != nullptr)
+ completer->setModel(proxyModel);
+ else
+ completer->setModel(model);
+ }
#endif
}
}
- if (!d->nativeDialogInUse)
- d->qFileDialogUi->fileNameEdit->setFocus();
-
- QDialog::setVisible(visible);
+ if (visible && usingWidgets())
+ qFileDialogUi->fileNameEdit->setFocus();
+
+ QDialogPrivate::setVisible(visible);
}
/*!
@@ -787,12 +905,20 @@
/*!
Sets the file dialog's current \a directory.
+
+ \note On iOS, if you set \a directory to \l{QStandardPaths::standardLocations()}
+ {QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).last()},
+ a native image picker dialog will be used for accessing the user's photo album.
+ The filename returned can be loaded using QFile and related APIs.
+ For this to be enabled, the Info.plist assigned to QMAKE_INFO_PLIST in the
+ project file must contain the key \c NSPhotoLibraryUsageDescription. See
+ Info.plist documentation from Apple for more information regarding this key.
+ This feature was added in Qt 5.5.
*/
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);
@@ -800,26 +926,30 @@
if (!directory.isEmpty() && newDirectory.isEmpty())
return;
- d->setLastVisitedDirectory(newDirectory);
-
- if (d->nativeDialogInUse){
- d->setDirectory_sys(newDirectory);
+ QUrl newDirUrl = QUrl::fromLocalFile(newDirectory);
+ QFileDialogPrivate::setLastVisitedDirectory(newDirUrl);
+
+ d->options->setInitialDirectory(QUrl::fromLocalFile(directory));
+ if (!d->usingWidgets()) {
+ d->setDirectory_sys(newDirUrl);
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('/'));
+ if (!d->nativeDialogInUse) {
+ d->qFileDialogUi->newFolderButton->setEnabled(d->model->flags(root) & Qt::ItemIsDropEnabled);
+ if (root != d->rootIndex()) {
+#if QT_CONFIG(fscompleter)
+ if (directory.endsWith(u'/'))
+ d->completer->setCompletionPrefix(newDirectory);
+ else
+ d->completer->setCompletionPrefix(newDirectory + u'/');
#endif
- d->setRootIndex(root);
+ d->setRootIndex(root);
+ }
+ d->qFileDialogUi->listView->selectionModel()->clear();
}
- d->qFileDialogUi->listView->selectionModel()->clear();
}
/*!
@@ -828,7 +958,97 @@
QDir QFileDialog::directory() const
{
Q_D(const QFileDialog);
- return QDir(d->nativeDialogInUse ? d->directory_sys() : d->rootPath());
+ if (d->nativeDialogInUse) {
+ QString dir = d->directory_sys().toLocalFile();
+ return QDir(dir.isEmpty() ? d->options->initialDirectory().toLocalFile() : dir);
+ }
+ return d->rootPath();
+}
+
+/*!
+ Sets the file dialog's current \a directory url.
+
+ \note The non-native QFileDialog supports only local files.
+
+ \note On Windows, it is possible to pass URLs representing
+ one of the \e {virtual folders}, such as "Computer" or "Network".
+ This is done by passing a QUrl using the scheme \c clsid followed
+ by the CLSID value with the curly braces removed. For example the URL
+ \c clsid:374DE290-123F-4565-9164-39C4925E467B denotes the download
+ location. For a complete list of possible values, see the MSDN documentation on
+ \l{https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid}{KNOWNFOLDERID}.
+ This feature was added in Qt 5.5.
+
+ \sa QUuid
+ \since 5.2
+*/
+void QFileDialog::setDirectoryUrl(const QUrl &directory)
+{
+ Q_D(QFileDialog);
+ if (!directory.isValid())
+ return;
+
+ QFileDialogPrivate::setLastVisitedDirectory(directory);
+ d->options->setInitialDirectory(directory);
+
+ if (d->nativeDialogInUse)
+ d->setDirectory_sys(directory);
+ else if (directory.isLocalFile())
+ setDirectory(directory.toLocalFile());
+ else if (Q_UNLIKELY(d->usingWidgets()))
+ qWarning("Non-native QFileDialog supports only local files");
+}
+
+/*!
+ Returns the url of the directory currently being displayed in the dialog.
+
+ \since 5.2
+*/
+QUrl QFileDialog::directoryUrl() const
+{
+ Q_D(const QFileDialog);
+ if (d->nativeDialogInUse)
+ return d->directory_sys();
+ else
+ return QUrl::fromLocalFile(directory().absolutePath());
+}
+
+// FIXME Qt 5.4: Use upcoming QVolumeInfo class to determine this information?
+static inline bool isCaseSensitiveFileSystem(const QString &path)
+{
+ Q_UNUSED(path);
+#if defined(Q_OS_WIN)
+ // Return case insensitive unconditionally, even if someone has a case sensitive
+ // file system mounted, wrongly capitalized drive letters will cause mismatches.
+ return false;
+#elif defined(Q_OS_MACOS)
+ return pathconf(QFile::encodeName(path).constData(), _PC_CASE_SENSITIVE);
+#else
+ return true;
+#endif
+}
+
+// Determine the file name to be set on the line edit from the path
+// passed to selectFile() in mode QFileDialog::AcceptSave.
+static inline QString fileFromPath(const QString &rootPath, QString path)
+{
+ if (!QFileInfo(path).isAbsolute())
+ return path;
+ if (path.startsWith(rootPath, isCaseSensitiveFileSystem(rootPath) ? Qt::CaseSensitive : Qt::CaseInsensitive))
+ path.remove(0, rootPath.size());
+
+ if (path.isEmpty())
+ return path;
+
+ if (path.at(0) == QDir::separator()
+#ifdef Q_OS_WIN
+ //On Windows both cases can happen
+ || path.at(0) == u'/'
+#endif
+ ) {
+ path.remove(0, 1);
+ }
+ return path;
}
/*!
@@ -842,8 +1062,19 @@
if (filename.isEmpty())
return;
- if (d->nativeDialogInUse){
- d->selectFile_sys(filename);
+ if (!d->usingWidgets()) {
+ QUrl url;
+ if (QFileInfo(filename).isRelative()) {
+ url = d->options->initialDirectory();
+ QString path = url.path();
+ if (!path.endsWith(u'/'))
+ path += u'/';
+ url.setPath(path + filename);
+ } else {
+ url = QUrl::fromLocalFile(filename);
+ }
+ d->selectFile_sys(url);
+ d->options->setInitiallySelectedFiles(QList() << url);
return;
}
@@ -856,73 +1087,71 @@
}
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);
+ d->lineEdit()->setText(index.isValid() ? index.data().toString() : fileFromPath(d->rootPath(), filename));
+}
+
+/*!
+ Selects the given \a url in the file dialog.
+
+ \note The non-native QFileDialog supports only local files.
+
+ \sa selectedUrls()
+ \since 5.2
+*/
+void QFileDialog::selectUrl(const QUrl &url)
+{
+ Q_D(QFileDialog);
+ if (!url.isValid())
+ return;
+
+ if (d->nativeDialogInUse)
+ d->selectFile_sys(url);
+ else if (url.isLocalFile())
+ selectFile(url.toLocalFile());
+ else
+ qWarning("Non-native QFileDialog supports only local files");
}
#ifdef Q_OS_UNIX
-Q_AUTOTEST_EXPORT QString qt_tildeExpansion(const QString &path, bool *expanded = 0)
+Q_AUTOTEST_EXPORT QString qt_tildeExpansion(const QString &path)
{
- if (expanded != 0)
- *expanded = false;
- if (!path.startsWith(QLatin1Char('~')))
+ if (!path.startsWith(u'~'))
return path;
- QString ret = path;
-#if !defined(Q_OS_INTEGRITY)
- QStringList tokens = ret.split(QDir::separator());
- if (tokens.first() == QLatin1String("~")) {
- ret.replace(0, 1, QDir::homePath());
+ int separatorPosition = path.indexOf(QDir::separator());
+ if (separatorPosition < 0)
+ separatorPosition = path.size();
+ if (separatorPosition == 1) {
+ return QDir::homePath() + QStringView{path}.mid(1);
} else {
- QString userName = tokens.first();
- userName.remove(0, 1);
-#if defined(Q_OS_VXWORKS)
+#if defined(Q_OS_VXWORKS) || defined(Q_OS_INTEGRITY)
const QString homePath = QDir::homePath();
-#elif defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD)
+#else
+ const QByteArray userName = QStringView{path}.mid(1, separatorPosition - 1).toLocal8Bit();
+# if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_WASM)
passwd pw;
passwd *tmpPw;
char buf[200];
const int bufSize = sizeof(buf);
int err = 0;
-#if defined(Q_OS_SOLARIS) && (_POSIX_C_SOURCE - 0 < 199506L)
- tmpPw = getpwnam_r(userName.toLocal8Bit().constData(), &pw, buf, bufSize);
-#else
- err = getpwnam_r(userName.toLocal8Bit().constData(), &pw, buf, bufSize, &tmpPw);
-#endif
+# if defined(Q_OS_SOLARIS) && (_POSIX_C_SOURCE - 0 < 199506L)
+ tmpPw = getpwnam_r(userName.constData(), &pw, buf, bufSize);
+# else
+ err = getpwnam_r(userName.constData(), &pw, buf, bufSize, &tmpPw);
+# endif
if (err || !tmpPw)
- return ret;
+ return path;
const QString homePath = QString::fromLocal8Bit(pw.pw_dir);
-#else
- passwd *pw = getpwnam(userName.toLocal8Bit().constData());
+# else
+ passwd *pw = getpwnam(userName.constData());
if (!pw)
- return ret;
+ return path;
const QString homePath = QString::fromLocal8Bit(pw->pw_dir);
+# endif
#endif
- ret.replace(0, tokens.first().length(), homePath);
+ return homePath + QStringView{path}.mid(separatorPosition);
}
- if (expanded != 0)
- *expanded = true;
-#endif
- return ret;
}
#endif
@@ -931,12 +1160,10 @@
*/
QStringList QFileDialogPrivate::typedFiles() const
{
-#ifdef Q_OS_UNIX
Q_Q(const QFileDialog);
-#endif
QStringList files;
QString editText = lineEdit()->text();
- if (!editText.contains(QLatin1Char('"'))) {
+ if (!editText.contains(u'"')) {
#ifdef Q_OS_UNIX
const QString prefix = q->directory().absolutePath() + QDir::separator();
if (QFile::exists(prefix + editText))
@@ -945,11 +1172,12 @@
files << qt_tildeExpansion(editText);
#else
files << editText;
+ Q_UNUSED(q);
#endif
} else {
// " is used to separate files like so: "file1" "file2" "file3" ...
// ### need escape character for filenames with quotes (")
- QStringList tokens = editText.split(QLatin1Char('\"'));
+ QStringList tokens = editText.split(u'\"');
for (int i=0; i QFileDialogPrivate::userSelectedFiles() const
+{
+ QList files;
+
+ if (!usingWidgets())
+ return addDefaultSuffixToUrls(selectedFiles_sys());
+
+ const QModelIndexList selectedRows = qFileDialogUi->listView->selectionModel()->selectedRows();
+ files.reserve(selectedRows.size());
+ for (const QModelIndex &index : selectedRows)
+ files.append(QUrl::fromLocalFile(index.data(QFileSystemModel::FilePathRole).toString()));
+
+ if (files.isEmpty() && !lineEdit()->text().isEmpty()) {
+ const QStringList typedFilesList = typedFiles();
+ files.reserve(typedFilesList.size());
+ for (const QString &path : typedFilesList)
+ files.append(QUrl::fromLocalFile(path));
+ }
+
+ return files;
+}
+
+QStringList QFileDialogPrivate::addDefaultSuffixToFiles(const QStringList &filesToFix) const
{
QStringList files;
for (int i=0; idefaultSuffix();
+ if (!defaultSuffix.isEmpty() && !info.isDir() && !info.fileName().contains(u'.'))
+ name += u'.' + defaultSuffix;
+
if (info.isAbsolute()) {
files.append(name);
} else {
@@ -984,8 +1239,8 @@
// 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('/');
+ if (!path.endsWith(u'/'))
+ path += u'/';
path += name;
files.append(path);
}
@@ -993,6 +1248,24 @@
return files;
}
+QList QFileDialogPrivate::addDefaultSuffixToUrls(const QList &urlsToFix) const
+{
+ QList urls;
+ urls.reserve(urlsToFix.size());
+ // if the filename has no suffix, add the default suffix
+ const QString defaultSuffix = options->defaultSuffix();
+ for (QUrl url : urlsToFix) {
+ if (!defaultSuffix.isEmpty()) {
+ const QString urlPath = url.path();
+ const auto idx = urlPath.lastIndexOf(u'/');
+ if (idx != (urlPath.size() - 1) && !QStringView{urlPath}.mid(idx + 1).contains(u'.'))
+ url.setPath(urlPath + u'.' + defaultSuffix);
+ }
+ urls.append(url);
+ }
+ return urls;
+}
+
/*!
Returns a list of strings containing the absolute paths of the
@@ -1004,43 +1277,58 @@
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());
+ const QList userSelectedFiles = d->userSelectedFiles();
+ files.reserve(userSelectedFiles.size());
+ for (const QUrl &file : userSelectedFiles)
+ files.append(file.toString(QUrl::PreferLocalFile));
+
+ if (files.isEmpty() && d->usingWidgets()) {
+ const FileMode fm = fileMode();
+ if (fm != ExistingFile && fm != ExistingFiles)
+ files.append(d->rootIndex().data(QFileSystemModel::FilePathRole).toString());
+ }
return files;
}
+/*!
+ Returns a list of urls containing the selected files in the dialog.
+ If no files are selected, or the mode is not ExistingFiles or
+ ExistingFile, selectedUrls() contains the current path in the viewport.
+
+ \sa selectedNameFilter(), selectUrl()
+ \since 5.2
+*/
+QList QFileDialog::selectedUrls() const
+{
+ Q_D(const QFileDialog);
+ if (d->nativeDialogInUse) {
+ return d->userSelectedFiles();
+ } else {
+ QList urls;
+ const QStringList selectedFileList = selectedFiles();
+ urls.reserve(selectedFileList.size());
+ for (const QString &file : selectedFileList)
+ urls.append(QUrl::fromLocalFile(file));
+ return urls;
+ }
+}
+
/*
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())
+ if (filter.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);
+ auto sep = ";;"_L1;
+ if (!filter.contains(sep) && filter.contains(u'\n'))
+ sep = "\n"_L1;
+
+ return filter.split(sep);
}
/*!
@@ -1049,67 +1337,43 @@
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
+ filename-wildcard patterns, 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()
+ \snippet code/src_gui_dialogs_qfiledialog.cpp 6
+
+ \note With Android's native file dialog, the mime type matching the given
+ name filter is used because only mime types are supported.
+
+ \sa setMimeTypeFilters(), 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)
{
+#if QT_CONFIG(regularexpression)
QStringList strippedFilters;
- QRegExp r(QString::fromLatin1(qt_file_dialog_filter_reg_exp));
- for (int i = 0; i < filters.count(); ++i) {
+ static const QRegularExpression r(QString::fromLatin1(QPlatformFileDialogHelper::filterRegExp));
+ strippedFilters.reserve(filters.size());
+ for (const QString &filter : filters) {
QString filterName;
- int index = r.indexIn(filters[i]);
- if (index >= 0)
- filterName = r.cap(1);
+ auto match = r.match(filter);
+ if (match.hasMatch())
+ filterName = match.captured(1);
strippedFilters.append(filterName.simplified());
}
return strippedFilters;
+#else
+ return filters;
+#endif
}
@@ -1118,22 +1382,32 @@
Sets the \a filters used in the file dialog.
- \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 7
+ Note that the filter \b{*.*} is not portable, because the historical
+ assumption that the file extension determines the file type is not
+ consistent on every operating system. It is possible to have a file with no
+ dot in its name (for example, \c Makefile). In a native Windows file
+ dialog, \b{*.*} will match such files, while in other types of file dialogs
+ it may not. So it is better to use \b{*} if you mean to select any file.
+
+ \snippet code/src_gui_dialogs_qfiledialog.cpp 7
+
+ \l setMimeTypeFilters() has the advantage of providing all possible name
+ filters for each file type. For example, JPEG images have three possible
+ extensions; if your application can open such files, selecting the
+ \c image/jpeg mime type as a filter will allow you to open all of them.
*/
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);
+ cleanedFilters.reserve(filters.size());
+ for (const QString &filter : filters)
+ cleanedFilters << filter.simplified();
+
+ d->options->setNameFilters(cleanedFilters);
+
+ if (!d->usingWidgets())
return;
- }
d->qFileDialogUi->fileTypeCombo->clear();
if (cleanedFilters.isEmpty())
@@ -1148,16 +1422,6 @@
}
/*!
- \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
@@ -1165,18 +1429,7 @@
*/
QStringList QFileDialog::nameFilters() const
{
- return d_func()->nameFilters;
-}
-
-/*!
- \obsolete
-
- Use nameFilters() instead.
-*/
-
-QStringList QFileDialog::filters() const
-{
- return nameFilters();
+ return d_func()->options->nameFilters();
}
/*!
@@ -1190,7 +1443,8 @@
void QFileDialog::selectNameFilter(const QString &filter)
{
Q_D(QFileDialog);
- if (d->nativeDialogInUse) {
+ d->options->setInitiallySelectedNameFilter(filter);
+ if (!d->usingWidgets()) {
d->selectNameFilter_sys(filter);
return;
}
@@ -1209,17 +1463,6 @@
}
/*!
- \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.
@@ -1229,23 +1472,13 @@
QString QFileDialog::selectedNameFilter() const
{
Q_D(const QFileDialog);
- if (d->nativeDialogInUse)
+ if (!d->usingWidgets())
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.
@@ -1255,7 +1488,9 @@
QDir::Filters QFileDialog::filter() const
{
Q_D(const QFileDialog);
- return d->model->filter();
+ if (d->usingWidgets())
+ return d->model->filter();
+ return d->options->filter();
}
/*!
@@ -1270,15 +1505,129 @@
void QFileDialog::setFilter(QDir::Filters filters)
{
Q_D(QFileDialog);
- d->model->setFilter(filters);
- if (d->nativeDialogInUse){
+ d->options->setFilter(filters);
+ if (!d->usingWidgets()) {
d->setFilter_sys();
return;
}
+ d->model->setFilter(filters);
d->showHiddenAction->setChecked((filters & QDir::Hidden));
}
+#if QT_CONFIG(mimetype)
+
+static QString nameFilterForMime(const QString &mimeType)
+{
+ QMimeDatabase db;
+ QMimeType mime(db.mimeTypeForName(mimeType));
+ if (mime.isValid()) {
+ if (mime.isDefault()) {
+ return QFileDialog::tr("All files (*)");
+ } else {
+ const QString patterns = mime.globPatterns().join(u' ');
+ return mime.comment() + " ("_L1 + patterns + u')';
+ }
+ }
+ return QString();
+}
+
+/*!
+ \since 5.2
+
+ Sets the \a filters used in the file dialog, from a list of MIME types.
+
+ Convenience method for setNameFilters().
+ Uses QMimeType to create a name filter from the glob patterns and description
+ defined in each MIME type.
+
+ Use application/octet-stream for the "All files (*)" filter, since that
+ is the base MIME type for all files.
+
+ Calling setMimeTypeFilters overrides any previously set name filters,
+ and changes the return value of nameFilters().
+
+ \snippet code/src_gui_dialogs_qfiledialog.cpp 13
+*/
+void QFileDialog::setMimeTypeFilters(const QStringList &filters)
+{
+ Q_D(QFileDialog);
+ QStringList nameFilters;
+ for (const QString &mimeType : filters) {
+ const QString text = nameFilterForMime(mimeType);
+ if (!text.isEmpty())
+ nameFilters.append(text);
+ }
+ setNameFilters(nameFilters);
+ d->options->setMimeTypeFilters(filters);
+}
+
+/*!
+ \since 5.2
+
+ Returns the MIME type filters that are in operation on this file
+ dialog.
+*/
+QStringList QFileDialog::mimeTypeFilters() const
+{
+ return d_func()->options->mimeTypeFilters();
+}
+
+/*!
+ \since 5.2
+
+ Sets the current MIME type \a filter.
+
+*/
+void QFileDialog::selectMimeTypeFilter(const QString &filter)
+{
+ Q_D(QFileDialog);
+ d->options->setInitiallySelectedMimeTypeFilter(filter);
+
+ const QString filterForMime = nameFilterForMime(filter);
+
+ if (!d->usingWidgets()) {
+ d->selectMimeTypeFilter_sys(filter);
+ if (d->selectedMimeTypeFilter_sys().isEmpty() && !filterForMime.isEmpty()) {
+ selectNameFilter(filterForMime);
+ }
+ } else if (!filterForMime.isEmpty()) {
+ selectNameFilter(filterForMime);
+ }
+}
+
+#endif // mimetype
+
+/*!
+ * \since 5.9
+ * \return The mimetype of the file that the user selected in the file dialog.
+ */
+QString QFileDialog::selectedMimeTypeFilter() const
+{
+ Q_D(const QFileDialog);
+ QString mimeTypeFilter;
+ if (!d->usingWidgets())
+ mimeTypeFilter = d->selectedMimeTypeFilter_sys();
+
+#if QT_CONFIG(mimetype)
+ if (mimeTypeFilter.isNull() && !d->options->mimeTypeFilters().isEmpty()) {
+ const auto nameFilter = selectedNameFilter();
+ const auto mimeTypes = d->options->mimeTypeFilters();
+ for (const auto &mimeType: mimeTypes) {
+ QString filter = nameFilterForMime(mimeType);
+ if (testOption(HideNameFilterDetails))
+ filter = qt_strip_filters({ filter }).first();
+ if (filter == nameFilter) {
+ mimeTypeFilter = mimeType;
+ break;
+ }
+ }
+ }
+#endif
+
+ return mimeTypeFilter;
+}
+
/*!
\property QFileDialog::viewMode
\brief the way files and directories are displayed in the dialog
@@ -1291,6 +1640,9 @@
void QFileDialog::setViewMode(QFileDialog::ViewMode mode)
{
Q_D(QFileDialog);
+ d->options->setViewMode(static_cast(mode));
+ if (!d->usingWidgets())
+ return;
if (mode == Detail)
d->_q_showDetailsView();
else
@@ -1300,6 +1652,8 @@
QFileDialog::ViewMode QFileDialog::viewMode() const
{
Q_D(const QFileDialog);
+ if (!d->usingWidgets())
+ return static_cast(d->options->viewMode());
return (d->qFileDialogUi->stackedWidget->currentWidget() == d->qFileDialogUi->listView->parent() ? QFileDialog::List : QFileDialog::Detail);
}
@@ -1321,12 +1675,12 @@
void QFileDialog::setFileMode(QFileDialog::FileMode mode)
{
Q_D(QFileDialog);
- d->fileMode = mode;
+ d->options->setFileMode(static_cast(mode));
+ if (!d->usingWidgets())
+ return;
+
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)
@@ -1338,29 +1692,13 @@
// 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) {
+ if (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->updateFileNameLabel();
+ d->updateOkButtonText();
d->qFileDialogUi->fileTypeCombo->setEnabled(!testOption(ShowDirsOnly));
d->_q_updateOkButton();
}
@@ -1368,7 +1706,7 @@
QFileDialog::FileMode QFileDialog::fileMode() const
{
Q_D(const QFileDialog);
- return d->fileMode;
+ return static_cast(d->options->fileMode());
}
/*!
@@ -1384,24 +1722,43 @@
void QFileDialog::setAcceptMode(QFileDialog::AcceptMode mode)
{
Q_D(QFileDialog);
- d->acceptMode = mode;
- bool directoryMode = (d->fileMode == Directory || d->fileMode == DirectoryOnly);
+ d->options->setAcceptMode(static_cast(mode));
+ // clear WA_DontShowOnScreen so that d->canBeNativeDialog() doesn't return false incorrectly
+ setAttribute(Qt::WA_DontShowOnScreen, false);
+ if (!d->usingWidgets())
+ return;
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
+}
+
+/*!
+ \property QFileDialog::supportedSchemes
+ \brief the URL schemes that the file dialog should allow navigating to.
+ \since 5.6
+
+ Setting this property allows to restrict the type of URLs the
+ user will be able to select. It is a way for the application to declare
+ the protocols it will support to fetch the file content. An empty list
+ means that no restriction is applied (the default).
+ Supported for local files ("file" scheme) is implicit and always enabled;
+ it is not necessary to include it in the restriction.
+*/
+
+void QFileDialog::setSupportedSchemes(const QStringList &schemes)
+{
+ Q_D(QFileDialog);
+ d->options->setSupportedSchemes(schemes);
+}
+
+QStringList QFileDialog::supportedSchemes() const
+{
+ return d_func()->options->supportedSchemes();
}
/*
@@ -1414,7 +1771,7 @@
QAbstractItemView *QFileDialogPrivate::currentView() const {
if (!qFileDialogUi->stackedWidget)
- return 0;
+ return nullptr;
if (qFileDialogUi->stackedWidget->currentWidget() == qFileDialogUi->listView->parent())
return qFileDialogUi->listView;
return qFileDialogUi->treeView;
@@ -1424,6 +1781,22 @@
return (QLineEdit*)qFileDialogUi->fileNameEdit;
}
+long QFileDialogPrivate::maxNameLength(const QString &path)
+{
+#if defined(Q_OS_UNIX)
+ return ::pathconf(QFile::encodeName(path).data(), _PC_NAME_MAX);
+#elif defined(Q_OS_WIN)
+ DWORD maxLength;
+ const QString drive = path.left(3);
+ if (::GetVolumeInformation(reinterpret_cast(drive.utf16()), NULL, 0, NULL, &maxLength, NULL, NULL, 0) == false)
+ return -1;
+ return maxLength;
+#else
+ Q_UNUSED(path);
+#endif
+ return -1;
+}
+
/*
Sets the view root index to be the file system model index
*/
@@ -1450,67 +1823,7 @@
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);
+ return static_cast(d->options->acceptMode());
}
/*!
@@ -1521,17 +1834,19 @@
filename if it has no suffix already. The suffix is typically
used to indicate the file type (e.g. "txt" indicates a text
file).
+
+ If the first character is a dot ('.'), it is removed.
*/
void QFileDialog::setDefaultSuffix(const QString &suffix)
{
Q_D(QFileDialog);
- d->defaultSuffix = suffix;
+ d->options->setDefaultSuffix(suffix);
}
QString QFileDialog::defaultSuffix() const
{
Q_D(const QFileDialog);
- return d->defaultSuffix;
+ return d->options->defaultSuffix();
}
/*!
@@ -1541,7 +1856,8 @@
void QFileDialog::setHistory(const QStringList &paths)
{
Q_D(QFileDialog);
- d->qFileDialogUi->lookInCombo->setHistory(paths);
+ if (d->usingWidgets())
+ d->qFileDialogUi->lookInCombo->setHistory(paths);
}
void QFileDialogComboBox::setHistory(const QStringList &paths)
@@ -1549,9 +1865,11 @@
m_history = paths;
// Only populate the first item, showPopup will populate the rest if needed
QList list;
- QModelIndex idx = d_ptr->model->index(d_ptr->rootPath());
+ const 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()));
+ const QUrl url = idx.isValid()
+ ? QUrl::fromLocalFile(QDir::toNativeSeparators(idx.data(QFileSystemModel::FilePathRole).toString()))
+ : QUrl("file:"_L1);
if (url.isValid())
list.append(url);
urlModel->setUrls(list);
@@ -1563,6 +1881,8 @@
QStringList QFileDialog::history() const
{
Q_D(const QFileDialog);
+ if (!d->usingWidgets())
+ return QStringList();
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());
@@ -1575,6 +1895,9 @@
Sets the item delegate used to render items in the views in the
file dialog to the given \a delegate.
+ Any existing delegate will be removed, but not deleted. QFileDialog
+ does not take ownership of \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()}
@@ -1589,6 +1912,8 @@
void QFileDialog::setItemDelegate(QAbstractItemDelegate *delegate)
{
Q_D(QFileDialog);
+ if (!d->usingWidgets())
+ return;
d->qFileDialogUi->listView->setItemDelegate(delegate);
d->qFileDialogUi->treeView->setItemDelegate(delegate);
}
@@ -1599,15 +1924,19 @@
QAbstractItemDelegate *QFileDialog::itemDelegate() const
{
Q_D(const QFileDialog);
+ if (!d->usingWidgets())
+ return nullptr;
return d->qFileDialogUi->listView->itemDelegate();
}
/*!
Sets the icon provider used by the filedialog to the specified \a provider.
*/
-void QFileDialog::setIconProvider(QFileIconProvider *provider)
+void QFileDialog::setIconProvider(QAbstractFileIconProvider *provider)
{
Q_D(QFileDialog);
+ if (!d->usingWidgets())
+ return;
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());
@@ -1616,45 +1945,53 @@
/*!
Returns the icon provider used by the filedialog.
*/
-QFileIconProvider *QFileDialog::iconProvider() const
+QAbstractFileIconProvider *QFileDialog::iconProvider() const
{
Q_D(const QFileDialog);
+ if (!d->model)
+ return nullptr;
return d->model->iconProvider();
}
+void QFileDialogPrivate::setLabelTextControl(QFileDialog::DialogLabel label, const QString &text)
+{
+ if (!qFileDialogUi)
+ return;
+ switch (label) {
+ case QFileDialog::LookIn:
+ qFileDialogUi->lookInLabel->setText(text);
+ break;
+ case QFileDialog::FileName:
+ qFileDialogUi->fileNameLabel->setText(text);
+ break;
+ case QFileDialog::FileType:
+ qFileDialogUi->fileTypeLabel->setText(text);
+ break;
+ case QFileDialog::Accept:
+ if (q_func()->acceptMode() == QFileDialog::AcceptOpen) {
+ if (QPushButton *button = qFileDialogUi->buttonBox->button(QDialogButtonBox::Open))
+ button->setText(text);
+ } else {
+ if (QPushButton *button = qFileDialogUi->buttonBox->button(QDialogButtonBox::Save))
+ button->setText(text);
+ }
+ break;
+ case QFileDialog::Reject:
+ if (QPushButton *button = qFileDialogUi->buttonBox->button(QDialogButtonBox::Cancel))
+ button->setText(text);
+ break;
+ }
+}
+
/*!
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;
- }
+ d->options->setLabelText(static_cast(label), text);
+ d->setLabelTextControl(label, text);
}
/*!
@@ -1662,8 +1999,10 @@
*/
QString QFileDialog::labelText(DialogLabel label) const
{
+ Q_D(const QFileDialog);
+ if (!d->usingWidgets())
+ return d->options->labelText(static_cast(label));
QPushButton *button;
- Q_D(const QFileDialog);
switch (label) {
case LookIn:
return d->qFileDialogUi->lookInLabel->text();
@@ -1678,62 +2017,25 @@
button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Save);
if (button)
return button->text();
+ break;
case Reject:
button = d->qFileDialogUi->buttonBox->button(QDialogButtonBox::Cancel);
if (button)
return button->text();
+ break;
}
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
+ \snippet 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.
+ If \a parent is not \nullptr, 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
@@ -1742,9 +2044,7 @@
strings. If you want multiple filters, separate them with ';;', for
example:
- \code
- "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)"
- \endcode
+ \snippet code/src_gui_dialogs_qfiledialog.cpp 14
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
@@ -1753,12 +2053,13 @@
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, and \macos, this static function will use the
+ native file dialog and not a QFileDialog. Note that the \macos native file
+ dialog does not show a title bar.
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.
+ dispatch any QTimers, and if \a parent is not \nullptr 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},
@@ -1766,10 +2067,6 @@
\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.
@@ -1783,47 +2080,78 @@
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;
+ const QStringList schemes = QStringList(QStringLiteral("file"));
+ const QUrl selectedUrl = getOpenFileUrl(parent, caption, QUrl::fromLocalFile(dir), filter,
+ selectedFilter, options, schemes);
+ if (selectedUrl.isLocalFile() || selectedUrl.isEmpty())
+ return selectedUrl.toLocalFile();
+ else
+ return selectedUrl.toString();
+}
+
+/*!
+ This is a convenience static function that returns an existing file
+ selected by the user. If the user presses Cancel, it returns an
+ empty url.
+
+ The function is used similarly to QFileDialog::getOpenFileName(). In
+ particular \a parent, \a caption, \a dir, \a filter, \a selectedFilter
+ and \a options are used in the exact same way.
+
+ The main difference with QFileDialog::getOpenFileName() comes from
+ the ability offered to the user to select a remote file. That's why
+ the return type and the type of \a dir is QUrl.
+
+ The \a supportedSchemes argument allows to restrict the type of URLs the
+ user will be able to select. It is a way for the application to declare
+ the protocols it will support to fetch the file content. An empty list
+ means that no restriction is applied (the default).
+ Supported for local files ("file" scheme) is implicit and always enabled;
+ it is not necessary to include it in the restriction.
+
+ When possible, this static function will use the native file dialog and
+ not a QFileDialog. On platforms which don't support selecting remote
+ files, Qt will allow to select only local files.
+
+ \sa getOpenFileName(), getOpenFileUrls(), getSaveFileUrl(), getExistingDirectoryUrl()
+ \since 5.2
+*/
+QUrl QFileDialog::getOpenFileUrl(QWidget *parent,
+ const QString &caption,
+ const QUrl &dir,
+ const QString &filter,
+ QString *selectedFilter,
+ Options options,
+ const QStringList &supportedSchemes)
+{
+ QFileDialogArgs args(dir);
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);
+ dialog.setSupportedSchemes(supportedSchemes);
if (selectedFilter && !selectedFilter->isEmpty())
dialog.selectNameFilter(*selectedFilter);
if (dialog.exec() == QDialog::Accepted) {
if (selectedFilter)
- *selectedFilter = dialog.selectedFilter();
- return dialog.selectedFiles().value(0);
+ *selectedFilter = dialog.selectedNameFilter();
+ return dialog.selectedUrls().value(0);
}
- return QString();
+ return QUrl();
}
/*!
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
+ \snippet 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.
+ If \a parent is not \nullptr, 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
@@ -1832,19 +2160,18 @@
\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
+ \snippet code/src_gui_dialogs_qfiledialog.cpp 14
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, and \macos, this static function will use the
+ native file dialog and not a QFileDialog. Note that the \macos native file
+ dialog does not show a title bar.
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.
+ dispatch any QTimers, and if \a parent is not \nullptr 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},
@@ -1853,15 +2180,6 @@
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.
@@ -1875,37 +2193,179 @@
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;
+ const QStringList schemes = QStringList(QStringLiteral("file"));
+ const QList selectedUrls = getOpenFileUrls(parent, caption, QUrl::fromLocalFile(dir),
+ filter, selectedFilter, options, schemes);
+ QStringList fileNames;
+ fileNames.reserve(selectedUrls.size());
+ for (const QUrl &url : selectedUrls)
+ fileNames.append(url.toString(QUrl::PreferLocalFile));
+ return fileNames;
+}
+
+/*!
+ This is a convenience static function that will return one or more existing
+ files selected by the user. If the user presses Cancel, it returns an
+ empty list.
+
+ The function is used similarly to QFileDialog::getOpenFileNames(). In
+ particular \a parent, \a caption, \a dir, \a filter, \a selectedFilter
+ and \a options are used in the exact same way.
+
+ The main difference with QFileDialog::getOpenFileNames() comes from
+ the ability offered to the user to select remote files. That's why
+ the return type and the type of \a dir are respectively QList
+ and QUrl.
+
+ The \a supportedSchemes argument allows to restrict the type of URLs the
+ user will be able to select. It is a way for the application to declare
+ the protocols it will support to fetch the file content. An empty list
+ means that no restriction is applied (the default).
+ Supported for local files ("file" scheme) is implicit and always enabled;
+ it is not necessary to include it in the restriction.
+
+ When possible, this static function will use the native file dialog and
+ not a QFileDialog. On platforms which don't support selecting remote
+ files, Qt will allow to select only local files.
+
+ \sa getOpenFileNames(), getOpenFileUrl(), getSaveFileUrl(), getExistingDirectoryUrl()
+ \since 5.2
+*/
+QList QFileDialog::getOpenFileUrls(QWidget *parent,
+ const QString &caption,
+ const QUrl &dir,
+ const QString &filter,
+ QString *selectedFilter,
+ Options options,
+ const QStringList &supportedSchemes)
+{
+ QFileDialogArgs args(dir);
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);
+ dialog.setSupportedSchemes(supportedSchemes);
if (selectedFilter && !selectedFilter->isEmpty())
dialog.selectNameFilter(*selectedFilter);
if (dialog.exec() == QDialog::Accepted) {
if (selectedFilter)
- *selectedFilter = dialog.selectedFilter();
- return dialog.selectedFiles();
+ *selectedFilter = dialog.selectedNameFilter();
+ return dialog.selectedUrls();
}
- return QStringList();
+ return QList();
+}
+
+/*!
+ This is a convenience static function that will return the content of a file
+ selected by the user.
+
+ This function is used to access local files on Qt for WebAssembly, where the web
+ sandbox places restrictions on how such access may happen. Its implementation will
+ make the browser display a native file dialog, where the user makes the file selection
+ based on the parameter \a nameFilter.
+
+ It can also be used on other platforms, where it will fall back to using QFileDialog.
+
+ The function is asynchronous and returns immediately. The \a fileOpenCompleted
+ callback will be called when a file has been selected and its contents have been
+ read into memory.
+
+ \snippet code/src_gui_dialogs_qfiledialog.cpp 15
+ \since 5.13
+*/
+void QFileDialog::getOpenFileContent(const QString &nameFilter, const std::function &fileOpenCompleted)
+{
+#ifdef Q_OS_WASM
+ auto openFileImpl = std::make_shared>();
+ QString fileName;
+ QByteArray fileContent;
+ *openFileImpl = [=]() mutable {
+ auto fileDialogClosed = [&](bool fileSelected) {
+ if (!fileSelected) {
+ fileOpenCompleted(fileName, fileContent);
+ openFileImpl.reset();
+ }
+ };
+ auto acceptFile = [&](uint64_t size, const std::string name) -> char * {
+ const uint64_t twoGB = 1ULL << 31; // QByteArray limit
+ if (size > twoGB)
+ return nullptr;
+
+ fileName = QString::fromStdString(name);
+ fileContent.resize(size);
+ return fileContent.data();
+ };
+ auto fileContentReady = [&]() mutable {
+ fileOpenCompleted(fileName, fileContent);
+ openFileImpl.reset();
+ };
+
+ QWasmLocalFileAccess::openFile(nameFilter.toStdString(), fileDialogClosed, acceptFile, fileContentReady);
+ };
+
+ (*openFileImpl)();
+#else
+ QFileDialog *dialog = new QFileDialog();
+ dialog->setFileMode(QFileDialog::ExistingFile);
+ dialog->setNameFilter(nameFilter);
+
+ auto fileSelected = [=](const QString &fileName) {
+ QByteArray fileContent;
+ if (!fileName.isNull()) {
+ QFile selectedFile(fileName);
+ if (selectedFile.open(QIODevice::ReadOnly))
+ fileContent = selectedFile.readAll();
+ }
+ fileOpenCompleted(fileName, fileContent);
+ };
+
+ connect(dialog, &QFileDialog::fileSelected, fileSelected);
+ dialog->setAttribute(Qt::WA_DeleteOnClose);
+ dialog->show();
+#endif
+}
+
+/*!
+ This is a convenience static function that saves \a fileContent to a file, using
+ a file name and location chosen by the user. \a fileNameHint can be provided to
+ suggest a file name to the user.
+
+ This function is used to save files to the local file system on Qt for WebAssembly, where
+ the web sandbox places restrictions on how such access may happen. Its implementation will
+ make the browser display a native file dialog, where the user makes the file selection.
+
+ It can also be used on other platforms, where it will fall back to using QFileDialog.
+
+ The function is asynchronous and returns immediately.
+
+ \snippet code/src_gui_dialogs_qfiledialog.cpp 16
+ \since 5.14
+*/
+void QFileDialog::saveFileContent(const QByteArray &fileContent, const QString &fileNameHint)
+{
+#ifdef Q_OS_WASM
+ QWasmLocalFileAccess::saveFile(fileContent, fileNameHint.toStdString());
+#else
+ QFileDialog *dialog = new QFileDialog();
+ dialog->setAcceptMode(QFileDialog::AcceptSave);
+ dialog->setFileMode(QFileDialog::AnyFile);
+ dialog->selectFile(fileNameHint);
+
+ auto fileSelected = [=](const QString &fileName) {
+ if (!fileName.isNull()) {
+ QFile selectedFile(fileName);
+ if (selectedFile.open(QIODevice::WriteOnly))
+ selectedFile.write(fileContent);
+ }
+ };
+
+ connect(dialog, &QFileDialog::fileSelected, fileSelected);
+ dialog->setAttribute(Qt::WA_DeleteOnClose);
+ dialog->show();
+#endif
}
/*!
@@ -1913,10 +2373,10 @@
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
+ \a parent is not \nullptr, the dialog will be shown centered over the
+ parent widget.
+
+ \snippet 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
@@ -1924,9 +2384,7 @@
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
+ \snippet code/src_gui_dialogs_qfiledialog.cpp 14
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
@@ -1938,13 +2396,13 @@
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
+ On Windows, and \macos, 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.
+ dispatch any QTimers, and if \a parent is not \nullptr then it will
+ position the dialog just below the parent's title bar. On \macos, 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},
@@ -1952,10 +2410,6 @@
\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.
@@ -1969,50 +2423,79 @@
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;
+ const QStringList schemes = QStringList(QStringLiteral("file"));
+ const QUrl selectedUrl = getSaveFileUrl(parent, caption, QUrl::fromLocalFile(dir), filter,
+ selectedFilter, options, schemes);
+ if (selectedUrl.isLocalFile() || selectedUrl.isEmpty())
+ return selectedUrl.toLocalFile();
+ else
+ return selectedUrl.toString();
+}
+
+/*!
+ This is a convenience static function that returns a file selected by
+ the user. The file does not have to exist. If the user presses Cancel,
+ it returns an empty url.
+
+ The function is used similarly to QFileDialog::getSaveFileName(). In
+ particular \a parent, \a caption, \a dir, \a filter, \a selectedFilter
+ and \a options are used in the exact same way.
+
+ The main difference with QFileDialog::getSaveFileName() comes from
+ the ability offered to the user to select a remote file. That's why
+ the return type and the type of \a dir is QUrl.
+
+ The \a supportedSchemes argument allows to restrict the type of URLs the
+ user will be able to select. It is a way for the application to declare
+ the protocols it will support to save the file content. An empty list
+ means that no restriction is applied (the default).
+ Supported for local files ("file" scheme) is implicit and always enabled;
+ it is not necessary to include it in the restriction.
+
+ When possible, this static function will use the native file dialog and
+ not a QFileDialog. On platforms which don't support selecting remote
+ files, Qt will allow to select only local files.
+
+ \sa getSaveFileName(), getOpenFileUrl(), getOpenFileUrls(), getExistingDirectoryUrl()
+ \since 5.2
+*/
+QUrl QFileDialog::getSaveFileUrl(QWidget *parent,
+ const QString &caption,
+ const QUrl &dir,
+ const QString &filter,
+ QString *selectedFilter,
+ Options options,
+ const QStringList &supportedSchemes)
+{
+ QFileDialogArgs args(dir);
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.setSupportedSchemes(supportedSchemes);
dialog.setAcceptMode(AcceptSave);
if (selectedFilter && !selectedFilter->isEmpty())
dialog.selectNameFilter(*selectedFilter);
if (dialog.exec() == QDialog::Accepted) {
if (selectedFilter)
- *selectedFilter = dialog.selectedFilter();
- return dialog.selectedFiles().value(0);
+ *selectedFilter = dialog.selectedNameFilter();
+ return dialog.selectedUrls().value(0);
}
-
- return QString();
+ return QUrl();
}
/*!
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
+ \snippet 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.
+ If \a parent is not \nullptr, 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
@@ -2023,9 +2506,13 @@
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 Windows and \macos, this static function will use the
+ native file dialog and not a QFileDialog. However, the native Windows file
+ dialog does not support displaying files in the directory chooser. You need
+ to pass \l{QFileDialog::}{DontUseNativeDialog} to display files using a
+ QFileDialog.
+
+ Note that the \macos native file dialog does not show a 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},
@@ -2033,12 +2520,9 @@
\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.
+ On Windows, the dialog will spin a blocking modal event loop that will not
+ dispatch any QTimers, and if \a parent is not \nullptr then it will position
+ the dialog just below the parent's title bar.
\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
@@ -2051,80 +2535,109 @@
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;
+ const QStringList schemes = QStringList(QStringLiteral("file"));
+ const QUrl selectedUrl =
+ getExistingDirectoryUrl(parent, caption, QUrl::fromLocalFile(dir), options, schemes);
+ if (selectedUrl.isLocalFile() || selectedUrl.isEmpty())
+ return selectedUrl.toLocalFile();
+ else
+ return selectedUrl.toString();
+}
+
+/*!
+ This is a convenience static function that will return an existing
+ directory selected by the user. If the user presses Cancel, it
+ returns an empty url.
+
+ The function is used similarly to QFileDialog::getExistingDirectory().
+ In particular \a parent, \a caption, \a dir and \a options are used
+ in the exact same way.
+
+ The main difference with QFileDialog::getExistingDirectory() comes from
+ the ability offered to the user to select a remote directory. That's why
+ the return type and the type of \a dir is QUrl.
+
+ The \a supportedSchemes argument allows to restrict the type of URLs the
+ user will be able to select. It is a way for the application to declare
+ the protocols it will support to fetch the file content. An empty list
+ means that no restriction is applied (the default).
+ Supported for local files ("file" scheme) is implicit and always enabled;
+ it is not necessary to include it in the restriction.
+
+ When possible, this static function will use the native file dialog and
+ not a QFileDialog. On platforms which don't support selecting remote
+ files, Qt will allow to select only local files.
+
+ \sa getExistingDirectory(), getOpenFileUrl(), getOpenFileUrls(), getSaveFileUrl()
+ \since 5.2
+*/
+QUrl QFileDialog::getExistingDirectoryUrl(QWidget *parent,
+ const QString &caption,
+ const QUrl &dir,
+ Options options,
+ const QStringList &supportedSchemes)
+{
+ QFileDialogArgs args(dir);
args.parent = parent;
args.caption = caption;
- args.directory = QFileDialogPrivate::workingDirectory(dir);
- args.mode = (options & ShowDirsOnly ? DirectoryOnly : Directory);
+ args.mode = 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();
+ dialog.setSupportedSchemes(supportedSchemes);
+ if (dialog.exec() == QDialog::Accepted)
+ return dialog.selectedUrls().value(0);
+ return QUrl();
}
-inline static QString _qt_get_directory(const QString &path)
+inline static QUrl _qt_get_directory(const QUrl &url, const QFileInfo &local)
{
- 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;
+ if (url.isLocalFile()) {
+ QFileInfo info = local;
+ if (!local.isAbsolute())
+ info = QFileInfo(QDir::current(), url.toLocalFile());
+ const QFileInfo pathInfo(info.absolutePath());
+ if (!pathInfo.exists() || !pathInfo.isDir())
+ return QUrl();
+ if (info.exists() && info.isDir())
+ return QUrl::fromLocalFile(QDir::cleanPath(info.absoluteFilePath()));
+ return QUrl::fromLocalFile(pathInfo.absoluteFilePath());
+ } else {
+ return url;
}
- 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)
+ Initialize working directory and selection from \a url.
+*/
+QFileDialogArgs::QFileDialogArgs(const QUrl &url)
{
- if (!path.isEmpty()) {
- QFileInfo info(path);
- if (!info.isDir())
- return info.fileName();
+ // default case, re-use QFileInfo to avoid stat'ing
+ const QFileInfo local(url.toLocalFile());
+ // Get the initial directory URL
+ if (!url.isEmpty())
+ directory = _qt_get_directory(url, local);
+ if (directory.isEmpty()) {
+ const QUrl lastVisited = *lastVisitedDir();
+ if (lastVisited != url)
+ directory = _qt_get_directory(lastVisited, QFileInfo());
}
- return QString();
+ if (directory.isEmpty())
+ directory = QUrl::fromLocalFile(QDir::currentPath());
+
+ /*
+ The initial directory can contain both the initial directory
+ and initial selection, e.g. /home/user/foo.txt
+ */
+ if (selection.isEmpty() && !url.isEmpty()) {
+ if (url.isLocalFile()) {
+ if (!local.isDir())
+ selection = local.fileName();
+ } else {
+ // With remote URLs we can only assume.
+ selection = url.fileName();
+ }
+ }
}
/*!
@@ -2139,51 +2652,77 @@
if (d->receiverToDisconnectOnClose) {
disconnect(this, d->signalToDisconnectOnClose,
d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);
- d->receiverToDisconnectOnClose = 0;
+ d->receiverToDisconnectOnClose = nullptr;
}
d->memberToDisconnectOnClose.clear();
d->signalToDisconnectOnClose.clear();
}
+bool QFileDialogPrivate::itemAlreadyExists(const QString &fileName)
+{
+#if QT_CONFIG(messagebox)
+ Q_Q(QFileDialog);
+ const QString msg = QFileDialog::tr("%1 already exists.\nDo you want to replace it?").arg(fileName);
+ using B = QMessageBox;
+ const auto res = B::warning(q, q->windowTitle(), msg, B::Yes | B::No, B::No);
+ return res == B::Yes;
+#endif
+ return false;
+}
+
+void QFileDialogPrivate::itemNotFound(const QString &fileName, QFileDialog::FileMode mode)
+{
+#if QT_CONFIG(messagebox)
+ Q_Q(QFileDialog);
+ const QString message = mode == QFileDialog::Directory
+ ? QFileDialog::tr("%1\nDirectory not found.\n"
+ "Please verify the correct directory name was given.")
+ : QFileDialog::tr("%1\nFile not found.\nPlease verify the "
+ "correct file name was given.");
+
+ QMessageBox::warning(q, q->windowTitle(), message.arg(fileName));
+#endif // QT_CONFIG(messagebox)
+}
+
/*!
\reimp
*/
void QFileDialog::accept()
{
Q_D(QFileDialog);
- QStringList files = selectedFiles();
- if (files.isEmpty())
- return;
- if (d->nativeDialogInUse){
- d->emitFilesSelected(files);
+ if (!d->usingWidgets()) {
+ const QList urls = selectedUrls();
+ if (urls.isEmpty())
+ return;
+ d->_q_emitUrlsSelected(urls);
+ if (urls.size() == 1)
+ d->_q_emitUrlSelected(urls.first());
QDialog::accept();
return;
}
+ const QStringList files = selectedFiles();
+ if (files.isEmpty())
+ 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("..")) {
+ if (lineEditText == ".."_L1) {
d->_q_navigateToParent();
- bool block = d->qFileDialogUi->fileNameEdit->blockSignals(true);
+ const QSignalBlocker blocker(d->qFileDialogUi->fileNameEdit);
d->lineEdit()->selectAll();
- d->qFileDialogUi->fileNameEdit->blockSignals(block);
return;
}
- switch (d->fileMode) {
- case DirectoryOnly:
+ const auto mode = fileMode();
+ switch (mode) {
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
+ d->itemNotFound(info.fileName(), mode);
return;
}
if (info.isDir()) {
@@ -2202,42 +2741,32 @@
}
if (!info.exists()) {
- int maxNameLength = d->maxNameLength(info.path());
- if (maxNameLength >= 0 && info.fileName().length() > maxNameLength)
+ const long maxNameLength = d->maxNameLength(info.path());
+ if (maxNameLength >= 0 && info.fileName().size() > maxNameLength)
return;
}
// check if we have to ask for permission to overwrite the file
- if (!info.exists() || !confirmOverwrite() || acceptMode() == AcceptOpen) {
+ if (!info.exists() || testOption(DontConfirmOverwrite) || 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) {
+ if (d->itemAlreadyExists(info.fileName())) {
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));
+ for (const auto &file : files) {
+ QFileInfo info(file);
if (!info.exists())
- info = QFileInfo(d->getEnvironmentVariable(files.at(i)));
+ info = QFileInfo(d->getEnvironmentVariable(file));
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
+ d->itemNotFound(info.fileName(), mode);
return;
}
if (info.isDir()) {
@@ -2252,32 +2781,147 @@
}
}
+#if QT_CONFIG(settings)
+void QFileDialogPrivate::saveSettings()
+{
+ Q_Q(QFileDialog);
+ QSettings settings(QSettings::UserScope, u"QtProject"_s);
+ settings.beginGroup("FileDialog");
+
+ if (usingWidgets()) {
+ settings.setValue("sidebarWidth", qFileDialogUi->splitter->sizes().constFirst());
+ settings.setValue("shortcuts", QUrl::toStringList(qFileDialogUi->sidebar->urls()));
+ settings.setValue("treeViewHeader", qFileDialogUi->treeView->header()->saveState());
+ }
+ QStringList historyUrls;
+ const QStringList history = q->history();
+ historyUrls.reserve(history.size());
+ for (const QString &path : history)
+ historyUrls << QUrl::fromLocalFile(path).toString();
+ settings.setValue("history", historyUrls);
+ settings.setValue("lastVisited", lastVisitedDir()->toString());
+ const QMetaEnum &viewModeMeta = q->metaObject()->enumerator(q->metaObject()->indexOfEnumerator("ViewMode"));
+ settings.setValue("viewMode", QLatin1StringView(viewModeMeta.key(q->viewMode())));
+ settings.setValue("qtVersion", QT_VERSION_STR ""_L1);
+}
+
+bool QFileDialogPrivate::restoreFromSettings()
+{
+ Q_Q(QFileDialog);
+ QSettings settings(QSettings::UserScope, u"QtProject"_s);
+ if (!settings.childGroups().contains("FileDialog"_L1))
+ return false;
+ settings.beginGroup("FileDialog");
+
+ q->setDirectoryUrl(lastVisitedDir()->isEmpty() ? settings.value("lastVisited").toUrl() : *lastVisitedDir());
+
+ QByteArray viewModeStr = settings.value("viewMode").toString().toLatin1();
+ const QMetaEnum &viewModeMeta = q->metaObject()->enumerator(q->metaObject()->indexOfEnumerator("ViewMode"));
+ bool ok = false;
+ int viewMode = viewModeMeta.keyToValue(viewModeStr.constData(), &ok);
+ if (!ok)
+ viewMode = QFileDialog::List;
+ q->setViewMode(static_cast(viewMode));
+
+ sidebarUrls = QUrl::fromStringList(settings.value("shortcuts").toStringList());
+ headerData = settings.value("treeViewHeader").toByteArray();
+
+ if (!usingWidgets())
+ return true;
+
+ QStringList history;
+ const auto urlStrings = settings.value("history").toStringList();
+ for (const QString &urlStr : urlStrings) {
+ QUrl url(urlStr);
+ if (url.isLocalFile())
+ history << url.toLocalFile();
+ }
+
+ return restoreWidgetState(history, settings.value("sidebarWidth", -1).toInt());
+}
+#endif // settings
+
+bool QFileDialogPrivate::restoreWidgetState(QStringList &history, int splitterPosition)
+{
+ Q_Q(QFileDialog);
+ if (splitterPosition >= 0) {
+ QList splitterSizes;
+ splitterSizes.append(splitterPosition);
+ splitterSizes.append(qFileDialogUi->splitter->widget(1)->sizeHint().width());
+ qFileDialogUi->splitter->setSizes(splitterSizes);
+ } else {
+ if (!qFileDialogUi->splitter->restoreState(splitterState))
+ return false;
+ QList list = qFileDialogUi->splitter->sizes();
+ if (list.size() >= 2 && (list.at(0) == 0 || list.at(1) == 0)) {
+ for (int i = 0; i < list.size(); ++i)
+ list[i] = qFileDialogUi->splitter->widget(i)->sizeHint().width();
+ qFileDialogUi->splitter->setSizes(list);
+ }
+ }
+
+ qFileDialogUi->sidebar->setUrls(sidebarUrls);
+
+ static const int MaxHistorySize = 5;
+ if (history.size() > MaxHistorySize)
+ history.erase(history.begin(), history.end() - MaxHistorySize);
+ q->setHistory(history);
+
+ QHeaderView *headerView = qFileDialogUi->treeView->header();
+ if (!headerView->restoreState(headerData))
+ return false;
+
+ QList actions = headerView->actions();
+ QAbstractItemModel *abstractModel = model;
+#if QT_CONFIG(proxymodel)
+ if (proxyModel)
+ abstractModel = proxyModel;
+#endif
+ const int total = qMin(abstractModel->columnCount(QModelIndex()), int(actions.size() + 1));
+ for (int i = 1; i < total; ++i)
+ actions.at(i - 1)->setChecked(!headerView->isSectionHidden(i));
+
+ return true;
+}
+
/*!
\internal
Create widgets, layout and set default values
*/
-void QFileDialogPrivate::init(const QString &directory, const QString &nameFilter,
- const QString &caption)
+void QFileDialogPrivate::init(const QFileDialogArgs &args)
{
Q_Q(QFileDialog);
- if (!caption.isEmpty()) {
+ if (!args.caption.isEmpty()) {
useDefaultCaption = false;
- setWindowTitle = caption;
- q->setWindowTitle(caption);
+ setWindowTitle = args.caption;
+ q->setWindowTitle(args.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());
+ q->setAcceptMode(QFileDialog::AcceptOpen);
+ nativeDialogInUse = platformFileDialogHelper() != nullptr;
+ if (!nativeDialogInUse)
+ createWidgets();
+ q->setFileMode(QFileDialog::AnyFile);
+ if (!args.filter.isEmpty())
+ q->setNameFilter(args.filter);
+ // QTBUG-70798, prevent the default blocking the restore logic.
+ const bool dontStoreDir = !args.directory.isValid() && !lastVisitedDir()->isValid();
+ q->setDirectoryUrl(args.directory);
+ if (dontStoreDir)
+ lastVisitedDir()->clear();
+ if (args.directory.isLocalFile())
+ q->selectFile(args.selection);
+ else
+ q->selectUrl(args.directory);
+
+#if QT_CONFIG(settings)
+ // Try to restore from the FileDialog settings group; if it fails, fall back
+ // to the pre-5.5 QByteArray serialized settings.
+ if (!restoreFromSettings()) {
+ const QSettings settings(QSettings::UserScope, u"QtProject"_s);
+ q->restoreState(settings.value("Qt/filedialog").toByteArray());
+ }
#endif
#if defined(Q_EMBEDDED_SMALLSCREEN)
@@ -2286,15 +2930,10 @@
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());
+
+ const QSize sizeHint = q->sizeHint();
+ if (sizeHint.isValid())
+ q->resize(sizeHint);
}
/*!
@@ -2304,14 +2943,24 @@
*/
void QFileDialogPrivate::createWidgets()
{
+ if (qFileDialogUi)
+ return;
Q_Q(QFileDialog);
+
+ // This function is sometimes called late (e.g as a fallback from setVisible). In that case we
+ // need to ensure that the following UI code (setupUI in particular) doesn't reset any explicitly
+ // set window state or geometry.
+ QSize preSize = q->testAttribute(Qt::WA_Resized) ? q->size() : QSize();
+ Qt::WindowStates preState = q->windowState();
+
model = new QFileSystemModel(q);
- model->setObjectName(QLatin1String("qt_filesystem_model"));
-#ifdef Q_WS_MAC
- model->setNameFilterDisables(true);
-#else
- model->setNameFilterDisables(false);
-#endif
+ model->setIconProvider(&defaultIconProvider);
+ model->setFilter(options->filter());
+ model->setObjectName("qt_filesystem_model"_L1);
+ if (QPlatformFileDialogHelper *helper = platformFileDialogHelper())
+ model->setNameFilterDisables(helper->defaultNameFilterDisables());
+ else
+ model->setNameFilterDisables(false);
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)),
@@ -2324,31 +2973,33 @@
qFileDialogUi->setupUi(q);
QList initialBookmarks;
- initialBookmarks << QUrl::fromLocalFile(QLatin1String(""))
+ initialBookmarks << QUrl("file:"_L1)
<< QUrl::fromLocalFile(QDir::homePath());
- qFileDialogUi->sidebar->init(model, initialBookmarks);
+ qFileDialogUi->sidebar->setModelAndUrls(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->setFileDialogPrivate(this);
+ QObject::connect(qFileDialogUi->lookInCombo, SIGNAL(textActivated(QString)), q, SLOT(_q_goToDirectory(QString)));
qFileDialogUi->lookInCombo->setInsertPolicy(QComboBox::NoInsert);
qFileDialogUi->lookInCombo->setDuplicatesEnabled(false);
// filename
- qFileDialogUi->fileNameEdit->init(this);
+ qFileDialogUi->fileNameEdit->setFileDialogPrivate(this);
#ifndef QT_NO_SHORTCUT
qFileDialogUi->fileNameLabel->setBuddy(qFileDialogUi->fileNameEdit);
#endif
-#ifndef QT_NO_FSCOMPLETER
+#if QT_CONFIG(fscompleter)
completer = new QFSCompleter(model, q);
qFileDialogUi->fileNameEdit->setCompleter(completer);
-#endif // QT_NO_FSCOMPLETER
+#endif // QT_CONFIG(fscompleter)
+
+ qFileDialogUi->fileNameEdit->setInputMethodHints(Qt::ImhNoPredictiveText);
+
QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(textChanged(QString)),
q, SLOT(_q_autoCompleteFileName(QString)));
QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(textChanged(QString)),
@@ -2358,42 +3009,41 @@
// filetype
qFileDialogUi->fileTypeCombo->setDuplicatesEnabled(false);
- qFileDialogUi->fileTypeCombo->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength);
+ qFileDialogUi->fileTypeCombo->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);
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)),
+ QObject::connect(qFileDialogUi->fileTypeCombo, SIGNAL(textActivated(QString)),
q, SIGNAL(filterSelected(QString)));
- qFileDialogUi->listView->init(this);
+ qFileDialogUi->listView->setFileDialogPrivate(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")));
+ QShortcut *shortcut = new QShortcut(QKeySequence::Delete, qFileDialogUi->listView);
QObject::connect(shortcut, SIGNAL(activated()), q, SLOT(_q_deleteCurrent()));
#endif
- qFileDialogUi->treeView->init(this);
+ qFileDialogUi->treeView->setFileDialogPrivate(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->resizeSection(0, fm.horizontalAdvance("wwwwwwwwwwwwwwwwwwwwwwwwww"_L1));
+ treeHeader->resizeSection(1, fm.horizontalAdvance("128.88 GB"_L1));
+ treeHeader->resizeSection(2, fm.horizontalAdvance("mp3Folder"_L1));
+ treeHeader->resizeSection(3, fm.horizontalAdvance("10/29/81 02:02PM"_L1));
treeHeader->setContextMenuPolicy(Qt::ActionsContextMenu);
QActionGroup *showActionGroup = new QActionGroup(q);
showActionGroup->setExclusive(false);
QObject::connect(showActionGroup, SIGNAL(triggered(QAction*)),
- q, SLOT(_q_showHeader(QAction*)));
+ q, SLOT(_q_showHeader(QAction*)));;
QAbstractItemModel *abstractModel = model;
-#ifndef QT_NO_PROXYMODEL
+#if QT_CONFIG(proxymodel)
if (proxyModel)
abstractModel = proxyModel;
#endif
@@ -2412,8 +3062,7 @@
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")));
+ shortcut = new QShortcut(QKeySequence::Delete, qFileDialogUi->treeView);
QObject::connect(shortcut, SIGNAL(activated()), q, SLOT(_q_deleteCurrent()));
#endif
@@ -2426,16 +3075,56 @@
qFileDialogUi->splitter->setStretchFactor(qFileDialogUi->splitter->indexOf(qFileDialogUi->splitter->widget(1)), QSizePolicy::Expanding);
createToolButtons();
+ createMenuActions();
+
+#if QT_CONFIG(settings)
+ // Try to restore from the FileDialog settings group; if it fails, fall back
+ // to the pre-5.5 QByteArray serialized settings.
+ if (!restoreFromSettings()) {
+ const QSettings settings(QSettings::UserScope, u"QtProject"_s);
+ q->restoreState(settings.value("Qt/filedialog").toByteArray());
+ }
+#endif
+
+ // Initial widget states from options
+ q->setFileMode(static_cast(options->fileMode()));
+ q->setAcceptMode(static_cast(options->acceptMode()));
+ q->setViewMode(static_cast(options->viewMode()));
+ q->setOptions(static_cast(static_cast(options->options())));
+ if (!options->sidebarUrls().isEmpty())
+ q->setSidebarUrls(options->sidebarUrls());
+ q->setDirectoryUrl(options->initialDirectory());
+#if QT_CONFIG(mimetype)
+ if (!options->mimeTypeFilters().isEmpty())
+ q->setMimeTypeFilters(options->mimeTypeFilters());
+ else
+#endif
+ if (!options->nameFilters().isEmpty())
+ q->setNameFilters(options->nameFilters());
+ q->selectNameFilter(options->initiallySelectedNameFilter());
+ q->setDefaultSuffix(options->defaultSuffix());
+ q->setHistory(options->history());
+ const auto initiallySelectedFiles = options->initiallySelectedFiles();
+ if (initiallySelectedFiles.size() == 1)
+ q->selectFile(initiallySelectedFiles.first().fileName());
+ for (const QUrl &url : initiallySelectedFiles)
+ q->selectUrl(url);
+ lineEdit()->selectAll();
+ _q_updateOkButton();
+ retranslateStrings();
+ q->resize(preSize.isValid() ? preSize : q->sizeHint());
+ q->setWindowState(preState);
}
void QFileDialogPrivate::_q_showHeader(QAction *action)
{
Q_Q(QFileDialog);
QActionGroup *actionGroup = qobject_cast(q->sender());
- qFileDialogUi->treeView->header()->setSectionHidden(actionGroup->actions().indexOf(action) + 1, !action->isChecked());
+ qFileDialogUi->treeView->header()->setSectionHidden(int(actionGroup->actions().indexOf(action) + 1),
+ !action->isChecked());
}
-#ifndef QT_NO_PROXYMODEL
+#if QT_CONFIG(proxymodel)
/*!
\since 4.3
@@ -2451,6 +3140,8 @@
void QFileDialog::setProxyModel(QAbstractProxyModel *proxyModel)
{
Q_D(QFileDialog);
+ if (!d->usingWidgets())
+ return;
if ((!proxyModel && !d->proxyModel)
|| (proxyModel == d->proxyModel))
return;
@@ -2464,26 +3155,26 @@
this, SLOT(_q_rowsInserted(QModelIndex)));
}
- if (proxyModel != 0) {
+ if (proxyModel != nullptr) {
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
+#if QT_CONFIG(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->proxyModel = nullptr;
d->qFileDialogUi->listView->setModel(d->model);
d->qFileDialogUi->treeView->setModel(d->model);
-#ifndef QT_NO_FSCOMPLETER
+#if QT_CONFIG(fscompleter)
d->completer->setModel(d->model);
d->completer->sourceModel = d->model;
- d->completer->proxyModel = 0;
+ d->completer->proxyModel = nullptr;
#endif
connect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
this, SLOT(_q_rowsInserted(QModelIndex)));
@@ -2511,7 +3202,7 @@
Q_D(const QFileDialog);
return d->proxyModel;
}
-#endif // QT_NO_PROXYMODEL
+#endif // QT_CONFIG(proxymodel)
/*!
\internal
@@ -2521,27 +3212,27 @@
void QFileDialogPrivate::createToolButtons()
{
Q_Q(QFileDialog);
- qFileDialogUi->backButton->setIcon(q->style()->standardIcon(QStyle::SP_ArrowBack, 0, q));
+ qFileDialogUi->backButton->setIcon(q->style()->standardIcon(QStyle::SP_ArrowBack, nullptr, 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->setIcon(q->style()->standardIcon(QStyle::SP_ArrowForward, nullptr, 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->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogToParent, nullptr, 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->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogListView, nullptr, 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->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogDetailedView, nullptr, q));
qFileDialogUi->detailModeButton->setAutoRaise(true);
QObject::connect(qFileDialogUi->detailModeButton, SIGNAL(clicked()), q, SLOT(_q_showDetailsView()));
@@ -2552,7 +3243,7 @@
qFileDialogUi->forwardButton->setFixedSize(toolSize);
qFileDialogUi->toParentButton->setFixedSize(toolSize);
- qFileDialogUi->newFolderButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogNewFolder, 0, q));
+ qFileDialogUi->newFolderButton->setIcon(q->style()->standardIcon(QStyle::SP_FileDialogNewFolder, nullptr, q));
qFileDialogUi->newFolderButton->setFixedSize(toolSize);
qFileDialogUi->newFolderButton->setAutoRaise(true);
qFileDialogUi->newFolderButton->setEnabled(false);
@@ -2570,7 +3261,7 @@
QAction *goHomeAction = new QAction(q);
#ifndef QT_NO_SHORTCUT
- goHomeAction->setShortcut(Qt::CTRL + Qt::Key_H + Qt::SHIFT);
+ goHomeAction->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_H);
#endif
QObject::connect(goHomeAction, SIGNAL(triggered()), q, SLOT(_q_goHome()));
q->addAction(goHomeAction);
@@ -2578,30 +3269,30 @@
// ### TODO add Desktop & Computer actions
QAction *goToParent = new QAction(q);
- goToParent->setObjectName(QLatin1String("qt_goto_parent_action"));
+ goToParent->setObjectName("qt_goto_parent_action"_L1);
#ifndef QT_NO_SHORTCUT
- goToParent->setShortcut(Qt::CTRL + Qt::UpArrow);
+ goToParent->setShortcut(Qt::CTRL | Qt::Key_Up);
#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"));
+ renameAction->setObjectName("qt_rename_action"_L1);
QObject::connect(renameAction, SIGNAL(triggered()), q, SLOT(_q_renameCurrent()));
deleteAction = new QAction(q);
deleteAction->setEnabled(false);
- deleteAction->setObjectName(QLatin1String("qt_delete_action"));
+ deleteAction->setObjectName("qt_delete_action"_L1);
QObject::connect(deleteAction, SIGNAL(triggered()), q, SLOT(_q_deleteCurrent()));
showHiddenAction = new QAction(q);
- showHiddenAction->setObjectName(QLatin1String("qt_show_hidden_action"));
+ showHiddenAction->setObjectName("qt_show_hidden_action"_L1);
showHiddenAction->setCheckable(true);
QObject::connect(showHiddenAction, SIGNAL(triggered()), q, SLOT(_q_showHidden()));
newFolderAction = new QAction(q);
- newFolderAction->setObjectName(QLatin1String("qt_new_folder_action"));
+ newFolderAction->setObjectName("qt_new_folder_action"_L1);
QObject::connect(newFolderAction, SIGNAL(triggered()), q, SLOT(_q_createDirectory()));
}
@@ -2611,6 +3302,18 @@
q->setDirectory(QDir::homePath());
}
+
+void QFileDialogPrivate::saveHistorySelection()
+{
+ if (qFileDialogUi.isNull() || currentHistoryLocation < 0 || currentHistoryLocation >= currentHistory.size())
+ return;
+ auto &item = currentHistory[currentHistoryLocation];
+ item.selection.clear();
+ const auto selectedIndexes = qFileDialogUi->listView->selectionModel()->selectedRows();
+ for (const auto &index : selectedIndexes)
+ item.selection.append(QPersistentModelIndex(index));
+}
+
/*!
\internal
@@ -2619,22 +3322,55 @@
void QFileDialogPrivate::_q_pathChanged(const QString &newPath)
{
Q_Q(QFileDialog);
- QDir dir(model->rootDirectory());
- qFileDialogUi->toParentButton->setEnabled(dir.exists());
+ qFileDialogUi->toParentButton->setEnabled(QFileInfo::exists(model->rootPath()));
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()) {
+ const QString newNativePath = QDir::toNativeSeparators(newPath);
+
+ // equal paths indicate this was invoked by _q_navigateBack/Forward()
+ if (currentHistoryLocation < 0 || currentHistory.value(currentHistoryLocation).path != newNativePath) {
+ if (currentHistoryLocation >= 0)
+ saveHistorySelection();
+ while (currentHistoryLocation >= 0 && currentHistoryLocation + 1 < currentHistory.size()) {
currentHistory.removeLast();
}
- currentHistory.append(QDir::toNativeSeparators(newPath));
+ currentHistory.append({newNativePath, PersistentModelIndexList()});
++currentHistoryLocation;
}
qFileDialogUi->forwardButton->setEnabled(currentHistory.size() - currentHistoryLocation > 1);
qFileDialogUi->backButton->setEnabled(currentHistoryLocation > 0);
}
+void QFileDialogPrivate::navigate(HistoryItem &historyItem)
+{
+ Q_Q(QFileDialog);
+ q->setDirectory(historyItem.path);
+ // Restore selection unless something has changed in the file system
+ if (qFileDialogUi.isNull() || historyItem.selection.isEmpty())
+ return;
+ if (std::any_of(historyItem.selection.cbegin(), historyItem.selection.cend(),
+ [](const QPersistentModelIndex &i) { return !i.isValid(); })) {
+ historyItem.selection.clear();
+ return;
+ }
+
+ QAbstractItemView *view = q->viewMode() == QFileDialog::List
+ ? static_cast(qFileDialogUi->listView)
+ : static_cast(qFileDialogUi->treeView);
+ auto selectionModel = view->selectionModel();
+ const QItemSelectionModel::SelectionFlags flags = QItemSelectionModel::Select
+ | QItemSelectionModel::Rows;
+ selectionModel->select(historyItem.selection.constFirst(),
+ flags | QItemSelectionModel::Clear | QItemSelectionModel::Current);
+ auto it = historyItem.selection.cbegin() + 1;
+ const auto end = historyItem.selection.cend();
+ for (; it != end; ++it)
+ selectionModel->select(*it, flags);
+
+ view->scrollTo(historyItem.selection.constFirst());
+}
+
/*!
\internal
@@ -2642,11 +3378,9 @@
*/
void QFileDialogPrivate::_q_navigateBackward()
{
- Q_Q(QFileDialog);
if (!currentHistory.isEmpty() && currentHistoryLocation > 0) {
- --currentHistoryLocation;
- QString previousHistory = currentHistory.at(currentHistoryLocation);
- q->setDirectory(previousHistory);
+ saveHistorySelection();
+ navigate(currentHistory[--currentHistoryLocation]);
}
}
@@ -2657,11 +3391,9 @@
*/
void QFileDialogPrivate::_q_navigateForward()
{
- Q_Q(QFileDialog);
if (!currentHistory.isEmpty() && currentHistoryLocation < currentHistory.size() - 1) {
- ++currentHistoryLocation;
- QString nextHistory = currentHistory.at(currentHistoryLocation);
- q->setDirectory(nextHistory);
+ saveHistorySelection();
+ navigate(currentHistory[++currentHistoryLocation]);
}
}
@@ -2745,11 +3477,11 @@
*/
void QFileDialogPrivate::_q_showContextMenu(const QPoint &position)
{
-#ifdef QT_NO_MENU
+#if !QT_CONFIG(menu)
Q_UNUSED(position);
#else
Q_Q(QFileDialog);
- QAbstractItemView *view = 0;
+ QAbstractItemView *view = nullptr;
if (q->viewMode() == QFileDialog::Detail)
view = qFileDialogUi->treeView;
else
@@ -2757,23 +3489,27 @@
QModelIndex index = view->indexAt(position);
index = mapToSource(index.sibling(index.row(), 0));
- QMenu menu(view);
+ QMenu *menu = new QMenu(view);
+ menu->setAttribute(Qt::WA_DeleteOnClose);
+
if (index.isValid()) {
// file context menu
+ const bool ro = model && model->isReadOnly();
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();
+ renameAction->setEnabled(!ro && p & QFile::WriteUser);
+ menu->addAction(renameAction);
+ deleteAction->setEnabled(!ro && p & QFile::WriteUser);
+ menu->addAction(deleteAction);
+ menu->addSeparator();
}
- menu.addAction(showHiddenAction);
+ menu->addAction(showHiddenAction);
if (qFileDialogUi->newFolderButton->isVisible()) {
newFolderAction->setEnabled(qFileDialogUi->newFolderButton->isEnabled());
- menu.addAction(newFolderAction);
+ menu->addAction(newFolderAction);
}
- menu.exec(view->viewport()->mapToGlobal(position));
-#endif // QT_NO_MENU
+ menu->popup(view->viewport()->mapToGlobal(position));
+
+#endif // QT_CONFIG(menu)
}
/*!
@@ -2806,9 +3542,9 @@
if (model->isReadOnly())
return;
- QModelIndexList list = qFileDialogUi->listView->selectionModel()->selectedRows();
- for (int i = list.count() - 1; i >= 0; --i) {
- QModelIndex index = list.at(i);
+ const QModelIndexList list = qFileDialogUi->listView->selectionModel()->selectedRows();
+ for (auto it = list.crbegin(), end = list.crend(); it != end; ++it) {
+ QPersistentModelIndex index = *it;
if (index == qFileDialogUi->listView->rootIndex())
continue;
@@ -2816,33 +3552,35 @@
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;
+ QString fileName = index.data(QFileSystemModel::FileNameRole).toString();
+ QString filePath = index.data(QFileSystemModel::FilePathRole).toString();
+
+ QFile::Permissions p(index.parent().data(QFileSystemModel::FilePermissions).toInt());
+#if QT_CONFIG(messagebox)
+ Q_Q(QFileDialog);
+ if (!(p & QFile::WriteUser) && (QMessageBox::warning(q_func(), QFileDialog::tr("Delete"),
+ 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(), QFileDialog::tr("Delete"),
+ QFileDialog::tr("Are you sure you want to delete '%1'?")
+ .arg(fileName),
+ QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No)
+ return;
+
+ // the event loop has run, we have to validate if the index is valid because the model might have removed it.
+ if (!index.isValid())
+ 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 (!(p & QFile::WriteUser))
+ return;
+#endif // QT_CONFIG(messagebox)
+
+ if (model->isDir(index) && !model->fileInfo(index).isSymLink()) {
if (!removeDirectory(filePath)) {
-#ifndef QT_NO_MESSAGEBOX
+#if QT_CONFIG(messagebox)
QMessageBox::warning(q, q->windowTitle(),
QFileDialog::tr("Could not delete directory."));
#endif
@@ -2855,28 +3593,27 @@
void QFileDialogPrivate::_q_autoCompleteFileName(const QString &text)
{
- if (text.startsWith(QLatin1String("//")) || text.startsWith(QLatin1Char('\\'))) {
+ if (text.startsWith("//"_L1) || text.startsWith(u'\\')) {
qFileDialogUi->listView->selectionModel()->clearSelection();
return;
}
- QStringList multipleFiles = typedFiles();
- if (multipleFiles.count() > 0) {
+ const QStringList multipleFiles = typedFiles();
+ if (multipleFiles.size() > 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
+ QList newFiles;
+ for (const auto &file : multipleFiles) {
+ QModelIndex idx = model->index(file);
+ if (oldFiles.removeAll(idx) == 0)
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);
+ for (const auto &newFile : std::as_const(newFiles))
+ select(newFile);
+ if (lineEdit()->hasFocus()) {
+ auto *sm = qFileDialogUi->listView->selectionModel();
+ for (const auto &oldFile : std::as_const(oldFiles))
+ sm->select(oldFile, QItemSelectionModel::Toggle | QItemSelectionModel::Rows);
+ }
}
}
@@ -2886,31 +3623,30 @@
void QFileDialogPrivate::_q_updateOkButton()
{
Q_Q(QFileDialog);
- QPushButton *button = qFileDialogUi->buttonBox->button((acceptMode == QFileDialog::AcceptOpen)
+ QPushButton *button = qFileDialogUi->buttonBox->button((q->acceptMode() == QFileDialog::AcceptOpen)
? QDialogButtonBox::Open : QDialogButtonBox::Save);
if (!button)
return;
+ const QFileDialog::FileMode fileMode = q->fileMode();
bool enableButton = true;
bool isOpenDirectory = false;
- QStringList files = q->selectedFiles();
+ const QStringList files = q->selectedFiles();
QString lineEditText = lineEdit()->text();
- if (lineEditText.startsWith(QLatin1String("//")) || lineEditText.startsWith(QLatin1Char('\\'))) {
+ if (lineEditText.startsWith("//"_L1) || lineEditText.startsWith(u'\\')) {
button->setEnabled(true);
- if (acceptMode == QFileDialog::AcceptSave)
- button->setText(acceptLabel);
+ updateOkButtonText();
return;
}
if (files.isEmpty()) {
enableButton = false;
- } else if (lineEditText == QLatin1String("..")) {
+ } else if (lineEditText == ".."_L1) {
isOpenDirectory = true;
} else {
switch (fileMode) {
- case QFileDialog::DirectoryOnly:
case QFileDialog::Directory: {
QString fn = files.first();
QModelIndex idx = model->index(fn);
@@ -2929,10 +3665,10 @@
if (info.isDir()) {
fileDir = info.canonicalFilePath();
} else {
- fileDir = fn.mid(0, fn.lastIndexOf(QLatin1Char('/')));
- fileName = fn.mid(fileDir.length() + 1);
+ fileDir = fn.mid(0, fn.lastIndexOf(u'/'));
+ fileName = fn.mid(fileDir.size() + 1);
}
- if (lineEditText.contains(QLatin1String(".."))) {
+ if (lineEditText.contains(".."_L1)) {
fileDir = info.canonicalFilePath();
fileName = info.fileName();
}
@@ -2947,17 +3683,17 @@
break;
}
if (!idx.isValid()) {
- int maxLength = maxNameLength(fileDir);
- enableButton = maxLength < 0 || fileName.length() <= maxLength;
+ const long maxLength = maxNameLength(fileDir);
+ enableButton = maxLength < 0 || fileName.size() <= maxLength;
}
break;
}
case QFileDialog::ExistingFile:
case QFileDialog::ExistingFiles:
- for (int i = 0; i < files.count(); ++i) {
- QModelIndex idx = model->index(files.at(i));
+ for (const auto &file : files) {
+ QModelIndex idx = model->index(file);
if (!idx.isValid())
- idx = model->index(getEnvironmentVariable(files.at(i)));
+ idx = model->index(getEnvironmentVariable(file));
if (!idx.isValid()) {
enableButton = false;
break;
@@ -2974,8 +3710,7 @@
}
button->setEnabled(enableButton);
- if (acceptMode == QFileDialog::AcceptSave)
- button->setText(isOpenDirectory ? QFileDialog::tr("&Open") : acceptLabel);
+ updateOkButtonText(isOpenDirectory);
}
/*!
@@ -3000,18 +3735,18 @@
QModelIndex sourceIndex = index.model() == proxyModel ? mapToSource(index) : index;
QString path = sourceIndex.data(QFileSystemModel::FilePathRole).toString();
if (path.isEmpty() || model->isDir(sourceIndex)) {
+ const QFileDialog::FileMode fileMode = q->fileMode();
q->setDirectory(path);
emit q->directoryEntered(path);
- if (fileMode == QFileDialog::Directory
- || fileMode == QFileDialog::DirectoryOnly) {
+ if (fileMode == QFileDialog::Directory) {
// ### find out why you have to do both of these.
lineEdit()->setText(QString());
lineEdit()->clear();
}
} else {
// Do not accept when shift-clicking to multi-select a file in environments with single-click-activation (KDE)
- if (!q->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick)
- || q->fileMode() != QFileDialog::ExistingFiles || !(QApplication::keyboardModifiers() & Qt::CTRL)) {
+ if (!q->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, nullptr, qFileDialogUi->treeView)
+ || q->fileMode() != QFileDialog::ExistingFiles || !(QGuiApplication::keyboardModifiers() & Qt::CTRL)) {
q->accept();
}
}
@@ -3025,7 +3760,9 @@
*/
void QFileDialogPrivate::_q_goToDirectory(const QString &path)
{
- #ifndef QT_NO_MESSAGEBOX
+ enum { UrlRole = Qt::UserRole + 1 };
+
+ #if QT_CONFIG(messagebox)
Q_Q(QFileDialog);
#endif
QModelIndex index = qFileDialogUi->lookInCombo->model()->index(qFileDialogUi->lookInCombo->currentIndex(),
@@ -3040,30 +3777,19 @@
}
QDir dir(path2);
if (!dir.exists())
- dir = getEnvironmentVariable(path2);
+ dir.setPath(getEnvironmentVariable(path2));
if (dir.exists() || path2.isEmpty() || path2 == model->myComputer().toString()) {
_q_enterDirectory(index);
-#ifndef QT_NO_MESSAGEBOX
+#if QT_CONFIG(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
+#endif // QT_CONFIG(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
@@ -3072,23 +3798,25 @@
*/
void QFileDialogPrivate::_q_useNameFilter(int index)
{
+ QStringList nameFilters = options->nameFilters();
if (index == nameFilters.size()) {
QAbstractItemModel *comboModel = qFileDialogUi->fileTypeCombo->model();
nameFilters.append(comboModel->index(comboModel->rowCount() - 1, 0).data().toString());
+ options->setNameFilters(nameFilters);
}
QString nameFilter = nameFilters.at(index);
- QStringList newNameFilters = qt_clean_filter_list(nameFilter);
- if (acceptMode == QFileDialog::AcceptSave) {
+ QStringList newNameFilters = QPlatformFileDialogHelper::cleanFilterList(nameFilter);
+ if (q_func()->acceptMode() == QFileDialog::AcceptSave) {
QString newNameFilterExtension;
- if (newNameFilters.count() > 0)
+ if (newNameFilters.size() > 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,
+ const qsizetype fileNameExtensionLength = fileNameExtension.size();
+ fileName.replace(fileName.size() - fileNameExtensionLength,
fileNameExtensionLength, newNameFilterExtension);
qFileDialogUi->listView->clearSelection();
lineEdit()->setText(fileName);
@@ -3106,21 +3834,22 @@
*/
void QFileDialogPrivate::_q_selectionChanged()
{
- QModelIndexList indexes = qFileDialogUi->listView->selectionModel()->selectedRows();
- bool stripDirs = (fileMode != QFileDialog::DirectoryOnly && fileMode != QFileDialog::Directory);
+ const QFileDialog::FileMode fileMode = q_func()->fileMode();
+ const QModelIndexList indexes = qFileDialogUi->listView->selectionModel()->selectedRows();
+ bool stripDirs = fileMode != QFileDialog::Directory;
QStringList allFiles;
- for (int i = 0; i < indexes.count(); ++i) {
- if (stripDirs && model->isDir(mapToSource(indexes.at(i))))
+ for (const auto &index : indexes) {
+ if (stripDirs && model->isDir(mapToSource(index)))
continue;
- allFiles.append(indexes.at(i).data().toString());
+ allFiles.append(index.data().toString());
}
- if (allFiles.count() > 1)
- for (int i = 0; i < allFiles.count(); ++i) {
- allFiles.replace(i, QString(QLatin1Char('"') + allFiles.at(i) + QLatin1Char('"')));
+ if (allFiles.size() > 1)
+ for (qsizetype i = 0; i < allFiles.size(); ++i) {
+ allFiles.replace(i, QString(u'"' + allFiles.at(i) + u'"'));
}
- QString finalFiles = allFiles.join(QLatin1String(" "));
+ QString finalFiles = allFiles.join(u' ');
if (!finalFiles.isEmpty() && !lineEdit()->hasFocus() && lineEdit()->isVisible())
lineEdit()->setText(finalFiles);
else
@@ -3136,10 +3865,7 @@
{
Q_Q(QFileDialog);
QDir::Filters dirFilters = q->filter();
- if (showHiddenAction->isChecked())
- dirFilters |= QDir::Hidden;
- else
- dirFilters &= ~QDir::Hidden;
+ dirFilters.setFlag(QDir::Hidden, showHiddenAction->isChecked());
q->setFilter(dirFilters);
}
@@ -3159,31 +3885,77 @@
return;
}
-void QFileDialogPrivate::_q_fileRenamed(const QString &path, const QString oldName, const QString newName)
+void QFileDialogPrivate::_q_fileRenamed(const QString &path, const QString &oldName, const QString &newName)
{
- if (fileMode == QFileDialog::Directory || fileMode == QFileDialog::DirectoryOnly) {
+ const QFileDialog::FileMode fileMode = q_func()->fileMode();
+ if (fileMode == QFileDialog::Directory) {
if (path == rootPath() && lineEdit()->text() == oldName)
lineEdit()->setText(newName);
}
}
+void QFileDialogPrivate::_q_emitUrlSelected(const QUrl &file)
+{
+ Q_Q(QFileDialog);
+ emit q->urlSelected(file);
+ if (file.isLocalFile())
+ emit q->fileSelected(file.toLocalFile());
+}
+
+void QFileDialogPrivate::_q_emitUrlsSelected(const QList &files)
+{
+ Q_Q(QFileDialog);
+ emit q->urlsSelected(files);
+ QStringList localFiles;
+ for (const QUrl &file : files)
+ if (file.isLocalFile())
+ localFiles.append(file.toLocalFile());
+ if (!localFiles.isEmpty())
+ emit q->filesSelected(localFiles);
+}
+
+void QFileDialogPrivate::_q_nativeCurrentChanged(const QUrl &file)
+{
+ Q_Q(QFileDialog);
+ emit q->currentUrlChanged(file);
+ if (file.isLocalFile())
+ emit q->currentChanged(file.toLocalFile());
+}
+
+void QFileDialogPrivate::_q_nativeEnterDirectory(const QUrl &directory)
+{
+ Q_Q(QFileDialog);
+ emit q->directoryUrlEntered(directory);
+ if (!directory.isEmpty()) { // Windows native dialogs occasionally emit signals with empty strings.
+ *lastVisitedDir() = directory;
+ if (directory.isLocalFile())
+ emit q->directoryEntered(directory.toLocalFile());
+ }
+}
+
/*!
\internal
For the list and tree view watch keys to goto parent and back in the history
- returns true if handled
+ returns \c true if handled
*/
bool QFileDialogPrivate::itemViewKeyboardEvent(QKeyEvent *event) {
+#if QT_CONFIG(shortcut)
Q_Q(QFileDialog);
+ if (event->matches(QKeySequence::Cancel)) {
+ q->reject();
+ return true;
+ }
+#endif
switch (event->key()) {
case Qt::Key_Backspace:
_q_navigateToParent();
return true;
case Qt::Key_Back:
#ifdef QT_KEYPAD_NAVIGATION
- if (QApplication::keypadNavigationEnabled())
+ if (QApplicationPrivate::keypadNavigationEnabled())
return false;
#endif
case Qt::Key_Left:
@@ -3192,9 +3964,6 @@
return true;
}
break;
- case Qt::Key_Escape:
- q->hide();
- return true;
default:
break;
}
@@ -3204,18 +3973,18 @@
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()));
+ if (string.size() > 1 && string.startsWith(u'$')) {
+ return QString::fromLocal8Bit(qgetenv(QStringView{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()));
+ if (string.size() > 2 && string.startsWith(u'%') && string.endsWith(u'%')) {
+ return QString::fromLocal8Bit(qgetenv(QStringView{string}.mid(1, string.size() - 2).toLatin1().constData()));
}
#endif
return string;
}
-void QFileDialogComboBox::init(QFileDialogPrivate *d_pointer) {
+void QFileDialogComboBox::setFileDialogPrivate(QFileDialogPrivate *d_pointer) {
d_ptr = d_pointer;
urlModel = new QUrlModel(this);
urlModel->showFullPath = true;
@@ -3238,18 +4007,18 @@
idx = idx.parent();
}
// add "my computer"
- list.append(QUrl::fromLocalFile(QLatin1String("")));
+ list.append(QUrl("file:"_L1));
urlModel->addUrls(list, 0);
idx = model()->index(model()->rowCount() - 1, 0);
// append history
QList urls;
- for (int i = 0; i < m_history.count(); ++i) {
+ for (int i = 0; i < m_history.size(); ++i) {
QUrl path = QUrl::fromLocalFile(m_history.at(i));
if (!urls.contains(path))
urls.prepend(path);
}
- if (urls.count() > 0) {
+ if (urls.size() > 0) {
model()->insertRow(model()->rowCount());
idx = model()->index(model()->rowCount()-1, 0);
// ### TODO maybe add a horizontal line before this
@@ -3287,11 +4056,7 @@
painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
}
-QFileDialogListView::QFileDialogListView(QWidget *parent) : QListView(parent)
-{
-}
-
-void QFileDialogListView::init(QFileDialogPrivate *d_pointer)
+void QFileDialogListView::setFileDialogPrivate(QFileDialogPrivate *d_pointer)
{
d_ptr = d_pointer;
setSelectionBehavior(QAbstractItemView::SelectRows);
@@ -3299,7 +4064,7 @@
setResizeMode(QListView::Adjust);
setEditTriggers(QAbstractItemView::EditKeyPressed);
setContextMenuPolicy(Qt::CustomContextMenu);
-#ifndef QT_NO_DRAGANDDROP
+#if QT_CONFIG(draganddrop)
setDragDropMode(QAbstractItemView::InternalMove);
#endif
}
@@ -3324,11 +4089,7 @@
e->accept();
}
-QFileDialogTreeView::QFileDialogTreeView(QWidget *parent) : QTreeView(parent)
-{
-}
-
-void QFileDialogTreeView::init(QFileDialogPrivate *d_pointer)
+void QFileDialogTreeView::setFileDialogPrivate(QFileDialogPrivate *d_pointer)
{
d_ptr = d_pointer;
setSelectionBehavior(QAbstractItemView::SelectRows);
@@ -3340,7 +4101,7 @@
setTextElideMode(Qt::ElideMiddle);
setEditTriggers(QAbstractItemView::EditKeyPressed);
setContextMenuPolicy(Qt::CustomContextMenu);
-#ifndef QT_NO_DRAGANDDROP
+#if QT_CONFIG(draganddrop)
setDragDropMode(QAbstractItemView::InternalMove);
#endif
}
@@ -3379,18 +4140,17 @@
}
#endif // QT_KEYPAD_NAVIGATION
+#if QT_CONFIG(shortcut)
int key = e->key();
+#endif
QLineEdit::keyPressEvent(e);
- if (key != Qt::Key_Escape)
- e->accept();
- if (hideOnEsc && (key == Qt::Key_Escape || key == Qt::Key_Return || key == Qt::Key_Enter)) {
+#if QT_CONFIG(shortcut)
+ if (!e->matches(QKeySequence::Cancel) && key != Qt::Key_Back)
+#endif
e->accept();
- hide();
- d_ptr->currentView()->setFocus(Qt::ShortcutFocusReason);
- }
}
-#ifndef QT_NO_FSCOMPLETER
+#if QT_CONFIG(fscompleter)
QString QFSCompleter::pathFromIndex(const QModelIndex &index) const
{
@@ -3402,14 +4162,14 @@
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 defined(Q_OS_UNIX)
if (currentLocation == QDir::separator())
- return path.mid(currentLocation.length());
+ return path.remove(0, currentLocation.size());
#endif
- if (currentLocation.endsWith(QLatin1Char('/')))
- return path.mid(currentLocation.length());
+ if (currentLocation.endsWith(u'/'))
+ return path.remove(0, currentLocation.size());
else
- return path.mid(currentLocation.length()+1);
+ return path.remove(0, currentLocation.size()+1);
}
return index.data(QFileSystemModel::FilePathRole).toString();
}
@@ -3420,74 +4180,65 @@
return QStringList(completionPrefix());
QString pathCopy = QDir::toNativeSeparators(path);
- QString sep = QDir::separator();
-#if defined(Q_OS_SYMBIAN)
- if (pathCopy == QLatin1String("\\"))
+ QChar sep = QDir::separator();
+#if defined(Q_OS_WIN)
+ if (pathCopy == "\\"_L1 || pathCopy == "\\\\"_L1)
return QStringList(pathCopy);
-#elif defined(Q_OS_WIN)
- if (pathCopy == QLatin1String("\\") || pathCopy == QLatin1String("\\\\"))
- return QStringList(pathCopy);
- QString doubleSlash(QLatin1String("\\\\"));
+ QString doubleSlash("\\\\"_L1);
if (pathCopy.startsWith(doubleSlash))
pathCopy = pathCopy.mid(2);
else
doubleSlash.clear();
#elif defined(Q_OS_UNIX)
- bool expanded;
- pathCopy = qt_tildeExpansion(pathCopy, &expanded);
- if (expanded) {
- QFileSystemModel *dirModel;
- if (proxyModel)
- dirModel = qobject_cast(proxyModel->sourceModel());
- else
- dirModel = sourceModel;
- dirModel->fetchMore(dirModel->index(pathCopy));
+ {
+ QString tildeExpanded = qt_tildeExpansion(pathCopy);
+ if (tildeExpanded != pathCopy) {
+ QFileSystemModel *dirModel;
+ if (proxyModel)
+ dirModel = qobject_cast(proxyModel->sourceModel());
+ else
+ dirModel = sourceModel;
+ dirModel->fetchMore(dirModel->index(tildeExpanded));
+ }
+ pathCopy = std::move(tildeExpanded);
}
#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 defined(Q_OS_WIN)
+ QStringList parts = pathCopy.split(sep, Qt::SkipEmptyParts);
if (!doubleSlash.isEmpty() && !parts.isEmpty())
parts[0].prepend(doubleSlash);
if (pathCopy.endsWith(sep))
parts.append(QString());
#else
- QStringList parts = pathCopy.split(re);
- if (pathCopy[0] == sep[0]) // read the "/" at the beginning as the split removed it
- parts[0] = sep[0];
+ QStringList parts = pathCopy.split(sep);
+ if (pathCopy[0] == sep) // read the "/" at the beginning as the split removed it
+ parts[0] = sep;
#endif
-#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
- bool startsFromRoot = !parts.isEmpty() && parts[0].endsWith(QLatin1Char(':'));
+#if defined(Q_OS_WIN)
+ bool startsFromRoot = !parts.isEmpty() && parts[0].endsWith(u':');
#else
- bool startsFromRoot = pathCopy[0] == sep[0];
+ bool startsFromRoot = pathCopy[0] == sep;
#endif
- if (parts.count() == 1 || (parts.count() > 1 && !startsFromRoot)) {
+ if (parts.size() == 1 || (parts.size() > 1 && !startsFromRoot)) {
const QFileSystemModel *dirModel;
if (proxyModel)
dirModel = qobject_cast(proxyModel->sourceModel());
else
dirModel = sourceModel;
QString currentLocation = QDir::toNativeSeparators(dirModel->rootPath());
-#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
- if (currentLocation.endsWith(QLatin1Char(':')))
+#if defined(Q_OS_WIN)
+ if (currentLocation.endsWith(u':'))
currentLocation.append(sep);
#endif
if (currentLocation.contains(sep) && path != currentLocation) {
QStringList currentLocationList = splitPath(currentLocation);
- while (!currentLocationList.isEmpty()
- && parts.count() > 0
- && parts.at(0) == QLatin1String("..")) {
+ while (!currentLocationList.isEmpty() && parts.size() > 0 && parts.at(0) == ".."_L1) {
parts.removeFirst();
currentLocationList.removeLast();
}
- if (!currentLocationList.isEmpty() && currentLocationList.last().isEmpty())
+ if (!currentLocationList.isEmpty() && currentLocationList.constLast().isEmpty())
currentLocationList.removeLast();
return currentLocationList + parts;
}
@@ -3495,97 +4246,9 @@
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
+#endif // QT_CONFIG(completer)
+
QT_END_NAMESPACE
#include "moc_qfiledialog.cpp"
-
-#endif // QT_NO_FILEDIALOG
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qt/qfileinfogatherer.cpp
--- a/libgui/languages/build_ts/octave-qt/qfileinfogatherer.cpp Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qt/qfileinfogatherer.cpp Mon Dec 04 19:55:32 2023 +0100
@@ -1,48 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfileinfogatherer_p.h"
#include
-#include
#include
+#include
#ifndef Q_OS_WIN
# include
# include
@@ -53,42 +15,40 @@
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_FILESYSTEMMODEL
+using namespace Qt::StringLiterals;
#ifdef QT_BUILD_INTERNAL
-static bool fetchedRoot = false;
+Q_CONSTINIT static QBasicAtomicInt fetchedRoot = Q_BASIC_ATOMIC_INITIALIZER(false);
Q_AUTOTEST_EXPORT void qt_test_resetFetchedRoot()
{
- fetchedRoot = false;
+ fetchedRoot.storeRelaxed(false);
}
Q_AUTOTEST_EXPORT bool qt_test_isFetchedRoot()
{
- return fetchedRoot;
+ return fetchedRoot.loadRelaxed();
}
#endif
+static QString translateDriveName(const QFileInfo &drive)
+{
+ QString driveName = drive.absoluteFilePath();
+#ifdef Q_OS_WIN
+ if (driveName.startsWith(u'/')) // UNC host
+ return drive.fileName();
+ if (driveName.endsWith(u'/'))
+ driveName.chop(1);
+#endif // Q_OS_WIN
+ return driveName;
+}
+
/*!
Creates thread
*/
QFileInfoGatherer::QFileInfoGatherer(QObject *parent)
- : QThread(parent), abort(false),
-#ifndef QT_NO_FILESYSTEMWATCHER
- watcher(0),
-#endif
- m_resolveSymlinks(false), m_iconProvider(&defaultProvider)
+ : QThread(parent)
+ , m_iconProvider(&defaultProvider)
{
-#ifdef Q_OS_WIN
- m_resolveSymlinks = true;
-#elif !defined(Q_OS_INTEGRITY) && !defined(Q_OS_VXWORKS)
- 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);
}
@@ -97,9 +57,9 @@
*/
QFileInfoGatherer::~QFileInfoGatherer()
{
+ abort.storeRelaxed(true);
QMutexLocker locker(&mutex);
- abort = true;
- condition.wakeOne();
+ condition.wakeAll();
locker.unlock();
wait();
}
@@ -108,23 +68,39 @@
{
Q_UNUSED(enable);
#ifdef Q_OS_WIN
- QMutexLocker locker(&mutex);
m_resolveSymlinks = enable;
#endif
}
+void QFileInfoGatherer::driveAdded()
+{
+ fetchExtendedInformation(QString(), QStringList());
+}
+
+void QFileInfoGatherer::driveRemoved()
+{
+ QStringList drives;
+ const QFileInfoList driveInfoList = QDir::drives();
+ for (const QFileInfo &fi : driveInfoList)
+ drives.append(translateDriveName(fi));
+ emit newListOfFiles(QString(), drives);
+}
+
bool QFileInfoGatherer::resolveSymlinks() const
{
+#ifdef Q_OS_WIN
return m_resolveSymlinks;
+#else
+ return false;
+#endif
}
-void QFileInfoGatherer::setIconProvider(QFileIconProvider *provider)
+void QFileInfoGatherer::setIconProvider(QAbstractFileIconProvider *provider)
{
- QMutexLocker locker(&mutex);
m_iconProvider = provider;
}
-QFileIconProvider *QFileInfoGatherer::iconProvider() const
+QAbstractFileIconProvider *QFileInfoGatherer::iconProvider() const
{
return m_iconProvider;
}
@@ -137,7 +113,7 @@
void QFileInfoGatherer::fetchExtendedInformation(const QString &path, const QStringList &files)
{
QMutexLocker locker(&mutex);
- // See if we already have this dir/file in our que
+ // See if we already have this dir/file in our queue
int loc = this->path.lastIndexOf(path);
while (loc > 0) {
if (this->files.at(loc) == files) {
@@ -145,9 +121,22 @@
}
loc = this->path.lastIndexOf(path, loc - 1);
}
+#if QT_CONFIG(thread)
this->path.push(path);
this->files.push(files);
condition.wakeAll();
+#else // !QT_CONFIG(thread)
+ getFileInfos(path, files);
+#endif // QT_CONFIG(thread)
+
+#if QT_CONFIG(filesystemwatcher)
+ if (files.isEmpty()
+ && !path.isEmpty()
+ && !path.startsWith("//"_L1) /*don't watch UNC path*/) {
+ if (!watchedDirectories().contains(path))
+ watchPaths(QStringList(path));
+ }
+#endif
}
/*!
@@ -157,11 +146,96 @@
*/
void QFileInfoGatherer::updateFile(const QString &filePath)
{
- QString dir = filePath.mid(0, filePath.lastIndexOf(QDir::separator()));
- QString fileName = filePath.mid(dir.length() + 1);
+ QString dir = filePath.mid(0, filePath.lastIndexOf(u'/'));
+ QString fileName = filePath.mid(dir.size() + 1);
fetchExtendedInformation(dir, QStringList(fileName));
}
+QStringList QFileInfoGatherer::watchedFiles() const
+{
+#if QT_CONFIG(filesystemwatcher)
+ if (m_watcher)
+ return m_watcher->files();
+#endif
+ return {};
+}
+
+QStringList QFileInfoGatherer::watchedDirectories() const
+{
+#if QT_CONFIG(filesystemwatcher)
+ if (m_watcher)
+ return m_watcher->directories();
+#endif
+ return {};
+}
+
+void QFileInfoGatherer::createWatcher()
+{
+#if QT_CONFIG(filesystemwatcher)
+ m_watcher = new QFileSystemWatcher(this);
+ connect(m_watcher, &QFileSystemWatcher::directoryChanged, this, &QFileInfoGatherer::list);
+ connect(m_watcher, &QFileSystemWatcher::fileChanged, this, &QFileInfoGatherer::updateFile);
+# if defined(Q_OS_WIN)
+ const QVariant listener = m_watcher->property("_q_driveListener");
+ if (listener.canConvert()) {
+ if (QObject *driveListener = listener.value()) {
+ connect(driveListener, SIGNAL(driveAdded()), this, SLOT(driveAdded()));
+ connect(driveListener, SIGNAL(driveRemoved()), this, SLOT(driveRemoved()));
+ }
+ }
+# endif // Q_OS_WIN
+#endif
+}
+
+void QFileInfoGatherer::watchPaths(const QStringList &paths)
+{
+#if QT_CONFIG(filesystemwatcher)
+ if (m_watching) {
+ if (m_watcher == nullptr)
+ createWatcher();
+ m_watcher->addPaths(paths);
+ }
+#else
+ Q_UNUSED(paths);
+#endif
+}
+
+void QFileInfoGatherer::unwatchPaths(const QStringList &paths)
+{
+#if QT_CONFIG(filesystemwatcher)
+ if (m_watcher && !paths.isEmpty())
+ m_watcher->removePaths(paths);
+#else
+ Q_UNUSED(paths);
+#endif
+}
+
+bool QFileInfoGatherer::isWatching() const
+{
+ bool result = false;
+#if QT_CONFIG(filesystemwatcher)
+ QMutexLocker locker(&mutex);
+ result = m_watching;
+#endif
+ return result;
+}
+
+void QFileInfoGatherer::setWatching(bool v)
+{
+#if QT_CONFIG(filesystemwatcher)
+ QMutexLocker locker(&mutex);
+ if (v != m_watching) {
+ if (!v) {
+ delete m_watcher;
+ m_watcher = nullptr;
+ }
+ m_watching = v;
+ }
+#else
+ Q_UNUSED(v);
+#endif
+}
+
/*
List all files in \a directoryPath
@@ -169,10 +243,10 @@
*/
void QFileInfoGatherer::clear()
{
-#ifndef QT_NO_FILESYSTEMWATCHER
+#if QT_CONFIG(filesystemwatcher)
QMutexLocker locker(&mutex);
- watcher->removePaths(watcher->files());
- watcher->removePaths(watcher->directories());
+ unwatchPaths(watchedFiles());
+ unwatchPaths(watchedDirectories());
#endif
}
@@ -183,9 +257,11 @@
*/
void QFileInfoGatherer::removePath(const QString &path)
{
-#ifndef QT_NO_FILESYSTEMWATCHER
+#if QT_CONFIG(filesystemwatcher)
QMutexLocker locker(&mutex);
- watcher->removePath(path);
+ unwatchPaths(QStringList(path));
+#else
+ Q_UNUSED(path);
#endif
}
@@ -205,25 +281,18 @@
void QFileInfoGatherer::run()
{
forever {
- bool updateFiles = false;
QMutexLocker locker(&mutex);
- if (abort) {
- return;
- }
- if (this->path.isEmpty())
+ while (!abort.loadRelaxed() && 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;
- }
+ if (abort.loadRelaxed())
+ return;
+ const QString thisPath = std::as_const(path).front();
+ path.pop_front();
+ const QStringList thisList = std::as_const(files).front();
+ files.pop_front();
locker.unlock();
- if (updateFiles)
- getFileInfos(path, list);
+
+ getFileInfos(thisPath, thisList);
}
}
@@ -232,67 +301,62 @@
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
-#endif
+#if QT_CONFIG(filesystemwatcher)
+ // ### Not ready to listen all modifications by default
+ static const bool watchFiles = qEnvironmentVariableIsSet("QT_FILESYSTEMMODEL_WATCH_FILES");
+ if (watchFiles) {
+ if (!fileInfo.exists() && !fileInfo.isSymLink()) {
+ const_cast(this)->
+ unwatchPaths(QStringList(fileInfo.absoluteFilePath()));
+ } else {
+ const QString path = fileInfo.absoluteFilePath();
+ if (!path.isEmpty() && fileInfo.exists() && fileInfo.isFile() && fileInfo.isReadable()
+ && !watchedFiles().contains(path)) {
+ const_cast(this)->watchPaths(QStringList(path));
+ }
+ }
+ }
+#endif // filesystemwatcher
+#ifdef Q_OS_WIN
if (m_resolveSymlinks && info.isSymLink(/* ignoreNtfsSymLinks = */ true)) {
- QFileInfo resolvedInfo(fileInfo.symLinkTarget());
- resolvedInfo = resolvedInfo.canonicalFilePath();
+ QFileInfo resolvedInfo(QFileInfo(fileInfo.symLinkTarget()).canonicalFilePath());
if (resolvedInfo.exists()) {
emit nameResolved(fileInfo.filePath(), resolvedInfo.fileName());
}
}
+#endif
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;
+ fetchedRoot.storeRelaxed(true);
#endif
QFileInfoList infoList;
if (files.isEmpty()) {
infoList = QDir::drives();
} else {
- for (int i = 0; i < files.count(); ++i)
- infoList << QFileInfo(files.at(i));
+ infoList.reserve(files.size());
+ for (const auto &file : files)
+ infoList << QFileInfo(file);
}
- for (int i = infoList.count() - 1; i >= 0; --i) {
- QString driveName = translateDriveName(infoList.at(i));
- QList > updatedFiles;
- updatedFiles.append(QPair(driveName, infoList.at(i)));
- emit updates(path, updatedFiles);
+ QList> updatedFiles;
+ updatedFiles.reserve(infoList.size());
+ for (int i = infoList.size() - 1; i >= 0; --i) {
+ QFileInfo driveInfo = infoList.at(i);
+ driveInfo.stat();
+ QString driveName = translateDriveName(driveInfo);
+ updatedFiles.append(QPair(driveName, driveInfo));
}
+ emit updates(path, updatedFiles);
return;
}
@@ -300,25 +364,27 @@
base.start();
QFileInfo fileInfo;
bool firstTime = true;
- QList > updatedFiles;
+ QList> 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 (files.isEmpty()) {
+ QDirIterator dirIt(path, QDir::AllEntries | QDir::System | QDir::Hidden);
+ while (!abort.loadRelaxed() && dirIt.hasNext()) {
+ fileInfo = dirIt.nextFileInfo();
+ fileInfo.stat();
+ 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()) {
+ while (!abort.loadRelaxed() && filesIt != filesToCheck.constEnd()) {
fileInfo.setFile(path + QDir::separator() + *filesIt);
++filesIt;
+ fileInfo.stat();
fetch(fileInfo, base, firstTime, updatedFiles, path);
}
if (!updatedFiles.isEmpty())
@@ -326,11 +392,13 @@
emit directoryLoaded(path);
}
-void QFileInfoGatherer::fetch(const QFileInfo &fileInfo, QElapsedTimer &base, bool &firstTime, QList > &updatedFiles, const QString &path) {
+void QFileInfoGatherer::fetch(const QFileInfo &fileInfo, QElapsedTimer &base, bool &firstTime,
+ QList> &updatedFiles, const QString &path)
+{
updatedFiles.append(QPair(fileInfo.fileName(), fileInfo));
QElapsedTimer current;
current.start();
- if ((firstTime && updatedFiles.count() > 100) || base.msecsTo(current) > 1000) {
+ if ((firstTime && updatedFiles.size() > 100) || base.msecsTo(current) > 1000) {
emit updates(path, updatedFiles);
updatedFiles.clear();
base = current;
@@ -338,6 +406,6 @@
}
}
-#endif // QT_NO_FILESYSTEMMODEL
+QT_END_NAMESPACE
-QT_END_NAMESPACE
+#include "moc_qfileinfogatherer_p.cpp"
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qt/qfilesystemmodel.cpp
--- a/libgui/languages/build_ts/octave-qt/qfilesystemmodel.cpp Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qt/qfilesystemmodel.cpp Mon Dec 04 19:55:32 2023 +0100
@@ -1,63 +1,29 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfilesystemmodel_p.h"
#include "qfilesystemmodel.h"
+#include
#include
-#include
+#include
#include
#include
-#include
-#include
+#include
+#if QT_CONFIG(regularexpression)
+# include
+#endif
+
+#include
#ifdef Q_OS_WIN
-#include
-#endif
-#ifdef Q_OS_WIN32
-#include
+# include
+# include
+# include
#endif
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_FILESYSTEMMODEL
+using namespace Qt::StringLiterals;
/*!
\enum QFileSystemModel::Roles
@@ -74,6 +40,7 @@
\brief The QFileSystemModel class provides a data model for the local filesystem.
\ingroup model-view
+ \inmodule QtGui
This class provides access to the local filesystem, providing functions
for renaming and removing files and directories, and for creating new
@@ -83,30 +50,30 @@
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
+ The fileInfo(), isDir(), fileName() and filePath() 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.
+ \note QFileSystemModel requires an instance of \l QApplication.
\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
+ \snippet 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
+ \snippet 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
+ \snippet 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
+ hierarchical model is displayed. QFileSystemModel provides a convenience
function that returns a suitable model index for a path to a
directory within the model.
@@ -116,10 +83,9 @@
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 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.
@@ -128,21 +94,21 @@
*/
/*!
- \fn bool QFileSystemModel::rmdir(const QModelIndex &index) const
+ \fn bool QFileSystemModel::rmdir(const QModelIndex &index)
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 model and \b{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.
+ \b{not} move them to a location where they can be recovered.
\sa remove()
*/
/*!
- \fn QIcon QFileSystemModel::fileName(const QModelIndex &index) const
+ \fn QString QFileSystemModel::fileName(const QModelIndex &index) const
Returns the file name for the item stored in the model under the given
\a index.
@@ -161,6 +127,11 @@
Returns the QFileInfo for the item stored in the model under the given
\a index.
*/
+QFileInfo QFileSystemModel::fileInfo(const QModelIndex &index) const
+{
+ Q_D(const QFileSystemModel);
+ return d->node(index)->fileInfo();
+}
/*!
\fn void QFileSystemModel::rootPathChanged(const QString &newPath);
@@ -172,7 +143,7 @@
\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.
+ renamed to \a newName. The file is located in the directory \a path.
*/
/*!
@@ -184,56 +155,44 @@
*/
/*!
- \fn bool QFileSystemModel::remove(const QModelIndex &index) const
+ \fn bool QFileSystemModel::remove(const QModelIndex &index)
- Removes the model item \a index from the file system model and \bold{deletes the
+ Removes the model item \a index from the file system model and \b{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}
+ \warning This function deletes files from the file system; it does \b{not}
move them to a location where they can be recovered.
\sa rmdir()
*/
-bool QFileSystemModel::remove(const QModelIndex &aindex) const
+bool QFileSystemModel::remove(const QModelIndex &aindex)
{
- //### TODO optim
- QString path = filePath(aindex);
- QFileSystemModelPrivate * d = const_cast(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);
+ Q_D(QFileSystemModel);
- 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;
+ const QString path = d->filePath(aindex);
+ const QFileInfo fileInfo(path);
+#if QT_CONFIG(filesystemwatcher) && defined(Q_OS_WIN)
+ // QTBUG-65683: Remove file system watchers prior to deletion to prevent
+ // failure due to locked files on Windows.
+ const QStringList watchedPaths = d->unwatchPathsAt(aindex);
+#endif // filesystemwatcher && Q_OS_WIN
+ const bool success = (fileInfo.isFile() || fileInfo.isSymLink())
+ ? QFile::remove(path) : QDir(path).removeRecursively();
+#if QT_CONFIG(filesystemwatcher) && defined(Q_OS_WIN)
+ if (!success)
+ d->watchPaths(watchedPaths);
+#endif // filesystemwatcher && Q_OS_WIN
+ return success;
}
/*!
Constructs a file system model with the given \a parent.
*/
-QFileSystemModel::QFileSystemModel(QObject *parent)
- : QAbstractItemModel(*new QFileSystemModelPrivate, parent)
+QFileSystemModel::QFileSystemModel(QObject *parent) :
+ QFileSystemModel(*new QFileSystemModelPrivate, parent)
{
- Q_D(QFileSystemModel);
- d->init();
}
/*!
@@ -249,9 +208,7 @@
/*!
Destroys this file system model.
*/
-QFileSystemModel::~QFileSystemModel()
-{
-}
+QFileSystemModel::~QFileSystemModel() = default;
/*!
\reimp
@@ -268,7 +225,10 @@
Q_ASSERT(parentNode);
// now get the internal pointer for the index
- QString childName = parentNode->visibleChildren[d->translateVisibleLocation(parentNode, row)];
+ const int i = d->translateVisibleLocation(parentNode, row);
+ if (i >= parentNode->visibleChildren.size())
+ return QModelIndex();
+ const QString &childName = parentNode->visibleChildren.at(i);
const QFileSystemModelPrivate::QFileSystemNode *indexNode = parentNode->children.value(childName);
Q_ASSERT(indexNode);
@@ -276,6 +236,21 @@
}
/*!
+ \reimp
+*/
+QModelIndex QFileSystemModel::sibling(int row, int column, const QModelIndex &idx) const
+{
+ if (row == idx.row() && column < columnCount(idx.parent())) {
+ // cheap sibling operation: just adjust the column:
+ return createIndex(row, column, idx.internalPointer());
+ } else {
+ // for anything else: call the default implementation
+ // (this could probably be optimized, too):
+ return QAbstractItemModel::sibling(row, column, idx);
+ }
+}
+
+/*!
\overload
Returns the model item index for the given \a path and \a column.
@@ -284,10 +259,7 @@
{
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;
+ return d->index(node, column);
}
/*!
@@ -308,17 +280,17 @@
static QString qt_GetLongPathName(const QString &strShortPath)
{
if (strShortPath.isEmpty()
- || strShortPath == QLatin1String(".") || strShortPath == QLatin1String(".."))
+ || strShortPath == "."_L1 || strShortPath == ".."_L1)
return strShortPath;
- if (strShortPath.length() == 2 && strShortPath.endsWith(QLatin1Char(':')))
+ if (strShortPath.length() == 2 && strShortPath.endsWith(u':'))
return strShortPath.toUpper();
const QString absPath = QDir(strShortPath).absolutePath();
- if (absPath.startsWith(QLatin1String("//"))
- || absPath.startsWith(QLatin1String("\\\\"))) // unc
+ if (absPath.startsWith("//"_L1)
+ || absPath.startsWith("\\\\"_L1)) // unc
return QDir::fromNativeSeparators(absPath);
- if (absPath.startsWith(QLatin1Char('/')))
+ if (absPath.startsWith(u'/'))
return QString();
- const QString inputString = QLatin1String("\\\\?\\") + QDir::toNativeSeparators(absPath);
+ const QString inputString = "\\\\?\\"_L1 + QDir::toNativeSeparators(absPath);
QVarLengthArray buffer(MAX_PATH);
DWORD result = ::GetLongPathName((wchar_t*)inputString.utf16(),
buffer.data(),
@@ -348,7 +320,7 @@
{
Q_Q(const QFileSystemModel);
Q_UNUSED(q);
- if (path.isEmpty() || path == myComputer() || path.startsWith(QLatin1Char(':')))
+ if (path.isEmpty() || path == myComputer() || path.startsWith(u':'))
return const_cast(&root);
// Construct the nodes up to the new root path if they need to be built
@@ -364,25 +336,33 @@
absolutePath = QDir(longPath).absolutePath();
// ### TODO can we use bool QAbstractFileEngine::caseSensitive() const?
- QStringList pathElements = absolutePath.split(QLatin1Char('/'), QString::SkipEmptyParts);
+ QStringList pathElements = absolutePath.split(u'/', Qt::SkipEmptyParts);
if ((pathElements.isEmpty())
-#if (!defined(Q_OS_WIN) || defined(Q_OS_WINCE)) && !defined(Q_OS_SYMBIAN)
- && QDir::fromNativeSeparators(longPath) != QLatin1String("/")
+#if !defined(Q_OS_WIN)
+ && QDir::fromNativeSeparators(longPath) != "/"_L1
#endif
)
return const_cast(&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();
+ QString elementPath;
+ QChar separator = u'/';
+ QString trailingSeparator;
+#if defined(Q_OS_WIN)
+ if (absolutePath.startsWith("//"_L1)) { // UNC path
+ QString host = "\\\\"_L1 + pathElements.constFirst();
if (absolutePath == QDir::fromNativeSeparators(host))
- absolutePath.append(QLatin1Char('/'));
- if (longPath.endsWith(QLatin1Char('/')) && !absolutePath.endsWith(QLatin1Char('/')))
- absolutePath.append(QLatin1Char('/'));
+ absolutePath.append(u'/');
+ if (longPath.endsWith(u'/') && !absolutePath.endsWith(u'/'))
+ absolutePath.append(u'/');
+ if (absolutePath.endsWith(u'/'))
+ trailingSeparator = "\\"_L1;
int r = 0;
- QFileSystemModelPrivate::QFileSystemNode *rootNode = const_cast(&root);
- if (!root.children.contains(host.toLower())) {
- if (pathElements.count() == 1 && !absolutePath.endsWith(QLatin1Char('/')))
+ auto rootNode = const_cast(&root);
+ auto it = root.children.constFind(host);
+ if (it != root.children.cend()) {
+ host = it.key(); // Normalize case for lookup in visibleLocation()
+ } else {
+ if (pathElements.count() == 1 && !absolutePath.endsWith(u'/'))
return rootNode;
QFileInfo info(host);
if (!info.exists())
@@ -395,41 +375,52 @@
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.
+ separator = u'\\';
+ elementPath = host;
+ elementPath.append(separator);
+ } else {
+ if (!pathElements.at(0).contains(u':')) {
QString rootPath = QDir(longPath).rootPath();
pathElements.prepend(rootPath);
}
- if (pathElements.at(0).endsWith(QLatin1Char('/')))
+ if (pathElements.at(0).endsWith(u'/'))
pathElements[0].chop(1);
}
#else
// add the "/" item, since it is a valid path element on Unix
- if (absolutePath[0] == QLatin1Char('/'))
- pathElements.prepend(QLatin1String("/"));
+ if (absolutePath[0] == u'/')
+ pathElements.prepend("/"_L1);
#endif
QFileSystemModelPrivate::QFileSystemNode *parent = node(index);
- for (int i = 0; i < pathElements.count(); ++i) {
+ for (int i = 0; i < pathElements.size(); ++i) {
QString element = pathElements.at(i);
+ if (i != 0)
+ elementPath.append(separator);
+ elementPath.append(element);
+ if (i == pathElements.size() - 1)
+ elementPath.append(trailingSeparator);
#ifdef Q_OS_WIN
- // On Windows, "filename......." and "filename" are equivalent Task #133928
- while (element.endsWith(QLatin1Char('.')))
+ // On Windows, "filename " and "filename" are equivalent and
+ // "filename . " and "filename" are equivalent
+ // "filename......." and "filename" are equivalent Task #133928
+ // whereas "filename .txt" is still "filename .txt"
+ // If after stripping the characters there is nothing left then we
+ // just return the parent directory as it is assumed that the path
+ // is referring to the parent
+ while (element.endsWith(u'.') || element.endsWith(u' '))
element.chop(1);
+ // Only filenames that can't possibly exist will be end up being empty
+ if (element.isEmpty())
+ return parent;
#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)
+ if ((parent->children.size() == 0)
|| (parent->caseSensitive()
&& parent->children.value(element)->fileName != element)
|| (!parent->caseSensitive()
@@ -441,12 +432,12 @@
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);
+ QFileInfo info(elementPath);
if (!info.exists())
return const_cast(&root);
QFileSystemModelPrivate *p = const_cast(this);
node = p->addNode(parent, element,info);
-#ifndef QT_NO_FILESYSTEMWATCHER
+#if QT_CONFIG(filesystemwatcher)
node->populate(fileInfoGatherer.getInfo(info));
#endif
} else {
@@ -465,11 +456,8 @@
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);
+ Fetching f = { std::move(dir), std::move(element), node };
+ p->toFetch.append(std::move(f));
p->fetchingTimer.start(0, const_cast(q));
}
}
@@ -487,14 +475,14 @@
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) {
+#if QT_CONFIG(filesystemwatcher)
+ for (int i = 0; i < d->toFetch.size(); ++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";
+ // qDebug("yah!, you saved a little gerbil soul");
}
}
#endif
@@ -503,8 +491,8 @@
}
/*!
- Returns true if the model item \a index represents a directory;
- otherwise returns false.
+ Returns \c true if the model item \a index represents a directory;
+ otherwise returns \c false.
*/
bool QFileSystemModel::isDir(const QModelIndex &index) const
{
@@ -541,14 +529,38 @@
}
/*!
- Returns the date and time when \a index was last modified.
+ Returns the date and time (in local time) when \a index was last modified.
+
+ This is an overloaded function, equivalent to calling:
+ \code
+ lastModified(index, QTimeZone::LocalTime);
+ \endcode
+
+ If \a index is invalid, a default constructed QDateTime is returned.
*/
QDateTime QFileSystemModel::lastModified(const QModelIndex &index) const
{
+ return lastModified(index, QTimeZone::LocalTime);
+}
+
+/*!
+ \since 6.6
+ Returns the date and time, in the time zone \a tz, when
+ \a index was last modified.
+
+ Typical arguments for \a tz are \c QTimeZone::UTC or \c QTimeZone::LocalTime.
+ UTC does not require any conversion from the time returned by the native file
+ system API, therefore getting the time in UTC is potentially faster. LocalTime
+ is typically chosen if the time is shown to the user.
+
+ If \a index is invalid, a default constructed QDateTime is returned.
+ */
+QDateTime QFileSystemModel::lastModified(const QModelIndex &index, const QTimeZone &tz) const
+{
Q_D(const QFileSystemModel);
if (!index.isValid())
return QDateTime();
- return d->node(index)->lastModified();
+ return d->node(index)->lastModified(tz);
}
/*!
@@ -561,9 +573,9 @@
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)
+ Q_ASSERT(indexNode != nullptr);
+ QFileSystemModelPrivate::QFileSystemNode *parentNode = indexNode->parent;
+ if (parentNode == nullptr || parentNode == &d->root)
return QModelIndex();
// get the parent's row
@@ -580,10 +592,10 @@
return the index for node
*/
-QModelIndex QFileSystemModelPrivate::index(const QFileSystemModelPrivate::QFileSystemNode *node) const
+QModelIndex QFileSystemModelPrivate::index(const QFileSystemModelPrivate::QFileSystemNode *node, int column) const
{
Q_Q(const QFileSystemModel);
- QFileSystemModelPrivate::QFileSystemNode *parentNode = (node ? node->parent : 0);
+ QFileSystemModelPrivate::QFileSystemNode *parentNode = (node ? node->parent : nullptr);
if (node == &root || !parentNode)
return QModelIndex();
@@ -593,7 +605,7 @@
return QModelIndex();
int visualRow = translateVisibleLocation(parentNode, parentNode->visibleLocation(node->fileName));
- return q->createIndex(visualRow, 0, const_cast(node));
+ return q->createIndex(visualRow, column, const_cast(node));
}
/*!
@@ -619,6 +631,8 @@
bool QFileSystemModel::canFetchMore(const QModelIndex &parent) const
{
Q_D(const QFileSystemModel);
+ if (!d->setRootPath)
+ return false;
const QFileSystemModelPrivate::QFileSystemNode *indexNode = d->node(parent);
return (!indexNode->populatedChildren);
}
@@ -635,7 +649,9 @@
if (indexNode->populatedChildren)
return;
indexNode->populatedChildren = true;
+#if QT_CONFIG(filesystemwatcher)
d->fileInfoGatherer.list(filePath(parent));
+#endif
}
/*!
@@ -648,10 +664,10 @@
return 0;
if (!parent.isValid())
- return d->root.visibleChildren.count();
+ return d->root.visibleChildren.size();
const QFileSystemModelPrivate::QFileSystemNode *parentNode = d->node(parent);
- return parentNode->visibleChildren.count();
+ return parentNode->visibleChildren.size();
}
/*!
@@ -659,7 +675,7 @@
*/
int QFileSystemModel::columnCount(const QModelIndex &parent) const
{
- return (parent.column() > 0) ? 0 : 4;
+ return (parent.column() > 0) ? 0 : QFileSystemModelPrivate::NumColumns;
}
/*!
@@ -669,12 +685,16 @@
*/
QVariant QFileSystemModel::myComputer(int role) const
{
+#if QT_CONFIG(filesystemwatcher)
Q_D(const QFileSystemModel);
+#endif
switch (role) {
case Qt::DisplayRole:
- return d->myComputer();
+ return QFileSystemModelPrivate::myComputer();
+#if QT_CONFIG(filesystemwatcher)
case Qt::DecorationRole:
- return d->fileInfoGatherer.iconProvider()->icon(QFileIconProvider::Computer);
+ return d->fileInfoGatherer.iconProvider()->icon(QAbstractFileIconProvider::Computer);
+#endif
}
return QVariant();
}
@@ -690,12 +710,15 @@
switch (role) {
case Qt::EditRole:
+ if (index.column() == QFileSystemModelPrivate::NameColumn)
+ return d->name(index);
+ Q_FALLTHROUGH();
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);
+ case QFileSystemModelPrivate::NameColumn: return d->displayName(index);
+ case QFileSystemModelPrivate::SizeColumn: return d->size(index);
+ case QFileSystemModelPrivate::TypeColumn: return d->type(index);
+ case QFileSystemModelPrivate::TimeColumn: return d->time(index);
default:
qWarning("data: invalid display value column %d", index.column());
break;
@@ -706,20 +729,22 @@
case FileNameRole:
return d->name(index);
case Qt::DecorationRole:
- if (index.column() == 0) {
+ if (index.column() == QFileSystemModelPrivate::NameColumn) {
QIcon icon = d->icon(index);
+#if QT_CONFIG(filesystemwatcher)
if (icon.isNull()) {
if (d->node(index)->isDir())
- icon = d->fileInfoGatherer.iconProvider()->icon(QFileIconProvider::Folder);
+ icon = d->fileInfoGatherer.iconProvider()->icon(QAbstractFileIconProvider::Folder);
else
- icon = d->fileInfoGatherer.iconProvider()->icon(QFileIconProvider::File);
+ icon = d->fileInfoGatherer.iconProvider()->icon(QAbstractFileIconProvider::File);
}
+#endif // filesystemwatcher
return icon;
}
break;
case Qt::TextAlignmentRole:
- if (index.column() == 1)
- return Qt::AlignRight;
+ if (index.column() == QFileSystemModelPrivate::SizeColumn)
+ return QVariant(Qt::AlignTrailing | Qt::AlignVCenter);
break;
case FilePermissions:
int p = permissions(index);
@@ -739,9 +764,9 @@
const QFileSystemNode *n = node(index);
if (n->isDir()) {
#ifdef Q_OS_MAC
- return QLatin1String("--");
+ return "--"_L1;
#else
- return QLatin1String("");
+ return ""_L1;
#endif
// Windows - ""
// OS X - "--"
@@ -753,21 +778,7 @@
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));
+ return QLocale::system().formattedDataSize(bytes);
}
/*!
@@ -777,8 +788,8 @@
{
if (!index.isValid())
return QString();
-#ifndef QT_NO_DATESTRING
- return node(index)->lastModified().toString(Qt::SystemLocaleDate);
+#if QT_CONFIG(datestring)
+ return QLocale::system().toString(node(index)->lastModified(QTimeZone::LocalTime), QLocale::ShortFormat);
#else
Q_UNUSED(index);
return QString();
@@ -803,11 +814,13 @@
if (!index.isValid())
return QString();
QFileSystemNode *dirNode = node(index);
- if (fileInfoGatherer.resolveSymlinks() && !resolvedSymLinks.isEmpty() &&
- dirNode->isSymLink(/* ignoreNtfsSymLinks = */ true)) {
+ if (
+#if QT_CONFIG(filesystemwatcher)
+ fileInfoGatherer.resolveSymlinks() &&
+#endif
+ !resolvedSymLinks.isEmpty() && dirNode->isSymLink(/* ignoreNtfsSymLinks = */ true)) {
QString fullPath = QDir::fromNativeSeparators(filePath(index));
- if (resolvedSymLinks.contains(fullPath))
- return resolvedSymLinks[fullPath];
+ return resolvedSymLinks.value(fullPath, dirNode->fileName);
}
return dirNode->fileName;
}
@@ -817,10 +830,10 @@
*/
QString QFileSystemModelPrivate::displayName(const QModelIndex &index) const
{
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+#if defined(Q_OS_WIN)
QFileSystemNode *dirNode = node(index);
- if (!dirNode->volumeName.isNull())
- return dirNode->volumeName + QLatin1String(" (") + name(index) + QLatin1Char(')');
+ if (!dirNode->volumeName.isEmpty())
+ return dirNode->volumeName;
#endif
return name(index);
}
@@ -850,25 +863,30 @@
QString newName = value.toString();
QString oldName = idx.data().toString();
- if (newName == idx.data().toString())
+ if (newName == oldName)
return true;
- if (newName.isEmpty()
- || QDir::toNativeSeparators(newName).contains(QDir::separator())
- || !QDir(filePath(parent(idx))).rename(oldName, newName)) {
-#ifndef QT_NO_MESSAGEBOX
- QMessageBox::information(0, QFileSystemModel::tr("Invalid filename"),
- QFileSystemModel::tr("The name \"%1\" can not be used.Try using another name, with fewer characters or no punctuations marks.")
- .arg(newName),
- QMessageBox::Ok);
-#endif // QT_NO_MESSAGEBOX
+ const QString parentPath = filePath(parent(idx));
+
+ if (newName.isEmpty() || QDir::toNativeSeparators(newName).contains(QDir::separator()))
+ return false;
+
+#if QT_CONFIG(filesystemwatcher) && defined(Q_OS_WIN)
+ // QTBUG-65683: Remove file system watchers prior to renaming to prevent
+ // failure due to locked files on Windows.
+ const QStringList watchedPaths = d->unwatchPathsAt(idx);
+#endif // filesystemwatcher && Q_OS_WIN
+ if (!QDir(parentPath).rename(oldName, newName)) {
+#if QT_CONFIG(filesystemwatcher) && defined(Q_OS_WIN)
+ d->watchPaths(watchedPaths);
+#endif
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
+ - index pointer can't change because treeview doesn't use persistent index's
- if this get any more complicated think of changing it to just
use layoutChanged
@@ -878,21 +896,19 @@
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);
+ std::unique_ptr nodeToRename(parentNode->children.take(oldName));
+ nodeToRename->fileName = newName;
+ nodeToRename->parent = parentNode;
+#if QT_CONFIG(filesystemwatcher)
+ nodeToRename->populate(d->fileInfoGatherer.getInfo(QFileInfo(parentPath, newName)));
+#endif
+ nodeToRename->isVisible = true;
+ parentNode->children[newName] = nodeToRename.release();
parentNode->visibleChildren.insert(visibleLocation, newName);
d->delayedSort();
- emit fileRenamed(filePath(idx.parent()), oldName, newName);
+ emit fileRenamed(parentPath, oldName, newName);
}
return true;
}
@@ -907,9 +923,8 @@
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());
+ QImage pixmap(16, 1, QImage::Format_ARGB32_Premultiplied);
+ pixmap.fill(Qt::transparent);
return pixmap;
}
break;
@@ -922,23 +937,27 @@
QString returnValue;
switch (section) {
- case 0: returnValue = tr("Name");
- break;
- case 1: returnValue = tr("Size");
- break;
- case 2: returnValue =
+ case QFileSystemModelPrivate::NameColumn:
+ returnValue = tr("Name");
+ break;
+ case QFileSystemModelPrivate::SizeColumn:
+ returnValue = tr("Size");
+ break;
+ case QFileSystemModelPrivate::TypeColumn:
+ returnValue =
#ifdef Q_OS_MAC
- tr("Kind", "Match OS X Finder");
+ tr("Kind", "Match OS X Finder");
#else
- tr("Type", "All other platforms");
+ tr("Type", "All other platforms");
#endif
- break;
+ break;
// Windows - Type
// OS X - Kind
// Konqueror - File Type
// Nautilus - Type
- case 3: returnValue = tr("Date Modified");
- break;
+ case QFileSystemModelPrivate::TimeColumn:
+ returnValue = tr("Date Modified");
+ break;
default: return QVariant();
}
return returnValue;
@@ -962,6 +981,9 @@
}
flags |= Qt::ItemIsDragEnabled;
+
+ if (!indexNode->isDir())
+ flags |= Qt::ItemNeverHasChildren;
if (d->readOnly)
return flags;
if ((index.column() == 0) && indexNode->permissions() & QFile::WriteUser) {
@@ -981,84 +1003,6 @@
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
@@ -1067,13 +1011,17 @@
class QFileSystemModelSorter
{
public:
- inline QFileSystemModelSorter(int column) : sortColumn(column) {}
+ inline QFileSystemModelSorter(int column) : sortColumn(column)
+ {
+ naturalCompare.setNumericMode(true);
+ naturalCompare.setCaseSensitivity(Qt::CaseInsensitive);
+ }
bool compareNodes(const QFileSystemModelPrivate::QFileSystemNode *l,
const QFileSystemModelPrivate::QFileSystemNode *r) const
{
switch (sortColumn) {
- case 0: {
+ case QFileSystemModelPrivate::NameColumn: {
#ifndef Q_OS_MAC
// place directories before files
bool left = l->isDir();
@@ -1081,31 +1029,53 @@
if (left ^ right)
return left;
#endif
- return QFileSystemModelPrivate::naturalCompare(l->fileName,
- r->fileName, Qt::CaseInsensitive) < 0;
+ return naturalCompare.compare(l->fileName, r->fileName) < 0;
}
- case 1:
+ case QFileSystemModelPrivate::SizeColumn:
+ {
// 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();
+ bool left = l->isDir();
+ bool right = r->isDir();
+ if (left ^ right)
+ return left;
+
+ qint64 sizeDifference = l->size() - r->size();
+ if (sizeDifference == 0)
+ return naturalCompare.compare(l->fileName, r->fileName) < 0;
+
+ return sizeDifference < 0;
+ }
+ case QFileSystemModelPrivate::TypeColumn:
+ {
+ int compare = naturalCompare.compare(l->type(), r->type());
+ if (compare == 0)
+ return naturalCompare.compare(l->fileName, r->fileName) < 0;
+
+ return compare < 0;
+ }
+ case QFileSystemModelPrivate::TimeColumn:
+ {
+ const QDateTime left = l->lastModified(QTimeZone::UTC);
+ const QDateTime right = r->lastModified(QTimeZone::UTC);
+ if (left == right)
+ return naturalCompare.compare(l->fileName, r->fileName) < 0;
+
+ return left < right;
+ }
}
Q_ASSERT(false);
return false;
}
- bool operator()(const QPair &l,
- const QPair &r) const
+ bool operator()(const QFileSystemModelPrivate::QFileSystemNode *l,
+ const QFileSystemModelPrivate::QFileSystemNode *r) const
{
- return compareNodes(l.first, r.first);
+ return compareNodes(l, r);
}
private:
+ QCollator naturalCompare;
int sortColumn;
};
@@ -1118,29 +1088,28 @@
{
Q_Q(QFileSystemModel);
QFileSystemModelPrivate::QFileSystemNode *indexNode = node(parent);
- if (indexNode->children.count() == 0)
+ if (indexNode->children.size() == 0)
return;
- QList > values;
- QHash::const_iterator iterator;
- int i = 0;
- for(iterator = indexNode->children.begin() ; iterator != indexNode->children.end() ; ++iterator) {
+ QList values;
+
+ for (auto iterator = indexNode->children.constBegin(), cend = indexNode->children.constEnd(); iterator != cend; ++iterator) {
if (filtersAcceptsNode(iterator.value())) {
- values.append(QPair((iterator.value()), i));
+ values.append(iterator.value());
} else {
iterator.value()->isVisible = false;
}
- i++;
}
QFileSystemModelSorter ms(column);
- qStableSort(values.begin(), values.end(), ms);
+ std::sort(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;
+ indexNode->visibleChildren.reserve(values.size());
+ for (QFileSystemNode *node : std::as_const(values)) {
+ indexNode->visibleChildren.append(node->fileName);
+ node->isVisible = true;
}
if (!disableRecursiveSort) {
@@ -1165,9 +1134,10 @@
emit layoutAboutToBeChanged();
QModelIndexList oldList = persistentIndexList();
- QList > oldNodes;
- for (int i = 0; i < oldList.count(); ++i) {
- QPair pair(d->node(oldList.at(i)), oldList.at(i).column());
+ QList> oldNodes;
+ oldNodes.reserve(oldList.size());
+ for (const QModelIndex &oldNode : oldList) {
+ QPair pair(d->node(oldNode), oldNode.column());
oldNodes.append(pair);
}
@@ -1180,11 +1150,10 @@
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);
- }
+ newList.reserve(oldNodes.size());
+ for (const auto &[node, col]: std::as_const(oldNodes))
+ newList.append(d->index(node, col));
+
changePersistentIndexList(oldList, newList);
emit layoutChanged();
}
@@ -1195,7 +1164,7 @@
*/
QStringList QFileSystemModel::mimeTypes() const
{
- return QStringList(QLatin1String("text/uri-list"));
+ return QStringList("text/uri-list"_L1);
}
/*!
@@ -1203,15 +1172,15 @@
\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.
+ If the list of indexes is empty, \nullptr is returned rather than a
+ serialized empty list.
*/
QMimeData *QFileSystemModel::mimeData(const QModelIndexList &indexes) const
{
QList urls;
QList::const_iterator it = indexes.begin();
for (; it != indexes.end(); ++it)
- if ((*it).column() == 0)
+ if ((*it).column() == QFileSystemModelPrivate::NameColumn)
urls << QUrl::fromLocalFile(filePath(*it));
QMimeData *data = new QMimeData();
data->setUrls(urls);
@@ -1221,7 +1190,8 @@
/*!
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.
+ \a column and by the \a parent index. Returns true if the operation was
+ successful.
\sa supportedDropActions()
*/
@@ -1274,6 +1244,121 @@
}
/*!
+ \reimp
+*/
+QHash QFileSystemModel::roleNames() const
+{
+ auto ret = QAbstractItemModel::roleNames();
+ ret.insert(QFileSystemModel::FileIconRole,
+ QByteArrayLiteral("fileIcon")); // == Qt::decoration
+ ret.insert(QFileSystemModel::FilePathRole, QByteArrayLiteral("filePath"));
+ ret.insert(QFileSystemModel::FileNameRole, QByteArrayLiteral("fileName"));
+ ret.insert(QFileSystemModel::FilePermissions, QByteArrayLiteral("filePermissions"));
+ return ret;
+}
+
+/*!
+ \enum QFileSystemModel::Option
+ \since 5.14
+
+ \value DontWatchForChanges Do not add file watchers to the paths.
+ This reduces overhead when using the model for simple tasks
+ like line edit completion.
+
+ \value DontResolveSymlinks Don't resolve symlinks in the file
+ system model. By default, symlinks are resolved.
+
+ \value DontUseCustomDirectoryIcons Always use the default directory icon.
+ Some platforms allow the user to set a different icon. Custom icon lookup
+ causes a big performance impact over network or removable drives.
+ This sets the QFileIconProvider::DontUseCustomDirectoryIcons
+ option in the icon provider accordingly.
+
+ \sa resolveSymlinks
+*/
+
+/*!
+ \since 5.14
+ Sets the given \a option to be enabled if \a on is true; otherwise,
+ clears the given \a option.
+
+ Options should be set before changing properties.
+
+ \sa options, testOption()
+*/
+void QFileSystemModel::setOption(Option option, bool on)
+{
+ QFileSystemModel::Options previousOptions = options();
+ setOptions(previousOptions.setFlag(option, on));
+}
+
+/*!
+ \since 5.14
+
+ Returns \c true if the given \a option is enabled; otherwise, returns
+ false.
+
+ \sa options, setOption()
+*/
+bool QFileSystemModel::testOption(Option option) const
+{
+ return options().testFlag(option);
+}
+
+/*!
+ \property QFileSystemModel::options
+ \brief the various options that affect the model
+ \since 5.14
+
+ By default, all options are disabled.
+
+ Options should be set before changing properties.
+
+ \sa setOption(), testOption()
+*/
+void QFileSystemModel::setOptions(Options options)
+{
+ const Options changed = (options ^ QFileSystemModel::options());
+
+ if (changed.testFlag(DontResolveSymlinks))
+ setResolveSymlinks(!options.testFlag(DontResolveSymlinks));
+
+#if QT_CONFIG(filesystemwatcher)
+ Q_D(QFileSystemModel);
+ if (changed.testFlag(DontWatchForChanges))
+ d->fileInfoGatherer.setWatching(!options.testFlag(DontWatchForChanges));
+#endif
+
+ if (changed.testFlag(DontUseCustomDirectoryIcons)) {
+ if (auto provider = iconProvider()) {
+ QAbstractFileIconProvider::Options providerOptions = provider->options();
+ providerOptions.setFlag(QAbstractFileIconProvider::DontUseCustomDirectoryIcons,
+ options.testFlag(QFileSystemModel::DontUseCustomDirectoryIcons));
+ provider->setOptions(providerOptions);
+ } else {
+ qWarning("Setting QFileSystemModel::DontUseCustomDirectoryIcons has no effect when no provider is used");
+ }
+ }
+}
+
+QFileSystemModel::Options QFileSystemModel::options() const
+{
+ QFileSystemModel::Options result;
+ result.setFlag(DontResolveSymlinks, !resolveSymlinks());
+#if QT_CONFIG(filesystemwatcher)
+ Q_D(const QFileSystemModel);
+ result.setFlag(DontWatchForChanges, !d->fileInfoGatherer.isWatching());
+#else
+ result.setFlag(DontWatchForChanges);
+#endif
+ if (auto provider = iconProvider()) {
+ result.setFlag(DontUseCustomDirectoryIcons,
+ provider->options().testFlag(QAbstractFileIconProvider::DontUseCustomDirectoryIcons));
+ }
+ return result;
+}
+
+/*!
Returns the path of the item stored in the model under the
\a index given.
*/
@@ -1282,11 +1367,20 @@
Q_D(const QFileSystemModel);
QString fullPath = d->filePath(index);
QFileSystemModelPrivate::QFileSystemNode *dirNode = d->node(index);
- if (dirNode->isSymLink() && d->fileInfoGatherer.resolveSymlinks()
+ if (dirNode->isSymLink()
+#if QT_CONFIG(filesystemwatcher)
+ && d->fileInfoGatherer.resolveSymlinks()
+#endif
&& d->resolvedSymLinks.contains(fullPath)
&& dirNode->isDir()) {
- QFileInfo resolvedInfo(fullPath);
- resolvedInfo = resolvedInfo.canonicalFilePath();
+ QFileInfo fullPathInfo(dirNode->fileInfo());
+ if (!dirNode->hasInformation())
+ fullPathInfo = QFileInfo(fullPath);
+ QString canonicalPath = fullPathInfo.canonicalFilePath();
+ auto *canonicalNode = d->node(fullPathInfo.canonicalFilePath(), false);
+ QFileInfo resolvedInfo = canonicalNode->fileInfo();
+ if (!canonicalNode->hasInformation())
+ resolvedInfo = QFileInfo(canonicalPath);
if (resolvedInfo.exists())
return resolvedInfo.filePath();
}
@@ -1310,13 +1404,12 @@
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('/'))
+#if !defined(Q_OS_WIN)
+ if ((fullPath.size() > 2) && fullPath[0] == u'/' && fullPath[1] == u'/')
fullPath = fullPath.mid(1);
-#endif
-#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
- if (fullPath.length() == 2 && fullPath.endsWith(QLatin1Char(':')))
- fullPath.append(QLatin1Char('/'));
+#else
+ if (fullPath.length() == 2 && fullPath.endsWith(u':'))
+ fullPath.append(u'/');
#endif
return fullPath;
}
@@ -1337,7 +1430,9 @@
d->addNode(parentNode, name, QFileInfo());
Q_ASSERT(parentNode->children.contains(name));
QFileSystemModelPrivate::QFileSystemNode *node = parentNode->children[name];
+#if QT_CONFIG(filesystemwatcher)
node->populate(d->fileInfoGatherer.getInfo(QFileInfo(dir.absolutePath() + QDir::separator() + name)));
+#endif
d->addVisibleFiles(parentNode, QStringList(name));
return d->index(node);
}
@@ -1348,12 +1443,7 @@
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;
+ return d->node(index)->permissions();
}
/*!
@@ -1381,12 +1471,9 @@
#else
QString longNewPath = newPath;
#endif
- QDir newPathDir(longNewPath);
//we remove .. and . from the given path if exist
- if (!newPath.isEmpty()) {
+ if (!newPath.isEmpty())
longNewPath = QDir::cleanPath(longNewPath);
- newPathDir.setPath(longNewPath);
- }
d->setRootPath = true;
@@ -1397,14 +1484,23 @@
if (d->rootDir.path() == longNewPath)
return d->index(rootPath());
- bool showDrives = (longNewPath.isEmpty() || longNewPath == d->myComputer());
- if (!showDrives && !newPathDir.exists())
+ auto node = d->node(longNewPath);
+ QFileInfo newPathInfo;
+ if (node && node->hasInformation())
+ newPathInfo = node->fileInfo();
+ else
+ newPathInfo = QFileInfo(longNewPath);
+
+ bool showDrives = (longNewPath.isEmpty() || longNewPath == QFileSystemModelPrivate::myComputer());
+ if (!showDrives && !newPathInfo.exists())
return d->index(rootPath());
//We remove the watcher on the previous path
- if (!rootPath().isEmpty() && rootPath() != QLatin1String(".")) {
+ if (!rootPath().isEmpty() && rootPath() != "."_L1) {
//This remove the watcher for the old rootPath
+#if QT_CONFIG(filesystemwatcher)
d->fileInfoGatherer.removePath(rootPath());
+#endif
//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
@@ -1412,13 +1508,13 @@
}
// We have a new valid root path
- d->rootDir = newPathDir;
+ d->rootDir = QDir(longNewPath);
QModelIndex newRootIndex;
if (showDrives) {
// otherwise dir will become '.'
- d->rootDir.setPath(QLatin1String(""));
+ d->rootDir.setPath(""_L1);
} else {
- newRootIndex = d->index(newPathDir.path());
+ newRootIndex = d->index(d->rootDir.path());
}
fetchMore(newRootIndex);
emit rootPathChanged(longNewPath);
@@ -1455,20 +1551,26 @@
/*!
Sets the \a provider of file icons for the directory model.
*/
-void QFileSystemModel::setIconProvider(QFileIconProvider *provider)
+void QFileSystemModel::setIconProvider(QAbstractFileIconProvider *provider)
{
Q_D(QFileSystemModel);
+#if QT_CONFIG(filesystemwatcher)
d->fileInfoGatherer.setIconProvider(provider);
+#endif
d->root.updateIcon(provider, QString());
}
/*!
Returns the file icon provider for this directory model.
*/
-QFileIconProvider *QFileSystemModel::iconProvider() const
+QAbstractFileIconProvider *QFileSystemModel::iconProvider() const
{
+#if QT_CONFIG(filesystemwatcher)
Q_D(const QFileSystemModel);
return d->fileInfoGatherer.iconProvider();
+#else
+ return 0;
+#endif
}
/*!
@@ -1484,9 +1586,11 @@
Q_D(QFileSystemModel);
if (d->filters == filters)
return;
+ const bool changingCaseSensitivity =
+ filters.testFlag(QDir::CaseSensitive) != d->filters.testFlag(QDir::CaseSensitive);
d->filters = filters;
- // CaseSensitivity might have changed
- setNameFilters(nameFilters());
+ if (changingCaseSensitivity)
+ d->rebuildNameFilterRegexps();
d->forceSort = true;
d->delayedSort();
}
@@ -1509,20 +1613,30 @@
\property QFileSystemModel::resolveSymlinks
\brief Whether the directory model should resolve symbolic links
- This is only relevant on operating systems that support symbolic links.
+ This is only relevant on Windows.
- By default, this property is false.
+ By default, this property is \c true.
+
+ \sa QFileSystemModel::Options
*/
void QFileSystemModel::setResolveSymlinks(bool enable)
{
+#if QT_CONFIG(filesystemwatcher)
Q_D(QFileSystemModel);
d->fileInfoGatherer.setResolveSymlinks(enable);
+#else
+ Q_UNUSED(enable);
+#endif
}
bool QFileSystemModel::resolveSymlinks() const
{
+#if QT_CONFIG(filesystemwatcher)
Q_D(const QFileSystemModel);
return d->fileInfoGatherer.resolveSymlinks();
+#else
+ return false;
+#endif
}
/*!
@@ -1532,7 +1646,7 @@
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
+ This property is \c true by default
*/
void QFileSystemModel::setReadOnly(bool enable)
{
@@ -1550,7 +1664,7 @@
\property QFileSystemModel::nameFilterDisables
\brief Whether files that don't pass the name filter are hidden or disabled
- This property is true by default
+ This property is \c true by default
*/
void QFileSystemModel::setNameFilterDisables(bool enable)
{
@@ -1573,8 +1687,7 @@
*/
void QFileSystemModel::setNameFilters(const QStringList &filters)
{
- // Prep the regexp's ahead of time
-#ifndef QT_NO_REGEXP
+#if QT_CONFIG(regularexpression)
Q_D(QFileSystemModel);
if (!d->bypassFilters.isEmpty()) {
@@ -1582,10 +1695,9 @@
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));
+ const QModelIndexList persistentList = persistentIndexList();
+ for (const auto &persistentIndex : persistentList) {
+ QFileSystemModelPrivate::QFileSystemNode *node = d->node(persistentIndex);
while (node) {
if (d->bypassFilters.contains(node))
break;
@@ -1596,14 +1708,12 @@
}
}
- 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->nameFilters = filters;
+ d->rebuildNameFilterRegexps();
d->forceSort = true;
d->delayedSort();
+#else
+ Q_UNUSED(filters);
#endif
}
@@ -1612,14 +1722,12 @@
*/
QStringList QFileSystemModel::nameFilters() const
{
+#if QT_CONFIG(regularexpression)
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();
- }
+ return d->nameFilters;
+#else
+ return QStringList();
#endif
- return filters;
}
/*!
@@ -1627,20 +1735,27 @@
*/
bool QFileSystemModel::event(QEvent *event)
{
+#if QT_CONFIG(filesystemwatcher)
Q_D(QFileSystemModel);
if (event->type() == QEvent::LanguageChange) {
d->root.retranslateStrings(d->fileInfoGatherer.iconProvider(), QString());
return true;
}
+#endif
return QAbstractItemModel::event(event);
}
-bool QFileSystemModel::rmdir(const QModelIndex &aindex) const
+bool QFileSystemModel::rmdir(const QModelIndex &aindex)
{
QString path = filePath(aindex);
- QFileSystemModelPrivate * d = const_cast(d_func());
- d->fileInfoGatherer.removePath(path);
- return QDir().rmdir(path);
+ const bool success = QDir().rmdir(path);
+#if QT_CONFIG(filesystemwatcher)
+ if (success) {
+ QFileSystemModelPrivate * d = const_cast(d_func());
+ d->fileInfoGatherer.removePath(path);
+ }
+#endif
+ return success;
}
/*!
@@ -1652,37 +1767,41 @@
void QFileSystemModelPrivate::_q_directoryChanged(const QString &directory, const QStringList &files)
{
QFileSystemModelPrivate::QFileSystemNode *parentNode = node(directory, false);
- if (parentNode->children.count() == 0)
+ if (parentNode->children.size() == 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();
+ QStringList newFiles = files;
+ std::sort(newFiles.begin(), newFiles.end());
+ for (auto i = parentNode->children.constBegin(), cend = parentNode->children.constEnd(); i != cend; ++i) {
+ QStringList::iterator iterator = std::lower_bound(newFiles.begin(), newFiles.end(), i.value()->fileName);
+ if ((iterator == newFiles.end()) || (i.value()->fileName < *iterator))
+ toRemove.append(i.value()->fileName);
}
-#else
- QStringList newFiles = files;
-#endif
- qSort(newFiles.begin(), newFiles.end());
- QHash::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 )
+ for (int i = 0 ; i < toRemove.size() ; ++i )
removeNode(parentNode, toRemove[i]);
}
+#if defined(Q_OS_WIN)
+static QString volumeName(const QString &path)
+{
+ IShellItem *item = nullptr;
+ const QString native = QDir::toNativeSeparators(path);
+ HRESULT hr = SHCreateItemFromParsingName(reinterpret_cast(native.utf16()),
+ nullptr, IID_IShellItem,
+ reinterpret_cast(&item));
+ if (FAILED(hr))
+ return QString();
+ LPWSTR name = nullptr;
+ hr = item->GetDisplayName(SIGDN_NORMALDISPLAY, &name);
+ if (FAILED(hr))
+ return QString();
+ QString result = QString::fromWCharArray(name);
+ CoTaskMemFree(name);
+ item->Release();
+ return result;
+}
+#endif // Q_OS_WIN
+
/*!
\internal
@@ -1694,21 +1813,17 @@
{
// In the common case, itemLocation == count() so check there first
QFileSystemModelPrivate::QFileSystemNode *node = new QFileSystemModelPrivate::QFileSystemNode(fileName, parentNode);
-#ifndef QT_NO_FILESYSTEMWATCHER
+#if QT_CONFIG(filesystemwatcher)
node->populate(info);
+#else
+ Q_UNUSED(info);
#endif
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+#if defined(Q_OS_WIN)
//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);
- }
+ if (parentNode->fileName.isEmpty())
+ node->volumeName = volumeName(fileName);
#endif
+ Q_ASSERT(!parentNode->children.contains(fileName));
parentNode->children.insert(fileName, node);
return node;
}
@@ -1740,26 +1855,6 @@
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
@@ -1774,16 +1869,16 @@
QModelIndex parent = index(parentNode);
bool indexHidden = isHiddenByFilter(parentNode, parent);
if (!indexHidden) {
- q->beginInsertRows(parent, parentNode->visibleChildren.count() , parentNode->visibleChildren.count() + newFiles.count() - 1);
+ q->beginInsertRows(parent, parentNode->visibleChildren.size() , parentNode->visibleChildren.size() + newFiles.size() - 1);
}
if (parentNode->dirtyChildrenIndex == -1)
- parentNode->dirtyChildrenIndex = parentNode->visibleChildren.count();
+ parentNode->dirtyChildrenIndex = parentNode->visibleChildren.size();
- for (int i = 0; i < newFiles.count(); ++i) {
- parentNode->visibleChildren.append(newFiles.at(i));
- parentNode->children[newFiles.at(i)]->isVisible = true;
- }
+ for (const auto &newFile : newFiles) {
+ parentNode->visibleChildren.append(newFile);
+ parentNode->children.value(newFile)->isVisible = true;
+ }
if (!indexHidden)
q->endInsertRows();
}
@@ -1805,7 +1900,7 @@
if (!indexHidden)
q->beginRemoveRows(parent, translateVisibleLocation(parentNode, vLocation),
translateVisibleLocation(parentNode, vLocation));
- parentNode->children[parentNode->visibleChildren.at(vLocation)]->isVisible = false;
+ parentNode->children.value(parentNode->visibleChildren.at(vLocation))->isVisible = false;
parentNode->visibleChildren.removeAt(vLocation);
if (!indexHidden)
q->endRemoveRows();
@@ -1817,17 +1912,19 @@
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 > &updates)
+void QFileSystemModelPrivate::_q_fileSystemChanged(const QString &path,
+ const QList> &updates)
{
+#if QT_CONFIG(filesystemwatcher)
Q_Q(QFileSystemModel);
- QVector rowsToUpdate;
+ QList 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;
+ for (const auto &update : updates) {
+ QString fileName = update.first;
Q_ASSERT(!fileName.isEmpty());
- QExtendedInformation info = fileInfoGatherer.getInfo(updates.at(i).second);
+ QExtendedInformation info = fileInfoGatherer.getInfo(update.second);
bool previouslyHere = parentNode->children.contains(fileName);
if (!previouslyHere) {
addNode(parentNode, fileName, info.fileInfo());
@@ -1847,10 +1944,6 @@
node->fileName = fileName;
}
- if (info.size() == -1 && !info.isSymLink()) {
- removeNode(parentNode, fileName);
- continue;
- }
if (*node != info ) {
node->populate(info);
bypassFilters.remove(node);
@@ -1873,11 +1966,10 @@
}
// bundle up all of the changed signals into as few as possible.
- qSort(rowsToUpdate.begin(), rowsToUpdate.end());
+ std::sort(rowsToUpdate.begin(), rowsToUpdate.end());
QString min;
QString max;
- for (int i = 0; i < rowsToUpdate.count(); ++i) {
- QString value = rowsToUpdate.at(i);
+ for (const QString &value : std::as_const(rowsToUpdate)) {
//##TODO is there a way to bundle signals with QString as the content of the list?
/*if (min.isEmpty()) {
min = value;
@@ -1895,26 +1987,37 @@
int visibleMin = parentNode->visibleLocation(min);
int visibleMax = parentNode->visibleLocation(max);
if (visibleMin >= 0
- && visibleMin < parentNode->visibleChildren.count()
+ && visibleMin < parentNode->visibleChildren.size()
&& 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);
+ // don't use NumColumns here, a subclass might override columnCount
+ const int lastColumn = q->columnCount(parentIndex) - 1;
+ const QModelIndex top = q->index(translateVisibleLocation(parentNode, visibleMin),
+ QFileSystemModelPrivate::NameColumn, parentIndex);
+ const QModelIndex bottom = q->index(translateVisibleLocation(parentNode, visibleMax),
+ lastColumn, parentIndex);
+ // We document that emitting dataChanged with indexes that don't have the
+ // same parent is undefined behavior.
+ Q_ASSERT(bottom.parent() == top.parent());
+ emit q->dataChanged(top, bottom);
}
/*min = QString();
max = QString();*/
}
- if (newFiles.count() > 0) {
+ if (newFiles.size() > 0) {
addVisibleFiles(parentNode, newFiles);
}
- if (newFiles.count() > 0 || (sortColumn != 0 && rowsToUpdate.count() > 0)) {
+ if (newFiles.size() > 0 || (sortColumn != 0 && rowsToUpdate.size() > 0)) {
forceSort = true;
delayedSort();
}
+#else
+ Q_UNUSED(path);
+ Q_UNUSED(updates);
+#endif // filesystemwatcher
}
/*!
@@ -1925,35 +2028,77 @@
resolvedSymLinks[fileName] = resolvedName;
}
+#if QT_CONFIG(filesystemwatcher) && defined(Q_OS_WIN)
+// Remove file system watchers at/below the index and return a list of previously
+// watched files. This should be called prior to operations like rename/remove
+// which might fail due to watchers on platforms like Windows. The watchers
+// should be restored on failure.
+QStringList QFileSystemModelPrivate::unwatchPathsAt(const QModelIndex &index)
+{
+ const QFileSystemModelPrivate::QFileSystemNode *indexNode = node(index);
+ if (indexNode == nullptr)
+ return QStringList();
+ const Qt::CaseSensitivity caseSensitivity = indexNode->caseSensitive()
+ ? Qt::CaseSensitive : Qt::CaseInsensitive;
+ const QString path = indexNode->fileInfo().absoluteFilePath();
+
+ QStringList result;
+ const auto filter = [path, caseSensitivity] (const QString &watchedPath)
+ {
+ const int pathSize = path.size();
+ if (pathSize == watchedPath.size()) {
+ return path.compare(watchedPath, caseSensitivity) == 0;
+ } else if (watchedPath.size() > pathSize) {
+ return watchedPath.at(pathSize) == u'/'
+ && watchedPath.startsWith(path, caseSensitivity);
+ }
+ return false;
+ };
+
+ const QStringList &watchedFiles = fileInfoGatherer.watchedFiles();
+ std::copy_if(watchedFiles.cbegin(), watchedFiles.cend(),
+ std::back_inserter(result), filter);
+
+ const QStringList &watchedDirectories = fileInfoGatherer.watchedDirectories();
+ std::copy_if(watchedDirectories.cbegin(), watchedDirectories.cend(),
+ std::back_inserter(result), filter);
+
+ fileInfoGatherer.unwatchPaths(result);
+ return result;
+}
+#endif // filesystemwatcher && Q_OS_WIN
+
+QFileSystemModelPrivate::QFileSystemModelPrivate() = default;
+
+QFileSystemModelPrivate::~QFileSystemModelPrivate() = default;
+
/*!
\internal
*/
void QFileSystemModelPrivate::init()
{
Q_Q(QFileSystemModel);
- qRegisterMetaType > >("QList >");
+
+ delayedSortTimer.setSingleShot(true);
+
+ qRegisterMetaType>>();
+#if QT_CONFIG(filesystemwatcher)
q->connect(&fileInfoGatherer, SIGNAL(newListOfFiles(QString,QStringList)),
q, SLOT(_q_directoryChanged(QString,QStringList)));
- q->connect(&fileInfoGatherer, SIGNAL(updates(QString,QList >)),
- q, SLOT(_q_fileSystemChanged(QString,QList >)));
+ q->connect(&fileInfoGatherer, SIGNAL(updates(QString,QList>)), q,
+ SLOT(_q_fileSystemChanged(QString,QList>)));
q->connect(&fileInfoGatherer, SIGNAL(nameResolved(QString,QString)),
q, SLOT(_q_resolvedName(QString,QString)));
q->connect(&fileInfoGatherer, SIGNAL(directoryLoaded(QString)),
q, SIGNAL(directoryLoaded(QString)));
+#endif // filesystemwatcher
q->connect(&delayedSortTimer, SIGNAL(timeout()), q, SLOT(_q_performDelayedSort()), Qt::QueuedConnection);
-
- QHash 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
+ Returns \c false if node doesn't pass the filters otherwise true
QDir::Modified is not supported
QDir::Drives is not supported
@@ -1978,13 +2123,12 @@
const bool hideHidden = !(filters & QDir::Hidden);
const bool hideSystem = !(filters & QDir::System);
const bool hideSymlinks = (filters & QDir::NoSymLinks);
- const bool hideDot = (filters & QDir::NoDot) || (filters & QDir::NoDotAndDotDot); // ### Qt5: simplify (because NoDotAndDotDot=NoDot|NoDotDot)
- const bool hideDotDot = (filters & QDir::NoDotDot) || (filters & QDir::NoDotAndDotDot); // ### Qt5: simplify (because NoDotAndDotDot=NoDot|NoDotDot)
+ const bool hideDot = (filters & QDir::NoDot);
+ const bool hideDotDot = (filters & QDir::NoDotDot);
- // 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 isDot = (node->fileName == QLatin1String("."));
- bool isDotDot = (node->fileName == QLatin1String(".."));
+ // Note that we match the behavior of entryList and not QFileInfo on this.
+ bool isDot = (node->fileName == "."_L1);
+ bool isDotDot = (node->fileName == ".."_L1);
if ( (hideHidden && !(isDot || isDotDot) && node->isHidden())
|| (hideSystem && node->isSystem())
|| (hideDirs && node->isDir())
@@ -2003,28 +2147,47 @@
/*
\internal
- Returns true if node passes the name filters and should be visible.
+ Returns \c true if node passes the name filters and should be visible.
*/
bool QFileSystemModelPrivate::passNameFilters(const QFileSystemNode *node) const
{
-#ifndef QT_NO_REGEXP
+#if QT_CONFIG(regularexpression)
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;
+ const auto matchesNodeFileName = [node](const QRegularExpression &re)
+ {
+ return node->fileName.contains(re);
+ };
+ return std::any_of(nameFiltersRegexps.begin(),
+ nameFiltersRegexps.end(),
+ matchesNodeFileName);
}
+#else
+ Q_UNUSED(node);
#endif
return true;
}
+#if QT_CONFIG(regularexpression)
+void QFileSystemModelPrivate::rebuildNameFilterRegexps()
+{
+ nameFiltersRegexps.clear();
+ nameFiltersRegexps.reserve(nameFilters.size());
+ const auto cs = (filters & QDir::CaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive;
+ const auto convertWildcardToRegexp = [cs](const QString &nameFilter)
+ {
+ return QRegularExpression::fromWildcard(nameFilter, cs);
+ };
+ std::transform(nameFilters.constBegin(),
+ nameFilters.constEnd(),
+ std::back_inserter(nameFiltersRegexps),
+ convertWildcardToRegexp);
+}
+#endif
+
QT_END_NAMESPACE
#include "moc_qfilesystemmodel.cpp"
-
-#endif // QT_NO_FILESYSTEMMODEL
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qt/qfontdialog.cpp
--- a/libgui/languages/build_ts/octave-qt/qfontdialog.cpp Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qt/qfontdialog.cpp Mon Dec 04 19:55:32 2023 +0100
@@ -1,56 +1,15 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowdefs.h"
+#include "qfontdialog.h"
-#ifndef QT_NO_FONTDIALOG
-
-#include "qfontdialog.h"
#include "qfontdialog_p.h"
#include
#include
#include
#include
-#include
#include
#include
#include
@@ -62,14 +21,13 @@
#include
#include
#include
+#include
#include
#include
-#if defined(Q_WS_S60)
-#include
-#endif
+QT_BEGIN_NAMESPACE
-QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
class QFontListView : public QListView
{
@@ -92,7 +50,7 @@
int row = QListView::currentIndex().row();
return row < 0 ? QString() : model()->stringList().at(row);
}
- void currentChanged(const QModelIndex ¤t, const QModelIndex &previous) {
+ void currentChanged(const QModelIndex ¤t, const QModelIndex &previous) override {
QListView::currentChanged(current, previous);
if (current.isValid())
emit highlighted(current.row());
@@ -111,12 +69,23 @@
setEditTriggers(NoEditTriggers);
}
-static const Qt::WindowFlags DefaultWindowFlags =
- Qt::Dialog | Qt::WindowSystemMenuHint;
+static const Qt::WindowFlags qfd_DefaultWindowFlags =
+ Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
+
+QFontDialogPrivate::QFontDialogPrivate()
+ : writingSystem(QFontDatabase::Any),
+ options(QFontDialogOptions::create())
+{
+}
+
+QFontDialogPrivate::~QFontDialogPrivate()
+{
+}
/*!
\class QFontDialog
\ingroup standard-dialogs
+ \inmodule QtWidgets
\brief The QFontDialog class provides a dialog widget for selecting a font.
@@ -125,16 +94,16 @@
Examples:
- \snippet doc/src/snippets/code/src_gui_dialogs_qfontdialog.cpp 0
+ \snippet 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
+ \snippet 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.
+ \image fusion-fontdialog.png A font dialog in the Fusion widget style.
- \sa QFont, QFontInfo, QFontMetrics, QColorDialog, QFileDialog, QPrintDialog,
+ \sa QFont, QFontInfo, QFontMetrics, QColorDialog, QFileDialog,
{Standard Dialogs Example}
*/
@@ -150,7 +119,7 @@
\sa getFont()
*/
QFontDialog::QFontDialog(QWidget *parent)
- : QDialog(*new QFontDialogPrivate, parent, DefaultWindowFlags)
+ : QDialog(*new QFontDialogPrivate, parent, qfd_DefaultWindowFlags)
{
Q_D(QFontDialog);
d->init();
@@ -163,10 +132,8 @@
\a initial font.
*/
QFontDialog::QFontDialog(const QFont &initial, QWidget *parent)
- : QDialog(*new QFontDialogPrivate, parent, DefaultWindowFlags)
+ : QFontDialog(parent)
{
- Q_D(QFontDialog);
- d->init();
setCurrentFont(initial);
}
@@ -174,11 +141,6 @@
{
Q_Q(QFontDialog);
-#ifdef Q_WS_MAC
- nativeDialogInUse = false;
- delegate = 0;
-#endif
-
q->setSizeGripEnabled(true);
q->setWindowTitle(QFontDialog::tr("Select Font"));
@@ -232,7 +194,7 @@
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"));
+ sampleEdit->setText("AaBbYyZz"_L1);
hbox->addWidget(sampleEdit);
writingSystemCombo = new QComboBox(q);
@@ -264,8 +226,10 @@
}
updateFamilies();
- if (familyList->count() != 0)
+ if (familyList->count() != 0) {
familyList->setCurrentItem(0);
+ sizeList->setCurrentItem(0);
+ }
// grid layout
QGridLayout *mainGrid = new QGridLayout(q);
@@ -278,7 +242,7 @@
mainGrid->setColumnMinimumWidth(3, spacing);
int margin = 0;
- mainGrid->getContentsMargins(0, 0, 0, &margin);
+ mainGrid->getContentsMargins(nullptr, nullptr, nullptr, &margin);
mainGrid->setRowMinimumHeight(3, margin);
mainGrid->setRowMinimumHeight(6, 2);
@@ -319,13 +283,7 @@
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);
@@ -334,6 +292,7 @@
familyList->setFocus();
retranslateStrings();
+ sampleEdit->setObjectName("qt_fontDialog_sampleEdit"_L1);
}
/*!
@@ -343,32 +302,25 @@
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.
+ If the user clicks \uicontrol OK, the selected font is returned. If the user
+ clicks \uicontrol 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.
+ the value it refers to is set to true if the user clicks \uicontrol OK, and set to
+ false if the user clicks \uicontrol Cancel.
Examples:
- \snippet doc/src/snippets/code/src_gui_dialogs_qfontdialog.cpp 2
+ \snippet 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
+ \snippet 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.
@@ -384,36 +336,19 @@
/*!
\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.
+ If the user clicks \uicontrol OK, the selected font is returned. If the user
+ clicks \uicontrol 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.
+ to true if the user clicks \uicontrol OK, and false if the user clicks
+ \uicontrol Cancel.
Example:
- \snippet doc/src/snippets/code/src_gui_dialogs_qfontdialog.cpp 4
+ \snippet 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
@@ -422,7 +357,7 @@
QFont QFontDialog::getFont(bool *ok, QWidget *parent)
{
QFont initial;
- return QFontDialogPrivate::getFont(ok, initial, parent, QString(), 0);
+ return QFontDialogPrivate::getFont(ok, initial, parent, QString(), { });
}
QFont QFontDialogPrivate::getFont(bool *ok, const QFont &initial, QWidget *parent,
@@ -455,7 +390,7 @@
{
Q_D(QFontDialog);
if (e->type() == QEvent::KeyPress) {
- QKeyEvent *k = (QKeyEvent *)e;
+ QKeyEvent *k = static_cast(e);
if (o == d->sizeEdit &&
(k->key() == Qt::Key_Up ||
k->key() == Qt::Key_Down ||
@@ -463,10 +398,10 @@
k->key() == Qt::Key_PageDown)) {
int ci = d->sizeList->currentItem();
- ()QApplication::sendEvent(d->sizeList, k);
+ QCoreApplication::sendEvent(d->sizeList, k);
if (ci != d->sizeList->currentItem()
- && style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, 0, this))
+ && style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, nullptr, this))
d->sizeEdit->selectAll();
return true;
} else if ((o == d->familyList || o == d->styleList) &&
@@ -476,7 +411,7 @@
return true;
}
} else if (e->type() == QEvent::FocusIn
- && style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, 0, this)) {
+ && style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, nullptr, this)) {
if (o == d->familyList)
d->familyEdit->selectAll();
else if (o == d->styleList)
@@ -489,6 +424,21 @@
return QDialog::eventFilter(o, e);
}
+void QFontDialogPrivate::initHelper(QPlatformDialogHelper *h)
+{
+ Q_Q(QFontDialog);
+ auto *fontDialogHelper = static_cast(h);
+ fontDialogHelper->setOptions(options);
+ fontDialogHelper->setCurrentFont(q->currentFont());
+ QObject::connect(h, SIGNAL(currentFontChanged(QFont)), q, SIGNAL(currentFontChanged(QFont)));
+ QObject::connect(h, SIGNAL(fontSelected(QFont)), q, SIGNAL(fontSelected(QFont)));
+}
+
+void QFontDialogPrivate::helperPrepareShow(QPlatformDialogHelper *)
+{
+ options->setWindowTitle(q_func()->windowTitle());
+}
+
/*
Updates the contents of the "font family" list box. This
function can be reimplemented if you have special requirements.
@@ -500,7 +450,26 @@
enum match_t { MATCH_NONE = 0, MATCH_LAST_RESORT = 1, MATCH_APP = 2, MATCH_FAMILY = 3 };
- QStringList familyNames = fdb.families(writingSystem);
+ const QFontDialog::FontDialogOptions scalableMask = (QFontDialog::ScalableFonts | QFontDialog::NonScalableFonts);
+ const QFontDialog::FontDialogOptions spacingMask = (QFontDialog::ProportionalFonts | QFontDialog::MonospacedFonts);
+ const QFontDialog::FontDialogOptions options = q->options();
+
+ QStringList familyNames;
+ const auto families = QFontDatabase::families(writingSystem);
+ for (const QString &family : families) {
+ if (QFontDatabase::isPrivateFamily(family))
+ continue;
+
+ if ((options & scalableMask) && (options & scalableMask) != scalableMask) {
+ if (bool(options & QFontDialog::ScalableFonts) != QFontDatabase::isSmoothlyScalable(family))
+ continue;
+ }
+ if ((options & spacingMask) && (options & spacingMask) != spacingMask) {
+ if (bool(options & QFontDialog::MonospacedFonts) != QFontDatabase::isFixedPitch(family))
+ continue;
+ }
+ familyNames << family;
+ }
familyList->model()->setStringList(familyNames);
@@ -511,12 +480,12 @@
QFont f;
// ##### do the right thing for a list of family names in the font.
- QFontDatabase::parseFontName(family, foundryName1, familyName1);
+ QFontDatabasePrivate::parseFontName(family, foundryName1, familyName1);
QStringList::const_iterator it = familyNames.constBegin();
int i = 0;
for(; it != familyNames.constEnd(); ++it, ++i) {
- QFontDatabase::parseFontName(*it, foundryName2, familyName2);
+ QFontDatabasePrivate::parseFontName(*it, foundryName2, familyName2);
//try to match...
if (familyName1 == familyName2) {
@@ -531,9 +500,9 @@
//and try some fall backs
match_t type = MATCH_NONE;
- if (bestFamilyType <= MATCH_NONE && familyName2 == f.lastResortFamily())
+ if (bestFamilyType <= MATCH_NONE && familyName2 == QStringLiteral("helvetica"))
type = MATCH_LAST_RESORT;
- if (bestFamilyType <= MATCH_LAST_RESORT && familyName2 == f.family())
+ if (bestFamilyType <= MATCH_LAST_RESORT && familyName2 == f.families().first())
type = MATCH_APP;
// ### add fallback for writingSystem
if (type != MATCH_NONE) {
@@ -547,7 +516,7 @@
else
familyList->setCurrentItem(0);
familyEdit->setText(familyList->currentText());
- if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, 0, q)
+ if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, nullptr, q)
&& familyList->hasFocus())
familyEdit->selectAll();
@@ -561,7 +530,7 @@
void QFontDialogPrivate::updateStyles()
{
Q_Q(QFontDialog);
- QStringList styles = fdb.styles(familyList->currentText());
+ QStringList styles = QFontDatabase::styles(familyList->currentText());
styleList->model()->setStringList(styles);
if (styles.isEmpty()) {
@@ -574,7 +543,7 @@
QString cstyle = style;
redo:
- for (int i = 0; i < (int)styleList->count(); i++) {
+ for (int i = 0; i < static_cast(styleList->count()); i++) {
if (cstyle == styleList->text(i)) {
styleList->setCurrentItem(i);
found = true;
@@ -582,12 +551,20 @@
}
}
if (!found && first) {
- if (cstyle.contains(QLatin1String("Italic"))) {
- cstyle.replace(QLatin1String("Italic"), QLatin1String("Oblique"));
+ if (cstyle.contains("Italic"_L1)) {
+ cstyle.replace("Italic"_L1, "Oblique"_L1);
first = false;
goto redo;
- } else if (cstyle.contains(QLatin1String("Oblique"))) {
- cstyle.replace(QLatin1String("Oblique"), QLatin1String("Italic"));
+ } else if (cstyle.contains("Oblique"_L1)) {
+ cstyle.replace("Oblique"_L1, "Italic"_L1);
+ first = false;
+ goto redo;
+ } else if (cstyle.contains("Regular"_L1)) {
+ cstyle.replace("Regular"_L1, "Normal"_L1);
+ first = false;
+ goto redo;
+ } else if (cstyle.contains("Normal"_L1)) {
+ cstyle.replace("Normal"_L1, "Regular"_L1);
first = false;
goto redo;
}
@@ -599,11 +576,11 @@
}
styleEdit->setText(styleList->currentText());
- if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, 0, q)
+ if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, nullptr, q)
&& styleList->hasFocus())
styleEdit->selectAll();
- smoothScalable = fdb.isSmoothlyScalable(familyList->currentText(), styleList->currentText());
+ smoothScalable = QFontDatabase::isSmoothlyScalable(familyList->currentText(), styleList->currentText());
}
updateSizes();
@@ -620,30 +597,27 @@
Q_Q(QFontDialog);
if (!familyList->currentText().isEmpty()) {
- QList sizes = fdb.pointSizes(familyList->currentText(), styleList->currentText());
+ QList sizes = QFontDatabase::pointSizes(familyList->currentText(), styleList->currentText());
int i = 0;
int current = -1;
QStringList str_sizes;
+ str_sizes.reserve(sizes.size());
for(QList::const_iterator it = sizes.constBegin(); it != sizes.constEnd(); ++it) {
str_sizes.append(QString::number(*it));
- if (current == -1 && *it >= size)
+ 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);
+ if (current != -1)
+ sizeList->setCurrentItem(current);
- sizeEdit->blockSignals(true);
+ const QSignalBlocker blocker(sizeEdit);
sizeEdit->setText((smoothScalable ? QString::number(size) : sizeList->currentText()));
- if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, 0, q)
+ if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, nullptr, q)
&& sizeList->hasFocus())
sizeEdit->selectAll();
- sizeEdit->blockSignals(false);
} else {
sizeEdit->clear();
}
@@ -655,7 +629,7 @@
{
// compute new font
int pSize = sizeEdit->text().toInt();
- QFont newFont(fdb.font(familyList->currentText(), style, pSize));
+ QFont newFont(QFontDatabase::font(familyList->currentText(), style, pSize));
newFont.setStrikeOut(strikeout->isChecked());
newFont.setUnderline(underline->isChecked());
@@ -680,7 +654,7 @@
void QFontDialogPrivate::_q_writingSystemHighlighted(int index)
{
writingSystem = QFontDatabase::WritingSystem(index);
- sampleEdit->setText(fdb.writingSystemSample(writingSystem));
+ sampleEdit->setText(QFontDatabase::writingSystemSample(writingSystem));
updateFamilies();
}
@@ -692,7 +666,7 @@
Q_Q(QFontDialog);
family = familyList->text(i);
familyEdit->setText(family);
- if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, 0, q)
+ if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, nullptr, q)
&& familyList->hasFocus())
familyEdit->selectAll();
@@ -709,7 +683,7 @@
Q_Q(QFontDialog);
QString s = styleList->text(index);
styleEdit->setText(s);
- if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, 0, q)
+ if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, nullptr, q)
&& styleList->hasFocus())
styleEdit->selectAll();
@@ -728,7 +702,7 @@
Q_Q(QFontDialog);
QString s = sizeList->text(index);
sizeEdit->setText(s);
- if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, 0, q)
+ if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, nullptr, q)
&& sizeEdit->hasFocus())
sizeEdit->selectAll();
@@ -756,9 +730,11 @@
if (sizeList->text(i).toInt() >= this->size)
break;
}
- sizeList->blockSignals(true);
- sizeList->setCurrentItem(i);
- sizeList->blockSignals(false);
+ const QSignalBlocker blocker(sizeList);
+ if (sizeList->text(i).toInt() == this->size)
+ sizeList->setCurrentItem(i);
+ else
+ sizeList->clearSelection();
}
_q_updateSample();
}
@@ -768,11 +744,7 @@
familyAccel->setText(QFontDialog::tr("&Font"));
styleAccel->setText(QFontDialog::tr("Font st&yle"));
sizeAccel->setText(QFontDialog::tr("&Size"));
-#ifndef Q_WS_S60
- // Removed the title due to lack of screen estate in small S60 screen.
- // The effects are descriptive without a title (strikeout, underline).
effects->setTitle(QFontDialog::tr("Effects"));
-#endif
strikeout->setText(QFontDialog::tr("Stri&keout"));
underline->setText(QFontDialog::tr("&Underline"));
sample->setTitle(QFontDialog::tr("Sample"));
@@ -808,8 +780,8 @@
void QFontDialog::setCurrentFont(const QFont &font)
{
Q_D(QFontDialog);
- d->family = font.family();
- d->style = d->fdb.styleString(font);
+ d->family = font.families().value(0);
+ d->style = QFontDatabase::styleString(font);
d->size = font.pointSize();
if (d->size == -1) {
QFontInfo fi(font);
@@ -819,10 +791,10 @@
d->underline->setChecked(font.underline());
d->updateFamilies();
-#ifdef Q_WS_MAC
- if (d->delegate)
- QFontDialogPrivate::setFont(d->delegate, font);
-#endif
+ if (d->nativeDialogInUse) {
+ if (QPlatformFontDialogHelper *helper = d->platformFontDialogHelper())
+ helper->setCurrentFont(font);
+ }
}
/*!
@@ -835,11 +807,16 @@
QFont QFontDialog::currentFont() const
{
Q_D(const QFontDialog);
+
+ if (d->nativeDialogInUse) {
+ if (const QPlatformFontDialogHelper *helper = d->platformFontDialogHelper())
+ return helper->currentFont();
+ }
return d->sampleEdit->font();
}
/*!
- Returns the font that the user selected by clicking the \gui{OK}
+ Returns the font that the user selected by clicking the \uicontrol{OK}
or equivalent button.
\note This font is not always the same as the font held by the
@@ -859,10 +836,20 @@
This enum specifies various options that affect the look and feel
of a font dialog.
- \value NoButtons Don't display \gui{OK} and \gui{Cancel} buttons. (Useful for "live dialogs".)
+ For instance, it allows to specify which type of font should be
+ displayed. If none are specified all fonts available will be listed.
+
+ Note that the font filtering options might not be supported on some
+ platforms (e.g. Mac). They are always supported by the non native
+ dialog (used on Windows or Linux).
+
+ \value NoButtons Don't display \uicontrol{OK} and \uicontrol{Cancel} buttons. (Useful for "live dialogs".)
\value DontUseNativeDialog Use Qt's standard font dialog on the Mac instead of Apple's
- native font panel. (Currently, the native dialog is never used,
- but this is likely to change in future Qt releases.)
+ native font panel.
+ \value ScalableFonts Show scalable fonts
+ \value NonScalableFonts Show non scalable fonts
+ \value MonospacedFonts Show monospaced fonts
+ \value ProportionalFonts Show proportional fonts
\sa options, setOption(), testOption()
*/
@@ -875,13 +862,13 @@
*/
void QFontDialog::setOption(FontDialogOption option, bool on)
{
- Q_D(QFontDialog);
- if (!(d->opts & option) != !on)
- setOptions(d->opts ^ option);
+ const QFontDialog::FontDialogOptions previousOptions = options();
+ if (!(previousOptions & option) != !on)
+ setOptions(previousOptions ^ option);
}
/*!
- Returns true if the given \a option is enabled; otherwise, returns
+ Returns \c true if the given \a option is enabled; otherwise, returns
false.
\sa options, setOption()
@@ -889,7 +876,7 @@
bool QFontDialog::testOption(FontDialogOption option) const
{
Q_D(const QFontDialog);
- return (d->opts & option) != 0;
+ return d->options->testOption(static_cast(option));
}
/*!
@@ -909,28 +896,21 @@
{
Q_D(QFontDialog);
- FontDialogOptions changed = (options ^ d->opts);
- if (!changed)
+ if (QFontDialog::options() == options)
return;
- d->opts = options;
+ d->options->setOptions(QFontDialogOptions::FontDialogOptions(int(options)));
d->buttonBox->setVisible(!(options & NoButtons));
}
QFontDialog::FontDialogOptions QFontDialog::options() const
{
Q_D(const QFontDialog);
- return d->opts;
+ return QFontDialog::FontDialogOptions(int(d->options->options()));
}
-#ifdef Q_WS_MAC
-// can only have one Cocoa font panel active
-bool QFontDialogPrivate::sharedFontPanelAvailable = true;
-#endif
-
/*!
\since 4.5
- \overload
Opens the dialog and connects its fontSelected() signal to the slot specified
by \a receiver and \a member.
@@ -980,23 +960,32 @@
*/
void QFontDialog::setVisible(bool visible)
{
- if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden) != visible)
+ // will call QFontDialogPrivate::setVisible
+ QDialog::setVisible(visible);
+}
+
+/*!
+ \internal
+
+ The implementation of QFontDialog::setVisible() has to live here so that the call
+ to hide() in ~QDialog calls this function; it wouldn't call the override of
+ QDialog::setVisible().
+*/
+void QFontDialogPrivate::setVisible(bool visible)
+{
+ Q_Q(QFontDialog);
+ if (q->testAttribute(Qt::WA_WState_ExplicitShowHide) && q->testAttribute(Qt::WA_WState_Hidden) != visible)
return;
-#ifdef Q_WS_MAC
- Q_D(QFontDialog);
- if (d->canBeNativeDialog()){
- if (d->setVisible_sys(visible)){
- d->nativeDialogInUse = true;
- // Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below
- // updates the state correctly, but skips showing the non-native version:
- setAttribute(Qt::WA_DontShowOnScreen, true);
- } else {
- d->nativeDialogInUse = false;
- setAttribute(Qt::WA_DontShowOnScreen, false);
- }
+ if (canBeNativeDialog())
+ setNativeDialogVisible(visible);
+ if (nativeDialogInUse) {
+ // Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below
+ // updates the state correctly, but skips showing the non-native version:
+ q->setAttribute(Qt::WA_DontShowOnScreen, true);
+ } else {
+ q->setAttribute(Qt::WA_DontShowOnScreen, false);
}
-#endif // Q_WS_MAC
- QDialog::setVisible(visible);
+ QDialogPrivate::setVisible(visible);
}
/*!
@@ -1009,11 +998,10 @@
void QFontDialog::done(int result)
{
Q_D(QFontDialog);
- QDialog::done(result);
if (result == Accepted) {
// We check if this is the same font we had before, if so we emit currentFontChanged
QFont selectedFont = currentFont();
- if(selectedFont != d->selectedFont)
+ if (selectedFont != d->selectedFont)
emit(currentFontChanged(selectedFont));
d->selectedFont = selectedFont;
emit fontSelected(d->selectedFont);
@@ -1022,56 +1010,29 @@
if (d->receiverToDisconnectOnClose) {
disconnect(this, SIGNAL(fontSelected(QFont)),
d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);
- d->receiverToDisconnectOnClose = 0;
+ d->receiverToDisconnectOnClose = nullptr;
}
d->memberToDisconnectOnClose.clear();
+ QDialog::done(result);
}
-#ifdef Q_WS_MAC
-bool QFontDialogPrivate::canBeNativeDialog()
+bool QFontDialogPrivate::canBeNativeDialog() const
{
- Q_Q(QFontDialog);
+ // Don't use Q_Q here! This function is called from ~QDialog,
+ // so Q_Q calling q_func() invokes undefined behavior (invalid cast in q_func()).
+ const QDialog * const q = static_cast(q_ptr);
if (nativeDialogInUse)
return true;
- if (q->testAttribute(Qt::WA_DontShowOnScreen))
- return false;
- if (opts & QFontDialog::DontUseNativeDialog)
+ if (QCoreApplication::testAttribute(Qt::AA_DontUseNativeDialogs)
+ || q->testAttribute(Qt::WA_DontShowOnScreen)
+ || (options->options() & QFontDialog::DontUseNativeDialog)) {
return false;
-
- QLatin1String staticName(QFontDialog::staticMetaObject.className());
- QLatin1String dynamicName(q->metaObject()->className());
- return (staticName == dynamicName);
-}
-#endif // Q_WS_MAC
-
-/*!
- \fn QFont QFontDialog::getFont(bool *ok, const QFont &initial, QWidget* parent, const char* name)
- \since 4.5
-
- Call getFont(\a ok, \a initial, \a parent) instead.
+ }
- \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.
-
- The \a name parameter is ignored.
-*/
-
-/*!
- \fn QFont QFontDialog::getFont(bool *ok, QWidget* parent, const char* name)
-
- Call getFont(\a ok, \a parent) instead.
-
- \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.
-
- The \a name parameter is ignored.
-*/
+ return strcmp(QFontDialog::staticMetaObject.className(), q->metaObject()->className()) == 0;
+}
QT_END_NAMESPACE
#include "qfontdialog.moc"
#include "moc_qfontdialog.cpp"
-
-#endif // QT_NO_FONTDIALOG
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qt/qhelpsearchquerywidget.cpp
--- a/libgui/languages/build_ts/octave-qt/qhelpsearchquerywidget.cpp Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qt/qhelpsearchquerywidget.cpp Mon Dec 04 19:55:32 2023 +0100
@@ -1,43 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the Qt Assistant of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qhelpsearchquerywidget.h"
@@ -46,13 +8,13 @@
#include
#include
-#include
-#include
-#include
-#include
+#include
+#include
+#include
+#include
#include
-#include
-#include
+#include
+#include
QT_BEGIN_NAMESPACE
@@ -63,7 +25,7 @@
private:
struct QueryHistory {
explicit QueryHistory() : curQuery(-1) {}
- QList > queries;
+ QStringList queries;
int curQuery;
};
@@ -73,14 +35,14 @@
explicit CompleterModel(QObject *parent)
: QAbstractListModel(parent) {}
- int rowCount(const QModelIndex &parent = QModelIndex()) const
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override
{
return parent.isValid() ? 0 : termList.size();
}
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
{
- if (!index.isValid() || index.row() >= termList.count()||
+ if (!index.isValid() || index.row() >= termList.size()||
(role != Qt::EditRole && role != Qt::DisplayRole))
return QVariant();
return termList.at(index.row());
@@ -89,8 +51,9 @@
void addTerm(const QString &term)
{
if (!termList.contains(term)) {
+ beginResetModel();
termList.append(term);
- reset();
+ endResetModel();
}
}
@@ -100,285 +63,112 @@
QHelpSearchQueryWidgetPrivate()
: QObject()
- , simpleSearch(true)
- , searchCompleter(new CompleterModel(this), this)
+ , m_searchCompleter(new CompleterModel(this), this)
{
- searchButton = 0;
- advancedSearchWidget = 0;
- showHideAdvancedSearchButton = 0;
- defaultQuery = 0;
- exactQuery = 0;
- similarQuery = 0;
- withoutQuery = 0;
- allQuery = 0;
- atLeastQuery = 0;
}
- ~QHelpSearchQueryWidgetPrivate()
+ ~QHelpSearchQueryWidgetPrivate() override
{
// nothing todo
}
void retranslate()
{
- simpleSearchLabel->setText(QHelpSearchQueryWidget::tr("Search for:"));
- prevQueryButton->setToolTip(QHelpSearchQueryWidget::tr("Previous search"));
- nextQueryButton->setToolTip(QHelpSearchQueryWidget::tr("Next search"));
- searchButton->setText(QHelpSearchQueryWidget::tr("Search"));
-#ifdef QT_CLUCENE_SUPPORT
- advancedSearchLabel->setText(QHelpSearchQueryWidget::tr("Advanced search"));
- similarLabel->setText(QHelpSearchQueryWidget::tr("words similar to:"));
- withoutLabel->setText(QHelpSearchQueryWidget::tr("without the words:"));
- exactLabel->setText(QHelpSearchQueryWidget::tr("with exact phrase:"));
- allLabel->setText(QHelpSearchQueryWidget::tr("with all of the words:"));
- atLeastLabel->setText(QHelpSearchQueryWidget::tr("with at least one of the words:"));
+ m_searchLabel->setText(QHelpSearchQueryWidget::tr("Search for:"));
+ m_searchButton->setText(QHelpSearchQueryWidget::tr("Search"));
+#if QT_CONFIG(tooltip)
+ m_prevQueryButton->setToolTip(QHelpSearchQueryWidget::tr("Previous search"));
+ m_nextQueryButton->setToolTip(QHelpSearchQueryWidget::tr("Next search"));
#endif
}
- QStringList buildTermList(const QString query)
- {
- bool s = false;
- QString phrase;
- QStringList wordList;
- QString searchTerm = query;
-
- for (int i = 0; i < searchTerm.length(); ++i) {
- if (searchTerm[i] == QLatin1Char('\"') && !s) {
- s = true;
- phrase = searchTerm[i];
- continue;
- }
- if (searchTerm[i] != QLatin1Char('\"') && s)
- phrase += searchTerm[i];
- if (searchTerm[i] == QLatin1Char('\"') && s) {
- s = false;
- phrase += searchTerm[i];
- wordList.append(phrase);
- searchTerm.remove(phrase);
- }
- }
- if (s)
- searchTerm.replace(phrase, phrase.mid(1));
-
- const QRegExp exp(QLatin1String("\\s+"));
- wordList += searchTerm.split(exp, QString::SkipEmptyParts);
- return wordList;
- }
-
- void saveQuery(const QList &query, QueryHistory &queryHist)
+ void saveQuery(const QString &query)
{
// We only add the query to the list if it is different from the last one.
- bool insert = false;
- if (queryHist.queries.empty())
- insert = true;
- else {
- const QList &lastQuery = queryHist.queries.last();
- if (lastQuery.size() != query.size()) {
- insert = true;
- } else {
- for (int i = 0; i < query.size(); ++i) {
- if (query.at(i).fieldName != lastQuery.at(i).fieldName
- || query.at(i).wordList != lastQuery.at(i).wordList) {
- insert = true;
- break;
- }
- }
- }
- }
- if (insert) {
- queryHist.queries.append(query);
- foreach (const QHelpSearchQuery &queryPart, query) {
- static_cast(searchCompleter.model())->
- addTerm(queryPart.wordList.join(" "));
- }
- }
+ if (!m_queries.queries.isEmpty() && m_queries.queries.last() == query)
+ return;
+
+ m_queries.queries.append(query);
+ static_cast(m_searchCompleter.model())->addTerm(query);
}
void nextOrPrevQuery(int maxOrMinIndex, int addend, QToolButton *thisButton,
QToolButton *otherButton)
{
- QueryHistory *queryHist;
- QList lineEdits;
- if (simpleSearch) {
- queryHist = &simpleQueries;
- lineEdits << defaultQuery;
- } else {
- queryHist = &complexQueries;
- lineEdits << allQuery << atLeastQuery << similarQuery
- << withoutQuery << exactQuery;
- }
- foreach (QLineEdit *lineEdit, lineEdits)
- lineEdit->clear();
+ m_lineEdit->clear();
// Otherwise, the respective button would be disabled.
- Q_ASSERT(queryHist->curQuery != maxOrMinIndex);
+ Q_ASSERT(m_queries.curQuery != maxOrMinIndex);
- queryHist->curQuery += addend;
- const QList &query =
- queryHist->queries.at(queryHist->curQuery);
- foreach (const QHelpSearchQuery &queryPart, query) {
- if (QLineEdit *lineEdit = lineEditFor(queryPart.fieldName))
- lineEdit->setText(queryPart.wordList.join(" "));
- }
+ m_queries.curQuery = qBound(0, m_queries.curQuery + addend, m_queries.queries.size() - 1);
+ const QString &query = m_queries.queries.at(m_queries.curQuery);
+ m_lineEdit->setText(query);
- if (queryHist->curQuery == maxOrMinIndex)
+ if (m_queries.curQuery == maxOrMinIndex)
thisButton->setEnabled(false);
otherButton->setEnabled(true);
}
- QLineEdit* lineEditFor(const QHelpSearchQuery::FieldName &fieldName) const
- {
- switch (fieldName) {
- case QHelpSearchQuery::DEFAULT:
- return defaultQuery;
- case QHelpSearchQuery::ALL:
- return allQuery;
- case QHelpSearchQuery::ATLEAST:
- return atLeastQuery;
- case QHelpSearchQuery::FUZZY:
- return similarQuery;
- case QHelpSearchQuery::WITHOUT:
- return withoutQuery;
- case QHelpSearchQuery::PHRASE:
- return exactQuery;
- default:
- Q_ASSERT(0);
- }
- return 0;
- }
-
void enableOrDisableToolButtons()
{
- const QueryHistory &queryHist = simpleSearch ? simpleQueries
- : complexQueries;
- prevQueryButton->setEnabled(queryHist.curQuery > 0);
- nextQueryButton->setEnabled(queryHist.curQuery
- < queryHist.queries.size() - 1);
+ m_prevQueryButton->setEnabled(m_queries.curQuery > 0);
+ m_nextQueryButton->setEnabled(m_queries.curQuery
+ < m_queries.queries.size() - 1);
}
private slots:
- void showHideAdvancedSearch()
+ bool eventFilter(QObject *ob, QEvent *event) override
{
- if (simpleSearch) {
- advancedSearchWidget->show();
- showHideAdvancedSearchButton->setText((QLatin1String("-")));
- } else {
- advancedSearchWidget->hide();
- showHideAdvancedSearchButton->setText((QLatin1String("+")));
+ if (event->type() == QEvent::KeyPress) {
+ QKeyEvent *const keyEvent = static_cast(event);
+ if (keyEvent->key() == Qt::Key_Down) {
+ if (m_queries.curQuery + 1 < m_queries.queries.size())
+ nextQuery();
+ return true;
+ }
+ if (keyEvent->key() == Qt::Key_Up) {
+ if (m_queries.curQuery > 0)
+ prevQuery();
+ return true;
+ }
+
}
-
- simpleSearch = !simpleSearch;
- defaultQuery->setEnabled(simpleSearch);
- enableOrDisableToolButtons();
+ return QObject::eventFilter(ob, event);
}
void searchRequested()
{
- QList queryList;
-#if !defined(QT_CLUCENE_SUPPORT)
- queryList.append(QHelpSearchQuery(QHelpSearchQuery::DEFAULT,
- QStringList(defaultQuery->text())));
-
-#else
- if (defaultQuery->isEnabled()) {
- queryList.append(QHelpSearchQuery(QHelpSearchQuery::DEFAULT,
- buildTermList(defaultQuery->text())));
- } else {
- const QRegExp exp(QLatin1String("\\s+"));
- QStringList lst = similarQuery->text().split(exp,
- QString::SkipEmptyParts);
- if (!lst.isEmpty()) {
- QStringList fuzzy;
- foreach (const QString &term, lst)
- fuzzy += buildTermList(term);
- queryList.append(QHelpSearchQuery(QHelpSearchQuery::FUZZY,
- fuzzy));
- }
-
- lst = withoutQuery->text().split(exp, QString::SkipEmptyParts);
- if (!lst.isEmpty()) {
- QStringList without;
- foreach (const QString &term, lst)
- without.append(term);
- queryList.append(QHelpSearchQuery(QHelpSearchQuery::WITHOUT,
- without));
- }
-
- if (!exactQuery->text().isEmpty()) {
- QString phrase = exactQuery->text().remove(QLatin1Char('\"'));
- phrase = phrase.simplified();
- queryList.append(QHelpSearchQuery(QHelpSearchQuery::PHRASE,
- QStringList(phrase)));
- }
-
- lst = allQuery->text().split(exp, QString::SkipEmptyParts);
- if (!lst.isEmpty()) {
- QStringList all;
- foreach (const QString &term, lst)
- all.append(term);
- queryList.append(QHelpSearchQuery(QHelpSearchQuery::ALL, all));
- }
-
- lst = atLeastQuery->text().split(exp, QString::SkipEmptyParts);
- if (!lst.isEmpty()) {
- QStringList atLeast;
- foreach (const QString &term, lst)
- atLeast += buildTermList(term);
- queryList.append(QHelpSearchQuery(QHelpSearchQuery::ATLEAST,
- atLeast));
- }
- }
-#endif
- QueryHistory &queryHist = simpleSearch ? simpleQueries : complexQueries;
- saveQuery(queryList, queryHist);
- queryHist.curQuery = queryHist.queries.size() - 1;
- if (queryHist.curQuery > 0)
- prevQueryButton->setEnabled(true);
- nextQueryButton->setEnabled(false);
+ saveQuery(m_lineEdit->text());
+ m_queries.curQuery = m_queries.queries.size() - 1;
+ if (m_queries.curQuery > 0)
+ m_prevQueryButton->setEnabled(true);
+ m_nextQueryButton->setEnabled(false);
}
void nextQuery()
{
- nextOrPrevQuery((simpleSearch ? simpleQueries
- : complexQueries).queries.size() - 1, 1, nextQueryButton,
- prevQueryButton);
+ nextOrPrevQuery(m_queries.queries.size() - 1, 1, m_nextQueryButton,
+ m_prevQueryButton);
}
void prevQuery()
{
- nextOrPrevQuery(0, -1, prevQueryButton, nextQueryButton);
+ nextOrPrevQuery(0, -1, m_prevQueryButton, m_nextQueryButton);
}
private:
friend class QHelpSearchQueryWidget;
- bool simpleSearch;
- QLabel *simpleSearchLabel;
- QLabel *advancedSearchLabel;
- QLabel *similarLabel;
- QLabel *withoutLabel;
- QLabel *exactLabel;
- QLabel *allLabel;
- QLabel *atLeastLabel;
- QPushButton *searchButton;
- QWidget* advancedSearchWidget;
- QToolButton *showHideAdvancedSearchButton;
- QLineEdit *defaultQuery;
- QLineEdit *exactQuery;
- QLineEdit *similarQuery;
- QLineEdit *withoutQuery;
- QLineEdit *allQuery;
- QLineEdit *atLeastQuery;
- QToolButton *nextQueryButton;
- QToolButton *prevQueryButton;
- QueryHistory simpleQueries;
- QueryHistory complexQueries;
- QCompleter searchCompleter;
+ QLabel *m_searchLabel = nullptr;
+ QPushButton *m_searchButton = nullptr;
+ QLineEdit *m_lineEdit = nullptr;
+ QToolButton *m_nextQueryButton = nullptr;
+ QToolButton *m_prevQueryButton = nullptr;
+ QueryHistory m_queries;
+ QCompleter m_searchCompleter;
+ bool m_compactMode = false;
};
-#include "qhelpsearchquerywidget.moc"
-
-
/*!
\class QHelpSearchQueryWidget
\since 4.4
@@ -392,9 +182,8 @@
\fn void QHelpSearchQueryWidget::search()
This signal is emitted when a the user has the search button invoked.
- After reciving the signal you can ask the QHelpSearchQueryWidget for the
- build list of QHelpSearchQuery's that you may pass to the QHelpSearchEngine's
- search() function.
+ After receiving the signal you can ask the QHelpSearchQueryWidget for the
+ search input that you may pass to the QHelpSearchEngine::search() function.
*/
/*!
@@ -406,100 +195,42 @@
d = new QHelpSearchQueryWidgetPrivate();
QVBoxLayout *vLayout = new QVBoxLayout(this);
- vLayout->setMargin(0);
+ vLayout->setContentsMargins(QMargins());
QHBoxLayout* hBoxLayout = new QHBoxLayout();
- d->simpleSearchLabel = new QLabel(this);
- d->defaultQuery = new QLineEdit(this);
- d->defaultQuery->setCompleter(&d->searchCompleter);
- d->prevQueryButton = new QToolButton(this);
- d->prevQueryButton->setArrowType(Qt::LeftArrow);
- d->prevQueryButton->setEnabled(false);
- d->nextQueryButton = new QToolButton(this);
- d->nextQueryButton->setArrowType(Qt::RightArrow);
- d->nextQueryButton->setEnabled(false);
- d->searchButton = new QPushButton(this);
- hBoxLayout->addWidget(d->simpleSearchLabel);
- hBoxLayout->addWidget(d->defaultQuery);
- hBoxLayout->addWidget(d->prevQueryButton);
- hBoxLayout->addWidget(d->nextQueryButton);
- hBoxLayout->addWidget(d->searchButton);
-
- vLayout->addLayout(hBoxLayout);
-
- connect(d->prevQueryButton, SIGNAL(clicked()), d, SLOT(prevQuery()));
- connect(d->nextQueryButton, SIGNAL(clicked()), d, SLOT(nextQuery()));
- connect(d->searchButton, SIGNAL(clicked()), this, SIGNAL(search()));
- connect(d->defaultQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
-
-#if defined(QT_CLUCENE_SUPPORT)
- hBoxLayout = new QHBoxLayout();
- d->showHideAdvancedSearchButton = new QToolButton(this);
- d->showHideAdvancedSearchButton->setText(QLatin1String("+"));
- d->showHideAdvancedSearchButton->setMinimumSize(25, 20);
-
- d->advancedSearchLabel = new QLabel(this);
- QSizePolicy sizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
- sizePolicy.setHeightForWidth(d->advancedSearchLabel->sizePolicy().hasHeightForWidth());
- d->advancedSearchLabel->setSizePolicy(sizePolicy);
-
- QFrame* hLine = new QFrame(this);
- hLine->setFrameStyle(QFrame::HLine);
- hBoxLayout->addWidget(d->showHideAdvancedSearchButton);
- hBoxLayout->addWidget(d->advancedSearchLabel);
- hBoxLayout->addWidget(hLine);
+ d->m_searchLabel = new QLabel(this);
+ d->m_lineEdit = new QLineEdit(this);
+ d->m_lineEdit->setClearButtonEnabled(true);
+ d->m_lineEdit->setCompleter(&d->m_searchCompleter);
+ d->m_lineEdit->installEventFilter(d);
+ d->m_prevQueryButton = new QToolButton(this);
+ d->m_prevQueryButton->setArrowType(Qt::LeftArrow);
+ d->m_prevQueryButton->setEnabled(false);
+ d->m_nextQueryButton = new QToolButton(this);
+ d->m_nextQueryButton->setArrowType(Qt::RightArrow);
+ d->m_nextQueryButton->setEnabled(false);
+ d->m_searchButton = new QPushButton(this);
+ hBoxLayout->addWidget(d->m_searchLabel);
+ hBoxLayout->addWidget(d->m_lineEdit);
+ hBoxLayout->addWidget(d->m_prevQueryButton);
+ hBoxLayout->addWidget(d->m_nextQueryButton);
+ hBoxLayout->addWidget(d->m_searchButton);
vLayout->addLayout(hBoxLayout);
- // setup advanced search layout
- d->advancedSearchWidget = new QWidget(this);
- QGridLayout *gLayout = new QGridLayout(d->advancedSearchWidget);
- gLayout->setMargin(0);
-
- d->similarLabel = new QLabel(this);
- gLayout->addWidget(d->similarLabel, 0, 0);
- d->similarQuery = new QLineEdit(this);
- d->similarQuery->setCompleter(&d->searchCompleter);
- gLayout->addWidget(d->similarQuery, 0, 1);
-
- d->withoutLabel = new QLabel(this);
- gLayout->addWidget(d->withoutLabel, 1, 0);
- d->withoutQuery = new QLineEdit(this);
- d->withoutQuery->setCompleter(&d->searchCompleter);
- gLayout->addWidget(d->withoutQuery, 1, 1);
-
- d->exactLabel = new QLabel(this);
- gLayout->addWidget(d->exactLabel, 2, 0);
- d->exactQuery = new QLineEdit(this);
- d->exactQuery->setCompleter(&d->searchCompleter);
- gLayout->addWidget(d->exactQuery, 2, 1);
-
- d->allLabel = new QLabel(this);
- gLayout->addWidget(d->allLabel, 3, 0);
- d->allQuery = new QLineEdit(this);
- d->allQuery->setCompleter(&d->searchCompleter);
- gLayout->addWidget(d->allQuery, 3, 1);
-
- d->atLeastLabel = new QLabel(this);
- gLayout->addWidget(d->atLeastLabel, 4, 0);
- d->atLeastQuery = new QLineEdit(this);
- d->atLeastQuery->setCompleter(&d->searchCompleter);
- gLayout->addWidget(d->atLeastQuery, 4, 1);
-
- vLayout->addWidget(d->advancedSearchWidget);
- d->advancedSearchWidget->hide();
+ connect(d->m_prevQueryButton, &QAbstractButton::clicked,
+ d, &QHelpSearchQueryWidgetPrivate::prevQuery);
+ connect(d->m_nextQueryButton, &QAbstractButton::clicked,
+ d, &QHelpSearchQueryWidgetPrivate::nextQuery);
+ connect(d->m_searchButton, &QAbstractButton::clicked,
+ this, &QHelpSearchQueryWidget::search);
+ connect(d->m_lineEdit, &QLineEdit::returnPressed,
+ this, &QHelpSearchQueryWidget::search);
d->retranslate();
-
- connect(d->exactQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
- connect(d->similarQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
- connect(d->withoutQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
- connect(d->allQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
- connect(d->atLeastQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
- connect(d->showHideAdvancedSearchButton, SIGNAL(clicked()),
- d, SLOT(showHideAdvancedSearch()));
-#endif
- connect(this, SIGNAL(search()), d, SLOT(searchRequested()));
+ connect(this, &QHelpSearchQueryWidget::search,
+ d, &QHelpSearchQueryWidgetPrivate::searchRequested);
+ setCompactMode(true);
}
/*!
@@ -511,62 +242,92 @@
}
/*!
- \since 4.8
-
Expands the search query widget so that the extended search fields are shown.
*/
void QHelpSearchQueryWidget::expandExtendedSearch()
{
- if (d->simpleSearch)
- d->showHideAdvancedSearch();
+ // TODO: no extended search anymore, deprecate it?
}
/*!
- \since 4.8
-
Collapses the search query widget so that only the default search field is
shown.
*/
void QHelpSearchQueryWidget::collapseExtendedSearch()
{
- if (!d->simpleSearch)
- d->showHideAdvancedSearch();
+ // TODO: no extended search anymore, deprecate it?
}
+#if QT_DEPRECATED_SINCE(5, 9)
/*!
- Returns a list of queries to use in combination with the search engines
- search(QList &queryList) function.
+ \deprecated
+
+ Use searchInput() instead.
*/
QList QHelpSearchQueryWidget::query() const
{
- const QHelpSearchQueryWidgetPrivate::QueryHistory &queryHist =
- d->simpleSearch ? d->simpleQueries : d->complexQueries;
- return queryHist.queries.isEmpty() ?
- QList() : queryHist.queries.last();
+ return QList() << QHelpSearchQuery(QHelpSearchQuery::DEFAULT,
+ searchInput().split(QChar::Space, Qt::SkipEmptyParts));
}
/*!
- \since 4.8
+ \deprecated
- Sets the QHelpSearchQueryWidget input fields to the values specified by
- \a queryList search field name. Please note that one has to call the search
- engine's search(QList &queryList) function to perform the
- actual search.
+ Use setSearchInput() instead.
*/
void QHelpSearchQueryWidget::setQuery(const QList &queryList)
{
- QList lineEdits;
- lineEdits << d->defaultQuery << d->allQuery << d->atLeastQuery
- << d->similarQuery << d->withoutQuery << d->exactQuery;
- foreach (QLineEdit *lineEdit, lineEdits)
- lineEdit->clear();
+ if (queryList.isEmpty())
+ return;
+
+ setSearchInput(queryList.first().wordList.join(QChar::Space));
+}
+#endif // QT_DEPRECATED_SINCE(5, 9)
+
+/*!
+ \since 5.9
+
+ Returns a search phrase to use in combination with the
+ QHelpSearchEngine::search(const QString &searchInput) function.
+*/
+QString QHelpSearchQueryWidget::searchInput() const
+{
+ if (d->m_queries.queries.isEmpty())
+ return QString();
+ return d->m_queries.queries.last();
+}
+
+/*!
+ \since 5.9
+
+ Sets the QHelpSearchQueryWidget input field to the value specified by
+ \a searchInput.
- const QLatin1String space(" ");
- foreach (const QHelpSearchQuery &q, queryList) {
- if (QLineEdit *lineEdit = d->lineEditFor(q.fieldName))
- lineEdit->setText(lineEdit->text() + q.wordList.join(space) + space);
+ \note The QHelpSearchEngine::search(const QString &searchInput) function has
+ to be called to perform the actual search.
+*/
+void QHelpSearchQueryWidget::setSearchInput(const QString &searchInput)
+{
+ d->m_lineEdit->clear();
+
+ d->m_lineEdit->setText(searchInput);
+
+ d->searchRequested();
+}
+
+bool QHelpSearchQueryWidget::isCompactMode() const
+{
+ return d->m_compactMode;
+}
+
+void QHelpSearchQueryWidget::setCompactMode(bool on)
+{
+ if (d->m_compactMode != on) {
+ d->m_compactMode = on;
+ d->m_prevQueryButton->setVisible(!on);
+ d->m_nextQueryButton->setVisible(!on);
+ d->m_searchLabel->setVisible(!on);
}
- d->searchRequested();
}
/*!
@@ -575,12 +336,13 @@
void QHelpSearchQueryWidget::focusInEvent(QFocusEvent *focusEvent)
{
if (focusEvent->reason() != Qt::MouseFocusReason) {
- d->defaultQuery->selectAll();
- d->defaultQuery->setFocus();
+ d->m_lineEdit->selectAll();
+ d->m_lineEdit->setFocus();
}
}
-/*! \reimp
+/*!
+ \reimp
*/
void QHelpSearchQueryWidget::changeEvent(QEvent *event)
{
@@ -591,3 +353,5 @@
}
QT_END_NAMESPACE
+
+#include "qhelpsearchquerywidget.moc"
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qt/qinputdialog.cpp
--- a/libgui/languages/build_ts/octave-qt/qinputdialog.cpp Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qt/qinputdialog.cpp Mon Dec 04 19:55:32 2023 +0100
@@ -1,55 +1,16 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qinputdialog.h"
-#ifndef QT_NO_INPUTDIALOG
-
#include "qapplication.h"
#include "qcombobox.h"
#include "qdialogbuttonbox.h"
#include "qlabel.h"
#include "qlayout.h"
#include "qlineedit.h"
-#include "qlistwidget.h"
+#include "qplaintextedit.h"
+#include "qlistview.h"
#include "qpushbutton.h"
#include "qspinbox.h"
#include "qstackedlayout.h"
@@ -59,25 +20,37 @@
QT_USE_NAMESPACE
+enum CandidateSignal {
+ TextValueSelectedSignal,
+ IntValueSelectedSignal,
+ DoubleValueSelectedSignal,
+
+ NumCandidateSignals
+};
+
+static const char *candidateSignal(int which)
+{
+ switch (CandidateSignal(which)) {
+ case TextValueSelectedSignal: return SIGNAL(textValueSelected(QString));
+ case IntValueSelectedSignal: return SIGNAL(intValueSelected(int));
+ case DoubleValueSelectedSignal: return SIGNAL(doubleValueSelected(double));
+
+ case NumCandidateSignals:
+ break;
+ };
+ Q_UNREACHABLE_RETURN(nullptr);
+}
+
static const char *signalForMember(const char *member)
{
- static const int NumCandidates = 4;
- static const char * const candidateSignals[NumCandidates] = {
- SIGNAL(textValueSelected(QString)),
- SIGNAL(intValueSelected(int)),
- SIGNAL(doubleValueSelected(double)),
- SIGNAL(accepted())
- };
-
QByteArray normalizedMember(QMetaObject::normalizedSignature(member));
- int i = 0;
- while (i < NumCandidates - 1) { // sic
- if (QMetaObject::checkConnectArgs(candidateSignals[i], normalizedMember))
- break;
- ++i;
- }
- return candidateSignals[i];
+ for (int i = 0; i < NumCandidateSignals; ++i)
+ if (QMetaObject::checkConnectArgs(candidateSignal(i), normalizedMember))
+ return candidateSignal(i);
+
+ // otherwise, use fit-all accepted signal:
+ return SIGNAL(accepted());
}
QT_BEGIN_NAMESPACE
@@ -106,18 +79,16 @@
void notifyTextChanged() { emit textChanged(hasAcceptableInput()); }
private:
- void keyPressEvent(QKeyEvent *event) {
+ void keyPressEvent(QKeyEvent *event) override {
if ((event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) && !hasAcceptableInput()) {
-#ifndef QT_NO_PROPERTIES
setProperty("value", property("value"));
-#endif
} else {
QSpinBox::keyPressEvent(event);
}
notifyTextChanged();
}
- void mousePressEvent(QMouseEvent *event) {
+ void mousePressEvent(QMouseEvent *event) override {
QSpinBox::mousePressEvent(event);
notifyTextChanged();
}
@@ -128,7 +99,7 @@
Q_OBJECT
public:
- QInputDialogDoubleSpinBox(QWidget *parent = 0)
+ QInputDialogDoubleSpinBox(QWidget *parent = nullptr)
: QDoubleSpinBox(parent) {
connect(lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(notifyTextChanged()));
connect(this, SIGNAL(editingFinished()), this, SLOT(notifyTextChanged()));
@@ -141,26 +112,32 @@
void notifyTextChanged() { emit textChanged(hasAcceptableInput()); }
private:
- void keyPressEvent(QKeyEvent *event) {
+ void keyPressEvent(QKeyEvent *event) override {
if ((event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) && !hasAcceptableInput()) {
-#ifndef QT_NO_PROPERTIES
setProperty("value", property("value"));
-#endif
} else {
QDoubleSpinBox::keyPressEvent(event);
}
notifyTextChanged();
}
- void mousePressEvent(QMouseEvent *event) {
+ void mousePressEvent(QMouseEvent *event) override {
QDoubleSpinBox::mousePressEvent(event);
notifyTextChanged();
}
};
-QT_BEGIN_INCLUDE_NAMESPACE
-#include "qinputdialog.moc"
-QT_END_INCLUDE_NAMESPACE
+class QInputDialogListView : public QListView
+{
+public:
+ QInputDialogListView(QWidget *parent = nullptr) : QListView(parent) {}
+ QVariant inputMethodQuery(Qt::InputMethodQuery query) const override
+ {
+ if (query == Qt::ImEnabled)
+ return false;
+ return QListView::inputMethodQuery(query);
+ }
+};
class QInputDialogPrivate : public QDialogPrivate
{
@@ -171,6 +148,7 @@
void ensureLayout();
void ensureLineEdit();
+ void ensurePlainTextEdit();
void ensureComboBox();
void ensureListView();
void ensureIntSpinBox();
@@ -184,15 +162,17 @@
void ensureLayout() const { const_cast(this)->ensureLayout(); }
bool useComboBoxOrListView() const { return comboBox && comboBox->count() > 0; }
void _q_textChanged(const QString &text);
+ void _q_plainTextEditTextChanged();
void _q_currentRowChanged(const QModelIndex &newIndex, const QModelIndex &oldIndex);
mutable QLabel *label;
mutable QDialogButtonBox *buttonBox;
mutable QLineEdit *lineEdit;
+ mutable QPlainTextEdit *plainTextEdit;
mutable QSpinBox *intSpinBox;
mutable QDoubleSpinBox *doubleSpinBox;
mutable QComboBox *comboBox;
- mutable QListView *listView;
+ mutable QInputDialogListView *listView;
mutable QWidget *inputWidget;
mutable QVBoxLayout *mainLayout;
QInputDialog::InputDialogOptions opts;
@@ -202,8 +182,8 @@
};
QInputDialogPrivate::QInputDialogPrivate()
- : label(0), buttonBox(0), lineEdit(0), intSpinBox(0), doubleSpinBox(0), comboBox(0), listView(0),
- inputWidget(0), mainLayout(0)
+ : label(nullptr), buttonBox(nullptr), lineEdit(nullptr), plainTextEdit(nullptr), intSpinBox(nullptr), doubleSpinBox(nullptr),
+ comboBox(nullptr), listView(nullptr), inputWidget(nullptr), mainLayout(nullptr)
{
}
@@ -231,12 +211,7 @@
QObject::connect(buttonBox, SIGNAL(rejected()), q, SLOT(reject()));
mainLayout = new QVBoxLayout(q);
- //we want to let the input dialog grow to available size on Symbian.
-#ifndef Q_OS_SYMBIAN
mainLayout->setSizeConstraint(QLayout::SetMinAndMaxSize);
-#else
- label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
-#endif
mainLayout->addWidget(label);
mainLayout->addWidget(inputWidget);
mainLayout->addWidget(buttonBox);
@@ -258,6 +233,21 @@
}
}
+void QInputDialogPrivate::ensurePlainTextEdit()
+{
+ Q_Q(QInputDialog);
+ if (!plainTextEdit) {
+ plainTextEdit = new QPlainTextEdit(q);
+ plainTextEdit->setLineWrapMode(QPlainTextEdit::NoWrap);
+#ifndef QT_NO_IM
+ qt_widget_private(plainTextEdit)->inheritsInputMethodHints = 1;
+#endif
+ plainTextEdit->hide();
+ QObject::connect(plainTextEdit, SIGNAL(textChanged()),
+ q, SLOT(_q_plainTextEditTextChanged()));
+ }
+}
+
void QInputDialogPrivate::ensureComboBox()
{
Q_Q(QInputDialog);
@@ -269,7 +259,7 @@
comboBox->hide();
QObject::connect(comboBox, SIGNAL(editTextChanged(QString)),
q, SLOT(_q_textChanged(QString)));
- QObject::connect(comboBox, SIGNAL(currentIndexChanged(QString)),
+ QObject::connect(comboBox, SIGNAL(currentTextChanged(QString)),
q, SLOT(_q_textChanged(QString)));
}
}
@@ -279,8 +269,7 @@
Q_Q(QInputDialog);
if (!listView) {
ensureComboBox();
-
- listView = new QListView(q);
+ listView = new QInputDialogListView(q);
listView->hide();
listView->setEditTriggers(QAbstractItemView::NoEditTriggers);
listView->setSelectionMode(QAbstractItemView::SingleSelection);
@@ -352,6 +341,8 @@
// textValue
if (widget == lineEdit) {
lineEdit->setText(textValue);
+ } else if (widget == plainTextEdit) {
+ plainTextEdit->setPlainText(textValue);
} else if (widget == comboBox) {
setComboBoxText(textValue);
} else if (widget == listView) {
@@ -372,6 +363,9 @@
} else {
widget = comboBox;
}
+ } else if (opts & QInputDialog::UsePlainTextEditForTextInput) {
+ ensurePlainTextEdit();
+ widget = plainTextEdit;
} else {
ensureLineEdit();
widget = lineEdit;
@@ -425,6 +419,16 @@
}
}
+void QInputDialogPrivate::_q_plainTextEditTextChanged()
+{
+ Q_Q(QInputDialog);
+ QString text = plainTextEdit->toPlainText();
+ if (textValue != text) {
+ textValue = text;
+ emit q->textValueChanged(text);
+ }
+}
+
void QInputDialogPrivate::_q_currentRowChanged(const QModelIndex &newIndex,
const QModelIndex & /* oldIndex */)
{
@@ -437,21 +441,21 @@
\brief The QInputDialog class provides a simple convenience dialog to get a
single value from the user.
\ingroup standard-dialogs
-
+ \inmodule QtWidgets
The input value can be a string, a number or an item from a list. A label
must be set to tell the user what they should enter.
- Four static convenience functions are provided: getText(), getInt(),
- getDouble(), and getItem(). All the functions can be used in a similar way,
+ Five static convenience functions are provided: getText(), getMultiLineText(),
+ getInt(), getDouble(), and getItem(). All the functions can be used in a similar way,
for example:
- \snippet examples/dialogs/standarddialogs/dialog.cpp 3
+ \snippet dialogs/standarddialogs/dialog.cpp 3
- The \c ok variable is set to true if the user clicks \gui OK; otherwise it
+ The \c ok variable is set to true if the user clicks \uicontrol OK; otherwise, it
is set to false.
- \img inputdialogs.png Input Dialogs
+ \image inputdialogs.png Input Dialogs
The \l{dialogs/standarddialogs}{Standard Dialogs} example shows how to use
QInputDialog as well as other built-in Qt dialogs.
@@ -500,7 +504,7 @@
\brief the mode used for input
- This property help determines which widget is used for entering input into
+ This property helps determine which widget is used for entering input into
the dialog.
*/
void QInputDialog::setInputMode(InputMode mode)
@@ -553,7 +557,7 @@
\property QInputDialog::labelText
- \brief the text to for the label to describe what needs to be input
+ \brief the label's text which describes what needs to be input
*/
void QInputDialog::setLabelText(const QString &text)
{
@@ -563,9 +567,6 @@
} else {
d->label->setText(text);
}
-#ifdef Q_OS_SYMBIAN
- d->label->setWordWrap(true);
-#endif
}
QString QInputDialog::labelText() const
@@ -583,9 +584,11 @@
This enum specifies various options that affect the look and feel
of an input dialog.
- \value NoButtons Don't display \gui{OK} and \gui{Cancel} buttons. (Useful for "live dialogs".)
+ \value NoButtons Don't display \uicontrol{OK} and \uicontrol{Cancel} buttons (useful for "live dialogs").
\value UseListViewForComboBoxItems Use a QListView rather than a non-editable QComboBox for
displaying the items set with setComboBoxItems().
+ \value UsePlainTextEditForTextInput Use a QPlainTextEdit for multiline text input. This value was
+ introduced in 5.2.
\sa options, setOption(), testOption()
*/
@@ -604,7 +607,7 @@
}
/*!
- Returns true if the given \a option is enabled; otherwise, returns
+ Returns \c true if the given \a option is enabled; otherwise, returns
false.
\sa options, setOption()
@@ -639,6 +642,8 @@
d->buttonBox->setVisible(!(options & NoButtons));
if ((changed & UseListViewForComboBoxItems) && inputMode() == TextInput)
d->chooseRightTextInputWidget();
+ if ((changed & UsePlainTextEditForTextInput) && inputMode() == TextInput)
+ d->chooseRightTextInputWidget();
}
QInputDialog::InputDialogOptions QInputDialog::options() const
@@ -664,6 +669,8 @@
setInputMode(TextInput);
if (d->inputWidget == d->lineEdit) {
d->lineEdit->setText(text);
+ } else if (d->inputWidget == d->plainTextEdit) {
+ d->plainTextEdit->setPlainText(text);
} else if (d->inputWidget == d->comboBox) {
d->setComboBoxText(text);
} else {
@@ -709,7 +716,7 @@
\property QInputDialog::comboBoxEditable
- \brief whether or not the combo box is used in the input dialog is editable
+ \brief whether or not the combo box used in the input dialog is editable
*/
void QInputDialog::setComboBoxEditable(bool editable)
{
@@ -735,17 +742,18 @@
\property QInputDialog::comboBoxItems
- \brief the items used in the combobox for the input dialog
+ \brief the items used in the combo box for the input dialog
*/
void QInputDialog::setComboBoxItems(const QStringList &items)
{
Q_D(QInputDialog);
d->ensureComboBox();
- d->comboBox->blockSignals(true);
- d->comboBox->clear();
- d->comboBox->addItems(items);
- d->comboBox->blockSignals(false);
+ {
+ const QSignalBlocker blocker(d->comboBox);
+ d->comboBox->clear();
+ d->comboBox->addItems(items);
+ }
if (inputMode() == TextInput)
d->chooseRightTextInputWidget();
@@ -757,6 +765,7 @@
QStringList result;
if (d->comboBox) {
const int count = d->comboBox->count();
+ result.reserve(count);
for (int i = 0; i < count; ++i)
result.append(d->comboBox->itemText(i));
}
@@ -967,7 +976,7 @@
\property QInputDialog::doubleDecimals
- \brief sets the percision of the double spinbox in decimals
+ \brief sets the precision of the double spinbox in decimals
\sa QDoubleSpinBox::setDecimals()
*/
@@ -1031,17 +1040,16 @@
/*!
\since 4.5
- \overload
This function connects one of its signals to the slot specified by \a receiver
and \a member. The specific signal depends on the arguments that are specified
in \a member. These are:
\list
- \o textValueSelected() if \a member has a QString for its first argument.
- \o intValueSelected() if \a member has an int for its first argument.
- \o doubleValueSelected() if \a member has a double for its first argument.
- \o accepted() if \a member has NO arguments.
+ \li textValueSelected() if \a member has a QString for its first argument.
+ \li intValueSelected() if \a member has an int for its first argument.
+ \li doubleValueSelected() if \a member has a double for its first argument.
+ \li accepted() if \a member has NO arguments.
\endlist
The signal will be disconnected from the slot when the dialog is closed.
@@ -1086,6 +1094,8 @@
d->inputWidget->setFocus();
if (d->inputWidget == d->lineEdit) {
d->lineEdit->selectAll();
+ } else if (d->inputWidget == d->plainTextEdit) {
+ d->plainTextEdit->selectAll();
} else if (d->inputWidget == d->intSpinBox) {
d->intSpinBox->selectAll();
} else if (d->inputWidget == d->doubleSpinBox) {
@@ -1123,7 +1133,7 @@
if (d->receiverToDisconnectOnClose) {
disconnect(this, signalForMember(d->memberToDisconnectOnClose),
d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);
- d->receiverToDisconnectOnClose = 0;
+ d->receiverToDisconnectOnClose = nullptr;
}
d->memberToDisconnectOnClose.clear();
}
@@ -1139,8 +1149,8 @@
\a inputMethodHints is the input method hints that will be used in the
edit widget if an input method is active.
- If \a ok is nonnull \e *\a ok will be set to true if the user pressed
- \gui OK and to false if the user pressed \gui Cancel. The dialog's parent
+ If \a ok is nonnull \e {*ok} will be set to true if the user pressed
+ \uicontrol OK and to false if the user pressed \uicontrol Cancel. The dialog's parent
is \a parent. The dialog will be modal and uses the specified widget
\a flags.
@@ -1149,45 +1159,78 @@
Use this static function like this:
- \snippet examples/dialogs/standarddialogs/dialog.cpp 3
+ \snippet dialogs/standarddialogs/dialog.cpp 3
- \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
- QInputDialog constructors.
-
- \sa getInt(), getDouble(), getItem()
+ \sa getInt(), getDouble(), getItem(), getMultiLineText()
*/
QString QInputDialog::getText(QWidget *parent, const QString &title, const QString &label,
QLineEdit::EchoMode mode, const QString &text, bool *ok,
Qt::WindowFlags flags, Qt::InputMethodHints inputMethodHints)
{
- QInputDialog dialog(parent, flags);
- dialog.setWindowTitle(title);
- dialog.setLabelText(label);
- dialog.setTextValue(text);
- dialog.setTextEchoMode(mode);
- dialog.setInputMethodHints(inputMethodHints);
+ QAutoPointer dialog(new QInputDialog(parent, flags));
+ dialog->setWindowTitle(title);
+ dialog->setLabelText(label);
+ dialog->setTextValue(text);
+ dialog->setTextEchoMode(mode);
+ dialog->setInputMethodHints(inputMethodHints);
- int ret = dialog.exec();
+ const int ret = dialog->exec();
if (ok)
*ok = !!ret;
if (ret) {
- return dialog.textValue();
+ return dialog->textValue();
} else {
return QString();
}
}
/*!
- \internal
+ \since 5.2
+
+ Static convenience function to get a multiline string from the user.
+
+ \a title is the text which is displayed in the title bar of the dialog.
+ \a label is the text which is shown to the user (it should say what should
+ be entered).
+ \a text is the default text which is placed in the plain text edit.
+ \a inputMethodHints is the input method hints that will be used in the
+ edit widget if an input method is active.
+
+ If \a ok is nonnull \e {*ok} will be set to true if the user pressed
+ \uicontrol OK and to false if the user pressed \uicontrol Cancel. The dialog's parent
+ is \a parent. The dialog will be modal and uses the specified widget
+ \a flags.
+
+ If the dialog is accepted, this function returns the text in the dialog's
+ plain text edit. If the dialog is rejected, a null QString is returned.
+
+ Use this static function like this:
+
+ \snippet dialogs/standarddialogs/dialog.cpp 4
+
+ \sa getInt(), getDouble(), getItem(), getText()
*/
-// ### Qt 5: Use only the version above.
-QString QInputDialog::getText(QWidget *parent, const QString &title, const QString &label,
- QLineEdit::EchoMode mode, const QString &text, bool *ok,
- Qt::WindowFlags flags)
+
+QString QInputDialog::getMultiLineText(QWidget *parent, const QString &title, const QString &label,
+ const QString &text, bool *ok, Qt::WindowFlags flags,
+ Qt::InputMethodHints inputMethodHints)
{
- return getText(parent, title, label, mode, text, ok, flags, Qt::ImhNone);
+ QAutoPointer dialog(new QInputDialog(parent, flags));
+ dialog->setOptions(QInputDialog::UsePlainTextEditForTextInput);
+ dialog->setWindowTitle(title);
+ dialog->setLabelText(label);
+ dialog->setTextValue(text);
+ dialog->setInputMethodHints(inputMethodHints);
+
+ const int ret = dialog->exec();
+ if (ok)
+ *ok = !!ret;
+ if (ret) {
+ return dialog->textValue();
+ } else {
+ return QString();
+ }
}
/*!
@@ -1203,8 +1246,8 @@
\a step is the amount by which the values change as the user presses the
arrow buttons to increment or decrement the value.
- If \a ok is nonnull *\a ok will be set to true if the user pressed \gui OK
- and to false if the user pressed \gui Cancel. The dialog's parent is
+ If \a ok is nonnull *\a ok will be set to true if the user pressed \uicontrol OK
+ and to false if the user pressed \uicontrol Cancel. The dialog's parent is
\a parent. The dialog will be modal and uses the widget \a flags.
On success, this function returns the integer which has been entered by the
@@ -1212,30 +1255,26 @@
Use this static function like this:
- \snippet examples/dialogs/standarddialogs/dialog.cpp 0
+ \snippet dialogs/standarddialogs/dialog.cpp 0
- \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
- QInputDialog constructors.
-
- \sa getText(), getDouble(), getItem()
+ \sa getText(), getDouble(), getItem(), getMultiLineText()
*/
int QInputDialog::getInt(QWidget *parent, const QString &title, const QString &label, int value,
int min, int max, int step, bool *ok, Qt::WindowFlags flags)
{
- QInputDialog dialog(parent, flags);
- dialog.setWindowTitle(title);
- dialog.setLabelText(label);
- dialog.setIntRange(min, max);
- dialog.setIntValue(value);
- dialog.setIntStep(step);
+ QAutoPointer dialog(new QInputDialog(parent, flags));
+ dialog->setWindowTitle(title);
+ dialog->setLabelText(label);
+ dialog->setIntRange(min, max);
+ dialog->setIntValue(value);
+ dialog->setIntStep(step);
- int ret = dialog.exec();
+ const int ret = dialog->exec();
if (ok)
*ok = !!ret;
if (ret) {
- return dialog.intValue();
+ return dialog->intValue();
} else {
return value;
}
@@ -1251,9 +1290,11 @@
set to.
\a min and \a max are the minimum and maximum values the user may choose.
\a decimals is the maximum number of decimal places the number may have.
+ \a step is the amount by which the values change as the user presses the
+ arrow buttons to increment or decrement the value.
- If \a ok is nonnull, *\a ok will be set to true if the user pressed \gui OK
- and to false if the user pressed \gui Cancel. The dialog's parent is
+ If \a ok is nonnull, *\a ok will be set to true if the user pressed \uicontrol OK
+ and to false if the user pressed \uicontrol Cancel. The dialog's parent is
\a parent. The dialog will be modal and uses the widget \a flags.
This function returns the floating point number which has been entered by
@@ -1261,31 +1302,28 @@
Use this static function like this:
- \snippet examples/dialogs/standarddialogs/dialog.cpp 1
+ \snippet dialogs/standarddialogs/dialog.cpp 1
- \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
- QInputDialog constructors.
-
- \sa getText(), getInt(), getItem()
+ \sa getText(), getInt(), getItem(), getMultiLineText()
*/
double QInputDialog::getDouble(QWidget *parent, const QString &title, const QString &label,
double value, double min, double max, int decimals, bool *ok,
- Qt::WindowFlags flags)
+ Qt::WindowFlags flags, double step)
{
- QInputDialog dialog(parent, flags);
- dialog.setWindowTitle(title);
- dialog.setLabelText(label);
- dialog.setDoubleDecimals(decimals);
- dialog.setDoubleRange(min, max);
- dialog.setDoubleValue(value);
+ QAutoPointer dialog(new QInputDialog(parent, flags));
+ dialog->setWindowTitle(title);
+ dialog->setLabelText(label);
+ dialog->setDoubleDecimals(decimals);
+ dialog->setDoubleRange(min, max);
+ dialog->setDoubleValue(value);
+ dialog->setDoubleStep(step);
- int ret = dialog.exec();
+ const int ret = dialog->exec();
if (ok)
*ok = !!ret;
if (ret) {
- return dialog.doubleValue();
+ return dialog->doubleValue();
} else {
return value;
}
@@ -1298,30 +1336,26 @@
\a title is the text which is displayed in the title bar of the dialog.
\a label is the text which is shown to the user (it should say what should
be entered).
- \a items is the string list which is inserted into the combobox.
+ \a items is the string list which is inserted into the combo box.
\a current is the number of the item which should be the current item.
\a inputMethodHints is the input method hints that will be used if the
- combobox is editable and an input method is active.
+ combo box is editable and an input method is active.
- If \a editable is true the user can enter their own text; otherwise the
+ If \a editable is true the user can enter their own text; otherwise, the
user may only select one of the existing items.
- If \a ok is nonnull \e *\a ok will be set to true if the user pressed
- \gui OK and to false if the user pressed \gui Cancel. The dialog's parent
+ If \a ok is nonnull \e {*ok} will be set to true if the user pressed
+ \uicontrol OK and to false if the user pressed \uicontrol Cancel. The dialog's parent
is \a parent. The dialog will be modal and uses the widget \a flags.
This function returns the text of the current item, or if \a editable is
- true, the current text of the combobox.
+ true, the current text of the combo box.
Use this static function like this:
- \snippet examples/dialogs/standarddialogs/dialog.cpp 2
+ \snippet dialogs/standarddialogs/dialog.cpp 2
- \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
- QInputDialog constructors.
-
- \sa getText(), getInt(), getDouble()
+ \sa getText(), getInt(), getDouble(), getMultiLineText()
*/
QString QInputDialog::getItem(QWidget *parent, const QString &title, const QString &label,
@@ -1330,94 +1364,48 @@
{
QString text(items.value(current));
- QInputDialog dialog(parent, flags);
- dialog.setWindowTitle(title);
- dialog.setLabelText(label);
- dialog.setComboBoxItems(items);
- dialog.setTextValue(text);
- dialog.setComboBoxEditable(editable);
- dialog.setInputMethodHints(inputMethodHints);
+ QAutoPointer dialog(new QInputDialog(parent, flags));
+ dialog->setWindowTitle(title);
+ dialog->setLabelText(label);
+ dialog->setComboBoxItems(items);
+ dialog->setTextValue(text);
+ dialog->setComboBoxEditable(editable);
+ dialog->setInputMethodHints(inputMethodHints);
- int ret = dialog.exec();
+ const int ret = dialog->exec();
if (ok)
*ok = !!ret;
if (ret) {
- return dialog.textValue();
+ return dialog->textValue();
} else {
return text;
}
}
/*!
- \internal
-*/
-// ### Qt 5: Use only the version above.
-QString QInputDialog::getItem(QWidget *parent, const QString &title, const QString &label,
- const QStringList &items, int current, bool editable, bool *ok,
- Qt::WindowFlags flags)
-{
- return getItem(parent, title, label, items, current, editable, ok, flags, Qt::ImhNone);
-}
-
-/*!
- \obsolete
+ \property QInputDialog::doubleStep
+ \since 5.10
+ \brief the step by which the double value is increased and decreased
- Use getInt() instead.
-*/
-int QInputDialog::getInteger(QWidget *parent, const QString &title, const QString &label,
- int value, int min, int max, int step, bool *ok,
- Qt::WindowFlags flags)
-{
- return getInt(parent, title, label, value, min, max, step, ok, flags);
-}
-
-/*!
- \fn QString QInputDialog::getText(const QString &title, const QString &label,
- QLineEdit::EchoMode echo = QLineEdit::Normal,
- const QString &text = QString(), bool *ok = 0,
- QWidget *parent = 0, const char *name = 0, Qt::WindowFlags flags = 0)
-
- Call getText(\a parent, \a title, \a label, \a echo, \a text, \a
- ok, \a flags) instead.
-
- The \a name parameter is ignored.
+ This property is only relevant when the input dialog is used in
+ DoubleInput mode.
*/
-/*!
- \fn int QInputDialog::getInteger(const QString &title, const QString &label, int value = 0,
- int min = -2147483647, int max = 2147483647,
- int step = 1, bool *ok = 0,
- QWidget *parent = 0, const char *name = 0, Qt::WindowFlags flags = 0)
-
-
- Call getInteger(\a parent, \a title, \a label, \a value, \a
- min, \a max, \a step, \a ok, \a flags) instead.
-
- The \a name parameter is ignored.
-*/
+void QInputDialog::setDoubleStep(double step)
+{
+ Q_D(QInputDialog);
+ d->ensureDoubleSpinBox();
+ d->doubleSpinBox->setSingleStep(step);
+}
-/*!
- \fn double QInputDialog::getDouble(const QString &title, const QString &label, double value = 0,
- double min = -2147483647, double max = 2147483647,
- int decimals = 1, bool *ok = 0,
- QWidget *parent = 0, const char *name = 0, Qt::WindowFlags flags = 0)
-
- Call getDouble(\a parent, \a title, \a label, \a value, \a
- min, \a max, \a decimals, \a ok, \a flags).
-
- The \a name parameter is ignored.
-*/
-
-/*!
- \fn QString QInputDialog::getItem(const QString &title, const QString &label, const QStringList &list,
- int current = 0, bool editable = true, bool *ok = 0,
- QWidget *parent = 0, const char *name = 0, Qt::WindowFlags flags = 0)
-
- Call getItem(\a parent, \a title, \a label, \a list, \a current,
- \a editable, \a ok, \a flags) instead.
-
- The \a name parameter is ignored.
-*/
+double QInputDialog::doubleStep() const
+{
+ Q_D(const QInputDialog);
+ if (d->doubleSpinBox)
+ return d->doubleSpinBox->singleStep();
+ else
+ return 1.0;
+}
/*!
\fn void QInputDialog::doubleValueChanged(double value)
@@ -1433,7 +1421,7 @@
\fn void QInputDialog::doubleValueSelected(double value)
This signal is emitted whenever the user selects a double value by
- accepting the dialog; for example, by clicking the \gui{OK} button.
+ accepting the dialog; for example, by clicking the \uicontrol{OK} button.
The selected value is specified by \a value.
This signal is only relevant when the input dialog is used in
@@ -1454,7 +1442,7 @@
\fn void QInputDialog::intValueSelected(int value)
This signal is emitted whenever the user selects a integer value by
- accepting the dialog; for example, by clicking the \gui{OK} button.
+ accepting the dialog; for example, by clicking the \uicontrol{OK} button.
The selected value is specified by \a value.
This signal is only relevant when the input dialog is used in
@@ -1475,7 +1463,7 @@
\fn void QInputDialog::textValueSelected(const QString &text)
This signal is emitted whenever the user selects a text string by
- accepting the dialog; for example, by clicking the \gui{OK} button.
+ accepting the dialog; for example, by clicking the \uicontrol{OK} button.
The selected string is specified by \a text.
This signal is only relevant when the input dialog is used in
@@ -1484,6 +1472,5 @@
QT_END_NAMESPACE
+#include "qinputdialog.moc"
#include "moc_qinputdialog.cpp"
-
-#endif // QT_NO_INPUTDIALOG
diff -r 97e55a21cd20 -r dd5ece3664ed libgui/languages/build_ts/octave-qt/qmessagebox.cpp
--- a/libgui/languages/build_ts/octave-qt/qmessagebox.cpp Mon Dec 04 20:38:36 2023 -0800
+++ b/libgui/languages/build_ts/octave-qt/qmessagebox.cpp Mon Dec 04 19:55:32 2023 +0100
@@ -1,114 +1,91 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include
-
-#ifndef QT_NO_MESSAGEBOX
-
-#include
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include
+
+#include
#include "private/qlabel_p.h"
#include "private/qapplication_p.h"
#include
#include
-#include
-#include
-#include
-#include
-#include
+#include
+#include
+#include
+#include
+#include
#include
#include
#include
-#include
-#include
-#include