diff options
author | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2013-11-26 22:30:27 +0100 |
---|---|---|
committer | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2013-11-26 22:35:48 +0100 |
commit | 4a8273a6fc2e741e811cf5dabc9a3c240306cf7f (patch) | |
tree | 2148abc88f8543eecdc0b97b2dd92594836af9b2 /src | |
parent | 036c5db468164297d213764c59a4b59daa76d90a (diff) | |
parent | 1c2be58fecaff1de5f2849192eb712984ebd59bd (diff) |
Merge remote-tracking branch 'origin/stable' into dev
For the conflicts in msvc_nmake.cpp the ifdefs are extended since we
need to support windows phone in the target branch while it is not there
in the current stable branch (as of Qt 5.2).
Conflicts:
configure
qmake/generators/win32/msvc_nmake.cpp
src/3rdparty/angle/src/libEGL/Surface.cpp
src/angle/src/common/common.pri
src/corelib/global/qglobal.h
src/corelib/io/qstandardpaths.cpp
src/plugins/platforms/qnx/qqnxintegration.cpp
src/plugins/platforms/qnx/qqnxscreeneventhandler.h
src/plugins/platforms/xcb/qglxintegration.h
src/widgets/kernel/win.pri
tests/auto/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp
tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp
tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
tools/configure/configureapp.cpp
Change-Id: I00b579eefebaf61d26ab9b00046d2b5bd5958812
Diffstat (limited to 'src')
457 files changed, 8766 insertions, 7354 deletions
diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp index abc6d7d3b9..ee8d4800ae 100644 --- a/src/3rdparty/angle/src/libEGL/Surface.cpp +++ b/src/3rdparty/angle/src/libEGL/Surface.cpp @@ -20,6 +20,8 @@ #include "libEGL/main.h" #include "libEGL/Display.h" +#include <algorithm> + #if defined(ANGLE_OS_WINRT) #include <windows.foundation.h> #include <windows.ui.core.h> diff --git a/src/3rdparty/angle/src/third_party/trace_event/trace_event.h b/src/3rdparty/angle/src/third_party/trace_event/trace_event.h index 113b126a77..72d354dd64 100644 --- a/src/3rdparty/angle/src/third_party/trace_event/trace_event.h +++ b/src/3rdparty/angle/src/third_party/trace_event/trace_event.h @@ -589,7 +589,7 @@ const unsigned long long noEventId = 0; class TraceID { public: explicit TraceID(const void* id, unsigned char* flags) : - m_data(static_cast<unsigned long long>(reinterpret_cast<unsigned long>(id))) + m_data(reinterpret_cast<unsigned long long>(id)) { *flags |= TRACE_EVENT_FLAG_MANGLE_ID; } diff --git a/src/3rdparty/sha3/KeccakF-1600-opt64.c b/src/3rdparty/sha3/KeccakF-1600-opt64.c index 0432f1ab18..7bd442ef69 100755 --- a/src/3rdparty/sha3/KeccakF-1600-opt64.c +++ b/src/3rdparty/sha3/KeccakF-1600-opt64.c @@ -19,12 +19,16 @@ http://creativecommons.org/publicdomain/zero/1.0/ typedef unsigned char UINT8; typedef unsigned long long int UINT64; +#if defined(UseSSE) || defined(UseXOP) #if defined(__GNUC__) #define ALIGN __attribute__ ((aligned(32))) #elif defined(_MSC_VER) #define ALIGN __declspec(align(32)) -#else -#define ALIGN +#endif +#endif + +#ifndef ALIGN +# define ALIGN #endif #if defined(UseSSE) diff --git a/src/3rdparty/sha3/KeccakSponge.h b/src/3rdparty/sha3/KeccakSponge.h index a545cacb30..8bb11a8a1d 100755 --- a/src/3rdparty/sha3/KeccakSponge.h +++ b/src/3rdparty/sha3/KeccakSponge.h @@ -19,12 +19,16 @@ http://creativecommons.org/publicdomain/zero/1.0/ #define KeccakMaximumRate 1536 #define KeccakMaximumRateInBytes (KeccakMaximumRate/8) +#if defined(UseSSE) || defined(UseXOP) #if defined(__GNUC__) #define ALIGN __attribute__ ((aligned(32))) #elif defined(_MSC_VER) #define ALIGN __declspec(align(32)) -#else -#define ALIGN +#endif +#endif + +#ifndef ALIGN +# define ALIGN #endif ALIGN typedef struct spongeStateStruct { diff --git a/src/3rdparty/xcb/include/xcb/xkb.h b/src/3rdparty/xcb/include/xcb/xkb.h index 44b0a8d1ae..0180ec8b58 100644 --- a/src/3rdparty/xcb/include/xcb/xkb.h +++ b/src/3rdparty/xcb/include/xcb/xkb.h @@ -114,8 +114,8 @@ typedef enum xcb_xkb_control_t { XCB_XKB_CONTROL_GROUPS_WRAP = 134217728, XCB_XKB_CONTROL_INTERNAL_MODS = 268435456, XCB_XKB_CONTROL_IGNORE_LOCK_MODS = 536870912, - XCB_XKB_CONTROL_PER_KEY_REPEAT = 1073741824, - XCB_XKB_CONTROL_CONTROLS_ENABLED = 2147483648 + XCB_XKB_CONTROL_PER_KEY_REPEAT = 1073741824u, + XCB_XKB_CONTROL_CONTROLS_ENABLED = 2147483648u } xcb_xkb_control_t; typedef enum xcb_xkb_axfb_opt_t { diff --git a/src/3rdparty/xcb/libxcb/fix_compiler_warning_on_32bit_systems.patch b/src/3rdparty/xcb/libxcb/fix_compiler_warning_on_32bit_systems.patch new file mode 100644 index 0000000000..240c20d2ac --- /dev/null +++ b/src/3rdparty/xcb/libxcb/fix_compiler_warning_on_32bit_systems.patch @@ -0,0 +1,15 @@ +diff --git a/src/3rdparty/xcb/include/xcb/xkb.h b/src/3rdparty/xcb/include/xcb/xkb.h +index 44b0a8d..0180ec8 100644 +--- a/src/3rdparty/xcb/include/xcb/xkb.h ++++ b/src/3rdparty/xcb/include/xcb/xkb.h +@@ -114,8 +114,8 @@ typedef enum xcb_xkb_control_t { + XCB_XKB_CONTROL_GROUPS_WRAP = 134217728, + XCB_XKB_CONTROL_INTERNAL_MODS = 268435456, + XCB_XKB_CONTROL_IGNORE_LOCK_MODS = 536870912, +- XCB_XKB_CONTROL_PER_KEY_REPEAT = 1073741824, +- XCB_XKB_CONTROL_CONTROLS_ENABLED = 2147483648 ++ XCB_XKB_CONTROL_PER_KEY_REPEAT = 1073741824u, ++ XCB_XKB_CONTROL_CONTROLS_ENABLED = 2147483648u + } xcb_xkb_control_t; + + typedef enum xcb_xkb_axfb_opt_t { diff --git a/src/android/jar/jar.pri b/src/android/jar/jar.pri index 19501d7b29..5906231c73 100644 --- a/src/android/jar/jar.pri +++ b/src/android/jar/jar.pri @@ -9,6 +9,7 @@ JAVASOURCES += \ $$PATHPREFIX/QtEditText.java \ $$PATHPREFIX/QtInputConnection.java \ $$PATHPREFIX/QtLayout.java \ + $$PATHPREFIX/QtMessageDialogHelper.java \ $$PATHPREFIX/QtNative.java \ $$PATHPREFIX/QtNativeLibrariesDir.java \ $$PATHPREFIX/QtSurface.java diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java index 11af4d4280..3dcffeb07d 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -42,13 +42,6 @@ package org.qtproject.qt5.android; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Iterator; - import android.app.Activity; import android.content.Context; import android.content.pm.PackageManager; @@ -57,6 +50,8 @@ import android.content.res.Configuration; import android.graphics.Rect; import android.os.Build; import android.os.Bundle; +import android.os.Handler; +import android.os.ResultReceiver; import android.text.method.MetaKeyKeyListener; import android.util.DisplayMetrics; import android.util.Log; @@ -66,11 +61,19 @@ import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; +import android.view.Surface; import android.view.View; +import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; -import android.view.Surface; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Iterator; public class QtActivityDelegate { @@ -109,8 +112,9 @@ public class QtActivityDelegate private boolean m_quitApp = true; private Process m_debuggerProcess = null; // debugger process - public boolean m_keyboardIsVisible = false; - public boolean m_keyboardIsHiding = false; + private boolean m_keyboardIsVisible = false; + public boolean m_backKeyPressedSent = false; + public QtLayout getQtLayout() { @@ -173,6 +177,13 @@ public class QtActivityDelegate private final int ApplicationInactive = 0x2; private final int ApplicationActive = 0x4; + public void setKeyboardVisibility(boolean visibility) + { + if (m_keyboardIsVisible == visibility) + return; + m_keyboardIsVisible = visibility; + QtNative.keyboardVisibilityChanged(m_keyboardIsVisible); + } public void resetSoftwareKeyboard() { if (m_imm == null) @@ -181,6 +192,7 @@ public class QtActivityDelegate @Override public void run() { m_imm.restartInput(m_editText); + m_editText.m_optionsChanged = false; } }, 5); } @@ -253,15 +265,25 @@ public class QtActivityDelegate m_editText.postDelayed(new Runnable() { @Override public void run() { - m_imm.showSoftInput(m_editText, 0); - m_keyboardIsVisible = true; - m_keyboardIsHiding = false; - m_editText.postDelayed(new Runnable() { + m_imm.showSoftInput(m_editText, 0, new ResultReceiver(new Handler()) { @Override - public void run() { - m_imm.restartInput(m_editText); + protected void onReceiveResult(int resultCode, Bundle resultData) { + switch (resultCode) { + case InputMethodManager.RESULT_SHOWN: + case InputMethodManager.RESULT_UNCHANGED_SHOWN: + setKeyboardVisibility(true); + break; + case InputMethodManager.RESULT_HIDDEN: + case InputMethodManager.RESULT_UNCHANGED_HIDDEN: + setKeyboardVisibility(false); + break; + } } - }, 25); + }); + if (m_editText.m_optionsChanged) { + m_imm.restartInput(m_editText); + m_editText.m_optionsChanged = false; + } } }, 15); } @@ -270,9 +292,21 @@ public class QtActivityDelegate { if (m_imm == null) return; - m_imm.hideSoftInputFromWindow(m_editText.getWindowToken(), 0); - m_keyboardIsVisible = false; - m_keyboardIsHiding = false; + m_imm.hideSoftInputFromWindow(m_editText.getWindowToken(), 0, new ResultReceiver( new Handler()){ + @Override + protected void onReceiveResult(int resultCode, Bundle resultData) { + switch (resultCode) { + case InputMethodManager.RESULT_SHOWN: + case InputMethodManager.RESULT_UNCHANGED_SHOWN: + setKeyboardVisibility(true); + break; + case InputMethodManager.RESULT_HIDDEN: + case InputMethodManager.RESULT_UNCHANGED_HIDDEN: + setKeyboardVisibility(false); + break; + } + } + }); } public boolean isSoftwareKeyboardVisible() @@ -362,7 +396,7 @@ public class QtActivityDelegate + "\tNECESSITAS_API_LEVEL=" + necessitasApiLevel + "\tHOME=" + m_activity.getFilesDir().getAbsolutePath() + "\tTMPDIR=" + m_activity.getFilesDir().getAbsolutePath(); - if (android.os.Build.VERSION.SDK_INT < 14) + if (Build.VERSION.SDK_INT < 14) additionalEnvironmentVariables += "\tQT_ANDROID_FONTS=Droid Sans;Droid Sans Fallback"; else additionalEnvironmentVariables += "\tQT_ANDROID_FONTS=Roboto;Droid Sans;Droid Sans Fallback"; @@ -378,6 +412,7 @@ public class QtActivityDelegate m_applicationParameters = loaderParams.getString(APPLICATION_PARAMETERS_KEY); else m_applicationParameters = ""; + setActionBarVisibility(false); return true; } @@ -585,9 +620,9 @@ public class QtActivityDelegate } m_layout = new QtLayout(m_activity); m_surface = new QtSurface(m_activity, 0); - m_editText = new QtEditText(m_activity); + m_editText = new QtEditText(m_activity, this); m_imm = (InputMethodManager)m_activity.getSystemService(Context.INPUT_METHOD_SERVICE); - m_layout.addView(m_surface,0); + m_layout.addView(m_surface, 0); m_activity.setContentView(m_layout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT)); @@ -717,8 +752,12 @@ public class QtActivityDelegate } m_lastChar = lc; - if (keyCode != KeyEvent.KEYCODE_BACK) - QtNative.keyDown(keyCode, c, event.getMetaState()); + if (keyCode == KeyEvent.KEYCODE_BACK) { + m_backKeyPressedSent = !m_keyboardIsVisible; + if (!m_backKeyPressedSent) + return true; + } + QtNative.keyDown(keyCode, c, event.getMetaState()); return true; } @@ -737,8 +776,9 @@ public class QtActivityDelegate } } - if (keyCode == KeyEvent.KEYCODE_BACK && m_keyboardIsVisible && !m_keyboardIsHiding) { + if (keyCode == KeyEvent.KEYCODE_BACK && !m_backKeyPressedSent) { hideSoftwareKeyboard(); + setKeyboardVisibility(false); return true; } @@ -775,7 +815,10 @@ public class QtActivityDelegate public boolean onPrepareOptionsMenu(Menu menu) { m_opionsMenuIsVisible = true; - return QtNative.onPrepareOptionsMenu(menu); + boolean res = QtNative.onPrepareOptionsMenu(menu); + if (!res || menu.size() == 0) + setActionBarVisibility(false); + return res; } public boolean onOptionsItemSelected(MenuItem item) @@ -791,8 +834,17 @@ public class QtActivityDelegate public void resetOptionsMenu() { - if (m_opionsMenuIsVisible) - m_activity.closeOptionsMenu(); + setActionBarVisibility(true); + if (Build.VERSION.SDK_INT > 10) { + try { + Activity.class.getMethod("invalidateOptionsMenu").invoke(m_activity); + } catch (Exception e) { + e.printStackTrace(); + } + } + else + if (m_opionsMenuIsVisible) + m_activity.closeOptionsMenu(); } private boolean m_contextMenuVisible = false; public void onCreateContextMenu(ContextMenu menu, @@ -833,4 +885,46 @@ public class QtActivityDelegate { m_activity.closeContextMenu(); } + + private boolean hasPermanentMenuKey() + { + try { + return Build.VERSION.SDK_INT < 11 || (Build.VERSION.SDK_INT >= 14 && + (Boolean)ViewConfiguration.class.getMethod("hasPermanentMenuKey").invoke(ViewConfiguration.get(m_activity))); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + private Object getActionBar() + { + try { + return Activity.class.getMethod("getActionBar").invoke(m_activity); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + private void setActionBarVisibility(boolean visible) + { + if (hasPermanentMenuKey() || !visible) { + if (Build.VERSION.SDK_INT > 10 && getActionBar() != null) { + try { + Class.forName("android.app.ActionBar").getMethod("hide").invoke(getActionBar()); + } catch (Exception e) { + e.printStackTrace(); + } + } + + } else { + if (Build.VERSION.SDK_INT > 10 && getActionBar() != null) + try { + Class.forName("android.app.ActionBar").getMethod("show").invoke(getActionBar()); + } catch (Exception e) { + e.printStackTrace(); + } + } + } } diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtEditText.java b/src/android/jar/src/org/qtproject/qt5/android/QtEditText.java index b95e0c070c..593746aac9 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtEditText.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtEditText.java @@ -50,33 +50,47 @@ import android.view.inputmethod.InputConnection; public class QtEditText extends View { - QtInputConnection m_inputConnection; int m_initialCapsMode = 0; int m_imeOptions = 0; int m_inputType = InputType.TYPE_CLASS_TEXT; + boolean m_optionsChanged = false; + QtActivityDelegate m_activityDelegate; public void setImeOptions(int m_imeOptions) { + if (m_imeOptions == this.m_imeOptions) + return; this.m_imeOptions = m_imeOptions; + m_optionsChanged = true; } public void setInitialCapsMode(int m_initialCapsMode) { + if (m_initialCapsMode == this.m_initialCapsMode) + return; this.m_initialCapsMode = m_initialCapsMode; + m_optionsChanged = true; } public void setInputType(int m_inputType) { + if (m_inputType == this.m_inputType) + return; this.m_inputType = m_inputType; + m_optionsChanged = true; } - public QtEditText(Context context) + public QtEditText(Context context, QtActivityDelegate activityDelegate) { super(context); setFocusable(true); setFocusableInTouchMode(true); - m_inputConnection = new QtInputConnection(this); + m_activityDelegate = activityDelegate; + } + public QtActivityDelegate getActivityDelegate() + { + return m_activityDelegate; } @Override @@ -86,8 +100,9 @@ public class QtEditText extends View outAttrs.imeOptions = m_imeOptions; outAttrs.initialCapsMode = m_initialCapsMode; outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_EXTRACT_UI; - return m_inputConnection; + return new QtInputConnection(this); } + // // DEBUG CODE // @Override // protected void onDraw(Canvas canvas) { diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java b/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java index f251369737..4b2d50ca1f 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java @@ -43,8 +43,6 @@ package org.qtproject.qt5.android; import android.content.Context; -import android.os.Build; -import android.view.View; import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.ExtractedText; @@ -82,6 +80,22 @@ class QtNativeInputConnection static native boolean paste(); } +class HideKeyboardRunnable implements Runnable { + private QtInputConnection m_connection; + HideKeyboardRunnable(QtInputConnection connection) + { + m_connection = connection; + } + + @Override + public void run() { + if (m_connection.getInputState() == QtInputConnection.InputStates.Hiding) { + QtNative.activityDelegate().setKeyboardVisibility(false); + m_connection.reset(); + } + } +} + public class QtInputConnection extends BaseInputConnection { private static final int ID_SELECT_ALL = android.R.id.selectAll; @@ -92,67 +106,83 @@ public class QtInputConnection extends BaseInputConnection private static final int ID_SWITCH_INPUT_METHOD = android.R.id.switchInputMethod; private static final int ID_ADD_TO_DICTIONARY = android.R.id.addToDictionary; - View m_view; - boolean m_closing; - public QtInputConnection(View targetView) + + enum InputStates { Visible, FinishComposing, Hiding }; + + private QtEditText m_view = null; + private InputStates m_inputState = InputStates.Visible; + + public void reset() + { + m_inputState = InputStates.Visible; + } + + public InputStates getInputState() + { + return m_inputState; + } + + private void setClosing(boolean closing) + { + if (closing && m_inputState == InputStates.Hiding) + return; + + if (closing && m_inputState == InputStates.FinishComposing && m_view.getActivityDelegate().isSoftwareKeyboardVisible()) { + m_view.postDelayed(new HideKeyboardRunnable(this), 100); + m_inputState = InputStates.Hiding; + } else { + if (m_inputState == InputStates.Hiding) + QtNative.activityDelegate().setKeyboardVisibility(true); + m_inputState = closing ? InputStates.FinishComposing : InputStates.Visible; + } + } + + public QtInputConnection(QtEditText targetView) { super(targetView, true); m_view = targetView; - m_closing = false; } @Override public boolean beginBatchEdit() { - m_closing = false; + setClosing(false); return true; } @Override public boolean endBatchEdit() { - m_closing = false; +// setClosing(false); return true; } @Override public boolean commitCompletion(CompletionInfo text) { - m_closing = false; + setClosing(false); return QtNativeInputConnection.commitCompletion(text.getText().toString(), text.getPosition()); } @Override public boolean commitText(CharSequence text, int newCursorPosition) { - m_closing = false; + setClosing(false); return QtNativeInputConnection.commitText(text.toString(), newCursorPosition); } @Override public boolean deleteSurroundingText(int leftLength, int rightLength) { - m_closing = false; + setClosing(false); return QtNativeInputConnection.deleteSurroundingText(leftLength, rightLength); } @Override public boolean finishComposingText() { - if (m_closing) { - QtNative.activityDelegate().m_keyboardIsHiding = true; - m_view.postDelayed(new Runnable() { - @Override - public void run() { - if (QtNative.activityDelegate().m_keyboardIsHiding) - QtNative.activityDelegate().m_keyboardIsVisible=false; - } - }, 5000); // it seems finishComposingText comes musch faster than onKeyUp event, - // so we must delay hide notification - m_closing = false; - } else { - m_closing = true; - } + // on some/all android devices hide event is not coming, but instead finishComposingText() is called twice + setClosing(true); return QtNativeInputConnection.finishComposingText(); } @@ -234,18 +264,21 @@ public class QtInputConnection extends BaseInputConnection @Override public boolean setComposingText(CharSequence text, int newCursorPosition) { + setClosing(false); return QtNativeInputConnection.setComposingText(text.toString(), newCursorPosition); } @Override public boolean setComposingRegion(int start, int end) { + setClosing(false); return QtNativeInputConnection.setComposingRegion(start, end); } @Override public boolean setSelection(int start, int end) { + setClosing(false); return QtNativeInputConnection.setSelection(start, end); } } diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtMessageDialogHelper.java b/src/android/jar/src/org/qtproject/qt5/android/QtMessageDialogHelper.java new file mode 100644 index 0000000000..6ee1304c12 --- /dev/null +++ b/src/android/jar/src/org/qtproject/qt5/android/QtMessageDialogHelper.java @@ -0,0 +1,425 @@ +/**************************************************************************** + ** + ** Copyright (C) 2013 BogDan Vatra <bogdan@kde.org> + ** Contact: http://www.qt-project.org/legal + ** + ** This file is part of the Android port 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 Digia. For licensing terms and + ** conditions see http://qt.digia.com/licensing. For further information + ** use the contact form at http://qt.digia.com/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 as published by the Free Software + ** Foundation and appearing in the file LICENSE.LGPL included in the + ** packaging of this file. Please review the following information to + ** ensure the GNU Lesser General Public License version 2.1 requirements + ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Digia gives you certain additional + ** rights. These rights are described in the Digia Qt 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$ + ** + ****************************************************************************/ + + +package org.qtproject.qt5.android; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.text.ClipboardManager; +import android.util.TypedValue; +import android.view.View; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.ScrollView; +import android.widget.TextView; +import android.widget.Toast; + +import java.util.ArrayList; + +class QtNativeDialogHelper +{ + static native void dialogResult(long handler, int buttonID); +} + +class ButtonStruct implements View.OnClickListener +{ + ButtonStruct(QtMessageDialogHelper dialog, int id, String text) + { + m_dialog = dialog; + m_id = id; + m_text = text; + } + QtMessageDialogHelper m_dialog; + private int m_id; + String m_text; + + @Override + public void onClick(View view) { + QtNativeDialogHelper.dialogResult(m_dialog.handler(), m_id); + } +} + +public class QtMessageDialogHelper +{ + + public QtMessageDialogHelper(Activity activity) + { + m_activity = activity; + } + + + public void setIcon(int icon) + { + m_icon = icon; + + } + + private Drawable getIconDrawable() + { + if (m_icon == 0) + return null; + + if (Build.VERSION.SDK_INT > 10) { + try { + TypedValue typedValue = new TypedValue(); + m_theme.resolveAttribute(Class.forName("android.R$attr").getDeclaredField("alertDialogIcon").getInt(null), typedValue, true); + return m_activity.getResources().getDrawable(typedValue.resourceId); + } catch (Exception e) { + e.printStackTrace(); + } + } + + // Information, Warning, Critical, Question + switch (m_icon) + { + case 1: // Information + try { + return m_activity.getResources().getDrawable(Class.forName("android.R$drawable").getDeclaredField("ic_dialog_info").getInt(null)); + } catch (Exception e) { + e.printStackTrace(); + } + break; + case 2: // Warning +// try { +// return Class.forName("android.R$drawable").getDeclaredField("stat_sys_warning").getInt(null); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// break; + case 3: // Critical + try { + return m_activity.getResources().getDrawable(Class.forName("android.R$drawable").getDeclaredField("ic_dialog_alert").getInt(null)); + } catch (Exception e) { + e.printStackTrace(); + } + break; + case 4: // Question + try { + return m_activity.getResources().getDrawable(Class.forName("android.R$drawable").getDeclaredField("ic_menu_help").getInt(null)); + } catch (Exception e) { + e.printStackTrace(); + } + break; + } + return null; + } + + public void setTile(String title) + { + m_title = title; + } + + public void setText(String text) + { + m_text = text; + } + + public void setInformativeText(String informativeText) + { + m_informativeText = informativeText; + } + + public void setDetailedText(String text) + { + m_detailedText = text; + } + + public void addButton(int id, String text) + { + if (m_buttonsList == null) + m_buttonsList = new ArrayList<ButtonStruct>(); + m_buttonsList.add(new ButtonStruct(this, id, text)); + } + + private void setTextAppearance(TextView view, String attr, String style) + { + try { + int[] attrs = (int[]) Class.forName("android.R$styleable").getDeclaredField("TextAppearance").get(null); + final TypedArray a = m_theme.obtainStyledAttributes(null, + attrs, + Class.forName("android.R$attr").getDeclaredField(attr).getInt(null), + Class.forName("android.R$style").getDeclaredField(style).getInt(null)); + final int textSize = a.getDimensionPixelSize( + Class.forName("android.R$styleable").getDeclaredField("TextAppearance_textSize").getInt(null), 0); + if (textSize != 0) + view.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize); + + final int textColor = a.getColor( + Class.forName("android.R$styleable").getDeclaredField("TextAppearance_textColor").getInt(null), 0x3138); + if (textColor != 0x3138) + view.setTextColor(textColor); + + a.recycle(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private Drawable getStyledDrawable(String drawable) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException + { + int[] attrs = {Class.forName("android.R$attr").getDeclaredField(drawable).getInt(null)}; + final TypedArray a = m_theme.obtainStyledAttributes(attrs); + Drawable d = a.getDrawable(0); + a.recycle(); + return d; + } + + + public void show(long handler) + { + m_handler = handler; + m_activity.runOnUiThread( new Runnable() { + @Override + public void run() { + if (m_dialog != null && m_dialog.isShowing()) + m_dialog.dismiss(); + + m_dialog = new AlertDialog.Builder(m_activity).create(); + m_theme = m_dialog.getWindow().getContext().getTheme(); + + if (m_title != null) + m_dialog.setTitle(m_title); + m_dialog.setOnCancelListener( new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialogInterface) { + QtNativeDialogHelper.dialogResult(handler(), -1); + } + }); + m_dialog.setCancelable(m_buttonsList == null); + m_dialog.setCanceledOnTouchOutside(m_buttonsList == null); + m_dialog.setIcon(getIconDrawable()); + ScrollView scrollView = new ScrollView(m_activity); + RelativeLayout dialogLayout = new RelativeLayout(m_activity); + int id = 1; + View lastView = null; + View.OnLongClickListener copyText = new View.OnLongClickListener() { + @Override + public boolean onLongClick(View view) { + TextView tv = (TextView)view; + if (tv != null) { + ClipboardManager cm = (android.text.ClipboardManager) m_activity.getSystemService(Context.CLIPBOARD_SERVICE); + cm.setText(tv.getText()); + } + return true; + } + }; + if (m_text != null) + { + TextView view = new TextView(m_activity); + view.setId(id++); + view.setOnLongClickListener(copyText); + view.setLongClickable(true); + + view.setText(m_text); + setTextAppearance(view, "textAppearanceMedium", "TextAppearance_Medium"); + + RelativeLayout.LayoutParams layout = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT); + layout.setMargins(16, 8, 16, 8); + layout.addRule(RelativeLayout.ALIGN_PARENT_TOP); + dialogLayout.addView(view, layout); + lastView = view; + } + + if (m_informativeText != null) + { + TextView view= new TextView(m_activity); + view.setId(id++); + view.setOnLongClickListener(copyText); + view.setLongClickable(true); + + view.setText(m_informativeText); + setTextAppearance(view, "textAppearanceMedium", "TextAppearance_Medium"); + + RelativeLayout.LayoutParams layout = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT); + layout.setMargins(16, 8, 16, 8); + if (lastView != null) + layout.addRule(RelativeLayout.BELOW, lastView.getId()); + else + layout.addRule(RelativeLayout.ALIGN_PARENT_TOP); + dialogLayout.addView(view, layout); + lastView = view; + } + + if (m_detailedText != null) + { + TextView view= new TextView(m_activity); + view.setId(id++); + view.setOnLongClickListener(copyText); + view.setLongClickable(true); + + view.setText(m_detailedText); + setTextAppearance(view, "textAppearanceSmall", "TextAppearance_Small"); + + RelativeLayout.LayoutParams layout = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT); + layout.setMargins(16, 8, 16, 8); + if (lastView != null) + layout.addRule(RelativeLayout.BELOW, lastView.getId()); + else + layout.addRule(RelativeLayout.ALIGN_PARENT_TOP); + dialogLayout.addView(view, layout); + lastView = view; + } + + if (m_buttonsList != null) + { + LinearLayout buttonsLayout = new LinearLayout(m_activity); + buttonsLayout.setOrientation(LinearLayout.HORIZONTAL); + buttonsLayout.setId(id++); + boolean firstButton = true; + for (ButtonStruct button: m_buttonsList) + { + Button bv; + if (Build.VERSION.SDK_INT > 10) { + try { + bv = new Button(m_activity, null, Class.forName("android.R$attr").getDeclaredField("borderlessButtonStyle").getInt(null)); + } catch (Exception e) { + bv = new Button(m_activity); + e.printStackTrace(); + } + } else { + bv = new Button(m_activity); + } + + bv.setText(button.m_text); + bv.setOnClickListener(button); + if (!firstButton) // first button + { + LinearLayout.LayoutParams layout = null; + View spacer = new View(m_activity); + if (Build.VERSION.SDK_INT > 10) { + try { + layout = new LinearLayout.LayoutParams(1, RelativeLayout.LayoutParams.MATCH_PARENT); + spacer.setBackgroundDrawable(getStyledDrawable("dividerVertical")); + buttonsLayout.addView(spacer, layout); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + LinearLayout.LayoutParams layout = null; + layout = new LinearLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT, 1.0f); + buttonsLayout.addView(bv, layout); + firstButton = false; + } + + if (Build.VERSION.SDK_INT > 10) { + try { + View horizontalDevider = new View(m_activity); + horizontalDevider.setId(id++); + horizontalDevider.setBackgroundDrawable(getStyledDrawable("dividerHorizontal")); + RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, 1); + relativeParams.setMargins(0, 10, 0, 0); + if (lastView != null) { + relativeParams.addRule(RelativeLayout.BELOW, lastView.getId()); + } + else + relativeParams.addRule(RelativeLayout.ALIGN_PARENT_TOP); + dialogLayout.addView(horizontalDevider, relativeParams); + lastView = horizontalDevider; + } catch (Exception e) { + e.printStackTrace(); + } + } + RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT); + if (lastView != null) { + relativeParams.addRule(RelativeLayout.BELOW, lastView.getId()); + } + else + relativeParams.addRule(RelativeLayout.ALIGN_PARENT_TOP); + if (Build.VERSION.SDK_INT < 11) + relativeParams.setMargins(2, 12, 2, 4); + else + relativeParams.setMargins(2, 0, 2, 0); + dialogLayout.addView(buttonsLayout, relativeParams); + } + scrollView.addView(dialogLayout); + m_dialog.setView(scrollView); + m_dialog.show(); + } + }); + } + + public void hide() + { + m_activity.runOnUiThread( new Runnable() { + @Override + public void run() { + if (m_dialog != null && m_dialog.isShowing()) + m_dialog.dismiss(); + reset(); + } + }); + } + + public long handler() + { + return m_handler; + } + + public void reset() + { + m_icon = 0; + m_title = null; + m_text = null; + m_informativeText = null; + m_detailedText = null; + m_buttonsList = null; + m_dialog = null; + m_handler = 0; + } + + private Activity m_activity; + private int m_icon = 0; + private String m_title, m_text, m_informativeText, m_detailedText; + private ArrayList<ButtonStruct> m_buttonsList; + private AlertDialog m_dialog; + private long m_handler = 0; + private Resources.Theme m_theme; +} diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java index 1385c90e3e..57f3642b56 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java @@ -50,7 +50,6 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; import android.net.Uri; -import android.os.Build; import android.text.ClipboardManager; import android.util.Log; import android.view.ContextMenu; @@ -110,9 +109,13 @@ public class QtNative public static void openURL(String url) { - Uri uri = Uri.parse(url); - Intent intent = new Intent(Intent.ACTION_VIEW, uri); - activity().startActivity(intent); + try { + Uri uri = Uri.parse(url); + Intent intent = new Intent(Intent.ACTION_VIEW, uri); + activity().startActivity(intent); + } catch (Exception e) { + e.printStackTrace(); + } } // this method loads full path libs @@ -419,30 +422,21 @@ public class QtNative private static boolean isSoftwareKeyboardVisible() { - Semaphore semaphore = new Semaphore(1); - Boolean ret = false; - class RunnableRes implements Runnable { - @SuppressWarnings("unused") - Boolean returnValue = null; - Semaphore semaphore = null; - RunnableRes(Boolean ret, Semaphore sem) { - semaphore = sem; - returnValue = ret; - } + final Semaphore semaphore = new Semaphore(0); + final Boolean[] ret = {false}; + runAction(new Runnable() { @Override public void run() { - returnValue = m_activityDelegate.isSoftwareKeyboardVisible(); + ret[0] = m_activityDelegate.isSoftwareKeyboardVisible(); semaphore.release(); } - } - - runAction(new RunnableRes(ret, semaphore)); + }); try { semaphore.acquire(); } catch (Exception e) { e.printStackTrace(); } - return ret; + return ret[0]; } private static void setFullScreen(final boolean fullScreen) @@ -458,7 +452,7 @@ public class QtNative private static void registerClipboardManager() { - final Semaphore semaphore = new Semaphore(1); + final Semaphore semaphore = new Semaphore(0); runAction(new Runnable() { @Override public void run() { @@ -569,6 +563,7 @@ public class QtNative // keyboard methods public static native void keyDown(int key, int unicode, int modifier); public static native void keyUp(int key, int unicode, int modifier); + public static native void keyboardVisibilityChanged(boolean visibility); // keyboard methods // surface methods diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtSurface.java b/src/android/jar/src/org/qtproject/qt5/android/QtSurface.java index cd0bddf2c8..c499dc3898 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtSurface.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtSurface.java @@ -117,21 +117,23 @@ public class QtSurface extends SurfaceView implements SurfaceHolder.Callback // Initialize Accessibility // The accessibility code depends on android API level 16, so dynamically resolve it - try { - final String a11yDelegateClassName = "org.qtproject.qt5.android.accessibility.QtAccessibilityDelegate"; - Class<?> qtDelegateClass = Class.forName(a11yDelegateClassName); - Constructor constructor = qtDelegateClass.getConstructor(Class.forName("android.view.View")); - m_accessibilityDelegate = constructor.newInstance(this); - - Class a11yDelegateClass = Class.forName("android.view.View$AccessibilityDelegate"); - Method setDelegateMethod = this.getClass().getMethod("setAccessibilityDelegate", a11yDelegateClass); - setDelegateMethod.invoke(this, m_accessibilityDelegate); - } catch (ClassNotFoundException e) { - // Class not found is fine since we are compatible with Android API < 16, but the function will - // only be available with that API level. - } catch (Exception e) { - // Unknown exception means something went wrong. - Log.w("Qt A11y", "Unknown exception: " + e.toString()); + if (android.os.Build.VERSION.SDK_INT >= 16) { + try { + final String a11yDelegateClassName = "org.qtproject.qt5.android.accessibility.QtAccessibilityDelegate"; + Class<?> qtDelegateClass = Class.forName(a11yDelegateClassName); + Constructor constructor = qtDelegateClass.getConstructor(Class.forName("android.view.View")); + m_accessibilityDelegate = constructor.newInstance(this); + + Class a11yDelegateClass = Class.forName("android.view.View$AccessibilityDelegate"); + Method setDelegateMethod = this.getClass().getMethod("setAccessibilityDelegate", a11yDelegateClass); + setDelegateMethod.invoke(this, m_accessibilityDelegate); + } catch (ClassNotFoundException e) { + // Class not found is fine since we are compatible with Android API < 16, but the function will + // only be available with that API level. + } catch (Exception e) { + // Unknown exception means something went wrong. + Log.w("Qt A11y", "Unknown exception: " + e.toString()); + } } } diff --git a/src/android/java/AndroidManifest.xml b/src/android/java/AndroidManifest.xml index 6463793e0b..cfad4553ee 100644 --- a/src/android/java/AndroidManifest.xml +++ b/src/android/java/AndroidManifest.xml @@ -1,7 +1,7 @@ <?xml version='1.0' encoding='utf-8'?> -<manifest package="org.qtproject.example" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1"> +<manifest package="org.qtproject.example" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto"> <application android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="@string/app_name"> - <activity android:configChanges="orientation|locale|fontScale|keyboard|keyboardHidden|navigation|screenSize" + <activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="org.qtproject.qt5.android.bindings.QtActivity" android:label="@string/app_name" android:screenOrientation="unspecified"> @@ -34,8 +34,10 @@ <!-- Splash screen --> </activity> </application> - <!-- %%INSERT_USES_SDK%% --> + <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="14"/> <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/> + <!-- %%INSERT_PERMISSIONS --> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> + <!-- %%INSERT_FEATURES --> </manifest> diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java index 9c7b57a4f5..7c741edfda 100644 --- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java +++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java @@ -56,6 +56,7 @@ import android.content.res.AssetManager; import android.graphics.Bitmap; import android.graphics.Canvas; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; @@ -79,6 +80,7 @@ import android.view.ActionMode; import android.view.ActionMode.Callback; //@ANDROID-11 + public class QtActivity extends Activity { private final static int MINISTRO_INSTALL_REQUEST_CODE = 0xf3ee; // request code used to know when Ministro instalation is finished @@ -113,28 +115,37 @@ public class QtActivity extends Activity // for more details. private static final String REPOSITORY_KEY = "repository"; // use this key to overwrite the default ministro repsitory + private static final String ANDROID_THEMES_KEY = "android.themes"; // themes that your application uses + - private static final String APPLICATION_PARAMETERS = null; // use this variable to pass any parameters to your application, + public String APPLICATION_PARAMETERS = null; // use this variable to pass any parameters to your application, // the parameters must not contain any white spaces // and must be separated with "\t" // e.g "-param1\t-param2=value2\t-param3\tvalue3" - private String ENVIRONMENT_VARIABLES = "QT_USE_ANDROID_NATIVE_STYLE=1\t"; + public String ENVIRONMENT_VARIABLES = "QT_USE_ANDROID_NATIVE_STYLE=1\tQT_USE_ANDROID_NATIVE_DIALOGS=1\t"; // use this variable to add any environment variables to your application. // the env vars must be separated with "\t" // e.g. "ENV_VAR1=1\tENV_VAR2=2\t" // Currently the following vars are used by the android plugin: - // * QT_USE_ANDROID_NATIVE_STYLE - 1 to use the android widget style if available, - // note that the android style plugin in Qt 5.1 is not fully functional. - - private static final String QT_ANDROID_THEME = "light"; // sets the default theme to light. Possible values are: - // * "" - for the device default dark theme - // * "light" - for the device default light theme - // * "holo" - for the holo dark theme - // * "holo_light" - for the holo light theme + // * QT_USE_ANDROID_NATIVE_STYLE - 1 to use the android widget style if available. + // * QT_USE_ANDROID_NATIVE_DIALOGS -1 to use the android native dialogs. + + public String[] QT_ANDROID_THEMES = null; // A list with all themes that your application want to use. + // The name of the theme must be the same with any theme from + // http://developer.android.com/reference/android/R.style.html + // The most used themes are: + // * "Theme" - (fallback) check http://developer.android.com/reference/android/R.style.html#Theme + // * "Theme_Black" - check http://developer.android.com/reference/android/R.style.html#Theme_Black + // * "Theme_Light" - (default for API <=10) check http://developer.android.com/reference/android/R.style.html#Theme_Light + // * "Theme_Holo" - check http://developer.android.com/reference/android/R.style.html#Theme_Holo + // * "Theme_Holo_Light" - (default for API 11-13) check http://developer.android.com/reference/android/R.style.html#Theme_Holo_Light + // * "Theme_DeviceDefault" - check http://developer.android.com/reference/android/R.style.html#Theme_DeviceDefault + // * "Theme_DeviceDefault_Light" - (default for API 14+) check http://developer.android.com/reference/android/R.style.html#Theme_DeviceDefault_Light + + public String QT_ANDROID_DEFAULT_THEME = null; // sets the default theme. private static final int INCOMPATIBLE_MINISTRO_VERSION = 1; // Incompatible Ministro version. Ministro needs to be upgraded. - private static final String DISPLAY_DPI_KEY = "display.dpi"; private static final int BUFFER_SIZE = 1024; private ActivityInfo m_activityInfo = null; // activity info object, used to access the libs and the strings @@ -153,6 +164,21 @@ public class QtActivity extends Activity // this repository is used to push Qt snapshots. private String[] m_qtLibs = null; // required qt libs + public QtActivity() + { + if (Build.VERSION.SDK_INT <= 10) { + QT_ANDROID_THEMES = new String[] {"Theme_Light"}; + QT_ANDROID_DEFAULT_THEME = "Theme_Light"; + } + else if (Build.VERSION.SDK_INT >= 11 && Build.VERSION.SDK_INT <= 13) { + QT_ANDROID_THEMES = new String[] {"Theme_Holo_Light"}; + QT_ANDROID_DEFAULT_THEME = "Theme_Holo_Light"; + } else { + QT_ANDROID_THEMES = new String[] {"Theme_DeviceDefault_Light"}; + QT_ANDROID_DEFAULT_THEME = "Theme_DeviceDefault_Light"; + } + } + // this function is used to load and start the loader private void loadApplication(Bundle loaderParams) { @@ -237,23 +263,24 @@ public class QtActivity extends Activity private ServiceConnection m_ministroConnection=new ServiceConnection() { private IMinistro m_service = null; - @Override + @Override public void onServiceConnected(ComponentName name, IBinder service) { m_service = IMinistro.Stub.asInterface(service); try { - if (m_service!=null) { - Bundle parameters= new Bundle(); + if (m_service != null) { + Bundle parameters = new Bundle(); parameters.putStringArray(REQUIRED_MODULES_KEY, m_qtLibs); parameters.putString(APPLICATION_TITLE_KEY, (String)QtActivity.this.getTitle()); parameters.putInt(MINIMUM_MINISTRO_API_KEY, MINISTRO_API_LEVEL); parameters.putInt(MINIMUM_QT_VERSION_KEY, QT_VERSION); parameters.putString(ENVIRONMENT_VARIABLES_KEY, ENVIRONMENT_VARIABLES); - if (null!=APPLICATION_PARAMETERS) + if (APPLICATION_PARAMETERS != null) parameters.putString(APPLICATION_PARAMETERS_KEY, APPLICATION_PARAMETERS); parameters.putStringArray(SOURCES_KEY, m_sources); parameters.putString(REPOSITORY_KEY, m_repository); - parameters.putInt(DISPLAY_DPI_KEY, QtActivity.this.getResources().getDisplayMetrics().densityDpi); + if (QT_ANDROID_THEMES != null) + parameters.putStringArray(ANDROID_THEMES_KEY, QT_ANDROID_THEMES); m_service.requestLoader(m_ministroCallback, parameters); } } catch (RemoteException e) { @@ -261,19 +288,19 @@ public class QtActivity extends Activity } } - private IMinistroCallback m_ministroCallback = new IMinistroCallback.Stub() { - // this function is called back by Ministro. - @Override - public void loaderReady(final Bundle loaderParams) throws RemoteException { - runOnUiThread(new Runnable() { - @Override - public void run() { - unbindService(m_ministroConnection); - loadApplication(loaderParams); - } - }); - } - }; + private IMinistroCallback m_ministroCallback = new IMinistroCallback.Stub() { + // this function is called back by Ministro. + @Override + public void loaderReady(final Bundle loaderParams) throws RemoteException { + runOnUiThread(new Runnable() { + @Override + public void run() { + unbindService(m_ministroConnection); + loadApplication(loaderParams); + } + }); + } + }; @Override public void onServiceDisconnected(ComponentName name) { @@ -683,13 +710,30 @@ public class QtActivity extends Activity public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + try { + setTheme(Class.forName("android.R$style").getDeclaredField(QT_ANDROID_DEFAULT_THEME).getInt(null)); + } catch (Exception e) { + e.printStackTrace(); + } + + if (Build.VERSION.SDK_INT > 10) { + try { + requestWindowFeature(Window.class.getField("FEATURE_ACTION_BAR").getInt(null)); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + requestWindowFeature(Window.FEATURE_NO_TITLE); + } + if (QtApplication.m_delegateObject != null && QtApplication.onCreate != null) { QtApplication.invokeDelegateMethod(QtApplication.onCreate, savedInstanceState); return; } - ENVIRONMENT_VARIABLES += "\tQT_ANDROID_THEME=" + QT_ANDROID_THEME + + ENVIRONMENT_VARIABLES += "\tQT_ANDROID_THEME=" + QT_ANDROID_DEFAULT_THEME + "/\tQT_ANDROID_THEME_DISPLAY_DPI=" + getResources().getDisplayMetrics().densityDpi + "\t"; - requestWindowFeature(Window.FEATURE_NO_TITLE); + try { m_activityInfo = getPackageManager().getActivityInfo(getComponentName(), PackageManager.GET_META_DATA); } catch (NameNotFoundException e) { diff --git a/src/angle/patches/0001-ANGLE-Fix-compilation-with-MSVC2013.patch b/src/angle/patches/0001-ANGLE-Fix-compilation-with-MSVC2013.patch new file mode 100644 index 0000000000..cf32a20d46 --- /dev/null +++ b/src/angle/patches/0001-ANGLE-Fix-compilation-with-MSVC2013.patch @@ -0,0 +1,28 @@ +From 4863cf64cd332a5fcefe453634c3c5ef62cb758c Mon Sep 17 00:00:00 2001 +From: Friedemann Kleint <Friedemann.Kleint@digia.com> +Date: Thu, 24 Oct 2013 12:49:59 +0300 +Subject: [PATCH] ANGLE: Fix compilation with MSVC2013. + +Add missing include for std::min(), std::max(). + +Change-Id: I740e5db94f9f958ac65de8dd7baab7e203482637 +--- + src/3rdparty/angle/src/libEGL/Surface.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp +index b47a7bc..83fbbf5 100644 +--- a/src/3rdparty/angle/src/libEGL/Surface.cpp ++++ b/src/3rdparty/angle/src/libEGL/Surface.cpp +@@ -20,6 +20,8 @@ + #include "libEGL/main.h" + #include "libEGL/Display.h" + ++#include <algorithm> ++ + namespace egl + { + +-- +1.8.3.msysgit.0 + diff --git a/src/angle/patches/0001-Fix-compilation-with-MinGW-gcc-64-bit.patch b/src/angle/patches/0001-Fix-compilation-with-MinGW-gcc-64-bit.patch new file mode 100644 index 0000000000..0420694c91 --- /dev/null +++ b/src/angle/patches/0001-Fix-compilation-with-MinGW-gcc-64-bit.patch @@ -0,0 +1,35 @@ +From 821c28d387b332bf16b6ea35ec22a77d3ba41632 Mon Sep 17 00:00:00 2001 +From: Kai Koehne <kai.koehne@digia.com> +Date: Mon, 28 Oct 2013 10:27:53 +0100 +Subject: [PATCH] Fix compilation with MinGW gcc 64 bit + +Fix compilation of ANGLE with gcc 4.8.0 64 bit: The + + reinterpret_cast<unsigned long>(void*) + +was causing + + error: cast from 'const void*' to 'long unsigned int' loses precision + +Task-number: QTBUG-34395 +Change-Id: Ibde75dd4b5536f3827bdf0ab02a15e93a1a8a4f0 +--- + src/3rdparty/angle/src/third_party/trace_event/trace_event.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/3rdparty/angle/src/third_party/trace_event/trace_event.h b/src/3rdparty/angle/src/third_party/trace_event/trace_event.h +index 113b126..72d354d 100644 +--- a/src/3rdparty/angle/src/third_party/trace_event/trace_event.h ++++ b/src/3rdparty/angle/src/third_party/trace_event/trace_event.h +@@ -589,7 +589,7 @@ const unsigned long long noEventId = 0; + class TraceID { + public: + explicit TraceID(const void* id, unsigned char* flags) : +- m_data(static_cast<unsigned long long>(reinterpret_cast<unsigned long>(id))) ++ m_data(reinterpret_cast<unsigned long long>(id)) + { + *flags |= TRACE_EVENT_FLAG_MANGLE_ID; + } +-- +1.8.3.msysgit.0 + diff --git a/src/angle/src/common/common.pri b/src/angle/src/common/common.pri index 12e26a9a68..58ad88673a 100644 --- a/src/angle/src/common/common.pri +++ b/src/angle/src/common/common.pri @@ -4,10 +4,10 @@ INCLUDEPATH += \ $$ANGLE_DIR/src \ $$ANGLE_DIR/include -LIBS = $$QMAKE_LIBS_CORE $$QMAKE_LIBS_GUI +LIBS_PRIVATE = $$QMAKE_LIBS_CORE $$QMAKE_LIBS_GUI # DirectX is included in the Windows 8 Kit, but everything else requires the DX SDK. -win32-msvc2012|winrt { +win32-msvc2012|win32-msvc2013|winrt { FXC = fxc.exe } else { DX_DIR = $$(DXSDK_DIR) @@ -36,7 +36,7 @@ win32-msvc2012|winrt { # Similarly we want the MinGW linker to use the import libraries shipped with the compiler # instead of those from the SDK which cause a crash on startup. - LIBS += -L\"$$DXLIB_DIR\" + LIBS_PRIVATE += -L\"$$DXLIB_DIR\" } } diff --git a/src/angle/src/libEGL/libEGL.pro b/src/angle/src/libEGL/libEGL.pro index 3781bd7868..b5854189f9 100644 --- a/src/angle/src/libEGL/libEGL.pro +++ b/src/angle/src/libEGL/libEGL.pro @@ -4,11 +4,11 @@ TARGET = $$qtLibraryTarget(libEGL) include(../common/common.pri) angle_d3d11 { - LIBS += -ld3d11 + LIBS_PRIVATE += -ld3d11 } else { - LIBS += -ld3d9 + LIBS_PRIVATE += -ld3d9 } -LIBS += -ldxguid -L$$QT_BUILD_TREE/lib -l$$qtLibraryTarget(libGLESv2) +LIBS_PRIVATE += -ldxguid -L$$QT_BUILD_TREE/lib -l$$qtLibraryTarget(libGLESv2) HEADERS += \ $$ANGLE_DIR/src/libEGL/Config.h \ diff --git a/src/angle/src/libGLESv2/libGLESv2.pro b/src/angle/src/libGLESv2/libGLESv2.pro index b39ce781e1..5b3a49ed56 100644 --- a/src/angle/src/libGLESv2/libGLESv2.pro +++ b/src/angle/src/libGLESv2/libGLESv2.pro @@ -8,18 +8,18 @@ INCLUDEPATH += $$OUT_PWD/.. $$ANGLE_DIR/src/libGLESv2 # Remember to adapt tools/configure/configureapp.cpp if the Direct X version changes. angle_d3d11 { - LIBS += -ldxgi -ld3d11 + LIBS_PRIVATE += -ldxgi -ld3d11 } else { - LIBS += -ld3d9 + LIBS_PRIVATE += -ld3d9 } -LIBS += -ldxguid +LIBS_PRIVATE += -ldxguid STATICLIBS = translator_common translator_hlsl preprocessor for(libname, STATICLIBS) { # Appends 'd' to the library for debug builds and builds up the fully # qualified path to pass to the linker. staticlib = $$QT_BUILD_TREE/lib/$${QMAKE_PREFIX_STATICLIB}$$qtLibraryTarget($$libname).$${QMAKE_EXTENSION_STATICLIB} - LIBS += $$staticlib + LIBS_PRIVATE += $$staticlib PRE_TARGETDEPS += $$staticlib } diff --git a/src/concurrent/concurrent.pro b/src/concurrent/concurrent.pro index 53b6bd0472..2b8fef2d6a 100644 --- a/src/concurrent/concurrent.pro +++ b/src/concurrent/concurrent.pro @@ -39,5 +39,5 @@ HEADERS += \ HEADERS += \ contains(QT_CONFIG, clock-gettime) { - linux-*|hpux-*|solaris-*:LIBS *= -lrt + linux-*|hpux-*|solaris-*: LIBS_PRIVATE *= -lrt } diff --git a/src/concurrent/doc/qtconcurrent.qdocconf b/src/concurrent/doc/qtconcurrent.qdocconf index 9d89192946..e45047cb51 100644 --- a/src/concurrent/doc/qtconcurrent.qdocconf +++ b/src/concurrent/doc/qtconcurrent.qdocconf @@ -2,7 +2,7 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf) project = QtConcurrent description = Qt Concurrent Reference Documentation -url = http://qt-project.org/doc/qt-$QT_VER/qtconcurrent +url = http://qt-project.org/doc/qt-$QT_VER version = $QT_VERSION examplesinstallpath = qtconcurrent diff --git a/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentfilter.cpp b/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentfilter.cpp index 7160f80b34..9afcdc9740 100644 --- a/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentfilter.cpp +++ b/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentfilter.cpp @@ -136,7 +136,7 @@ bool QString::contains(const QRegExp ®exp) const; //! [10] -boost::bind(&QString::contains, QRegExp("^\\S+$")); // matches strings without whitespace +std::bind(&QString::contains, QRegExp("^\\S+$")); // matches strings without whitespace //! [10] @@ -147,7 +147,7 @@ bool contains(const QString &string) //! [12] QStringList strings = ...; -boost::bind(static_cast<bool(QString::*)(const QRegExp&)>( &QString::contains ), QRegExp("..." )); +std::bind(static_cast<bool(QString::*)(const QRegExp&)>( &QString::contains ), QRegExp("..." )); //! [12] //! [13] diff --git a/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentmap.cpp b/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentmap.cpp index 756ca3902c..634c03e808 100644 --- a/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentmap.cpp +++ b/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentmap.cpp @@ -149,7 +149,7 @@ QImage QImage::scaledToWidth(int width, Qt::TransformationMode) const; //! [11] -boost::bind(&QImage::scaledToWidth, 100, Qt::SmoothTransformation) +std::bind(&QImage::scaledToWidth, 100, Qt::SmoothTransformation) //! [11] @@ -160,7 +160,7 @@ QImage scaledToWith(const QImage &image) //! [13] QList<QImage> images = ...; -QFuture<QImage> thumbnails = QtConcurrent::mapped(images, boost::bind(&QImage::scaledToWidth, 100 Qt::SmoothTransformation)); +QFuture<QImage> thumbnails = QtConcurrent::mapped(images, std::bind(&QImage::scaledToWidth, 100 Qt::SmoothTransformation)); //! [13] //! [14] diff --git a/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentrun.cpp b/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentrun.cpp index 7288fc642b..8922e41f34 100644 --- a/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentrun.cpp +++ b/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentrun.cpp @@ -93,6 +93,6 @@ future.waitForFinished(); //! [6] void someFunction(int arg1, double arg2); -QFuture<void> future = QtConcurrent::run(boost::bind(someFunction, 1, 2.0)); +QFuture<void> future = QtConcurrent::run(std::bind(someFunction, 1, 2.0)); ... //! [6] diff --git a/src/concurrent/qtconcurrentfilter.cpp b/src/concurrent/qtconcurrentfilter.cpp index 22a1243c18..ab0227983d 100644 --- a/src/concurrent/qtconcurrentfilter.cpp +++ b/src/concurrent/qtconcurrentfilter.cpp @@ -40,15 +40,10 @@ ****************************************************************************/ /*! - \headerfile <QtConcurrentFilter> + \page qtconcurrentfilter.html \title Concurrent Filter and Filter-Reduce \ingroup thread - \brief The <QtConcurrentFilter> header provides concurrent Filter and - Filter-Reduce. - - These functions are a part of the \l {Qt Concurrent} framework. - The QtConcurrent::filter(), QtConcurrent::filtered() and QtConcurrent::filteredReduced() functions filter items in a sequence such as a QList or a QVector in parallel. QtConcurrent::filter() modifies a @@ -56,6 +51,8 @@ containing the filtered content, and QtConcurrent::filteredReduced() returns a single result. + These functions are a part of the \l {Qt Concurrent} framework. + Each of the above functions have a blocking variant that returns the final result instead of a QFuture. You use them in the same way as the asynchronous variants. @@ -155,15 +152,11 @@ \section2 Using Bound Function Arguments - Note that Qt does not provide support for bound functions. This is - provided by 3rd party libraries like - \l{http://www.boost.org/libs/bind/bind.html}{Boost} or - \l{http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf} - {C++ TR1 Library Extensions}. - If you want to use a filter function takes more than one argument, you can - use boost::bind() or std::tr1::bind() to transform it onto a function that - takes one argument. + use std::bind() to transform it onto a function that takes one argument. If + C++11 support is not available, \l{http://www.boost.org/libs/bind/bind.html} + {boost::bind()} or \l{http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf} + {std::tr1::bind()} are suitable replacements. As an example, we use QString::contains(): @@ -177,7 +170,7 @@ \snippet code/src_concurrent_qtconcurrentfilter.cpp 10 - The return value from boost::bind() is a function object (functor) with + The return value from std::bind() is a function object (functor) with the following signature: \snippet code/src_concurrent_qtconcurrentfilter.cpp 11 @@ -190,7 +183,6 @@ /*! \fn QFuture<void> QtConcurrent::filter(Sequence &sequence, FilterFunction filterFunction) - \relates <QtConcurrentFilter> Calls \a filterFunction once for each item in \a sequence. If \a filterFunction returns \c true, the item is kept in \a sequence; @@ -199,7 +191,6 @@ /*! \fn QFuture<T> QtConcurrent::filtered(const Sequence &sequence, FilterFunction filterFunction) - \relates <QtConcurrentFilter> Calls \a filterFunction once for each item in \a sequence and returns a new Sequence of kept items. If \a filterFunction returns \c true, a copy of @@ -209,7 +200,6 @@ /*! \fn QFuture<T> QtConcurrent::filtered(ConstIterator begin, ConstIterator end, FilterFunction filterFunction) - \relates <QtConcurrentFilter> Calls \a filterFunction once for each item from \a begin to \a end and returns a new Sequence of kept items. If \a filterFunction returns \c true, a @@ -219,7 +209,6 @@ /*! \fn QFuture<T> QtConcurrent::filteredReduced(const Sequence &sequence, FilterFunction filterFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions) - \relates <QtConcurrentFilter> Calls \a filterFunction once for each item in \a sequence. If \a filterFunction returns \c true for an item, that item is then passed to @@ -236,7 +225,6 @@ /*! \fn QFuture<T> QtConcurrent::filteredReduced(ConstIterator begin, ConstIterator end, FilterFunction filterFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions) - \relates <QtConcurrentFilter> Calls \a filterFunction once for each item from \a begin to \a end. If \a filterFunction returns \c true for an item, that item is then passed to diff --git a/src/concurrent/qtconcurrentmap.cpp b/src/concurrent/qtconcurrentmap.cpp index da2a601ae2..fc904a4d59 100644 --- a/src/concurrent/qtconcurrentmap.cpp +++ b/src/concurrent/qtconcurrentmap.cpp @@ -68,14 +68,10 @@ */ /*! - \headerfile <QtConcurrentMap> + \page qtconcurrentmap.html \title Concurrent Map and Map-Reduce \ingroup thread - \brief The <QtConcurrentMap> header provides concurrent Map and MapReduce. - - These functions are a part of the \l {Qt Concurrent} framework. - The QtConcurrent::map(), QtConcurrent::mapped() and QtConcurrent::mappedReduced() functions run computations in parallel on the items in a sequence such as a QList or a QVector. QtConcurrent::map() @@ -83,6 +79,8 @@ sequence containing the modified content, and QtConcurrent::mappedReduced() returns a single result. + These functions are a part of the \l {Qt Concurrent} framework. + Each of the above functions has a blocking variant that returns the final result instead of a QFuture. You use them in the same way as the asynchronous variants. @@ -204,15 +202,11 @@ \section2 Using Bound Function Arguments - Note that Qt does not provide support for bound functions. This is - provided by 3rd party libraries like - \l{http://www.boost.org/libs/bind/bind.html}{Boost} or - \l{http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf}{C++ - TR1 Library Extensions}. - If you want to use a map function that takes more than one argument you can - use boost::bind() or std::tr1::bind() to transform it onto a function that - takes one argument. + use std::bind() to transform it onto a function that takes one argument. If + C++11 support is not available, \l{http://www.boost.org/libs/bind/bind.html} + {boost::bind()} or \l{http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf} + {std::tr1::bind()} are suitable replacements. As an example, we'll use QImage::scaledToWidth(): @@ -226,7 +220,7 @@ \snippet code/src_concurrent_qtconcurrentmap.cpp 11 - The return value from boost::bind() is a function object (functor) with + The return value from std::bind() is a function object (functor) with the following signature: \snippet code/src_concurrent_qtconcurrentmap.cpp 12 @@ -239,7 +233,6 @@ /*! \fn QFuture<void> QtConcurrent::map(Sequence &sequence, MapFunction function) - \relates <QtConcurrentMap> Calls \a function once for each item in \a sequence. The \a function is passed a reference to the item, so that any modifications done to the item @@ -248,7 +241,6 @@ /*! \fn QFuture<void> QtConcurrent::map(Iterator begin, Iterator end, MapFunction function) - \relates <QtConcurrentMap> Calls \a function once for each item from \a begin to \a end. The \a function is passed a reference to the item, so that any modifications @@ -257,7 +249,6 @@ /*! \fn QFuture<T> QtConcurrent::mapped(const Sequence &sequence, MapFunction function) - \relates <QtConcurrentMap> Calls \a function once for each item in \a sequence and returns a future with each mapped item as a result. You can use QFuture::const_iterator or @@ -266,7 +257,6 @@ /*! \fn QFuture<T> QtConcurrent::mapped(ConstIterator begin, ConstIterator end, MapFunction function) - \relates <QtConcurrentMap> Calls \a function once for each item from \a begin to \a end and returns a future with each mapped item as a result. You can use @@ -278,8 +268,6 @@ MapFunction mapFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions) - \relates <QtConcurrentMap> - Calls \a mapFunction once for each item in \a sequence. The return value of each \a mapFunction is passed to \a reduceFunction. @@ -293,8 +281,6 @@ ConstIterator end, MapFunction mapFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions) - \relates <QtConcurrentMap> - Calls \a mapFunction once for each item from \a begin to \a end. The return value of each \a mapFunction is passed to \a reduceFunction. @@ -361,8 +347,6 @@ /*! \fn T QtConcurrent::blockingMappedReduced(const Sequence &sequence, MapFunction mapFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions) - \relates <QtConcurrentMap> - Calls \a mapFunction once for each item in \a sequence. The return value of each \a mapFunction is passed to \a reduceFunction. @@ -378,8 +362,6 @@ /*! \fn T QtConcurrent::blockingMappedReduced(ConstIterator begin, ConstIterator end, MapFunction mapFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions) - \relates <QtConcurrentMap> - Calls \a mapFunction once for each item from \a begin to \a end. The return value of each \a mapFunction is passed to \a reduceFunction. diff --git a/src/concurrent/qtconcurrentmedian.h b/src/concurrent/qtconcurrentmedian.h index 29342e6402..b39b3ed32b 100644 --- a/src/concurrent/qtconcurrentmedian.h +++ b/src/concurrent/qtconcurrentmedian.h @@ -90,7 +90,7 @@ public: dirty = true; } - values[currentIndex] = qMove(value); + values[currentIndex] = value; } bool isMedianValid() const @@ -105,7 +105,7 @@ public: QVector<T> copy = values; typename QVector<T>::iterator begin = copy.begin(), mid = copy.begin() + bufferSize/2, end = copy.end(); std::nth_element(begin, mid, end); - currentMedian = qMove(*mid); + currentMedian = *mid; } return currentMedian; } diff --git a/src/concurrent/qtconcurrentrun.cpp b/src/concurrent/qtconcurrentrun.cpp index 4398e1a91f..c71fc9048f 100644 --- a/src/concurrent/qtconcurrentrun.cpp +++ b/src/concurrent/qtconcurrentrun.cpp @@ -40,19 +40,15 @@ ****************************************************************************/ /*! - \headerfile <QtConcurrentRun> - \title Asynchronous Run - - \brief The <QtConcurrentRun> header provides a way to run a function in a - separate thread. - + \page qtconcurrentrun.html + \title Concurrent Run \ingroup thread - This function is a part of the \l {Qt Concurrent} framework. - The QtConcurrent::run() function runs a function in a separate thread. The return value of the function is made available through the QFuture API. + This function is a part of the \l {Qt Concurrent} framework. + \section1 Running a Function in a Separate Thread To run a function in another thread, use QtConcurrent::run(): @@ -110,15 +106,12 @@ \section2 Using Bound Function Arguments - Note that Qt does not provide support for bound functions. This is - provided by 3rd party libraries like - \l{http://www.boost.org/libs/bind/bind.html}{Boost} or - \l{http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf} - {C++ TR1 Library Extensions}. + You can use std::bind() to \e bind a number of arguments to a function when + called. If C++11 support is not available, \l{http://www.boost.org/libs/bind/bind.html} + {boost::bind()} or \l{http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf} + {std::tr1::bind()} are suitable replacements. - You can use boost::bind() or std::tr1::bind() to \e bind a number of - arguments to a function when called. There are number of reasons for doing - this: + There are number of reasons for binding: \list \li To call a function that takes more than 5 arguments. @@ -136,7 +129,6 @@ /*! \fn QFuture<T> QtConcurrent::run(Function function, ...); - \relates <QtConcurrentRun> Runs \a function in a separate thread. The thread is taken from the global QThreadPool. Note that the function may not run immediately; the function diff --git a/src/corelib/Qt5CoreConfigExtras.cmake.in b/src/corelib/Qt5CoreConfigExtras.cmake.in index 2d87783107..9bda70ec07 100644 --- a/src/corelib/Qt5CoreConfigExtras.cmake.in +++ b/src/corelib/Qt5CoreConfigExtras.cmake.in @@ -51,8 +51,9 @@ set(Qt5Core_MOC_EXECUTABLE Qt5::moc) set(Qt5Core_RCC_EXECUTABLE Qt5::rcc) set_property(TARGET Qt5::Core PROPERTY INTERFACE_QT_MAJOR_VERSION 5) +set_property(TARGET Qt5::Core PROPERTY INTERFACE_QT_COORD_TYPE $$QT_COORD_TYPE) set_property(TARGET Qt5::Core APPEND PROPERTY - COMPATIBLE_INTERFACE_STRING QT_MAJOR_VERSION + COMPATIBLE_INTERFACE_STRING QT_MAJOR_VERSION QT_COORD_TYPE ) include(\"${CMAKE_CURRENT_LIST_DIR}/Qt5CoreConfigExtrasMkspecDir.cmake\") @@ -80,6 +81,12 @@ list(APPEND Qt5Core_COMPILE_DEFINITIONS QT_NAMESPACE=$$QT_NAMESPACE) set_property(TARGET Qt5::Core APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS QT_NAMESPACE=$$QT_NAMESPACE) !!ENDIF +!!IF !isEmpty(CMAKE_DISABLED_FEATURES) +set(Qt5_DISABLED_FEATURES + $$CMAKE_DISABLED_FEATURES +) +!!ENDIF + set_property(TARGET Qt5::Core APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS $<$<NOT:$<CONFIG:Debug>>:QT_NO_DEBUG>) !!IF contains(QT_CONFIG, reduce_exports) diff --git a/src/corelib/animation/qsequentialanimationgroup.cpp b/src/corelib/animation/qsequentialanimationgroup.cpp index 42debea782..1c84e3dbc9 100644 --- a/src/corelib/animation/qsequentialanimationgroup.cpp +++ b/src/corelib/animation/qsequentialanimationgroup.cpp @@ -303,8 +303,6 @@ QPauseAnimation *QSequentialAnimationGroup::insertPause(int index, int msecs) /*! \property QSequentialAnimationGroup::currentAnimation Returns the animation in the current time. - - \sa currentAnimationChanged() */ QAbstractAnimation *QSequentialAnimationGroup::currentAnimation() const { diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro index 1ed55bb0c8..b513149e7c 100644 --- a/src/corelib/corelib.pro +++ b/src/corelib/corelib.pro @@ -20,8 +20,7 @@ ANDROID_JAR_DEPENDENCIES = \ jar/QtAndroid.jar \ jar/QtAndroidAccessibility.jar ANDROID_LIB_DEPENDENCIES = \ - plugins/platforms/android/libqtforandroid.so \ - libs/libgnustl_shared.so + plugins/platforms/android/libqtforandroid.so ANDROID_BUNDLED_JAR_DEPENDENCIES = \ jar/QtAndroid-bundled.jar \ jar/QtAndroidAccessibility-bundled.jar @@ -49,7 +48,7 @@ mac|darwin { LIBS_PRIVATE += -framework CoreServices } LIBS_PRIVATE += -framework CoreFoundation - LIBS += -framework Foundation + LIBS_PRIVATE += -framework Foundation } win32:DEFINES-=QT_NO_CAST_TO_ASCII DEFINES += $$MODULE_DEFINES @@ -80,6 +79,9 @@ cmake_umbrella_config_version_file.input = $$PWD/../../mkspecs/features/data/cma cmake_umbrella_config_version_file.output = $$DESTDIR/cmake/Qt5/Qt5ConfigVersion.cmake load(cmake_functions) +load(qfeatures) + +CMAKE_DISABLED_FEATURES = $$join(QT_DISABLED_FEATURES, "$$escape_expand(\\n) ") CMAKE_HOST_DATA_DIR = $$cmakeRelativePath($$[QT_HOST_DATA/src], $$[QT_INSTALL_PREFIX]) contains(CMAKE_HOST_DATA_DIR, "^\\.\\./.*"):!isEmpty(CMAKE_HOST_DATA_DIR) { diff --git a/src/corelib/doc/images/thread_clock.png b/src/corelib/doc/images/thread_clock.png Binary files differdeleted file mode 100644 index b8a8aa0a39..0000000000 --- a/src/corelib/doc/images/thread_clock.png +++ /dev/null diff --git a/src/corelib/doc/images/threadsandobjects.png b/src/corelib/doc/images/threadsandobjects.png Binary files differdeleted file mode 100644 index 8357d2532a..0000000000 --- a/src/corelib/doc/images/threadsandobjects.png +++ /dev/null diff --git a/src/corelib/doc/images/threadvisual-example.png b/src/corelib/doc/images/threadvisual-example.png Binary files differdeleted file mode 100644 index 2a49874719..0000000000 --- a/src/corelib/doc/images/threadvisual-example.png +++ /dev/null diff --git a/src/corelib/doc/qtcore.qdocconf b/src/corelib/doc/qtcore.qdocconf index fdd46995c5..9ab66c6645 100644 --- a/src/corelib/doc/qtcore.qdocconf +++ b/src/corelib/doc/qtcore.qdocconf @@ -2,7 +2,7 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf) project = QtCore description = Qt Core Reference Documentation -url = http://qt-project.org/doc/qt-$QT_VER/qtcore +url = http://qt-project.org/doc/qt-$QT_VER version = $QT_VERSION examplesinstallpath = core @@ -26,7 +26,7 @@ qhp.QtCore.subprojects.classes.sortPages = true tagfile = ../../../doc/qtcore/qtcore.tags -depends += qtgui qtwidgets qtnetwork qtdoc qtquick qtlinguist qtdesigner +depends += qtgui qtwidgets qtnetwork qtdoc qtquick qtlinguist qtdesigner qtconcurrent qtxml headerdirs += .. diff --git a/src/corelib/doc/snippets/code/doc_src_resources.cpp b/src/corelib/doc/snippets/code/doc_src_resources.cpp index 482c25a222..8ac7b0e970 100644 --- a/src/corelib/doc/snippets/code/doc_src_resources.cpp +++ b/src/corelib/doc/snippets/code/doc_src_resources.cpp @@ -44,11 +44,24 @@ QResource::registerResource("/path/to/myresource.rcc"); //! [5] +MyClass::MyClass() : BaseClass() +{ + Q_INIT_RESOURCE(resources); + + QFile file("qrc:/myfile.dat"); + ... +} +//! [5] + + +//! [6] int main(int argc, char *argv[]) { QApplication app(argc, argv); Q_INIT_RESOURCE(graphlib); + + QFile file("qrc:/graph.png"); ... return app.exec(); } -//! [5] +//! [6] diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp index 003fce580b..9210d2737f 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp @@ -416,7 +416,7 @@ text.data(); // returns "Qt is great!" //! [46] QString tmp = "test"; QByteArray text = tmp.toLocal8Bit(); -char *data = new char[text.size()] +char *data = new char[text.size()]; strcpy(data, text.data()); delete [] data; //! [46] @@ -424,7 +424,7 @@ delete [] data; //! [47] QString tmp = "test"; QByteArray text = tmp.toLocal8Bit(); -char *data = new char[text.size() + 1] +char *data = new char[text.size() + 1]; strcpy(data, text.data()); delete [] data; //! [47] diff --git a/src/corelib/doc/snippets/qtracer/ftracer.cpp b/src/corelib/doc/snippets/qtracer/ftracer.cpp deleted file mode 100644 index b12e3ed9c3..0000000000 --- a/src/corelib/doc/snippets/qtracer/ftracer.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <unistd.h> - -#include <QCoreApplication> -#include <QLoggingCategory> - - -//![1] -QLoggingCategory theFooArea("foo"); -QLoggingCategory theBarArea("bar"); -QLoggingCategory theBazArea("baz"); -//![1] - -// Note: These locations are Ubuntu specific. - -// Note: To make the example work with user permissions, make sure -// the files are user-writable and the path leading there accessible. - -const char traceSwitch[] = "/sys/kernel/debug/tracing/tracing_on"; -const char traceSink[] = "/sys/kernel/debug/tracing/trace_marker"; - -// The base class only serves as a facility to share code -// between the "single line" data logging aspect and the -// scoped "measuring" aspect. - -// Both aspects and the base class could be combined into -// a single tracer serving both purposes, but are split -// here for clarity. - -// Error handling is left as an exercise. - -//![2] -class MyTracerBase : public QTracer -{ -public: - MyTracerBase() { - enable = ::open(traceSwitch, O_WRONLY); - marker = ::open(traceSink, O_WRONLY); - } - - ~MyTracerBase() { - ::close(enable); - ::close(marker); - } - -protected: - int enable; - int marker; -}; -//![2] - - -//![2] -class MyTracer : public MyTracerBase -{ -public: - void start() { ::write(marker, "B", 1); } - void end() { ::write(marker, "E", 1); } -}; -//![2] - - -//![3] -class MyDataLogger : public MyTracerBase -{ -public: - MyDataLogger() { - buf[0] = 0; - pos = 0; - } - - void record(int i) { pos += sprintf(buf + pos, "%d", i); } - void record(const char *msg) { pos += sprintf(buf + pos, "%s", msg); } - void end() { ::write(marker, buf, pos); pos = 0; } - -private: - char buf[100]; - int pos; -}; -//![3] - -// Simplest possible example for "measuring". -//![4] -int foo(int i) -{ - qCTraceGuard(theFooArea); - // Here could be some lengthy code. - return i * i; -} -//![4] - -// We can switch on/off tracing dynamically. -// The tracer will be temporarily switched off at the third call -// and re-enabled at the eighth. -//![5] -int bar(int i) -{ - static int n = 0; - ++n; - if (n == 3) - theBarArea.setEnabled(QtTraceMsg, false); - if (n == 8) - theBarArea.setEnabled(QtTraceMsg, true); - - qCTraceGuard(theBarArea); - return i * i; -} -//![5] - -// An example to create "complex" log messages. -//![6] -int baz(int i) -{ - qCTrace(theBazArea) << 32 << "some stuff"; - - return i * i; -} -//![6] - - - -//![7] -namespace { -static struct Init -{ - Init() { - tracer.addToCategory(theFooArea); - tracer.addToCategory(theBarArea); - logger.addToCategory(theBazArea); - } - - MyTracer tracer; - MyDataLogger logger; - -} initializer; -} -//![7] diff --git a/src/corelib/doc/snippets/qtracer/main.cpp b/src/corelib/doc/snippets/qtracer/main.cpp deleted file mode 100644 index 758a2bbdb8..0000000000 --- a/src/corelib/doc/snippets/qtracer/main.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -int foo(int i); -int bar(int i); -int baz(int i); - -int main() -{ - int s = 0; - for (int i = 0; i != 10; ++i) - s += foo(i); - - for (int i = 0; i != 10; ++i) - s += bar(i); - - for (int i = 0; i != 10; ++i) - s += baz(i); - - return s; -} - diff --git a/src/corelib/doc/snippets/qtracer/qtracer.pro b/src/corelib/doc/snippets/qtracer/qtracer.pro deleted file mode 100644 index 254e22be76..0000000000 --- a/src/corelib/doc/snippets/qtracer/qtracer.pro +++ /dev/null @@ -1,2 +0,0 @@ - -SOURCES += ftracer.cpp main.cpp diff --git a/src/corelib/doc/src/custom-types.qdoc b/src/corelib/doc/src/custom-types.qdoc index cbf347a2f7..ed846aee83 100644 --- a/src/corelib/doc/src/custom-types.qdoc +++ b/src/corelib/doc/src/custom-types.qdoc @@ -155,10 +155,9 @@ The Q_DECLARE_METATYPE() macro and qRegisterMetaType() function documentation contain more detailed information about their uses and limitations. - The \l{Custom Type Example}{Custom Type}, - \l{Custom Type Sending Example}{Custom Type Sending} - and \l{Queued Custom Type Example}{Queued Custom Type} examples show how to - implement a custom type with the features outlined in this document. + The \l{Custom Type Example}{Custom Type} and \l{Queued Custom Type Example} + {Queued Custom Type} examples show how to implement a custom type with the + features outlined in this document. The \l{Debugging Techniques} document provides an overview of the debugging mechanisms discussed above. diff --git a/src/corelib/doc/src/objectmodel/object.qdoc b/src/corelib/doc/src/objectmodel/object.qdoc index 89a781da39..8d24096b7a 100644 --- a/src/corelib/doc/src/objectmodel/object.qdoc +++ b/src/corelib/doc/src/objectmodel/object.qdoc @@ -46,7 +46,8 @@ \li queryable and designable \l{Qt's Property System}{object properties} \li powerful \l{The Event System}{events and event filters} - \li contextual \l{i18n}{string translation for internationalization} + \li contextual \l{Internationalization with Qt}{string translation for + internationalization} \li sophisticated interval driven \l {Timers}{timers} that make it possible to elegantly integrate many tasks in an event-driven GUI \li hierarchical and queryable \l{Object Trees & Ownership}{object diff --git a/src/corelib/doc/src/objectmodel/signalsandslots.qdoc b/src/corelib/doc/src/objectmodel/signalsandslots.qdoc index dd93b80cae..e894d547d0 100644 --- a/src/corelib/doc/src/objectmodel/signalsandslots.qdoc +++ b/src/corelib/doc/src/objectmodel/signalsandslots.qdoc @@ -275,7 +275,7 @@ and slot members, as well as pointers to these functions. The meta-object contains additional information such as the - object's \l{QObject::className()}{class name}. You can + object's \l{QMetaObject::className()}{class name}. You can also check if an object \l{QObject::inherits()}{inherits} a specific class, for example: diff --git a/src/corelib/doc/src/plugins-howto.qdoc b/src/corelib/doc/src/plugins-howto.qdoc index 2dbf1f8141..7565d610cc 100644 --- a/src/corelib/doc/src/plugins-howto.qdoc +++ b/src/corelib/doc/src/plugins-howto.qdoc @@ -35,10 +35,7 @@ These \l{Qt Core} classes deal with shared libraries, (e.g. .so and DLL files), and with Qt plugins. - See the \l{How to Create Qt Plugins} page for more information.. - - See also the \l{ActiveQt framework} for Windows. - + See the \l{How to Create Qt Plugins} page for more information. */ /*! diff --git a/src/corelib/doc/src/resource-system.qdoc b/src/corelib/doc/src/resource-system.qdoc index 5ef6bb285c..91ce8afcf8 100644 --- a/src/corelib/doc/src/resource-system.qdoc +++ b/src/corelib/doc/src/resource-system.qdoc @@ -184,15 +184,39 @@ path list is empty at startup; call QDir::addSearchPath() to add paths to it. - If you have resources in a static library, you might need to - force initialization of your resources by calling \l - Q_INIT_RESOURCE() with the base name of the \c .qrc file. For - example: + \section1 Using Resources in a Library + + If you have resources in a library, you need to force initialization + of your resources by calling \l Q_INIT_RESOURCE() with the base name + of the \c .qrc file. For example: \snippet code/doc_src_resources.cpp 5 + This ensures that the resources are linked into the final application + binary in the case of static linking. You should put the initialization + code close to where the resources are used in your library, so that + clients of your library will only link in the resources if they use + the feature of the library that depends on them. + + Note: As the resource initializers generated by rcc are declared in the + global namespace, your calls to \l Q_INIT_RESOURCE() also need to be done + outside of any namespace. + + If the library includes resources that are not used internally, but + instead exposed to clients of the library, the initialization needs + to happen in the application code. For example: + + \snippet code/doc_src_resources.cpp 6 + + As before, this ensures that the resources are linked into the final + application binary in the case of static linking, but also triggers + loading of the library in the case of dynamic linking, such as plugins. + Similarly, if you must unload a set of resources explicitly (because a plugin is being unloaded or the resources are not valid any longer), you can force removal of your resources by calling - Q_CLEANUP_RESOURCE() with the same base name as above. + \l Q_CLEANUP_RESOURCE() with the same base name as above. + + Note: The use of \l Q_INIT_RESOURCE() and \l Q_CLEANUP_RESOURCE() is + not necessary when the resource is built as part of the application. */ diff --git a/src/corelib/doc/src/threads-basics.qdoc b/src/corelib/doc/src/threads-basics.qdoc deleted file mode 100644 index 4f381421b4..0000000000 --- a/src/corelib/doc/src/threads-basics.qdoc +++ /dev/null @@ -1,365 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: http://www.gnu.org/copyleft/fdl.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \page thread-basics.html - \ingroup tutorials - \startpage {index.html}{Qt Reference Documentation} - - \title Threading Basics - \brief An introduction to threads - - \section1 What Are Threads? - - Threads are about doing things in parallel, just like processes. So how do - threads differ from processes? While you are making calculations on a - spreadsheet, there may also be a media player running on the same desktop - playing your favorite song. Here is an example of two processes working in - parallel: one running the spreadsheet program; one running a media player. - Multitasking is a well known term for this. A closer look at the media - player reveals that there are again things going on in parallel within one - single process. While the media player is sending music to the audio driver, - the user interface with all its bells and whistles is being constantly - updated. This is what threads are for -- concurrency within one single - process. - - So how is concurrency implemented? Parallel work on single core CPUs is an - illusion which is somewhat similar to the illusion of moving images in - cinema. - For processes, the illusion is produced by interrupting the processor's - work on one process after a very short time. Then the processor moves on to - the next process. In order to switch between processes, the current program - counter is saved and the next processor's program counter is loaded. This - is not sufficient because the same needs to be done with registers and - certain architecture and OS specific data. - - Just as one CPU can power two or more processes, it is also possible to let - the CPU run on two different code segments of one single process. When a - process starts, it always executes one code segment and therefore the - process is said to have one thread. However, the program may decide to - start a second thread. Then, two different code sequences are processed - simultaneously inside one process. Concurrency is achieved on single core - CPUs by repeatedly saving program counters and registers then loading the - next thread's program counters and registers. No cooperation from the - program is required to cycle between the active threads. A thread may be in - any state when the switch to the next thread occurs. - - The current trend in CPU design is to have several cores. A typical - single-threaded application can make use of only one core. However, a - program with multiple threads can be assigned to multiple cores, making - things happen in a truly concurrent way. As a result, distributing work - to more than one thread can make a program run much faster on multicore - CPUs because additional cores can be used. - - \section2 GUI Thread and Worker Thread - - As mentioned, each program has one thread when it is started. This thread - is called the "main thread" (also known as the "GUI thread" in Qt - applications). The Qt GUI must run in this thread. All widgets and several - related classes, for example QPixmap, don't work in secondary threads. - A secondary thread is commonly referred to as a "worker thread" because it - is used to offload processing work from the main thread. - - \section2 Simultaneous Access to Data - - Each thread has its own stack, which means each thread has its own call - history and local variables. Unlike processes, threads share the same - address space. The following diagram shows how the building blocks of - threads are located in memory. Program counter and registers of inactive - threads are typically kept in kernel space. There is a shared copy of the - code and a separate stack for each thread. - - \image threadvisual-example.png "Thread visualization" - - If two threads have a pointer to the same object, it is possible that both - threads will access that object at the same time and this can potentially - destroy the object's integrity. It's easy to imagine the many things that - can go wrong when two methods of the same object are executed - simultaneously. - - Sometimes it is necessary to access one object from different threads; - for example, when objects living in different threads need to communicate. - Since threads use the same address space, it is easier and faster for - threads to exchange data than it is for processes. Data does not have to be - serialized and copied. Passing pointers is possible, but there must be a - strict coordination of what thread touches which object. Simultaneous - execution of operations on one object must be prevented. There are several - ways of achieving this and some of them are described below. - - So what can be done safely? All objects created in a thread can be used - safely within that thread provided that other threads don't have references - to them and objects don't have implicit coupling with other threads. Such - implicit coupling may happen when data is shared between instances as with - static members, singletons or global data. Familiarize yourself with the - concept of \l{Reentrancy and Thread-Safety}{thread safe and reentrant} - classes and functions. - - \section1 Using Threads - - There are basically two use cases for threads: - - \list - \li Make processing faster by making use of multicore processors. - \li Keep the GUI thread or other time critical threads responsive by - offloading long lasting processing or blocking calls to other threads. - \endlist - - \section2 When to Use Alternatives to Threads - - Developers need to be very careful with threads. It is easy to start other - threads, but very hard to ensure that all shared data remains consistent. - Problems are often hard to find because they may only show up once in a - while or only on specific hardware configurations. Before creating threads - to solve certain problems, possible alternatives should be considered. - - \table - \header - \li Alternative - \li Comment - \row - \li QEventLoop::processEvents() - \li Calling QEventLoop::processEvents() repeatedly during a - time-consuming calculation prevents GUI blocking. However, this - solution doesn't scale well because the call to processEvents() may - occur too often, or not often enough, depending on hardware. - \row - \li QTimer - \li Background processing can sometimes be done conveniently using a - timer to schedule execution of a slot at some point in the future. - A timer with an interval of 0 will time out as soon as there are no - more events to process. - \row - \li QSocketNotifier QNetworkAccessManager QIODevice::readyRead() - \li This is an alternative to having one or multiple threads, each with - a blocking read on a slow network connection. As long as the - calculation in response to a chunk of network data can be executed - quickly, this reactive design is better than synchronous waiting in - threads. Reactive design is less error prone and energy efficient - than threading. In many cases there are also performance benefits. - \endtable - - In general, it is recommended to only use safe and tested paths and to - avoid introducing ad-hoc threading concepts. The QtConcurrent module provides an easy - interface for distributing work to all of the processor's cores. The - threading code is completely hidden in the QtConcurrent framework, so you - don't have to take care of the details. However, QtConcurrent can't be used - when communication with the running thread is needed, and it shouldn't be - used to handle blocking operations. - - \section2 Which Qt Thread Technology Should You Use? - - See the \l{Multithreading Technologies in Qt} page for an introduction to the - different approaches to multithreading to Qt, and for guidelines on how to - choose among them. - - - \section1 Qt Thread Basics - - The following sections describe how QObjects interact with threads, how - programs can safely access data from multiple threads, and how asynchronous - execution produces results without blocking a thread. - - \section2 QObject and Threads - - As mentioned above, developers must always be careful when calling objects' - methods from other threads. \l{QObject#Thread Affinity}{Thread affinity} - does not change this situation. - Qt documentation marks several methods as thread-safe. - \l{QCoreApplication::}{postEvent()} is a noteworthy example. A thread-safe - method may be called from different threads simultaneously. - - In cases where there is usually no concurrent access to methods, calling - non-thread-safe methods of objects in other threads may work thousands - of times before a concurrent access occurs, causing unexpected behavior. - Writing test code does not entirely ensure thread correctness, but it is - still important. - On Linux, Valgrind and Helgrind can help detect threading errors. - - \section2 Protecting the Integrity of Data - - When writing a multithread application, extra care must be taken to avoid - data corruption. See \l{Synchronizing Threads} for a discussion on how to - use threads safely. - - \section2 Dealing with Asynchronous Execution - - One way to obtain a worker thread's result is by waiting for the thread - to terminate. In many cases, however, a blocking wait isn't acceptable. The - alternative to a blocking wait are asynchronous result deliveries with - either posted events or queued signals and slots. This generates a certain - overhead because an operation's result does not appear on the next source - line, but in a slot located somewhere else in the source file. Qt - developers are used to working with this kind of asynchronous behavior - because it is much similar to the kind of event-driven programming used in - GUI applications. - - \section1 Examples - - This tutorial comes with examples for Qt's three basic ways of working with - threads. Two more examples show how to communicate with a running thread - and how a QObject can be placed in another thread, providing service to the - main thread. - - \list - \li Using QThread as shown \l{Qt thread basics}{above} - \li \l{Example 1: Using the Thread Pool}{Using the global QThreadPool} - \li \l{Example 2: Using QtConcurrent}{Using QtConcurrent} - \li \l{Example 3: Clock}{Communication with the GUI thread} - \li \l{Example 4: A Permanent Thread}{A permanent QObject in another thread - provides service to the main thread} - \endlist - - The following examples can all be compiled and run independently. The source can - be found in the examples directory: examples/tutorials/threads/ - - \section2 Example 1: Using the Thread Pool - - Creating and destroying threads frequently can be expensive. To avoid the - cost of thread creation, a thread pool can be used. A thread pool is a - place where threads can be parked and fetched. We can write the same - "hello thread" program as \l{Qt Thread Basics}{above} using the global - thread pool. We derive a class from QRunnable. The code we want to run in - another thread needs to be placed in the reimplemented QRunnable::run() - method. - - \snippet ../widgets/tutorials/threads/hellothreadpool/hellothreadpool.cpp 1 - - We instantiate Work in main(), locate the global thread pool and use the - QThreadPool::start() method. Now the thread pool runs our worker in another - thread. Using the thread pool has a performance advantage because threads - are not destroyed after they have finished running. They are kept in a pool - and wait to be used again later. - - \section2 Example 2: Using QtConcurrent - - \snippet ../widgets/tutorials/threads/helloconcurrent/helloconcurrent.cpp 1 - - We write a global function hello() to implement the work. QtConcurrent::run() - is used to run the function in another thread. The result is a QFuture. - QFuture provides a method called \l{QFuture::}{waitForFinished()}, which - blocks until the calculation is completed. The real power of QtConcurrent - becomes visible when data can be made available in a container. QtConcurrent - provides several functions that are able to process itemized data on all - available cores simultaneously. The use of QtConcurrent is very similar to - applying an STL algorithm to an STL container. - \l{examples-threadandconcurrent.html}{QtConcurrent Map} is a very short and - clear example about how a container of images can be scaled on all available - cores. The image scaling example uses the blocking variants of the functions - used. For every blocking function there is also a non-blocking, asynchronous - counterpart. Getting results asynchronously is implemented with QFuture and - QFutureWatcher. - - \section2 Example 3: Clock - - \image thread_clock.png "clock" - - We want to produce a clock application. The application has a GUI and a - worker thread. The worker thread checks every 10 milliseconds what time it - is. If the formatted time has changed, the result will be sent to the GUI - thread where it is displayed. - - Of course, this is an overly complicated way of designing a clock and, - actually, a separate thread is unnecessary. We would be better off placing - the timer in the main thread because the calculation made in the timer slot - is very short-lived. This example is purely for instructional use and shows - how to communicate from a worker thread to a GUI thread. Note that - communication in this direction is easy. We only need to add a signal - to QThread and make a queued signal/slot connection to the main thread. - Communication from the GUI to the worker thread is shown in the next - example. - - \snippet ../widgets/tutorials/threads/clock/main.cpp 1 - - We've connected the \c clockThread with the label. The connection must be a - queued signal-slot connection because we want to put the call in the event - loop. - - \snippet ../widgets/tutorials/threads/clock/clockthread.h 1 - - We have derived a class from QThread and declared the \c sendTime() signal. - - \snippet ../widgets/tutorials/threads/clock/clockthread.cpp 1 - - The trickiest part of this example is that the timer is connected to its - slot via a direct connection. A default connection would produce a queued - signal-slot connection because the connected objects live in different - threads; remember that QThread does not live in the thread it creates. - - Still it is safe to access ClockThread::timerHit() from the worker thread - because ClockThread::timerHit() is private and only touches local variables - and a private member that isn't touched by public methods. - QDateTime::currentDateTime() isn't marked as thread-safe in Qt - documentation, however we can get away with using it in this small - example because we know that the QDateTime::currentDateTime() static - method isn't used in any other threads. - - \section2 Example 4: A Permanent Thread - - This example shows how it is possible to have a QObject in a worker thread - that accepts requests from the GUI thread, does polling using a timer and - continuously reports results back to the GUI thread. The actual work - including the polling must be implemented in a class derived from QObject. - We have called this class \c WorkerObject in the code shown below. The - thread-specific code is hidden in a class called \c Thread, derived from - QThread. - \c Thread has two additional public members. The \c launchWorker() member - takes the worker object and moves it to another thread with a started event - loop. - The call blocks for a very short moment until the thread creation operation - is completed, allowing the worker object to be used again on the next line. - The \c Thread class's code is short but somewhat involved, so we only show - how to use the class. - - \snippet ../widgets/tutorials/threads/movedobject/main.cpp 1 - - QMetaObject::invokeMethod() calls a slot via the event loop. The worker - object's methods should not be called directly after the object has been - moved to another thread. We let the worker thread do some work and polling, - and use a timer to shut the application down after 3 seconds. Shutting the - worker down needs some care. We call \c{Thread::stop()} to exit the event - loop. We wait for the thread to terminate and, after this has occurred, we - delete the worker. - - \section1 Digging Deeper - - Threading is a very complicated subject. Qt offers more classes for - threading than we have presented in this tutorial. The following materials - can help you go into the subject in more depth: - - \list - \li Good video tutorials about threads with Qt can be found in the material - from the \l{Training Day at Qt Developer Days 2009}. - \li The \l{Thread Support in Qt} document is a good starting point into - the reference documentation. - \li Qt comes with several additional examples for - \l{Threading and Concurrent Programming Examples}{QThread and QtConcurrent}. - \li Several good books describe how to work with Qt threads. The most - extensive coverage can be found in \e{Advanced Qt Programming} by Mark - Summerfield, Prentice Hall - roughly 70 of 500 pages cover QThread and - QtConcurrent. - \endlist -*/ diff --git a/src/corelib/doc/src/threads.qdoc b/src/corelib/doc/src/threads.qdoc deleted file mode 100644 index 890fd9f6ff..0000000000 --- a/src/corelib/doc/src/threads.qdoc +++ /dev/null @@ -1,828 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: http://www.gnu.org/copyleft/fdl.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \group thread - \title Threading Classes - - These \l{Qt Core} classes provide threading support to applications. - The \l{Thread Support in Qt} page covers how to use these classes. -*/ - -/*! - \page threads.html - \title Thread Support in Qt - \ingroup qt-basic-concepts - \brief A detailed discussion of thread handling in Qt. - - \ingroup frameworks-technologies - - \nextpage Multithreading Technologies in Qt - - Qt provides thread support in the form of platform-independent - threading classes, a thread-safe way of posting events, and - signal-slot connections across threads. This makes it easy to - develop portable multithreaded Qt applications and take advantage - of multiprocessor machines. Multithreaded programming is also a - useful paradigm for performing time-consuming operations without - freezing the user interface of an application. - - Earlier versions of Qt offered an option to build the library - without thread support. Since Qt 4.0, threads are always enabled. - - \section1 Topics: - - \list - \li \l{Recommended Reading} - \li \l{The Threading Classes} - \li \l{Multithreading Technologies in Qt} - \li \l{Synchronizing Threads} - \li \l{Reentrancy and Thread-Safety} - \li \l{Threads and QObjects} - \li \l{Thread-Support in Qt Modules} - \endlist - - \section1 Recommended Reading - - This document is intended for an audience that has knowledge of, - and experience with, multithreaded applications. If you are new - to threading see our Recommended Reading list: - - \list - \li \l {http://www.amazon.com/Threads-Primer-Guide-Multithreaded-Programming/dp/0134436989}{Threads Primer: A Guide to Multithreaded Programming} - \li \l {http://www.amazon.com/Thread-Time-MultiThreaded-Programming-Guide/dp/0131900676}{Thread Time: The Multithreaded Programming Guide} - \li \l {http://www.amazon.com/Pthreads-Programming-Standard-Multiprocessing-Nutshell/dp/1565921151a}{Pthreads Programming: A POSIX Standard for Better Multiprocessing} - \li \l {http://www.amazon.com/WIN32-Multithreaded-Programming-Aaron-Cohen/dp/1565922964}{Win32 Multithreaded Programming} - \endlist - - \section1 The Threading Classes - - These classes are relevant to threaded applications. - - \annotatedlist thread - -\omit - \list - \li QThread provides the means to start a new thread. - \li QThreadStorage provides per-thread data storage. - \li QThreadPool manages a pool of threads that run QRunnable objects. - \li QRunnable is an abstract class representing a runnable object. - \li QMutex provides a mutual exclusion lock, or mutex. - \li QMutexLocker is a convenience class that automatically locks - and unlocks a QMutex. - \li QReadWriteLock provides a lock that allows simultaneous read access. - \li QReadLocker and QWriteLocker are convenience classes that automatically - lock and unlock a QReadWriteLock. - \li QSemaphore provides an integer semaphore (a generalization of a mutex). - \li QWaitCondition provides a way for threads to go to sleep until - woken up by another thread. - \li QAtomicInt provides atomic operations on integers. - \li QAtomicPointer provides atomic operations on pointers. - \endlist -\endomit - - \note Qt's threading classes are implemented with native threading APIs; - e.g., Win32 and pthreads. Therefore, they can be used with threads of the - same native API. -*/ - -/*! - \page threads-technologies.html - \title Multithreading Technologies in Qt - \ingroup qt-basic-concepts - \brief An overview and comparison of different ways to use threads in Qt. - - \ingroup frameworks-technologies - - \contentspage Thread Support in Qt - \previouspage Thread Support in Qt - \nextpage Synchronizing Threads - - Qt offers many classes and functions for working with threads. Below are - four different approaches that Qt programmers can use to implement - multithreaded applications. - - - \section1 QThread: Low-Level API with Optional Event Loops - - QThread is the foundation of all thread control in Qt. Each QThread - instance represents and controls one thread. - - QThread can either be instantiated directly or subclassed. Instantiating a - QThread provides a parallel event loop, allowing QObject slots to be invoked - in a secondary thread. Subclassing a QThread allows the application to initialize - the new thread before starting its event loop, or to run parallel code - without an event loop. - - See the \l{QThread}{QThread class reference} and the \l{Threading and - Concurrent Programming Examples}{threading examples} for demonstrations on - how to use QThread. - - - \section1 QThreadPool and QRunnable: Reusing Threads - - Creating and destroying threads frequently can be expensive. To reduce this - overhead, existing threads can be reused for new tasks. QThreadPool is a - collection of reuseable QThreads. - - To run code in one of a QThreadPool's threads, reimplement QRunnable::run() - and instantiate the subclassed QRunnable. Use QThreadPool::start() to put - the QRunnable in the QThreadPool's run queue. When a thread becomes available, - the code within QRunnable::run() will execute in that thread. - - Each Qt application has a global thread pool, which is accessible through - QThreadPool::globalInstance(). This global thread pool automatically maintains - an optimal number of threads based on the number of cores in the CPU. However, - a separate QThreadPool can be created and managed explicitly. - - - \section1 Qt Concurrent: Using a High-level API - - The \l{Qt Concurrent} module provides high-level functions that deal with some - common parallel computation patterns: map, filter, and reduce. Unlike using - QThread and QRunnable, these functions never require the use of \l{Synchronizing - Threads#Low-Level Synchronization Primitives}{low-level threading primitives} - such as mutexes or semaphores. Instead, they return a QFuture object which can - be used to retrieve the functions' results when they are ready. QFuture can - also be used to query computation progress and to pause/resume/cancel the - computation. For convenience, QFutureWatcher enables interactions with - \l{QFuture}s via signals and slots. - - \l{Qt Concurrent}'s map, filter and reduce algorithms automatically distribute - computation across all available processor cores, so applications written today - will continue to scale when deployed later on a system with more cores. - - This module also provides the QtConcurrent::run() function, which can run any - function in another thread. However, QtConcurrent::run() only supports a subset - of features available to the map, filter and reduce functions. The QFuture - can be used to retrieve the function's return value and to check if the thread - is running. However, a call to QtConcurrent::run() uses one thread only, cannot - be paused/resumed/canceled, and cannot be queried for progress. - - See the \l{Qt Concurrent} module documentation for details on the individual functions. - - - \section1 WorkerScript: Threading in QML - - The WorkerScript QML type lets JavaScript code run in parallel with the GUI - thread. - - Each WorkerScript instance can have one \c{.js} script attached to it. When - WorkerScript::sendMessage() is called, the script will run in a separate thread - (and a separate \l{QQmlContext}{QML context}). When the script finishes - running, it can send a reply back to the GUI thread which will invoke the - WorkerScript::onMessage() signal handler. - - Using a WorkerScript is similar to using a worker QObject that has been moved - to another thread. Data is transferred between threads via signals. - - See the WorkerScript documentation for details on how to implement the script, - and for a list of data types that can be passed between threads. - - - \section1 Choosing an Appropriate Approach - - As demonstrated above, Qt provides different solutions for developing threaded - applications. The right solution for a given application depends on the purpose - of the new thread and the thread's lifetime. Below is a comparison of Qt's - threading technologies, followed by recommended solutions for some example use cases. - - \section2 Comparison of Solutions - - \table - \header - \li Feature - \li QThread - \li QRunnable and QThreadPool - \li QtConcurrent::run() - \li Qt Concurrent (Map, Filter, Reduce) - \li WorkerScript - \row - \li API - \li C++ - \li C++ - \li C++ - \li C++ - \li QML - \row - \li Thread priority can be specified - \li Yes - \li Yes - \li - \li - \li - \row - \li Thread can run an event loop - \li Yes - \li - \li - \li - \li - \row - \li Thread can receive data updates through signals - \li Yes (received by a worker QObject) - \li - \li - \li - \li Yes (received by WorkerScript) - \row - \li Thread can be controlled using signals - \li Yes (received by QThread) - \li - \li - \li Yes (received by QFutureWatcher) - \li - \row - \li Thread can be monitored through a QFuture - \li - \li - \li Partially - \li Yes - \li - \row - \li Built-in ability to pause/resume/cancel - \li - \li - \li - \li Yes - \li - \endtable - - - \section2 Example Use Cases - - \table - \header - \li Lifetime of thread - \li Operation - \li Solution - \row - \li One call - \li Run a new linear function within another thread, optionally with progress - updates during the run. - \li Qt provides different solutions: - \list - \li Place the function in a reimplementation of QThread::run() and - start the QThread. Emit signals to update progress. OR - \li Place the function in a reimplementation of QRunnable::run() and - add the QRunnable to a QThreadPool. Write to a \l{Synchronizing - Threads}{thread-safe variable} to update progress. OR - \li Run the function using QtConcurrent::run(). Write to a \l{Synchronizing - Threads}{thread-safe variable} to update progress. - \endlist - \row - \li One call - \li Run an existing function within another thread and get its return value. - \li Run the function using QtConcurrent::run(). Have a QFutureWatcher emit - the \l{QFutureWatcher::}{finished()} signal when the function has - returned, and call QFutureWatcher::result() to get the function's return - value. - \row - \li One call - \li Perform an operation on all items of a container, using all available - cores. For example, producing thumbnails from a list of images. - \li Use Qt Concurrent's \l{QtConcurrent::}{filter()} function to select - container elements, and the \l{QtConcurrent::}{map()} function to apply - an operation to each element. To fold the output into a single result, - use \l{QtConcurrent::}{filteredReduced()} and - \l{QtConcurrent::}{mappedReduced()} instead. - \row - \li One call/Permanent - \li Perfrom a long computation in a pure QML application, and update the GUI - when the results are ready. - \li Place the computation code in a \c{.js} script and attach it to a - WorkerScript instance. Call \l{WorkerScript::}{sendMessage()} to start the - computation in a new thread. Let the script call WorkerScript::sendMessage() - too, to pass the result back to the GUI thread. Handle the result in - \l{WorkerScript::}{onMessage} and update the GUI there. - \row - \li Permanent - \li Have an object living in another thread that can perform different - tasks upon request and/or can receive new data to work with. - \li Subclass a QObject to create a worker. Instantiate this worker object - and a QThread. Move the worker to the new thread. Send commands or - data to the worker object over queued signal-slot connections. - \row - \li Permanent - \li Repeatedly perform an expensive operation in another thread, where the - thread does not need to receive any signals or events. - \li Write the infinite loop directly within a reimplementation of QThread::run(). - Start the thread without an event loop. Let the thread emit signals to - send data back to the GUI thread. - \endtable -*/ - -/*! - \page threads-synchronizing.html - \title Synchronizing Threads - - \previouspage Multithreading Technologies in Qt - \contentspage Thread Support in Qt - \nextpage Reentrancy and Thread-Safety - - While the purpose of threads is to allow code to run in parallel, - there are times where threads must stop and wait for other - threads. For example, if two threads try to write to the same - variable simultaneously, the result is undefined. The principle of - forcing threads to wait for one another is called \e{mutual exclusion}. - It is a common technique for protecting shared resources such as data. - - Qt provides low-level primitives as well as high-level mechanisms - for synchronizing threads. - - \section1 Low-Level Synchronization Primitives - - QMutex is the basic class for enforcing mutual exclusion. A thread - locks a mutex in order to gain access to a shared resource. If a second - thread tries to lock the mutex while it is already locked, the second - thread will be put to sleep until the first thread completes its task - and unlocks the mutex. - - QReadWriteLock is similar to QMutex, except that it distinguishes - between "read" and "write" access. When a piece of data is not being - written to, it is safe for multiple threads to read from it simultaneously. - A QMutex forces multiple readers to take turns to read shared data, but a - QReadWriteLock allows simultaneous reading, thus improving parallelism. - - QSemaphore is a generalization of QMutex that protects a certain - number of identical resources. In contrast, a QMutex protects - exactly one resource. The \l{Semaphores Example} shows a typical application - of semaphores: synchronizing access to a circular buffer between a producer - and a consumer. - - QWaitCondition synchronizes threads not by enforcing mutual exclusion but by - providing a \e{condition variable}. While the other primitives make threads - wait until a resource is unlocked, QWaitCondition makes threads wait until a - particular condition has been met. To allow the waiting threads to proceed, - call \l{QWaitCondition::wakeOne()}{wakeOne()} to wake one randomly - selected thread or \l{QWaitCondition::wakeAll()}{wakeAll()} to wake them all - simultaneously. The \l{Wait Conditions Example} shows how to solve the - producer-consumer problem using QWaitCondition instead of QSemaphore. - - \note Qt's synchronization classes rely on the use of properly - aligned pointers. For instance, you cannot use packed classes with - MSVC. - - These synchronization classes can be used to make a method thread safe. - However, doing so incurs a performance penalty, which is why most Qt methods - are not made thread safe. - - \section2 Risks - - If a thread locks a resource but does not unlock it, the application may - freeze because the resource will become permanently unavailable to other threads. - This can happen, for example, if a an exception is thrown and forces the current - function to return without releasing its lock. - - Another similar scenario is a \e{deadlock}. For example, suppose that - thread A is waiting for thread B to unlock a resource. If thread B is also - waiting for thread A to unlock a different resource, then both threads will - end up waiting forever, so the application will freeze. - - \section2 Convenience classes - - QMutexLocker, QReadLocker and QWriteLocker are convenience classes that make it - easier to use QMutex and QReadWriteLock. They lock a resource when they are - constructed, and automatically unlock it when they are destroyed. They are - designed to simplify code that use QMutex and QReadWriteLocker, thus reducing - the chances that a resource becomes permanently locked by accident. - - \section1 High-Level Event Queues - - Qt's \l{The Event System}{event system} is very useful for inter-thread - communication. Every thread may have its own event loop. To call a slot (or - any \l{Q_INVOKABLE}{invokable} method) in another thread, place that call in - the target thread's event loop. This lets the target thread finish its current - task before the slot starts running, while the original thread continues - running in parallel. - - To place an invocation in an event loop, make a queued \l{Signals & Slots} - {signal-slot} connection. Whenever the signal is emitted, its arguments will - be recorded by the event system. The thread that the signal receiver - \l{QObject#Thread Affinity}{lives in} will then run the slot. Alternatively, - call QMetaObject::invokeMethod() to achieve the same effect without signals. - In both cases, a \l{Qt::QueuedConnection}{queued connection} must be used - because a \l{Qt::DirectConnection}{direct connection} bypasses the event - system and runs the method immediately in the current thread. - - There is no risk of deadlocks when using the event system for thread - synchronization, unlike using low-level primitives. However, the event system - does not enforce mutual exclusion. If invokable methods access shared data, - they must still be protected with low-level primitives. - - Having said that, Qt's event system, along with \l{Implicit Sharing}{implicitly - shared} data structures, offers an alternative to traditional thread locking. - If signals and slots are used exclusively and no variables are shared between - threads, a multithreaded program can do without low-level primitives altogether. - - \sa QThread::exec(), {Threads and QObjects} -*/ - -/*! - \page threads-reentrancy.html - \title Reentrancy and Thread-Safety - - \keyword reentrant - \keyword thread-safe - - \previouspage Synchronizing Threads - \contentspage Thread Support in Qt - \nextpage Threads and QObjects - - Throughout the documentation, the terms \e{reentrant} and - \e{thread-safe} are used to mark classes and functions to indicate - how they can be used in multithread applications: - - \list - \li A \e thread-safe function can be called simultaneously from - multiple threads, even when the invocations use shared data, - because all references to the shared data are serialized. - \li A \e reentrant function can also be called simultaneously from - multiple threads, but only if each invocation uses its own data. - \endlist - - Hence, a \e{thread-safe} function is always \e{reentrant}, but a - \e{reentrant} function is not always \e{thread-safe}. - - By extension, a class is said to be \e{reentrant} if its member - functions can be called safely from multiple threads, as long as - each thread uses a \e{different} instance of the class. The class - is \e{thread-safe} if its member functions can be called safely - from multiple threads, even if all the threads use the \e{same} - instance of the class. - - \note Qt classes are only documented as \e{thread-safe} if they - are intended to be used by multiple threads. If a function is not - marked as thread-safe or reentrant, it should not be used from - different threads. If a class is not marked as thread-safe or - reentrant then a specific instance of that class should not be - accessed from different threads. - - \section1 Reentrancy - - C++ classes are often reentrant, simply because they only access - their own member data. Any thread can call a member function on an - instance of a reentrant class, as long as no other thread can call - a member function on the \e{same} instance of the class at the - same time. For example, the \c Counter class below is reentrant: - - \snippet threads/threads.cpp 3 - \snippet threads/threads.cpp 4 - - The class isn't thread-safe, because if multiple threads try to - modify the data member \c n, the result is undefined. This is - because the \c ++ and \c -- operators aren't always atomic. - Indeed, they usually expand to three machine instructions: - - \list 1 - \li Load the variable's value in a register. - \li Increment or decrement the register's value. - \li Store the register's value back into main memory. - \endlist - - If thread A and thread B load the variable's old value - simultaneously, increment their register, and store it back, they - end up overwriting each other, and the variable is incremented - only once! - - \section1 Thread-Safety - - Clearly, the access must be serialized: Thread A must perform - steps 1, 2, 3 without interruption (atomically) before thread B - can perform the same steps; or vice versa. An easy way to make - the class thread-safe is to protect all access to the data - members with a QMutex: - - \snippet threads/threads.cpp 5 - \snippet threads/threads.cpp 6 - - The QMutexLocker class automatically locks the mutex in its - constructor and unlocks it when the destructor is invoked, at the - end of the function. Locking the mutex ensures that access from - different threads will be serialized. The \c mutex data member is - declared with the \c mutable qualifier because we need to lock - and unlock the mutex in \c value(), which is a const function. - - \section1 Notes on Qt Classes - - Many Qt classes are \e{reentrant}, but they are not made - \e{thread-safe}, because making them thread-safe would incur the - extra overhead of repeatedly locking and unlocking a QMutex. For - example, QString is reentrant but not thread-safe. You can safely - access \e{different} instances of QString from multiple threads - simultaneously, but you can't safely access the \e{same} instance - of QString from multiple threads simultaneously (unless you - protect the accesses yourself with a QMutex). - - Some Qt classes and functions are thread-safe. These are mainly - the thread-related classes (e.g. QMutex) and fundamental functions - (e.g. QCoreApplication::postEvent()). - - \note Terminology in the multithreading domain isn't entirely - standardized. POSIX uses definitions of reentrant and thread-safe - that are somewhat different for its C APIs. When using other - object-oriented C++ class libraries with Qt, be sure the - definitions are understood. -*/ - -/*! - \page threads-qobject.html - \title Threads and QObjects - - \previouspage Reentrancy and Thread Safety - \contentspage Thread Support in Qt - \nextpage Thread-Support in Qt Modules - - QThread inherits QObject. It emits signals to indicate that the - thread started or finished executing, and provides a few slots as - well. - - More interesting is that \l{QObject}s can be used in multiple - threads, emit signals that invoke slots in other threads, and - post events to objects that "live" in other threads. This is - possible because each thread is allowed to have its own event - loop. - - \section1 QObject Reentrancy - - QObject is reentrant. Most of its non-GUI subclasses, such as - QTimer, QTcpSocket, QUdpSocket and QProcess, are also - reentrant, making it possible to use these classes from multiple - threads simultaneously. Note that these classes are designed to be - created and used from within a single thread; creating an object - in one thread and calling its functions from another thread is not - guaranteed to work. There are three constraints to be aware of: - - \list - \li \e{The child of a QObject must always be created in the thread - where the parent was created.} This implies, among other - things, that you should never pass the QThread object (\c - this) as the parent of an object created in the thread (since - the QThread object itself was created in another thread). - - \li \e{Event driven objects may only be used in a single thread.} - Specifically, this applies to the \l{timers.html}{timer - mechanism} and the \l{QtNetwork}{network module}. For example, - you cannot start a timer or connect a socket in a thread that - is not the \l{QObject::thread()}{object's thread}. - - \li \e{You must ensure that all objects created in a thread are - deleted before you delete the QThread.} This can be done - easily by creating the objects on the stack in your - \l{QThread::run()}{run()} implementation. - \endlist - - Although QObject is reentrant, the GUI classes, notably QWidget - and all its subclasses, are not reentrant. They can only be used - from the main thread. As noted earlier, QCoreApplication::exec() - must also be called from that thread. - - In practice, the impossibility of using GUI classes in other - threads than the main thread can easily be worked around by - putting time-consuming operations in a separate worker thread and - displaying the results on screen in the main thread when the - worker thread is finished. This is the approach used for - implementing the \l{threads/mandelbrot}{Mandelbrot} and - the \l{network/blockingfortuneclient}{Blocking Fortune Client} - example. - - \section1 Per-Thread Event Loop - - Each thread can have its own event loop. The initial thread - starts its event loops using QCoreApplication::exec(); other - threads can start an event loop using QThread::exec(). Like - QCoreApplication, QThread provides an - \l{QThread::exit()}{exit(int)} function and a - \l{QThread::quit()}{quit()} slot. - - An event loop in a thread makes it possible for the thread to use - certain non-GUI Qt classes that require the presence of an event - loop (such as QTimer, QTcpSocket, and QProcess). It also makes it - possible to connect signals from any threads to slots of a - specific thread. This is explained in more detail in the - \l{Signals and Slots Across Threads} section below. - - \image threadsandobjects.png Threads, objects, and event loops - - A QObject instance is said to \e live in the thread in which it - is created. Events to that object are dispatched by that thread's - event loop. The thread in which a QObject lives is available using - QObject::thread(). - - Note that for QObjects that are created before QApplication, - QObject::thread() returns zero. This means that the main thread - will only handle posted events for these objects; other event - processing is not done at all for objects with no thread. Use the - QObject::moveToThread() function to change the thread affinity for - an object and its children (the object cannot be moved if it has a - parent). - - Calling \c delete on a QObject from a thread other than the one - that \e owns the object (or accessing the object in other ways) is - unsafe, unless you guarantee that the object isn't processing - events at that moment. Use QObject::deleteLater() instead, and a - \l{QEvent::DeferredDelete}{DeferredDelete} event will be posted, - which the event loop of the object's thread will eventually pick - up. By default, the thread that \e owns a QObject is the thread - that \e creates the QObject, but not after QObject::moveToThread() - has been called. - - If no event loop is running, events won't be delivered to the - object. For example, if you create a QTimer object in a thread but - never call \l{QThread::exec()}{exec()}, the QTimer will never emit - its \l{QTimer::timeout()}{timeout()} signal. Calling - \l{QObject::deleteLater()}{deleteLater()} won't work - either. (These restrictions apply to the main thread as well.) - - You can manually post events to any object in any thread at any - time using the thread-safe function - QCoreApplication::postEvent(). The events will automatically be - dispatched by the event loop of the thread where the object was - created. - - Event filters are supported in all threads, with the restriction - that the monitoring object must live in the same thread as the - monitored object. Similarly, QCoreApplication::sendEvent() - (unlike \l{QCoreApplication::postEvent()}{postEvent()}) can only - be used to dispatch events to objects living in the thread from - which the function is called. - - \section1 Accessing QObject Subclasses from Other Threads - - QObject and all of its subclasses are not thread-safe. This - includes the entire event delivery system. It is important to keep - in mind that the event loop may be delivering events to your - QObject subclass while you are accessing the object from another - thread. - - If you are calling a function on an QObject subclass that doesn't - live in the current thread and the object might receive events, - you must protect all access to your QObject subclass's internal - data with a mutex; otherwise, you may experience crashes or other - undesired behavior. - - Like other objects, QThread objects live in the thread where the - object was created -- \e not in the thread that is created when - QThread::run() is called. It is generally unsafe to provide slots - in your QThread subclass, unless you protect the member variables - with a mutex. - - On the other hand, you can safely emit signals from your - QThread::run() implementation, because signal emission is - thread-safe. - - \section1 Signals and Slots Across Threads - - Qt supports these signal-slot connection types: - - \list - - \li \l{Qt::AutoConnection}{Auto Connection} (default) If the signal is - emitted in the thread which the receiving object has affinity then - the behavior is the same as the Direct Connection. Otherwise, - the behavior is the same as the Queued Connection." - - \li \l{Qt::DirectConnection}{Direct Connection} The slot is invoked - immediately, when the signal is emitted. The slot is executed - in the emitter's thread, which is not necessarily the - receiver's thread. - - \li \l{Qt::QueuedConnection}{Queued Connection} The slot is invoked - when control returns to the event loop of the receiver's - thread. The slot is executed in the receiver's thread. - - \li \l{Qt::BlockingQueuedConnection}{Blocking Queued Connection} - The slot is invoked as for the Queued Connection, except the - current thread blocks until the slot returns. \note Using this - type to connect objects in the same thread will cause deadlock. - - \li \l{Qt::UniqueConnection}{Unique Connection} The behavior is the - same as the Auto Connection, but the connection is made only if - it does not duplicate an existing connection. i.e., if the same - signal is already connected to the same slot for the same pair - of objects, then the connection is not made and connect() - returns \c false. - - \endlist - - The connection type can be specified by passing an additional - argument to \l{QObject::connect()}{connect()}. Be aware that - using direct connections when the sender and receiver live in - different threads is unsafe if an event loop is running in the - receiver's thread, for the same reason that calling any function - on an object living in another thread is unsafe. - - QObject::connect() itself is thread-safe. - - The \l{threads/mandelbrot}{Mandelbrot} example uses a queued - connection to communicate between a worker thread and the main - thread. To avoid freezing the main thread's event loop (and, as a - consequence, the application's user interface), all the - Mandelbrot fractal computation is done in a separate worker - thread. The thread emits a signal when it is done rendering the - fractal. - - Similarly, the \l{network/blockingfortuneclient}{Blocking Fortune - Client} example uses a separate thread for communicating with - a TCP server asynchronously. -*/ - -/*! - \page threads-modules.html - \title Thread-Support in Qt Modules - - \previouspage Threads and QObjects - \contentspage Thread Support in Qt - - \section1 Threads and the SQL Module - - A connection can only be used from within the thread that created it. - Moving connections between threads or creating queries from a different - thread is not supported. - - In addition, the third party libraries used by the QSqlDrivers can impose - further restrictions on using the SQL Module in a multithreaded program. - Consult the manual of your database client for more information - - \section1 Painting in Threads - - QPainter can be used in a thread to paint onto QImage, QPrinter, and - QPicture paint devices. Painting onto QPixmaps and QWidgets is \e not - supported. On Mac OS X the automatic progress dialog will not be - displayed if you are printing from outside the GUI thread. - - Any number of threads can paint at any given time, however only - one thread at a time can paint on a given paint device. In other - words, two threads can paint at the same time if each paints onto - separate QImages, but the two threads cannot paint onto the same - QImage at the same time. - - \section1 Threads and Rich Text Processing - - The QTextDocument, QTextCursor, and \l{richtext.html}{all related classes} are reentrant. - - Note that a QTextDocument instance created in the GUI thread may - contain QPixmap image resources. Use QTextDocument::clone() to - create a copy of the document, and pass the copy to another thread for - further processing (such as printing). - - \section1 Threads and the SVG module - - The QSvgGenerator and QSvgRenderer classes in the QtSvg module - are reentrant. - - \section1 Threads and Implicitly Shared Classes - - Qt uses an optimization called \l{implicit sharing} for many of - its value class, notably QImage and QString. Beginning with Qt 4, - implicit shared classes can safely be copied across threads, like - any other value classes. They are fully - \l{Reentrancy and Thread-Safety}{reentrant}. The implicit sharing - is really \e implicit. - - In many people's minds, implicit sharing and multithreading are - incompatible concepts, because of the way the reference counting - is typically done. Qt, however, uses atomic reference counting to - ensure the integrity of the shared data, avoiding potential - corruption of the reference counter. - - Note that atomic reference counting does not guarantee - \l{Reentrancy and Thread-Safety}{thread-safety}. Proper locking should be used - when sharing an instance of an implicitly shared class between - threads. This is the same requirement placed on all - \l{Reentrancy and Thread-Safety}{reentrant} classes, shared or not. Atomic reference - counting does, however, guarantee that a thread working on its - own, local instance of an implicitly shared class is safe. We - recommend using \l{Signals and Slots Across Threads}{signals and - slots} to pass data between threads, as this can be done without - the need for any explicit locking. - - To sum it up, implicitly shared classes in Qt 4 are really \e - implicitly shared. Even in multithreaded applications, you can - safely use them as if they were plain, non-shared, reentrant - value-based classes. -*/ diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri index a0842a946d..fd031469f6 100644 --- a/src/corelib/global/global.pri +++ b/src/corelib/global/global.pri @@ -31,6 +31,7 @@ INCLUDEPATH += $$QT_BUILD_TREE/src/corelib/global # configure creates these, not syncqt, so we need to manually inject them qconfig_h_files = \ + $$OUT_PWD/global/qfeatures.h \ $$OUT_PWD/global/qconfig.h \ $$QT_BUILD_TREE/include/QtCore/QtConfig targ_headers.files += $$qconfig_h_files diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 102a6487ee..2b957782e8 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -470,6 +470,7 @@ * N2659 Q_COMPILER_THREAD_LOCAL * N2765 Q_COMPILER_UDL * N2442 Q_COMPILER_UNICODE_STRINGS + * N2640 Q_COMPILER_UNIFORM_INIT * N2544 Q_COMPILER_UNRESTRICTED_UNIONS * N1653 Q_COMPILER_VARIADIC_MACROS * N2242 N2555 Q_COMPILER_VARIADIC_TEMPLATES @@ -507,6 +508,7 @@ // constexpr support is only partial //# define Q_COMPILER_CONSTEXPR # define Q_COMPILER_INITIALIZER_LISTS +# define Q_COMPILER_UNIFORM_INIT # define Q_COMPILER_NOEXCEPT # endif # if __INTEL_COMPILER >= 1400 @@ -581,6 +583,7 @@ # endif # if __has_feature(cxx_generalized_initializers) # define Q_COMPILER_INITIALIZER_LISTS +# define Q_COMPILER_UNIFORM_INIT /* both covered by this feature macro, according to docs */ # endif # if __has_feature(cxx_lambdas) # define Q_COMPILER_LAMBDA @@ -653,6 +656,7 @@ # define Q_COMPILER_DELETE_MEMBERS # define Q_COMPILER_EXTERN_TEMPLATES # define Q_COMPILER_INITIALIZER_LISTS +# define Q_COMPILER_UNIFORM_INIT # define Q_COMPILER_UNICODE_STRINGS # define Q_COMPILER_VARIADIC_TEMPLATES # endif @@ -726,8 +730,9 @@ # define Q_COMPILER_DECLTYPE # define Q_COMPILER_RVALUE_REFS # define Q_COMPILER_STATIC_ASSERT -// MSVC has std::initilizer_list, but does not support the braces initialization +// MSVC's library has std::initilizer_list, but the compiler does not support the braces initialization //# define Q_COMPILER_INITIALIZER_LISTS +//# define Q_COMPILER_UNIFORM_INIT # endif # if _MSC_VER >= 1700 /* C++11 features supported in VC11 = VC2012: */ @@ -738,6 +743,20 @@ # define Q_COMPILER_CLASS_ENUM # define Q_COMPILER_ATOMICS # endif /* VC 11 */ +# if _MSC_VER >= 1800 + /* C++11 features in VC12 = VC2013 */ +# define Q_COMPILER_DEFAULT_MEMBERS +# define Q_COMPILER_DELETE_MEMBERS +# define Q_COMPILER_DELEGATING_CONSTRUCTORS +# define Q_COMPILER_EXPLICIT_CONVERSIONS +# define Q_COMPILER_NONSTATIC_MEMBER_INIT +# define Q_COMPILER_INITIALIZER_LISTS +// implemented in principle, but has a bug that makes it unusable: http://connect.microsoft.com/VisualStudio/feedback/details/802058/c-11-unified-initialization-fails-with-c-style-arrays +// #define Q_COMPILER_UNIFORM_INIT +# define Q_COMPILER_RAW_STRINGS +# define Q_COMPILER_TEMPLATE_ALIAS +# define Q_COMPILER_VARIADIC_TEMPLATES +# endif /* VC 12 */ #endif /* Q_CC_MSVC */ #ifdef __cplusplus diff --git a/src/corelib/global/qconfig-large.h b/src/corelib/global/qconfig-large.h index 584be07067..0c1fcbf7da 100644 --- a/src/corelib/global/qconfig-large.h +++ b/src/corelib/global/qconfig-large.h @@ -56,11 +56,6 @@ # define QT_NO_PROGRESSDIALOG #endif -/* Fonts */ -#ifndef QT_NO_QWS_QPF -# define QT_NO_QWS_QPF -#endif - /* Images */ #ifndef QT_NO_IMAGEFORMAT_BMP # define QT_NO_IMAGEFORMAT_BMP @@ -76,9 +71,6 @@ #ifndef QT_NO_TRANSLATION # define QT_NO_TRANSLATION #endif -#ifndef QT_NO_TRANSLATION_UTF8 -# define QT_NO_TRANSLATION_UTF8 -#endif /* ItemViews */ #ifndef QT_NO_TABLEVIEW @@ -101,23 +93,14 @@ #ifndef QT_NO_PROPERTIES # define QT_NO_PROPERTIES #endif -#ifndef QT_NO_SOUND -# define QT_NO_SOUND -#endif /* Networking */ -#ifndef QT_NO_HOSTINFO -# define QT_NO_HOSTINFO -#endif #ifndef QT_NO_HTTP # define QT_NO_HTTP #endif #ifndef QT_NO_UDPSOCKET # define QT_NO_UDPSOCKET #endif -#ifndef QT_NO_URLINFO -# define QT_NO_URLINFO -#endif #ifndef QT_NO_FTP # define QT_NO_FTP #endif @@ -136,18 +119,7 @@ # define QT_NO_CUPS #endif -/* Qt for Embedded Linux */ -#ifndef QT_NO_QWS_SOUNDSERVER -# define QT_NO_QWS_SOUNDSERVER -#endif - /* Styles */ -#ifndef QT_NO_STYLE_MOTIF -# define QT_NO_STYLE_MOTIF -#endif -#ifndef QT_NO_STYLE_CDE -# define QT_NO_STYLE_CDE -#endif #ifndef QT_NO_STYLE_STYLESHEET # define QT_NO_STYLE_STYLESHEET #endif diff --git a/src/corelib/global/qconfig-medium.h b/src/corelib/global/qconfig-medium.h index 132c8ce45c..e5ab33faed 100644 --- a/src/corelib/global/qconfig-medium.h +++ b/src/corelib/global/qconfig-medium.h @@ -58,14 +58,6 @@ #ifndef QT_NO_PROGRESSDIALOG # define QT_NO_PROGRESSDIALOG #endif -#ifndef QT_NO_TABDIALOG -# define QT_NO_TABDIALOG -#endif - -/* Fonts */ -#ifndef QT_NO_QWS_QPF -# define QT_NO_QWS_QPF -#endif /* Images */ #ifndef QT_NO_IMAGEFORMAT_BMP @@ -91,9 +83,6 @@ #ifndef QT_NO_TRANSLATION # define QT_NO_TRANSLATION #endif -#ifndef QT_NO_TRANSLATION_UTF8 -# define QT_NO_TRANSLATION_UTF8 -#endif /* ItemViews */ #ifndef QT_NO_TABLEVIEW @@ -125,20 +114,11 @@ #ifndef QT_NO_SHORTCUT # define QT_NO_SHORTCUT #endif -#ifndef QT_NO_SOUND -# define QT_NO_SOUND -#endif #ifndef QT_NO_WHEELEVENT # define QT_NO_WHEELEVENT #endif /* Networking */ -#ifndef QT_NO_COP -# define QT_NO_COP -#endif -#ifndef QT_NO_HOSTINFO -# define QT_NO_HOSTINFO -#endif #ifndef QT_NO_HTTP # define QT_NO_HTTP #endif @@ -151,9 +131,6 @@ #ifndef QT_NO_UDPSOCKET # define QT_NO_UDPSOCKET #endif -#ifndef QT_NO_URLINFO -# define QT_NO_URLINFO -#endif #ifndef QT_NO_FTP # define QT_NO_FTP #endif @@ -172,24 +149,7 @@ # define QT_NO_CUPS #endif -/* Qt for Embedded Linux */ -#ifndef QT_NO_QWSEMBEDWIDGET -# define QT_NO_QWSEMBEDWIDGET -#endif -#ifndef QT_NO_QWS_SOUNDSERVER -# define QT_NO_QWS_SOUNDSERVER -#endif -#ifndef QT_NO_QWS_PROPERTIES -# define QT_NO_QWS_PROPERTIES -#endif - /* Styles */ -#ifndef QT_NO_STYLE_MOTIF -# define QT_NO_STYLE_MOTIF -#endif -#ifndef QT_NO_STYLE_CDE -# define QT_NO_STYLE_CDE -#endif #ifndef QT_NO_STYLE_STYLESHEET # define QT_NO_STYLE_STYLESHEET #endif @@ -281,8 +241,3 @@ #ifndef QT_NO_TREEWIDGET # define QT_NO_TREEWIDGET #endif - -/* Windows */ -#ifndef QT_NO_WIN_ACTIVEQT -# define QT_NO_WIN_ACTIVEQT -#endif diff --git a/src/corelib/global/qconfig-minimal.h b/src/corelib/global/qconfig-minimal.h index cc5ac9987c..b27f3271c1 100644 --- a/src/corelib/global/qconfig-minimal.h +++ b/src/corelib/global/qconfig-minimal.h @@ -75,9 +75,6 @@ #ifndef QT_NO_PROGRESSDIALOG # define QT_NO_PROGRESSDIALOG #endif -#ifndef QT_NO_TABDIALOG -# define QT_NO_TABDIALOG -#endif #ifndef QT_NO_WIZARD # define QT_NO_WIZARD #endif @@ -109,9 +106,6 @@ #ifndef QT_NO_FREETYPE # define QT_NO_FREETYPE #endif -#ifndef QT_NO_QWS_QPF2 -# define QT_NO_QWS_QPF2 -#endif /* Images */ #ifndef QT_NO_IMAGEFORMATPLUGIN @@ -146,9 +140,6 @@ #ifndef QT_NO_BIG_CODECS # define QT_NO_BIG_CODECS #endif -#ifndef QT_NO_QWS_INPUTMETHODS -# define QT_NO_QWS_INPUTMETHODS -#endif #ifndef QT_NO_TEXTCODEC # define QT_NO_TEXTCODEC #endif @@ -158,9 +149,6 @@ #ifndef QT_NO_TRANSLATION # define QT_NO_TRANSLATION #endif -#ifndef QT_NO_TRANSLATION_UTF8 -# define QT_NO_TRANSLATION_UTF8 -#endif /* ItemViews */ #ifndef QT_NO_ITEMVIEWS @@ -228,9 +216,6 @@ #ifndef QT_NO_SHORTCUT # define QT_NO_SHORTCUT #endif -#ifndef QT_NO_SOUND -# define QT_NO_SOUND -#endif #ifndef QT_NO_SYSTEMSEMAPHORE # define QT_NO_SYSTEMSEMAPHORE #endif @@ -257,12 +242,6 @@ #endif /* Networking */ -#ifndef QT_NO_COP -# define QT_NO_COP -#endif -#ifndef QT_NO_HOSTINFO -# define QT_NO_HOSTINFO -#endif #ifndef QT_NO_HTTP # define QT_NO_HTTP #endif @@ -275,9 +254,6 @@ #ifndef QT_NO_UDPSOCKET # define QT_NO_UDPSOCKET #endif -#ifndef QT_NO_URLINFO -# define QT_NO_URLINFO -#endif #ifndef QT_NO_FTP # define QT_NO_FTP #endif @@ -286,12 +262,6 @@ #ifndef QT_NO_COLORNAMES # define QT_NO_COLORNAMES #endif -#ifndef QT_NO_DIRECTPAINTER -# define QT_NO_DIRECTPAINTER -#endif -#ifndef QT_NO_PAINTONSCREEN -# define QT_NO_PAINTONSCREEN -#endif #ifndef QT_NO_PAINT_DEBUG # define QT_NO_PAINT_DEBUG #endif @@ -305,73 +275,6 @@ # define QT_NO_CUPS #endif -/* Qt for Embedded Linux */ -#ifndef QT_NO_QWSEMBEDWIDGET -# define QT_NO_QWSEMBEDWIDGET -#endif -#ifndef QT_NO_QWS_ALPHA_CURSOR -# define QT_NO_QWS_ALPHA_CURSOR -#endif -#ifndef QT_NO_QWS_CURSOR -# define QT_NO_QWS_CURSOR -#endif -#ifndef QT_NO_QWS_DECORATION_DEFAULT -# define QT_NO_QWS_DECORATION_DEFAULT -#endif -#ifndef QT_NO_QWS_DECORATION_STYLED -# define QT_NO_QWS_DECORATION_STYLED -#endif -#ifndef QT_NO_QWS_DECORATION_WINDOWS -# define QT_NO_QWS_DECORATION_WINDOWS -#endif -#ifndef QT_NO_QWS_MANAGER -# define QT_NO_QWS_MANAGER -#endif -#ifndef QT_NO_QWS_KEYBOARD -# define QT_NO_QWS_KEYBOARD -#endif -#ifndef QT_NO_QWS_MOUSE -# define QT_NO_QWS_MOUSE -#endif -#ifndef QT_NO_QWS_MOUSE_AUTO -# define QT_NO_QWS_MOUSE_AUTO -#endif -#ifndef QT_NO_QWS_MOUSE_MANUAL -# define QT_NO_QWS_MOUSE_MANUAL -#endif -#ifndef QT_NO_QWS_MULTIPROCESS -# define QT_NO_QWS_MULTIPROCESS -#endif -#ifndef QT_NO_QWS_SOUNDSERVER -# define QT_NO_QWS_SOUNDSERVER -#endif -#ifndef QT_NO_QWS_PROPERTIES -# define QT_NO_QWS_PROPERTIES -#endif -#ifndef QT_NO_QWS_PROXYSCREEN -# define QT_NO_QWS_PROXYSCREEN -#endif -#ifndef QT_NO_QWS_DYNAMICSCREENTRANSFORMATION -# define QT_NO_QWS_DYNAMICSCREENTRANSFORMATION -#endif - -/* SVG */ -#ifndef QT_NO_SVG -# define QT_NO_SVG -#endif -#ifndef QT_NO_GRAPHICSSVGITEM -# define QT_NO_GRAPHICSSVGITEM -#endif -#ifndef QT_NO_SVGGENERATOR -# define QT_NO_SVGGENERATOR -#endif -#ifndef QT_NO_SVGRENDERER -# define QT_NO_SVGRENDERER -#endif -#ifndef QT_NO_SVGWIDGET -# define QT_NO_SVGWIDGET -#endif - /* Styles */ #ifndef QT_NO_STYLE_FUSION # define QT_NO_STYLE_FUSION @@ -402,9 +305,6 @@ #ifndef QT_NO_DESKTOPSERVICES # define QT_NO_DESKTOPSERVICES #endif -#ifndef QT_NO_SCRIPT -# define QT_NO_SCRIPT -#endif #ifndef QT_NO_SYSTEMTRAYICON # define QT_NO_SYSTEMTRAYICON #endif @@ -485,9 +385,6 @@ #ifndef QT_NO_SPLITTER # define QT_NO_SPLITTER #endif -#ifndef QT_NO_SIGNALMAPPER -# define QT_NO_SIGNALMAPPER -#endif #ifndef QT_NO_SIZEGRIP # define QT_NO_SIZEGRIP #endif @@ -563,8 +460,3 @@ #ifndef QT_NO_VALIDATOR # define QT_NO_VALIDATOR #endif - -/* Windows */ -#ifndef QT_NO_WIN_ACTIVEQT -# define QT_NO_WIN_ACTIVEQT -#endif diff --git a/src/corelib/global/qconfig-nacl.h b/src/corelib/global/qconfig-nacl.h index c2854b26c3..22dd56e772 100644 --- a/src/corelib/global/qconfig-nacl.h +++ b/src/corelib/global/qconfig-nacl.h @@ -72,9 +72,6 @@ #ifndef QT_NO_FILESYSTEMWATCHER # define QT_NO_FILESYSTEMWATCHER #endif -#ifndef QT_NO_FSFILEENGINE -# define QT_NO_FSFILEENGINE -#endif #ifndef QT_NO_FILESYSTEMMODEL # define QT_NO_FILESYSTEMMODEL #endif @@ -94,11 +91,6 @@ # define QT_NO_LIBRARY #endif -/* Fonts */ -#ifndef QT_NO_QWS_QPF2 -# define QT_NO_QWS_QPF2 -#endif - /* Images */ #ifndef QT_NO_IMAGEFORMATPLUGIN # define QT_NO_IMAGEFORMATPLUGIN @@ -114,9 +106,6 @@ #ifndef QT_NO_BIG_CODECS # define QT_NO_BIG_CODECS #endif -#ifndef QT_NO_QWS_INPUTMETHODS -# define QT_NO_QWS_INPUTMETHODS -#endif #ifndef QT_NO_TEXTCODEC # define QT_NO_TEXTCODEC #endif @@ -126,9 +115,6 @@ #ifndef QT_NO_TRANSLATION # define QT_NO_TRANSLATION #endif -#ifndef QT_NO_TRANSLATION_UTF8 -# define QT_NO_TRANSLATION_UTF8 -#endif /* ItemViews */ @@ -158,9 +144,6 @@ #ifndef QT_NO_SHAREDMEMORY # define QT_NO_SHAREDMEMORY #endif -#ifndef QT_NO_SOUND -# define QT_NO_SOUND -#endif #ifndef QT_NO_SYSTEMLOCALE # define QT_NO_SYSTEMSEMAPHORE #endif @@ -187,12 +170,6 @@ #endif /* Networking */ -#ifndef QT_NO_COP -# define QT_NO_COP -#endif -#ifndef QT_NO_HOSTINFO -# define QT_NO_HOSTINFO -#endif #ifndef QT_NO_HTTP # define QT_NO_HTTP #endif @@ -205,9 +182,6 @@ #ifndef QT_NO_UDPSOCKET # define QT_NO_UDPSOCKET #endif -#ifndef QT_NO_URLINFO -# define QT_NO_URLINFO -#endif #ifndef QT_NO_FTP # define QT_NO_FTP #endif @@ -216,12 +190,6 @@ #ifndef QT_NO_COLORNAMES # define QT_NO_COLORNAMES #endif -#ifndef QT_NO_DIRECTPAINTER -# define QT_NO_DIRECTPAINTER -#endif -#ifndef QT_NO_PAINTONSCREEN -# define QT_NO_PAINTONSCREEN -#endif #ifndef QT_NO_PAINT_DEBUG # define QT_NO_PAINT_DEBUG #endif @@ -235,92 +203,7 @@ # define QT_NO_CUPS #endif -/* Qt for Embedded Linux */ -#ifndef QT_NO_QWSEMBEDWIDGET -# define QT_NO_QWSEMBEDWIDGET -#endif -#ifndef QT_NO_QWS_ALPHA_CURSOR -# define QT_NO_QWS_ALPHA_CURSOR -#endif -#ifndef QT_NO_QWS_CURSOR -# define QT_NO_QWS_CURSOR -#endif -#ifndef QT_NO_QWS_DECORATION_DEFAULT -# define QT_NO_QWS_DECORATION_DEFAULT -#endif -#ifndef QT_NO_QWS_DECORATION_STYLED -# define QT_NO_QWS_DECORATION_STYLED -#endif -#ifndef QT_NO_QWS_DECORATION_WINDOWS -# define QT_NO_QWS_DECORATION_WINDOWS -#endif -#ifndef QT_NO_QWS_MANAGER -# define QT_NO_QWS_MANAGER -#endif -#ifndef QT_NO_QWS_KEYBOARD -# define QT_NO_QWS_KEYBOARD -#endif -#ifndef QT_NO_QWS_MOUSE -# define QT_NO_QWS_MOUSE -#endif -#ifndef QT_NO_QWS_MOUSE_AUTO -# define QT_NO_QWS_MOUSE_AUTO -#endif -#ifndef QT_NO_QWS_MOUSE_MANUAL -# define QT_NO_QWS_MOUSE_MANUAL -#endif -#ifndef QT_NO_QWS_MULTIPROCESS -# define QT_NO_QWS_MULTIPROCESS -#endif -#ifndef QT_NO_QWS_SOUNDSERVER -# define QT_NO_QWS_SOUNDSERVER -#endif -#ifndef QT_NO_QWS_PROPERTIES -# define QT_NO_QWS_PROPERTIES -#endif -#ifndef QT_NO_QWS_PROXYSCREEN -# define QT_NO_QWS_PROXYSCREEN -#endif -#ifndef QT_NO_QWS_DYNAMICSCREENTRANSFORMATION -# define QT_NO_QWS_DYNAMICSCREENTRANSFORMATION -#endif -#ifndef QT_NO_QWS_LINUXFB -# define QT_NO_QWS_LINUXFB -#endif -#ifndef QT_NO_QWS_MOUSE_PC -# define QT_NO_QWS_MOUSE_PC -#endif -#ifndef QT_NO_QWS_MOUSE_LINUXTP -# define QT_NO_QWS_MOUSE_LINUXTP -#endif -#ifndef QT_NO_QWS_QPF -# define QT_NO_QWS_QPF -#endif - -/* SVG */ -#ifndef QT_NO_SVG -# define QT_NO_SVG -#endif -#ifndef QT_NO_GRAPHICSSVGITEM -# define QT_NO_GRAPHICSSVGITEM -#endif -#ifndef QT_NO_SVGGENERATOR -# define QT_NO_SVGGENERATOR -#endif -#ifndef QT_NO_SVGRENDERER -# define QT_NO_SVGRENDERER -#endif -#ifndef QT_NO_SVGWIDGET -# define QT_NO_SVGWIDGET -#endif - /* Styles */ -#ifndef QT_NO_STYLE_MOTIF -# define QT_NO_STYLE_MOTIF -#endif -#ifndef QT_NO_STYLE_CDE -# define QT_NO_STYLE_CDE -#endif #ifndef QT_NO_STYLE_STYLESHEET # define QT_NO_STYLE_STYLESHEET #endif @@ -347,14 +230,6 @@ #ifndef QT_NO_DESKTOPSERVICES # define QT_NO_DESKTOPSERVICES #endif -#ifndef QT_NO_SCRIPT -# define QT_NO_SCRIPT -#endif #ifndef QT_NO_SYSTEMTRAYICON # define QT_NO_SYSTEMTRAYICON #endif - -/* Windows */ -#ifndef QT_NO_WIN_ACTIVEQT -# define QT_NO_WIN_ACTIVEQT -#endif diff --git a/src/corelib/global/qconfig-small.h b/src/corelib/global/qconfig-small.h index f730b3d5d2..8a0e769383 100644 --- a/src/corelib/global/qconfig-small.h +++ b/src/corelib/global/qconfig-small.h @@ -64,9 +64,6 @@ #ifndef QT_NO_PROGRESSDIALOG # define QT_NO_PROGRESSDIALOG #endif -#ifndef QT_NO_TABDIALOG -# define QT_NO_TABDIALOG -#endif /* File I/O */ #ifndef QT_NO_SETTINGS @@ -105,9 +102,6 @@ #endif /* Internationalization */ -#ifndef QT_NO_QWS_INPUTMETHODS -# define QT_NO_QWS_INPUTMETHODS -#endif #ifndef QT_NO_TEXTCODEC # define QT_NO_TEXTCODEC #endif @@ -117,9 +111,6 @@ #ifndef QT_NO_TRANSLATION # define QT_NO_TRANSLATION #endif -#ifndef QT_NO_TRANSLATION_UTF8 -# define QT_NO_TRANSLATION_UTF8 -#endif /* ItemViews */ #ifndef QT_NO_DIRMODEL @@ -163,20 +154,11 @@ #ifndef QT_NO_SHORTCUT # define QT_NO_SHORTCUT #endif -#ifndef QT_NO_SOUND -# define QT_NO_SOUND -#endif #ifndef QT_NO_WHEELEVENT # define QT_NO_WHEELEVENT #endif /* Networking */ -#ifndef QT_NO_COP -# define QT_NO_COP -#endif -#ifndef QT_NO_HOSTINFO -# define QT_NO_HOSTINFO -#endif #ifndef QT_NO_HTTP # define QT_NO_HTTP #endif @@ -195,14 +177,6 @@ # define QT_NO_CUPS #endif -/* Qt for Embedded Linux */ -#ifndef QT_NO_QWS_SOUNDSERVER -# define QT_NO_QWS_SOUNDSERVER -#endif -#ifndef QT_NO_QWS_PROPERTIES -# define QT_NO_QWS_PROPERTIES -#endif - /* Styles */ #ifndef QT_NO_STYLE_FUSION # define QT_NO_STYLE_FUSION diff --git a/src/corelib/global/qfeatures.h b/src/corelib/global/qfeatures.h deleted file mode 100644 index 17dd600265..0000000000 --- a/src/corelib/global/qfeatures.h +++ /dev/null @@ -1,686 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtCore 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/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 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt 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$ -** -****************************************************************************/ - -/* - * All features and their dependencies. - * - * This list is generated from $QTDIR/src/corelib/global/qfeatures.txt - * by $QTSRCDIR/util/scripts/make_qfeatures_dot_h - */ - -// QAction -//#define QT_NO_ACTION - -// QClipboard -//#define QT_NO_CLIPBOARD - -// Color Names -//#define QT_NO_COLORNAMES - -// QtConcurrent -//#define QT_NO_CONCURRENT - -// CssParser -//#define QT_NO_CSSPARSER - -// QCursor -//#define QT_NO_CURSOR - -// QDesktopServices -//#define QT_NO_DESKTOPSERVICES - -// Document Object Model -//#define QT_NO_DOM - -// Effects -//#define QT_NO_EFFECTS - -// QFileSystemIterator -//#define QT_NO_FILESYSTEMITERATOR - -// QFileSystemWatcher -//#define QT_NO_FILESYSTEMWATCHER - -// Freetype Font Engine -//#define QT_NO_FREETYPE - -// Gesture -//#define QT_NO_GESTURES - -// QGroupBox -//#define QT_NO_GROUPBOX - -// QHostInfo -//#define QT_NO_HOSTINFO - -// BMP Image Format -//#define QT_NO_IMAGEFORMAT_BMP - -// JPEG Image Format -//#define QT_NO_IMAGEFORMAT_JPEG - -// PNG Image Format -//#define QT_NO_IMAGEFORMAT_PNG - -// PPM Image Format -//#define QT_NO_IMAGEFORMAT_PPM - -// XBM Image Format -//#define QT_NO_IMAGEFORMAT_XBM - -// XPM Image Format -//#define QT_NO_IMAGEFORMAT_XPM - -// QImage::createHeuristicMask() -//#define QT_NO_IMAGE_HEURISTIC_MASK - -// Image Text -//#define QT_NO_IMAGE_TEXT - -// QKeySequenceEdit -//#define QT_NO_KEYSEQUENCEEDIT - -// QLCDNumber -//#define QT_NO_LCDNUMBER - -// QLibrary -//#define QT_NO_LIBRARY - -// QLineEdit -//#define QT_NO_LINEEDIT - -// QMessageBox -//#define QT_NO_MESSAGEBOX - -// QMovie -//#define QT_NO_MOVIE - -// QNetworkInterface -//#define QT_NO_NETWORKINTERFACE - -// QNetworkProxy -//#define QT_NO_NETWORKPROXY - -// Qt::WA_PaintOnScreen -//#define QT_NO_PAINTONSCREEN - -// Painting Debug Utilities -//#define QT_NO_PAINT_DEBUG - -// QPicture -//#define QT_NO_PICTURE - -// QProcess -//#define QT_NO_PROCESS - -// QProgressBar -//#define QT_NO_PROGRESSBAR - -// Properties -//#define QT_NO_PROPERTIES - -// QRegularExpression -//#define QT_NO_REGULAREXPRESSION - -// Resize Handler -//#define QT_NO_RESIZEHANDLER - -// QRubberBand -//#define QT_NO_RUBBERBAND - -// Session Manager -//#define QT_NO_SESSIONMANAGER - -// QSettings -//#define QT_NO_SETTINGS - -// QSharedMemory -//#define QT_NO_SHAREDMEMORY - -// QShortcut -//#define QT_NO_SHORTCUT - -// QSizeGrip -//#define QT_NO_SIZEGRIP - -// QSlider -//#define QT_NO_SLIDER - -// Spin Widget -//#define QT_NO_SPINWIDGET - -// Splash screen widget -//#define QT_NO_SPLASHSCREEN - -// QStackedWidget -//#define QT_NO_STACKEDWIDGET - -// QStatusBar -//#define QT_NO_STATUSBAR - -// Status Tip -//#define QT_NO_STATUSTIP - -// QWindowsStyle -//#define QT_NO_STYLE_WINDOWS - -// QSystemSemaphore -//#define QT_NO_SYSTEMSEMAPHORE - -// QSystemTrayIcon -//#define QT_NO_SYSTEMTRAYICON - -// QTabletEvent -//#define QT_NO_TABLETEVENT - -// QTemporaryFile -//#define QT_NO_TEMPORARYFILE - -// QTextCodec -//#define QT_NO_TEXTCODEC - -// Text Date -//#define QT_NO_TEXTDATE - -// HtmlParser -//#define QT_NO_TEXTHTMLPARSER - -// QToolTip -//#define QT_NO_TOOLTIP - -// Translation -//#define QT_NO_TRANSLATION - -// QUdpSocket -//#define QT_NO_UDPSOCKET - -// QUndoCommand -//#define QT_NO_UNDOCOMMAND - -// QValidator -//#define QT_NO_VALIDATOR - -// QWheelEvent -//#define QT_NO_WHEELEVENT - -// -//#define QT_NO_XMLSTREAM - -// Animation -#if !defined(QT_NO_ANIMATION) && (defined(QT_NO_PROPERTIES)) -#define QT_NO_ANIMATION -#endif - -// Big Codecs -#if !defined(QT_NO_BIG_CODECS) && (defined(QT_NO_TEXTCODEC)) -#define QT_NO_BIG_CODECS -#endif - -// QButtonGroup -#if !defined(QT_NO_BUTTONGROUP) && (defined(QT_NO_GROUPBOX)) -#define QT_NO_BUTTONGROUP -#endif - -// Codecs -#if !defined(QT_NO_CODECS) && (defined(QT_NO_TEXTCODEC)) -#define QT_NO_CODECS -#endif - -// QDate/QTime/QDateTime -#if !defined(QT_NO_DATESTRING) && (defined(QT_NO_TEXTDATE)) -#define QT_NO_DATESTRING -#endif - -// QDial -#if !defined(QT_NO_DIAL) && (defined(QT_NO_SLIDER)) -#define QT_NO_DIAL -#endif - -// Drag and drop -#if !defined(QT_NO_DRAGANDDROP) && (defined(QT_NO_IMAGEFORMAT_XPM)) -#define QT_NO_DRAGANDDROP -#endif - -// File Transfer Protocol -#if !defined(QT_NO_FTP) && (defined(QT_NO_TEXTDATE)) -#define QT_NO_FTP -#endif - -// Hyper Text Transfer Protocol -#if !defined(QT_NO_HTTP) && (defined(QT_NO_HOSTINFO)) -#define QT_NO_HTTP -#endif - -// iconv -#if !defined(QT_NO_ICONV) && (defined(QT_NO_TEXTCODEC)) -#define QT_NO_ICONV -#endif - -// QInputContext -#if !defined(QT_NO_IM) && (defined(QT_NO_LIBRARY)) -#define QT_NO_IM -#endif - -// QImageIOPlugin -#if !defined(QT_NO_IMAGEFORMATPLUGIN) && (defined(QT_NO_LIBRARY)) -#define QT_NO_IMAGEFORMATPLUGIN -#endif - -// QKeySequenceEdit -#if !defined(QT_NO_KEYSEQUENCEEDIT) && (defined(QT_NO_SHORTCUT)) -#define QT_NO_KEYSEQUENCEEDIT -#endif - -// QLocalServer -#if !defined(QT_NO_LOCALSERVER) && (defined(QT_NO_TEMPORARYFILE)) -#define QT_NO_LOCALSERVER -#endif - -// QPdf -#if !defined(QT_NO_PDF) && (defined(QT_NO_TEMPORARYFILE)) -#define QT_NO_PDF -#endif - -// QMenu -#if !defined(QT_NO_MENU) && (defined(QT_NO_ACTION)) -#define QT_NO_MENU -#endif - -// QNetworkDiskCache -#if !defined(QT_NO_NETWORKDISKCACHE) && (defined(QT_NO_TEMPORARYFILE)) -#define QT_NO_NETWORKDISKCACHE -#endif - -// QProgressDialog -#if !defined(QT_NO_PROGRESSDIALOG) && (defined(QT_NO_PROGRESSBAR)) -#define QT_NO_PROGRESSDIALOG -#endif - -// QScrollBar -#if !defined(QT_NO_SCROLLBAR) && (defined(QT_NO_SLIDER)) -#define QT_NO_SCROLLBAR -#endif - -// SOCKS5 -#if !defined(QT_NO_SOCKS5) && (defined(QT_NO_NETWORKPROXY)) -#define QT_NO_SOCKS5 -#endif - -// QSplitter -#if !defined(QT_NO_SPLITTER) && (defined(QT_NO_RUBBERBAND)) -#define QT_NO_SPLITTER -#endif - -// State machine -#if !defined(QT_NO_STATEMACHINE) && (defined(QT_NO_PROPERTIES)) -#define QT_NO_STATEMACHINE -#endif - -// QFusionStyle -#if !defined(QT_NO_STYLE_FUSION) && (defined(QT_NO_IMAGEFORMAT_XPM)) -#define QT_NO_STYLE_FUSION -#endif - -// QWindowsXPStyle -#if !defined(QT_NO_STYLE_WINDOWSXP) && (defined(QT_NO_STYLE_WINDOWS)) -#define QT_NO_STYLE_WINDOWSXP -#endif - -// QToolButton -#if !defined(QT_NO_TOOLBUTTON) && (defined(QT_NO_ACTION)) -#define QT_NO_TOOLBUTTON -#endif - -// QUndoStack -#if !defined(QT_NO_UNDOSTACK) && (defined(QT_NO_UNDOCOMMAND)) -#define QT_NO_UNDOSTACK -#endif - -// QWizard -#if !defined(QT_NO_WIZARD) && (defined(QT_NO_PROPERTIES)) -#define QT_NO_WIZARD -#endif - -// QXmlStreamReader -#if !defined(QT_NO_XMLSTREAMREADER) && (defined(QT_NO_XMLSTREAM)) -#define QT_NO_XMLSTREAMREADER -#endif - -// QXmlStreamWriter -#if !defined(QT_NO_XMLSTREAMWRITER) && (defined(QT_NO_XMLSTREAM)) -#define QT_NO_XMLSTREAMWRITER -#endif - -// Context menu -#if !defined(QT_NO_CONTEXTMENU) && (defined(QT_NO_MENU)) -#define QT_NO_CONTEXTMENU -#endif - -// QPrinter -#if !defined(QT_NO_PRINTER) && (defined(QT_NO_PICTURE) || defined(QT_NO_TEMPORARYFILE)) -#define QT_NO_PRINTER -#endif - -// QScrollArea -#if !defined(QT_NO_SCROLLAREA) && (defined(QT_NO_SCROLLBAR)) -#define QT_NO_SCROLLAREA -#endif - -// QWindowsCEStyle -#if !defined(QT_NO_STYLE_WINDOWSCE) && (defined(QT_NO_STYLE_WINDOWS) || defined(QT_NO_IMAGEFORMAT_XPM)) -#define QT_NO_STYLE_WINDOWSCE -#endif - -// QWindowsMobileStyle -#if !defined(QT_NO_STYLE_WINDOWSMOBILE) && (defined(QT_NO_STYLE_WINDOWS) || defined(QT_NO_IMAGEFORMAT_XPM)) -#define QT_NO_STYLE_WINDOWSMOBILE -#endif - -// QWindowsVistaStyle -#if !defined(QT_NO_STYLE_WINDOWSVISTA) && (defined(QT_NO_STYLE_WINDOWSXP)) -#define QT_NO_STYLE_WINDOWSVISTA -#endif - -// QTabBar -#if !defined(QT_NO_TABBAR) && (defined(QT_NO_TOOLBUTTON)) -#define QT_NO_TABBAR -#endif - -// OdfWriter -#if !defined(QT_NO_TEXTODFWRITER) && (defined(QT_NO_XMLSTREAMWRITER)) -#define QT_NO_TEXTODFWRITER -#endif - -// Translation (UTF-8 representation) -#if !defined(QT_NO_TRANSLATION_UTF8) && (defined(QT_NO_TRANSLATION) || defined(QT_NO_TEXTCODEC)) -#define QT_NO_TRANSLATION_UTF8 -#endif - -// QUndoGroup -#if !defined(QT_NO_UNDOGROUP) && (defined(QT_NO_UNDOSTACK)) -#define QT_NO_UNDOGROUP -#endif - -// QWhatsThis -#if !defined(QT_NO_WHATSTHIS) && (defined(QT_NO_TOOLBUTTON)) -#define QT_NO_WHATSTHIS -#endif - -// Bearer Management -#if !defined(QT_NO_BEARERMANAGEMENT) && (defined(QT_NO_LIBRARY) || defined(QT_NO_NETWORKINTERFACE) || defined(QT_NO_PROPERTIES)) -#define QT_NO_BEARERMANAGEMENT -#endif - -// Qt D-Bus module -#if !defined(QT_NO_DBUS) && (defined(QT_NO_PROPERTIES) || defined(QT_NO_XMLSTREAMREADER)) -#define QT_NO_DBUS -#endif - -// QGraphicsView -#if !defined(QT_NO_GRAPHICSVIEW) && (defined(QT_NO_SCROLLAREA)) -#define QT_NO_GRAPHICSVIEW -#endif - -// QMdiArea -#if !defined(QT_NO_MDIAREA) && (defined(QT_NO_SCROLLAREA)) -#define QT_NO_MDIAREA -#endif - -// QSpinBox -#if !defined(QT_NO_SPINBOX) && (defined(QT_NO_SPINWIDGET) || defined(QT_NO_LINEEDIT) || defined(QT_NO_VALIDATOR)) -#define QT_NO_SPINBOX -#endif - -// QStyleSheetStyle -#if !defined(QT_NO_STYLE_STYLESHEET) && (defined(QT_NO_STYLE_WINDOWS) || defined(QT_NO_PROPERTIES) || defined(QT_NO_CSSPARSER)) -#define QT_NO_STYLE_STYLESHEET -#endif - -// QColorDialog -#if !defined(QT_NO_COLORDIALOG) && (defined(QT_NO_SPINBOX)) -#define QT_NO_COLORDIALOG -#endif - -// Common UNIX Printing System -#if !defined(QT_NO_CUPS) && (defined(QT_NO_PRINTER) || defined(QT_NO_LIBRARY)) -#define QT_NO_CUPS -#endif - -// QGraphicsEffect -#if !defined(QT_NO_GRAPHICSEFFECT) && (defined(QT_NO_GRAPHICSVIEW)) -#define QT_NO_GRAPHICSEFFECT -#endif - -// The Model/View Framework -#if !defined(QT_NO_ITEMVIEWS) && (defined(QT_NO_RUBBERBAND) || defined(QT_NO_SCROLLAREA)) -#define QT_NO_ITEMVIEWS -#endif - -// QMenuBar -#if !defined(QT_NO_MENUBAR) && (defined(QT_NO_MENU) || defined(QT_NO_TOOLBUTTON)) -#define QT_NO_MENUBAR -#endif - -// QTabWidget -#if !defined(QT_NO_TABWIDGET) && (defined(QT_NO_TABBAR) || defined(QT_NO_STACKEDWIDGET)) -#define QT_NO_TABWIDGET -#endif - -// QTextEdit -#if !defined(QT_NO_TEXTEDIT) && (defined(QT_NO_SCROLLAREA) || defined(QT_NO_PROPERTIES)) -#define QT_NO_TEXTEDIT -#endif - -// QErrorMessage -#if !defined(QT_NO_ERRORMESSAGE) && (defined(QT_NO_TEXTEDIT)) -#define QT_NO_ERRORMESSAGE -#endif - -// QListView -#if !defined(QT_NO_LISTVIEW) && (defined(QT_NO_ITEMVIEWS)) -#define QT_NO_LISTVIEW -#endif - -// QMainWindow -#if !defined(QT_NO_MAINWINDOW) && (defined(QT_NO_MENU) || defined(QT_NO_RESIZEHANDLER) || defined(QT_NO_TOOLBUTTON)) -#define QT_NO_MAINWINDOW -#endif - -// QAbstractProxyModel -#if !defined(QT_NO_PROXYMODEL) && (defined(QT_NO_ITEMVIEWS)) -#define QT_NO_PROXYMODEL -#endif - -// QStandardItemModel -#if !defined(QT_NO_STANDARDITEMMODEL) && (defined(QT_NO_ITEMVIEWS)) -#define QT_NO_STANDARDITEMMODEL -#endif - -// QStringListModel -#if !defined(QT_NO_STRINGLISTMODEL) && (defined(QT_NO_ITEMVIEWS)) -#define QT_NO_STRINGLISTMODEL -#endif - -// QSyntaxHighlighter -#if !defined(QT_NO_SYNTAXHIGHLIGHTER) && (defined(QT_NO_TEXTEDIT)) -#define QT_NO_SYNTAXHIGHLIGHTER -#endif - -// QTableView -#if !defined(QT_NO_TABLEVIEW) && (defined(QT_NO_ITEMVIEWS)) -#define QT_NO_TABLEVIEW -#endif - -// QTextBrowser -#if !defined(QT_NO_TEXTBROWSER) && (defined(QT_NO_TEXTEDIT)) -#define QT_NO_TEXTBROWSER -#endif - -// QToolBox -#if !defined(QT_NO_TOOLBOX) && (defined(QT_NO_TOOLBUTTON) || defined(QT_NO_SCROLLAREA)) -#define QT_NO_TOOLBOX -#endif - -// QTreeView -#if !defined(QT_NO_TREEVIEW) && (defined(QT_NO_ITEMVIEWS)) -#define QT_NO_TREEVIEW -#endif - -// Accessibility -#if !defined(QT_NO_ACCESSIBILITY) && (defined(QT_NO_PROPERTIES) || defined(QT_NO_MENUBAR)) -#define QT_NO_ACCESSIBILITY -#endif - -// QColumnView -#if !defined(QT_NO_COLUMNVIEW) && (defined(QT_NO_LISTVIEW)) -#define QT_NO_COLUMNVIEW -#endif - -// QCompleter -#if !defined(QT_NO_COMPLETER) && (defined(QT_NO_PROXYMODEL)) -#define QT_NO_COMPLETER -#endif - -// QDataWidgetMapper -#if !defined(QT_NO_DATAWIDGETMAPPER) && (defined(QT_NO_ITEMVIEWS) || defined(QT_NO_PROPERTIES)) -#define QT_NO_DATAWIDGETMAPPER -#endif - -// QIdentityProxyModel -#if !defined(QT_NO_IDENTITYPROXYMODEL) && (defined(QT_NO_PROXYMODEL)) -#define QT_NO_IDENTITYPROXYMODEL -#endif - -// QListWidget -#if !defined(QT_NO_LISTWIDGET) && (defined(QT_NO_LISTVIEW)) -#define QT_NO_LISTWIDGET -#endif - -// QSortFilterProxyModel -#if !defined(QT_NO_SORTFILTERPROXYMODEL) && (defined(QT_NO_PROXYMODEL)) -#define QT_NO_SORTFILTERPROXYMODEL -#endif - -// QTableWidget -#if !defined(QT_NO_TABLEWIDGET) && (defined(QT_NO_TABLEVIEW)) -#define QT_NO_TABLEWIDGET -#endif - -// QToolBar -#if !defined(QT_NO_TOOLBAR) && (defined(QT_NO_MAINWINDOW)) -#define QT_NO_TOOLBAR -#endif - -// QTreeWidget -#if !defined(QT_NO_TREEWIDGET) && (defined(QT_NO_TREEVIEW)) -#define QT_NO_TREEWIDGET -#endif - -// QDirModel -#if !defined(QT_NO_DIRMODEL) && (defined(QT_NO_ITEMVIEWS) || defined(QT_NO_FILESYSTEMMODEL)) -#define QT_NO_DIRMODEL -#endif - -// QDockwidget -#if !defined(QT_NO_DOCKWIDGET) && (defined(QT_NO_RUBBERBAND) || defined(QT_NO_MAINWINDOW)) -#define QT_NO_DOCKWIDGET -#endif - -// QUndoView -#if !defined(QT_NO_UNDOVIEW) && (defined(QT_NO_UNDOSTACK) || defined(QT_NO_LISTVIEW)) -#define QT_NO_UNDOVIEW -#endif - -// QCompleter -#if !defined(QT_NO_FSCOMPLETER) && (defined(QT_NO_FILESYSTEMMODEL) || defined(QT_NO_COMPLETER)) -#define QT_NO_FSCOMPLETER -#endif - -// QComboBox -#if !defined(QT_NO_COMBOBOX) && (defined(QT_NO_LINEEDIT) || defined(QT_NO_STANDARDITEMMODEL) || defined(QT_NO_LISTVIEW)) -#define QT_NO_COMBOBOX -#endif - -// QPrintPreviewWidget -#if !defined(QT_NO_PRINTPREVIEWWIDGET) && (defined(QT_NO_GRAPHICSVIEW) || defined(QT_NO_PRINTER) || defined(QT_NO_MAINWINDOW)) -#define QT_NO_PRINTPREVIEWWIDGET -#endif - -// QCalendarWidget -#if !defined(QT_NO_CALENDARWIDGET) && (defined(QT_NO_TABLEVIEW) || defined(QT_NO_MENU) || defined(QT_NO_TEXTDATE) || defined(QT_NO_SPINBOX) || defined(QT_NO_TOOLBUTTON)) -#define QT_NO_CALENDARWIDGET -#endif - -// QDateTimeEdit -#if !defined(QT_NO_DATETIMEEDIT) && (defined(QT_NO_CALENDARWIDGET) || defined(QT_NO_DATESTRING)) -#define QT_NO_DATETIMEEDIT -#endif - -// QInputDialog -#if !defined(QT_NO_INPUTDIALOG) && (defined(QT_NO_COMBOBOX) || defined(QT_NO_SPINBOX) || defined(QT_NO_STACKEDWIDGET)) -#define QT_NO_INPUTDIALOG -#endif - -// QFontComboBox -#if !defined(QT_NO_FONTCOMBOBOX) && (defined(QT_NO_COMBOBOX) || defined(QT_NO_STRINGLISTMODEL)) -#define QT_NO_FONTCOMBOBOX -#endif - -// QFontDialog -#if !defined(QT_NO_FONTDIALOG) && (defined(QT_NO_STRINGLISTMODEL) || defined(QT_NO_COMBOBOX) || defined(QT_NO_VALIDATOR) || defined(QT_NO_GROUPBOX)) -#define QT_NO_FONTDIALOG -#endif - -// QPrintDialog -#if !defined(QT_NO_PRINTDIALOG) && (defined(QT_NO_PRINTER) || defined(QT_NO_COMBOBOX) || defined(QT_NO_BUTTONGROUP) || defined(QT_NO_SPINBOX) || defined(QT_NO_TREEVIEW) || defined(QT_NO_TABWIDGET)) -#define QT_NO_PRINTDIALOG -#endif - -// QFileDialog -#if !defined(QT_NO_FILEDIALOG) && (defined(QT_NO_DIRMODEL) || defined(QT_NO_TREEVIEW) || defined(QT_NO_COMBOBOX) || defined(QT_NO_TOOLBUTTON) || defined(QT_NO_BUTTONGROUP) || defined(QT_NO_TOOLTIP) || defined(QT_NO_SPLITTER) || defined(QT_NO_STACKEDWIDGET) || defined(QT_NO_PROXYMODEL)) -#define QT_NO_FILEDIALOG -#endif - -// QPrintPreviewDialog -#if !defined(QT_NO_PRINTPREVIEWDIALOG) && (defined(QT_NO_PRINTPREVIEWWIDGET) || defined(QT_NO_PRINTDIALOG) || defined(QT_NO_TOOLBAR)) -#define QT_NO_PRINTPREVIEWDIALOG -#endif - diff --git a/src/corelib/global/qfeatures.txt b/src/corelib/global/qfeatures.txt index ec54c7bdbf..84c9379bbc 100644 --- a/src/corelib/global/qfeatures.txt +++ b/src/corelib/global/qfeatures.txt @@ -1,3 +1,11 @@ +# Generic entry format +#Feature: UPPERCASENAME (for the #define) +#Description: One sentence description of what this does. +#Section: Categorization +#Requires: UPPERCASENAME... +#Name: CamelCaseName (often a class name) +#SeeAlso: UPPERCASENAME... (currently unused) + # Kernel Feature: PROPERTIES @@ -5,147 +13,127 @@ Description: Supports scripting Qt-based applications. Section: Kernel Requires: Name: Properties -SeeAlso: ??? Feature: TEXTHTMLPARSER Description: Parser for HTML Section: Kernel Requires: Name: HtmlParser -SeeAlso: ??? Feature: TEXTODFWRITER Description: Provides an ODF writer Section: Kernel Requires: XMLSTREAMWRITER Name: OdfWriter -SeeAlso: ??? Feature: CSSPARSER Description: Parser for Style Sheets Section: Kernel Requires: Name: CssParser -SeeAlso: ??? Feature: REGULAREXPRESSION Description: Perl-compatible regular expression APIs Section: Kernel Requires: Name: QRegularExpression -SeeAlso: ??? Feature: CONCURRENT Description: Provides a high-level multi-threaded APIs Section: Kernel Requires: Name: QtConcurrent -SeeAlso: ??? Feature: DRAGANDDROP Description: Supports the drag and drop mechansim. Section: Kernel Requires: IMAGEFORMAT_XPM Name: Drag and drop -SeeAlso: ??? Feature: SESSIONMANAGER Description: Supports session management. Section: Kernel Requires: Name: Session Manager -SeeAlso: ??? Feature: SHORTCUT Description: Supports keyboard accelerators and shortcuts. Section: Kernel Requires: Name: QShortcut -SeeAlso: ??? Feature: ACTION Description: Supports widget actions. Section: Kernel Requires: Name: QAction -SeeAlso: ??? Feature: CURSOR Description: Supports mouse cursors. Section: Kernel Requires: Name: QCursor -SeeAlso: ??? Feature: CLIPBOARD Description: Supports cut and paste operations. Section: Kernel Requires: Name: QClipboard -SeeAlso: ??? Feature: WHEELEVENT Description: Supports wheel events. Section: Kernel Requires: Name: QWheelEvent -SeeAlso: ??? Feature: TABLETEVENT Description: Supports tablet events. Section: Kernel Requires: Name: QTabletEvent -SeeAlso: ??? Feature: EFFECTS Description: Supports special widget effects (e.g. fading and scrolling). Section: Kernel Requires: Name: Effects -SeeAlso: ??? Feature: SHAREDMEMORY Description: Provides access to a shared memory segment. Section: Kernel Requires: Name: QSharedMemory -SeeAlso: ??? Feature: SYSTEMSEMAPHORE Description: Provides a general counting system semaphore. Section: Kernel Requires: Name: QSystemSemaphore -SeeAlso: ??? Feature: XMLSTREAM Description: Provides a simple streaming API for XML. Section: Kernel Requires: -Name: -SeeAlso: ??? +Name: XML Streaming APIs Feature: XMLSTREAMREADER Description: Provides a well-formed XML parser with a simple streaming API. Section: Kernel Requires: XMLSTREAM Name: QXmlStreamReader -SeeAlso: ??? Feature: XMLSTREAMWRITER Description: Provides a XML writer with a simple streaming API. Section: Kernel Requires: XMLSTREAM Name: QXmlStreamWriter -SeeAlso: ??? Feature: IM Description: Inputmethods with QInputContext Section: Kernel Requires: LIBRARY Name: QInputContext -SeeAlso: ??? + # Data structures Feature: TEXTDATE @@ -153,14 +141,12 @@ Description: Supports month and day names in dates. Section: Data structures Requires: Name: Text Date -SeeAlso: ??? Feature: DATESTRING Description: Supports convertion between dates and strings. Section: Data structures Requires: TEXTDATE Name: QDate/QTime/QDateTime -SeeAlso: ??? # File I/O @@ -169,58 +155,48 @@ Description: Supports external process invocation. Section: File I/O Requires: Name: QProcess -SeeAlso: ??? Feature: TEMPORARYFILE Description: Provides an I/O device that operates on temporary files. Section: File I/O Requires: Name: QTemporaryFile -SeeAlso: ??? Feature: LIBRARY Description: Supports a shared library wrapper. Section: File I/O Requires: Name: QLibrary -SeeAlso: ??? Feature: SETTINGS Description: Supports persistent application settings. Section: File I/O Requires: Name: QSettings -SeeAlso: ??? Feature: DOM Description: Supports the Document Object Model. Section: File I/O Requires: Name: Document Object Model -SeeAlso: ??? Feature: FILESYSTEMMODEL Description: Provides a data model for the local filesystem. Section: File I/O Requires: Name: QFileSystemModel -SeeAlso: ??? Feature: FILESYSTEMWATCHER -Description: Provides an interface for monitoring files and directories -for modications. +Description: Provides an interface for monitoring files and directories for modications. Section: File I/O Requires: Name: QFileSystemWatcher -SeeAlso: ??? Feature: FILESYSTEMITERATOR Description: Provides fast file-system iteration. -for modications. Section: File I/O Requires: Name: QFileSystemIterator -SeeAlso: ??? # Widgets @@ -229,326 +205,282 @@ Description: Supports views using tree models. Section: Widgets Requires: TREEVIEW Name: QTreeWidget -SeeAlso: ??? Feature: LISTWIDGET Description: Supports item-based list widgets. Section: Widgets Requires: LISTVIEW Name: QListWidget -SeeAlso: ??? Feature: TABLEWIDGET Description: Supports item-based table views. Section: Widgets Requires: TABLEVIEW Name: QTableWidget -SeeAlso: ??? Feature: DATETIMEEDIT Description: Supports editing dates and times. Section: Widgets Requires: CALENDARWIDGET DATESTRING Name: QDateTimeEdit -SeeAlso: ??? Feature: STACKEDWIDGET Description: Supports stacked widgets. Section: Widgets Requires: Name: QStackedWidget -SeeAlso: ??? Feature: TEXTBROWSER Description: Supports HTML document browsing. Section: Widgets Requires: TEXTEDIT Name: QTextBrowser -SeeAlso: ??? Feature: SPLASHSCREEN Description: Supports splash screens that can be shown during application startup. Section: Widgets Requires: Name: Splash screen widget -SeeAlso: ??? Feature: SPLITTER Description: Supports user controlled splitter widgets. Section: Widgets Requires: RUBBERBAND Name: QSplitter -SeeAlso: ??? Feature: LCDNUMBER Description: Supports LCD-like digits. Section: Widgets Requires: Name: QLCDNumber -SeeAlso: ??? Feature: MENU Description: Supports popup-menus. Section: Widgets Requires: ACTION Name: QMenu -SeeAlso: ??? Feature: LINEEDIT Description: Supports single-line edits. Section: Widgets Requires: Name: QLineEdit -SeeAlso: ??? Feature: SPINBOX Description: Supports spin boxes handling integers and discrete sets of values. Section: Widgets Requires: SPINWIDGET LINEEDIT VALIDATOR Name: QSpinBox -SeeAlso: ??? Feature: TABBAR Description: Supports tab bars, e.g. for use in tabbed dialogs. Section: Widgets Requires: TOOLBUTTON Name: QTabBar -SeeAlso: ??? Feature: TABWIDGET Description: Supports stacking tabbed widgets. Section: Widgets Requires: TABBAR STACKEDWIDGET Name: QTabWidget -SeeAlso: ??? Feature: COMBOBOX Description: Supports comboboxes presenting a list of options to the user. Section: Widgets Requires: LINEEDIT STANDARDITEMMODEL LISTVIEW Name: QComboBox -SeeAlso: ??? Feature: FONTCOMBOBOX Description: Supports a combobox that lets the user select a font family. Section: Widgets Requires: COMBOBOX STRINGLISTMODEL Name: QFontComboBox -SeeAlso: ??? Feature: TOOLBUTTON Description: Supports quick-access buttons to commands and options. Section: Widgets Requires: ACTION Name: QToolButton -SeeAlso: ??? Feature: TOOLBAR Description: Supports movable panels containing a set of controls. Section: Widgets Requires: MAINWINDOW Name: QToolBar -SeeAlso: ??? Feature: TOOLBOX -Description: Supports columns of tabbed widget items. +Description: Supports columns of tabbed widget items. Section: Widgets Requires: TOOLBUTTON SCROLLAREA Name: QToolBox -SeeAlso: ??? Feature: GROUPBOX Description: Supports group box frames. Section: Widgets Requires: Name: QGroupBox -SeeAlso: ??? Feature: BUTTONGROUP Description: Supports organizing groups of button widgets. Section: Widgets Requires: GROUPBOX Name: QButtonGroup -SeeAlso: ??? Feature: MAINWINDOW Description: Supports main application windows. Section: Widgets Requires: MENU RESIZEHANDLER TOOLBUTTON Name: QMainWindow -SeeAlso: ??? Feature: DOCKWIDGET -Description: Supports docking widgets inside a QMainWindow or floated as -a top-level window on the desktop. +Description: Supports docking widgets inside a QMainWindow or floated as a top-level window on the desktop. Section: Widgets Requires: RUBBERBAND MAINWINDOW Name: QDockwidget -SeeAlso: ??? Feature: MDIAREA Description: Provides an area in which MDI windows are displayed. Section: Widgets Requires: SCROLLAREA Name: QMdiArea -SeeAlso: ??? Feature: RESIZEHANDLER Description: Supports an internal resize handler. Section: Widgets Requires: Name: Resize Handler -SeeAlso: ??? Feature: STATUSBAR Description: Supports presentation of status information. Section: Widgets Requires: Name: QStatusBar -SeeAlso: ??? Feature: MENUBAR Description: Supports pull-down menu items. Section: Widgets Requires: MENU TOOLBUTTON Name: QMenuBar -SeeAlso: ??? Feature: CONTEXTMENU Description: Supports pop-up menus on right mouse click Section: Widgets Requires: MENU Name: Context menu -SeeeAlso: ??? Feature: PROGRESSBAR Description: Supports presentation of operation progress. Section: Widgets Requires: Name: QProgressBar -SeeAlso: ??? Feature: SLIDER Description: Supports sliders controlling a bounded value. Section: Widgets Requires: Name: QSlider -SeeAlso: ??? Feature: SCROLLBAR -Description: Supports scrollbars allowing the user access parts of a -document that is larger than the widget used to display it. +Description: Supports scrollbars allowing the user access parts of a document that is larger than the widget used to display it. Section: Widgets Requires: SLIDER Name: QScrollBar -SeeAlso: ??? Feature: DIAL Description: Supports rounded range control, e.g. like a speedometer. Section: Widgets Requires: SLIDER Name: QDial -SeeAlso: ??? Feature: SCROLLAREA Description: Supports scrolling views onto widgets. Section: Widgets Requires: SCROLLBAR Name: QScrollArea -SeeAlso: ??? Feature: GRAPHICSVIEW Description: Supports the graphicsview classes. Section: Widgets Requires: SCROLLAREA Name: QGraphicsView -SeeAlso: ??? Feature: GRAPHICSEFFECT Description: Supports the graphicseffect classes. Section: Widgets Requires: GRAPHICSVIEW Name: QGraphicsEffect -SeeAlso: ??? Feature: SPINWIDGET Description: Supports spinbox control widgets. Section: Widgets Requires: Name: Spin Widget -SeeAlso: ??? Feature: TEXTEDIT Description: Supports rich text editing. Section: Widgets Requires: SCROLLAREA PROPERTIES Name: QTextEdit -SeeAlso: ??? Feature: SYNTAXHIGHLIGHTER Description: Supports custom syntax highlighting. Section: Widgets Requires: TEXTEDIT Name: QSyntaxHighlighter -SeeAlso: ??? Feature: RUBBERBAND Description: Supports using rubberbands to indicate selections and boundaries. Section: Widgets Requires: Name: QRubberBand -SeeAlso: ??? Feature: TOOLTIP Description: Supports presentation of tooltips. Section: Widgets Requires: Name: QToolTip -SeeAlso: ??? Feature: STATUSTIP Description: Supports status tip functionality and events. Section: Widgets Requires: Name: Status Tip -SeeAlso: ??? Feature: WHATSTHIS Description: Supports displaying "What's this" help. Section: Widgets Requires: TOOLBUTTON Name: QWhatsThis -SeeAlso: ??? Feature: VALIDATOR Description: Supports validation of input text. Section: Widgets Requires: Name: QValidator -SeeAlso: ??? Feature: SIZEGRIP Description: Supports corner-grips for resizing a top-level windows. Section: Widgets Requires: Name: QSizeGrip -SeeAlso: ??? Feature: CALENDARWIDGET -Description: Provides a monthly based calendar widget allowing the user to select -a date. +Description: Provides a monthly based calendar widget allowing the user to select a date. Section: Widgets Requires: TABLEVIEW MENU TEXTDATE SPINBOX TOOLBUTTON Name: QCalendarWidget -SeeAlso: ??? Feature: PRINTPREVIEWWIDGET Description: Provides a widget for previewing page layouts for printer output. -a date. Section: Widgets Requires: GRAPHICSVIEW PRINTER MAINWINDOW Name: QPrintPreviewWidget -SeeAlso: ??? + +Feature: KEYSEQUENCEEDIT +Description: Provides a widget for editing QKeySequences +Section: Widgets +Requires: LINEEDIT SHORTCUT +Name: QKeySequenceEdit # Dialogs @@ -558,158 +490,134 @@ informative messages and simple questions. Section: Dialogs Requires: Name: QMessageBox -SeeAlso: ??? Feature: COLORDIALOG Description: Supports a dialog widget for specifying colors. Section: Dialogs Requires: SPINBOX Name: QColorDialog -SeeAlso: ??? Feature: FILEDIALOG Description: Supports a dialog widget for selecting files or directories. Section: Dialogs Requires: DIRMODEL TREEVIEW COMBOBOX TOOLBUTTON BUTTONGROUP TOOLTIP SPLITTER STACKEDWIDGET PROXYMODEL Name: QFileDialog -SeeAlso: ??? Feature: FONTDIALOG Description: Supports a dialog widget for selecting fonts. Section: Dialogs Requires: STRINGLISTMODEL COMBOBOX VALIDATOR GROUPBOX Name: QFontDialog -SeeAlso: ??? Feature: PRINTDIALOG Description: Supports a dialog widget for specifying printer configuration. Section: Dialogs Requires: PRINTER COMBOBOX BUTTONGROUP SPINBOX TREEVIEW TABWIDGET Name: QPrintDialog -SeeAlso: ??? Feature: PRINTPREVIEWDIALOG Description: Provides a dialog for previewing and configuring page layouts for printer output. Section: Dialogs Requires: PRINTPREVIEWWIDGET PRINTDIALOG TOOLBAR Name: QPrintPreviewDialog -SeeAlso: ??? Feature: PROGRESSDIALOG Description: Supports feedback on the progress of a slow operation. Section: Dialogs Requires: PROGRESSBAR Name: QProgressDialog -SeeAlso: ??? Feature: INPUTDIALOG Description: Supports a simple convenience dialog to get a single value from the user. Section: Dialogs Requires: COMBOBOX SPINBOX STACKEDWIDGET Name: QInputDialog -SeeAlso: ??? Feature: ERRORMESSAGE -Description: Supports an error message display dialog. +Description: Supports an error message display dialog. Section: Dialogs Requires: TEXTEDIT Name: QErrorMessage -SeeAlso: ??? Feature: WIZARD Description: Provides a framework for wizards. Section: Dialogs Requires: PROPERTIES Name: QWizard -SeeAlso: ??? # ItemViews Feature: ITEMVIEWS -Description: Supports the model/view architecture managing the relationship -between data and the way it is presented to the user. +Description: Supports the model/view architecture managing the relationship between data and the way it is presented to the user. Section: ItemViews Requires: RUBBERBAND SCROLLAREA Name: The Model/View Framework -SeeAlso: ??? Feature: DIRMODEL Description: Supports a data model for the local filesystem. Section: ItemViews Requires: ITEMVIEWS FILESYSTEMMODEL Name: QDirModel -SeeAlso: ??? Feature: STANDARDITEMMODEL Description: Supports a generic model for storing custom data. Section: ItemViews Requires: ITEMVIEWS Name: QStandardItemModel -SeeAlso: ??? Feature: PROXYMODEL Description: Supports processing of data passed between another model and a view. Section: ItemViews Requires: ITEMVIEWS Name: QAbstractProxyModel -SeeAlso: ??? Feature: SORTFILTERPROXYMODEL -Description: Supports sorting and filtering of data passed between -another model and a view. +Description: Supports sorting and filtering of data passed between another model and a view. Section: ItemViews Requires: PROXYMODEL Name: QSortFilterProxyModel -SeeAlso: ??? Feature: IDENTITYPROXYMODEL Description: Supports proxying a source model unmodified. Section: ItemViews Requires: PROXYMODEL Name: QIdentityProxyModel -SeeAlso: ??? Feature: STRINGLISTMODEL Description: Supports a model that supplies strings to views. Section: ItemViews Requires: ITEMVIEWS Name: QStringListModel -SeeAlso: ??? Feature: LISTVIEW Description: Supports a list or icon view onto a model. Section: ItemViews Requires: ITEMVIEWS Name: QListView -SeeAlso: ??? Feature: TABLEVIEW Description: Supports a default model/view implementation of a table view. Section: ItemViews Requires: ITEMVIEWS Name: QTableView -SeeAlso: ??? Feature: TREEVIEW Description: Supports a default model/view implementation of a tree view. Section: ItemViews Requires: ITEMVIEWS Name: QTreeView -SeeAlso: ??? Feature: DATAWIDGETMAPPER Description: Provides mapping between a section of a data model to widgets. Section: ItemViews Requires: ITEMVIEWS PROPERTIES Name: QDataWidgetMapper -SeeAlso: ??? Feature: COLUMNVIEW Description: Provides a model/view implementation of a column view. Section: ItemViews Requires: LISTVIEW Name: QColumnView -SeeAlso: ??? # Styles @@ -718,49 +626,42 @@ Description: Supports a Microsoft Windows-like look and feel. Section: Styles Requires: Name: QWindowsStyle -SeeAlso: ??? Feature: STYLE_FUSION Description: Supports a modern platform independent widget style. Section: Styles Requires: IMAGEFORMAT_XPM Name: QFusionStyle -SeeAlso: ??? Feature: STYLE_WINDOWSXP Description: Supports a Microsoft WindowsXP-like look and feel. Section: Styles Requires: STYLE_WINDOWS Name: QWindowsXPStyle -SeeAlso: ??? Feature: STYLE_WINDOWSVISTA Description: Supports a Microsoft WindowsVista-like look and feel. Section: Styles Requires: STYLE_WINDOWSXP Name: QWindowsVistaStyle -SeeAlso: ??? Feature: STYLE_WINDOWSCE Description: WindowsCE look and feel Section: Styles Requires: STYLE_WINDOWS IMAGEFORMAT_XPM Name: QWindowsCEStyle -SeeAlso: ??? Feature: STYLE_WINDOWSMOBILE Description: WindowsMobile look and feel Section: Styles Requires: STYLE_WINDOWS IMAGEFORMAT_XPM Name: QWindowsMobileStyle -SeeAlso: ??? Feature: STYLE_STYLESHEET Description: Section: Styles Requires: STYLE_WINDOWS PROPERTIES CSSPARSER Name: QStyleSheetStyle -SeeAlso: ??? # Images @@ -769,70 +670,60 @@ Description: Supports writing an image format plugin. Section: Images Requires: LIBRARY Name: QImageIOPlugin -SeeAlso: ??? Feature: MOVIE Description: Supports animated images. Section: Images Requires: Name: QMovie -SeeAlso: ??? Feature: IMAGEFORMAT_BMP -Description: Supports Microsoft's Bitmap image file format. +Description: Supports Microsoft's Bitmap image file format. Section: Images Requires: Name: BMP Image Format -SeeAlso: ??? Feature: IMAGEFORMAT_PPM Description: Supports the Portable Pixmap image file format. Section: Images Requires: Name: PPM Image Format -SeeAlso: ??? Feature: IMAGEFORMAT_XBM Description: Supports the X11 Bitmap image file format. Section: Images Requires: Name: XBM Image Format -SeeAlso: ??? Feature: IMAGEFORMAT_XPM Description: Supports the X11 Pixmap image file format. Section: Images Requires: Name: XPM Image Format -SeeAlso: ??? Feature: IMAGEFORMAT_PNG Description: Supports the Portable Network Graphics image file format. Section: Images Requires: Name: PNG Image Format -SeeAlso: ??? Feature: IMAGEFORMAT_JPEG Description: Supports the Joint Photographic Experts Group image file format. Section: Images Requires: Name: JPEG Image Format -SeeAlso: ??? Feature: IMAGE_HEURISTIC_MASK Description: Supports creating a 1-bpp heuristic mask for images. Section: Images Requires: Name: QImage::createHeuristicMask() -SeeAlso: ??? Feature: IMAGE_TEXT Description: Supports image file text strings. Section: Images Requires: Name: Image Text -SeeAlso: ??? # Painting @@ -841,50 +732,36 @@ Description: Supports recording and replaying QPainter commands. Section: Painting Requires: Name: QPicture -SeeAlso: ??? Feature: COLORNAMES -Description: Supports color names such as "red", used by QColor -and by some HTML documents. +Description: Supports color names such as "red", used by QColor and by some HTML documents. Section: Painting Requires: Name: Color Names -SeeAlso: ??? Feature: PDF Description: Supports pdf format Section: Painting Requires: TEMPORARYFILE Name: QPdf -SeeAlso: ??? Feature: PRINTER Description: Supports printing Section: Painting Requires: PICTURE TEMPORARYFILE Name: QPrinter -SeeAlso: ??? Feature: CUPS Description Supports the Common UNIX Printing System Section: Painting Requires: PRINTER LIBRARY Name: Common UNIX Printing System -SeeAlso: ??? - -Feature: PAINTONSCREEN -Description: Supports the Qt::WA_PaintOnScreen widget attribute. -Section: Painting -Requires: -Name: Qt::WA_PaintOnScreen -SeeAlso: ??? Feature: PAINT_DEBUG Description: Debug painting with the environment variables QT_FLUSH_UPDATE and QT_FLUSH_PAINT Section: Painting Requires: Name: Painting Debug Utilities -SeeAlso: ??? # Fonts @@ -893,7 +770,6 @@ Description: Supports the FreeType 2 font engine (and its supported font formats Section: Fonts Requires: Name: Freetype Font Engine -SeeAlso: ??? # Internationalization @@ -902,114 +778,86 @@ Description: Supports translations using QObject::tr(). Section: Internationalization Requires: Name: Translation -SeeAlso: ??? - -Feature: TRANSLATION_UTF8 -Description: Supports translations using QObject::trUtf8(). -Section: Internationalization -Requires: TRANSLATION TEXTCODEC -Name: Translation (UTF-8 representation) -SeeAlso: ??? Feature: TEXTCODEC Description: Supports conversions between text encodings. Section: Internationalization Requires: Name: QTextCodec -SeeAlso: ??? Feature: CODECS Description: Supports non-unicode text conversions. Section: Internationalization Requires: TEXTCODEC Name: Codecs -SeeAlso: ??? Feature: BIG_CODECS Description: Supports big codecs, e.g. CJK. Section: Internationalization Requires: TEXTCODEC Name: Big Codecs -SeeAlso: ??? Feature: ICONV Description: Supports conversions between text encodings using iconv. Section: Internationalization Requires: TEXTCODEC Name: iconv -SeeAlso: ??? # Networking -Feature: HOSTINFO -Description: Supports host name lookups. -Section: Networking -Requires: -Name: QHostInfo -SeeAlso: ??? - Feature: FTP Description: Supports FTP file access. Section: Networking Requires: TEXTDATE Name: File Transfer Protocol -SeeAlso: ??? Feature: HTTP Description: Supports HTTP file access. Section: Networking -Requires: HOSTINFO +Requires: Name: Hyper Text Transfer Protocol -SeeAlso: ??? Feature: UDPSOCKET Description: Supports User Datagram Protocol sockets. Section: Networking Requires: Name: QUdpSocket -SeeAlso: ??? Feature: NETWORKPROXY Description: Supports configuring network layer proxy support to the Qt network classes. Section: Networking Requires: Name: QNetworkProxy -SeeAlso: ??? Feature: SOCKS5 Description: Supports SOCKS v5 network proxy. Section: Networking Requires: NETWORKPROXY -Name: SOCKS5 -SeeAlso: ??? +Name: SOCKS5 Feature: NETWORKINTERFACE Description: Supports listing the host's IP addresses and network interfaces Section: Networking Requires: Name: QNetworkInterface -SeeAlso: ??? Feature: NETWORKDISKCACHE Description: Supports a disk cache for network resources Section: Networking Requires: TEMPORARYFILE Name: QNetworkDiskCache -SeeAlso: ??? Feature: BEARERMANAGEMENT Description: Provides bearer management support Section: Networking Requires: LIBRARY NETWORKINTERFACE PROPERTIES Name: Bearer Management -SeeAlso: ??? Feature: LOCALSERVER Description: Supports a local socket based server Section: Networking Requires: TEMPORARYFILE Name: QLocalServer -SeeAlso: ??? # Utilities @@ -1018,84 +866,72 @@ Description: Provides completions based on an item model. Section: Utilities Requires: PROXYMODEL Name: QCompleter -SeeAlso: ??? Feature: FSCOMPLETER Description: Provides completions based on an item model. Section: Utilities Requires: FILESYSTEMMODEL COMPLETER Name: QCompleter -SeeAlso: ??? Feature: DESKTOPSERVICES Description: Provides methods for accessing common desktop services. Section: Utilities Requires: Name: QDesktopServices -SeeAlso: ??? Feature: SYSTEMTRAYICON Description: Provides an icon for an application in the system tray. Section: Utilities Requires: Name: QSystemTrayIcon -SeeAlso: ??? Feature: UNDOCOMMAND Description: Applies (redo or) undo of a single change in a document. Section: Utilities Requires: Name: QUndoCommand -SeeAlso: ??? Feature: UNDOSTACK Description: Provides the ability to (redo or) undo a list of changes in a document. Section: Utilities Requires: UNDOCOMMAND Name: QUndoStack -SeeAlso: ??? Feature: UNDOGROUP Description: Section: Utilities Requires: UNDOSTACK Name: QUndoGroup -SeeAlso: ??? Feature: UNDOVIEW Description: A widget which shows the contents of an undo stack. Section: Utilities Requires: UNDOSTACK LISTVIEW Name: QUndoView -SeeAlso: ??? Feature: ACCESSIBILITY Description: Provides accessibility support. Section: Utilities Requires: PROPERTIES MENUBAR Name: Accessibility -SeeAlso: ??? Feature: ANIMATION Description: Provides a framework for animations. Section: Utilities Requires: PROPERTIES Name: Animation -SeeAlso: ??? Feature: STATEMACHINE Description: Provides hierarchical finite state machines. Section: Utilities Requires: PROPERTIES Name: State machine -SeeAlso: ??? Feature: GESTURES Description: Provides a framework for gestures. Section: Utilities Requires: Name: Gesture -SeeAlso: ??? # D-Bus @@ -1104,5 +940,11 @@ Description: Provides classes for D-Bus. Section: D-Bus Requires: PROPERTIES XMLSTREAMREADER Name: Qt D-Bus module -SeeAlso: ??? +# XML Patterns + +Feature: XMLSCHEMA +Description: Provides XML schema validation. +Section: Xml Patterns +Requires: +Name: XML Schema APIs diff --git a/src/corelib/global/qflags.h b/src/corelib/global/qflags.h index 5b7edbafa6..dd4222b89f 100644 --- a/src/corelib/global/qflags.h +++ b/src/corelib/global/qflags.h @@ -111,14 +111,14 @@ public: Q_DECL_CONSTEXPR inline operator Int() const { return i; } - Q_DECL_CONSTEXPR inline QFlags operator|(QFlags f) const { return QFlags(Enum(i | f.i)); } - Q_DECL_CONSTEXPR inline QFlags operator|(Enum f) const { return QFlags(Enum(i | Int(f))); } - Q_DECL_CONSTEXPR inline QFlags operator^(QFlags f) const { return QFlags(Enum(i ^ f.i)); } - Q_DECL_CONSTEXPR inline QFlags operator^(Enum f) const { return QFlags(Enum(i ^ Int(f))); } - Q_DECL_CONSTEXPR inline QFlags operator&(int mask) const { return QFlags(Enum(i & mask)); } - Q_DECL_CONSTEXPR inline QFlags operator&(uint mask) const { return QFlags(Enum(i & mask)); } - Q_DECL_CONSTEXPR inline QFlags operator&(Enum f) const { return QFlags(Enum(i & Int(f))); } - Q_DECL_CONSTEXPR inline QFlags operator~() const { return QFlags(Enum(~i)); } + Q_DECL_CONSTEXPR inline QFlags operator|(QFlags f) const { return QFlags(QFlag(i | f.i)); } + Q_DECL_CONSTEXPR inline QFlags operator|(Enum f) const { return QFlags(QFlag(i | Int(f))); } + Q_DECL_CONSTEXPR inline QFlags operator^(QFlags f) const { return QFlags(QFlag(i ^ f.i)); } + Q_DECL_CONSTEXPR inline QFlags operator^(Enum f) const { return QFlags(QFlag(i ^ Int(f))); } + Q_DECL_CONSTEXPR inline QFlags operator&(int mask) const { return QFlags(QFlag(i & mask)); } + Q_DECL_CONSTEXPR inline QFlags operator&(uint mask) const { return QFlags(QFlag(i & mask)); } + Q_DECL_CONSTEXPR inline QFlags operator&(Enum f) const { return QFlags(QFlag(i & Int(f))); } + Q_DECL_CONSTEXPR inline QFlags operator~() const { return QFlags(QFlag(~i)); } Q_DECL_CONSTEXPR inline bool operator!() const { return !i; } diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 6f74c7de88..f72d27c2e5 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -88,6 +88,14 @@ Q_CORE_EXPORT void *qMemCopy(void *dest, const void *src, size_t n); Q_CORE_EXPORT void *qMemSet(void *dest, int c, size_t n); #endif +// Statically check assumptions about the environment we're running +// in. The idea here is to error or warn if otherwise implicit Qt +// assumptions are not fulfilled on new hardware or compilers +// (if this list becomes too long, consider factoring into a separate file) +Q_STATIC_ASSERT_X(sizeof(int) == 4, "Qt assumes that int is 32 bits"); +Q_STATIC_ASSERT_X(UCHAR_MAX == 255, "Qt assumes that char is 8 bits"); + + /*! \class QFlag \inmodule QtCore @@ -721,10 +729,6 @@ Q_CORE_EXPORT void *qMemSet(void *dest, int c, size_t n); A message generated by the qCritical() function. \value QtFatalMsg A message generated by the qFatal() function. - \value QtTraceMsg - Used by the qCTrace() macro. Trace events are usually passed only - to dedicated \a QTracer objects, and do not appear in the installed - message handler. \value QtSystemMsg @@ -981,8 +985,7 @@ bool qSharedBuild() Q_DECL_NOTHROW /*! \fn QSysInfo::MacVersion QSysInfo::macVersion() - Returns the version of Mac OS X on which the application is run (Mac OS X - Only). + Returns the version of Darwin (OS X or iOS) on which the application is run. */ /*! @@ -1018,6 +1021,7 @@ bool qSharedBuild() Q_DECL_NOTHROW \value WV_VISTA Windows Vista, Windows Server 2008 (operating system version 6.0) \value WV_WINDOWS7 Windows 7, Windows Server 2008 R2 (operating system version 6.1) \value WV_WINDOWS8 Windows 8 (operating system version 6.2) + \value WV_WINDOWS8_1 Windows 8.1 (operating system version 6.3), introduced in Qt 5.2 Alternatively, you may use the following macros which correspond directly to the Windows operating system version number: @@ -1028,6 +1032,7 @@ bool qSharedBuild() Q_DECL_NOTHROW \value WV_6_0 Operating system version 6.0, corresponds to Windows Vista and Windows Server 2008 \value WV_6_1 Operating system version 6.1, corresponds to Windows 7 and Windows Server 2008 R2 \value WV_6_2 Operating system version 6.2, corresponds to Windows 8 + \value WV_6_3 Operating system version 6.3, corresponds to Windows 8.1, introduced in Qt 5.2 CE-based versions: @@ -1050,7 +1055,7 @@ bool qSharedBuild() Q_DECL_NOTHROW \enum QSysInfo::MacVersion This enum provides symbolic names for the various versions of the - OS X operating system. On OS X, the + Darwin operating system, covering both OS X and iOS. The QSysInfo::MacintoshVersion variable gives the version of the system on which the application is run. @@ -1078,6 +1083,15 @@ bool qSharedBuild() Q_DECL_NOTHROW \value MV_MOUNTAINLION Apple codename for MV_10_8 \value MV_MAVERICKS Apple codename for MV_10_9 + \value MV_IOS iOS (any) + \value MV_IOS_4_3 iOS 4.3 + \value MV_IOS_5_0 iOS 5.0 + \value MV_IOS_5_1 iOS 5.1 + \value MV_IOS_6_0 iOS 6.0 + \value MV_IOS_6_1 iOS 6.1 + \value MV_IOS_7_0 iOS 7.0 + \value MV_IOS_7_1 iOS 7.1 + \sa WinVersion */ @@ -1700,13 +1714,15 @@ static const unsigned int qt_one = 1; const int QSysInfo::ByteOrder = ((*((unsigned char *) &qt_one) == 0) ? BigEndian : LittleEndian); #endif -#if defined(Q_OS_MACX) +#if defined(Q_OS_MAC) QT_BEGIN_INCLUDE_NAMESPACE #include "private/qcore_mac_p.h" #include "qnamespace.h" QT_END_INCLUDE_NAMESPACE +#if defined(Q_OS_OSX) + Q_CORE_EXPORT OSErr qt_mac_create_fsref(const QString &file, FSRef *fsref) { return FSPathMakeRef(reinterpret_cast<const UInt8 *>(file.toUtf8().constData()), fsref, 0); @@ -1722,17 +1738,17 @@ Q_CORE_EXPORT void qt_mac_to_pascal_string(QString s, Str255 str, TextEncoding e Q_CORE_EXPORT QString qt_mac_from_pascal_string(const Str255 pstr) { return QCFString(CFStringCreateWithPascalString(0, pstr, CFStringGetSystemEncoding())); } -#endif // defined(Q_OS_MACX) - -#if defined(Q_OS_MAC) +#endif // defined(Q_OS_OSX) QSysInfo::MacVersion QSysInfo::macVersion() { -#ifdef Q_OS_MACX +#if defined(Q_OS_OSX) SInt32 gestalt_version; if (Gestalt(gestaltSystemVersion, &gestalt_version) == noErr) { return QSysInfo::MacVersion(((gestalt_version & 0x00F0) >> 4) + 2); } +#elif defined(Q_OS_IOS) + return qt_ios_version(); // qtcore_mac_objc.mm #endif return QSysInfo::MV_Unknown; } @@ -1744,6 +1760,38 @@ QT_BEGIN_INCLUDE_NAMESPACE #include "qt_windows.h" QT_END_INCLUDE_NAMESPACE +#ifndef Q_OS_WINRT +static inline OSVERSIONINFO winOsVersion() +{ + OSVERSIONINFO result = { sizeof(OSVERSIONINFO), 0, 0, 0, 0, {'\0'}}; + // GetVersionEx() has been deprecated in Windows 8.1 and will return + // only Windows 8 from that version on. +# if defined(_MSC_VER) && _MSC_VER >= 1800 +# pragma warning( push ) +# pragma warning( disable : 4996 ) +# endif + GetVersionEx(&result); +# if defined(_MSC_VER) && _MSC_VER >= 1800 +# pragma warning( pop ) +# endif +# ifndef Q_OS_WINCE + if (result.dwMajorVersion == 6 && result.dwMinorVersion == 2) { + // This could be Windows 8.1 or higher. Note that as of Windows 9, + // the major version needs to be checked as well. + DWORDLONG conditionMask = 0; + VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(conditionMask, VER_PLATFORMID, VER_EQUAL); + OSVERSIONINFOEX checkVersion = { sizeof(OSVERSIONINFOEX), result.dwMajorVersion, result.dwMinorVersion, + result.dwBuildNumber, result.dwPlatformId, {'\0'}, 0, 0, 0, 0, 0 }; + for ( ; VerifyVersionInfo(&checkVersion, VER_MAJORVERSION | VER_MINORVERSION | VER_PLATFORMID, conditionMask); ++checkVersion.dwMinorVersion) + result.dwMinorVersion = checkVersion.dwMinorVersion; + } +# endif // !Q_OS_WINCE + return result; +} +#endif // !Q_OS_WINRT + QSysInfo::WinVersion QSysInfo::windowsVersion() { #ifndef VER_PLATFORM_WIN32s @@ -1766,9 +1814,7 @@ QSysInfo::WinVersion QSysInfo::windowsVersion() winver = QSysInfo::WV_WINDOWS8; #else winver = QSysInfo::WV_NT; - OSVERSIONINFO osver; - osver.dwOSVersionInfoSize = sizeof(osver); - GetVersionEx(&osver); + const OSVERSIONINFO osver = winOsVersion(); #ifdef Q_OS_WINCE DWORD qt_cever = 0; qt_cever = osver.dwMajorVersion * 100; @@ -1814,6 +1860,8 @@ QSysInfo::WinVersion QSysInfo::windowsVersion() winver = QSysInfo::WV_WINDOWS7; } else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 2) { winver = QSysInfo::WV_WINDOWS8; + } else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 3) { + winver = QSysInfo::WV_WINDOWS8_1; } else { qWarning("Qt: Untested Windows version %d.%d detected!", int(osver.dwMajorVersion), int(osver.dwMinorVersion)); @@ -2389,9 +2437,14 @@ void qsrand(uint seed) srand(seed); } #elif defined(Q_OS_ANDROID) - QJNIObjectPrivate random = QJNIObjectPrivate("java/util/Random", - "(J)V", - jlong(seed)); + if (randomTLS->hasLocalData()) { + randomTLS->localData().callMethod<void>("setSeed", "(J)V", jlong(seed)); + return; + } + + QJNIObjectPrivate random("java/util/Random", + "(J)V", + jlong(seed)); if (!random.isValid()) { srand(seed); return; @@ -2444,19 +2497,20 @@ int qrand() if (!randomStorage) return rand(); - QJNIObjectPrivate random; - if (!randomStorage->hasLocalData()) { - random = QJNIObjectPrivate("java/util/Random", - "(J)V", - jlong(1)); - if (!random.isValid()) - return rand(); - - randomStorage->setLocalData(random); - } else { - random = randomStorage->localData(); + if (randomStorage->hasLocalData()) { + return randomStorage->localData().callMethod<jint>("nextInt", + "(I)I", + RAND_MAX); } + QJNIObjectPrivate random("java/util/Random", + "(J)V", + jlong(1)); + + if (!random.isValid()) + return rand(); + + randomStorage->setLocalData(random); return random.callMethod<jint>("nextInt", "(I)I", RAND_MAX); #else // On Windows srand() and rand() already use Thread-Local-Storage diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index b654ba3ac8..da5f65fafb 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -55,12 +55,11 @@ */ #define QT_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch)) -#if !defined(QT_BUILD_MOC) && !defined(QT_BUILD_QMAKE) && !defined(QT_BUILD_CONFIGURE) +#if !defined(QT_BUILD_QMAKE) && !defined(QT_BUILD_CONFIGURE) #include <QtCore/qconfig.h> -#endif - #include <QtCore/qfeatures.h> #define QT_SUPPORTS(FEATURE) (!defined(QT_NO_##FEATURE)) +#endif /* These two macros makes it possible to turn the builtin line expander into a * string literal. */ @@ -198,6 +197,8 @@ typedef quint64 qulonglong; # define QT_POINTER_SIZE 4 # elif defined(Q_OS_ANDROID) # define QT_POINTER_SIZE 4 // ### Add auto-detection to Windows configure +# elif !defined(QT_BOOTSTRAPPED) +# error could not determine QT_POINTER_SIZE # endif #endif @@ -212,11 +213,8 @@ typedef unsigned int uint; typedef unsigned long ulong; QT_END_INCLUDE_NAMESPACE -// This logic must match the one in qmetatype.h #if defined(QT_COORD_TYPE) typedef QT_COORD_TYPE qreal; -#elif defined(QT_NO_FPU) || defined(Q_PROCESSOR_ARM) || defined(Q_OS_WINCE) -typedef float qreal; #else typedef double qreal; #endif @@ -333,9 +331,6 @@ typedef double qreal; # define Q_AUTOTEST_EXPORT #endif -#define Q_INIT_RESOURCE_EXTERN(name) \ - extern int QT_MANGLE_NAMESPACE(qInitResources_ ## name) (); - #define Q_INIT_RESOURCE(name) \ do { extern int QT_MANGLE_NAMESPACE(qInitResources_ ## name) (); \ QT_MANGLE_NAMESPACE(qInitResources_ ## name) (); } while (0) @@ -530,6 +525,16 @@ Q_DECL_CONSTEXPR inline const T &qBound(const T &min, const T &val, const T &max # define QT_MAC_DEPLOYMENT_TARGET_BELOW(osx, ios) \ (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && osx != __MAC_NA && __MAC_OS_X_VERSION_MIN_REQUIRED < osx) || \ (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && ios != __IPHONE_NA && __IPHONE_OS_VERSION_MIN_REQUIRED < ios) + +# define QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(ios) \ + QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_NA, ios) +# define QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(osx) \ + QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(osx, __IPHONE_NA) + +# define QT_IOS_DEPLOYMENT_TARGET_BELOW(ios) \ + QT_MAC_DEPLOYMENT_TARGET_BELOW(__MAC_NA, ios) +# define QT_OSX_DEPLOYMENT_TARGET_BELOW(osx) \ + QT_MAC_DEPLOYMENT_TARGET_BELOW(osx, __IPHONE_NA) #endif /* diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index a279498e93..22a9980812 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -225,7 +225,7 @@ QLibraryInfo::QLibraryInfo() QString QLibraryInfo::licensee() { - const char *str = QT_CONFIGURE_LICENSEE; + const char * volatile str = QT_CONFIGURE_LICENSEE; return QString::fromLocal8Bit(str); } @@ -238,7 +238,7 @@ QLibraryInfo::licensee() QString QLibraryInfo::licensedProducts() { - const char *str = QT_CONFIGURE_LICENSED_PRODUCTS; + const char * volatile str = QT_CONFIGURE_LICENSED_PRODUCTS; return QString::fromLatin1(str); } diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index 0a261acc77..cc20891c76 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -816,7 +816,6 @@ Q_CORE_EXPORT QString qMessageFormatString(QtMsgType type, const QMessageLogCont case QtWarningMsg: message.append(QLatin1String("warning")); break; case QtCriticalMsg:message.append(QLatin1String("critical")); break; case QtFatalMsg: message.append(QLatin1String("fatal")); break; - case QtTraceMsg: message.append(QLatin1String("trace")); break; } } else if (token == fileTokenC) { if (context.file) @@ -874,7 +873,6 @@ static void android_default_message_handler(QtMsgType type, { android_LogPriority priority; switch (type) { - case QtTraceMsg: case QtDebugMsg: priority = ANDROID_LOG_DEBUG; break; case QtWarningMsg: priority = ANDROID_LOG_WARN; break; case QtCriticalMsg: priority = ANDROID_LOG_ERROR; break; diff --git a/src/corelib/global/qlogging.h b/src/corelib/global/qlogging.h index 68a24d0397..2b798f9ea0 100644 --- a/src/corelib/global/qlogging.h +++ b/src/corelib/global/qlogging.h @@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE class QDebug; class QNoDebug; -enum QtMsgType { QtDebugMsg, QtWarningMsg, QtCriticalMsg, QtFatalMsg, QtTraceMsg, QtSystemMsg = QtCriticalMsg }; +enum QtMsgType { QtDebugMsg, QtWarningMsg, QtCriticalMsg, QtFatalMsg, QtSystemMsg = QtCriticalMsg }; class QMessageLogContext { diff --git a/src/corelib/global/qsysinfo.h b/src/corelib/global/qsysinfo.h index a6accdfebc..38735c12de 100644 --- a/src/corelib/global/qsysinfo.h +++ b/src/corelib/global/qsysinfo.h @@ -96,6 +96,7 @@ public: WV_VISTA = 0x0080, WV_WINDOWS7 = 0x0090, WV_WINDOWS8 = 0x00a0, + WV_WINDOWS8_1 = 0x00b0, WV_NT_based = 0x00f0, /* version numbers */ @@ -106,6 +107,7 @@ public: WV_6_0 = WV_VISTA, WV_6_1 = WV_WINDOWS7, WV_6_2 = WV_WINDOWS8, + WV_6_3 = WV_WINDOWS8_1, WV_CE = 0x0100, WV_CENET = 0x0200, @@ -118,6 +120,7 @@ public: #endif #ifdef Q_OS_MAC +# define Q_MV_IOS(major, minor) (QSysInfo::MV_IOS | major << 4 | minor) enum MacVersion { MV_Unknown = 0x0000, @@ -144,7 +147,17 @@ public: MV_SNOWLEOPARD = MV_10_6, MV_LION = MV_10_7, MV_MOUNTAINLION = MV_10_8, - MV_MAVERICKS = MV_10_9 + MV_MAVERICKS = MV_10_9, + + /* iOS */ + MV_IOS = 1 << 8, + MV_IOS_4_3 = Q_MV_IOS(4, 3), + MV_IOS_5_0 = Q_MV_IOS(5, 0), + MV_IOS_5_1 = Q_MV_IOS(5, 1), + MV_IOS_6_0 = Q_MV_IOS(6, 0), + MV_IOS_6_1 = Q_MV_IOS(6, 1), + MV_IOS_7_0 = Q_MV_IOS(7, 0), + MV_IOS_7_1 = Q_MV_IOS(7, 1) }; static const MacVersion MacintoshVersion; static MacVersion macVersion(); diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index 701f79d21e..0ec3d949b9 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -137,6 +137,8 @@ win32 { mac { macx { SOURCES += io/qstandardpaths_mac.cpp + } else:ios { + OBJECTIVE_SOURCES += io/qstandardpaths_ios.mm } else { SOURCES += io/qstandardpaths_unix.cpp } diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index bb2b2e99f3..624f45caaf 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -1863,9 +1863,12 @@ bool QDir::setCurrent(const QString &path) */ /*! - Returns the absolute path of the application's current directory. + Returns the absolute path of the application's current directory. The + current directory is the last directory set with QDir::setCurrent() or, if + that was never called, the directory at which this application was started + at by the parent process. - \sa current(), setCurrent(), homePath(), rootPath(), tempPath() + \sa current(), setCurrent(), homePath(), rootPath(), tempPath(), QCoreApplication::applicationDirPath() */ QString QDir::currentPath() { @@ -2205,10 +2208,10 @@ QStringList QDir::nameFiltersFromString(const QString &nameFilter) \relates QDir Initializes the resources specified by the \c .qrc file with the - specified base \a name. Normally, Qt resources are loaded - automatically at startup. The Q_INIT_RESOURCE() macro is - necessary on some platforms for resources stored in a static - library. + specified base \a name. Normally, when resources are built as part + of the application, the resources are loaded automatically at + startup. The Q_INIT_RESOURCE() macro is necessary on some platforms + for resources stored in a static library. For example, if your application's resources are listed in a file called \c myapp.qrc, you can ensure that the resources are diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp index 897af352c9..2cf97ef94e 100644 --- a/src/corelib/io/qfileinfo.cpp +++ b/src/corelib/io/qfileinfo.cpp @@ -682,7 +682,7 @@ bool QFileInfo::exists() const \note If \a file is a symlink that points to a non-existing file, false is returned. - \note Using this function is faster for than using + \note Using this function is faster than using \c QFileInfo(file).exists() for file system access. */ bool QFileInfo::exists(const QString &file) diff --git a/src/corelib/io/qfileselector.cpp b/src/corelib/io/qfileselector.cpp index d67ea80e51..72e4198fb0 100644 --- a/src/corelib/io/qfileselector.cpp +++ b/src/corelib/io/qfileselector.cpp @@ -348,22 +348,30 @@ void QFileSelectorPrivate::updateSelectors() QStringList QFileSelectorPrivate::platformSelectors() { QStringList ret; -#if defined(Q_OS_LINUX_ANDROID) +#if defined(Q_OS_WIN) + ret << QStringLiteral("windows"); +# if defined(Q_OS_WINCE) + ret << QStringLiteral("wince"); +# endif +#elif defined(Q_OS_UNIX) + ret << QStringLiteral("unix"); +# if defined(Q_OS_LINUX_ANDROID) ret << QStringLiteral("android"); -#elif defined(Q_OS_BLACKBERRY) +# elif defined(Q_OS_BLACKBERRY) ret << QStringLiteral("blackberry"); -#elif defined(Q_OS_IOS) +# elif defined(Q_OS_QNX) + ret << QStringLiteral("qnx"); +# elif defined(Q_OS_IOS) ret << QStringLiteral("ios"); -#elif defined(Q_OS_WINCE) - ret << QStringLiteral("wince"); -#elif defined(Q_OS_WIN) - ret << QStringLiteral("windows"); -#elif defined(Q_OS_LINUX) +# elif defined(Q_OS_LINUX) ret << QStringLiteral("linux"); -#elif defined(Q_OS_OSX) - ret << QStringLiteral("osx"); -#elif defined(Q_OS_UNIX) - ret << QStringLiteral("generic_unix"); +# elif defined(Q_OS_MAC) + ret << QStringLiteral("mac"); +# else + struct utsname u; + if (uname(&u) != -1) + ret << QString::fromLatin1(u.sysname).toLower(); +# endif #endif return ret; } diff --git a/src/corelib/io/qfileselector.h b/src/corelib/io/qfileselector.h index 9afd985757..cb5f71faae 100644 --- a/src/corelib/io/qfileselector.h +++ b/src/corelib/io/qfileselector.h @@ -52,7 +52,7 @@ class Q_CORE_EXPORT QFileSelector : public QObject { Q_OBJECT public: - QFileSelector(QObject *parent = 0); + explicit QFileSelector(QObject *parent = 0); ~QFileSelector(); QString select(const QString &filePath) const; diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index dc8817706c..d1ef9c1770 100644 --- a/src/corelib/io/qlockfile_unix.cpp +++ b/src/corelib/io/qlockfile_unix.cpp @@ -54,16 +54,17 @@ #include <sys/file.h> // flock #include <sys/types.h> // kill #include <signal.h> // kill +#include <unistd.h> // gethostname QT_BEGIN_NAMESPACE -static QString localHostName() // from QHostInfo::localHostName() +static QByteArray localHostName() // from QHostInfo::localHostName(), modified to return a QByteArray { - char hostName[512]; - if (gethostname(hostName, sizeof(hostName)) == -1) - return QString(); - hostName[sizeof(hostName) - 1] = '\0'; - return QString::fromLocal8Bit(hostName); + QByteArray hostName(512, Qt::Uninitialized); + if (gethostname(hostName.data(), hostName.size()) == -1) + return QByteArray(); + hostName.truncate(strlen(hostName.data())); + return hostName; } // ### merge into qt_safe_write? @@ -145,7 +146,7 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys() // Use operator% from the fast builder to avoid multiple memory allocations. QByteArray fileData = QByteArray::number(QCoreApplication::applicationPid()) % '\n' % qAppName().toUtf8() % '\n' - % localHostName().toUtf8() % '\n'; + % localHostName() % '\n'; const QByteArray lockFileName = QFile::encodeName(fileName); const int fd = qt_safe_open(lockFileName.constData(), O_WRONLY | O_CREAT | O_EXCL, 0644); @@ -190,7 +191,7 @@ bool QLockFilePrivate::isApparentlyStale() const QString hostname, appname; if (!getLockInfo(&pid, &hostname, &appname)) return false; - if (hostname == localHostName()) { + if (hostname == QString::fromLocal8Bit(localHostName())) { if (::kill(pid, 0) == -1 && errno == ESRCH) return true; // PID doesn't exist anymore } diff --git a/src/corelib/io/qloggingcategory.cpp b/src/corelib/io/qloggingcategory.cpp index 8d337ec630..93a98b1835 100644 --- a/src/corelib/io/qloggingcategory.cpp +++ b/src/corelib/io/qloggingcategory.cpp @@ -75,10 +75,9 @@ Q_GLOBAL_STATIC_WITH_ARGS(QLoggingCategory, qtDefaultCategory, \l isCriticalEnabled(), \l isTraceEnabled(), as well as \l isEnabled() to check whether messages for the given message type should be logged. - \note The qCDebug(), qCWarning(), qCCritical(), qCTrace() and - qCTraceGuard() macros prevent arguments from being evaluated if the - respective message types are not enabled for the category, so explicit - checking is not needed: + \note The qCDebug(), qCWarning(), qCCritical() macros prevent arguments + from being evaluated if the respective message types are not enabled for the + category, so explicit checking is not needed: \snippet qloggingcategory/main.cpp 4 @@ -103,14 +102,6 @@ Q_GLOBAL_STATIC_WITH_ARGS(QLoggingCategory, qtDefaultCategory, \snippet qloggingcategory/main.cpp 3 */ -typedef QVector<QTracer *> Tracers; - -class QLoggingCategoryPrivate -{ -public: - Tracers tracers; -}; - /*! Constructs a QLoggingCategory object with the provided \a category name. The object becomes the local identifier for the category. @@ -118,16 +109,15 @@ public: If \a category is \c{0}, the category name is changed to \c "default". */ QLoggingCategory::QLoggingCategory(const char *category) - : d(new QLoggingCategoryPrivate), + : d(0), name(0), enabledDebug(false), enabledWarning(true), - enabledCritical(true), - enabledTrace(false), - placeholder1(false), - placeholder2(false), - placeholder3(false) + enabledCritical(true) { + Q_UNUSED(d); + Q_UNUSED(placeholder); + bool isDefaultCategory = (category == 0) || (strcmp(category, qtDefaultCategoryName) == 0); @@ -151,7 +141,6 @@ QLoggingCategory::~QLoggingCategory() { if (QLoggingRegistry *reg = QLoggingRegistry::instance()) reg->unregisterCategory(this); - delete d; } /*! @@ -194,18 +183,6 @@ QLoggingCategory::~QLoggingCategory() */ /*! - \fn bool QLoggingCategory::isTraceEnabled() const - - Returns \c true if the tracers associated with this category should - receive messages. Returns \c false otherwise. - - \note The \l qCTrace() and \l qCTraceGuard() macros already do this check - before executing any - code. However, calling this method may be useful to avoid - expensive generation of data that is only used for debug output. -*/ - -/*! Returns \c true if a message of type \a msgtype for the category should be shown. Returns \c false otherwise. */ @@ -215,7 +192,6 @@ bool QLoggingCategory::isEnabled(QtMsgType msgtype) const case QtDebugMsg: return enabledDebug; case QtWarningMsg: return enabledWarning; case QtCriticalMsg: return enabledCritical; - case QtTraceMsg: return enabledTrace; case QtFatalMsg: return true; } return false; @@ -237,7 +213,6 @@ void QLoggingCategory::setEnabled(QtMsgType type, bool enable) case QtDebugMsg: enabledDebug = enable; break; case QtWarningMsg: enabledWarning = enable; break; case QtCriticalMsg: enabledCritical = enable; break; - case QtTraceMsg: enabledTrace = enable; break; case QtFatalMsg: break; } } @@ -313,7 +288,7 @@ QLoggingCategory::installFilter(QLoggingCategory::CategoryFilter filter) where \c <category> is the name of the category, potentially with \c{*} as a wildcard symbol at the start and/or the end. The optional \c <type> must - be either \c debug, \c warning, \c critical, or \c trace. + be either \c debug, \c warning, or \c critical. Example: @@ -395,56 +370,6 @@ void QLoggingCategory::setFilterRules(const QString &rules) */ /*! - \relates QLoggingCategory - \macro qCTrace(category) - \since 5.2 - - Returns an output stream for trace messages in the logging category - \a category. - - The macro expands to code that checks whether - \l QLoggingCategory::isTraceEnabled() evaluates to \c true. - If so, the stream arguments are processed and sent to the \l QTracer objects - registered with the category. - - \note Arguments are not processed if trace output for the category is not - enabled, so do not rely on any side effects. - - Example: - - \snippet qtracer/ftracer.cpp 6 - - \sa qCTraceGuard() QTraceGuard -*/ - -/*! - \relates QLoggingCategory - \macro qCTraceGuard(category) - \since 5.2 - - The macro expands to code that creates a guard object with automatic - storage. The guard constructor checks whether - \l QLoggingCategory::isTraceEnabled() evaluates to \c true. - If so, the stream arguments are processed and the \c{start()} - functions of the \l QTracer objects registered with the \a category are - called. - - The guard destructor also checks whether the category is enabled for - tracing and if so, the \c{end()} - functions of the \l QTracer objects registered with the \a category are called. - - \note Arguments are always processed, even if trace output for the - category is disabled. They will, however, in that case not be passed - to the \c{record()} functions of the registered tracers. - - Example: - - \snippet qtracer/ftracer.cpp 4 - - \sa qCTrace() QTracer -*/ - -/*! \macro Q_DECLARE_LOGGING_CATEGORY(name) \relates QLoggingCategory \since 5.2 @@ -469,234 +394,4 @@ void QLoggingCategory::setFilterRules(const QString &rules) This macro must be used outside of a class or method. */ - -/*! - \class QTracer - \inmodule QtCore - \since 5.2 - - \brief The QTracer class provides an interface for handling - trace events associated with a logging category. - - \c QTracer objects are registered with logging categories. - Multiple \c QTracer objects - can be registered with the same category, and the same - \c QTracer object can be registered with different categories. - - If code containing \c qCTrace is executed, and the associated - logging category is enabled for tracing, all \c QTracer objects - that are registered with the category are notified. - - \c QTracer objects -*/ - -/*! - \fn QTracer::QTracer() - - Constructs a tracer object. - - Example: - - \snippet qtracer/ftracer.cpp 2 -*/ - -/*! - \fn QTracer::~QTracer() - - Destroys the tracer object. -*/ - -/*! - Registers this tracer for the \a category. - - The tracer will later be notified of messages of type - \c QtTraceMsg, as long as that message type - is enabled in the category. - - Example: - - \snippet qtracer/ftracer.cpp 1 - \codeline - \snippet qtracer/ftracer.cpp 7 -*/ - -void QTracer::addToCategory(QLoggingCategory &category) -{ - category.d->tracers.append(this); -} - -/*! - \fn void QTracer::start() - - This function is invoked when a tracing activity starts, - typically from the constructor of a \c QTraceGuard object - defined by \c qCTrace() or \c qCTraceGuard(). - - The base implementation does nothing. \c QTracer subclasses - are advised to override it if needed. - - \sa qCTrace(), qCTraceGuard() -*/ - -/*! - \fn void QTracer::end() - - This function is invoked when a tracing activity ends, - typically from the destructor of a \c QTraceGuard object - defined by \c qCTrace() or \c qCTraceGuard(). - - The base implementation does nothing. It is common for - \c QTracer subclasses to override it to perform flushing - of collected data. - - \sa qCTrace(), qCTraceGuard() -*/ - -/*! - \fn void QTracer::record(int data) - - This function is invoked during a tracing activity to - pass integer \a data to the \c QTracer object. - - Example: - - \snippet qtracer/ftracer.cpp 3 -*/ - -/*! - \fn void QTracer::record(const char *data) - - This function is invoked during a tracing activity to - pass string \a data to the \c QTracer object. -*/ - -/*! - \fn void QTracer::record(const QVariant &data) - - This function is invoked during a tracing activity to - pass abitrary (non-integer, non-string) \a data to - the \c QTracer object. -*/ - -/*! - \class QTraceGuard - \since 5.2 - \inmodule QtCore - - \brief The QTraceGuard class facilitates notifications to - \c QTracer objects. - - \c QTraceGuard objects are typically implicitly created on the - stack when using the \c qCTrace or \c qCTraceGuard macros and - are associated to a \c QLoggingCategory. - - The constructor of a \c QTraceGuard objects checks whether - its associated category is enabled, and if so, informs all - \c QTracer objects registered with the category that a - tracing activity starts. - - The destructor of a \c QTraceGuard objects checks whether - its associated category is enabled, and if so, informs all - \c QTracer objects registered with the category that a - tracing activity ended. - - A \c QTraceGuard object created by \c qCTrace will be destroyed - at the end of the full expression, a guard created by - \c qCTraceGuard at the end of the block containing the macro. - - During the lifetime of a QTraceGuard object, its \c operator<<() - can be used to pass additional data to the active tracers. - The fast path handles only \c int and \c{const char *} data, - but it is possible to use arbitrary values wrapped in \c QVariants. - - \sa QTracer -*/ - -/*! - \fn QTraceGuard::QTraceGuard(QLoggingCategory &category) - \internal - - Constructs a trace guard object relaying to \a category. -*/ - -/*! - \fn QTraceGuard::~QTraceGuard() - \internal - - Destroys the trace guard object. -*/ - -/*! - \internal - - Calls \c start() on all registered tracers. -*/ - -void QTraceGuard::start() -{ - const Tracers &tracers = target->d->tracers; - for (int i = tracers.size(); --i >= 0; ) - tracers.at(i)->start(); -} - -/*! - \internal - - Calls \c end() on all registered tracers. -*/ - -void QTraceGuard::end() -{ - const Tracers &tracers = target->d->tracers; - for (int i = tracers.size(); --i >= 0; ) - tracers.at(i)->end(); -} - - -/*! - \internal - - This function is called for int parameters passed to the - qCTrace stream. -*/ - -QTraceGuard &QTraceGuard::operator<<(int msg) -{ - const Tracers &tracers = target->d->tracers; - for (int i = tracers.size(); --i >= 0; ) - tracers.at(i)->record(msg); - return *this; -} - -/*! - \internal - - This function is called for string parameters passed to the - qCTrace stream. -*/ - -QTraceGuard &QTraceGuard::operator<<(const char *msg) -{ - const Tracers &tracers = target->d->tracers; - for (int i = tracers.size(); --i >= 0; ) - tracers.at(i)->record(msg); - return *this; -} - - -/*! - \internal - - This function is called for QVariant parameters passed to the - qCTrace stream. -*/ - -QTraceGuard &QTraceGuard::operator<<(const QVariant &msg) -{ - const Tracers &tracers = target->d->tracers; - for (int i = tracers.size(); --i >= 0; ) - tracers.at(i)->record(msg); - return *this; -} - QT_END_NAMESPACE diff --git a/src/corelib/io/qloggingcategory.h b/src/corelib/io/qloggingcategory.h index 7a119f4937..15c0519827 100644 --- a/src/corelib/io/qloggingcategory.h +++ b/src/corelib/io/qloggingcategory.h @@ -44,14 +44,9 @@ #include <QtCore/qglobal.h> #include <QtCore/qdebug.h> -#include <QtCore/qvector.h> QT_BEGIN_NAMESPACE -class QTracer; -class QTraceGuard; -class QLoggingCategoryPrivate; - class Q_CORE_EXPORT QLoggingCategory { Q_DISABLE_COPY(QLoggingCategory) @@ -65,7 +60,6 @@ public: bool isDebugEnabled() const { return enabledDebug; } bool isWarningEnabled() const { return enabledWarning; } bool isCriticalEnabled() const { return enabledCritical; } - bool isTraceEnabled() const { return enabledTrace; } const char *categoryName() const { return name; } @@ -80,66 +74,13 @@ public: static void setFilterRules(const QString &rules); private: - friend class QLoggingCategoryPrivate; - friend class QLoggingRegistry; - friend class QTraceGuard; - friend class QTracer; - - QLoggingCategoryPrivate *d; + void *d; // reserved for future use const char *name; bool enabledDebug; bool enabledWarning; bool enabledCritical; - bool enabledTrace; - // reserve space for future use - bool placeholder1; - bool placeholder2; - bool placeholder3; -}; - -class Q_CORE_EXPORT QTracer -{ - Q_DISABLE_COPY(QTracer) -public: - QTracer() {} - virtual ~QTracer() {} - - void addToCategory(QLoggingCategory &category); - - virtual void start() {} - virtual void end() {} - virtual void record(int) {} - virtual void record(const char *) {} - virtual void record(const QVariant &) {} -}; - -class Q_CORE_EXPORT QTraceGuard -{ - Q_DISABLE_COPY(QTraceGuard) -public: - QTraceGuard(QLoggingCategory &category) - { - target = category.isTraceEnabled() ? &category : 0; - if (target) - start(); - } - - ~QTraceGuard() - { - if (target) - end(); - } - - QTraceGuard &operator<<(int msg); - QTraceGuard &operator<<(const char *msg); - QTraceGuard &operator<<(const QVariant &msg); - -private: - void start(); - void end(); - - QLoggingCategory *target; + bool placeholder[5]; // reserve for future use }; #define Q_DECLARE_LOGGING_CATEGORY(name) \ @@ -154,7 +95,7 @@ private: } #define qCDebug(category) \ - for (bool enabled = category().isDebugEnabled(); enabled; enabled = false) \ + for (bool enabled = category().isDebugEnabled(); Q_UNLIKELY(enabled); enabled = false) \ QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO, category().categoryName()).debug() #define qCWarning(category) \ for (bool enabled = category().isWarningEnabled(); enabled; enabled = false) \ @@ -162,17 +103,6 @@ private: #define qCCritical(category) \ for (bool enabled = category().isCriticalEnabled(); enabled; enabled = false) \ QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO, category().categoryName()).critical() -#define qCTrace(category) \ - for (bool enabled = category.isTraceEnabled(); enabled; enabled = false) \ - QTraceGuard(category) - - -#define Q_TRACE_GUARD_NAME_HELPER(line) qTraceGuard ## line -#define Q_TRACE_GUARD_NAME(line) Q_TRACE_GUARD_NAME_HELPER(line) - -#define qCTraceGuard(category) \ - QTraceGuard Q_TRACE_GUARD_NAME(__LINE__)(category); - #if defined(QT_NO_DEBUG_OUTPUT) # undef qCDebug diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp index 885b51709d..a82e6f65f4 100644 --- a/src/corelib/io/qloggingregistry.cpp +++ b/src/corelib/io/qloggingregistry.cpp @@ -86,9 +86,6 @@ int QLoggingRule::pass(const QString &categoryName, QtMsgType msgType) const case QtCriticalMsg: fullCategory += QLatin1String(".critical"); break; - case QtTraceMsg: - fullCategory += QLatin1String(".trace"); - break; default: break; } @@ -291,7 +288,6 @@ void QLoggingRegistry::defaultCategoryFilter(QLoggingCategory *cat) bool debug = (cat->categoryName() == qtDefaultCategoryName); bool warning = true; bool critical = true; - bool trace = true; QString categoryName = QLatin1String(cat->categoryName()); QLoggingRegistry *reg = QLoggingRegistry::instance(); @@ -305,15 +301,11 @@ void QLoggingRegistry::defaultCategoryFilter(QLoggingCategory *cat) filterpass = item.pass(categoryName, QtCriticalMsg); if (filterpass != 0) critical = (filterpass > 0); - filterpass = item.pass(categoryName, QtTraceMsg); - if (filterpass != 0) - trace = (filterpass > 0); } cat->setEnabled(QtDebugMsg, debug); cat->setEnabled(QtWarningMsg, warning); cat->setEnabled(QtCriticalMsg, critical); - cat->setEnabled(QtTraceMsg, trace); } diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index a0910869c6..8b67fc1962 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -900,7 +900,9 @@ StNormal: ++j; } -#ifndef QT_NO_TEXTCODEC +#ifdef QT_NO_TEXTCODEC + Q_UNUSED(codec) +#else if (codec) { stringResult += codec->toUnicode(str.constData() + i, j - i); } else diff --git a/src/corelib/io/qsettings_mac.cpp b/src/corelib/io/qsettings_mac.cpp index f6b14c3027..23cff6af27 100644 --- a/src/corelib/io/qsettings_mac.cpp +++ b/src/corelib/io/qsettings_mac.cpp @@ -691,7 +691,8 @@ bool QConfFileSettingsPrivate::writePlistFile(const QString &fileName, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - QCFType<CFDataRef> xmlData = CFPropertyListCreateXMLData(kCFAllocatorDefault, propertyList); + QCFType<CFDataRef> xmlData = CFPropertyListCreateData( + kCFAllocatorDefault, propertyList, kCFPropertyListXMLFormat_v1_0, 0, 0); SInt32 code; return CFURLWriteDataAndPropertiesToResource(urlFromFileName(fileName), xmlData, 0, &code); diff --git a/src/corelib/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp index 5e2428527c..1181d1b980 100644 --- a/src/corelib/io/qstandardpaths.cpp +++ b/src/corelib/io/qstandardpaths.cpp @@ -139,6 +139,9 @@ QT_BEGIN_NAMESPACE \value DownloadLocation Returns a directory for user's downloaded files. This is a generic value. If no directory specific for downloads exists, a sensible fallback for storing user documents is returned. + \value GenericConfigLocation Returns a directory location where user-specific + configuration files shared between multiple applications should be written. + This is a generic value and the returned path is never empty. The following table gives examples of paths on different operating systems. The first path is the writable path (unless noted). Other, additional @@ -499,6 +502,8 @@ QString QStandardPaths::displayName(StandardLocation type) return QCoreApplication::translate("QStandardPaths", "Runtime"); case ConfigLocation: return QCoreApplication::translate("QStandardPaths", "Configuration"); + case GenericConfigLocation: + return QCoreApplication::translate("QStandardPaths", "Shared Configuration"); case GenericCacheLocation: return QCoreApplication::translate("QStandardPaths", "Shared Cache"); case DownloadLocation: @@ -522,7 +527,7 @@ QString QStandardPaths::displayName(StandardLocation type) or writing to the current user's configuration. This affects the locations into which test programs might write files: - GenericDataLocation, DataLocation, ConfigLocation, + GenericDataLocation, DataLocation, ConfigLocation, GenericConfigLocation, GenericCacheLocation, CacheLocation. Other locations are not affected. diff --git a/src/corelib/io/qstandardpaths.h b/src/corelib/io/qstandardpaths.h index df9089ace7..08d6d7b50c 100644 --- a/src/corelib/io/qstandardpaths.h +++ b/src/corelib/io/qstandardpaths.h @@ -69,7 +69,8 @@ public: RuntimeLocation, ConfigLocation, DownloadLocation, - GenericCacheLocation + GenericCacheLocation, + GenericConfigLocation }; static QString writableLocation(StandardLocation type); diff --git a/src/corelib/io/qstandardpaths_blackberry.cpp b/src/corelib/io/qstandardpaths_blackberry.cpp index a801c2fba3..815756ff9a 100644 --- a/src/corelib/io/qstandardpaths_blackberry.cpp +++ b/src/corelib/io/qstandardpaths_blackberry.cpp @@ -75,6 +75,7 @@ QString QStandardPaths::writableLocation(StandardLocation type) case GenericCacheLocation: return QDir::homePath() + testModeInsert() + QLatin1String("/Cache"); case ConfigLocation: + case GenericConfigLocation: return QDir::homePath() + testModeInsert() + QLatin1String("/Settings"); case GenericDataLocation: return sharedRoot + testModeInsert() + QLatin1String("/misc"); diff --git a/src/corelib/io/qstandardpaths_ios.mm b/src/corelib/io/qstandardpaths_ios.mm new file mode 100644 index 0000000000..e2100045a6 --- /dev/null +++ b/src/corelib/io/qstandardpaths_ios.mm @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtCore 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt 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$ +** +****************************************************************************/ + +#import <UIKit/UIKit.h> + +#include "qstandardpaths.h" + +#ifndef QT_NO_STANDARDPATHS + +QT_BEGIN_NAMESPACE + +static QString pathForDirectory(NSSearchPathDirectory directory) +{ + return QString::fromNSString( + [NSSearchPathForDirectoriesInDomains(directory, NSUserDomainMask, YES) lastObject]); +} + +static QString bundlePath() +{ + return QString::fromNSString([[NSBundle mainBundle] bundlePath]); +} + +QString QStandardPaths::writableLocation(StandardLocation type) +{ + QString location; + + switch (type) { + case DesktopLocation: + location = pathForDirectory(NSDesktopDirectory); + break; + case DocumentsLocation: + location = pathForDirectory(NSDocumentDirectory); + break; + case FontsLocation: + location = bundlePath() + QLatin1String("/.fonts"); + break; + case ApplicationsLocation: + location = pathForDirectory(NSApplicationDirectory); + break; + case MusicLocation: + location = pathForDirectory(NSMusicDirectory); + break; + case MoviesLocation: + location = pathForDirectory(NSMoviesDirectory); + break; + case PicturesLocation: + location = pathForDirectory(NSPicturesDirectory); + break; + case TempLocation: + location = QString::fromNSString(NSTemporaryDirectory()); + break; + case HomeLocation: + location = bundlePath(); + break; + case DataLocation: + case GenericDataLocation: + location = pathForDirectory(NSDocumentDirectory); + break; + case CacheLocation: + case GenericCacheLocation: + location = pathForDirectory(NSCachesDirectory); + break; + case ConfigLocation: + case GenericConfigLocation: + location = pathForDirectory(NSDocumentDirectory); + break; + case DownloadLocation: + location = pathForDirectory(NSDownloadsDirectory); + break; + default: + break; + } + + switch (type) { + case RuntimeLocation: + break; + default: + // All other types must return something, so use the document directory + // as a reasonable fall-back (which will always exist). + if (location.isEmpty()) + location = pathForDirectory(NSDocumentDirectory); + break; + } + + return location; +} + +QStringList QStandardPaths::standardLocations(StandardLocation type) +{ + QStringList dirs; + const QString localDir = writableLocation(type); + dirs.prepend(localDir); + return dirs; +} + +QT_END_NAMESPACE + +#endif // QT_NO_STANDARDPATHS diff --git a/src/corelib/io/qstandardpaths_mac.cpp b/src/corelib/io/qstandardpaths_mac.cpp index 6744bfeab4..0efdfae253 100644 --- a/src/corelib/io/qstandardpaths_mac.cpp +++ b/src/corelib/io/qstandardpaths_mac.cpp @@ -58,6 +58,7 @@ OSType translateLocation(QStandardPaths::StandardLocation type) { switch (type) { case QStandardPaths::ConfigLocation: + case QStandardPaths::GenericConfigLocation: return kPreferencesFolderType; case QStandardPaths::DesktopLocation: return kDesktopFolderType; @@ -149,6 +150,7 @@ QString QStandardPaths::writableLocation(StandardLocation type) if (type == CacheLocation) appendOrganizationAndApp(path); return path; + case GenericConfigLocation: case ConfigLocation: return qttestDir + QLatin1String("/Preferences"); default: diff --git a/src/corelib/io/qstandardpaths_unix.cpp b/src/corelib/io/qstandardpaths_unix.cpp index 61e2e03a3d..1b9078f712 100644 --- a/src/corelib/io/qstandardpaths_unix.cpp +++ b/src/corelib/io/qstandardpaths_unix.cpp @@ -103,6 +103,7 @@ QString QStandardPaths::writableLocation(StandardLocation type) return xdgDataHome; } case ConfigLocation: + case GenericConfigLocation: { // http://standards.freedesktop.org/basedir-spec/latest/ QString xdgConfigHome = QFile::decodeName(qgetenv("XDG_CONFIG_HOME")); @@ -277,6 +278,7 @@ QStringList QStandardPaths::standardLocations(StandardLocation type) QStringList dirs; switch (type) { case ConfigLocation: + case GenericConfigLocation: { // http://standards.freedesktop.org/basedir-spec/latest/ const QString xdgConfigDirs = QFile::decodeName(qgetenv("XDG_CONFIG_DIRS")); diff --git a/src/corelib/io/qstandardpaths_win.cpp b/src/corelib/io/qstandardpaths_win.cpp index d4e0779381..6a79c7c00b 100644 --- a/src/corelib/io/qstandardpaths_win.cpp +++ b/src/corelib/io/qstandardpaths_win.cpp @@ -99,7 +99,8 @@ QString QStandardPaths::writableLocation(StandardLocation type) wchar_t path[MAX_PATH]; switch (type) { - case ConfigLocation: // same as DataLocation, on Windows + case ConfigLocation: // same as DataLocation, on Windows (oversight, but too late to fix it) + case GenericConfigLocation: // same as GenericDataLocation, on Windows case DataLocation: case GenericDataLocation: #if defined Q_OS_WINCE @@ -111,7 +112,7 @@ QString QStandardPaths::writableLocation(StandardLocation type) if (isTestModeEnabled()) result += QLatin1String("/qttest"); #ifndef QT_BOOTSTRAPPED - if (type != GenericDataLocation) { + if (type != GenericDataLocation && type != GenericConfigLocation) { if (!QCoreApplication::organizationName().isEmpty()) result += QLatin1Char('/') + QCoreApplication::organizationName(); if (!QCoreApplication::applicationName().isEmpty()) @@ -188,12 +189,13 @@ QStringList QStandardPaths::standardLocations(StandardLocation type) if (SHGetSpecialFolderPath) { wchar_t path[MAX_PATH]; switch (type) { - case ConfigLocation: // same as DataLocation, on Windows + case ConfigLocation: // same as DataLocation, on Windows (oversight, but too late to fix it) + case GenericConfigLocation: // same as GenericDataLocation, on Windows case DataLocation: case GenericDataLocation: if (SHGetSpecialFolderPath(0, path, CSIDL_COMMON_APPDATA, FALSE)) { QString result = convertCharArray(path); - if (type != GenericDataLocation) { + if (type != GenericDataLocation && type != GenericConfigLocation) { #ifndef QT_BOOTSTRAPPED if (!QCoreApplication::organizationName().isEmpty()) result += QLatin1Char('/') + QCoreApplication::organizationName(); diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index fe5faa2be7..77aa3c4821 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -3586,7 +3586,7 @@ bool QUrl::matches(const QUrl &url, FormattingOptions options) const else if (d->fragment != url.d->fragment) return false; - if (!(d->sectionIsPresent & mask) == (url.d->sectionIsPresent & mask)) + if ((d->sectionIsPresent & mask) != (url.d->sectionIsPresent & mask)) return false; // Compare paths, after applying path-related options diff --git a/src/corelib/io/qurl.h b/src/corelib/io/qurl.h index e7edb4365e..602e91ce30 100644 --- a/src/corelib/io/qurl.h +++ b/src/corelib/io/qurl.h @@ -51,8 +51,10 @@ #include <QtCore/qglobal.h> #ifdef Q_OS_MAC -Q_FORWARD_DECLARE_OBJC_CLASS(NSURL); Q_FORWARD_DECLARE_CF_TYPE(CFURL); +# ifdef __OBJC__ +Q_FORWARD_DECLARE_OBJC_CLASS(NSURL); +# endif #endif QT_BEGIN_NAMESPACE @@ -84,36 +86,36 @@ public: inline QUrlTwoFlags &operator^=(E1 f) { i ^= f; return *this; } inline QUrlTwoFlags &operator^=(E2 f) { i ^= f; return *this; } - Q_DECL_CONSTEXPR inline operator QFlags<E1>() const { return E1(i); } - Q_DECL_CONSTEXPR inline operator QFlags<E2>() const { return E2(i); } + Q_DECL_CONSTEXPR inline operator QFlags<E1>() const { return QFlag(i); } + Q_DECL_CONSTEXPR inline operator QFlags<E2>() const { return QFlag(i); } Q_DECL_CONSTEXPR inline operator int() const { return i; } Q_DECL_CONSTEXPR inline bool operator!() const { return !i; } Q_DECL_CONSTEXPR inline QUrlTwoFlags operator|(QUrlTwoFlags f) const - { return QUrlTwoFlags(E1(i | f.i)); } + { return QUrlTwoFlags(QFlag(i | f.i)); } Q_DECL_CONSTEXPR inline QUrlTwoFlags operator|(E1 f) const - { return QUrlTwoFlags(E1(i | f)); } + { return QUrlTwoFlags(QFlag(i | f)); } Q_DECL_CONSTEXPR inline QUrlTwoFlags operator|(E2 f) const - { return QUrlTwoFlags(E2(i | f)); } + { return QUrlTwoFlags(QFlag(i | f)); } Q_DECL_CONSTEXPR inline QUrlTwoFlags operator^(QUrlTwoFlags f) const - { return QUrlTwoFlags(E1(i ^ f.i)); } + { return QUrlTwoFlags(QFlag(i ^ f.i)); } Q_DECL_CONSTEXPR inline QUrlTwoFlags operator^(E1 f) const - { return QUrlTwoFlags(E1(i ^ f)); } + { return QUrlTwoFlags(QFlag(i ^ f)); } Q_DECL_CONSTEXPR inline QUrlTwoFlags operator^(E2 f) const - { return QUrlTwoFlags(E2(i ^ f)); } + { return QUrlTwoFlags(QFlag(i ^ f)); } Q_DECL_CONSTEXPR inline QUrlTwoFlags operator&(int mask) const - { return QUrlTwoFlags(E1(i & mask)); } + { return QUrlTwoFlags(QFlag(i & mask)); } Q_DECL_CONSTEXPR inline QUrlTwoFlags operator&(uint mask) const - { return QUrlTwoFlags(E1(i & mask)); } + { return QUrlTwoFlags(QFlag(i & mask)); } Q_DECL_CONSTEXPR inline QUrlTwoFlags operator&(E1 f) const - { return QUrlTwoFlags(E1(i & f)); } + { return QUrlTwoFlags(QFlag(i & f)); } Q_DECL_CONSTEXPR inline QUrlTwoFlags operator&(E2 f) const - { return QUrlTwoFlags(E2(i & f)); } + { return QUrlTwoFlags(QFlag(i & f)); } Q_DECL_CONSTEXPR inline QUrlTwoFlags operator~() const - { return QUrlTwoFlags(E1(~i)); } + { return QUrlTwoFlags(QFlag(~i)); } - inline bool testFlag(E1 f) const { return (i & f) == f && (f != 0 || i == int(f)); } - inline bool testFlag(E2 f) const { return (i & f) == f && (f != 0 || i == int(f)); } + Q_DECL_CONSTEXPR inline bool testFlag(E1 f) const { return (i & f) == f && (f != 0 || i == int(f)); } + Q_DECL_CONSTEXPR inline bool testFlag(E2 f) const { return (i & f) == f && (f != 0 || i == int(f)); } }; template<typename E1, typename E2> @@ -265,8 +267,10 @@ public: #if defined(Q_OS_MAC) || defined(Q_QDOC) static QUrl fromCFURL(CFURLRef url); CFURLRef toCFURL() const Q_DECL_CF_RETURNS_RETAINED; +# if defined(__OBJC__) || defined(Q_QDOC) static QUrl fromNSURL(const NSURL *url); NSURL *toNSURL() const Q_DECL_NS_RETURNS_AUTORELEASED; +# endif #endif #if QT_DEPRECATED_SINCE(5,0) diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri index 998bf56874..4c43f292fb 100644 --- a/src/corelib/kernel/kernel.pri +++ b/src/corelib/kernel/kernel.pri @@ -110,6 +110,9 @@ mac:!nacl { kernel/qcore_mac.cpp OBJECTIVE_SOURCES += \ kernel/qcore_mac_objc.mm + + # We need UIKit for UIDevice + ios: LIBS_PRIVATE += -framework UIKit } nacl { diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm index 7b9eb67969..73f8296021 100644 --- a/src/corelib/kernel/qcore_mac_objc.mm +++ b/src/corelib/kernel/qcore_mac_objc.mm @@ -41,6 +41,10 @@ #include <private/qcore_mac_p.h> +#ifdef Q_OS_IOS +#import <UIKit/UIKit.h> +#endif + QT_BEGIN_NAMESPACE NSString *QCFString::toNSString(const QString &string) @@ -54,5 +58,31 @@ QString QCFString::toQString(const NSString *nsstr) return toQString(reinterpret_cast<CFStringRef>(nsstr)); } +#ifdef Q_OS_IOS +QSysInfo::MacVersion qt_ios_version() +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + int major = 0, minor = 0; + NSArray *components = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:@"."]; + switch ([components count]) { + case 3: + // We don't care about the patch version + case 2: + minor = [[components objectAtIndex:1] intValue]; + // fall through + case 1: + major = [[components objectAtIndex:0] intValue]; + break; + default: + Q_UNREACHABLE(); + } + + [pool release]; + + return QSysInfo::MacVersion(Q_MV_IOS(major, minor)); +} +#endif + QT_END_NAMESPACE diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index fa911fb967..f491be9768 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -143,6 +143,10 @@ private: QString string; }; +#ifdef Q_OS_IOS +QSysInfo::MacVersion qt_ios_version(); +#endif + QT_END_NAMESPACE #endif // QCORE_MAC_P_H diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 00e98a69bc..e83a6e2ac4 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -151,23 +151,21 @@ QString QCoreApplicationPrivate::macMenuBarName() #endif QString QCoreApplicationPrivate::appName() const { - static QBasicMutex applicationNameMutex; - QMutexLocker locker(&applicationNameMutex); - - if (applicationName.isNull()) { + QString applicationName; #ifdef Q_OS_MAC - applicationName = macMenuBarName(); + applicationName = macMenuBarName(); #endif - if (applicationName.isEmpty() && argv[0]) { - char *p = strrchr(argv[0], '/'); - applicationName = QString::fromLocal8Bit(p ? p + 1 : argv[0]); - } + if (applicationName.isEmpty() && argv[0]) { + char *p = strrchr(argv[0], '/'); + applicationName = QString::fromLocal8Bit(p ? p + 1 : argv[0]); } return applicationName; } #endif +QString *QCoreApplicationPrivate::cachedApplicationFilePath = 0; + bool QCoreApplicationPrivate::checkInstance(const char *function) { bool b = (QCoreApplication::self != 0); @@ -433,6 +431,7 @@ QCoreApplicationPrivate::~QCoreApplicationPrivate() #ifdef Q_OS_WIN delete [] origArgv; #endif + QCoreApplicationPrivate::clearApplicationFilePath(); } #ifndef QT_NO_QOBJECT @@ -1041,7 +1040,7 @@ bool QCoreApplication::closingDown() You can call this function occasionally when your program is busy performing a long operation (e.g. copying a file). - In event you are running a local loop which calls this function + In the event that you are running a local loop which calls this function continuously, without an event loop, the \l{QEvent::DeferredDelete}{DeferredDelete} events will not be processed. This can affect the behaviour of widgets, @@ -1898,6 +1897,20 @@ QString QCoreApplication::translate(const char *context, const char *sourceText, #endif //QT_NO_TRANSLATE +// Makes it possible to point QCoreApplication to a custom location to ensure +// the directory is added to the patch, and qt.conf and deployed plugins are +// found from there. This is for use cases in which QGuiApplication is +// instantiated by a library and not by an application executable, for example, +// Active X servers. + +void QCoreApplicationPrivate::setApplicationFilePath(const QString &path) +{ + if (QCoreApplicationPrivate::cachedApplicationFilePath) + *QCoreApplicationPrivate::cachedApplicationFilePath = path; + else + QCoreApplicationPrivate::cachedApplicationFilePath = new QString(path); +} + /*! Returns the directory that contains the application executable. @@ -1953,20 +1966,28 @@ QString QCoreApplication::applicationFilePath() } QCoreApplicationPrivate *d = self->d_func(); - if (!d->cachedApplicationFilePath.isNull()) - return d->cachedApplicationFilePath; + + static char *procName = d->argv[0]; + if (qstrcmp(procName, d->argv[0]) != 0) { + // clear the cache if the procname changes, so we reprocess it. + QCoreApplicationPrivate::clearApplicationFilePath(); + procName = d->argv[0]; + } + + if (QCoreApplicationPrivate::cachedApplicationFilePath) + return *QCoreApplicationPrivate::cachedApplicationFilePath; #if defined(Q_OS_WIN) - d->cachedApplicationFilePath = QFileInfo(qAppFileName()).filePath(); - return d->cachedApplicationFilePath; + QCoreApplicationPrivate::setApplicationFilePath(QFileInfo(qAppFileName()).filePath()); + return *QCoreApplicationPrivate::cachedApplicationFilePath; #elif defined(Q_OS_BLACKBERRY) if (!arguments().isEmpty()) { // args is never empty, but the navigator can change behaviour some day QFileInfo fileInfo(arguments().at(0)); const bool zygotized = fileInfo.exists(); if (zygotized) { // Handle the zygotized case: - d->cachedApplicationFilePath = QDir::cleanPath(fileInfo.absoluteFilePath()); - return d->cachedApplicationFilePath; + QCoreApplicationPrivate::setApplicationFilePath(QDir::cleanPath(fileInfo.absoluteFilePath())); + return *QCoreApplicationPrivate::cachedApplicationFilePath; } } @@ -1974,7 +1995,7 @@ QString QCoreApplication::applicationFilePath() const size_t maximum_path = static_cast<size_t>(pathconf("/",_PC_PATH_MAX)); char buff[maximum_path+1]; if (_cmdname(buff)) { - d->cachedApplicationFilePath = QDir::cleanPath(QString::fromLocal8Bit(buff)); + QCoreApplicationPrivate::setApplicationFilePath(QDir::cleanPath(QString::fromLocal8Bit(buff))); } else { qWarning("QCoreApplication::applicationFilePath: _cmdname() failed"); // _cmdname() won't fail, but just in case, fallback to the old method @@ -1982,18 +2003,19 @@ QString QCoreApplication::applicationFilePath() QStringList executables = dir.entryList(QDir::Executable | QDir::Files); if (!executables.empty()) { //We assume that there is only one executable in the folder - d->cachedApplicationFilePath = dir.absoluteFilePath(executables.first()); - } else { - d->cachedApplicationFilePath = QString(); + QCoreApplicationPrivate::setApplicationFilePath(dir.absoluteFilePath(executables.first())); } } - return d->cachedApplicationFilePath; + return *QCoreApplicationPrivate::cachedApplicationFilePath; #elif defined(Q_OS_MAC) QString qAppFileName_str = qAppFileName(); if(!qAppFileName_str.isEmpty()) { QFileInfo fi(qAppFileName_str); - d->cachedApplicationFilePath = fi.exists() ? fi.canonicalFilePath() : QString(); - return d->cachedApplicationFilePath; + if (fi.exists()) { + QCoreApplicationPrivate::setApplicationFilePath(fi.canonicalFilePath()); + return *QCoreApplicationPrivate::cachedApplicationFilePath; + } + return QString(); } #endif #if defined( Q_OS_UNIX ) @@ -2002,8 +2024,8 @@ QString QCoreApplication::applicationFilePath() // the absolute path of the executable QFileInfo pfi(QString::fromLatin1("/proc/%1/exe").arg(getpid())); if (pfi.exists() && pfi.isSymLink()) { - d->cachedApplicationFilePath = pfi.canonicalFilePath(); - return d->cachedApplicationFilePath; + QCoreApplicationPrivate::setApplicationFilePath(pfi.canonicalFilePath()); + return *QCoreApplicationPrivate::cachedApplicationFilePath; } # endif if (!arguments().isEmpty()) { @@ -2033,13 +2055,15 @@ QString QCoreApplication::applicationFilePath() absPath = QDir::cleanPath(absPath); QFileInfo fi(absPath); - d->cachedApplicationFilePath = fi.exists() ? fi.canonicalFilePath() : QString(); - } else { - d->cachedApplicationFilePath = QString(); + if (fi.exists()) { + QCoreApplicationPrivate::setApplicationFilePath(fi.canonicalFilePath()); + return *QCoreApplicationPrivate::cachedApplicationFilePath; + } } - return d->cachedApplicationFilePath; + return QString(); #endif + Q_UNREACHABLE(); } /*! diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h index 4b57a7b67d..0c00f396b5 100644 --- a/src/corelib/kernel/qcoreapplication_p.h +++ b/src/corelib/kernel/qcoreapplication_p.h @@ -83,7 +83,6 @@ public: ~QCoreApplicationPrivate(); QString appName() const; - mutable QString applicationName; #ifdef Q_OS_MAC static QString macMenuBarName(); @@ -140,7 +139,9 @@ public: QCoreApplicationPrivate::Type application_type; QString cachedApplicationDirPath; - QString cachedApplicationFilePath; + static QString *cachedApplicationFilePath; + static void setApplicationFilePath(const QString &path); + static inline void clearApplicationFilePath() { delete cachedApplicationFilePath; cachedApplicationFilePath = 0; } #ifndef QT_NO_QOBJECT bool in_exec; diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp index 418074dc7a..65ca6b0dcb 100644 --- a/src/corelib/kernel/qcoreapplication_win.cpp +++ b/src/corelib/kernel/qcoreapplication_win.cpp @@ -831,6 +831,11 @@ QString decodeMSG(const MSG& msg) } break; #endif +#ifdef WM_INPUTLANGCHANGE + case WM_INPUTLANGCHANGE: + parameters = QStringLiteral("Keyboard layout changed"); + break; +#endif // WM_INPUTLANGCHANGE #ifdef WM_NCACTIVATE case WM_NCACTIVATE: { diff --git a/src/corelib/kernel/qeventdispatcher_blackberry.cpp b/src/corelib/kernel/qeventdispatcher_blackberry.cpp index b9137ec139..a52cc60eaa 100644 --- a/src/corelib/kernel/qeventdispatcher_blackberry.cpp +++ b/src/corelib/kernel/qeventdispatcher_blackberry.cpp @@ -237,9 +237,6 @@ void QEventDispatcherBlackberry::registerSocketNotifier(QSocketNotifier *notifie return; } - // Call the base Unix implementation. Needed to allow select() to be called correctly - QEventDispatcherUNIX::registerSocketNotifier(notifier); - // Register the fd with bps BpsChannelScopeSwitcher channelSwitcher(d->bps_channel); int io_events = ioEvents(sockfd); @@ -265,6 +262,9 @@ void QEventDispatcherBlackberry::registerSocketNotifier(QSocketNotifier *notifie const int result = bps_add_fd(sockfd, io_events, &bpsIOHandler, d->ioData.data()); if (Q_UNLIKELY(result != BPS_SUCCESS)) qWarning() << "QEventDispatcherBlackberry: bps_add_fd failed"; + + // Call the base Unix implementation. Needed to allow select() to be called correctly + QEventDispatcherUNIX::registerSocketNotifier(notifier); } void QEventDispatcherBlackberry::unregisterSocketNotifier(QSocketNotifier *notifier) @@ -280,23 +280,22 @@ void QEventDispatcherBlackberry::unregisterSocketNotifier(QSocketNotifier *notif return; } - // Allow the base Unix implementation to unregister the fd too + // Allow the base Unix implementation to unregister the fd too (before call to ioEvents()!) QEventDispatcherUNIX::unregisterSocketNotifier(notifier); // Unregister the fd with bps BpsChannelScopeSwitcher channelSwitcher(d->bps_channel); - const int io_events = ioEvents(sockfd); int result = bps_remove_fd(sockfd); if (Q_UNLIKELY(result != BPS_SUCCESS)) qWarning() << "QEventDispatcherBlackberry: bps_remove_fd failed" << sockfd; - // if no other socket notifier is watching sockfd, our job ends here - if (!io_events) - return; - - result = bps_add_fd(sockfd, io_events, &bpsIOHandler, d->ioData.data()); - if (Q_UNLIKELY(result != BPS_SUCCESS)) - qWarning("QEventDispatcherBlackberry: bps_add_fd error"); + const int io_events = ioEvents(sockfd); + // if other socket notifier is watching sockfd, readd it + if (io_events) { + result = bps_add_fd(sockfd, io_events, &bpsIOHandler, d->ioData.data()); + if (Q_UNLIKELY(result != BPS_SUCCESS)) + qWarning("QEventDispatcherBlackberry: bps_add_fd error"); + } } static inline int timespecToMillisecs(const timespec &tv) diff --git a/src/corelib/kernel/qjni.cpp b/src/corelib/kernel/qjni.cpp index 54cd2b5a75..4e06d12aee 100644 --- a/src/corelib/kernel/qjni.cpp +++ b/src/corelib/kernel/qjni.cpp @@ -162,24 +162,31 @@ static jfieldID getCachedFieldID(JNIEnv *env, return id; } -Q_GLOBAL_STATIC(QThreadStorage<int>, refCount) +class QJNIEnvironmentPrivateTLS +{ +public: + inline ~QJNIEnvironmentPrivateTLS() + { + QtAndroidPrivate::javaVM()->DetachCurrentThread(); + } +}; + +Q_GLOBAL_STATIC(QThreadStorage<QJNIEnvironmentPrivateTLS *>, jniEnvTLS) QJNIEnvironmentPrivate::QJNIEnvironmentPrivate() : jniEnv(0) { JavaVM *vm = QtAndroidPrivate::javaVM(); if (vm->GetEnv((void**)&jniEnv, JNI_VERSION_1_6) == JNI_EDETACHED) { - if (vm->AttachCurrentThread(&jniEnv, 0) < 0) + if (vm->AttachCurrentThread(&jniEnv, 0) != JNI_OK) return; } if (!jniEnv) return; - if (!refCount->hasLocalData()) - refCount->setLocalData(1); - else - refCount->setLocalData(refCount->localData() + 1); + if (!jniEnvTLS->hasLocalData()) + jniEnvTLS->setLocalData(new QJNIEnvironmentPrivateTLS); } JNIEnv *QJNIEnvironmentPrivate::operator->() @@ -194,16 +201,6 @@ QJNIEnvironmentPrivate::operator JNIEnv* () const QJNIEnvironmentPrivate::~QJNIEnvironmentPrivate() { - if (!jniEnv) - return; - - const int newRef = refCount->localData() - 1; - refCount->setLocalData(newRef); - - if (newRef == 0) - QtAndroidPrivate::javaVM()->DetachCurrentThread(); - - jniEnv = 0; } QJNIObjectData::QJNIObjectData() @@ -354,7 +351,9 @@ QJNIObjectPrivate::QJNIObjectPrivate(jobject obj) QJNIEnvironmentPrivate env; d->m_jobject = env->NewGlobalRef(obj); - d->m_jclass = static_cast<jclass>(env->NewGlobalRef(env->GetObjectClass(d->m_jobject))); + jclass objectClass = env->GetObjectClass(d->m_jobject); + d->m_jclass = static_cast<jclass>(env->NewGlobalRef(objectClass)); + env->DeleteLocalRef(objectClass); } template <> @@ -1265,7 +1264,10 @@ QJNIObjectPrivate QJNIObjectPrivate::callObjectMethod(const char *methodName, if (id) { res = env->CallObjectMethodV(d->m_jobject, id, args); } - return res; + + QJNIObjectPrivate obj(res); + env->DeleteLocalRef(res); + return obj; } QJNIObjectPrivate QJNIObjectPrivate::callObjectMethod(const char *methodName, @@ -1342,7 +1344,9 @@ QJNIObjectPrivate QJNIObjectPrivate::callStaticObjectMethod(const char *classNam } } - return res; + QJNIObjectPrivate obj(res); + env->DeleteLocalRef(res); + return obj; } QJNIObjectPrivate QJNIObjectPrivate::callStaticObjectMethod(const char *className, @@ -1369,7 +1373,9 @@ QJNIObjectPrivate QJNIObjectPrivate::callStaticObjectMethod(jclass clazz, res = env->CallStaticObjectMethodV(clazz, id, args); } - return res; + QJNIObjectPrivate obj(res); + env->DeleteLocalRef(res); + return obj; } QJNIObjectPrivate QJNIObjectPrivate::callStaticObjectMethod(jclass clazz, @@ -1681,7 +1687,9 @@ QJNIObjectPrivate QJNIObjectPrivate::getObjectField(const char *fieldName, if (id) res = env->GetObjectField(d->m_jobject, id); - return res; + QJNIObjectPrivate obj(res); + env->DeleteLocalRef(res); + return obj; } QJNIObjectPrivate QJNIObjectPrivate::getStaticObjectField(const char *className, @@ -1707,7 +1715,9 @@ QJNIObjectPrivate QJNIObjectPrivate::getStaticObjectField(jclass clazz, if (id) res = env->GetStaticObjectField(clazz, id); - return res; + QJNIObjectPrivate obj(res); + env->DeleteLocalRef(res); + return obj; } template <> @@ -2109,7 +2119,9 @@ QJNIObjectPrivate QJNIObjectPrivate::fromString(const QString &string) QJNIEnvironmentPrivate env; jstring res = env->NewString(reinterpret_cast<const jchar*>(string.constData()), string.length()); - return res; + QJNIObjectPrivate obj(res); + env->DeleteLocalRef(res); + return obj; } QString QJNIObjectPrivate::toString() const diff --git a/src/corelib/kernel/qjni_p.h b/src/corelib/kernel/qjni_p.h index c5bbae26b9..ab98aec1bf 100644 --- a/src/corelib/kernel/qjni_p.h +++ b/src/corelib/kernel/qjni_p.h @@ -180,7 +180,9 @@ public: d = QSharedPointer<QJNIObjectData>(new QJNIObjectData()); QJNIEnvironmentPrivate env; d->m_jobject = env->NewGlobalRef(jobj); - d->m_jclass = static_cast<jclass>(env->NewGlobalRef(env->GetObjectClass(jobj))); + jclass objectClass = env->GetObjectClass(jobj); + d->m_jclass = static_cast<jclass>(env->NewGlobalRef(objectClass)); + env->DeleteLocalRef(objectClass); } return *this; diff --git a/src/corelib/kernel/qjnihelpers.cpp b/src/corelib/kernel/qjnihelpers.cpp index fbcd0606e6..9ec491f6a9 100644 --- a/src/corelib/kernel/qjnihelpers.cpp +++ b/src/corelib/kernel/qjnihelpers.cpp @@ -94,7 +94,9 @@ jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env) return JNI_ERR; g_jClassLoader = env->NewGlobalRef(classLoader); + env->DeleteLocalRef(classLoader); g_jActivity = env->NewGlobalRef(activity); + env->DeleteLocalRef(activity); g_javaVM = vm; return JNI_OK; diff --git a/src/corelib/kernel/qmath.cpp b/src/corelib/kernel/qmath.cpp index 8f900e2101..b1860fa24a 100644 --- a/src/corelib/kernel/qmath.cpp +++ b/src/corelib/kernel/qmath.cpp @@ -310,8 +310,6 @@ const qreal qt_sine_table[QT_SINE_TABLE_SIZE] = { \brief The <QtMath> header file includes generic math declarations. - The global declarations include \l{functions}. - These functions are partly convenience definitions for basic operations, for instance not available in the Standard Template Library et al. diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 72ce941b6e..29c5a3dd24 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com> ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -177,6 +178,7 @@ private: void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = 0; +void (*QAbstractDeclarativeData::destroyed_qml1)(QAbstractDeclarativeData *, QObject *) = 0; void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = 0; void (*QAbstractDeclarativeData::signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **) = 0; int (*QAbstractDeclarativeData::receivers)(QAbstractDeclarativeData *, const QObject *, int) = 0; @@ -639,7 +641,7 @@ void QMetaCallEvent::placeMetaCall(QObject *object) \li When a QObject is moved to another thread, all its children will be automatically moved too. \li moveToThread() will fail if the QObject has a parent. - \li If \l{QObject}s are created within QThread::run(), they cannot + \li If QObjects are created within QThread::run(), they cannot become children of the QThread object because the QThread does not live in the thread that calls QThread::run(). \endlist @@ -878,8 +880,12 @@ QObject::~QObject() } } - if (d->declarativeData) - QAbstractDeclarativeData::destroyed(d->declarativeData, this); + if (d->declarativeData) { + if (QAbstractDeclarativeData::destroyed) + QAbstractDeclarativeData::destroyed(d->declarativeData, this); + if (QAbstractDeclarativeData::destroyed_qml1) + QAbstractDeclarativeData::destroyed_qml1(d->declarativeData, this); + } // set ref to zero to indicate that this object has been deleted if (d->currentSender != 0) @@ -920,9 +926,9 @@ QObject::~QObject() // The destroy operation must happen outside the lock if (c->isSlotObject) { + c->isSlotObject = false; locker.unlock(); c->slotObj->destroyIfLastRef(); - c->isSlotObject = false; locker.relock(); } c->deref(); @@ -937,15 +943,29 @@ QObject::~QObject() d->connectionLists = 0; } - // disconnect all senders + /* Disconnect all senders: + * This loop basically just does + * for (node = d->senders; node; node = node->next) { ... } + * + * We need to temporarily unlock the receiver mutex to destroy the functors or to lock the + * sender's mutex. And when the mutex is released, node->next might be destroyed by another + * thread. That's why we set node->prev to &node, that way, if node is destroyed, node will + * be updated. + */ QObjectPrivate::Connection *node = d->senders; while (node) { QObject *sender = node->sender; + // Send disconnectNotify before removing the connection from sender's connection list. + // This ensures any eventual destructor of sender will block on getting receiver's lock + // and not finish until we release it. + sender->disconnectNotify(QMetaObjectPrivate::signal(sender->metaObject(), node->signal_index)); QMutex *m = signalSlotLock(sender); node->prev = &node; bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m); //the node has maybe been removed while the mutex was unlocked in relock? if (!node || node->sender != sender) { + // We hold the wrong mutex + Q_ASSERT(needToUnlock); m->unlock(); continue; } @@ -954,8 +974,6 @@ QObject::~QObject() if (senderLists) senderLists->dirty = true; - int signal_index = node->signal_index; - QtPrivate::QSlotObjectBase *slotObj = Q_NULLPTR; if (node->isSlotObject) { slotObj = node->slotObj; @@ -967,12 +985,12 @@ QObject::~QObject() m->unlock(); if (slotObj) { + if (node) + node->prev = &node; locker.unlock(); slotObj->destroyIfLastRef(); locker.relock(); } - - sender->disconnectNotify(QMetaObjectPrivate::signal(sender->metaObject(), signal_index)); } } @@ -1557,12 +1575,12 @@ int QObject::startTimer(int interval, Qt::TimerType timerType) Q_D(QObject); if (interval < 0) { - qWarning("QObject::startTimer: QTimer cannot have a negative interval"); + qWarning("QObject::startTimer: Timers cannot have negative intervals"); return 0; } if (!d->threadData->eventDispatcher.load()) { - qWarning("QObject::startTimer: QTimer can only be used with threads started with QThread"); + qWarning("QObject::startTimer: Timers can only be used with threads started with QThread"); return 0; } int timerId = d->threadData->eventDispatcher.load()->registerTimer(interval, timerType, this); @@ -1931,7 +1949,7 @@ void QObjectPrivate::setParent_helper(QObject *o) } } } - if (!isDeletingChildren && declarativeData) + if (!isDeletingChildren && declarativeData && QAbstractDeclarativeData::parentChanged) QAbstractDeclarativeData::parentChanged(declarativeData, q, o); } @@ -3236,7 +3254,7 @@ bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c, && (slot == 0 || (c->isSlotObject && c->slotObj->compare(slot)))))) { bool needToUnlock = false; QMutex *receiverMutex = 0; - if (!receiver) { + if (c->receiver) { receiverMutex = signalSlotLock(c->receiver); // need to relock this receiver and sender in the correct order needToUnlock = QOrderedMutexLocker::relock(senderMutex, receiverMutex); @@ -3253,9 +3271,9 @@ bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c, c->receiver = 0; if (c->isSlotObject) { + c->isSlotObject = false; senderMutex->unlock(); c->slotObj->destroyIfLastRef(); - c->isSlotObject = false; senderMutex->lock(); } @@ -3284,8 +3302,7 @@ bool QMetaObjectPrivate::disconnect(const QObject *sender, QObject *s = const_cast<QObject *>(sender); QMutex *senderMutex = signalSlotLock(sender); - QMutex *receiverMutex = receiver ? signalSlotLock(receiver) : 0; - QOrderedMutexLocker locker(senderMutex, receiverMutex); + QMutexLocker locker(senderMutex); QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists; if (!connectionLists) @@ -4213,7 +4230,7 @@ QDebug operator<<(QDebug dbg, const QObject *o) { \macro Q_INVOKABLE \relates QObject - Apply this macro to definitions of member functions to allow them to + Apply this macro to declarations of member functions to allow them to be invoked via the meta-object system. The macro is written before the return type, as shown in the following example: @@ -4230,7 +4247,7 @@ QDebug operator<<(QDebug dbg, const QObject *o) { \macro Q_REVISION \relates QObject - Apply this macro to definitions of member functions to tag them with a + Apply this macro to declarations of member functions to tag them with a revision number in the meta-object system. The macro is written before the return type, as shown in the following example: @@ -4695,7 +4712,7 @@ bool QObjectPrivate::disconnect(const QObject *sender, int signal_index, void ** It can be used to disconnect that connection, or check if the connection was successful - \sa QObject::disconnect + \sa QObject::disconnect() */ /*! diff --git a/src/corelib/kernel/qobject_impl.h b/src/corelib/kernel/qobject_impl.h index 1bbd548be6..d2996e6e4d 100644 --- a/src/corelib/kernel/qobject_impl.h +++ b/src/corelib/kernel/qobject_impl.h @@ -99,6 +99,8 @@ namespace QtPrivate { template <typename ArgList, bool Declared = TypesAreDeclaredMetaType<ArgList>::Value > struct ConnectionTypes { static const int *types() { return 0; } }; + template <> struct ConnectionTypes<List<>, true> + { static const int *types() { return 0; } }; template <typename... Args> struct ConnectionTypes<List<Args...>, true> { static const int *types() { static const int t[sizeof...(Args) + 1] = { (QtPrivate::QMetaTypeIdHelper<Args>::qt_metatype_id())..., 0 }; return t; } }; #endif diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index f5745515c9..cd2d592cec 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -90,6 +90,7 @@ class Q_CORE_EXPORT QAbstractDeclarativeData { public: static void (*destroyed)(QAbstractDeclarativeData *, QObject *); + static void (*destroyed_qml1)(QAbstractDeclarativeData *, QObject *); static void (*parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *); static void (*signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **); static int (*receivers)(QAbstractDeclarativeData *, const QObject *, int); diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index db3b96d202..91ccf3996e 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com> ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -221,6 +222,19 @@ static qlonglong qConvertToNumber(const QVariant::Private *d, bool *ok) return qlonglong(qMetaTypeUNumber(d)); } + if (QMetaType::typeFlags(d->type) & QMetaType::IsEnumeration) { + switch (QMetaType::sizeOf(d->type)) { + case 1: + return d->is_shared ? *reinterpret_cast<signed char *>(d->data.shared->ptr) : d->data.sc; + case 2: + return d->is_shared ? *reinterpret_cast<qint16 *>(d->data.shared->ptr) : d->data.s; + case 4: + return d->is_shared ? *reinterpret_cast<qint32 *>(d->data.shared->ptr) : d->data.i; + case 8: + return d->is_shared ? *reinterpret_cast<qint64 *>(d->data.shared->ptr) : d->data.ll; + } + } + *ok = false; return Q_INT64_C(0); } @@ -256,6 +270,19 @@ static qulonglong qConvertToUnsignedNumber(const QVariant::Private *d, bool *ok) return qMetaTypeUNumber(d); } + if (QMetaType::typeFlags(d->type) & QMetaType::IsEnumeration) { + switch (QMetaType::sizeOf(d->type)) { + case 1: + return d->is_shared ? *reinterpret_cast<uchar *>(d->data.shared->ptr) : d->data.uc; + case 2: + return d->is_shared ? *reinterpret_cast<quint16 *>(d->data.shared->ptr) : d->data.us; + case 4: + return d->is_shared ? *reinterpret_cast<quint32 *>(d->data.shared->ptr) : d->data.u; + case 8: + return d->is_shared ? *reinterpret_cast<qint64 *>(d->data.shared->ptr) : d->data.ull; + } + } + *ok = false; return Q_UINT64_C(0); } @@ -888,15 +915,13 @@ static bool customCompare(const QVariant::Private *a, const QVariant::Private *b static bool customConvert(const QVariant::Private *d, int t, void *result, bool *ok) { if (d->type >= QMetaType::User || t >= QMetaType::User) { - const bool isOk = QMetaType::convert(constData(*d), d->type, result, t); - if (ok) - *ok = isOk; - return isOk; + if (QMetaType::convert(constData(*d), d->type, result, t)) { + if (ok) + *ok = true; + return true; + } } - - if (ok) - *ok = false; - return false; + return convert(d, t, result, ok); } #if !defined(QT_NO_DEBUG_STREAM) @@ -2854,8 +2879,13 @@ bool QVariant::canConvert(int targetTypeId) const if (targetTypeId < 0) return false; - if (targetTypeId >= QMetaType::User) - return canConvertMetaObject(currentType, targetTypeId, d.data.o); + if (targetTypeId >= QMetaType::User) { + if (QMetaType::typeFlags(targetTypeId) & QMetaType::IsEnumeration) { + targetTypeId = QMetaType::Int; + } else { + return canConvertMetaObject(currentType, targetTypeId, d.data.o); + } + } if (currentType == QMetaType::QJsonValue) { switch (targetTypeId) { @@ -2888,13 +2918,16 @@ bool QVariant::canConvert(int targetTypeId) const return true; // fall through case QVariant::UInt: + case QVariant::LongLong: + case QVariant::ULongLong: return currentType == QMetaType::ULong || currentType == QMetaType::Long || currentType == QMetaType::UShort || currentType == QMetaType::UChar || currentType == QMetaType::Char || currentType == QMetaType::SChar - || currentType == QMetaType::Short; + || currentType == QMetaType::Short + || QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration; case QVariant::Image: return currentType == QVariant::Pixmap || currentType == QVariant::Bitmap; case QVariant::Pixmap: @@ -2923,7 +2956,9 @@ bool QVariant::canConvert(int targetTypeId) const case QMetaType::ULong: case QMetaType::Short: case QMetaType::UShort: - return qCanConvertMatrix[QVariant::Int] & (1 << currentType) || currentType == QVariant::Int; + return qCanConvertMatrix[QVariant::Int] & (1 << currentType) + || currentType == QVariant::Int + || QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration; case QMetaType::QObjectStar: return canConvertMetaObject(currentType, targetTypeId, d.data.o); default: @@ -2974,7 +3009,8 @@ bool QVariant::convert(int targetTypeId) } bool isOk = true; - if (!handlerManager[d.type]->convert(&oldValue.d, targetTypeId, data(), &isOk)) + int converterType = std::max(oldValue.userType(), targetTypeId); + if (!handlerManager[converterType]->convert(&oldValue.d, targetTypeId, data(), &isOk)) isOk = false; d.is_null = !isOk; return isOk; diff --git a/src/corelib/kernel/qwineventnotifier.h b/src/corelib/kernel/qwineventnotifier.h index 56605d9aaa..cddb9d73be 100644 --- a/src/corelib/kernel/qwineventnotifier.h +++ b/src/corelib/kernel/qwineventnotifier.h @@ -45,7 +45,6 @@ #include "QtCore/qobject.h" #ifdef Q_OS_WIN -#include "QtCore/qt_windows.h" QT_BEGIN_NAMESPACE @@ -54,6 +53,7 @@ class Q_CORE_EXPORT QWinEventNotifier : public QObject { Q_OBJECT Q_DECLARE_PRIVATE(QWinEventNotifier) + typedef Qt::HANDLE HANDLE; public: explicit QWinEventNotifier(QObject *parent = 0); diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp index aa03395f94..bdea75a3b9 100644 --- a/src/corelib/mimetypes/qmimeprovider.cpp +++ b/src/corelib/mimetypes/qmimeprovider.cpp @@ -53,6 +53,11 @@ #include <QDateTime> #include <QtEndian> +static void initResources() +{ + Q_INIT_RESOURCE(mimetypes); +} + QT_BEGIN_NAMESPACE static QString fallbackParent(const QString &mimeTypeName) @@ -704,6 +709,7 @@ void QMimeBinaryProvider::loadGenericIcon(QMimeTypePrivate &data) QMimeXMLProvider::QMimeXMLProvider(QMimeDatabasePrivate *db) : QMimeProviderBase(db), m_loaded(false) { + initResources(); } bool QMimeXMLProvider::isValid() diff --git a/src/corelib/plugin/quuid.h b/src/corelib/plugin/quuid.h index 31b9890351..a0d2923bed 100644 --- a/src/corelib/plugin/quuid.h +++ b/src/corelib/plugin/quuid.h @@ -82,7 +82,7 @@ public: Sha1 = 5 // 0 1 0 1 }; -#if defined(Q_COMPILER_INITIALIZER_LISTS) && !defined(Q_QDOC) +#if defined(Q_COMPILER_UNIFORM_INIT) && !defined(Q_QDOC) Q_DECL_CONSTEXPR QUuid() : data1(0), data2(0), data3(0), data4{0,0,0,0,0,0,0,0} {} Q_DECL_CONSTEXPR QUuid(uint l, ushort w1, ushort w2, uchar b1, uchar b2, uchar b3, @@ -147,7 +147,7 @@ public: #if defined(Q_OS_WIN) // On Windows we have a type GUID that is used by the platform API, so we // provide convenience operators to cast from and to this type. -#if defined(Q_COMPILER_INITIALIZER_LISTS) && !defined(Q_QDOC) +#if defined(Q_COMPILER_UNIFORM_INIT) && !defined(Q_QDOC) Q_DECL_CONSTEXPR QUuid(const GUID &guid) : data1(guid.Data1), data2(guid.Data2), data3(guid.Data3), data4{guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], diff --git a/src/corelib/thread/qbasicatomic.h b/src/corelib/thread/qbasicatomic.h index ddcc25f7b7..782ae90698 100644 --- a/src/corelib/thread/qbasicatomic.h +++ b/src/corelib/thread/qbasicatomic.h @@ -137,12 +137,11 @@ public: typename Ops::Type _q_value; - // Non-atomic API + // Everything below is either implemented in ../arch/qatomic_XXX.h or (as fallback) in qgenericatomic.h + T load() const Q_DECL_NOTHROW { return Ops::load(_q_value); } void store(T newValue) Q_DECL_NOTHROW { Ops::store(_q_value, newValue); } - // Atomic API, implemented in qatomic_XXX.h - T loadAcquire() const Q_DECL_NOTHROW { return Ops::loadAcquire(_q_value); } void storeRelease(T newValue) Q_DECL_NOTHROW { Ops::storeRelease(_q_value, newValue); } diff --git a/src/corelib/thread/qreadwritelock.cpp b/src/corelib/thread/qreadwritelock.cpp index e4cdf7a985..ffda3c4fad 100644 --- a/src/corelib/thread/qreadwritelock.cpp +++ b/src/corelib/thread/qreadwritelock.cpp @@ -98,7 +98,7 @@ QT_BEGIN_NAMESPACE \since 4.4 \value Recursive In this mode, a thread can lock the same - QReadWriteLock multiple times and the mutex won't be unlocked + QReadWriteLock multiple times. The QReadWriteLock won't be unlocked until a corresponding number of unlock() calls have been made. \value NonRecursive In this mode, a thread may only lock a diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index 3de1e991c1..903e72c151 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -232,7 +232,7 @@ void qt_watch_adopted_thread(const HANDLE adoptedThreadHandle, QThread *qthread) qt_adopted_thread_handles.prepend(qt_adopted_thread_wakeup); } - CreateThread(0, 0, qt_adopted_thread_watcher_function, 0, 0, &qt_adopted_thread_watcher_id); + CloseHandle(CreateThread(0, 0, qt_adopted_thread_watcher_function, 0, 0, &qt_adopted_thread_watcher_id)); } else { SetEvent(qt_adopted_thread_wakeup); } diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index eb06bd4713..03b10903ab 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -1854,7 +1854,7 @@ QByteArray &QByteArray::remove(int pos, int len) if (len <= 0 || uint(pos) >= uint(d->size)) return *this; detach(); - if (pos + len >= d->size) { + if (len >= d->size - pos) { resize(pos); } else { memmove(d->data() + pos, d->data() + pos + len, d->size - pos - len); diff --git a/src/corelib/tools/qcollator.cpp b/src/corelib/tools/qcollator.cpp index a3a9ef940b..9c97d6b158 100644 --- a/src/corelib/tools/qcollator.cpp +++ b/src/corelib/tools/qcollator.cpp @@ -99,7 +99,7 @@ QCollator::QCollator(const QCollator &other) */ QCollator::~QCollator() { - if (!d->ref.deref()) + if (d && !d->ref.deref()) delete d; } @@ -109,14 +109,41 @@ QCollator::~QCollator() QCollator &QCollator::operator=(const QCollator &other) { if (this != &other) { - if (!d->ref.deref()) + if (d && !d->ref.deref()) delete d; d = other.d; - d->ref.ref(); + if (d) d->ref.ref(); } return *this; } +/* + \fn void QCollator::QCollator(QCollator &&other) + + Move constructor. Moves from \a other into this collator. + + Note that a moved-from QCollator can only be destroyed or assigned + to. The effect of calling other functions than the destructor or + one of the assignment operators is undefined. +*/ + +/* + \fn QCollator &QCollator::operator=(QCollator &&other) + + Move-assigns from \a other to this collator. + + Note that a moved-from QCollator can only be destroyed or assigned + to. The effect of calling other functions than the destructor or + one of the assignment operators is undefined. +*/ + +/*! + \fn void QCollator::swap(QCollator &other) + + Swaps this collator with \a other. This function is very fast and + never fails. +*/ + /*! \internal */ @@ -301,12 +328,13 @@ QCollatorSortKey& QCollatorSortKey::operator=(const QCollatorSortKey &other) } /*! - \fn bool QCollatorSortKey::operator<(const QCollatorSortKey &otherKey) const + \fn bool operator<(const QCollatorSortKey &lhs, const QCollatorSortKey &rhs) + \relates QCollatorSortKey - According to the QCollator that created the key, returns \c true if the - key should be sorted before than \a otherKey; otherwise returns \c false. + According to the QCollator that created the keys, returns \c true if \a lhs + should be sorted before \a rhs; otherwise returns \c false. - \sa compare() + \sa QCollatorSortKey::compare() */ /*! diff --git a/src/corelib/tools/qcollator.h b/src/corelib/tools/qcollator.h index b99fd1c0cc..781e95b10c 100644 --- a/src/corelib/tools/qcollator.h +++ b/src/corelib/tools/qcollator.h @@ -61,10 +61,11 @@ public: QCollatorSortKey &operator=(const QCollatorSortKey &other); #ifdef Q_COMPILER_RVALUE_REFS inline QCollatorSortKey &operator=(QCollatorSortKey &&other) - { qSwap(d, other.d); return *this; } + { swap(other); return *this; } #endif + void swap(QCollatorSortKey &other) + { d.swap(other.d); } - bool operator<(const QCollatorSortKey &key) const; int compare(const QCollatorSortKey &key) const; protected: @@ -76,13 +77,27 @@ private: QCollatorSortKey(); }; +inline bool operator<(const QCollatorSortKey &lhs, const QCollatorSortKey &rhs) +{ + return lhs.compare(rhs) < 0; +} + class Q_CORE_EXPORT QCollator { public: - QCollator(const QLocale &locale = QLocale()); + explicit QCollator(const QLocale &locale = QLocale()); QCollator(const QCollator &); ~QCollator(); QCollator &operator=(const QCollator &); +#ifdef Q_COMPILER_RVALUE_REFS + QCollator(QCollator &&other) + : d(other.d) { other.d = 0; } + QCollator &operator=(QCollator &&other) + { swap(other); return *this; } +#endif + + void swap(QCollator &other) + { qSwap(d, other.d); } void setLocale(const QLocale &locale); QLocale locale() const; @@ -111,6 +126,9 @@ private: void detach(); }; +Q_DECLARE_SHARED(QCollatorSortKey) +Q_DECLARE_SHARED(QCollator) + QT_END_NAMESPACE #endif // QCOLLATOR_P_H diff --git a/src/corelib/tools/qcollator_icu.cpp b/src/corelib/tools/qcollator_icu.cpp index 46f830a34c..407a493d25 100644 --- a/src/corelib/tools/qcollator_icu.cpp +++ b/src/corelib/tools/qcollator_icu.cpp @@ -151,11 +151,6 @@ QCollatorSortKey QCollator::sortKey(const QString &string) const return QCollatorSortKey(new QCollatorSortKeyPrivate(result)); } -bool QCollatorSortKey::operator<(const QCollatorSortKey &otherKey) const -{ - return d->m_key < otherKey.d->m_key; -} - int QCollatorSortKey::compare(const QCollatorSortKey &otherKey) const { return qstrcmp(d->m_key, otherKey.d->m_key); diff --git a/src/corelib/tools/qcollator_macx.cpp b/src/corelib/tools/qcollator_macx.cpp index 8edd190fbe..8985cd4eba 100644 --- a/src/corelib/tools/qcollator_macx.cpp +++ b/src/corelib/tools/qcollator_macx.cpp @@ -162,11 +162,6 @@ QCollatorSortKey QCollator::sortKey(const QString &string) const return QCollatorSortKey(new QCollatorSortKeyPrivate(ret)); } -bool QCollatorSortKey::operator<(const QCollatorSortKey &key) const -{ - return compare(key) < 0; -} - int QCollatorSortKey::compare(const QCollatorSortKey &key) const { SInt32 order; diff --git a/src/corelib/tools/qcollator_posix.cpp b/src/corelib/tools/qcollator_posix.cpp index a43618dcf1..b47b546d01 100644 --- a/src/corelib/tools/qcollator_posix.cpp +++ b/src/corelib/tools/qcollator_posix.cpp @@ -135,11 +135,6 @@ QCollatorSortKey QCollator::sortKey(const QString &string) const return QCollatorSortKey(new QCollatorSortKeyPrivate(result)); } -bool QCollatorSortKey::operator<(const QCollatorSortKey &otherKey) const -{ - return compare(otherKey) < 0; -} - int QCollatorSortKey::compare(const QCollatorSortKey &otherKey) const { return std::wcscmp(d->m_key.constData(), diff --git a/src/corelib/tools/qcollator_win.cpp b/src/corelib/tools/qcollator_win.cpp index 6cc15891f5..9a672a0505 100644 --- a/src/corelib/tools/qcollator_win.cpp +++ b/src/corelib/tools/qcollator_win.cpp @@ -179,11 +179,6 @@ QCollatorSortKey QCollator::sortKey(const QString &string) const return QCollatorSortKey(new QCollatorSortKeyPrivate(ret)); } -bool QCollatorSortKey::operator<(const QCollatorSortKey &otherKey) const -{ - return d->m_key < otherKey.d->m_key; -} - int QCollatorSortKey::compare(const QCollatorSortKey &otherKey) const { return d->m_key.compare(otherKey.d->m_key); diff --git a/src/corelib/tools/qcommandlineparser.cpp b/src/corelib/tools/qcommandlineparser.cpp index 8054542333..5463e4f0c1 100644 --- a/src/corelib/tools/qcommandlineparser.cpp +++ b/src/corelib/tools/qcommandlineparser.cpp @@ -845,11 +845,50 @@ static QString wrapText(const QString &names, int longestOptionNameString, const { const QLatin1Char nl('\n'); QString text = QStringLiteral(" ") + names.leftJustified(longestOptionNameString) + QLatin1Char(' '); - const int leftColumnWidth = text.length(); - const int rightColumnWidth = 79 - leftColumnWidth; - text += description.left(rightColumnWidth) + nl; - for (int n = rightColumnWidth; n < description.length(); n += rightColumnWidth) - text += QStringLiteral(" ").repeated(leftColumnWidth) + description.mid(n, rightColumnWidth) + nl; + const int indent = text.length(); + int lineStart = 0; + int lastBreakable = -1; + const int max = 79 - indent; + int x = 0; + const int len = description.length(); + + for (int i = 0; i < len; ++i) { + ++x; + const QChar c = description.at(i); + if (c.isSpace()) + lastBreakable = i; + + int breakAt = -1; + int nextLineStart = -1; + if (x > max && lastBreakable != -1) { + // time to break and we know where + breakAt = lastBreakable; + nextLineStart = lastBreakable + 1; + } else if ((x > max - 1 && lastBreakable == -1) || i == len - 1) { + // time to break but found nowhere [-> break here], or end of last line + breakAt = i + 1; + nextLineStart = breakAt; + } else if (c == nl) { + // forced break + breakAt = i; + nextLineStart = i + 1; + } + + if (breakAt != -1) { + const int numChars = breakAt - lineStart; + //qDebug() << "breakAt=" << description.at(breakAt) << "breakAtSpace=" << breakAtSpace << lineStart << "to" << breakAt << description.mid(lineStart, numChars); + if (lineStart > 0) + text += QString(indent, QLatin1Char(' ')); + text += description.midRef(lineStart, numChars) + nl; + x = 0; + lastBreakable = -1; + lineStart = nextLineStart; + if (lineStart < len && description.at(lineStart).isSpace()) + ++lineStart; // don't start a line with a space + i = lineStart; + } + } + return text; } diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index 6620c55a0f..a95c7f53f7 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -2685,10 +2685,10 @@ void QDateTimePrivate::getDateTime(QDate *date, QTime *time) const { msecsToTime(m_msecs, date, time); - if (isNullDate()) + if (date && isNullDate()) *date = QDate(); - if (isNullTime()) + if (time && isNullTime()) *time = QTime(); } @@ -2768,9 +2768,6 @@ void QDateTimePrivate::refreshDateTime() } // We have a valid date and time and a Qt::LocalTime or Qt::TimeZone that needs calculating - QDate date; - QTime time; - getDateTime(&date, &time); // LocalTime and TimeZone might fall into "missing" DaylightTime transition hour // Calling toEpochMSecs will adjust the returned date/time if it does QDate testDate; @@ -2784,7 +2781,7 @@ void QDateTimePrivate::refreshDateTime() epochMSecs = zoneMSecsToEpochMSecs(m_msecs, m_timeZone, &testDate, &testTime); #endif // QT_BOOTSTRAPPED } - if (testDate == date && testTime == time) { + if (timeToMSecs(testDate, testTime) == m_msecs) { setValidDateTime(); // Cache the offset to use in toMSecsSinceEpoch() m_offsetFromUtc = (m_msecs - epochMSecs) / 1000; @@ -3097,9 +3094,10 @@ bool QDateTime::isValid() const QDate QDateTime::date() const { + if (d->isNullDate()) + return QDate(); QDate dt; - QTime tm; - d->getDateTime(&dt, &tm); + msecsToTime(d->m_msecs, &dt, 0); return dt; } @@ -3111,9 +3109,10 @@ QDate QDateTime::date() const QTime QDateTime::time() const { - QDate dt; + if (d->isNullTime()) + return QTime(); QTime tm; - d->getDateTime(&dt, &tm); + msecsToTime(d->m_msecs, 0, &tm); return tm; } diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index fb233c0640..0eb202c5e2 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -531,7 +531,11 @@ static const QLocaleData *default_data = 0; static uint default_number_options = 0; static const QLocaleData *const c_data = locale_data; -static QLocalePrivate c_private = { c_data, Q_BASIC_ATOMIC_INITIALIZER(1), 0 }; +static QLocalePrivate *c_private() +{ + static QLocalePrivate c_locale = { c_data, Q_BASIC_ATOMIC_INITIALIZER(1), 0 }; + return &c_locale; +} #ifndef QT_NO_SYSTEMLOCALE @@ -700,7 +704,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(QSharedDataPointer<QLocalePrivate>, defaultLocalePriva static QLocalePrivate *localePrivateByName(const QString &name) { if (name == QLatin1String("C")) - return &c_private; + return c_private(); return QLocalePrivate::create(findLocaleData(name)); } @@ -708,7 +712,7 @@ static QLocalePrivate *findLocalePrivate(QLocale::Language language, QLocale::Sc QLocale::Country country) { if (language == QLocale::C) - return &c_private; + return c_private(); const QLocaleData *data = QLocaleData::findLocaleData(language, script, country); diff --git a/src/corelib/tools/qlocale_blackberry.cpp b/src/corelib/tools/qlocale_blackberry.cpp index e2dfa6c801..48faa73070 100644 --- a/src/corelib/tools/qlocale_blackberry.cpp +++ b/src/corelib/tools/qlocale_blackberry.cpp @@ -68,17 +68,20 @@ QBBSystemLocaleData::QBBSystemLocaleData() , measurementNotifier(0) , hourNotifier(0) { + // Do not use qWarning to log warnings if qt_safe_open fails to open the pps file + // since the user code may install a message handler that invokes QLocale API again + // (i.e QDate, QDateTime, ...) which will cause a deadlock. if ((measurementFd = qt_safe_open(ppsUomPath, O_RDONLY)) == -1) - qWarning("Failed to open uom pps, errno=%d", errno); + fprintf(stderr, "Failed to open uom pps, errno=%d\n", errno); if ((regionFd = qt_safe_open(ppsRegionLocalePath, O_RDONLY)) == -1) - qWarning("Failed to open region pps, errno=%d", errno); + fprintf(stderr, "Failed to open region pps, errno=%d\n", errno); if ((languageFd = qt_safe_open(ppsLanguageLocalePath, O_RDONLY)) == -1) - qWarning("Failed to open language pps, errno=%d", errno); + fprintf(stderr, "Failed to open language pps, errno=%d\n", errno); if ((hourFd = qt_safe_open(ppsHourFormatPath, O_RDONLY)) == -1) - qWarning("Failed to open hour format pps, errno=%d", errno); + fprintf(stderr, "Failed to open hour format pps, errno=%d\n", errno); // we cannot call this directly, because by the time this constructor is // called, the event dispatcher has not yet been created, causing the @@ -186,8 +189,12 @@ QByteArray QBBSystemLocaleData::readPpsValue(const char *ppsObject, int ppsFd) char buffer[ppsBufferSize]; int bytes = qt_safe_read(ppsFd, buffer, ppsBufferSize - 1); + // This method is called in the ctor(), so do not use qWarning to log warnings + // if qt_safe_read fails to read the pps file + // since the user code may install a message handler that invokes QLocale API again + // (i.e QDate, QDateTime, ...) which will cause a deadlock. if (bytes == -1) { - qWarning("Failed to read Locale pps, errno=%d", errno); + fprintf(stderr, "Failed to read pps object:%s, errno=%d\n", ppsObject, errno); return result; } // ensure data is null terminated diff --git a/src/corelib/tools/qmap.cpp b/src/corelib/tools/qmap.cpp index 9aebbb7b3c..22d744f869 100644 --- a/src/corelib/tools/qmap.cpp +++ b/src/corelib/tools/qmap.cpp @@ -897,6 +897,7 @@ void QMapDataBase::freeData(QMapDataBase *d) */ /*! \fn const Key &QMap::firstKey() const + \since 5.2 Returns a reference to the smallest key in the map. This function assumes that the map is not empty. @@ -907,6 +908,7 @@ void QMapDataBase::freeData(QMapDataBase *d) */ /*! \fn const Key &QMap::lastKey() const + \since 5.2 Returns a reference to the largest key in the map. This function assumes that the map is not empty. @@ -917,6 +919,7 @@ void QMapDataBase::freeData(QMapDataBase *d) */ /*! \fn T &QMap::first() + \since 5.2 Returns a reference to the first value in the map, that is the value mapped to the smallest key. This function assumes that the map is not empty. @@ -927,11 +930,13 @@ void QMapDataBase::freeData(QMapDataBase *d) */ /*! \fn const T &QMap::first() const + \since 5.2 \overload */ /*! \fn T &QMap::last() + \since 5.2 Returns a reference to the last value in the map, that is the value mapped to the largest key. This function assumes that the map is not empty. @@ -942,6 +947,7 @@ void QMapDataBase::freeData(QMapDataBase *d) */ /*! \fn const T &QMap::last() const + \since 5.2 \overload */ diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 150adfe192..77d002e4d5 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -455,8 +455,8 @@ const QString::Null QString::null = { }; your applications will be easy to translate if you want to expand your application's market at some point. The two main cases where QByteArray is appropriate are when you need to store raw binary - data, and when memory conservation is critical (e.g., with - \l{Qt for Embedded Linux}). + data, and when memory conservation is critical (like in embedded + systems). \tableofcontents @@ -5048,7 +5048,7 @@ int QString::compare_helper(const QChar *data1, int length1, QLatin1String s2, On Mac OS X since Qt 4.3, this function compares according the "Order for sorted lists" setting in the International preferences panel. - \sa compare(), QTextCodec::locale() + \sa compare(), QLocale */ /*! @@ -8463,7 +8463,7 @@ QStringRef QStringRef::appendTo(QString *string) const On Mac OS X, this function compares according the "Order for sorted lists" setting in the International prefereces panel. - \sa compare(), QTextCodec::locale() + \sa compare(), QLocale */ /*! diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 3933e3978e..798ff2f3e0 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -65,8 +65,10 @@ namespace std #endif #ifdef Q_OS_MAC -Q_FORWARD_DECLARE_OBJC_CLASS(NSString); Q_FORWARD_DECLARE_CF_TYPE(CFString); +# ifdef __OBJC__ +Q_FORWARD_DECLARE_OBJC_CLASS(NSString); +# endif #endif QT_BEGIN_NAMESPACE @@ -682,8 +684,10 @@ public: #if defined(Q_OS_MAC) || defined(Q_QDOC) static QString fromCFString(CFStringRef string); CFStringRef toCFString() const Q_DECL_CF_RETURNS_RETAINED; +# if defined(__OBJC__) || defined(Q_QDOC) static QString fromNSString(const NSString *string); NSString *toNSString() const Q_DECL_NS_RETURNS_AUTORELEASED; +# endif #endif // compatibility struct Null { }; diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/tools/qtimezone.cpp index 9c7c54ea09..24c20b46c7 100644 --- a/src/corelib/tools/qtimezone.cpp +++ b/src/corelib/tools/qtimezone.cpp @@ -107,7 +107,7 @@ public: QTimeZoneSingleton() : backend(newBackendTimeZone()) {} // The backend_tz is the tz to use in static methods such as availableTimeZoneIds() and - // isTimeZoneIdAvailable() and to create named Olsen time zones. This is usually the host + // isTimeZoneIdAvailable() and to create named IANA time zones. This is usually the host // system, but may be different if the host resources are insufficient or if // QT_NO_SYSTEMLOCALE is set. A simple UTC backend is used if no alternative is available. QSharedDataPointer<QTimeZonePrivate> backend; @@ -137,18 +137,21 @@ Q_GLOBAL_STATIC(QTimeZoneSingleton, global_tz); \section1 - \section2 Olsen Time Zone IDs + \section2 IANA Time Zone IDs - QTimeZone uses the Olsen time zone IDs as defined in the IANA Time Zone + QTimeZone uses the IANA time zone IDs as defined in the IANA Time Zone Database (http://www.iana.org/time-zones). This is to ensure a standard ID - across all supported platforms. Most platforms support the Olsen IDs + across all supported platforms. Most platforms support the IANA IDs and the IANA Database natively, but for Windows a mapping is required to the native IDs. See below for more details. - The Olsen IDs can and do change on a regular basis, and can vary depending + The IANA IDs can and do change on a regular basis, and can vary depending on how recently the host system data was updated. As such you cannot rely on any given ID existing on any host system. You must use - availableTimeZoneIds() to determine what Olsen IDs are available. + availableTimeZoneIds() to determine what IANA IDs are available. + + The IANA IDs and database are also know as the Olson IDs and database, + named after their creator. \section2 UTC Offset Time Zones @@ -167,7 +170,7 @@ Q_GLOBAL_STATIC(QTimeZoneSingleton, global_tz); the current year. QTimeZone uses a conversion table derived form the Unicode CLDR data to map - between Olsen IDs and Windows IDs. Depending on your version of Windows + between IANA IDs and Windows IDs. Depending on your version of Windows and Qt, this table may not be able to provide a valid conversion, in which "UTC" will be returned. @@ -182,7 +185,7 @@ Q_GLOBAL_STATIC(QTimeZoneSingleton, global_tz); If you require a QDateTime that uses the current system time zone at any given moment then you should use a Qt::TimeSpec of Qt::LocalTime. - The method systemTimeZoneId() returns the current system Olsen time zone + The method systemTimeZoneId() returns the current system IANA time zone ID which on OSX and Linux will always be correct. On Windows this ID is translated from the the Windows system ID using an internal translation table and the user's selected country. As a consequence there is a small @@ -325,7 +328,7 @@ QTimeZone::QTimeZone() } /*! - Creates an instance of the requested time zone \a olsenId. + Creates an instance of the requested time zone \a ianaId. The ID must be one of the available system IDs otherwise an invalid time zone will be returned. @@ -333,14 +336,14 @@ QTimeZone::QTimeZone() \sa availableTimeZoneIds() */ -QTimeZone::QTimeZone(const QByteArray &olsenId) +QTimeZone::QTimeZone(const QByteArray &ianaId) { // Try and see if it's a valid UTC offset ID, just as quick to try create as look-up - d = new QUtcTimeZonePrivate(olsenId); + d = new QUtcTimeZonePrivate(ianaId); // If not a valid UTC offset ID then try create it with the system backend // Relies on backend not creating valid tz with invalid name if (!d->isValid()) - d = newBackendTimeZone(olsenId); + d = newBackendTimeZone(ianaId); } /*! @@ -361,14 +364,14 @@ QTimeZone::QTimeZone(int offsetSeconds) } /*! - Creates a custom time zone with an ID of \a olsenId and an offset from UTC + Creates a custom time zone with an ID of \a ianaId and an offset from UTC of \a offsetSeconds. The \a name will be the name used by displayName() for the LongName, the \a abbreviation will be used by displayName() for the ShortName and by abbreviation(), and the optional \a country will be used by country(). The \a comment is an optional note that may be displayed in a GUI to assist users in selecting a time zone. - The \a olsenId must not be one of the available system IDs returned by + The \a ianaId must not be one of the available system IDs returned by availableTimeZoneIds(). The \a offsetSeconds from UTC must be in the range -14 hours to +14 hours. @@ -376,12 +379,12 @@ QTimeZone::QTimeZone(int offsetSeconds) default value of QLocale::AnyCountry. */ -QTimeZone::QTimeZone(const QByteArray &olsenId, int offsetSeconds, const QString &name, +QTimeZone::QTimeZone(const QByteArray &ianaId, int offsetSeconds, const QString &name, const QString &abbreviation, QLocale::Country country, const QString &comment) { - // olsenId must be a valid ID and must not clash with the standard system names - if (QTimeZonePrivate::isValidId(olsenId) && !availableTimeZoneIds().contains(olsenId)) - d = new QUtcTimeZonePrivate(olsenId, offsetSeconds, name, abbreviation, country, comment); + // ianaId must be a valid ID and must not clash with the standard system names + if (QTimeZonePrivate::isValidId(ianaId) && !availableTimeZoneIds().contains(ianaId)) + d = new QUtcTimeZonePrivate(ianaId, offsetSeconds, name, abbreviation, country, comment); else d = 0; } @@ -424,13 +427,18 @@ QTimeZone &QTimeZone::operator=(const QTimeZone &other) return *this; } +/* + \fn void QTimeZone::swap(QTimeZone &other) + + Swaps this timezone with \a other. This function is very fast and + never fails. +*/ + /*! \fn QTimeZone &QTimeZone::operator=(QTimeZone &&other) Move-assigns \a other to this QTimeZone instance, transferring the ownership of the managed pointer to this instance. - - \since 5.2 */ /*! @@ -470,10 +478,10 @@ bool QTimeZone::isValid() const } /*! - Returns the Olsen ID for the time zone. + Returns the IANA ID for the time zone. - Olsen IDs are used on all platforms. On Windows these are translated - from the Windows ID into the closest Olsen ID for the time zone and country. + IANA IDs are used on all platforms. On Windows these are translated + from the Windows ID into the closest IANA ID for the time zone and country. */ QByteArray QTimeZone::id() const @@ -702,6 +710,9 @@ bool QTimeZone::hasTransitions() const This is most useful when you have a Transition time and wish to find the Transition after it. + If there is no transition after the given \a afterDateTime then an invalid + OffsetData will be returned with an invalid QDateTime. + The given \a afterDateTime is exclusive. \sa hasTransitions(), previousTransition(), transitions() @@ -720,6 +731,9 @@ QTimeZone::OffsetData QTimeZone::nextTransition(const QDateTime &afterDateTime) This is most useful when you have a Transition time and wish to find the Transition before it. + If there is no transition before the given \a beforeDateTime then an invalid + OffsetData will be returned with an invalid QDateTime. + The given \a beforeDateTime is exclusive. \sa hasTransitions(), nextTransition(), transitions() @@ -757,7 +771,7 @@ QTimeZone::OffsetDataList QTimeZone::transitions(const QDateTime &fromDateTime, // Static methods /*! - Returns the current system time zone Olsen ID. + Returns the current system time zone IANA ID. On Windows this ID is translated from the the Windows ID using an internal translation table and the user's selected country. As a consequence there @@ -771,20 +785,20 @@ QByteArray QTimeZone::systemTimeZoneId() } /*! - Returns \c true if a given time zone \a olsenId is available on this system. + Returns \c true if a given time zone \a ianaId is available on this system. \sa availableTimeZoneIds() */ -bool QTimeZone::isTimeZoneIdAvailable(const QByteArray &olsenId) +bool QTimeZone::isTimeZoneIdAvailable(const QByteArray &ianaId) { // isValidId is not strictly required, but faster to weed out invalid // IDs as availableTimeZoneIds() may be slow - return (QTimeZonePrivate::isValidId(olsenId) && (availableTimeZoneIds().contains(olsenId))); + return (QTimeZonePrivate::isValidId(ianaId) && (availableTimeZoneIds().contains(ianaId))); } /*! - Returns a list of all available Olsen time zone IDs on this system. + Returns a list of all available IANA time zone IDs on this system. \sa isTimeZoneIdAvailable() */ @@ -799,7 +813,7 @@ QList<QByteArray> QTimeZone::availableTimeZoneIds() } /*! - Returns a list of all available Olsen time zone IDs for a given \a country. + Returns a list of all available IANA time zone IDs for a given \a country. As a special case, a \a country of Qt::AnyCountry returns those time zones that do not have any country related to them, such as UTC. If you require @@ -819,7 +833,7 @@ QList<QByteArray> QTimeZone::availableTimeZoneIds(QLocale::Country country) } /*! - Returns a list of all available Olsen time zone IDs with a given standard + Returns a list of all available IANA time zone IDs with a given standard time offset of \a offsetSeconds. \sa isTimeZoneIdAvailable() @@ -835,79 +849,79 @@ QList<QByteArray> QTimeZone::availableTimeZoneIds(int offsetSeconds) } /*! - Returns the Windows ID equivalent to the given \a olsenId. + Returns the Windows ID equivalent to the given \a ianaId. - \sa windowsIdToDefaultOlsenId(), windowsIdToOlsenIds() + \sa windowsIdToDefaultIanaId(), windowsIdToIanaIds() */ -QByteArray QTimeZone::olsenIdToWindowsId(const QByteArray &olsenId) +QByteArray QTimeZone::ianaIdToWindowsId(const QByteArray &ianaId) { - return QTimeZonePrivate::olsenIdToWindowsId(olsenId); + return QTimeZonePrivate::ianaIdToWindowsId(ianaId); } /*! - Returns the default Olsen ID for a given \a windowsId. + Returns the default IANA ID for a given \a windowsId. - Because a Windows ID can cover several Olsen IDs in several different - countries, this function returns the most frequently used Olsen ID with no + Because a Windows ID can cover several IANA IDs in several different + countries, this function returns the most frequently used IANA ID with no regard for the country and should thus be used with care. It is usually best to request the default for a specific country. - \sa olsenIdToWindowsId(), windowsIdToOlsenIds() + \sa ianaIdToWindowsId(), windowsIdToIanaIds() */ -QByteArray QTimeZone::windowsIdToDefaultOlsenId(const QByteArray &windowsId) +QByteArray QTimeZone::windowsIdToDefaultIanaId(const QByteArray &windowsId) { - return QTimeZonePrivate::windowsIdToDefaultOlsenId(windowsId); + return QTimeZonePrivate::windowsIdToDefaultIanaId(windowsId); } /*! - Returns the default Olsen ID for a given \a windowsId and \a country. + Returns the default IANA ID for a given \a windowsId and \a country. - Because a Windows ID can cover several Olsen IDs within a given country, - the most frequently used Olsen ID in that country is returned. + Because a Windows ID can cover several IANA IDs within a given country, + the most frequently used IANA ID in that country is returned. - As a special case, QLocale::AnyCountry returns the default of those Olsen IDs + As a special case, QLocale::AnyCountry returns the default of those IANA IDs that do not have any specific country. - \sa olsenIdToWindowsId(), windowsIdToOlsenIds() + \sa ianaIdToWindowsId(), windowsIdToIanaIds() */ -QByteArray QTimeZone::windowsIdToDefaultOlsenId(const QByteArray &windowsId, +QByteArray QTimeZone::windowsIdToDefaultIanaId(const QByteArray &windowsId, QLocale::Country country) { - return QTimeZonePrivate::windowsIdToDefaultOlsenId(windowsId, country); + return QTimeZonePrivate::windowsIdToDefaultIanaId(windowsId, country); } /*! - Returns all the Olsen IDs for a given \a windowsId. + Returns all the IANA IDs for a given \a windowsId. The returned list is sorted alphabetically. - \sa olsenIdToWindowsId(), windowsIdToDefaultOlsenId() + \sa ianaIdToWindowsId(), windowsIdToDefaultIanaId() */ -QList<QByteArray> QTimeZone::windowsIdToOlsenIds(const QByteArray &windowsId) +QList<QByteArray> QTimeZone::windowsIdToIanaIds(const QByteArray &windowsId) { - return QTimeZonePrivate::windowsIdToOlsenIds(windowsId); + return QTimeZonePrivate::windowsIdToIanaIds(windowsId); } /*! - Returns all the Olsen IDs for a given \a windowsId and \a country. + Returns all the IANA IDs for a given \a windowsId and \a country. - As a special case QLocale::AnyCountry returns those Olsen IDs that do + As a special case QLocale::AnyCountry returns those IANA IDs that do not have any specific country. The returned list is in order of frequency of usage, i.e. larger zones within a country are listed first. - \sa olsenIdToWindowsId(), windowsIdToDefaultOlsenId() + \sa ianaIdToWindowsId(), windowsIdToDefaultIanaId() */ -QList<QByteArray> QTimeZone::windowsIdToOlsenIds(const QByteArray &windowsId, +QList<QByteArray> QTimeZone::windowsIdToIanaIds(const QByteArray &windowsId, QLocale::Country country) { - return QTimeZonePrivate::windowsIdToOlsenIds(windowsId, country); + return QTimeZonePrivate::windowsIdToIanaIds(windowsId, country); } #ifndef QT_NO_DATASTREAM diff --git a/src/corelib/tools/qtimezone.h b/src/corelib/tools/qtimezone.h index 1a6a923cf4..b038d66a65 100644 --- a/src/corelib/tools/qtimezone.h +++ b/src/corelib/tools/qtimezone.h @@ -77,9 +77,9 @@ public: typedef QVector<OffsetData> OffsetDataList; QTimeZone(); - explicit QTimeZone(const QByteArray &olsenId); - QTimeZone(int offsetSeconds); - QTimeZone(const QByteArray &zoneId, int offsetSeconds, const QString &name, + explicit QTimeZone(const QByteArray &ianaId); + explicit QTimeZone(int offsetSeconds); + /*implicit*/ QTimeZone(const QByteArray &zoneId, int offsetSeconds, const QString &name, const QString &abbreviation, QLocale::Country country = QLocale::AnyCountry, const QString &comment = QString()); QTimeZone(const QTimeZone &other); @@ -87,9 +87,12 @@ public: QTimeZone &operator=(const QTimeZone &other); #ifdef Q_COMPILER_RVALUE_REFS - QTimeZone &operator=(QTimeZone &&other) { std::swap(d, other.d); return *this; } + QTimeZone &operator=(QTimeZone &&other) { swap(other); return *this; } #endif + void swap(QTimeZone &other) + { d.swap(other.d); } + bool operator==(const QTimeZone &other) const; bool operator!=(const QTimeZone &other) const; @@ -123,18 +126,18 @@ public: static QByteArray systemTimeZoneId(); - static bool isTimeZoneIdAvailable(const QByteArray &olsenId); + static bool isTimeZoneIdAvailable(const QByteArray &ianaId); static QList<QByteArray> availableTimeZoneIds(); static QList<QByteArray> availableTimeZoneIds(QLocale::Country country); static QList<QByteArray> availableTimeZoneIds(int offsetSeconds); - static QByteArray olsenIdToWindowsId(const QByteArray &olsenId); - static QByteArray windowsIdToDefaultOlsenId(const QByteArray &windowsId); - static QByteArray windowsIdToDefaultOlsenId(const QByteArray &windowsId, + static QByteArray ianaIdToWindowsId(const QByteArray &ianaId); + static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId); + static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId, QLocale::Country country); - static QList<QByteArray> windowsIdToOlsenIds(const QByteArray &windowsId); - static QList<QByteArray> windowsIdToOlsenIds(const QByteArray &windowsId, + static QList<QByteArray> windowsIdToIanaIds(const QByteArray &windowsId); + static QList<QByteArray> windowsIdToIanaIds(const QByteArray &windowsId, QLocale::Country country); private: @@ -149,6 +152,7 @@ private: }; Q_DECLARE_TYPEINFO(QTimeZone::OffsetData, Q_MOVABLE_TYPE); +Q_DECLARE_SHARED(QTimeZone) #ifndef QT_NO_DATASTREAM Q_CORE_EXPORT QDataStream &operator<<(QDataStream &ds, const QTimeZone &tz); diff --git a/src/corelib/tools/qtimezoneprivate.cpp b/src/corelib/tools/qtimezoneprivate.cpp index 8d5d60bf37..08a5ce0861 100644 --- a/src/corelib/tools/qtimezoneprivate.cpp +++ b/src/corelib/tools/qtimezoneprivate.cpp @@ -264,7 +264,8 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs) // If the local msecs is less than the real local time of the transition // then get the previous transition to use instead if (forLocalMSecs < tran.atMSecsSinceEpoch + (tran.offsetFromUtc * 1000)) { - while (forLocalMSecs < tran.atMSecsSinceEpoch + (tran.offsetFromUtc * 1000)) { + while (tran.atMSecsSinceEpoch != invalidMSecs() + && forLocalMSecs < tran.atMSecsSinceEpoch + (tran.offsetFromUtc * 1000)) { nextTran = tran; tran = previousTransition(tran.atMSecsSinceEpoch); } @@ -272,7 +273,8 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs) // The zone msecs is after the transition, so check it is before the next tran // If not try use the next transition instead nextTran = nextTransition(tran.atMSecsSinceEpoch); - while (forLocalMSecs >= nextTran.atMSecsSinceEpoch + (nextTran.offsetFromUtc * 1000)) { + while (nextTran.atMSecsSinceEpoch != invalidMSecs() + && forLocalMSecs >= nextTran.atMSecsSinceEpoch + (nextTran.offsetFromUtc * 1000)) { tran = nextTran; nextTran = nextTransition(tran.atMSecsSinceEpoch); } @@ -292,7 +294,8 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs) // then use the prev tran as we default to the FirstOccurrence // TODO Check if faster to just always get prev tran, or if faster using 6 hour check. Data dstTran = previousTransition(tran.atMSecsSinceEpoch); - if (dstTran.daylightTimeOffset > 0 && diffPrevTran < (dstTran.daylightTimeOffset * 1000)) + if (dstTran.atMSecsSinceEpoch != invalidMSecs() + && dstTran.daylightTimeOffset > 0 && diffPrevTran < (dstTran.daylightTimeOffset * 1000)) tran = dstTran; } else if (diffNextTran >= 0 && diffNextTran <= (nextTran.daylightTimeOffset * 1000)) { // If time falls within last hour of standard time then is actually the missing hour @@ -328,10 +331,11 @@ QTimeZonePrivate::DataList QTimeZonePrivate::transitions(qint64 fromMSecsSinceEp qint64 toMSecsSinceEpoch) const { DataList list; - if (toMSecsSinceEpoch > fromMSecsSinceEpoch) { + if (toMSecsSinceEpoch >= fromMSecsSinceEpoch) { // fromMSecsSinceEpoch is inclusive but nextTransitionTime() is exclusive so go back 1 msec Data next = nextTransition(fromMSecsSinceEpoch - 1); - while (next.atMSecsSinceEpoch <= toMSecsSinceEpoch) { + while (next.atMSecsSinceEpoch != invalidMSecs() + && next.atMSecsSinceEpoch <= toMSecsSinceEpoch) { list.append(next); next = nextTransition(next.atMSecsSinceEpoch); } @@ -477,7 +481,7 @@ QString QTimeZonePrivate::isoOffsetFormat(int offsetFromUtc) .arg(qAbs(mins) % 60, 2, 10, QLatin1Char('0')); } -QByteArray QTimeZonePrivate::olsenIdToWindowsId(const QByteArray &id) +QByteArray QTimeZonePrivate::ianaIdToWindowsId(const QByteArray &id) { for (int i = 0; i < zoneDataTableSize; ++i) { const QZoneData *data = zoneData(i); @@ -487,7 +491,7 @@ QByteArray QTimeZonePrivate::olsenIdToWindowsId(const QByteArray &id) return QByteArray(); } -QByteArray QTimeZonePrivate::windowsIdToDefaultOlsenId(const QByteArray &windowsId) +QByteArray QTimeZonePrivate::windowsIdToDefaultIanaId(const QByteArray &windowsId) { const quint16 windowsIdKey = toWindowsIdKey(windowsId); for (int i = 0; i < windowsDataTableSize; ++i) { @@ -498,17 +502,17 @@ QByteArray QTimeZonePrivate::windowsIdToDefaultOlsenId(const QByteArray &windows return QByteArray(); } -QByteArray QTimeZonePrivate::windowsIdToDefaultOlsenId(const QByteArray &windowsId, +QByteArray QTimeZonePrivate::windowsIdToDefaultIanaId(const QByteArray &windowsId, QLocale::Country country) { - const QList<QByteArray> list = windowsIdToOlsenIds(windowsId, country); + const QList<QByteArray> list = windowsIdToIanaIds(windowsId, country); if (list.count() > 0) return list.first(); else return QByteArray(); } -QList<QByteArray> QTimeZonePrivate::windowsIdToOlsenIds(const QByteArray &windowsId) +QList<QByteArray> QTimeZonePrivate::windowsIdToIanaIds(const QByteArray &windowsId) { const quint16 windowsIdKey = toWindowsIdKey(windowsId); QList<QByteArray> list; @@ -524,7 +528,7 @@ QList<QByteArray> QTimeZonePrivate::windowsIdToOlsenIds(const QByteArray &window return list; } -QList<QByteArray> QTimeZonePrivate::windowsIdToOlsenIds(const QByteArray &windowsId, +QList<QByteArray> QTimeZonePrivate::windowsIdToIanaIds(const QByteArray &windowsId, QLocale::Country country) { const quint16 windowsIdKey = toWindowsIdKey(windowsId); diff --git a/src/corelib/tools/qtimezoneprivate_mac.mm b/src/corelib/tools/qtimezoneprivate_mac.mm index 8d319aebbd..69d2c42d27 100644 --- a/src/corelib/tools/qtimezoneprivate_mac.mm +++ b/src/corelib/tools/qtimezoneprivate_mac.mm @@ -185,15 +185,14 @@ bool QMacTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const QTimeZonePrivate::Data QMacTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const { const NSTimeInterval seconds = forMSecsSinceEpoch / 1000.0; + NSDate *date = [NSDate dateWithTimeIntervalSince1970:seconds]; Data data; data.atMSecsSinceEpoch = forMSecsSinceEpoch; - data.offsetFromUtc = [m_nstz secondsFromGMTForDate: - [NSDate dateWithTimeIntervalSince1970:seconds]]; - data.daylightTimeOffset = [m_nstz daylightSavingTimeOffsetForDate: - [NSDate dateWithTimeIntervalSince1970:seconds]]; + data.offsetFromUtc = [m_nstz secondsFromGMTForDate:date]; + data.daylightTimeOffset = [m_nstz daylightSavingTimeOffsetForDate:date]; data.standardTimeOffset = data.offsetFromUtc - data.daylightTimeOffset; - data.abbreviation = QCFString::toQString([m_nstz abbreviationForDate: - [NSDate dateWithTimeIntervalSince1970:seconds]]); + data.abbreviation = QCFString::toQString([m_nstz abbreviationForDate:date]); + [date release]; return data; } @@ -213,26 +212,46 @@ QTimeZonePrivate::Data QMacTimeZonePrivate::nextTransition(qint64 afterMSecsSinc { QTimeZonePrivate::Data tran; const NSTimeInterval seconds = afterMSecsSinceEpoch / 1000.0; - NSDate *date = [NSDate dateWithTimeIntervalSince1970:seconds]; - const NSDate *next = [m_nstz nextDaylightSavingTimeTransitionAfterDate:date]; - const NSTimeInterval nextSecs = [next timeIntervalSince1970]; + NSDate *nextDate = [NSDate dateWithTimeIntervalSince1970:seconds]; + nextDate = [m_nstz nextDaylightSavingTimeTransitionAfterDate:nextDate]; + const NSTimeInterval nextSecs = [nextDate timeIntervalSince1970]; + if (nextDate == nil || nextSecs <= seconds) { + [nextDate release]; + return invalidData(); + } tran.atMSecsSinceEpoch = nextSecs * 1000; - tran.offsetFromUtc = [m_nstz secondsFromGMTForDate: - [NSDate dateWithTimeIntervalSince1970:nextSecs]]; - tran.daylightTimeOffset = [m_nstz daylightSavingTimeOffsetForDate: - [NSDate dateWithTimeIntervalSince1970:nextSecs]]; + tran.offsetFromUtc = [m_nstz secondsFromGMTForDate:nextDate]; + tran.daylightTimeOffset = [m_nstz daylightSavingTimeOffsetForDate:nextDate]; tran.standardTimeOffset = tran.offsetFromUtc - tran.daylightTimeOffset; - tran.abbreviation = QCFString::toQString([m_nstz abbreviationForDate:date]); - [next release]; - [date release]; + tran.abbreviation = QCFString::toQString([m_nstz abbreviationForDate:nextDate]); + [nextDate release]; return tran; } QTimeZonePrivate::Data QMacTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const { - // TODO No direct Mac API, so get all transitions since epoch and return the last one - // Probably slow, need to optimize - return transitions(0, beforeMSecsSinceEpoch - 1).last(); + // No direct Mac API, so get all transitions since epoch and return the last one + QList<int> secsList; + if (beforeMSecsSinceEpoch > 0) { + const int endSecs = beforeMSecsSinceEpoch / 1000.0; + NSTimeInterval prevSecs = 0; + NSTimeInterval nextSecs = 0; + NSDate *nextDate = [NSDate dateWithTimeIntervalSince1970:nextSecs]; + // If invalid may return a nil date or an Epoch date + nextDate = [m_nstz nextDaylightSavingTimeTransitionAfterDate:nextDate]; + nextSecs = [nextDate timeIntervalSince1970]; + while (nextDate != nil && nextSecs > prevSecs && nextSecs < endSecs) { + secsList.append(nextSecs); + prevSecs = nextSecs; + nextDate = [m_nstz nextDaylightSavingTimeTransitionAfterDate:nextDate]; + nextSecs = [nextDate timeIntervalSince1970]; + } + [nextDate release]; + } + if (secsList.size() >= 1) + return data(qint64(secsList.last()) * 1000); + else + return invalidData(); } QByteArray QMacTimeZonePrivate::systemTimeZoneId() const diff --git a/src/corelib/tools/qtimezoneprivate_p.h b/src/corelib/tools/qtimezoneprivate_p.h index 9f99f49fcf..108aec2654 100644 --- a/src/corelib/tools/qtimezoneprivate_p.h +++ b/src/corelib/tools/qtimezoneprivate_p.h @@ -146,12 +146,12 @@ public: static bool isValidId(const QByteArray &olsenId); static QString isoOffsetFormat(int offsetFromUtc); - static QByteArray olsenIdToWindowsId(const QByteArray &olsenId); - static QByteArray windowsIdToDefaultOlsenId(const QByteArray &windowsId); - static QByteArray windowsIdToDefaultOlsenId(const QByteArray &windowsId, + static QByteArray ianaIdToWindowsId(const QByteArray &ianaId); + static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId); + static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId, QLocale::Country country); - static QList<QByteArray> windowsIdToOlsenIds(const QByteArray &windowsId); - static QList<QByteArray> windowsIdToOlsenIds(const QByteArray &windowsId, + static QList<QByteArray> windowsIdToIanaIds(const QByteArray &windowsId); + static QList<QByteArray> windowsIdToIanaIds(const QByteArray &windowsId, QLocale::Country country); protected: @@ -309,6 +309,7 @@ private: bool operator==(const QTzTransitionRule &other) { return (stdOffset == other.stdOffset && dstOffset == other.dstOffset && abbreviationIndex == other.abbreviationIndex); } }; + Data dataForTzTransition(QTzTransitionTime tran) const; QList<QTzTransitionTime> m_tranTimes; QList<QTzTransitionRule> m_tranRules; QList<QByteArray> m_abbreviations; diff --git a/src/corelib/tools/qtimezoneprivate_tz.cpp b/src/corelib/tools/qtimezoneprivate_tz.cpp index 4bf19178fa..1fb6bb1b5a 100644 --- a/src/corelib/tools/qtimezoneprivate_tz.cpp +++ b/src/corelib/tools/qtimezoneprivate_tz.cpp @@ -149,11 +149,13 @@ static QTzHeader parseTzHeader(QDataStream &ds, bool *ok) if (memcmp(hdr.tzh_magic, TZ_MAGIC, 4) != 0 || ds.status() != QDataStream::Ok) return hdr; - // Parse Version, 1 byte, before 2005 was '\0', since 2005 a '2' + // Parse Version, 1 byte, before 2005 was '\0', since 2005 a '2', since 2013 a '3' ds >> ch; hdr.tzh_version = ch; - if (ds.status() != QDataStream::Ok || (hdr.tzh_version != '2' && hdr.tzh_version != '\0')) + if (ds.status() != QDataStream::Ok + || (hdr.tzh_version != '2' && hdr.tzh_version != '\0' && hdr.tzh_version != '3')) { return hdr; + } // Parse reserved space, 15 bytes ds.readRawData(hdr.tzh_reserved, 15); @@ -238,30 +240,31 @@ static QList<QTzType> parseTzTypes(QDataStream &ds, int tzh_typecnt) return typeList; } -static QMap<int, QByteArray> parseTzAbbreviations(QDataStream &ds, int tzh_charcnt) +static QMap<int, QByteArray> parseTzAbbreviations(QDataStream &ds, int tzh_charcnt, QList<QTzType> typeList) { // Parse the abbreviation list which is tzh_charcnt long with '\0' separated strings. The - // tz_abbrind index points to the first char of the abbreviation in the array, not the - // occurrence in the list. By parsing char at a time we can track the char index and convert - // to an occurrence index. By using a map with tz_abbrind as ordered key we get both index + // QTzType.tz_abbrind index points to the first char of the abbreviation in the array, not the + // occurrence in the list. It can also point to a partial string so we need to use the actual typeList + // index values when parsing. By using a map with tz_abbrind as ordered key we get both index // methods in one data structure and can convert the types afterwards. QMap<int, QByteArray> map; quint8 ch; - QByteArray abbrev; - // Track the start position of each abbreviation - int tz_abbrind = 0; + QByteArray input; + // First parse the full abbrev string for (int i = 0; i < tzh_charcnt && ds.status() == QDataStream::Ok; ++i) { ds >> ch; - if (ds.status() == QDataStream::Ok) { - if (ch == '\0') { - // Have reached end of an abbreviation, so add to map - map[tz_abbrind] = abbrev; - tz_abbrind = i + 1; - abbrev.clear(); - } else { - abbrev.append((char)ch); - } - } + if (ds.status() == QDataStream::Ok) + input.append(char(ch)); + else + return map; + } + // Then extract all the substrings pointed to by typeList + foreach (const QTzType type, typeList) { + QByteArray abbrev; + for (int i = type.tz_abbrind; input.at(i) != '\0'; ++i) + abbrev.append(input.at(i)); + // Have reached end of an abbreviation, so add to map + map[type.tz_abbrind] = abbrev; } return map; } @@ -371,7 +374,7 @@ static QDate calculatePosixDate(const QByteArray dateRule, int year) } } -static QTime parsePosixTime(const QByteArray timeRule) +static QTime parsePosixTime(const QByteArray &timeRule) { // Format "HH:mm:ss", put check parts count just in case QList<QByteArray> parts = timeRule.split(':'); @@ -385,7 +388,7 @@ static QTime parsePosixTime(const QByteArray timeRule) return QTime(2, 0, 0); } -static int parsePosixOffset(const QByteArray timeRule) +static int parsePosixOffset(const QByteArray &timeRule) { // Format "[+|-]hh[:mm[:ss]]" QList<QByteArray> parts = timeRule.split(':'); @@ -399,7 +402,9 @@ static int parsePosixOffset(const QByteArray timeRule) return 0; } -static QList<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArray &posixRule, int startYear, int endYear) +static QList<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArray &posixRule, + int startYear, int endYear, + int lastTranMSecs) { QList<QTimeZonePrivate::Data> list; @@ -443,11 +448,13 @@ static QList<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArray // If only the name part then no transitions if (parts.count() == 1) { QTimeZonePrivate::Data data; - data.atMSecsSinceEpoch = 0; + data.atMSecsSinceEpoch = lastTranMSecs; data.offsetFromUtc = utcOffset; data.standardTimeOffset = utcOffset; data.daylightTimeOffset = 0; data.abbreviation = stdName; + list << data; + return list; } // If not populated the total dst offset is 1 hour @@ -572,7 +579,7 @@ void QTzTimeZonePrivate::init(const QByteArray &olsenId) QList<QTzType> typeList = parseTzTypes(ds, hdr.tzh_typecnt); if (ds.status() != QDataStream::Ok) return; - QMap<int, QByteArray> abbrevMap = parseTzAbbreviations(ds, hdr.tzh_charcnt); + QMap<int, QByteArray> abbrevMap = parseTzAbbreviations(ds, hdr.tzh_charcnt, typeList); if (ds.status() != QDataStream::Ok) return; parseTzLeapSeconds(ds, hdr.tzh_leapcnt, false); @@ -583,7 +590,7 @@ void QTzTimeZonePrivate::init(const QByteArray &olsenId) return; // If version 2 then parse the second block of data - if (hdr.tzh_version == '2') { + if (hdr.tzh_version == '2' || hdr.tzh_version == '3') { ok = false; QTzHeader hdr2 = parseTzHeader(ds, &ok); if (!ok || ds.status() != QDataStream::Ok) @@ -594,7 +601,7 @@ void QTzTimeZonePrivate::init(const QByteArray &olsenId) typeList = parseTzTypes(ds, hdr2.tzh_typecnt); if (ds.status() != QDataStream::Ok) return; - abbrevMap = parseTzAbbreviations(ds, hdr2.tzh_charcnt); + abbrevMap = parseTzAbbreviations(ds, hdr2.tzh_charcnt, typeList); if (ds.status() != QDataStream::Ok) return; parseTzLeapSeconds(ds, hdr2.tzh_leapcnt, true); @@ -682,12 +689,14 @@ QString QTzTimeZonePrivate::displayName(qint64 atMSecsSinceEpoch, if (!m_icu) m_icu = new QIcuTimeZonePrivate(m_id); // TODO small risk may not match if tran times differ due to outdated files - return m_icu->displayName(atMSecsSinceEpoch, nameType, locale); + // TODO Some valid TZ names are not valid ICU names, use translation table? + if (m_icu->isValid()) + return m_icu->displayName(atMSecsSinceEpoch, nameType, locale); #else Q_UNUSED(nameType) Q_UNUSED(locale) - return abbreviation(atMSecsSinceEpoch); #endif // QT_USE_ICU + return abbreviation(atMSecsSinceEpoch); } QString QTzTimeZonePrivate::displayName(QTimeZone::TimeType timeType, @@ -698,19 +707,59 @@ QString QTzTimeZonePrivate::displayName(QTimeZone::TimeType timeType, if (!m_icu) m_icu = new QIcuTimeZonePrivate(m_id); // TODO small risk may not match if tran times differ due to outdated files - return m_icu->displayName(timeType, nameType, locale); + // TODO Some valid TZ names are not valid ICU names, use translation table? + if (m_icu->isValid()) + return m_icu->displayName(timeType, nameType, locale); #else Q_UNUSED(timeType) Q_UNUSED(nameType) Q_UNUSED(locale) - const int atMSecsSinceEpoch = QDateTime::currentMSecsSinceEpoch(); - QTimeZonePrivate::Data tran = data(atMSecsSinceEpoch); - while ((timeType == QTimeZone::StandardTime && tran.daylightTimeOffset != 0) - || (timeType == QTimeZone::DaylightTime && tran.daylightTimeOffset == 0)) { - tran = nextTransition(tran.atMSecsSinceEpoch); - } - return tran.abbreviation; #endif // QT_USE_ICU + // If no ICU available then have to use abbreviations instead + // Abbreviations don't have GenericTime + if (timeType == QTimeZone::GenericTime) + timeType = QTimeZone::StandardTime; + + // Get current tran, if valid and is what we want, then use it + const qint64 currentMSecs = QDateTime::currentMSecsSinceEpoch(); + QTimeZonePrivate::Data tran = data(currentMSecs); + if (tran.atMSecsSinceEpoch != invalidMSecs() + && ((timeType == QTimeZone::DaylightTime && tran.daylightTimeOffset != 0) + || (timeType == QTimeZone::StandardTime && tran.daylightTimeOffset == 0))) { + return tran.abbreviation; + } + + // Otherwise get next tran and if valid and is what we want, then use it + tran = nextTransition(currentMSecs); + if (tran.atMSecsSinceEpoch != invalidMSecs() + && ((timeType == QTimeZone::DaylightTime && tran.daylightTimeOffset != 0) + || (timeType == QTimeZone::StandardTime && tran.daylightTimeOffset == 0))) { + return tran.abbreviation; + } + + // Otherwise get prev tran and if valid and is what we want, then use it + tran = previousTransition(currentMSecs); + if (tran.atMSecsSinceEpoch != invalidMSecs()) + tran = previousTransition(tran.atMSecsSinceEpoch); + if (tran.atMSecsSinceEpoch != invalidMSecs() + && ((timeType == QTimeZone::DaylightTime && tran.daylightTimeOffset != 0) + || (timeType == QTimeZone::StandardTime && tran.daylightTimeOffset == 0))) { + return tran.abbreviation; + } + + // Otherwise is strange sequence, so work backwards through trans looking for first match, if any + for (int i = m_tranTimes.size() - 1; i >= 0; --i) { + if (m_tranTimes.at(i).atMSecsSinceEpoch <= currentMSecs) { + tran = dataForTzTransition(m_tranTimes.at(i)); + if ((timeType == QTimeZone::DaylightTime && tran.daylightTimeOffset != 0) + || (timeType == QTimeZone::StandardTime && tran.daylightTimeOffset == 0)) { + return tran.abbreviation; + } + } + } + + // Otherwise if no match use current data + return data(currentMSecs).abbreviation; } QString QTzTimeZonePrivate::abbreviation(qint64 atMSecsSinceEpoch) const @@ -749,35 +798,55 @@ bool QTzTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const return (daylightTimeOffset(atMSecsSinceEpoch) != 0); } +QTimeZonePrivate::Data QTzTimeZonePrivate::dataForTzTransition(QTzTransitionTime tran) const +{ + QTimeZonePrivate::Data data; + data.atMSecsSinceEpoch = tran.atMSecsSinceEpoch; + QTzTransitionRule rule = m_tranRules.at(tran.ruleIndex); + data.standardTimeOffset = rule.stdOffset; + data.daylightTimeOffset = rule.dstOffset; + data.offsetFromUtc = rule.stdOffset + rule.dstOffset; + data.abbreviation = QString::fromUtf8(m_abbreviations.at(rule.abbreviationIndex)); + return data; +} + QTimeZonePrivate::Data QTzTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const { - QTimeZonePrivate::Data data = invalidData(); - int lastTran = m_tranTimes.size() - 1; - int tran; - for (tran = lastTran; tran > 0; --tran) { - if (m_tranTimes.at(tran).atMSecsSinceEpoch <= forMSecsSinceEpoch) - break; - } - // If after the last transition time then we need to use the posix rule if available - if (tran >= lastTran && !m_posixRule.isEmpty()) { - QDateTime dt = QDateTime::fromMSecsSinceEpoch(forMSecsSinceEpoch); - int year = dt.date().year(); - QList<QTimeZonePrivate::Data> posixTrans = calculatePosixTransitions(m_posixRule, year - 1, year + 1); - for (int i = posixTrans.size() - 1; i > 0; --i) { + // If the required time is after the last transition and we have a POSIX rule then use it + if (m_tranTimes.size() > 0 && m_tranTimes.last().atMSecsSinceEpoch < forMSecsSinceEpoch + &&!m_posixRule.isEmpty() && forMSecsSinceEpoch >= 0) { + const int year = QDateTime::fromMSecsSinceEpoch(forMSecsSinceEpoch, Qt::UTC).date().year(); + const int lastMSecs = (m_tranTimes.size() > 0) ? m_tranTimes.last().atMSecsSinceEpoch : 0; + QList<QTimeZonePrivate::Data> posixTrans = calculatePosixTransitions(m_posixRule, year - 1, + year + 1, lastMSecs); + for (int i = posixTrans.size() - 1; i >= 0; --i) { if (posixTrans.at(i).atMSecsSinceEpoch <= forMSecsSinceEpoch) { + QTimeZonePrivate::Data data; data = posixTrans.at(i); data.atMSecsSinceEpoch = forMSecsSinceEpoch; return data; } } } - data.atMSecsSinceEpoch = forMSecsSinceEpoch; - QTzTransitionRule rule = m_tranRules.at(m_tranTimes.at(tran).ruleIndex); - data.standardTimeOffset = rule.stdOffset; - data.daylightTimeOffset = rule.dstOffset; - data.offsetFromUtc = rule.stdOffset + rule.dstOffset; - data.abbreviation = QString::fromUtf8(m_abbreviations.at(rule.abbreviationIndex)); - return data; + + // Otherwise if we can find a valid tran then use its rule + for (int i = m_tranTimes.size() - 1; i >= 0; --i) { + if (m_tranTimes.at(i).atMSecsSinceEpoch <= forMSecsSinceEpoch) { + Data data = dataForTzTransition(m_tranTimes.at(i)); + data.atMSecsSinceEpoch = forMSecsSinceEpoch; + return data; + } + } + + // Otherwise use the earliest transition we have + if (m_tranTimes.size() > 0) { + Data data = dataForTzTransition(m_tranTimes.at(0)); + data.atMSecsSinceEpoch = forMSecsSinceEpoch; + return data; + } + + // Otherwise we have no rules, so probably an invalid tz, so return invalid data + return invalidData(); } bool QTzTimeZonePrivate::hasTransitions() const @@ -787,60 +856,54 @@ bool QTzTimeZonePrivate::hasTransitions() const QTimeZonePrivate::Data QTzTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch) const { - int lastTran = m_tranTimes.size() - 1; - int tran; - for (tran = 0; tran < lastTran; ++tran) { - if (m_tranTimes.at(tran).atMSecsSinceEpoch > afterMSecsSinceEpoch) - break; - } - // If after the last transition time then we need to use the posix rule if available - if (tran >= lastTran && !m_posixRule.isEmpty()) { - QDateTime dt = QDateTime::fromMSecsSinceEpoch(afterMSecsSinceEpoch); - int year = dt.date().year(); - QList<QTimeZonePrivate::Data> posixTrans = calculatePosixTransitions(m_posixRule, year - 1, year + 1); - for (int i = 0; i < posixTrans.size() - 1; ++i) { + // If the required time is after the last transition and we have a POSIX rule then use it + if (m_tranTimes.size() > 0 && m_tranTimes.last().atMSecsSinceEpoch < afterMSecsSinceEpoch + &&!m_posixRule.isEmpty() && afterMSecsSinceEpoch >= 0) { + const int year = QDateTime::fromMSecsSinceEpoch(afterMSecsSinceEpoch, Qt::UTC).date().year(); + const int lastMSecs = (m_tranTimes.size() > 0) ? m_tranTimes.last().atMSecsSinceEpoch : 0; + QList<QTimeZonePrivate::Data> posixTrans = calculatePosixTransitions(m_posixRule, year - 1, + year + 1, lastMSecs); + for (int i = 0; i < posixTrans.size(); ++i) { if (posixTrans.at(i).atMSecsSinceEpoch > afterMSecsSinceEpoch) return posixTrans.at(i); } } - // Otherwise use the transition we found - QTimeZonePrivate::Data data; - data.atMSecsSinceEpoch = m_tranTimes.at(tran).atMSecsSinceEpoch; - QTzTransitionRule rule = m_tranRules.at(m_tranTimes.at(tran).ruleIndex); - data.standardTimeOffset = rule.stdOffset; - data.daylightTimeOffset = rule.dstOffset; - data.offsetFromUtc = rule.stdOffset + rule.dstOffset; - data.abbreviation = QString::fromUtf8(m_abbreviations.at(rule.abbreviationIndex)); - return data; + + // Otherwise if we can find a valid tran then use its rule + for (int i = 0; i < m_tranTimes.size(); ++i) { + if (m_tranTimes.at(i).atMSecsSinceEpoch > afterMSecsSinceEpoch) { + return dataForTzTransition(m_tranTimes.at(i)); + } + } + + // Otherwise we have no rule, or there is no next transition, so return invalid data + return invalidData(); } QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const { - int lastTran = m_tranTimes.size() - 1; - int tran; - for (tran = lastTran; tran > 0; --tran) { - if (m_tranTimes.at(tran).atMSecsSinceEpoch < beforeMSecsSinceEpoch) - break; - } - // If after the last transition time then we need to use the posix rule if available - if (tran >= lastTran && !m_posixRule.isEmpty()) { - QDateTime dt = QDateTime::fromMSecsSinceEpoch(beforeMSecsSinceEpoch); - int year = dt.date().year(); - QList<QTimeZonePrivate::Data> posixTrans = calculatePosixTransitions(m_posixRule, year - 1, year + 1); - for (int i = posixTrans.size() - 1; i > 0; --i) { + // If the required time is after the last transition and we have a POSIX rule then use it + if (m_tranTimes.size() > 0 && m_tranTimes.last().atMSecsSinceEpoch < beforeMSecsSinceEpoch + &&!m_posixRule.isEmpty() && beforeMSecsSinceEpoch > 0) { + const int year = QDateTime::fromMSecsSinceEpoch(beforeMSecsSinceEpoch, Qt::UTC).date().year(); + const int lastMSecs = (m_tranTimes.size() > 0) ? m_tranTimes.last().atMSecsSinceEpoch : 0; + QList<QTimeZonePrivate::Data> posixTrans = calculatePosixTransitions(m_posixRule, year - 1, + year + 1, lastMSecs); + for (int i = posixTrans.size() - 1; i >= 0; --i) { if (posixTrans.at(i).atMSecsSinceEpoch < beforeMSecsSinceEpoch) return posixTrans.at(i); } } - // Otherwise use the transition we found - QTimeZonePrivate::Data data; - data.atMSecsSinceEpoch = m_tranTimes.at(tran).atMSecsSinceEpoch; - QTzTransitionRule rule = m_tranRules.at(m_tranTimes.at(tran).ruleIndex); - data.standardTimeOffset = rule.stdOffset; - data.daylightTimeOffset = rule.dstOffset; - data.offsetFromUtc = rule.stdOffset + rule.dstOffset; - data.abbreviation = QString::fromUtf8(m_abbreviations.at(rule.abbreviationIndex)); - return data; + + // Otherwise if we can find a valid tran then use its rule + for (int i = m_tranTimes.size() - 1; i >= 0; --i) { + if (m_tranTimes.at(i).atMSecsSinceEpoch < beforeMSecsSinceEpoch) { + return dataForTzTransition(m_tranTimes.at(i)); + } + } + + // Otherwise we have no rule, so return invalid data + return invalidData(); } // TODO Could cache the value and monitor the required files for any changes diff --git a/src/corelib/tools/qtimezoneprivate_win.cpp b/src/corelib/tools/qtimezoneprivate_win.cpp index c219a49e1e..04588b2ba8 100644 --- a/src/corelib/tools/qtimezoneprivate_win.cpp +++ b/src/corelib/tools/qtimezoneprivate_win.cpp @@ -106,14 +106,6 @@ static QDate msecsToDate(qint64 msecs) return QDate::fromJulianDay(jd); } -static qint64 systemtimeToMsecs(const SYSTEMTIME &systemtime) -{ - FILETIME utcFileTime; - SystemTimeToFileTime(&systemtime, &utcFileTime); - ULONGLONG utcNSecs = (((ULONGLONG) utcFileTime.dwHighDateTime) << 32) + utcFileTime.dwLowDateTime; - return (utcNSecs - FILETIME_UNIX_EPOCH) / 10000; -} - static bool equalSystemtime(const SYSTEMTIME &t1, const SYSTEMTIME &t2) { return (t1.wYear == t2.wYear @@ -262,6 +254,10 @@ static QByteArray windowsSystemZoneId() static QDate calculateTransitionLocalDate(const SYSTEMTIME &rule, int year) { + // If month is 0 then there is no date + if (rule.wMonth == 0) + return QDate(); + SYSTEMTIME time = rule; // If the year isn't set, then the rule date is relative if (time.wYear == 0) { @@ -277,9 +273,10 @@ static QDate calculateTransitionLocalDate(const SYSTEMTIME &rule, int year) while (date.month() != time.wMonth) date = date.addDays(-7); return date; - } else { - return QDate(time.wYear, time.wMonth, time.wDay); } + + // If the year is set then is an absolute date + return QDate(time.wYear, time.wMonth, time.wDay); } // Converts a date/time value into msecs @@ -293,19 +290,25 @@ static void calculateTransitionsForYear(const QWinTimeZonePrivate::QWinTransitio qint64 *stdMSecs, qint64 *dstMSecs) { // TODO Consider caching the calculated values - - // The local time in Daylight Time when switches to Standard TIme + // The local time in Daylight Time when switches to Standard Time QDate standardDate = calculateTransitionLocalDate(rule.standardTimeRule, year); QTime standardTime = QTime(rule.standardTimeRule.wHour, rule.standardTimeRule.wMinute, rule.standardTimeRule.wSecond); - // The local time in Standard Time when switches to Daylight TIme + if (standardDate.isValid() && standardTime.isValid()) { + *stdMSecs = timeToMSecs(standardDate, standardTime) + + ((rule.standardTimeBias + rule.daylightTimeBias) * 60000); + } else { + *stdMSecs = QTimeZonePrivate::invalidMSecs(); + } + + // The local time in Standard Time when switches to Daylight Time QDate daylightDate = calculateTransitionLocalDate(rule.daylightTimeRule, year); QTime daylightTime = QTime(rule.daylightTimeRule.wHour, rule.daylightTimeRule.wMinute, rule.daylightTimeRule.wSecond); - - *stdMSecs = timeToMSecs(standardDate, standardTime) - + ((rule.standardTimeBias + rule.daylightTimeBias) * 60000); - *dstMSecs = timeToMSecs(daylightDate, daylightTime) + (rule.standardTimeBias * 60000); + if (daylightDate.isValid() && daylightTime.isValid()) + *dstMSecs = timeToMSecs(daylightDate, daylightTime) + (rule.standardTimeBias * 60000); + else + *dstMSecs = QTimeZonePrivate::invalidMSecs(); } static QLocale::Country userCountry() @@ -359,7 +362,7 @@ void QWinTimeZonePrivate::init(const QByteArray &olsenId) m_windowsId = windowsSystemZoneId(); m_id = systemTimeZoneId(); } else { - m_windowsId = olsenIdToWindowsId(olsenId); + m_windowsId = ianaIdToWindowsId(olsenId); m_id = olsenId; } @@ -473,15 +476,8 @@ bool QWinTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const QTimeZonePrivate::Data QWinTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const { - // Convert MSecs to year to get transitions for, but around 31 Dec/1 Jan may not be right year - // So get the year after we think we want transitions for, to be safe - QDate date = msecsToDate(forMSecsSinceEpoch); - int year; - int month; - int day; - date.getDate(&year, &month, &day); - if ((month == 12 && day == 31) || (month == 1 && day == 1)) - ++year; + // Convert MSecs to year to get transitions for, assumes no transitions around 31 Dec/1 Jan + int year = msecsToDate(forMSecsSinceEpoch).year(); qint64 first; qint64 second; @@ -492,21 +488,26 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::data(qint64 forMSecsSinceEpoch) cons do { // Convert the transition rules into msecs for the year we want to try rule = ruleForYear(year); + // If no transition rules to calculate then no DST, so just use rule for std + if (rule.standardTimeRule.wMonth == 0 && rule.daylightTimeRule.wMonth == 0) + break; calculateTransitionsForYear(rule, year, &stdMSecs, &dstMSecs); - first = qMin(stdMSecs, dstMSecs); - second = qMax(stdMSecs, dstMSecs); - if (forMSecsSinceEpoch >= second) + if (stdMSecs < dstMSecs) { + first = stdMSecs; + second = dstMSecs; + } else { + first = dstMSecs; + second = stdMSecs; + } + if (forMSecsSinceEpoch >= second && second != invalidMSecs()) next = second; - else if (forMSecsSinceEpoch >= first) + else if (forMSecsSinceEpoch >= first && first != invalidMSecs()) next = first; // If didn't fall in this year, try the previous --year; - } while (forMSecsSinceEpoch < first && year >= MIN_YEAR); + } while (next == maxMSecs() && year >= MIN_YEAR); - if (next == dstMSecs) - return ruleToData(rule, forMSecsSinceEpoch, QTimeZone::DaylightTime); - else - return ruleToData(rule, forMSecsSinceEpoch, QTimeZone::StandardTime); + return ruleToData(rule, forMSecsSinceEpoch, (next == dstMSecs) ? QTimeZone::DaylightTime : QTimeZone::StandardTime); } bool QWinTimeZonePrivate::hasTransitions() const @@ -520,79 +521,105 @@ bool QWinTimeZonePrivate::hasTransitions() const QTimeZonePrivate::Data QWinTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch) const { - // Convert MSecs to year to get transitions for, but around 31 Dec/1 Jan may not be right year - // Get the year before we think we want transitions for, to be safe - QDate date = msecsToDate(afterMSecsSinceEpoch); - int year; - int month; - int day; - date.getDate(&year, &month, &day); - if ((month == 12 && day == 31) || (month == 1 && day == 1)) - --year; + // Convert MSecs to year to get transitions for, assumes no transitions around 31 Dec/1 Jan + int year = msecsToDate(afterMSecsSinceEpoch).year(); + QWinTransitionRule rule; + // If the required year falls after the last rule start year and the last rule has no + // valid future transition calculations then there is no next transition + if (year > m_tranRules.last().startYear) { + rule = ruleForYear(year); + // If the rules have either a fixed year, or no month, then no future trans + if (rule.standardTimeRule.wYear != 0 || rule.daylightTimeRule.wYear != 0 + || rule.standardTimeRule.wMonth == 0 || rule.daylightTimeRule.wMonth == 0) { + return invalidData(); + } + } + + // Otherwise we have a valid rule for the required year that can be used + // to calculate this year or next qint64 first; qint64 second; qint64 next = minMSecs(); qint64 stdMSecs; qint64 dstMSecs; - QWinTransitionRule rule; do { // Convert the transition rules into msecs for the year we want to try rule = ruleForYear(year); + // If no transition rules to calculate then no next transition + if (rule.standardTimeRule.wMonth == 0 && rule.daylightTimeRule.wMonth == 0) + return invalidData(); calculateTransitionsForYear(rule, year, &stdMSecs, &dstMSecs); // Find the first and second transition for the year - first = qMin(stdMSecs, dstMSecs); - second = qMax(stdMSecs, dstMSecs); + if (stdMSecs < dstMSecs) { + first = stdMSecs; + second = dstMSecs; + } else { + first = dstMSecs; + second = stdMSecs; + } if (afterMSecsSinceEpoch < first) next = first; else if (afterMSecsSinceEpoch < second) next = second; // If didn't fall in this year, try the next ++year; - } while (afterMSecsSinceEpoch >= second && year <= MAX_YEAR); + } while (next == minMSecs() && year <= MAX_YEAR); - if (next == dstMSecs) - return ruleToData(rule, next, QTimeZone::DaylightTime); - else - return ruleToData(rule, next, QTimeZone::StandardTime); + if (next == minMSecs() || next == invalidMSecs()) + return invalidData(); + + return ruleToData(rule, next, (next == dstMSecs) ? QTimeZone::DaylightTime : QTimeZone::StandardTime); } QTimeZonePrivate::Data QWinTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const { - // Convert MSecs to year to get transitions for, but around 31 Dec/1 Jan may not be right year - // So get the year after we think we want transitions for, to be safe - QDate date = msecsToDate(beforeMSecsSinceEpoch); - int year; - int month; - int day; - date.getDate(&year, &month, &day); - if ((month == 12 && day == 31) || (month == 1 && day == 1)) - ++year; + // Convert MSecs to year to get transitions for, assumes no transitions around 31 Dec/1 Jan + int year = msecsToDate(beforeMSecsSinceEpoch).year(); + + QWinTransitionRule rule; + // If the required year falls before the first rule start year and the first rule has no + // valid transition calculations then there is no previous transition + if (year < m_tranRules.first().startYear) { + rule = ruleForYear(year); + // If the rules have either a fixed year, or no month, then no previous trans + if (rule.standardTimeRule.wYear != 0 || rule.daylightTimeRule.wYear != 0 + || rule.standardTimeRule.wMonth == 0 || rule.daylightTimeRule.wMonth == 0) { + return invalidData(); + } + } qint64 first; qint64 second; qint64 next = maxMSecs(); qint64 stdMSecs; qint64 dstMSecs; - QWinTransitionRule rule; do { // Convert the transition rules into msecs for the year we want to try rule = ruleForYear(year); + // If no transition rules to calculate then no previous transition + if (rule.standardTimeRule.wMonth == 0 && rule.daylightTimeRule.wMonth == 0) + return invalidData(); calculateTransitionsForYear(rule, year, &stdMSecs, &dstMSecs); - first = qMin(stdMSecs, dstMSecs); - second = qMax(stdMSecs, dstMSecs); - if (beforeMSecsSinceEpoch > second) + if (stdMSecs < dstMSecs) { + first = stdMSecs; + second = dstMSecs; + } else { + first = dstMSecs; + second = stdMSecs; + } + if (beforeMSecsSinceEpoch > second && second != invalidMSecs()) next = second; - else if (beforeMSecsSinceEpoch > first) + else if (beforeMSecsSinceEpoch > first && first != invalidMSecs()) next = first; // If didn't fall in this year, try the previous --year; - } while (beforeMSecsSinceEpoch < first && year >= MIN_YEAR); + } while (next == maxMSecs() && year >= MIN_YEAR); - if (next == dstMSecs) - return ruleToData(rule, next, QTimeZone::DaylightTime); - else - return ruleToData(rule, next, QTimeZone::StandardTime); + if (next == maxMSecs()) + return invalidData(); + + return ruleToData(rule, next, (next == dstMSecs) ? QTimeZone::DaylightTime : QTimeZone::StandardTime); } QByteArray QWinTimeZonePrivate::systemTimeZoneId() const @@ -602,10 +629,10 @@ QByteArray QWinTimeZonePrivate::systemTimeZoneId() const QByteArray olsenId; // If we have a real country, then try get a specific match for that country if (country != QLocale::AnyCountry) - olsenId = windowsIdToDefaultOlsenId(windowsId, country); + olsenId = windowsIdToDefaultIanaId(windowsId, country); // If we don't have a real country, or there wasn't a specific match, try the global default if (olsenId.isEmpty()) { - olsenId = windowsIdToDefaultOlsenId(windowsId); + olsenId = windowsIdToDefaultIanaId(windowsId); // If no global default then probably an unknown Windows ID so return UTC if (olsenId.isEmpty()) return QByteArrayLiteral("UTC"); @@ -617,7 +644,7 @@ QSet<QByteArray> QWinTimeZonePrivate::availableTimeZoneIds() const { QSet<QByteArray> set; foreach (const QByteArray &winId, availableWindowsIds()) { - foreach (const QByteArray &olsenId, windowsIdToOlsenIds(winId)) + foreach (const QByteArray &olsenId, windowsIdToIanaIds(winId)) set << olsenId; } return set; diff --git a/src/corelib/tools/qvector.cpp b/src/corelib/tools/qvector.cpp index b9281c6915..4beb0f939c 100644 --- a/src/corelib/tools/qvector.cpp +++ b/src/corelib/tools/qvector.cpp @@ -572,7 +572,7 @@ Provided for compatibility with QList. - \sa remove(int), QList::removeAt(int) + \sa remove(), QList::removeAt() */ /*! \fn int QVector::length() const @@ -597,7 +597,7 @@ Provided for compatibility with QList. - \sa takeFirst(), takeLast(), QList::takeAt(int) + \sa takeFirst(), takeLast(), QList::takeAt() */ /*! \fn void QVector::removeFirst() @@ -621,6 +621,7 @@ */ /*! \fn T QVector::takeFirst() + \since 5.1 Removes the first item in the vector and returns it. This function assumes the vector is not empty. To avoid failure, call isEmpty() @@ -630,6 +631,7 @@ */ /*! \fn T QVector::takeLast() + \since 5.1 Removes the last item in the list and returns it. This function assumes the vector is not empty. To avoid failure, call isEmpty() diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index 553797a22f..5de2364fe2 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -14,6 +14,7 @@ HEADERS += \ tools/qcommandlineoption.h \ tools/qcommandlineparser.h \ tools/qcollator.h \ + tools/qcollator_p.h \ tools/qcontainerfwd.h \ tools/qcryptographichash.h \ tools/qdatetime.h \ diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp index 75ccea94e0..2a26c2ede4 100644 --- a/src/corelib/xml/qxmlstream.cpp +++ b/src/corelib/xml/qxmlstream.cpp @@ -41,13 +41,6 @@ #include "QtCore/qxmlstream.h" -#if defined(QT_BUILD_XML_LIB) && defined(Q_OS_MAC64) -// No need to define this in the 64-bit Mac libraries. -// Since Qt 4.4 and previous weren't supported in 64-bit, there are -// no QXmlStream* symbols to keep compatibility with -# define QT_NO_XMLSTREAM -#endif - #ifndef QT_NO_XMLSTREAM #include "qxmlutils_p.h" diff --git a/src/gui/Qt5GuiConfigExtras.cmake.in b/src/gui/Qt5GuiConfigExtras.cmake.in index 77e456df53..75a2385d57 100644 --- a/src/gui/Qt5GuiConfigExtras.cmake.in +++ b/src/gui/Qt5GuiConfigExtras.cmake.in @@ -54,12 +54,17 @@ set(Qt5Gui_OPENGL_LIBRARIES Qt5::Gui_GLESv2) !!IF !isEmpty(CMAKE_GL_INCDIRS) +set(_GL_INCDIRS $$CMAKE_GL_INCDIRS) find_path(_qt5gui_OPENGL_INCLUDE_DIR $$CMAKE_GL_HEADER_NAME - PATHS $$CMAKE_GL_INCDIRS - NO_DEFAULT_PATH) + PATHS ${_GL_INCDIRS} +!!IF !mac + NO_DEFAULT_PATH +!!ENDIF +) if (NOT _qt5gui_OPENGL_INCLUDE_DIR) - message(FATAL_ERROR \"Failed to find \\\"$$CMAKE_GL_HEADER_NAME\\\" in \\\"$$CMAKE_GL_INCDIRS\\\".\") + message(FATAL_ERROR \"Failed to find \\\"$$CMAKE_GL_HEADER_NAME\\\" in \\\"${_GL_INCDIRS}\\\".\") endif() +unset(_GL_INCDIRS) _qt5_Gui_check_file_exists(${_qt5gui_OPENGL_INCLUDE_DIR}) @@ -72,13 +77,30 @@ unset(_qt5gui_OPENGL_INCLUDE_DIR CACHE) macro(_qt5gui_find_extra_libs Name Libs LibDir IncDirs) set(Qt5Gui_${Name}_LIBRARIES) +!!IF !mac set(Qt5Gui_${Name}_INCLUDE_DIRS ${IncDirs}) +!!ELSE + foreach(_dir ${IncDirs}) + if (EXISTS ${_dir}) + list(APPEND Qt5Gui_${Name}_INCLUDE_DIRS ${_dir}) + else() + find_path(_actual_dir ${_dir}) # Look in sdk directories + if (_actual_dir) + list(APPEND Qt5Gui_${Name}_INCLUDE_DIRS ${_actual_dir}) + endif() + unset(_actual_dir CACHE) + endif() + endforeach() +!!ENDIF foreach(_lib ${Libs}) string(REGEX REPLACE "[^_A-Za-z0-9]" "_" _cmake_lib_name ${_lib}) if (NOT TARGET Qt5::Gui_${_cmake_lib_name}) find_library(Qt5Gui_${_cmake_lib_name}_LIBRARY ${_lib} !!IF !isEmpty(CROSS_COMPILE) - PATHS \"${LibDir}\" NO_DEFAULT_PATH + PATHS \"${LibDir}\" +!!IF !mac + NO_DEFAULT_PATH +!!ENDIF !!ENDIF ) !!IF mac @@ -92,7 +114,7 @@ macro(_qt5gui_find_extra_libs Name Libs LibDir IncDirs) endif() endif() add_library(Qt5::Gui_${_cmake_lib_name} SHARED IMPORTED) - set_property(TARGET Qt5::Gui_${_cmake_lib_name} APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${IncDirs}) + set_property(TARGET Qt5::Gui_${_cmake_lib_name} APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${Qt5Gui_${Name}_INCLUDE_DIRS}) set_property(TARGET Qt5::Gui_${_cmake_lib_name} APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) _qt5_Gui_check_file_exists(\"${Qt5Gui_${_cmake_lib_name}_LIBRARY}\") @@ -104,7 +126,11 @@ macro(_qt5gui_find_extra_libs Name Libs LibDir IncDirs) unset(Qt5Gui_${_cmake_lib_name}_LIBRARY CACHE) find_library(Qt5Gui_${_cmake_lib_name}_LIBRARY_DEBUG ${_lib}d - PATHS \"${LibDir}\" NO_DEFAULT_PATH) + PATHS \"${LibDir}\" +!!IF !mac + NO_DEFAULT_PATH +!!ENDIF + ) if (Qt5Gui_${_cmake_lib_name}_LIBRARY_DEBUG) set_property(TARGET Qt5::Gui_${_cmake_lib_name} APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) _qt5_Gui_check_file_exists(\"${Qt5Gui_${_cmake_lib_name}_LIBRARY_DEBUG}\") @@ -118,7 +144,7 @@ macro(_qt5gui_find_extra_libs Name Libs LibDir IncDirs) list(APPEND Qt5Gui_${Name}_LIBRARIES Qt5::Gui_${_cmake_lib_name}) endforeach() if (NOT CMAKE_CROSSCOMPILING) - foreach(_dir ${IncDirs}) + foreach(_dir ${Qt5Gui_${Name}_INCLUDE_DIRS}) _qt5_Gui_check_file_exists(${_dir}) endforeach() endif() diff --git a/src/gui/accessible/accessible.pri b/src/gui/accessible/accessible.pri index 9453ac20d0..615323dbec 100644 --- a/src/gui/accessible/accessible.pri +++ b/src/gui/accessible/accessible.pri @@ -4,7 +4,6 @@ contains(QT_CONFIG, accessibility) { HEADERS += \ accessible/qaccessible.h \ accessible/qaccessiblecache_p.h \ - accessible/qaccessible2_p.h \ accessible/qaccessibleobject.h \ accessible/qaccessibleplugin.h \ accessible/qplatformaccessibility.h diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp index b8771ec583..5d28512697 100644 --- a/src/gui/accessible/qaccessible.cpp +++ b/src/gui/accessible/qaccessible.cpp @@ -1270,8 +1270,16 @@ QAccessibleInterface::~QAccessibleInterface() /*! \fn QAccessibleEvent::QAccessibleEvent(QObject *object, QAccessible::Event type) Constructs a QAccessibleEvent to notify that \a object has changed. - The event \a type explains what changed. - */ + The event \a type describes what changed. +*/ + +/*! \fn QAccessibleEvent::QAccessibleEvent(QAccessibleInterface *interface, QAccessible::Event type) + + Constructs a QAccessibleEvent to notify that \a interface has changed. + The event \a type describes what changed. + Use this function if you already have a QAccessibleInterface or no QObject, otherwise consider + the overload taking a \l QObject parameter as it might be cheaper. +*/ /*! \fn QAccessibleEvent::~QAccessibleEvent() Destroys the event. @@ -1293,6 +1301,22 @@ QAccessibleInterface::~QAccessibleInterface() Returns the child index. */ +/*! + \internal + Returns the uniqueId of the QAccessibleInterface represented by this event. + + In case the object() function returns 0 this is the only way to access the + interface. +*/ +QAccessible::Id QAccessibleEvent::uniqueId() const +{ + if (!m_object) + return m_uniqueId; + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(m_object); + if (m_child != -1) + iface = iface->child(m_child); + return QAccessible::uniqueId(iface); +} /*! \class QAccessibleValueChangeEvent @@ -1530,6 +1554,9 @@ QAccessibleInterface::~QAccessibleInterface() */ QAccessibleInterface *QAccessibleEvent::accessibleInterface() const { + if (m_object == 0) + return QAccessible::accessibleInterface(m_uniqueId); + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(m_object); if (!iface || !iface->isValid()) { static bool hasWarned = false; @@ -1681,9 +1708,13 @@ QDebug operator<<(QDebug d, const QAccessibleEvent &ev) d << "QAccessibleEvent(null)"; return d; } - d.nospace() << "QAccessibleEvent(object=" << hex << ev.object(); - d.nospace() << dec; - d.nospace() << "child=" << ev.child(); + d.nospace() << "QAccessibleEvent("; + if (ev.object()) { + d.nospace() << "object=" << hex << ev.object() << dec; + d.nospace() << "child=" << ev.child(); + } else { + d.nospace() << "no object, uniqueId=" << ev.uniqueId(); + } d << " event=" << qAccessibleEventString(ev.type()); if (ev.type() == QAccessible::StateChanged) { QAccessible::State changed = static_cast<const QAccessibleStateChangeEvent*>(&ev)->changedStates(); diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h index d5b0af550e..25ce161940 100644 --- a/src/gui/accessible/qaccessible.h +++ b/src/gui/accessible/qaccessible.h @@ -597,6 +597,7 @@ class Q_GUI_EXPORT QAccessibleEvent { Q_DISABLE_COPY(QAccessibleEvent) public: + inline QAccessibleEvent(QObject *obj, QAccessible::Event typ) : m_type(typ), m_object(obj), m_child(-1) { @@ -613,11 +614,27 @@ public: Q_ASSERT(m_type != QAccessible::TableModelChanged); } + inline QAccessibleEvent(QAccessibleInterface *iface, QAccessible::Event typ) + : m_type(typ), m_object(0) + { + Q_ASSERT(iface); + Q_ASSERT(m_type != QAccessible::ValueChanged); + Q_ASSERT(m_type != QAccessible::StateChanged); + Q_ASSERT(m_type != QAccessible::TextCaretMoved); + Q_ASSERT(m_type != QAccessible::TextSelectionChanged); + Q_ASSERT(m_type != QAccessible::TextInserted); + Q_ASSERT(m_type != QAccessible::TextRemoved); + Q_ASSERT(m_type != QAccessible::TextUpdated); + Q_ASSERT(m_type != QAccessible::TableModelChanged); + m_uniqueId = QAccessible::uniqueId(iface); + } + virtual ~QAccessibleEvent() {} QAccessible::Event type() const { return m_type; } QObject *object() const { return m_object; } + QAccessible::Id uniqueId() const; void setChild(int chld) { m_child = chld; } int child() const { return m_child; } @@ -627,7 +644,11 @@ public: protected: QAccessible::Event m_type; QObject *m_object; - int m_child; + union { + int m_child; + QAccessible::Id m_uniqueId; + }; + }; class Q_GUI_EXPORT QAccessibleStateChangeEvent :public QAccessibleEvent @@ -638,6 +659,11 @@ public: { m_type = QAccessible::StateChanged; } + inline QAccessibleStateChangeEvent(QAccessibleInterface *iface, QAccessible::State state) + : QAccessibleEvent(iface, QAccessible::InvalidEvent), m_changedStates(state) + { + m_type = QAccessible::StateChanged; + } QAccessible::State changedStates() const { return m_changedStates; @@ -657,6 +683,12 @@ public: { m_type = QAccessible::TextCaretMoved; } + inline QAccessibleTextCursorEvent(QAccessibleInterface *iface, int cursorPos) + : QAccessibleEvent(iface, QAccessible::InvalidEvent) + , m_cursorPosition(cursorPos) + { + m_type = QAccessible::TextCaretMoved; + } void setCursorPosition(int position) { m_cursorPosition = position; } int cursorPosition() const { return m_cursorPosition; } @@ -675,6 +707,12 @@ public: { m_type = QAccessible::TextSelectionChanged; } + inline QAccessibleTextSelectionEvent(QAccessibleInterface *iface, int start, int end) + : QAccessibleTextCursorEvent(iface, (start == -1) ? 0 : end) + , m_selectionStart(start), m_selectionEnd(end) + { + m_type = QAccessible::TextSelectionChanged; + } void setSelection(int start, int end) { m_selectionStart = start; @@ -698,6 +736,12 @@ public: { m_type = QAccessible::TextInserted; } + inline QAccessibleTextInsertEvent(QAccessibleInterface *iface, int position, const QString &text) + : QAccessibleTextCursorEvent(iface, position + text.length()) + , m_position(position), m_text(text) + { + m_type = QAccessible::TextInserted; + } QString textInserted() const { return m_text; @@ -720,6 +764,12 @@ public: { m_type = QAccessible::TextRemoved; } + inline QAccessibleTextRemoveEvent(QAccessibleInterface *iface, int position, const QString &text) + : QAccessibleTextCursorEvent(iface, position) + , m_position(position), m_text(text) + { + m_type = QAccessible::TextRemoved; + } QString textRemoved() const { return m_text; @@ -742,6 +792,12 @@ public: { m_type = QAccessible::TextUpdated; } + inline QAccessibleTextUpdateEvent(QAccessibleInterface *iface, int position, const QString &oldText, const QString &text) + : QAccessibleTextCursorEvent(iface, position + text.length()) + , m_position(position), m_oldText(oldText), m_text(text) + { + m_type = QAccessible::TextUpdated; + } QString textRemoved() const { return m_oldText; } @@ -767,6 +823,12 @@ public: { m_type = QAccessible::ValueChanged; } + inline QAccessibleValueChangeEvent(QAccessibleInterface *iface, const QVariant &val) + : QAccessibleEvent(iface, QAccessible::InvalidEvent) + , m_value(val) + { + m_type = QAccessible::ValueChanged; + } void setValue(const QVariant & val) { m_value= val; } QVariant value() const { return m_value; } @@ -794,6 +856,14 @@ public: { m_type = QAccessible::TableModelChanged; } + inline QAccessibleTableModelChangeEvent(QAccessibleInterface *iface, ModelChangeType changeType) + : QAccessibleEvent(iface, QAccessible::InvalidEvent) + , m_modelChangeType(changeType) + , m_firstRow(-1), m_firstColumn(-1), m_lastRow(-1), m_lastColumn(-1) + { + m_type = QAccessible::TableModelChanged; + } + void setModelChangeType(ModelChangeType changeType) { m_modelChangeType = changeType; } ModelChangeType modelChangeType() const { return m_modelChangeType; } diff --git a/src/gui/doc/qtgui.qdocconf b/src/gui/doc/qtgui.qdocconf index ed30172376..a963f55dc8 100644 --- a/src/gui/doc/qtgui.qdocconf +++ b/src/gui/doc/qtgui.qdocconf @@ -2,7 +2,7 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf) project = QtGui description = Qt GUI Reference Documentation -url = http://qt-project.org/doc/qt-$QT_VER/qtgui +url = http://qt-project.org/doc/qt-$QT_VER version = $QT_VERSION examplesinstallpath = gui diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 234742e6b9..0916826529 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -2324,7 +2324,7 @@ static bool convert_RGB_to_RGB16_inplace(QImageData *data, Qt::ImageConversionFl static void convert_ARGB_PM_to_ARGB(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) { Q_ASSERT(src->format == QImage::Format_ARGB32_Premultiplied || src->format == QImage::Format_RGBA8888_Premultiplied); - Q_ASSERT(dest->format == QImage::Format_ARGB32 || src->format == QImage::Format_RGBA8888); + Q_ASSERT(dest->format == QImage::Format_ARGB32 || dest->format == QImage::Format_RGBA8888); Q_ASSERT(src->width == dest->width); Q_ASSERT(src->height == dest->height); @@ -3853,6 +3853,9 @@ static InPlace_Image_Converter inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Format_RGB444 { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, // Format_ARGB4444_Premultiplied + { 0, 0, 0, @@ -3989,7 +3992,7 @@ void qGamma_correct_back_to_linear_cs(QImage *image) The specified image conversion \a flags control how the image data is handled during the conversion process. - \sa {QImage#Image Format}{Image Format} + \sa {Image Formats} */ QImage QImage::convertToFormat(Format format, Qt::ImageConversionFlags flags) const { diff --git a/src/gui/image/qimageiohandler.cpp b/src/gui/image/qimageiohandler.cpp index 04e3213c53..d67b22c31e 100644 --- a/src/gui/image/qimageiohandler.cpp +++ b/src/gui/image/qimageiohandler.cpp @@ -187,11 +187,15 @@ return this handler. The json metadata file for the plugin needs to contain information - about the image formats the plugins supports. For a jpeg plugin, this - could e.g. look as follows: + about the image formats the plugins supports, together with the + corresponding MIME types (one for each format). For a jpeg plugin, this + could, for example, look as follows: \code - { "Keys": [ "jpg", "jpeg" ] } + { + "Keys": [ "jpg", "jpeg" ], + "MimeTypes": [ "image/jpeg", "image/jpeg" ] + } \endcode Different plugins can support different capabilities. For example, @@ -537,23 +541,33 @@ QImageIOPlugin::~QImageIOPlugin() /*! \fn QImageIOPlugin::capabilities(QIODevice *device, const QByteArray &format) const - Returns the capabilities on the plugin, based on the data in \a - device and the format \a format. For example, if the - QImageIOHandler supports the BMP format, and the data in the - device starts with the characters "BM", this function should - return \l CanRead. If \a format is "bmp" and the handler supports - both reading and writing, this function should return \l CanRead | - \l CanWrite. + Returns the capabilities of the plugin, based on the data in \a + device and the format \a format. If \a device is \c 0, it should + simply report whether the format can be read or written. Otherwise, + it should attempt to determine whether the given format (or any + format supported by the plugin if \a format is empty) can be read + from or written to \a device. It should do this without changing + the state of \a device (typically by using QIODevice::peek()). + + For example, if the QImageIOPlugin supports the BMP format, \a format + is either empty or \c "bmp", and the data in the device starts with the + characters \c "BM", this function should return \l CanRead. If \a format + is \c "bmp", \a device is \c 0 and the handler supports both reading and + writing, this function should return \l CanRead | \l CanWrite. + + Format names are always given in lower case. */ /*! \fn QImageIOHandler *QImageIOPlugin::create(QIODevice *device, const QByteArray &format) const Creates and returns a QImageIOHandler subclass, with \a device - and \a format set. The \a format must come from the list returned by keys(). - Format names are case sensitive. + and \a format set. The \a format must come from the values listed + in the \c "Keys" entry in the plugin metadata, or be empty. If it is + empty, the data in \a device must have been recognized by the + capabilities() method (with a likewise empty format). - \sa keys() + Format names are always given in lower case. */ #endif // QT_NO_IMAGEFORMATPLUGIN diff --git a/src/gui/image/qimagewriter.cpp b/src/gui/image/qimagewriter.cpp index e4065724be..900093b51b 100644 --- a/src/gui/image/qimagewriter.cpp +++ b/src/gui/image/qimagewriter.cpp @@ -772,7 +772,9 @@ QList<QByteArray> QImageWriter::supportedImageFormats() QList<QByteArray> QImageWriter::supportedMimeTypes() { QSet<QByteArray> mimeTypes; +#ifndef QT_NO_IMAGEFORMAT_BMP mimeTypes << "image/bmp"; +#endif #ifndef QT_NO_IMAGEFORMAT_PPM mimeTypes << "image/x-portable-bitmap"; mimeTypes << "image/x-portable-graymap"; diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index 5f51358eb2..a620d34553 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -73,7 +73,7 @@ QT_BEGIN_NAMESPACE static bool qt_pixmap_thread_test() { if (!QCoreApplication::instance()) { - qFatal("QPixmap: Must construct a QApplication before a QPaintDevice"); + qFatal("QPixmap: Must construct a QGuiApplication before a QPixmap"); return false; } diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 816419d155..ae63b8bc32 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -118,7 +118,7 @@ QInputEvent::~QInputEvent() Returns the keyboard modifier flags that existed immediately before the event occurred. - \sa QApplication::keyboardModifiers() + \sa QGuiApplication::keyboardModifiers() */ /*! \fn void QInputEvent::setModifiers(Qt::KeyboardModifiers modifiers) @@ -331,7 +331,7 @@ Qt::MouseEventSource QMouseEvent::source() const Returns the position of the mouse cursor as a QPointF, relative to the screen that received the event. - \sa x(), y(), pos(), localPos(), screenPos() + \sa x(), y(), pos(), localPos(), windowPos() */ /*! @@ -1023,7 +1023,7 @@ QKeyEvent::~QKeyEvent() confuse it by pressing both \uicontrol{Shift} keys simultaneously and releasing one of them, for example. - \sa QApplication::keyboardModifiers() + \sa QGuiApplication::keyboardModifiers() */ Qt::KeyboardModifiers QKeyEvent::modifiers() const @@ -1375,7 +1375,7 @@ QResizeEvent::~QResizeEvent() signal when they are deleted. If the last top-level window is closed, the - QApplication::lastWindowClosed() signal is emitted. + QGuiApplication::lastWindowClosed() signal is emitted. The isAccepted() function returns \c true if the event's receiver has agreed to close the widget; call accept() to agree to close the @@ -1384,7 +1384,7 @@ QResizeEvent::~QResizeEvent() \sa QWidget::close(), QWidget::hide(), QObject::destroyed(), QCoreApplication::exec(), QCoreApplication::quit(), - QApplication::lastWindowClosed() + QGuiApplication::lastWindowClosed() */ /*! @@ -2694,9 +2694,8 @@ QDragEnterEvent::~QDragEnterEvent() is within its boundaries, if it accepts \l{QWidget::setAcceptDrops()}{drop events} and \l {QWidget::dragEnterEvent()}{enter events}. The widget should - examine the event to see what kind of data it - \l{QDragMoveEvent::provides()}{provides}, and call the accept() - function to accept the drop if appropriate. + examine the event to see what kind of \l{mimeData()}{data} it + provides, and call the accept() function to accept the drop if appropriate. The rectangle supplied by the answerRect() function can be used to restrict drops to certain parts of the widget. For example, we can check whether the diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index db655bd2ad..9f95f2c234 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1672,41 +1672,36 @@ void QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyE QWindow *window = e->window.data(); modifier_buttons = e->modifiers; if (e->nullWindow -#ifdef Q_OS_ANDROID - || (e->keyType == QEvent::KeyRelease && e->key == Qt::Key_Back) || e->key == Qt::Key_Menu +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_NO_SDK) + || e->key == Qt::Key_Back || e->key == Qt::Key_Menu #endif ) { window = QGuiApplication::focusWindow(); } - if (!window -#ifdef Q_OS_ANDROID - && e->keyType != QEvent::KeyRelease && e->key != Qt::Key_Back -#endif - ) { - return; - } - if (window && window->d_func()->blockedByModalWindow) { - // a modal window is blocking this window, don't allow key events through - return; - } QKeyEvent ev(e->keyType, e->key, e->modifiers, e->nativeScanCode, e->nativeVirtualKey, e->nativeModifiers, e->unicode, e->repeat, e->repeatCount); ev.setTimestamp(e->timestamp); -#ifdef Q_OS_ANDROID - if (e->keyType == QEvent::KeyRelease && e->key == Qt::Key_Back) { - if (!window) { + // only deliver key events when we have a window, and no modal window is blocking this window + + if (window && !window->d_func()->blockedByModalWindow) + QGuiApplication::sendSpontaneousEvent(window, &ev); +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_NO_SDK) + else + ev.setAccepted(false); + + static bool backKeyPressAccepted = false; + if (e->keyType == QEvent::KeyPress) { + backKeyPressAccepted = e->key == Qt::Key_Back && ev.isAccepted(); + } else if (e->keyType == QEvent::KeyRelease && e->key == Qt::Key_Back && !backKeyPressAccepted && !ev.isAccepted()) { + if (!window) qApp->quit(); - } else { - QGuiApplication::sendEvent(window, &ev); - if (!ev.isAccepted() && e->key == Qt::Key_Back) - QWindowSystemInterface::handleCloseEvent(window); - } - } else + else + QWindowSystemInterface::handleCloseEvent(window); + } #endif - QGuiApplication::sendSpontaneousEvent(window, &ev); } void QGuiApplicationPrivate::processEnterEvent(QWindowSystemInterfacePrivate::EnterEvent *e) @@ -1834,33 +1829,33 @@ void QGuiApplicationPrivate::processGeometryChangeEvent(QWindowSystemInterfacePr return; QRect newRect = e->newGeometry; - QRect cr = window->d_func()->geometry; + QRect oldRect = e->oldGeometry.isNull() ? window->d_func()->geometry : e->oldGeometry; - bool isResize = cr.size() != newRect.size(); - bool isMove = cr.topLeft() != newRect.topLeft(); + bool isResize = oldRect.size() != newRect.size(); + bool isMove = oldRect.topLeft() != newRect.topLeft(); window->d_func()->geometry = newRect; if (isResize || window->d_func()->resizeEventPending) { - QResizeEvent e(newRect.size(), cr.size()); + QResizeEvent e(newRect.size(), oldRect.size()); QGuiApplication::sendSpontaneousEvent(window, &e); window->d_func()->resizeEventPending = false; - if (cr.width() != newRect.width()) + if (oldRect.width() != newRect.width()) window->widthChanged(newRect.width()); - if (cr.height() != newRect.height()) + if (oldRect.height() != newRect.height()) window->heightChanged(newRect.height()); } if (isMove) { //### frame geometry - QMoveEvent e(newRect.topLeft(), cr.topLeft()); + QMoveEvent e(newRect.topLeft(), oldRect.topLeft()); QGuiApplication::sendSpontaneousEvent(window, &e); - if (cr.x() != newRect.x()) + if (oldRect.x() != newRect.x()) window->xChanged(newRect.x()); - if (cr.y() != newRect.y()) + if (oldRect.y() != newRect.y()) window->yChanged(newRect.y()); } } @@ -2813,6 +2808,27 @@ bool QGuiApplication::isSavingSession() const return d->is_saving_session; } +/*! + \since 5.2 + + Function that can be used to sync Qt state with the Window Systems state. + + This function will first empty Qts events by calling QCoreApplication::processEvents(), + then the platform plugin will sync up with the windowsystem, and finally Qts events + will be delived by another call to QCoreApplication::processEvents(); + + This function is timeconsuming and its use is discouraged. +*/ +void QGuiApplication::sync() +{ + QCoreApplication::processEvents(); + if (QGuiApplicationPrivate::platform_integration + && QGuiApplicationPrivate::platform_integration->hasCapability(QPlatformIntegration::SyncState)) { + QGuiApplicationPrivate::platform_integration->sync(); + QCoreApplication::processEvents(); + } +} + void QGuiApplicationPrivate::commitData() { Q_Q(QGuiApplication); diff --git a/src/gui/kernel/qguiapplication.h b/src/gui/kernel/qguiapplication.h index bd42f18418..0089d48fa6 100644 --- a/src/gui/kernel/qguiapplication.h +++ b/src/gui/kernel/qguiapplication.h @@ -155,6 +155,7 @@ public: bool isSavingSession() const; #endif + static void sync(); Q_SIGNALS: void fontDatabaseChanged(); void screenAdded(QScreen *screen); diff --git a/src/gui/kernel/qkeysequence_p.h b/src/gui/kernel/qkeysequence_p.h index eac0d4b0a6..3751660500 100644 --- a/src/gui/kernel/qkeysequence_p.h +++ b/src/gui/kernel/qkeysequence_p.h @@ -69,6 +69,7 @@ struct Q_AUTOTEST_EXPORT QKeyBinding class Q_AUTOTEST_EXPORT QKeySequencePrivate { public: + enum { MaxKeyCount = 4 }; // used in QKeySequenceEdit inline QKeySequencePrivate() : ref(1) { key[0] = key[1] = key[2] = key[3] = 0; diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index ab782fac34..39dd2a2dfa 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -56,9 +56,7 @@ #include <private/qopenglextensions_p.h> #include <private/qopenglversionfunctionsfactory_p.h> -#if !defined(QT_OPENGL_ES_2) #include <private/qopengltexturehelper_p.h> -#endif #include <QDebug> @@ -274,7 +272,7 @@ QMutex QOpenGLContextPrivate::makeCurrentTrackerMutex; or OpenGL ES 1.x. For more information about the OpenGL API, refer to the official - \l{OpenGL documentation}. + \l{http://www.opengl.org}{OpenGL documentation}. For an example of how to use QOpenGLContext see the \l{OpenGL Window Example}{OpenGL Window} example. @@ -527,10 +525,8 @@ void QOpenGLContext::destroy() d->versionFunctions.clear(); qDeleteAll(d->versionFunctionsBackend); d->versionFunctionsBackend.clear(); -#if !defined(QT_OPENGL_ES_2) delete d->textureFunctions; d->textureFunctions = 0; -#endif } /*! @@ -591,6 +587,8 @@ QOpenGLFunctions *QOpenGLContext::functions() const /*! \fn T *QOpenGLContext::versionFunctions() const + \overload versionFunctions() + Returns a pointer to an object that provides access to all functions for the version and profile of this context. Before using any of the functions they must be initialized by calling QAbstractOpenGLFunctions::initializeOpenGLFunctions(). @@ -640,8 +638,6 @@ QOpenGLFunctions *QOpenGLContext::functions() const Usually one would use the template version of this function to automatically have the result cast to the correct type. - - \sa T *QOpenGLContext::versionFunctions() */ QAbstractOpenGLFunctions *QOpenGLContext::versionFunctions(const QOpenGLVersionProfile &versionProfile) const { @@ -984,7 +980,6 @@ void QOpenGLContext::removeFunctionsBackend(const QOpenGLVersionStatus &v) d->versionFunctionsBackend.remove(v); } -#if !defined(QT_OPENGL_ES_2) /*! \internal */ @@ -1002,7 +997,6 @@ void QOpenGLContext::setTextureFunctions(QOpenGLTextureHelper* textureFuncs) Q_D(QOpenGLContext); d->textureFunctions = textureFuncs; } -#endif /*! \class QOpenGLContextGroup diff --git a/src/gui/kernel/qopenglcontext.h b/src/gui/kernel/qopenglcontext.h index 9756be30df..ce34a2d5a5 100644 --- a/src/gui/kernel/qopenglcontext.h +++ b/src/gui/kernel/qopenglcontext.h @@ -221,10 +221,8 @@ private: QOpenGLVersionFunctionsBackend *backend); void removeFunctionsBackend(const QOpenGLVersionStatus &v); -#if !defined(QT_OPENGL_ES_2) QOpenGLTextureHelper* textureFunctions() const; void setTextureFunctions(QOpenGLTextureHelper* textureFuncs); -#endif void destroy(); }; diff --git a/src/gui/kernel/qplatformdialoghelper.cpp b/src/gui/kernel/qplatformdialoghelper.cpp index fe5db27117..5ddd718e69 100644 --- a/src/gui/kernel/qplatformdialoghelper.cpp +++ b/src/gui/kernel/qplatformdialoghelper.cpp @@ -693,6 +693,48 @@ QMessageDialogOptions::StandardButtons QMessageDialogOptions::standardButtons() return d->buttons; } +QMessageDialogOptions::ButtonRole QMessageDialogOptions::buttonRole(QMessageDialogOptions::StandardButton button) +{ + switch (button) { + case Ok: + case Save: + case Open: + case SaveAll: + case Retry: + case Ignore: + return AcceptRole; + + case Cancel: + case Close: + case Abort: + return RejectRole; + + case Discard: + return DestructiveRole; + + case Help: + return HelpRole; + + case Apply: + return ApplyRole; + + case Yes: + case YesToAll: + return YesRole; + + case No: + case NoToAll: + return NoRole; + + case RestoreDefaults: + case Reset: + return ResetRole; + + default: + break; + } + return InvalidRole; +} /*! \class QPlatformMessageDialogHelper diff --git a/src/gui/kernel/qplatformdialoghelper.h b/src/gui/kernel/qplatformdialoghelper.h index ad818c8644..9eeb0a6da4 100644 --- a/src/gui/kernel/qplatformdialoghelper.h +++ b/src/gui/kernel/qplatformdialoghelper.h @@ -361,6 +361,21 @@ public: Q_DECLARE_FLAGS(StandardButtons, StandardButton) + enum ButtonRole { + InvalidRole = -1, + AcceptRole, + RejectRole, + DestructiveRole, + ActionRole, + HelpRole, + YesRole, + NoRole, + ResetRole, + ApplyRole, + + NRoles + }; + QMessageDialogOptions(); QMessageDialogOptions(const QMessageDialogOptions &rhs); QMessageDialogOptions &operator=(const QMessageDialogOptions &rhs); @@ -386,6 +401,8 @@ public: void setStandardButtons(StandardButtons buttons); StandardButtons standardButtons() const; + static ButtonRole buttonRole(StandardButton button); + private: QSharedDataPointer<QMessageDialogOptionsPrivate> d; }; @@ -400,7 +417,7 @@ public: void setOptions(const QSharedPointer<QMessageDialogOptions> &options); Q_SIGNALS: - void clicked(QMessageDialogOptions::StandardButton button); + void clicked(QMessageDialogOptions::StandardButton button, QMessageDialogOptions::ButtonRole role); private: QSharedPointer<QMessageDialogOptions> m_options; diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp index 49ac7836cb..26aaf931b3 100644 --- a/src/gui/kernel/qplatformintegration.cpp +++ b/src/gui/kernel/qplatformintegration.cpp @@ -343,6 +343,8 @@ QVariant QPlatformIntegration::styleHint(StyleHint hint) const return QPlatformTheme::defaultThemeHint(QPlatformTheme::StartDragTime); case ShowIsFullScreen: return false; + case ShowIsMaximized: + return false; case PasswordMaskDelay: return QPlatformTheme::defaultThemeHint(QPlatformTheme::PasswordMaskDelay); case PasswordMaskCharacter: @@ -362,6 +364,20 @@ QVariant QPlatformIntegration::styleHint(StyleHint hint) const return 0; } +Qt::WindowState QPlatformIntegration::defaultWindowState(Qt::WindowFlags flags) const +{ + // Leave popup-windows as is + if (flags & Qt::Popup & ~Qt::Window) + return Qt::WindowNoState; + + if (styleHint(QPlatformIntegration::ShowIsFullScreen).toBool()) + return Qt::WindowFullScreen; + else if (styleHint(QPlatformIntegration::ShowIsMaximized).toBool()) + return Qt::WindowMaximized; + + return Qt::WindowNoState; +} + Qt::KeyboardModifiers QPlatformIntegration::queryKeyboardModifiers() const { return QGuiApplication::keyboardModifiers(); @@ -435,4 +451,19 @@ QPlatformSessionManager *QPlatformIntegration::createPlatformSessionManager(cons } #endif +/*! + \since 5.2 + + Function to sync the platform integrations state with the window system. + + This is often implemented as a roundtrip from the platformintegration to the window system. + + This function should not call QWindowSystemInterface::flushWindowSystemEvents() or + QCoreApplication::processEvents() +*/ +void QPlatformIntegration::sync() +{ + +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h index d3189f8641..580fc15233 100644 --- a/src/gui/kernel/qplatformintegration.h +++ b/src/gui/kernel/qplatformintegration.h @@ -94,7 +94,8 @@ public: ForeignWindows, NonFullScreenWindows, NativeWidgets, - WindowManagement + WindowManagement, + SyncState }; virtual ~QPlatformIntegration() { } @@ -146,10 +147,12 @@ public: UseRtlExtensions, SynthesizeMouseFromTouchEvents, PasswordMaskCharacter, - SetFocusOnTouchRelease + SetFocusOnTouchRelease, + ShowIsMaximized }; virtual QVariant styleHint(StyleHint hint) const; + virtual Qt::WindowState defaultWindowState(Qt::WindowFlags) const; virtual Qt::KeyboardModifiers queryKeyboardModifiers() const; virtual QList<int> possibleKeys(const QKeyEvent *) const; @@ -162,6 +165,8 @@ public: #ifndef QT_NO_SESSIONMANAGER virtual QPlatformSessionManager *createPlatformSessionManager(const QString &id, const QString &key) const; #endif + + virtual void sync(); protected: void screenAdded(QPlatformScreen *screen); }; diff --git a/src/gui/kernel/qplatformsystemtrayicon_qpa.cpp b/src/gui/kernel/qplatformsystemtrayicon_qpa.cpp index 5d7ff7864d..c4cec40a10 100644 --- a/src/gui/kernel/qplatformsystemtrayicon_qpa.cpp +++ b/src/gui/kernel/qplatformsystemtrayicon_qpa.cpp @@ -130,7 +130,7 @@ QPlatformSystemTrayIcon::~QPlatformSystemTrayIcon() const QIcon &icon, MessageIcon iconType, int secs) Shows a balloon message for the entry with the given \a title, message \a msg and \a icon for the time specified in \a secs. \a iconType is used as a hint for the implementing platform. - \sa QSystemTrayIcon::showMessage + \sa QSystemTrayIcon::showMessage() */ /*! diff --git a/src/gui/kernel/qplatformtheme.cpp b/src/gui/kernel/qplatformtheme.cpp index 562df1c913..1844232efe 100644 --- a/src/gui/kernel/qplatformtheme.cpp +++ b/src/gui/kernel/qplatformtheme.cpp @@ -50,6 +50,7 @@ #include <qtextformat.h> #include <private/qiconloader_p.h> #include <private/qguiapplication_p.h> +#include <qpa/qplatformintegration.h> QT_BEGIN_NAMESPACE @@ -399,7 +400,32 @@ QPixmap QPlatformTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF & QVariant QPlatformTheme::themeHint(ThemeHint hint) const { - return QPlatformTheme::defaultThemeHint(hint); + // For theme hints which mirror platform integration style hints, query + // the platform integration. The base QPlatformIntegration::styleHint() + // function will in turn query QPlatformTheme::defaultThemeHint() if there + // is no custom value. + switch (hint) { + case QPlatformTheme::CursorFlashTime: + return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::CursorFlashTime); + case QPlatformTheme::KeyboardInputInterval: + return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::KeyboardInputInterval); + case QPlatformTheme::KeyboardAutoRepeatRate: + return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::KeyboardAutoRepeatRate); + case QPlatformTheme::MouseDoubleClickInterval: + return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::MouseDoubleClickInterval); + case QPlatformTheme::StartDragDistance: + return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::StartDragDistance); + case QPlatformTheme::StartDragTime: + return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::StartDragTime); + case QPlatformTheme::StartDragVelocity: + return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::StartDragVelocity); + case QPlatformTheme::PasswordMaskDelay: + return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::PasswordMaskDelay); + case QPlatformTheme::PasswordMaskCharacter: + return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::PasswordMaskCharacter); + default: + return QPlatformTheme::defaultThemeHint(hint); + } } QVariant QPlatformTheme::defaultThemeHint(ThemeHint hint) diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp index 1f9183db44..954d47f18c 100644 --- a/src/gui/kernel/qplatformwindow.cpp +++ b/src/gui/kernel/qplatformwindow.cpp @@ -487,6 +487,27 @@ bool QPlatformWindow::isAlertState() const return false; } +// Return the effective screen for the initial geometry of a window. In a +// multimonitor-setup, try to find the right screen by checking the transient +// parent or the mouse cursor for parentless windows (cf QTBUG-34204, +// QDialog::adjustPosition()). +static inline const QScreen *effectiveScreen(const QWindow *window) +{ + if (!window) + return QGuiApplication::primaryScreen(); + const QScreen *screen = window->screen(); + if (!screen) + return QGuiApplication::primaryScreen(); + const QList<QScreen *> siblings = screen->virtualSiblings(); + if (siblings.size() > 1) { + const QPoint referencePoint = window->transientParent() ? window->transientParent()->geometry().center() : QCursor::pos(); + foreach (const QScreen *sibling, siblings) + if (sibling->geometry().contains(referencePoint)) + return sibling; + } + return screen; +} + /*! Helper function to get initial geometry on windowing systems which do not do smart positioning and also do not provide a means of centering a @@ -511,8 +532,8 @@ QRect QPlatformWindow::initialGeometry(const QWindow *w, } if (w->isTopLevel() && qt_window_private(const_cast<QWindow*>(w))->positionAutomatic && w->type() != Qt::Popup) { - if (const QPlatformScreen *platformScreen = QPlatformScreen::platformScreenForWindow(w)) { - const QRect availableGeometry = platformScreen->availableGeometry(); + if (const QScreen *screen = effectiveScreen(w)) { + const QRect availableGeometry = screen->availableGeometry(); // Center unless the geometry ( + unknown window frame) is too large for the screen). if (rect.height() < (availableGeometry.height() * 8) / 9 && rect.width() < (availableGeometry.width() * 8) / 9) { diff --git a/src/gui/kernel/qstylehints.cpp b/src/gui/kernel/qstylehints.cpp index 7899e2540b..8d751d8615 100644 --- a/src/gui/kernel/qstylehints.cpp +++ b/src/gui/kernel/qstylehints.cpp @@ -270,6 +270,9 @@ int QStyleHints::cursorFlashTime() const Returns \c true if the platform defaults to windows being fullscreen, otherwise \c false. + \note The platform may still choose to show certain windows non-fullscreen, + such as popups or dialogs. This method only returns the default behavior. + \sa QWindow::show() */ bool QStyleHints::showIsFullScreen() const diff --git a/src/gui/kernel/qsurfaceformat.cpp b/src/gui/kernel/qsurfaceformat.cpp index b8fe55adc0..2b6cb2d949 100644 --- a/src/gui/kernel/qsurfaceformat.cpp +++ b/src/gui/kernel/qsurfaceformat.cpp @@ -468,7 +468,7 @@ bool QSurfaceFormat::hasAlpha() const /*! Set the preferred stencil buffer size to \a size bits. - \sa stencilBufferSize(), setStencil(), stencil() + \sa stencilBufferSize() */ void QSurfaceFormat::setStencilBufferSize(int size) { @@ -481,7 +481,7 @@ void QSurfaceFormat::setStencilBufferSize(int size) /*! Returns the stencil buffer size in bits. - \sa stencil(), setStencil(), setStencilBufferSize() + \sa setStencilBufferSize() */ int QSurfaceFormat::stencilBufferSize() const { diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 13218fa178..2e1d8f9976 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -367,6 +367,10 @@ void QWindowPrivate::setScreen(QScreen *newScreen, bool recreate) } } +void QWindowPrivate::clearFocusObject() +{ +} + /*! Sets the \a surfaceType of the window. @@ -982,8 +986,13 @@ Qt::ScreenOrientation QWindow::contentOrientation() const qreal QWindow::devicePixelRatio() const { Q_D(const QWindow); + + // If there is no platform window, do the second best thing and + // return the app global devicePixelRatio. This is the highest + // devicePixelRatio found on the system screens, and will be + // correct for single-display systems (a very common case). if (!d->platformWindow) - return 1.0; + return qApp->devicePixelRatio(); return d->platformWindow->devicePixelRatio(); } @@ -1642,17 +1651,18 @@ QObject *QWindow::focusObject() const /*! Shows the window. - This equivalent to calling showFullScreen() or showNormal(), depending - on whether the platform defaults to windows being fullscreen or not, and - whether the window is a popup. + This is equivalent to calling showFullScreen(), showMaximized(), or showNormal(), + depending on the platform's default behavior for the window type and flags. - \sa showFullScreen(), showNormal(), hide(), QStyleHints::showIsFullScreen(), flags() + \sa showFullScreen(), showMaximized(), showNormal(), hide(), QStyleHints::showIsFullScreen(), flags() */ void QWindow::show() { - bool isPopup = d_func()->windowFlags & Qt::Popup & ~Qt::Window; - if (!isPopup && qApp->styleHints()->showIsFullScreen()) + Qt::WindowState defaultState = QGuiApplicationPrivate::platformIntegration()->defaultWindowState(d_func()->windowFlags); + if (defaultState == Qt::WindowFullScreen) showFullScreen(); + else if (defaultState == Qt::WindowMaximized) + showMaximized(); else showNormal(); } diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h index f43c1ea8ec..8d8fca3ce6 100644 --- a/src/gui/kernel/qwindow_p.h +++ b/src/gui/kernel/qwindow_p.h @@ -129,6 +129,8 @@ public: void setScreen(QScreen *newScreen, bool recreate); + virtual void clearFocusObject(); + QWindow::SurfaceType surfaceType; Qt::WindowFlags windowFlags; QWindow *parentWindow; diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 07717bb63d..49ff8bcb0d 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -141,9 +141,12 @@ void QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } -void QWindowSystemInterface::handleGeometryChange(QWindow *tlw, const QRect &newRect) +/*! + If \a oldRect is null, Qt will use the previously reported geometry instead. + */ +void QWindowSystemInterface::handleGeometryChange(QWindow *tlw, const QRect &newRect, const QRect &oldRect) { - QWindowSystemInterfacePrivate::GeometryChangeEvent *e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(tlw,newRect); + QWindowSystemInterfacePrivate::GeometryChangeEvent *e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(tlw,newRect, oldRect); QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h index 0c3494a46d..71feb1bcb7 100644 --- a/src/gui/kernel/qwindowsysteminterface.h +++ b/src/gui/kernel/qwindowsysteminterface.h @@ -138,7 +138,7 @@ public: static void handleTouchCancelEvent(QWindow *w, QTouchDevice *device, Qt::KeyboardModifiers mods = Qt::NoModifier); static void handleTouchCancelEvent(QWindow *w, ulong timestamp, QTouchDevice *device, Qt::KeyboardModifiers mods = Qt::NoModifier); - static void handleGeometryChange(QWindow *w, const QRect &newRect); + static void handleGeometryChange(QWindow *w, const QRect &newRect, const QRect &oldRect = QRect()); static void handleCloseEvent(QWindow *w, bool *accepted = 0); static void handleEnterEvent(QWindow *w, const QPointF &local = QPointF(), const QPointF& global = QPointF()); static void handleLeaveEvent(QWindow *w); diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h index f0398ffc51..367b0ac11d 100644 --- a/src/gui/kernel/qwindowsysteminterface_p.h +++ b/src/gui/kernel/qwindowsysteminterface_p.h @@ -117,11 +117,12 @@ public: class GeometryChangeEvent : public WindowSystemEvent { public: - GeometryChangeEvent(QWindow *tlw, const QRect &newGeometry) - : WindowSystemEvent(GeometryChange), tlw(tlw), newGeometry(newGeometry) + GeometryChangeEvent(QWindow *tlw, const QRect &newGeometry, const QRect &oldGeometry) + : WindowSystemEvent(GeometryChange), tlw(tlw), newGeometry(newGeometry), oldGeometry(oldGeometry) { } QPointer<QWindow> tlw; QRect newGeometry; + QRect oldGeometry; }; class EnterEvent : public WindowSystemEvent { diff --git a/src/gui/opengl/opengl.pri b/src/gui/opengl/opengl.pri index 8212c0981f..d249b855f5 100644 --- a/src/gui/opengl/opengl.pri +++ b/src/gui/opengl/opengl.pri @@ -53,6 +53,17 @@ contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles2) { opengl/qopenglvertexarrayobject.cpp \ opengl/qopengldebug.cpp + !wince* { + HEADERS += opengl/qopengltexture.h \ + opengl/qopengltexture_p.h \ + opengl/qopengltexturehelper_p.h \ + opengl/qopenglpixeltransferoptions.h + + SOURCES += opengl/qopengltexture.cpp \ + opengl/qopengltexturehelper.cpp \ + opengl/qopenglpixeltransferoptions.cpp + } + !contains(QT_CONFIG, opengles2) { HEADERS += opengl/qopenglfunctions_1_0.h \ opengl/qopenglfunctions_1_1.h \ @@ -77,11 +88,7 @@ contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles2) { opengl/qopenglfunctions_4_2_compatibility.h \ opengl/qopenglfunctions_4_3_compatibility.h \ opengl/qopenglqueryhelper_p.h \ - opengl/qopengltimerquery.h \ - opengl/qopengltexture.h \ - opengl/qopengltexture_p.h \ - opengl/qopengltexturehelper_p.h \ - opengl/qopenglpixeltransferoptions.h + opengl/qopengltimerquery.h SOURCES += opengl/qopenglfunctions_1_0.cpp \ opengl/qopenglfunctions_1_1.cpp \ @@ -105,10 +112,7 @@ contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles2) { opengl/qopenglfunctions_4_1_compatibility.cpp \ opengl/qopenglfunctions_4_2_compatibility.cpp \ opengl/qopenglfunctions_4_3_compatibility.cpp \ - opengl/qopengltimerquery.cpp \ - opengl/qopengltexture.cpp \ - opengl/qopengltexturehelper.cpp \ - opengl/qopenglpixeltransferoptions.cpp + opengl/qopengltimerquery.cpp } contains(QT_CONFIG, opengles2) { diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp index a4ed74637c..0e5a1327b0 100644 --- a/src/gui/opengl/qopenglfunctions.cpp +++ b/src/gui/opengl/qopenglfunctions.cpp @@ -347,6 +347,9 @@ static int qt_gl_resolve_extensions() { int extensions = 0; QOpenGLExtensionMatcher extensionMatcher; + if (extensionMatcher.match("GL_EXT_bgra")) + extensions |= QOpenGLExtensions::BGRATextureFormat; + #if defined(QT_OPENGL_ES) if (extensionMatcher.match("GL_OES_mapbuffer")) extensions |= QOpenGLExtensions::MapBuffer; @@ -356,10 +359,9 @@ static int qt_gl_resolve_extensions() extensions |= QOpenGLExtensions::ElementIndexUint; if (extensionMatcher.match("GL_OES_depth24")) extensions |= QOpenGLExtensions::Depth24; - - if (extensionMatcher.match("GL_EXT_bgra")) + // TODO: Consider matching GL_APPLE_texture_format_BGRA8888 as well, but it needs testing. + if (extensionMatcher.match("GL_IMG_texture_format_BGRA8888") || extensionMatcher.match("GL_EXT_texture_format_BGRA8888")) extensions |= QOpenGLExtensions::BGRATextureFormat; - #else QSurfaceFormat format = QOpenGLContext::currentContext()->format(); extensions |= QOpenGLExtensions::ElementIndexUint | QOpenGLExtensions::MapBuffer; diff --git a/src/gui/opengl/qopenglgradientcache.cpp b/src/gui/opengl/qopenglgradientcache.cpp index b48e96cd98..9c4fbbe013 100644 --- a/src/gui/opengl/qopenglgradientcache.cpp +++ b/src/gui/opengl/qopenglgradientcache.cpp @@ -152,22 +152,6 @@ GLuint QOpenGL2GradientCache::addCacheElement(quint64 hash_val, const QGradient } -// GL's expects pixels in RGBA (when using GL_RGBA), bin-endian (ABGR on x86). -// Qt always stores in ARGB reguardless of the byte-order the mancine uses. -static inline uint qtToGlColor(uint c) -{ - uint o; -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - o = (c & 0xff00ff00) // alpha & green already in the right place - | ((c >> 16) & 0x000000ff) // red - | ((c << 16) & 0x00ff0000); // blue -#else //Q_BIG_ENDIAN - o = (c << 8) - | ((c >> 24) & 0x000000ff); -#endif // Q_BYTE_ORDER - return o; -} - //TODO: Let GL generate the texture using an FBO void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, qreal opacity) const { @@ -184,7 +168,7 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient uint current_color = ARGB_COMBINE_ALPHA(colors[0], alpha); qreal incr = 1.0 / qreal(size); qreal fpos = 1.5 * incr; - colorTable[pos++] = qtToGlColor(PREMUL(current_color)); + colorTable[pos++] = ARGB2RGBA(PREMUL(current_color)); while (fpos <= s.first().first) { colorTable[pos] = colorTable[pos - 1]; @@ -205,9 +189,9 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient int dist = int(256 * ((fpos - s[i].first) * delta)); int idist = 256 - dist; if (colorInterpolation) - colorTable[pos] = qtToGlColor(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)); + colorTable[pos] = ARGB2RGBA(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)); else - colorTable[pos] = qtToGlColor(PREMUL(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist))); + colorTable[pos] = ARGB2RGBA(PREMUL(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist))); ++pos; fpos += incr; } @@ -216,7 +200,7 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient Q_ASSERT(s.size() > 0); - uint last_color = qtToGlColor(PREMUL(ARGB_COMBINE_ALPHA(colors[s.size() - 1], alpha))); + uint last_color = ARGB2RGBA(PREMUL(ARGB_COMBINE_ALPHA(colors[s.size() - 1], alpha))); for (;pos < size; ++pos) colorTable[pos] = last_color; diff --git a/src/gui/opengl/qopenglpixeltransferoptions.h b/src/gui/opengl/qopenglpixeltransferoptions.h index 1a5d3f00e2..c150e8aff4 100644 --- a/src/gui/opengl/qopenglpixeltransferoptions.h +++ b/src/gui/opengl/qopenglpixeltransferoptions.h @@ -60,6 +60,14 @@ public: QOpenGLPixelTransferOptions &operator=(const QOpenGLPixelTransferOptions &); ~QOpenGLPixelTransferOptions(); +#ifdef Q_COMPILER_RVALUE_REFS + QOpenGLPixelTransferOptions &operator=(QOpenGLPixelTransferOptions &&other) + { swap(other); return *this; } +#endif + + void swap(QOpenGLPixelTransferOptions &other) + { data.swap(other.data); } + void setAlignment(int alignment); int alignment() const; @@ -88,6 +96,8 @@ private: QSharedDataPointer<QOpenGLPixelTransferOptionsData> data; }; +Q_DECLARE_SHARED(QOpenGLPixelTransferOptions) + QT_END_NAMESPACE #endif // QT_NO_OPENGL diff --git a/src/gui/opengl/qopengltexture.cpp b/src/gui/opengl/qopengltexture.cpp index d5a7399c18..e3fffe5a1c 100644 --- a/src/gui/opengl/qopengltexture.cpp +++ b/src/gui/opengl/qopengltexture.cpp @@ -50,6 +50,11 @@ QT_BEGIN_NAMESPACE +//this is to work around GL_TEXTURE_WRAP_R_OES which also has 0x8072 as value +#if !defined(GL_TEXTURE_WRAP_R) + #define GL_TEXTURE_WRAP_R 0x8072 +#endif + QOpenGLTexturePrivate::QOpenGLTexturePrivate(QOpenGLTexture::Target textureTarget, QOpenGLTexture *qq) : q_ptr(qq), @@ -1255,6 +1260,13 @@ QOpenGLTexture *QOpenGLTexturePrivate::createTextureView(QOpenGLTexture::Target \value SRGB_Alpha_DXT3 Equivalent to GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT \value SRGB_Alpha_DXT5 Equivalent to GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT \value SRGB_BP_UNorm Equivalent to GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB + + \value DepthFormat Equivalent to GL_DEPTH_COMPONENT (OpenGL ES 2 only and when OES_depth_texture is present) + \value AlphaFormat Equivalent to GL_ALPHA (OpenGL ES 2 only) + \value RGBFormat Equivalent to GL_RGB (OpenGL ES 2 only) + \value RGBAFormat Equivalent to GL_RGBA (OpenGL ES 2 only) + \value LuminanceFormat Equivalent to GL_LUMINANCE (OpenGL ES 2 only) + \value LuminanceAlphaFormat Equivalent to GL_LUMINANCE_ALPHA (OpenGL ES 2 only) */ /*! @@ -1289,6 +1301,10 @@ QOpenGLTexture *QOpenGLTexturePrivate::createTextureView(QOpenGLTexture::Target \value BGRA_Integer Equivalent to GL_BGRA_INTEGER \value Depth Equivalent to GL_DEPTH_COMPONENT \value DepthStencil Equivalent to GL_DEPTH_STENCIL + \value Alpha Equivalent to GL_ALPHA (OpenGL ES 2 only) + \value Luminance Equivalent to GL_LUMINANCE (OpenGL ES 2 only) + \value LuminanceAlpha Equivalent to GL_LUMINANCE_ALPHA (OpenGL ES 2 only) + */ /*! @@ -1303,6 +1319,7 @@ QOpenGLTexture *QOpenGLTexturePrivate::createTextureView(QOpenGLTexture::Target \value Int32 Equivalent to GL_INT \value UInt32 Equivalent to GL_UNSIGNED_INT \value Float16 Equivalent to GL_HALF_FLOAT + \value Float16OES Equivalent to GL_HALF_FLOAT_OES \value Float32 Equivalent to GL_FLOAT \value UInt32_RGB9_E5 Equivalent to GL_UNSIGNED_INT_5_9_9_9_REV \value UInt32_RG11B10F Equivalent to GL_UNSIGNED_INT_10F_11F_11F_REV @@ -1752,6 +1769,12 @@ void QOpenGLTexture::setFormat(TextureFormat format) case D32: case D32F: case D32FS8X24: + case DepthFormat: + case AlphaFormat: + case RGBFormat: + case RGBAFormat: + case LuminanceFormat: + case LuminanceAlphaFormat: d->formatClass = FormatClass_Unique; break; } @@ -1825,7 +1848,7 @@ void QOpenGLTexture::setSize(int width, int height, int depth) /*! Returns the width of a 1D, 2D or 3D texture. - \sa height(), depth(), setDimensions() + \sa height(), depth(), setSize() */ int QOpenGLTexture::width() const { @@ -1836,7 +1859,7 @@ int QOpenGLTexture::width() const /*! Returns the height of a 2D or 3D texture. - \sa width(), depth(), setDimensions() + \sa width(), depth(), setSize() */ int QOpenGLTexture::height() const { @@ -1847,7 +1870,7 @@ int QOpenGLTexture::height() const /*! Returns the depth of a 3D texture. - \sa width(), height(), setDimensions() + \sa width(), height(), setSize() */ int QOpenGLTexture::depth() const { @@ -1913,7 +1936,7 @@ int QOpenGLTexture::mipLevels() const Returns the maximum number of mipmap levels that this texture can have given the current dimensions. - \sa setMipLevels(), mipLevels(), setDimensions() + \sa setMipLevels(), mipLevels(), setSize() */ int QOpenGLTexture::maximumMipLevels() const { @@ -2018,7 +2041,7 @@ void QOpenGLTexture::allocateStorage() The texture format, dimensions, mipmap levels and array layers cannot be altered once storage ihas been allocated. - \sa allocateStorage(), setDimensions(), setMipLevels(), setLayers(), setFormat() + \sa allocateStorage(), setSize(), setMipLevels(), setLayers(), setFormat() */ bool QOpenGLTexture::isStorageAllocated() const { @@ -2242,6 +2265,7 @@ bool QOpenGLTexture::hasFeature(Feature feature) bool supported = false; switch (feature) { +#if !defined(QT_OPENGL_ES_2) case ImmutableMultisampleStorage: case TextureBuffer: case StencilTexturing: @@ -2289,16 +2313,38 @@ bool QOpenGLTexture::hasFeature(Feature feature) break; } +#else + case Texture3D: + supported = ctx->hasExtension(QByteArrayLiteral("GL_OES_texture_3D")); + break; + case AnisotropicFiltering: + supported = ctx->hasExtension(QByteArrayLiteral("GL_EXT_texture_filter_anisotropic")); + break; + case NPOTTextures: + case NPOTTextureRepeat: + supported = f.version() >= qMakePair(3,0); + if (!supported) { + supported = ctx->hasExtension(QByteArrayLiteral("GL_OES_texture_npot")); + if (!supported) + supported = ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_non_power_of_two")); + } + default: + break; + } +#endif + return supported; } /*! Sets the base mipmap level used for all texture lookups with this texture to \a baseLevel. + \note This function has no effect on Qt built for OpenGL ES 2. \sa mipBaseLevel(), setMipMaxLevel(), setMipLevelRange() */ void QOpenGLTexture::setMipBaseLevel(int baseLevel) { +#if !defined(QT_OPENGL_ES_2) Q_D(QOpenGLTexture); d->create(); Q_ASSERT(d->textureId); @@ -2306,6 +2352,10 @@ void QOpenGLTexture::setMipBaseLevel(int baseLevel) Q_ASSERT(baseLevel <= d->maxLevel); d->baseLevel = baseLevel; d->texFuncs->glTextureParameteri(d->textureId, d->target, GL_TEXTURE_BASE_LEVEL, baseLevel); +#else + Q_UNUSED(baseLevel); + qWarning("QOpenGLTexture: Mipmap base level is not supported"); +#endif } /*! @@ -2323,10 +2373,12 @@ int QOpenGLTexture::mipBaseLevel() const /*! Sets the maximum mipmap level used for all texture lookups with this texture to \a maxLevel. + \note This function has no effect on Qt built for OpenGL ES 2. \sa mipMaxLevel(), setMipBaseLevel(), setMipLevelRange() */ void QOpenGLTexture::setMipMaxLevel(int maxLevel) { +#if !defined(QT_OPENGL_ES_2) Q_D(QOpenGLTexture); d->create(); Q_ASSERT(d->textureId); @@ -2334,6 +2386,10 @@ void QOpenGLTexture::setMipMaxLevel(int maxLevel) Q_ASSERT(d->baseLevel <= maxLevel); d->maxLevel = maxLevel; d->texFuncs->glTextureParameteri(d->textureId, d->target, GL_TEXTURE_MAX_LEVEL, maxLevel); +#else + Q_UNUSED(maxLevel); + qWarning("QOpenGLTexture: Mipmap max level is not supported"); +#endif } /*! @@ -2351,10 +2407,12 @@ int QOpenGLTexture::mipMaxLevel() const Sets the range of mipmap levels that can be used for texture lookups with this texture to range from \a baseLevel to \a maxLevel. + \note This function has no effect on Qt built for OpenGL ES 2. \sa setMipBaseLevel(), setMipMaxLevel(), mipLevelRange() */ void QOpenGLTexture::setMipLevelRange(int baseLevel, int maxLevel) { +#if !defined(QT_OPENGL_ES_2) Q_D(QOpenGLTexture); d->create(); Q_ASSERT(d->textureId); @@ -2362,12 +2420,17 @@ void QOpenGLTexture::setMipLevelRange(int baseLevel, int maxLevel) Q_ASSERT(baseLevel <= maxLevel); d->texFuncs->glTextureParameteri(d->textureId, d->target, GL_TEXTURE_BASE_LEVEL, baseLevel); d->texFuncs->glTextureParameteri(d->textureId, d->target, GL_TEXTURE_MAX_LEVEL, maxLevel); +#else + Q_UNUSED(baseLevel); + Q_UNUSED(maxLevel); + qWarning("QOpenGLTexture: Mipmap level range is not supported"); +#endif } /*! Returns the range of mipmap levels that can be used for texture lookups with this texture. - \sa mipBaseLevel(), mipMaxLevel(), mipLevelRange() + \sa mipBaseLevel(), mipMaxLevel() */ QPair<int, int> QOpenGLTexture::mipLevelRange() const { @@ -2451,11 +2514,12 @@ void QOpenGLTexture::generateMipMaps(int baseLevel, bool resetBaseLevel) This function maps \a component to the output \a value. + \note This function has no effect on Mac and Qt built for OpenGL ES 2. \sa swizzleMask() */ void QOpenGLTexture::setSwizzleMask(SwizzleComponent component, SwizzleValue value) { -#if !defined(Q_OS_MAC) +#if !defined(Q_OS_MAC) && !defined(QT_OPENGL_ES_2) Q_D(QOpenGLTexture); d->create(); Q_ASSERT(d->texFuncs); @@ -2467,9 +2531,9 @@ void QOpenGLTexture::setSwizzleMask(SwizzleComponent component, SwizzleValue val d->swizzleMask[component - SwizzleRed] = value; d->texFuncs->glTextureParameteri(d->textureId, d->target, component, value); #else - qWarning("Texture swizzling is not supported"); Q_UNUSED(component); Q_UNUSED(value); + qWarning("QOpenGLTexture: Texture swizzling is not supported"); #endif } @@ -2479,7 +2543,7 @@ void QOpenGLTexture::setSwizzleMask(SwizzleComponent component, SwizzleValue val void QOpenGLTexture::setSwizzleMask(SwizzleValue r, SwizzleValue g, SwizzleValue b, SwizzleValue a) { -#if !defined(Q_OS_MAC) +#if !defined(Q_OS_MAC) && !defined(QT_OPENGL_ES_2) Q_D(QOpenGLTexture); d->create(); Q_ASSERT(d->texFuncs); @@ -2495,11 +2559,11 @@ void QOpenGLTexture::setSwizzleMask(SwizzleValue r, SwizzleValue g, d->swizzleMask[3] = a; d->texFuncs->glTextureParameteriv(d->textureId, d->target, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); #else - qWarning("Texture swizzling is not supported"); Q_UNUSED(r); Q_UNUSED(g); Q_UNUSED(b); Q_UNUSED(a); + qWarning("QOpenGLTexture: Texture swizzling is not supported"); #endif } @@ -2520,11 +2584,12 @@ QOpenGLTexture::SwizzleValue QOpenGLTexture::swizzleMask(SwizzleComponent compon shader will access the depth component as a single float, as normal. But when the parameter is set to StencilMode?, the shader will access the stencil component. + \note This function has no effect on Mac and Qt built for OpenGL ES 2. \sa depthStencilMode() */ void QOpenGLTexture::setDepthStencilMode(QOpenGLTexture::DepthStencilMode mode) { -#if !defined(Q_OS_MAC) +#if !defined(Q_OS_MAC) && !defined(QT_OPENGL_ES_2) Q_D(QOpenGLTexture); d->create(); Q_ASSERT(d->texFuncs); @@ -2537,7 +2602,7 @@ void QOpenGLTexture::setDepthStencilMode(QOpenGLTexture::DepthStencilMode mode) d->texFuncs->glTextureParameteri(d->textureId, d->target, GL_DEPTH_STENCIL_TEXTURE_MODE, mode); #else Q_UNUSED(mode); - qWarning("DepthStencil Mode is not supported"); + qWarning("QOpenGLTexture: DepthStencil Mode is not supported"); #endif } @@ -2706,10 +2771,12 @@ QOpenGLTexture::WrapMode QOpenGLTexture::wrapMode(QOpenGLTexture::CoordinateDire /*! Sets the border color of the texture to \a color. + \note This function has no effect on Mac and Qt built for OpenGL ES 2. \sa borderColor() */ void QOpenGLTexture::setBorderColor(QColor color) { +#if !defined(QT_OPENGL_ES_2) Q_D(QOpenGLTexture); d->create(); Q_ASSERT(d->texFuncs); @@ -2723,6 +2790,10 @@ void QOpenGLTexture::setBorderColor(QColor color) for (int i = 0; i < 4; ++i) d->borderColor.append(QVariant(values[i])); d->texFuncs->glTextureParameterfv(d->textureId, d->target, GL_TEXTURE_BORDER_COLOR, values); +#else + Q_UNUSED(color); + qWarning("QOpenGLTexture: Border color is not supported"); +#endif } /*! @@ -2730,6 +2801,7 @@ void QOpenGLTexture::setBorderColor(QColor color) */ void QOpenGLTexture::setBorderColor(float r, float g, float b, float a) { +#if !defined(QT_OPENGL_ES_2) Q_D(QOpenGLTexture); d->create(); Q_ASSERT(d->texFuncs); @@ -2743,6 +2815,13 @@ void QOpenGLTexture::setBorderColor(float r, float g, float b, float a) for (int i = 0; i < 4; ++i) d->borderColor.append(QVariant(values[i])); d->texFuncs->glTextureParameterfv(d->textureId, d->target, GL_TEXTURE_BORDER_COLOR, values); +#else + Q_UNUSED(r); + Q_UNUSED(g); + Q_UNUSED(b); + Q_UNUSED(a); + qWarning("QOpenGLTexture: Border color is not supported"); +#endif } /*! @@ -2750,6 +2829,7 @@ void QOpenGLTexture::setBorderColor(float r, float g, float b, float a) */ void QOpenGLTexture::setBorderColor(int r, int g, int b, int a) { +#if !defined(QT_OPENGL_ES_2) Q_D(QOpenGLTexture); d->create(); Q_ASSERT(d->texFuncs); @@ -2763,6 +2843,13 @@ void QOpenGLTexture::setBorderColor(int r, int g, int b, int a) for (int i = 0; i < 4; ++i) d->borderColor.append(QVariant(values[i])); d->texFuncs->glTextureParameteriv(d->textureId, d->target, GL_TEXTURE_BORDER_COLOR, values); +#else + Q_UNUSED(r); + Q_UNUSED(g); + Q_UNUSED(b); + Q_UNUSED(a); + qWarning("QOpenGLTexture: Border color is not supported"); +#endif // TODO Handle case of using glTextureParameterIiv() based on format } @@ -2772,6 +2859,7 @@ void QOpenGLTexture::setBorderColor(int r, int g, int b, int a) */ void QOpenGLTexture::setBorderColor(uint r, uint g, uint b, uint a) { +#if !defined(QT_OPENGL_ES_2) Q_D(QOpenGLTexture); d->create(); Q_ASSERT(d->texFuncs); @@ -2785,6 +2873,13 @@ void QOpenGLTexture::setBorderColor(uint r, uint g, uint b, uint a) for (int i = 0; i < 4; ++i) d->borderColor.append(QVariant(values[i])); d->texFuncs->glTextureParameteriv(d->textureId, d->target, GL_TEXTURE_BORDER_COLOR, values); +#else + Q_UNUSED(r); + Q_UNUSED(g); + Q_UNUSED(b); + Q_UNUSED(a); + qWarning("QOpenGLTexture: Border color is not supported"); +#endif // TODO Handle case of using glTextureParameterIuiv() based on format } @@ -2862,10 +2957,12 @@ void QOpenGLTexture::borderColor(unsigned int *border) const Sets the minimum level of detail to \a value. This limits the selection of highest resolution mipmap (lowest mipmap level). The default value is -1000. + \note This function has no effect on Qt built for OpenGL ES 2. \sa minimumLevelOfDetail(), setMaximumLevelOfDetail(), setLevelOfDetailRange() */ void QOpenGLTexture::setMinimumLevelOfDetail(float value) { +#if !defined(QT_OPENGL_ES_2) Q_D(QOpenGLTexture); d->create(); Q_ASSERT(d->texFuncs); @@ -2873,6 +2970,10 @@ void QOpenGLTexture::setMinimumLevelOfDetail(float value) Q_ASSERT(value < d->maxLevelOfDetail); d->minLevelOfDetail = value; d->texFuncs->glTextureParameterf(d->textureId, d->target, GL_TEXTURE_MIN_LOD, value); +#else + Q_UNUSED(value); + qWarning("QOpenGLTexture: Detail level is not supported"); +#endif } /*! @@ -2890,10 +2991,12 @@ float QOpenGLTexture::minimumLevelOfDetail() const Sets the maximum level of detail to \a value. This limits the selection of lowest resolution mipmap (highest mipmap level). The default value is 1000. + \note This function has no effect on Qt built for OpenGL ES 2. \sa maximumLevelOfDetail(), setMinimumLevelOfDetail(), setLevelOfDetailRange() */ void QOpenGLTexture::setMaximumLevelOfDetail(float value) { +#if !defined(QT_OPENGL_ES_2) Q_D(QOpenGLTexture); d->create(); Q_ASSERT(d->texFuncs); @@ -2901,6 +3004,10 @@ void QOpenGLTexture::setMaximumLevelOfDetail(float value) Q_ASSERT(value > d->minLevelOfDetail); d->maxLevelOfDetail = value; d->texFuncs->glTextureParameterf(d->textureId, d->target, GL_TEXTURE_MAX_LOD, value); +#else + Q_UNUSED(value); + qWarning("QOpenGLTexture: Detail level is not supported"); +#endif } /*! @@ -2917,10 +3024,12 @@ float QOpenGLTexture::maximumLevelOfDetail() const /*! Sets the minimum and maximum level of detail parameters. + \note This function has no effect on Qt built for OpenGL ES 2. \sa levelOfDetailRange(), setMinimumLevelOfDetail(), setMaximumLevelOfDetail() */ void QOpenGLTexture::setLevelOfDetailRange(float min, float max) { +#if !defined(QT_OPENGL_ES_2) Q_D(QOpenGLTexture); d->create(); Q_ASSERT(d->texFuncs); @@ -2930,6 +3039,11 @@ void QOpenGLTexture::setLevelOfDetailRange(float min, float max) d->maxLevelOfDetail = max; d->texFuncs->glTextureParameterf(d->textureId, d->target, GL_TEXTURE_MIN_LOD, min); d->texFuncs->glTextureParameterf(d->textureId, d->target, GL_TEXTURE_MAX_LOD, max); +#else + Q_UNUSED(min); + Q_UNUSED(max); + qWarning("QOpenGLTexture: Detail level is not supported"); +#endif } /*! @@ -2946,16 +3060,22 @@ QPair<float, float> QOpenGLTexture::levelOfDetailRange() const /*! Sets the level of detail bias parameter. + \note This function has no effect on Qt built for OpenGL ES 2. \sa levelofDetailBias() */ void QOpenGLTexture::setLevelofDetailBias(float bias) { +#if !defined(QT_OPENGL_ES_2) Q_D(QOpenGLTexture); d->create(); Q_ASSERT(d->texFuncs); Q_ASSERT(d->textureId); d->levelOfDetailBias = bias; d->texFuncs->glTextureParameterf(d->textureId, d->target, GL_TEXTURE_LOD_BIAS, bias); +#else + Q_UNUSED(bias); + qWarning("QOpenGLTexture: Detail level is not supported"); +#endif } /*! diff --git a/src/gui/opengl/qopengltexture.h b/src/gui/opengl/qopengltexture.h index e06cf26f60..5c0f8101a6 100644 --- a/src/gui/opengl/qopengltexture.h +++ b/src/gui/opengl/qopengltexture.h @@ -96,8 +96,8 @@ public: DontResetTextureUnit }; - QOpenGLTexture(Target target); - QOpenGLTexture(const QImage& image, MipMapGeneration genMipMaps = GenerateMipMaps); + explicit QOpenGLTexture(Target target); + explicit QOpenGLTexture(const QImage& image, MipMapGeneration genMipMaps = GenerateMipMaps); ~QOpenGLTexture(); // Creation and destruction @@ -222,7 +222,16 @@ public: SRGB_Alpha_DXT1 = 0x8C4D, // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT SRGB_Alpha_DXT3 = 0x8C4E, // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT SRGB_Alpha_DXT5 = 0x8C4F, // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT - SRGB_BP_UNorm = 0x8E8D // GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB + SRGB_BP_UNorm = 0x8E8D, // GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB + + // ES 2 formats + DepthFormat = 0x1902, // GL_DEPTH_COMPONENT + AlphaFormat = 0x1906, // GL_ALPHA + RGBFormat = 0x1907, // GL_RGB + RGBAFormat = 0x1908, // GL_RGBA + LuminanceFormat = 0x1909, // GL_LUMINANCE + LuminanceAlphaFormat = 0x190A + }; // This is not used externally yet but is reserved to allow checking of @@ -296,7 +305,10 @@ public: RGBA_Integer = 0x8D99, // GL_RGBA_INTEGER BGRA_Integer = 0x8D9B, // GL_BGRA_INTEGER Depth = 0x1902, // GL_DEPTH_COMPONENT - DepthStencil = 0x84F9 // GL_DEPTH_STENCIL + DepthStencil = 0x84F9, // GL_DEPTH_STENCIL + Alpha = 0x1906, // GL_ALPHA + Luminance = 0x1909, // GL_LUMINANCE + LuminanceAlpha = 0x190A // GL_LUMINANCE_ALPHA }; enum PixelType { @@ -308,6 +320,7 @@ public: Int32 = 0x1404, // GL_INT UInt32 = 0x1405, // GL_UNSIGNED_INT Float16 = 0x140B, // GL_HALF_FLOAT + Float16OES = 0x8D61, // GL_HALF_FLOAT_OES Float32 = 0x1406, // GL_FLOAT UInt32_RGB9_E5 = 0x8C3E, // GL_UNSIGNED_INT_5_9_9_9_REV UInt32_RG11B10F = 0x8C3B, // GL_UNSIGNED_INT_10F_11F_11F_REV diff --git a/src/gui/opengl/qopengltexturecache.cpp b/src/gui/opengl/qopengltexturecache.cpp index 94b82885ff..4238f63cd8 100644 --- a/src/gui/opengl/qopengltexturecache.cpp +++ b/src/gui/opengl/qopengltexturecache.cpp @@ -95,10 +95,9 @@ void QOpenGLTextureCacheWrapper::cleanupTexturesForPixmapData(QPlatformPixmap *p cleanupTexturesForCacheKey(pmd->cacheKey()); } -QOpenGLTextureCache::QOpenGLTextureCache(QOpenGLContext *ctx, bool useByteSwapImage) +QOpenGLTextureCache::QOpenGLTextureCache(QOpenGLContext *ctx) : QOpenGLSharedResource(ctx->shareGroup()) , m_cache(64 * 1024) // 64 MB cache - , m_useByteSwapImage(useByteSwapImage) { } @@ -152,38 +151,13 @@ GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QImage &i return id; } -static inline void qgl_byteSwapImage(QImage &img) -{ - const int width = img.width(); - const int height = img.height(); - - if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) - { - for (int i = 0; i < height; ++i) { - uint *p = (uint *) img.scanLine(i); - for (int x = 0; x < width; ++x) - p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00); - } - } else { - for (int i = 0; i < height; ++i) { - uint *p = (uint *) img.scanLine(i); - for (int x = 0; x < width; ++x) - p[x] = (p[x] << 8) | (p[x] >> 24); - } - } -} - GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, qint64 key, const QImage &image) { GLuint id; glGenTextures(1, &id); glBindTexture(GL_TEXTURE_2D, id); - QImage tx = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); - - // Performance could be improved by skipping qgl_byteSwapImage(). - if (m_useByteSwapImage) - qgl_byteSwapImage(tx); + QImage tx = image.convertToFormat(QImage::Format_RGBA8888_Premultiplied); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tx.width(), tx.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, const_cast<const QImage &>(tx).bits()); diff --git a/src/gui/opengl/qopengltexturecache_p.h b/src/gui/opengl/qopengltexturecache_p.h index d4d3f00069..2e82d5f373 100644 --- a/src/gui/opengl/qopengltexturecache_p.h +++ b/src/gui/opengl/qopengltexturecache_p.h @@ -78,7 +78,7 @@ class Q_GUI_EXPORT QOpenGLTextureCache : public QOpenGLSharedResource public: static QOpenGLTextureCache *cacheForContext(QOpenGLContext *context); - QOpenGLTextureCache(QOpenGLContext *, bool useByteSwapImage = true); + QOpenGLTextureCache(QOpenGLContext *); ~QOpenGLTextureCache(); GLuint bindTexture(QOpenGLContext *context, const QPixmap &pixmap); @@ -94,7 +94,6 @@ private: QMutex m_mutex; QCache<quint64, QOpenGLCachedTexture> m_cache; - bool m_useByteSwapImage; }; QT_END_NAMESPACE diff --git a/src/gui/opengl/qopengltextureglyphcache.cpp b/src/gui/opengl/qopengltextureglyphcache.cpp index 506aec0f43..3b62d1d63a 100644 --- a/src/gui/opengl/qopengltextureglyphcache.cpp +++ b/src/gui/opengl/qopengltextureglyphcache.cpp @@ -43,6 +43,8 @@ #include "qopenglpaintengine_p.h" #include "private/qopenglengineshadersource_p.h" #include "qopenglextensions_p.h" +#include <qrgb.h> +#include <private/qdrawhelper_p.h> QT_BEGIN_NAMESPACE @@ -301,7 +303,17 @@ void QOpenGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed return; } - QImage mask = textureMapForGlyph(glyph, subPixelPosition); + QImage mask; + + if (m_current_fontengine->hasInternalCaching()) { + QImage *alphaMap = m_current_fontengine->lockedAlphaMapForGlyph(glyph, subPixelPosition, QFontEngine::Format_None); + if (!alphaMap || alphaMap->isNull()) + return; + mask = alphaMap->copy(); + m_current_fontengine->unlockAlphaMapForGlyph(); + } else { + mask = textureMapForGlyph(glyph, subPixelPosition); + } const int maskWidth = mask.width(); const int maskHeight = mask.height(); @@ -316,24 +328,27 @@ void QOpenGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed if (mask.format() == QImage::Format_RGB32 // We need to make the alpha component equal to the average of the RGB values. // This is needed when drawing sub-pixel antialiased text on translucent targets. +#if defined(QT_OPENGL_ES_2) || Q_BYTE_ORDER == Q_BIG_ENDIAN + || mask.format() == QImage::Format_ARGB32_Premultiplied +#endif ) { for (int y = 0; y < maskHeight; ++y) { - quint32 *src = (quint32 *) mask.scanLine(y); + QRgb *src = (QRgb *) mask.scanLine(y); for (int x = 0; x < maskWidth; ++x) { - uchar r = src[x] >> 16; - uchar g = src[x] >> 8; - uchar b = src[x]; - quint32 avg; + int r = qRed(src[x]); + int g = qGreen(src[x]); + int b = qBlue(src[x]); + int avg; if (mask.format() == QImage::Format_RGB32) - avg = (quint32(r) + quint32(g) + quint32(b) + 1) / 3; // "+1" for rounding. + avg = (r + g + b + 1) / 3; // "+1" for rounding. else // Format_ARGB_Premultiplied - avg = src[x] >> 24; + avg = qAlpha(src[x]); -#if defined(QT_OPENGL_ES_2) + src[x] = qRgba(r, g, b, avg); +#if defined(QT_OPENGL_ES_2) || Q_BYTE_ORDER == Q_BIG_ENDIAN // swizzle the bits to accommodate for the GL_RGBA upload. - src[x] = (avg << 24) | (quint32(r) << 0) | (quint32(g) << 8) | (quint32(b) << 16); + src[x] = ARGB2RGBA(src[x]); #endif - src[x] = (src[x] & 0x00ffffff) | (avg << 24); } } } @@ -341,7 +356,7 @@ void QOpenGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture); if (mask.depth() == 32) { -#if defined(QT_OPENGL_ES_2) +#if defined(QT_OPENGL_ES_2) || Q_BYTE_ORDER == Q_BIG_ENDIAN glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_RGBA, GL_UNSIGNED_BYTE, mask.bits()); #else glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_BGRA, GL_UNSIGNED_BYTE, mask.bits()); diff --git a/src/gui/opengl/qopengltexturehelper.cpp b/src/gui/opengl/qopengltexturehelper.cpp index e09b84cce6..676c0802de 100644 --- a/src/gui/opengl/qopengltexturehelper.cpp +++ b/src/gui/opengl/qopengltexturehelper.cpp @@ -48,6 +48,7 @@ QT_BEGIN_NAMESPACE QOpenGLTextureHelper::QOpenGLTextureHelper(QOpenGLContext *context) { // Resolve EXT_direct_state_access entry points if present +#if !defined(QT_OPENGL_ES_2) if (context->hasExtension(QByteArrayLiteral("GL_EXT_direct_state_access"))) { TextureParameteriEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLenum , GLint )>(context->getProcAddress(QByteArrayLiteral("glTextureParameteriEXT"))); TextureParameterivEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLenum , const GLint *)>(context->getProcAddress(QByteArrayLiteral("glTextureParameterivEXT"))); @@ -96,6 +97,7 @@ QOpenGLTextureHelper::QOpenGLTextureHelper(QOpenGLContext *context) CompressedTextureImage2D = &QOpenGLTextureHelper::dsa_CompressedTextureImage2D; CompressedTextureImage3D = &QOpenGLTextureHelper::dsa_CompressedTextureImage3D; } else { +#endif // Use our own DSA emulation TextureParameteri = &QOpenGLTextureHelper::qt_TextureParameteri; TextureParameteriv = &QOpenGLTextureHelper::qt_TextureParameteriv; @@ -117,9 +119,21 @@ QOpenGLTextureHelper::QOpenGLTextureHelper(QOpenGLContext *context) CompressedTextureImage1D = &QOpenGLTextureHelper::qt_CompressedTextureImage1D; CompressedTextureImage2D = &QOpenGLTextureHelper::qt_CompressedTextureImage2D; CompressedTextureImage3D = &QOpenGLTextureHelper::qt_CompressedTextureImage3D; +#if defined(QT_OPENGL_ES_2) + if (context->hasExtension(QByteArrayLiteral("GL_OES_texture_3D"))) { + TexImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*)>(context->getProcAddress(QByteArrayLiteral("glTexImage3DOES"))); + TexSubImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid*)>(context->getProcAddress(QByteArrayLiteral("glTexSubImage3DOES"))); + CompressedTexImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid*)>(context->getProcAddress(QByteArrayLiteral("glCompressedTexImage3DOES"))); + CompressedTexSubImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid*)>(context->getProcAddress(QByteArrayLiteral("glCompressedTexSubImage3DOES"))); + } +#endif + +#if !defined(QT_OPENGL_ES_2) } +#endif // Some DSA functions are part of NV_texture_multisample instead +#if !defined(QT_OPENGL_ES_2) if (context->hasExtension(QByteArrayLiteral("GL_NV_texture_multisample"))) { TextureImage3DMultisampleNV = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLsizei , GLint , GLsizei , GLsizei , GLsizei , GLboolean )>(context->getProcAddress(QByteArrayLiteral("glTextureImage3DMultisampleNV"))); TextureImage2DMultisampleNV = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLsizei , GLint , GLsizei , GLsizei , GLboolean )>(context->getProcAddress(QByteArrayLiteral("glTextureImage2DMultisampleNV"))); @@ -127,11 +141,14 @@ QOpenGLTextureHelper::QOpenGLTextureHelper(QOpenGLContext *context) TextureImage3DMultisample = &QOpenGLTextureHelper::dsa_TextureImage3DMultisample; TextureImage2DMultisample = &QOpenGLTextureHelper::dsa_TextureImage2DMultisample; } else { +#endif TextureImage3DMultisample = &QOpenGLTextureHelper::qt_TextureImage3DMultisample; TextureImage2DMultisample = &QOpenGLTextureHelper::qt_TextureImage2DMultisample; +#if !defined(QT_OPENGL_ES_2) } +#endif -#if defined(Q_OS_WIN) +#if defined(Q_OS_WIN) && !defined(QT_OPENGL_ES_2) HMODULE handle = GetModuleHandleA("opengl32.dll"); // OpenGL 1.0 diff --git a/src/gui/opengl/qopengltexturehelper_p.h b/src/gui/opengl/qopengltexturehelper_p.h index e3abaa80af..fa4bd8120a 100644 --- a/src/gui/opengl/qopengltexturehelper_p.h +++ b/src/gui/opengl/qopengltexturehelper_p.h @@ -256,6 +256,7 @@ public: } private: +#if !defined(QT_OPENGL_ES_2) // DSA wrapper (so we can use pointer to member function as switch) inline void dsa_TextureParameteri(GLuint texture, GLenum target, GLenum pname, GLint param) { @@ -403,6 +404,7 @@ private: { CompressedTextureImage3DEXT(texture, target, level, internalFormat, width, height, depth, border, imageSize, bits); } +#endif // DSA-like API @@ -899,6 +901,7 @@ public: int val = 0; glGetIntegerv(GL_UNPACK_ALIGNMENT, &val); options.setAlignment(val); +#if !defined(QT_OPENGL_ES_2) glGetIntegerv(GL_UNPACK_SKIP_IMAGES, &val); options.setSkipImages(val); glGetIntegerv(GL_UNPACK_SKIP_ROWS, &val); @@ -914,12 +917,14 @@ public: options.setLeastSignificantByteFirst(b); glGetBooleanv(GL_UNPACK_SWAP_BYTES, &b); options.setSwapBytesEnabled(b); +#endif return options; } inline void setPixelUploadOptions(const QOpenGLPixelTransferOptions &options) { glPixelStorei(GL_UNPACK_ALIGNMENT, options.alignment()); +#if !defined(QT_OPENGL_ES_2) glPixelStorei(GL_UNPACK_SKIP_IMAGES, options.skipImages()); glPixelStorei(GL_UNPACK_SKIP_ROWS, options.skipRows()); glPixelStorei(GL_UNPACK_SKIP_PIXELS, options.skipPixels()); @@ -927,6 +932,7 @@ public: glPixelStorei(GL_UNPACK_ROW_LENGTH, options.rowLength()); glPixelStorei(GL_UNPACK_LSB_FIRST, options.isLeastSignificantBitFirst()); glPixelStorei(GL_UNPACK_SWAP_BYTES, options.isSwapBytesEnabled()); +#endif } private: @@ -982,6 +988,7 @@ private: CompressedTextureImage2DMemberFunc CompressedTextureImage2D; CompressedTextureImage3DMemberFunc CompressedTextureImage3D; +#if !defined(QT_OPENGL_ES_2) // Raw function pointers for core and DSA functions // EXT_direct_state_access used when DSA is available @@ -1012,6 +1019,7 @@ private: // Plus some missing ones that are in the NV_texture_multisample extension instead void (QOPENGLF_APIENTRYP TextureImage3DMultisampleNV)(GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); void (QOPENGLF_APIENTRYP TextureImage2DMultisampleNV)(GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations); +#endif // OpenGL 1.0 void (QOPENGLF_APIENTRYP GetIntegerv)(GLenum pname, GLint *params); diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp index 38c2dd6498..b35fa38ce0 100644 --- a/src/gui/painting/qbrush.cpp +++ b/src/gui/painting/qbrush.cpp @@ -508,7 +508,7 @@ QBrush::QBrush(Qt::GlobalColor color, Qt::BrushStyle style) The style is set to Qt::TexturePattern. The color will only have an effect for QBitmaps. - \sa setColor(), setPixmap() + \sa setColor(), setTexture() */ QBrush::QBrush(const QColor &color, const QPixmap &pixmap) @@ -525,7 +525,7 @@ QBrush::QBrush(const QColor &color, const QPixmap &pixmap) The style is set to Qt::TexturePattern. The color will only have an effect for QBitmaps. - \sa setColor(), setPixmap() + \sa setColor(), setTexture() */ QBrush::QBrush(Qt::GlobalColor color, const QPixmap &pixmap) { diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp index b12fd71563..541b3ef619 100644 --- a/src/gui/painting/qdrawhelper_neon.cpp +++ b/src/gui/painting/qdrawhelper_neon.cpp @@ -964,6 +964,7 @@ public: union Vect_buffer_i { Int32x4 v; int i[4]; }; union Vect_buffer_f { Float32x4 v; float f[4]; }; + static inline Float32x4 v_dup(double x) { return vdupq_n_f32(float(x)); } static inline Float32x4 v_dup(float x) { return vdupq_n_f32(x); } static inline Int32x4 v_dup(int x) { return vdupq_n_s32(x); } static inline Int32x4 v_dup(uint x) { return vdupq_n_s32(x); } diff --git a/src/gui/painting/qpaintengine.h b/src/gui/painting/qpaintengine.h index b4dec2929d..18b6d84146 100644 --- a/src/gui/painting/qpaintengine.h +++ b/src/gui/painting/qpaintengine.h @@ -247,12 +247,6 @@ private: friend class QFontEngineBox; friend class QFontEngineMac; friend class QFontEngineWin; -#ifndef QT_NO_QWS_QPF - friend class QFontEngineQPF1; -#endif -#ifndef QT_NO_QWS_QPF2 - friend class QFontEngineQPF; -#endif friend class QMacPrintEngine; friend class QMacPrintEnginePrivate; friend class QFontEngineQPA; diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 4a26da104d..bdd0d9cd4c 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -308,9 +308,9 @@ QRasterPaintEnginePrivate::QRasterPaintEnginePrivate() : of painting operations in Qt for Embedded Linux. Note that this functionality is only available in - \l{Qt for Embedded Linux}. + Qt for Embedded Linux. - In \l{Qt for Embedded Linux}, painting is a pure software + In Qt for Embedded Linux, painting is a pure software implementation. But starting with Qt 4.2, it is possible to add an accelerated graphics driver to take advantage of available hardware resources. @@ -318,19 +318,15 @@ QRasterPaintEnginePrivate::QRasterPaintEnginePrivate() : Hardware acceleration is accomplished by creating a custom screen driver, accelerating the copying from memory to the screen, and implementing a custom paint engine accelerating the various - painting operations. Then a custom paint device (derived from the - QCustomRasterPaintDevice class) and a custom window surface - (derived from QWSWindowSurface) must be implemented to make - \l{Qt for Embedded Linux} aware of the accelerated driver. + painting operations. Then a custom paint device and a custom + window surface must be implemented to make + Qt for Embedded Linux aware of the accelerated driver. \note The QRasterPaintEngine class does not support 8-bit images. Instead, they need to be converted to a supported format, such as QImage::Format_ARGB32_Premultiplied. - See the \l {Adding an Accelerated Graphics Driver to Qt for Embedded Linux} - documentation for details. - - \sa QCustomRasterPaintDevice, QPaintEngine + \sa QPaintEngine */ /*! diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 4c02abdfd5..424ed554a2 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -146,17 +146,16 @@ static inline uint line_emulation(uint emulation) } #ifndef QT_NO_DEBUG -static bool qt_painter_thread_test(int devType, const char *what, bool extraCondition = false) +static bool qt_painter_thread_test(int devType, const char *what) { switch (devType) { case QInternal::Image: case QInternal::Printer: case QInternal::Picture: // can be drawn onto these devices safely from any thread - if (extraCondition) - break; + break; default: - if (!extraCondition && QThread::currentThread() != qApp->thread()) { + if (QThread::currentThread() != qApp->thread()) { qWarning("QPainter: It is not safe to use %s outside the GUI thread", what); return false; } diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp index 9105e8b396..c05f47c59d 100644 --- a/src/gui/painting/qpdf.cpp +++ b/src/gui/painting/qpdf.cpp @@ -1651,7 +1651,7 @@ void QPdfEnginePrivate::writeInfo() xprintf("\n/Creator "); printString(creator); xprintf("\n/Producer "); - printString(QString::fromLatin1("Qt " QT_VERSION_STR " (C) 2012 Digia Plc and/or its subsidiary(-ies)")); + printString(QString::fromLatin1("Qt " QT_VERSION_STR)); QDateTime now = QDateTime::currentDateTime().toUTC(); QTime t = now.time(); QDate d = now.date(); diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp index 2166ae7975..b953f8d81f 100644 --- a/src/gui/painting/qtextureglyphcache.cpp +++ b/src/gui/painting/qtextureglyphcache.cpp @@ -152,6 +152,18 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const continue; if (listItemCoordinates.contains(GlyphAndSubPixelPosition(glyph, subPixelPosition))) continue; + + // This is a rather crude hack, but it works. + // The FreeType font engine is not capable of getting precise metrics for the alphamap + // without first rasterizing the glyph. If we force the glyph to be rasterized before + // we ask for the alphaMapBoundingBox(), the glyph will be loaded, rasterized and its + // proper metrics will be cached and used later. + if (fontEngine->hasInternalCaching()) { + QImage *locked = fontEngine->lockedAlphaMapForGlyph(glyph, subPixelPosition, format); + if (locked) + fontEngine->unlockAlphaMapForGlyph(); + } + glyph_metrics_t metrics = fontEngine->alphaMapBoundingBox(glyph, subPixelPosition, m_transform, format); #ifdef CACHE_DEBUG diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index a410004c06..49b5a9ba46 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -208,7 +208,7 @@ QFontEngine *QFontPrivate::engineForScript(int script) const QMutexLocker locker(qt_fontdatabase_mutex()); if (script <= QChar::Script_Latin) script = QChar::Script_Common; - if (engineData && engineData->fontCache != QFontCache::instance()) { + if (engineData && engineData->fontCacheId != QFontCache::instance()->id()) { // throw out engineData that came from a different thread if (!engineData->ref.deref()) delete engineData; @@ -317,7 +317,7 @@ void QFontPrivate::resolve(uint mask, const QFontPrivate *other) QFontEngineData::QFontEngineData() - : ref(0), fontCache(QFontCache::instance()) + : ref(0), fontCacheId(QFontCache::instance()->id()) { memset(engines, 0, QChar::ScriptCount * sizeof(QFontEngine *)); } @@ -2638,9 +2638,12 @@ void QFontCache::cleanup() } #endif // QT_NO_THREAD +QBasicAtomicInt font_cache_id = Q_BASIC_ATOMIC_INITIALIZER(1); + QFontCache::QFontCache() : QObject(), total_cost(0), max_cost(min_cost), - current_timestamp(0), fast(false), timer_id(-1) + current_timestamp(0), fast(false), timer_id(-1), + m_id(font_cache_id.fetchAndAddRelaxed(1)) { } diff --git a/src/gui/text/qfont_p.h b/src/gui/text/qfont_p.h index 115e866f24..5b7f918e21 100644 --- a/src/gui/text/qfont_p.h +++ b/src/gui/text/qfont_p.h @@ -140,7 +140,7 @@ public: ~QFontEngineData(); QAtomicInt ref; - QFontCache *fontCache; + const int fontCacheId; QFontEngine *engines[QChar::ScriptCount]; @@ -206,6 +206,8 @@ public: QFontCache(); ~QFontCache(); + int id() const { return m_id; } + void clear(); struct Key { @@ -263,6 +265,7 @@ private: uint current_timestamp; bool fast; int timer_id; + const int m_id; }; Q_GUI_EXPORT int qt_defaultDpiX(); diff --git a/src/gui/text/qfontdatabase_qpa.cpp b/src/gui/text/qfontdatabase_qpa.cpp index 6c0be950dc..fddbb11122 100644 --- a/src/gui/text/qfontdatabase_qpa.cpp +++ b/src/gui/text/qfontdatabase_qpa.cpp @@ -184,6 +184,7 @@ QFontEngine *loadSingleEngine(int script, if (!engine) { engine = pfdb->fontEngine(def, QChar::Script(script), size->handle); if (engine) { + engine->smoothScalable = style->smoothScalable; QFontCache::Key key(def,script); QFontCache::instance()->instance()->insertEngine(key,engine); } diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 303c85ce75..7d1afbbfb6 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -208,7 +208,8 @@ Q_AUTOTEST_EXPORT QList<QFontEngine *> QFontEngine_stopCollectingEngines() QFontEngine::QFontEngine() : ref(0), font_(0), font_destroy_func(0), - face_(0), face_destroy_func(0) + face_(0), face_destroy_func(0), + smoothScalable(false) { cache_cost = 0; fsType = 0; diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 6e14fc23c6..22d2585898 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -112,7 +112,7 @@ QT_BEGIN_NAMESPACE #endif #define FLOOR(x) ((x) & -64) -#define CEIL(x) (((x)+63) & -64) +#define CEIL(x) (((x)+63) & -64) #define TRUNC(x) ((x) >> 6) #define ROUND(x) (((x)+32) & -64) @@ -124,11 +124,21 @@ public: QtFreetypeData() : library(0) { } + ~QtFreetypeData(); FT_Library library; QHash<QFontEngine::FaceId, QFreetypeFace *> faces; }; +QtFreetypeData::~QtFreetypeData() +{ + for (QHash<QFontEngine::FaceId, QFreetypeFace *>::ConstIterator iter = faces.begin(); iter != faces.end(); ++iter) + iter.value()->cleanup(); + faces.clear(); + FT_Done_FreeType(library); + library = 0; +} + #ifdef QT_NO_THREAD Q_GLOBAL_STATIC(QtFreetypeData, theFreetypeData) @@ -292,23 +302,35 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id, return freetype; } +void QFreetypeFace::cleanup() +{ + if (hbFace && hbFace_destroy_func) { + hbFace_destroy_func(hbFace); + hbFace = 0; + } + FT_Done_Face(face); + face = 0; +} + void QFreetypeFace::release(const QFontEngine::FaceId &face_id) { - QtFreetypeData *freetypeData = qt_getFreetypeData(); if (!ref.deref()) { - if (hbFace && hbFace_destroy_func) { - hbFace_destroy_func(hbFace); - hbFace = 0; + if (face) { + QtFreetypeData *freetypeData = qt_getFreetypeData(); + + cleanup(); + + if (freetypeData->faces.contains(face_id)) + freetypeData->faces.take(face_id); + + if (freetypeData->faces.isEmpty()) { + FT_Done_FreeType(freetypeData->library); + freetypeData->library = 0; + } } - FT_Done_Face(face); - if(freetypeData->faces.contains(face_id)) - freetypeData->faces.take(face_id); + delete this; } - if (freetypeData->faces.isEmpty()) { - FT_Done_FreeType(freetypeData->library); - freetypeData->library = 0; - } } @@ -631,7 +653,8 @@ QFontEngineFT::QFontEngineFT(const QFontDef &fd) #endif defaultFormat = Format_None; embeddedbitmap = false; - cacheEnabled = qEnvironmentVariableIsSet("QT_USE_FT_CACHE"); + const QByteArray env = qgetenv("QT_NO_FT_CACHE"); + cacheEnabled = env.isEmpty() || env.toInt() == 0; m_subPixelPositionCount = 4; } @@ -699,7 +722,6 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format, line_thickness = QFixed::fromFixed(FT_MulFix(face->underline_thickness, face->size->metrics.y_scale)); underline_position = QFixed::fromFixed(-FT_MulFix(face->underline_position, face->size->metrics.y_scale)); } else { - // copied from QFontEngineQPF // ad hoc algorithm int score = fontDef.weight * fontDef.pixelSize; line_thickness = score / 700; @@ -1742,7 +1764,7 @@ glyph_metrics_t QFontEngineFT::alphaMapBoundingBox(glyph_t glyph, QFixed subPixe glyphSet = &defaultGlyphSet; } } - Glyph * g = glyphSet ? glyphSet->getGlyph(glyph) : 0; + Glyph * g = glyphSet ? glyphSet->getGlyph(glyph, subPixelPosition) : 0; if (!g || g->format != format) { face = lockFace(); FT_Matrix m = this->matrix; diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h index e64fec2f27..7df66b9678 100644 --- a/src/gui/text/qfontengine_ft_p.h +++ b/src/gui/text/qfontengine_ft_p.h @@ -114,9 +114,11 @@ public: private: friend class QFontEngineFT; + friend class QtFreetypeData; friend struct QScopedPointerDeleter<QFreetypeFace>; QFreetypeFace() : _lock(QMutex::Recursive) {} ~QFreetypeFace() {} + void cleanup(); QAtomicInt ref; QMutex _lock; QByteArray fontData; diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index c181d61d73..07be498764 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -302,6 +302,8 @@ public: inline QVariant userData() const { return m_userData; } + bool smoothScalable; + protected: QFixed lastRightBearing(const QGlyphLayout &glyphs, bool round = false); diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp index 58c9addec1..1a66657cbd 100644 --- a/src/gui/text/qfontmetrics.cpp +++ b/src/gui/text/qfontmetrics.cpp @@ -1587,7 +1587,7 @@ QRectF QFontMetricsF::boundingRect(const QRectF &rect, int flags, const QString& \li Qt::TextWordBreak breaks the text to fit the rectangle. \endlist - These flags are defined in \l{Qt::TextFlags}. + These flags are defined in the \l{Qt::TextFlag} enum. If Qt::TextExpandTabs is set in \a flags, the following behavior is used to interpret tab characters in the text: diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index 180b09be33..82d63237e7 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -2527,7 +2527,7 @@ static bool isOrderedList(int style) || style == QTextListFormat::ListUpperAlpha || style == QTextListFormat::ListUpperRoman || style == QTextListFormat::ListLowerRoman - ; + ; } void QTextHtmlExporter::emitBlockAttributes(const QTextBlock &block) diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp index f0910dd52d..4b6ce667fa 100644 --- a/src/gui/text/qtextdocument_p.cpp +++ b/src/gui/text/qtextdocument_p.cpp @@ -632,7 +632,7 @@ void QTextDocumentPrivate::move(int pos, int to, int length, QTextUndoCommand::O blockRevision); if (key+1 != blocks.position(b)) { -// qDebug("remove_string from %d length %d", key, X->size_array[0]); +// qDebug("remove_string from %d length %d", key, X->size_array[0]); Q_ASSERT(noBlockInString(text.mid(X->stringPosition, X->size_array[0]))); w = remove_string(key, X->size_array[0], op); @@ -641,7 +641,7 @@ void QTextDocumentPrivate::move(int pos, int to, int length, QTextUndoCommand::O dstKey += X->size_array[0]; } } else { -// qDebug("remove_block at %d", key); +// qDebug("remove_block at %d", key); Q_ASSERT(X->size_array[0] == 1 && isValidBlockSeparator(text.at(X->stringPosition))); b = blocks.previous(b); B = 0; @@ -779,7 +779,7 @@ void QTextDocumentPrivate::setCharFormat(int pos, int length, const QTextCharFor } void QTextDocumentPrivate::setBlockFormat(const QTextBlock &from, const QTextBlock &to, - const QTextBlockFormat &newFormat, FormatChangeMode mode) + const QTextBlockFormat &newFormat, FormatChangeMode mode) { beginEditBlock(); @@ -795,7 +795,7 @@ void QTextDocumentPrivate::setBlockFormat(const QTextBlock &from, const QTextBlo QTextBlock it = from; QTextBlock end = to; if (end.isValid()) - end = end.next(); + end = end.next(); for (; it != end; it = it.next()) { int oldFormat = block(it)->format; @@ -820,8 +820,8 @@ void QTextDocumentPrivate::setBlockFormat(const QTextBlock &from, const QTextBlo if (group) group->blockInserted(it); } else if (group) { - group->blockFormatChanged(it); - } + group->blockFormatChanged(it); + } } documentChange(from.position(), to.position() + to.length() - from.position()); @@ -892,14 +892,14 @@ int QTextDocumentPrivate::undoRedo(bool undo) QTextUndoCommand &c = undoStack[undoState]; int resetBlockRevision = c.pos; - switch(c.command) { + switch (c.command) { case QTextUndoCommand::Inserted: remove(c.pos, c.length, (QTextUndoCommand::Operation)c.operation); PMDEBUG(" erase: from %d, length %d", c.pos, c.length); c.command = QTextUndoCommand::Removed; editPos = c.pos; editLength = 0; - break; + break; case QTextUndoCommand::Removed: PMDEBUG(" insert: format %d (from %d, length %d, strpos=%d)", c.format, c.pos, c.length, c.strPos); insert_string(c.pos, c.strPos, c.length, c.format, (QTextUndoCommand::Operation)c.operation); @@ -908,33 +908,33 @@ int QTextDocumentPrivate::undoRedo(bool undo) editLength = 0; editPos = c.pos; editLength += c.length; - break; - case QTextUndoCommand::BlockInserted: - case QTextUndoCommand::BlockAdded: + break; + case QTextUndoCommand::BlockInserted: + case QTextUndoCommand::BlockAdded: remove_block(c.pos, &c.blockFormat, c.command, (QTextUndoCommand::Operation)c.operation); PMDEBUG(" blockremove: from %d", c.pos); - if (c.command == QTextUndoCommand::BlockInserted) - c.command = QTextUndoCommand::BlockRemoved; - else - c.command = QTextUndoCommand::BlockDeleted; + if (c.command == QTextUndoCommand::BlockInserted) + c.command = QTextUndoCommand::BlockRemoved; + else + c.command = QTextUndoCommand::BlockDeleted; editPos = c.pos; editLength = 0; - break; - case QTextUndoCommand::BlockRemoved: - case QTextUndoCommand::BlockDeleted: + break; + case QTextUndoCommand::BlockRemoved: + |