diff options
author | Lasse Räihä <lasse.raiha@digia.com> | 2013-05-13 14:30:18 +0300 |
---|---|---|
committer | Kimmo Ollila <kimmo.ollila@digia.com> | 2013-05-13 14:41:53 +0300 |
commit | d542680173e0b9a5bcd11fd6fa31523a406d1847 (patch) | |
tree | 54b77966e4fff6510dfc45c15214381339cfdf55 | |
parent | 36f4b671ce645d84b2e1c07613dfe486aa792971 (diff) |
Fixed navigation. Added support to press Back-button. Fixed Slide-containers. Fixed some styles.
Change-Id: I8f009ded55a7c1f46faf8a4002a5b2a751bf4239
Reviewed-by: Kimmo Ollila <kimmo.ollila@digia.com>
21 files changed, 1677 insertions, 82 deletions
diff --git a/QtDemo/android/src/org/qtproject/qt5/android/bindings/QtActivity.java b/QtDemo/android/src/org/qtproject/qt5/android/bindings/QtActivity.java new file mode 100644 index 0000000..9a8056b --- /dev/null +++ b/QtDemo/android/src/org/qtproject/qt5/android/bindings/QtActivity.java @@ -0,0 +1,1314 @@ +/* + Copyright (c) 2012-2013, BogDan Vatra <bogdan@kde.org> + Contact: http://www.qt-project.org/legal + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. 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. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +*/ + +package org.qtproject.qt5.android.bindings; + +import java.io.File; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; + +import org.kde.necessitas.ministro.IMinistro; +import org.kde.necessitas.ministro.IMinistroCallback; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.ComponentName; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.Configuration; +import android.content.res.Resources.Theme; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.net.Uri; +import android.os.Bundle; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.AttributeSet; +import android.util.Log; +import android.view.ContextMenu; +import android.view.ContextMenu.ContextMenuInfo; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MotionEvent; +import android.view.View; +import android.view.Window; +import android.view.WindowManager.LayoutParams; +import android.view.accessibility.AccessibilityEvent; +import dalvik.system.DexClassLoader; + +//@ANDROID-11 +import android.app.Fragment; +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 + private static final int MINISTRO_API_LEVEL = 3; // Ministro api level (check IMinistro.aidl file) + private static final int NECESSITAS_API_LEVEL = 2; // Necessitas api level used by platform plugin + private static final int QT_VERSION = 0x050100; // This app requires at least Qt version 5.1.0 + + private static final String ERROR_CODE_KEY = "error.code"; + private static final String ERROR_MESSAGE_KEY = "error.message"; + private static final String DEX_PATH_KEY = "dex.path"; + private static final String LIB_PATH_KEY = "lib.path"; + private static final String LOADER_CLASS_NAME_KEY = "loader.class.name"; + private static final String NATIVE_LIBRARIES_KEY = "native.libraries"; + private static final String ENVIRONMENT_VARIABLES_KEY = "environment.variables"; + private static final String APPLICATION_PARAMETERS_KEY = "application.parameters"; + private static final String BUNDLED_LIBRARIES_KEY = "bundled.libraries"; + private static final String MAIN_LIBRARY_KEY = "main.library"; + private static final String STATIC_INIT_CLASSES_KEY = "static.init.classes"; + private static final String NECESSITAS_API_LEVEL_KEY = "necessitas.api.level"; + + /// Ministro server parameter keys + private static final String REQUIRED_MODULES_KEY = "required.modules"; + private static final String APPLICATION_TITLE_KEY = "application.title"; + private static final String MINIMUM_MINISTRO_API_KEY = "minimum.ministro.api"; + private static final String MINIMUM_QT_VERSION_KEY = "minimum.qt.version"; + private static final String SOURCES_KEY = "sources"; // needs MINISTRO_API_LEVEL >=3 !!! + // Use this key to specify any 3rd party sources urls + // Ministro will download these repositories into their + // own folders, check http://community.kde.org/Necessitas/Ministro + // for more details. + + private static final String REPOSITORY_KEY = "repository"; // use this key to overwrite the default ministro repsitory + + private static final 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 static final String ENVIRONMENT_VARIABLES = "QT_USE_ANDROID_NATIVE_STYLE=0\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 int INCOMPATIBLE_MINISTRO_VERSION = 1; // Incompatible Ministro version. Ministro needs to be upgraded. + private ActivityInfo m_activityInfo = null; // activity info object, used to access the libs and the strings + private DexClassLoader m_classLoader = null; // loader object + private String[] m_sources = {"https://files.kde.org/necessitas/ministro/android/necessitas/qt5/latest"}; // Make sure you are using ONLY secure locations + private String m_repository = "default"; // Overwrites the default Ministro repository + // Possible values: + // * default - Ministro default repository set with "Ministro configuration tool". + // By default the stable version is used. Only this or stable repositories should + // be used in production. + // * stable - stable repository, only this and default repositories should be used + // in production. + // * testing - testing repository, DO NOT use this repository in production, + // this repository is used to push a new release, and should be used to test your application. + // * unstable - unstable repository, DO NOT use this repository in production, + // this repository is used to push Qt snapshots. + private String[] m_qtLibs = null; // required qt libs + + // this function is used to load and start the loader + private void loadApplication(Bundle loaderParams) + { + try { + final int errorCode = loaderParams.getInt(ERROR_CODE_KEY); + if (errorCode != 0) { + if (errorCode == INCOMPATIBLE_MINISTRO_VERSION) { + downloadUpgradeMinistro(loaderParams.getString(ERROR_MESSAGE_KEY)); + return; + } + + // fatal error, show the error and quit + AlertDialog errorDialog = new AlertDialog.Builder(QtActivity.this).create(); + errorDialog.setMessage(loaderParams.getString(ERROR_MESSAGE_KEY)); + errorDialog.setButton(getResources().getString(android.R.string.ok), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + finish(); + } + }); + errorDialog.show(); + return; + } + + // add all bundled Qt libs to loader params + ArrayList<String> libs = new ArrayList<String>(); + if ( m_activityInfo.metaData.containsKey("android.app.bundled_libs_resource_id") ) + libs.addAll(Arrays.asList(getResources().getStringArray(m_activityInfo.metaData.getInt("android.app.bundled_libs_resource_id")))); + + String libName = null; + if ( m_activityInfo.metaData.containsKey("android.app.lib_name") ) { + libName = m_activityInfo.metaData.getString("android.app.lib_name"); + loaderParams.putString(MAIN_LIBRARY_KEY, libName); //main library contains main() function + } + + loaderParams.putStringArrayList(BUNDLED_LIBRARIES_KEY, libs); + loaderParams.putInt(NECESSITAS_API_LEVEL_KEY, NECESSITAS_API_LEVEL); + + // load and start QtLoader class + m_classLoader = new DexClassLoader(loaderParams.getString(DEX_PATH_KEY), // .jar/.apk files + getDir("outdex", Context.MODE_PRIVATE).getAbsolutePath(), // directory where optimized DEX files should be written. + loaderParams.containsKey(LIB_PATH_KEY) ? loaderParams.getString(LIB_PATH_KEY) : null, // libs folder (if exists) + getClassLoader()); // parent loader + + @SuppressWarnings("rawtypes") + Class loaderClass = m_classLoader.loadClass(loaderParams.getString(LOADER_CLASS_NAME_KEY)); // load QtLoader class + Object qtLoader = loaderClass.newInstance(); // create an instance + Method perpareAppMethod = qtLoader.getClass().getMethod("loadApplication", + Activity.class, + ClassLoader.class, + Bundle.class); + if (!(Boolean)perpareAppMethod.invoke(qtLoader, this, m_classLoader, loaderParams)) + throw new Exception(""); + + QtApplication.setQtActivityDelegate(qtLoader); + + // now load the application library so it's accessible from this class loader + if (libName != null) + System.loadLibrary(libName); + + Method startAppMethod=qtLoader.getClass().getMethod("startApplication"); + if (!(Boolean)startAppMethod.invoke(qtLoader)) + throw new Exception(""); + + } catch (Exception e) { + e.printStackTrace(); + AlertDialog errorDialog = new AlertDialog.Builder(QtActivity.this).create(); + if (m_activityInfo.metaData.containsKey("android.app.fatal_error_msg")) + errorDialog.setMessage(m_activityInfo.metaData.getString("android.app.fatal_error_msg")); + else + errorDialog.setMessage("Fatal error, your application can't be started."); + + errorDialog.setButton(getResources().getString(android.R.string.ok), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + finish(); + } + }); + errorDialog.show(); + } + } + + private ServiceConnection m_ministroConnection=new ServiceConnection() { + private IMinistro m_service = null; + @Override + public void onServiceConnected(ComponentName name, IBinder service) + { + m_service = IMinistro.Stub.asInterface(service); + try { + 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) + parameters.putString(APPLICATION_PARAMETERS_KEY, APPLICATION_PARAMETERS); + parameters.putStringArray(SOURCES_KEY, m_sources); + parameters.putString(REPOSITORY_KEY, m_repository); + m_service.requestLoader(m_ministroCallback, parameters); + } + } catch (RemoteException e) { + e.printStackTrace(); + } + } + + 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) { + m_service = null; + } + }; + + private void downloadUpgradeMinistro(String msg) + { + AlertDialog.Builder downloadDialog = new AlertDialog.Builder(this); + downloadDialog.setMessage(msg); + downloadDialog.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + try { + Uri uri = Uri.parse("market://search?q=pname:org.kde.necessitas.ministro"); + Intent intent = new Intent(Intent.ACTION_VIEW, uri); + startActivityForResult(intent, MINISTRO_INSTALL_REQUEST_CODE); + } catch (Exception e) { + e.printStackTrace(); + ministroNotFound(); + } + } + }); + + downloadDialog.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + QtActivity.this.finish(); + } + }); + downloadDialog.show(); + } + + private void ministroNotFound() + { + AlertDialog errorDialog = new AlertDialog.Builder(QtActivity.this).create(); + + if (m_activityInfo.metaData.containsKey("android.app.ministro_not_found_msg")) + errorDialog.setMessage(m_activityInfo.metaData.getString("android.app.ministro_not_found_msg")); + else + errorDialog.setMessage("Can't find Ministro service.\nThe application can't start."); + + errorDialog.setButton(getResources().getString(android.R.string.ok), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + finish(); + } + }); + errorDialog.show(); + } + + private void startApp(final boolean firstStart) + { + try { + if (m_activityInfo.metaData.containsKey("android.app.qt_sources_resource_id")) { + int resourceId = m_activityInfo.metaData.getInt("android.app.qt_sources_resource_id"); + m_sources = getResources().getStringArray(resourceId); + } + + if (m_activityInfo.metaData.containsKey("android.app.repository")) + m_repository = m_activityInfo.metaData.getString("android.app.repository"); + + if (m_activityInfo.metaData.containsKey("android.app.qt_libs_resource_id")) { + int resourceId = m_activityInfo.metaData.getInt("android.app.qt_libs_resource_id"); + m_qtLibs = getResources().getStringArray(resourceId); + } + + if (m_activityInfo.metaData.containsKey("android.app.use_local_qt_libs") + && m_activityInfo.metaData.getInt("android.app.use_local_qt_libs") == 1) { + ArrayList<String> libraryList = new ArrayList<String>(); + + String localPrefix = "/data/local/tmp/qt/"; + if (m_activityInfo.metaData.containsKey("android.app.libs_prefix")) + localPrefix = m_activityInfo.metaData.getString("android.app.libs_prefix"); + + if (m_qtLibs != null) { + for (int i=0;i<m_qtLibs.length;i++) + libraryList.add(localPrefix+"lib/lib"+m_qtLibs[i]+".so"); + } + + if (m_activityInfo.metaData.containsKey("android.app.load_local_libs")) { + String[] extraLibs = m_activityInfo.metaData.getString("android.app.load_local_libs").split(":"); + for (String lib : extraLibs) { + if (lib.length() > 0) + libraryList.add(localPrefix + lib); + } + } + + String dexPaths = new String(); + String pathSeparator = System.getProperty("path.separator", ":"); + if (m_activityInfo.metaData.containsKey("android.app.load_local_jars")) { + String[] jarFiles = m_activityInfo.metaData.getString("android.app.load_local_jars").split(":"); + for (String jar:jarFiles) { + if (jar.length() > 0) { + if (dexPaths.length() > 0) + dexPaths += pathSeparator; + dexPaths += localPrefix + jar; + } + } + } + + Bundle loaderParams = new Bundle(); + loaderParams.putInt(ERROR_CODE_KEY, 0); + loaderParams.putString(DEX_PATH_KEY, dexPaths); + loaderParams.putString(LOADER_CLASS_NAME_KEY, "org.qtproject.qt5.android.QtActivityDelegate"); + if (m_activityInfo.metaData.containsKey("android.app.static_init_classes")) { + loaderParams.putStringArray(STATIC_INIT_CLASSES_KEY, + m_activityInfo.metaData.getString("android.app.static_init_classes").split(":")); + } + loaderParams.putStringArrayList(NATIVE_LIBRARIES_KEY, libraryList); + loaderParams.putString(ENVIRONMENT_VARIABLES_KEY, ENVIRONMENT_VARIABLES + + "QT_QPA_EGLFS_HIDECURSOR=1" + + "\tQML2_IMPORT_PATH=" + localPrefix + "/qml" + + "\tQML_IMPORT_PATH=" + localPrefix + "/imports" + + "\tQT_PLUGIN_PATH=" + localPrefix + "/plugins"); + loadApplication(loaderParams); + return; + } + + try { + if (!bindService(new Intent(org.kde.necessitas.ministro.IMinistro.class.getCanonicalName()), + m_ministroConnection, + Context.BIND_AUTO_CREATE)) { + throw new SecurityException(""); + } + } catch (Exception e) { + if (firstStart) { + String msg = "This application requires Ministro service. Would you like to install it?"; + if (m_activityInfo.metaData.containsKey("android.app.ministro_needed_msg")) + msg = m_activityInfo.metaData.getString("android.app.ministro_needed_msg"); + downloadUpgradeMinistro(msg); + } else { + ministroNotFound(); + } + } + } catch (Exception e) { + Log.e(QtApplication.QtTAG, "Can't create main activity", e); + } + } + + + + /////////////////////////// forward all notifications //////////////////////////// + /////////////////////////// Super class calls //////////////////////////////////// + /////////////// PLEASE DO NOT CHANGE THE FOLLOWING CODE ////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + + @Override + public boolean dispatchKeyEvent(KeyEvent event) + { + if (QtApplication.m_delegateObject != null && QtApplication.dispatchKeyEvent != null) + return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.dispatchKeyEvent, event); + else + return super.dispatchKeyEvent(event); + } + public boolean super_dispatchKeyEvent(KeyEvent event) + { + return super.dispatchKeyEvent(event); + } + //--------------------------------------------------------------------------- + + @Override + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) + { + if (QtApplication.m_delegateObject != null && QtApplication.dispatchPopulateAccessibilityEvent != null) + return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.dispatchPopulateAccessibilityEvent, event); + else + return super.dispatchPopulateAccessibilityEvent(event); + } + public boolean super_dispatchPopulateAccessibilityEvent(AccessibilityEvent event) + { + return super_dispatchPopulateAccessibilityEvent(event); + } + //--------------------------------------------------------------------------- + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) + { + if (QtApplication.m_delegateObject != null && QtApplication.dispatchTouchEvent != null) + return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.dispatchTouchEvent, ev); + else + return super.dispatchTouchEvent(ev); + } + public boolean super_dispatchTouchEvent(MotionEvent event) + { + return super.dispatchTouchEvent(event); + } + //--------------------------------------------------------------------------- + + @Override + public boolean dispatchTrackballEvent(MotionEvent ev) + { + if (QtApplication.m_delegateObject != null && QtApplication.dispatchTrackballEvent != null) + return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.dispatchTrackballEvent, ev); + else + return super.dispatchTrackballEvent(ev); + } + public boolean super_dispatchTrackballEvent(MotionEvent event) + { + return super.dispatchTrackballEvent(event); + } + //--------------------------------------------------------------------------- + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) + { + + if (QtApplication.m_delegateObject != null && QtApplication.onActivityResult != null) { + QtApplication.invokeDelegateMethod(QtApplication.onActivityResult, requestCode, resultCode, data); + return; + } + if (requestCode == MINISTRO_INSTALL_REQUEST_CODE) + startApp(false); + super.onActivityResult(requestCode, resultCode, data); + } + public void super_onActivityResult(int requestCode, int resultCode, Intent data) + { + super.onActivityResult(requestCode, resultCode, data); + } + //--------------------------------------------------------------------------- + + @Override + protected void onApplyThemeResource(Theme theme, int resid, boolean first) + { + if (!QtApplication.invokeDelegate(theme, resid, first).invoked) + super.onApplyThemeResource(theme, resid, first); + } + public void super_onApplyThemeResource(Theme theme, int resid, boolean first) + { + super.onApplyThemeResource(theme, resid, first); + } + //--------------------------------------------------------------------------- + + + @Override + protected void onChildTitleChanged(Activity childActivity, CharSequence title) + { + if (!QtApplication.invokeDelegate(childActivity, title).invoked) + super.onChildTitleChanged(childActivity, title); + } + public void super_onChildTitleChanged(Activity childActivity, CharSequence title) + { + super.onChildTitleChanged(childActivity, title); + } + //--------------------------------------------------------------------------- + + @Override + public void onConfigurationChanged(Configuration newConfig) + { + if (!QtApplication.invokeDelegate(newConfig).invoked) + super.onConfigurationChanged(newConfig); + } + public void super_onConfigurationChanged(Configuration newConfig) + { + super.onConfigurationChanged(newConfig); + } + //--------------------------------------------------------------------------- + + @Override + public void onContentChanged() + { + if (!QtApplication.invokeDelegate().invoked) + super.onContentChanged(); + } + public void super_onContentChanged() + { + super.onContentChanged(); + } + //--------------------------------------------------------------------------- + + @Override + public boolean onContextItemSelected(MenuItem item) + { + QtApplication.InvokeResult res = QtApplication.invokeDelegate(item); + if (res.invoked) + return (Boolean)res.methodReturns; + else + return super.onContextItemSelected(item); + } + public boolean super_onContextItemSelected(MenuItem item) + { + return super.onContextItemSelected(item); + } + //--------------------------------------------------------------------------- + + @Override + public void onContextMenuClosed(Menu menu) + { + if (!QtApplication.invokeDelegate(menu).invoked) + super.onContextMenuClosed(menu); + } + public void super_onContextMenuClosed(Menu menu) + { + super.onContextMenuClosed(menu); + } + //--------------------------------------------------------------------------- + + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + if (QtApplication.m_delegateObject != null && QtApplication.onCreate != null) { + QtApplication.invokeDelegateMethod(QtApplication.onCreate, savedInstanceState); + return; + } + + requestWindowFeature(Window.FEATURE_NO_TITLE); + try { + m_activityInfo = getPackageManager().getActivityInfo(getComponentName(), PackageManager.GET_META_DATA); + } catch (NameNotFoundException e) { + e.printStackTrace(); + finish(); + return; + } + + if (null == getLastNonConfigurationInstance()) { + // if splash screen is defined, then show it + if (m_activityInfo.metaData.containsKey("android.app.splash_screen") ) + setContentView(m_activityInfo.metaData.getInt("android.app.splash_screen")); + startApp(true); + } + } + //--------------------------------------------------------------------------- + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) + { + if (!QtApplication.invokeDelegate(menu, v, menuInfo).invoked) + super.onCreateContextMenu(menu, v, menuInfo); + } + public void super_onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) + { + super.onCreateContextMenu(menu, v, menuInfo); + } + //--------------------------------------------------------------------------- + + @Override + public CharSequence onCreateDescription() + { + QtApplication.InvokeResult res = QtApplication.invokeDelegate(); + if (res.invoked) + return (CharSequence)res.methodReturns; + else + return super.onCreateDescription(); + } + public CharSequence super_onCreateDescription() + { + return super.onCreateDescription(); + } + //--------------------------------------------------------------------------- + + @Override + protected Dialog onCreateDialog(int id) + { + QtApplication.InvokeResult res = QtApplication.invokeDelegate(id); + if (res.invoked) + return (Dialog)res.methodReturns; + else + return super.onCreateDialog(id); + } + public Dialog super_onCreateDialog(int id) + { + return super.onCreateDialog(id); + } + //--------------------------------------------------------------------------- + + @Override + public boolean onCreateOptionsMenu(Menu menu) + { + QtApplication.InvokeResult res = QtApplication.invokeDelegate(menu); + if (res.invoked) + return (Boolean)res.methodReturns; + else + return super.onCreateOptionsMenu(menu); + } + public boolean super_onCreateOptionsMenu(Menu menu) + { + return super.onCreateOptionsMenu(menu); + } + //--------------------------------------------------------------------------- + + @Override + public boolean onCreatePanelMenu(int featureId, Menu menu) + { + QtApplication.InvokeResult res = QtApplication.invokeDelegate(featureId, menu); + if (res.invoked) + return (Boolean)res.methodReturns; + else + return super.onCreatePanelMenu(featureId, menu); + } + public boolean super_onCreatePanelMenu(int featureId, Menu menu) + { + return super.onCreatePanelMenu(featureId, menu); + } + //--------------------------------------------------------------------------- + + + @Override + public View onCreatePanelView(int featureId) + { + QtApplication.InvokeResult res = QtApplication.invokeDelegate(featureId); + if (res.invoked) + return (View)res.methodReturns; + else + return super.onCreatePanelView(featureId); + } + public View super_onCreatePanelView(int featureId) + { + return super.onCreatePanelView(featureId); + } + //--------------------------------------------------------------------------- + + @Override + public boolean onCreateThumbnail(Bitmap outBitmap, Canvas canvas) + { + QtApplication.InvokeResult res = QtApplication.invokeDelegate(outBitmap, canvas); + if (res.invoked) + return (Boolean)res.methodReturns; + else + return super.onCreateThumbnail(outBitmap, canvas); + } + public boolean super_onCreateThumbnail(Bitmap outBitmap, Canvas canvas) + { + return super.onCreateThumbnail(outBitmap, canvas); + } + //--------------------------------------------------------------------------- + + @Override + public View onCreateView(String name, Context context, AttributeSet attrs) + { + QtApplication.InvokeResult res = QtApplication.invokeDelegate(name, context, attrs); + if (res.invoked) + return (View)res.methodReturns; + else + return super.onCreateView(name, context, attrs); + } + public View super_onCreateView(String name, Context context, AttributeSet attrs) + { + return super.onCreateView(name, context, attrs); + } + //--------------------------------------------------------------------------- + + @Override + protected void onDestroy() + { + super.onDestroy(); + QtApplication.invokeDelegate(); + } + //--------------------------------------------------------------------------- + + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) + { + int newKeyCode = keyCode; + if ( (keyCode == KeyEvent.KEYCODE_BACK) ) + { + newKeyCode = KeyEvent.KEYCODE_MEDIA_PREVIOUS; + } + + if (QtApplication.m_delegateObject != null && QtApplication.onKeyDown != null) + return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onKeyDown, newKeyCode, event); + else + return super.onKeyDown(newKeyCode, event); + } + public boolean super_onKeyDown(int keyCode, KeyEvent event) + { + return super.onKeyDown(keyCode, event); + } + //--------------------------------------------------------------------------- + + + @Override + public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) + { + int newKeyCode = keyCode; + if ( (keyCode == KeyEvent.KEYCODE_BACK) ) + { + newKeyCode = KeyEvent.KEYCODE_MEDIA_PREVIOUS; + } + + if (QtApplication.m_delegateObject != null && QtApplication.onKeyMultiple != null) + return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onKeyMultiple, newKeyCode, repeatCount, event); + else + return super.onKeyMultiple(newKeyCode, repeatCount, event); + } + public boolean super_onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) + { + return super.onKeyMultiple(keyCode, repeatCount, event); + } + //--------------------------------------------------------------------------- + + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) + { + int newKeyCode = keyCode; + if ( (keyCode == KeyEvent.KEYCODE_BACK) ) + { + newKeyCode = KeyEvent.KEYCODE_MEDIA_PREVIOUS; + } + + if (QtApplication.m_delegateObject != null && QtApplication.onKeyDown != null) + return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onKeyUp, newKeyCode, event); + else + return super.onKeyUp(newKeyCode, event); + } + public boolean super_onKeyUp(int keyCode, KeyEvent event) + { + return super.onKeyUp(keyCode, event); + } + //--------------------------------------------------------------------------- + + @Override + public void onLowMemory() + { + if (!QtApplication.invokeDelegate().invoked) + super.onLowMemory(); + } + //--------------------------------------------------------------------------- + + @Override + public boolean onMenuItemSelected(int featureId, MenuItem item) + { + QtApplication.InvokeResult res = QtApplication.invokeDelegate(featureId, item); + if (res.invoked) + return (Boolean)res.methodReturns; + else + return super.onMenuItemSelected(featureId, item); + } + public boolean super_onMenuItemSelected(int featureId, MenuItem item) + { + return super.onMenuItemSelected(featureId, item); + } + //--------------------------------------------------------------------------- + + @Override + public boolean onMenuOpened(int featureId, Menu menu) + { + QtApplication.InvokeResult res = QtApplication.invokeDelegate(featureId, menu); + if (res.invoked) + return (Boolean)res.methodReturns; + else + return super.onMenuOpened(featureId, menu); + } + public boolean super_onMenuOpened(int featureId, Menu menu) + { + return super.onMenuOpened(featureId, menu); + } + //--------------------------------------------------------------------------- + + @Override + protected void onNewIntent(Intent intent) + { + if (!QtApplication.invokeDelegate(intent).invoked) + super.onNewIntent(intent); + } + public void super_onNewIntent(Intent intent) + { + super.onNewIntent(intent); + } + //--------------------------------------------------------------------------- + + @Override + public boolean onOptionsItemSelected(MenuItem item) + { + QtApplication.InvokeResult res = QtApplication.invokeDelegate(item); + if (res.invoked) + return (Boolean)res.methodReturns; + else + return super.onOptionsItemSelected(item); + } + public boolean super_onOptionsItemSelected(MenuItem item) + { + return super.onOptionsItemSelected(item); + } + //--------------------------------------------------------------------------- + + @Override + public void onOptionsMenuClosed(Menu menu) + { + if (!QtApplication.invokeDelegate(menu).invoked) + super.onOptionsMenuClosed(menu); + } + public void super_onOptionsMenuClosed(Menu menu) + { + super.onOptionsMenuClosed(menu); + } + //--------------------------------------------------------------------------- + + @Override + public void onPanelClosed(int featureId, Menu menu) + { + if (!QtApplication.invokeDelegate(featureId, menu).invoked) + super.onPanelClosed(featureId, menu); + } + public void super_onPanelClosed(int featureId, Menu menu) + { + super.onPanelClosed(featureId, menu); + } + //--------------------------------------------------------------------------- + + @Override + protected void onPause() + { + super.onPause(); + QtApplication.invokeDelegate(); + } + //--------------------------------------------------------------------------- + + @Override + protected void onPostCreate(Bundle savedInstanceState) + { + super.onPostCreate(savedInstanceState); + QtApplication.invokeDelegate(savedInstanceState); + } + //--------------------------------------------------------------------------- + + @Override + protected void onPostResume() + { + super.onPostResume(); + QtApplication.invokeDelegate(); + } + //--------------------------------------------------------------------------- + + @Override + protected void onPrepareDialog(int id, Dialog dialog) + { + if (!QtApplication.invokeDelegate(id, dialog).invoked) + super.onPrepareDialog(id, dialog); + } + public void super_onPrepareDialog(int id, Dialog dialog) + { + super.onPrepareDialog(id, dialog); + } + //--------------------------------------------------------------------------- + + @Override + public boolean onPrepareOptionsMenu(Menu menu) + { + QtApplication.InvokeResult res = QtApplication.invokeDelegate(menu); + if (res.invoked) + return (Boolean)res.methodReturns; + else + return super.onPrepareOptionsMenu(menu); + } + public boolean super_onPrepareOptionsMenu(Menu menu) + { + return super.onPrepareOptionsMenu(menu); + } + //--------------------------------------------------------------------------- + + @Override + public boolean onPreparePanel(int featureId, View view, Menu menu) + { + QtApplication.InvokeResult res = QtApplication.invokeDelegate(featureId, view, menu); + if (res.invoked) + return (Boolean)res.methodReturns; + else + return super.onPreparePanel(featureId, view, menu); + } + public boolean super_onPreparePanel(int featureId, View view, Menu menu) + { + return super.onPreparePanel(featureId, view, menu); + } + //--------------------------------------------------------------------------- + + @Override + protected void onRestart() + { + super.onRestart(); + QtApplication.invokeDelegate(); + } + //--------------------------------------------------------------------------- + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) + { + if (!QtApplication.invokeDelegate(savedInstanceState).invoked) + super.onRestoreInstanceState(savedInstanceState); + } + public void super_onRestoreInstanceState(Bundle savedInstanceState) + { + super.onRestoreInstanceState(savedInstanceState); + } + //--------------------------------------------------------------------------- + + @Override + protected void onResume() + { + super.onResume(); + QtApplication.invokeDelegate(); + } + //--------------------------------------------------------------------------- + + @Override + public Object onRetainNonConfigurationInstance() + { + QtApplication.InvokeResult res = QtApplication.invokeDelegate(); + if (res.invoked) + return res.methodReturns; + else + return super.onRetainNonConfigurationInstance(); + } + public Object super_onRetainNonConfigurationInstance() + { + return super.onRetainNonConfigurationInstance(); + } + //--------------------------------------------------------------------------- + + @Override + protected void onSaveInstanceState(Bundle outState) + { + if (!QtApplication.invokeDelegate(outState).invoked) + super.onSaveInstanceState(outState); + } + public void super_onSaveInstanceState(Bundle outState) + { + super.onSaveInstanceState(outState); + + } + //--------------------------------------------------------------------------- + + @Override + public boolean onSearchRequested() + { + QtApplication.InvokeResult res = QtApplication.invokeDelegate(); + if (res.invoked) + return (Boolean)res.methodReturns; + else + return super.onSearchRequested(); + } + public boolean super_onSearchRequested() + { + return super.onSearchRequested(); + } + //--------------------------------------------------------------------------- + + @Override + protected void onStart() + { + super.onStart(); + QtApplication.invokeDelegate(); + } + //--------------------------------------------------------------------------- + + @Override + protected void onStop() + { + super.onStop(); + QtApplication.invokeDelegate(); + } + //--------------------------------------------------------------------------- + + @Override + protected void onTitleChanged(CharSequence title, int color) + { + if (!QtApplication.invokeDelegate(title, color).invoked) + super.onTitleChanged(title, color); + } + public void super_onTitleChanged(CharSequence title, int color) + { + super.onTitleChanged(title, color); + } + //--------------------------------------------------------------------------- + + @Override + public boolean onTouchEvent(MotionEvent event) + { + if (QtApplication.m_delegateObject != null && QtApplication.onTouchEvent != null) + return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onTouchEvent, event); + else + return super.onTouchEvent(event); + } + public boolean super_onTouchEvent(MotionEvent event) + { + return super.onTouchEvent(event); + } + //--------------------------------------------------------------------------- + + @Override + public boolean onTrackballEvent(MotionEvent event) + { + if (QtApplication.m_delegateObject != null && QtApplication.onTrackballEvent != null) + return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onTrackballEvent, event); + else + return super.onTrackballEvent(event); + } + public boolean super_onTrackballEvent(MotionEvent event) + { + return super.onTrackballEvent(event); + } + //--------------------------------------------------------------------------- + + @Override + public void onUserInteraction() + { + if (!QtApplication.invokeDelegate().invoked) + super.onUserInteraction(); + } + public void super_onUserInteraction() + { + super.onUserInteraction(); + } + //--------------------------------------------------------------------------- + + @Override + protected void onUserLeaveHint() + { + if (!QtApplication.invokeDelegate().invoked) + super.onUserLeaveHint(); + } + public void super_onUserLeaveHint() + { + super.onUserLeaveHint(); + } + //--------------------------------------------------------------------------- + + @Override + public void onWindowAttributesChanged(LayoutParams params) + { + if (!QtApplication.invokeDelegate(params).invoked) + super.onWindowAttributesChanged(params); + } + public void super_onWindowAttributesChanged(LayoutParams params) + { + super.onWindowAttributesChanged(params); + } + //--------------------------------------------------------------------------- + + @Override + public void onWindowFocusChanged(boolean hasFocus) + { + if (!QtApplication.invokeDelegate(hasFocus).invoked) + super.onWindowFocusChanged(hasFocus); + } + public void super_onWindowFocusChanged(boolean hasFocus) + { + super.onWindowFocusChanged(hasFocus); + } + //--------------------------------------------------------------------------- + + //////////////// Activity API 5 ///////////// +//@ANDROID-5 + @Override + public void onAttachedToWindow() + { + if (!QtApplication.invokeDelegate().invoked) + super.onAttachedToWindow(); + } + public void super_onAttachedToWindow() + { + super.onAttachedToWindow(); + } + //--------------------------------------------------------------------------- + + @Override + public void onBackPressed() + { + if (!QtApplication.invokeDelegate().invoked) + super.onBackPressed(); + } + public void super_onBackPressed() + { + super.onBackPressed(); + } + + //--------------------------------------------------------------------------- + + @Override + public void onDetachedFromWindow() + { + if (!QtApplication.invokeDelegate().invoked) + super.onDetachedFromWindow(); + } + public void super_onDetachedFromWindow() + { + super.onDetachedFromWindow(); + } + //--------------------------------------------------------------------------- + + @Override + public boolean onKeyLongPress(int keyCode, KeyEvent event) + { + if (QtApplication.m_delegateObject != null && QtApplication.onKeyLongPress != null) + return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onKeyLongPress, keyCode, event); + else + return super.onKeyLongPress(keyCode, event); + } + public boolean super_onKeyLongPress(int keyCode, KeyEvent event) + { + return super.onKeyLongPress(keyCode, event); + } + //--------------------------------------------------------------------------- +//@ANDROID-5 + +//////////////// Activity API 8 ///////////// +//@ANDROID-8 +@Override + protected Dialog onCreateDialog(int id, Bundle args) + { + QtApplication.InvokeResult res = QtApplication.invokeDelegate(id, args); + if (res.invoked) + return (Dialog)res.methodReturns; + else + return super.onCreateDialog(id, args); + } + public Dialog super_onCreateDialog(int id, Bundle args) + { + return super.onCreateDialog(id, args); + } + //--------------------------------------------------------------------------- + + @Override + protected void onPrepareDialog(int id, Dialog dialog, Bundle args) + { + if (!QtApplication.invokeDelegate(id, dialog, args).invoked) + super.onPrepareDialog(id, dialog, args); + } + public void super_onPrepareDialog(int id, Dialog dialog, Bundle args) + { + super.onPrepareDialog(id, dialog, args); + } + //--------------------------------------------------------------------------- +//@ANDROID-8 + //////////////// Activity API 11 ///////////// + +//@ANDROID-11 + @Override + public boolean dispatchKeyShortcutEvent(KeyEvent event) + { + if (QtApplication.m_delegateObject != null && QtApplication.dispatchKeyShortcutEvent != null) + return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.dispatchKeyShortcutEvent, event); + else + return super.dispatchKeyShortcutEvent(event); + } + public boolean super_dispatchKeyShortcutEvent(KeyEvent event) + { + return super.dispatchKeyShortcutEvent(event); + } + //--------------------------------------------------------------------------- + + @Override + public void onActionModeFinished(ActionMode mode) + { + if (!QtApplication.invokeDelegate(mode).invoked) + super.onActionModeFinished(mode); + } + public void super_onActionModeFinished(ActionMode mode) + { + super.onActionModeFinished(mode); + } + //--------------------------------------------------------------------------- + + @Override + public void onActionModeStarted(ActionMode mode) + { + if (!QtApplication.invokeDelegate(mode).invoked) + super.onActionModeStarted(mode); + } + public void super_onActionModeStarted(ActionMode mode) + { + super.onActionModeStarted(mode); + } + //--------------------------------------------------------------------------- + + @Override + public void onAttachFragment(Fragment fragment) + { + if (!QtApplication.invokeDelegate(fragment).invoked) + super.onAttachFragment(fragment); + } + public void super_onAttachFragment(Fragment fragment) + { + super.onAttachFragment(fragment); + } + //--------------------------------------------------------------------------- + + @Override + public View onCreateView(View parent, String name, Context context, AttributeSet attrs) + { + QtApplication.InvokeResult res = QtApplication.invokeDelegate(parent, name, context, attrs); + if (res.invoked) + return (View)res.methodReturns; + else + return super.onCreateView(parent, name, context, attrs); + } + public View super_onCreateView(View parent, String name, Context context, + AttributeSet attrs) { + return super.onCreateView(parent, name, context, attrs); + } + //--------------------------------------------------------------------------- + + @Override + public boolean onKeyShortcut(int keyCode, KeyEvent event) + { + if (QtApplication.m_delegateObject != null && QtApplication.onKeyShortcut != null) + return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onKeyShortcut, keyCode,event); + else + return super.onKeyShortcut(keyCode, event); + } + public boolean super_onKeyShortcut(int keyCode, KeyEvent event) + { + return super.onKeyShortcut(keyCode, event); + } + //--------------------------------------------------------------------------- + + @Override + public ActionMode onWindowStartingActionMode(Callback callback) + { + QtApplication.InvokeResult res = QtApplication.invokeDelegate(callback); + if (res.invoked) + return (ActionMode)res.methodReturns; + else + return super.onWindowStartingActionMode(callback); + } + public ActionMode super_onWindowStartingActionMode(Callback callback) + { + return super.onWindowStartingActionMode(callback); + } + //--------------------------------------------------------------------------- +//@ANDROID-11 + //////////////// Activity API 12 ///////////// + +//@ANDROID-12 + @Override + public boolean dispatchGenericMotionEvent(MotionEvent ev) + { + if (QtApplication.m_delegateObject != null && QtApplication.dispatchGenericMotionEvent != null) + return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.dispatchGenericMotionEvent, ev); + else + return super.dispatchGenericMotionEvent(ev); + } + public boolean super_dispatchGenericMotionEvent(MotionEvent event) + { + return super.dispatchGenericMotionEvent(event); + } + //--------------------------------------------------------------------------- + + @Override + public boolean onGenericMotionEvent(MotionEvent event) + { + if (QtApplication.m_delegateObject != null && QtApplication.onGenericMotionEvent != null) + return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onGenericMotionEvent, event); + else + return super.onGenericMotionEvent(event); + } + public boolean super_onGenericMotionEvent(MotionEvent event) + { + return super.onGenericMotionEvent(event); + } + //--------------------------------------------------------------------------- +//@ANDROID-12 + +} diff --git a/QtDemo/android/src/org/qtproject/qt5/android/bindings/QtApplication.java b/QtDemo/android/src/org/qtproject/qt5/android/bindings/QtApplication.java new file mode 100644 index 0000000..4de1c83 --- /dev/null +++ b/QtDemo/android/src/org/qtproject/qt5/android/bindings/QtApplication.java @@ -0,0 +1,149 @@ +/* + Copyright (c) 2012-2013, BogDan Vatra <bogdan@kde.org> + Contact: http://www.qt-project.org/legal + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. 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. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +*/ + +package org.qtproject.qt5.android.bindings; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; + +import android.app.Application; + +public class QtApplication extends Application +{ + public final static String QtTAG = "Qt"; + public static Object m_delegateObject = null; + public static HashMap<String, ArrayList<Method>> m_delegateMethods= new HashMap<String, ArrayList<Method>>(); + public static Method dispatchKeyEvent = null; + public static Method dispatchPopulateAccessibilityEvent = null; + public static Method dispatchTouchEvent = null; + public static Method dispatchTrackballEvent = null; + public static Method onKeyDown = null; + public static Method onKeyMultiple = null; + public static Method onKeyUp = null; + public static Method onTouchEvent = null; + public static Method onTrackballEvent = null; + public static Method onActivityResult = null; + public static Method onCreate = null; + public static Method onKeyLongPress = null; + public static Method dispatchKeyShortcutEvent = null; + public static Method onKeyShortcut = null; + public static Method dispatchGenericMotionEvent = null; + public static Method onGenericMotionEvent = null; + + public static void setQtActivityDelegate(Object listener) + { + QtApplication.m_delegateObject = listener; + + ArrayList<Method> delegateMethods = new ArrayList<Method>(); + for (Method m : listener.getClass().getMethods()) { + if (m.getDeclaringClass().getName().startsWith("org.qtproject.qt5.android")) + delegateMethods.add(m); + } + + ArrayList<Field> applicationFields = new ArrayList<Field>(); + for (Field f : QtApplication.class.getFields()) { + if (f.getDeclaringClass().getName().equals(QtApplication.class.getName())) + applicationFields.add(f); + } + + for (Method delegateMethod : delegateMethods) { + try { + QtActivity.class.getDeclaredMethod(delegateMethod.getName(), delegateMethod.getParameterTypes()); + if (QtApplication.m_delegateMethods.containsKey(delegateMethod.getName())) { + QtApplication.m_delegateMethods.get(delegateMethod.getName()).add(delegateMethod); + } else { + ArrayList<Method> delegateSet = new ArrayList<Method>(); + delegateSet.add(delegateMethod); + QtApplication.m_delegateMethods.put(delegateMethod.getName(), delegateSet); + } + for (Field applicationField:applicationFields) { + if (applicationField.getName().equals(delegateMethod.getName())) { + try { + applicationField.set(null, delegateMethod); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } catch (Exception e) { + } + } + } + + @Override + public void onTerminate() { + if (m_delegateObject != null && m_delegateMethods.containsKey("onTerminate")) + invokeDelegateMethod(m_delegateMethods.get("onTerminate").get(0)); + super.onTerminate(); + } + + public static class InvokeResult + { + public boolean invoked = false; + public Object methodReturns = null; + } + + private static int stackDeep=-1; + public static InvokeResult invokeDelegate(Object... args) + { + InvokeResult result = new InvokeResult(); + if (m_delegateObject == null) + return result; + StackTraceElement[] elements = Thread.currentThread().getStackTrace(); + if (-1 == stackDeep) { + String activityClassName = QtActivity.class.getCanonicalName(); + for (int it=0;it<elements.length;it++) + if (elements[it].getClassName().equals(activityClassName)) { + stackDeep = it; + break; + } + } + final String methodName=elements[stackDeep].getMethodName(); + if (-1 == stackDeep || !m_delegateMethods.containsKey(methodName)) + return result; + + for (Method m : m_delegateMethods.get(methodName)) { + if (m.getParameterTypes().length == args.length) { + result.methodReturns = invokeDelegateMethod(m, args); + result.invoked = true; + return result; + } + } + return result; + } + + public static Object invokeDelegateMethod(Method m, Object... args) + { + try { + return m.invoke(m_delegateObject, args); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/QtDemo/qml/QtDemo/DialogButton.qml b/QtDemo/qml/QtDemo/DialogButton.qml new file mode 100644 index 0000000..b201786 --- /dev/null +++ b/QtDemo/qml/QtDemo/DialogButton.qml @@ -0,0 +1,26 @@ +import QtQuick 2.0 + +Rectangle { + id: button + radius: 10 + height: 0.3 * dialog.height + width: dialog.width * 0.5 - dialog.dialogMargin + color: "transparent" + + property string buttonText + signal clicked() + + Text { + anchors.centerIn: parent + text: button.buttonText + font.pixelSize: 0.4 * button.height + color: "#ffffff" + } + + MouseArea { + anchors.fill: parent + onPressed: parent.color = Qt.rgba(0.2, 0.2, 0.2, 0.4) + onReleased: parent.color = "transparent" + onClicked: button.clicked() + } +} diff --git a/QtDemo/qml/QtDemo/QuitDialog.qml b/QtDemo/qml/QtDemo/QuitDialog.qml new file mode 100644 index 0000000..7c460b3 --- /dev/null +++ b/QtDemo/qml/QtDemo/QuitDialog.qml @@ -0,0 +1,67 @@ +import QtQuick 2.0 + +Rectangle { + id: root + anchors.fill: parent + color: Qt.rgba(0.0, 0.0, 0.0, 0.7) + + signal yes() + signal no() + + MouseArea { + anchors.fill: parent + } + + Rectangle { + id: dialog + anchors.centerIn: parent + width: parent.width * 0.4 + height: parent.height * 0.3 + property double dialogMargin: height * 0.05 + + gradient: Gradient { + GradientStop { position: 0.0; color: "#222222" } + GradientStop { position: 0.3; color: "#000000" } + GradientStop { position: 1.0; color: "#111111" } + } + radius: 10 + border { color: "#999999"; width: 1 } + + Rectangle { + id: content + anchors { left: parent.left; right: parent.right; top: parent.top } + height: dialog.height * 0.6 + color: "transparent" + + Text { + anchors.centerIn: parent + verticalAlignment: Text.AlignVCenter + text: qsTr("Are you sure you want to quit?") + color: "#ffffff" + font.pixelSize: 0.2 *content.height + } + } + + Rectangle { + id: line + anchors { left: parent.left; right: parent.right; top: content.bottom } + anchors.leftMargin: dialog.dialogMargin + anchors.rightMargin: dialog.dialogMargin + height: 1 + color: "#777777" + } + + DialogButton { + anchors { bottom: dialog.bottom; left:dialog.left; bottomMargin: dialog.dialogMargin; leftMargin: dialog.dialogMargin } + buttonText: "Yes" + onClicked: root.yes() + } + DialogButton { + anchors { bottom: dialog.bottom; right:dialog.right; bottomMargin: dialog.dialogMargin; rightMargin: dialog.dialogMargin } + buttonText: "No" + onClicked: root.no() + } + + } + +} diff --git a/QtDemo/qml/QtDemo/Slide.qml b/QtDemo/qml/QtDemo/Slide.qml index c3c9e04..f41999f 100644 --- a/QtDemo/qml/QtDemo/Slide.qml +++ b/QtDemo/qml/QtDemo/Slide.qml @@ -1,61 +1,59 @@ import QtQuick 2.0 -Rectangle { +Item { id: slide objectName: "slide" - width: 867 - height: 520 - scale: 2 - - color: "transparent" - border {color: app.showDebugRects ? borderColor : "transparent"; width:3} - property int uid: 0 - property color borderColor: "black" property string url: "" property int device: 0 property string imageSource: "" property bool loaded: false property bool loading: false property real targetScale: 1 - property real targetAngle: device <= 2 ? -90 : 0 - + property real targetAngle: 0 + property bool animationRunning: navigationAnimation.running || zoomAnimation.running property int demoWidth: 603 property int demoHeight: 378 - property int maskVerticalOffset: 51 property int maskHorizontalOffset: 1 - property string name: "" function targetWidth() { - return device <= 2 ? demoHeight*scale: demoWidth*scale; + return device <= 1 ? demoHeight*scale: demoWidth*scale; } function targetHeight() { - return device <= 2 ? demoWidth*scale : demoHeight*scale; + return device <= 1 ? demoWidth*scale : demoHeight*scale; } - Rectangle{ - id: demoContainer + Rectangle { + id: demoBackground anchors.centerIn: parent - width: demoWidth - height: demoHeight - color: "#111111" - clip: true + width: demoContainer.width * 1.03 + height: demoContainer.height * 1.03 + color: "black" z: (slide.loading || slide.loaded) ? 1:-1 - Text { - id: splashScreenText - color: 'white' - font.pixelSize: parent.height *.1 - text: slide.name + Rectangle{ + id: demoContainer anchors.centerIn: parent - smooth: true - visible: false + width: demoWidth + height: demoHeight + color: "#111111" + clip: true + + Text { + id: splashScreenText + color: 'white' + font.pixelSize: parent.height *.1 + text: slide.name + anchors.centerIn: parent + smooth: true + visible: false + } } } @@ -67,7 +65,6 @@ Rectangle { sourceItem: demoContainer live: (slide.loading || slide.loaded) visible: true - smooth: false hideSource: true clip: true z: (slide.loading || slide.loaded) ? 1:-1 @@ -78,7 +75,8 @@ Rectangle { anchors.centerIn: parent anchors.verticalCenterOffset: maskVerticalOffset anchors.horizontalCenterOffset: maskHorizontalOffset - smooth: true + smooth: !animationRunning + antialiasing: !animationRunning source: slide.imageSource width: slide.width height: slide.height @@ -165,6 +163,8 @@ Rectangle { } function releaseDemo(){ + app.forceActiveFocus(); + if (!slide.loaded) return; diff --git a/QtDemo/qml/QtDemo/WorldCanvas.qml b/QtDemo/qml/QtDemo/WorldCanvas.qml index 9703eab..443bf57 100644 --- a/QtDemo/qml/QtDemo/WorldCanvas.qml +++ b/QtDemo/qml/QtDemo/WorldCanvas.qml @@ -28,7 +28,8 @@ Item{ rotationOriginY = 0; angle = 0; zoomInTarget = app.homeScaleFactor; - + app.navigationState = 0 //home + app.forceActiveFocus() navigationPanel.rotateButtons(0); zoomAnimation.restart(); } @@ -43,6 +44,7 @@ Item{ rotationOriginY = target.y; angle = -target.angle + target.targetAngle; zoomInTarget = target.targetScale; + app.navigationState = 1 //slide navigationPanel.rotateButtons(target.targetAngle); } } diff --git a/QtDemo/qml/QtDemo/WorldMouseArea.qml b/QtDemo/qml/QtDemo/WorldMouseArea.qml index 135400d..f7873b7 100644 --- a/QtDemo/qml/QtDemo/WorldMouseArea.qml +++ b/QtDemo/qml/QtDemo/WorldMouseArea.qml @@ -55,6 +55,7 @@ MouseArea{ panning = true; canvas.xOffset += dx; canvas.yOffset += dy; + app.navigationState = 2 //dirty } } diff --git a/QtDemo/qml/QtDemo/WorldPinchArea.qml b/QtDemo/qml/QtDemo/WorldPinchArea.qml index 50fad44..02bd3e5 100644 --- a/QtDemo/qml/QtDemo/WorldPinchArea.qml +++ b/QtDemo/qml/QtDemo/WorldPinchArea.qml @@ -8,7 +8,7 @@ PinchArea{ pinch.maximumScale: app.maxScaleFactor pinch.maximumRotation: 360 pinch.minimumRotation: -360 - enabled: !zoomAnimation.running + enabled: !zoomAnimation.running && !navigationAnimation.running property bool pinching: false diff --git a/QtDemo/qml/QtDemo/demos/boot/BootScreen.qml b/QtDemo/qml/QtDemo/demos/boot/BootScreen.qml index 7e665c2..e87b5aa 100644 --- a/QtDemo/qml/QtDemo/demos/boot/BootScreen.qml +++ b/QtDemo/qml/QtDemo/demos/boot/BootScreen.qml @@ -37,6 +37,4 @@ Rectangle { } //fadeOutAnimation.restart() } - - Component.onDestruction: print ("BootScreen released!") } diff --git a/QtDemo/qml/QtDemo/demos/calqlatr/Calqlatr.qml b/QtDemo/qml/QtDemo/demos/calqlatr/Calqlatr.qml index 7a0eb4c..5f6443e 100644 --- a/QtDemo/qml/QtDemo/demos/calqlatr/Calqlatr.qml +++ b/QtDemo/qml/QtDemo/demos/calqlatr/Calqlatr.qml @@ -46,11 +46,9 @@ import "content/calculator.js" as CalcEngine Rectangle { id: window anchors.fill: parent - focus: true + //focus: true color: "#272822" - //onWidthChanged: controller.reload() - function operatorPressed(operator) { CalcEngine.operatorPressed(operator) } function digitPressed(digit) { CalcEngine.digitPressed(digit) } diff --git a/QtDemo/qml/QtDemo/demos/rssnews/content/CategoryDelegate.qml b/QtDemo/qml/QtDemo/demos/rssnews/content/CategoryDelegate.qml index c46d423..2916d1b 100644 --- a/QtDemo/qml/QtDemo/demos/rssnews/content/CategoryDelegate.qml +++ b/QtDemo/qml/QtDemo/demos/rssnews/content/CategoryDelegate.qml @@ -43,15 +43,17 @@ import QtQuick 2.0 Item { id: delegate - - width: delegate.ListView.view.width; height: 60 + property double margin: delegate.height * 0.2; + width: delegate.ListView.view.width; + height: 60 Text { text: name color: delegate.ListView.isCurrentItem ? "white" : "black" - font { family: "Helvetica"; pixelSize: 18; bold: true } + font { family: "Helvetica"; pixelSize: delegate.height * 0.25; bold: true } anchors { - left: parent.left; leftMargin: 15 + left: parent.left; + leftMargin: margin verticalCenter: parent.verticalCenter } } @@ -59,7 +61,7 @@ Item { BusyIndicator { scale: 0.6 on: delegate.ListView.isCurrentItem && window.loading - anchors { right: parent.right; rightMargin: 10; verticalCenter: parent.verticalCenter } + anchors { right: parent.right; rightMargin: margin; verticalCenter: parent.verticalCenter } } Rectangle { diff --git a/QtDemo/qml/QtDemo/demos/rssnews/content/NewsDelegate.qml b/QtDemo/qml/QtDemo/demos/rssnews/content/NewsDelegate.qml index ec39510..3274af8 100644 --- a/QtDemo/qml/QtDemo/demos/rssnews/content/NewsDelegate.qml +++ b/QtDemo/qml/QtDemo/demos/rssnews/content/NewsDelegate.qml @@ -43,13 +43,15 @@ import QtQuick 2.0 Item { id: delegate - height: column.height + 40 + height: column.height + 2*margin width: delegate.ListView.view.width + property double margin: width * 0.03 + Column { id: column - x: 20; y: 20 - width: parent.width - 40 + x: margin; y: margin + width: parent.width - 2*margin Text { id: titleText diff --git a/QtDemo/qml/QtDemo/demos/rssnews/rssnews.qml b/QtDemo/qml/QtDemo/demos/rssnews/rssnews.qml index b92d030..5eae0a0 100644 --- a/QtDemo/qml/QtDemo/demos/rssnews/rssnews.qml +++ b/QtDemo/qml/QtDemo/demos/rssnews/rssnews.qml @@ -46,6 +46,12 @@ import "content" Rectangle { id: window anchors.fill: parent + gradient: Gradient { + GradientStop { position: 0.0; color: "#eeeeee" } + GradientStop { position: 0.1; color: "#ffffff" } + GradientStop { position: 0.9; color: "#ffffff" } + GradientStop { position: 1.0; color: "#bbbbbb" } + } property int listWidth: window.width*0.35 property string currentFeed: "feeds.bbci.co.uk/news/rss.xml" @@ -65,11 +71,11 @@ Rectangle { Row { Rectangle { + id: categoryContent width: window.listWidth; height: window.height color: "#efefef" ListView { - focus: true id: categories anchors.fill: parent model: rssFeeds diff --git a/QtDemo/qml/QtDemo/demos/shaders/Content.qml b/QtDemo/qml/QtDemo/demos/shaders/Content.qml index 82cc904..c623906 100755 --- a/QtDemo/qml/QtDemo/demos/shaders/Content.qml +++ b/QtDemo/qml/QtDemo/demos/shaders/Content.qml @@ -91,7 +91,6 @@ Rectangle { } function init() { - print("Content init()") theSource.sourceItem = logoContainer root.effectSource = "Effects/EffectPassThrough.qml" effectLoader.source = root.effectSource diff --git a/QtDemo/qml/QtDemo/demos/shaders/EffectSelectionPanel.qml b/QtDemo/qml/QtDemo/demos/shaders/EffectSelectionPanel.qml index 9cfd59a..6caa0c2 100755 --- a/QtDemo/qml/QtDemo/demos/shaders/EffectSelectionPanel.qml +++ b/QtDemo/qml/QtDemo/demos/shaders/EffectSelectionPanel.qml @@ -127,7 +127,7 @@ Rectangle { clip: true anchors.margins: root.width * 0.05 model: sources - focus: root.visible && root.opacity + //focus: root.visible && root.opacity currentIndex: 0 diff --git a/QtDemo/qml/QtDemo/demos/shaders/main.qml b/QtDemo/qml/QtDemo/demos/shaders/main.qml index 24fe018..2beba2f 100755 --- a/QtDemo/qml/QtDemo/demos/shaders/main.qml +++ b/QtDemo/qml/QtDemo/demos/shaders/main.qml @@ -43,7 +43,6 @@ import QtQuick 2.0 Rectangle { id: applicationWindow - focus: true anchors.fill:parent color: "black" diff --git a/QtDemo/qml/QtDemo/demos/tweetsearch/content/LineInput.qml b/QtDemo/qml/QtDemo/demos/tweetsearch/content/LineInput.qml index 43e5f23..6d5c215 100644 --- a/QtDemo/qml/QtDemo/demos/tweetsearch/content/LineInput.qml +++ b/QtDemo/qml/QtDemo/demos/tweetsearch/content/LineInput.qml @@ -84,14 +84,26 @@ FocusScope { onAccepted: wrapper.accepted() } - Image { - source: "resources/icon-search.png" + Rectangle { + id: searchRect anchors.right: parent.right - anchors.rightMargin: 12 + anchors.margins: parent.height * 0.1 anchors.verticalCenter: parent.verticalCenter - MouseArea { - anchors { fill: parent; margins: -10 } - onClicked: wrapper.accepted() + height: parent.height * 0.8 + width: height + color: "transparent" + radius: 4 + + Image { + source: "resources/icon-search.png" + anchors.fill: parent + anchors.margins: 5 + MouseArea { + anchors { fill: parent; margins: -10 } + onPressed: searchRect.color = "#ff9999" + onReleased: searchRect.color = "transparent" + onClicked: wrapper.accepted() + } } } } diff --git a/QtDemo/qml/QtDemo/demos/tweetsearch/content/TweetDelegate.qml b/QtDemo/qml/QtDemo/demos/tweetsearch/content/TweetDelegate.qml index 8cd2211..b96cd69 100644 --- a/QtDemo/qml/QtDemo/demos/tweetsearch/content/TweetDelegate.qml +++ b/QtDemo/qml/QtDemo/demos/tweetsearch/content/TweetDelegate.qml @@ -74,7 +74,7 @@ Item { front: Rectangle { width: container.ListView.view ? container.ListView.view.width : 0 - height: Math.max(72, tweet.y + tweet.height + 10) + height: parent.height; //Math.max(72, tweet.y + tweet.height + 10) color: "#2699bf" Rectangle { color: "#33ccff"; width: parent.width; height: 1 } diff --git a/QtDemo/qml/QtDemo/engine.js b/QtDemo/qml/QtDemo/engine.js index e36bace..b9c8285 100644 --- a/QtDemo/qml/QtDemo/engine.js +++ b/QtDemo/qml/QtDemo/engine.js @@ -1,39 +1,39 @@ -var positions = [{x:-800, y:-800, angle: 0, borderColor: "green", url: "demos/calqlatr/Calqlatr.qml", device: 0, name: "Calqlatr"}, - {x:700, y:-900, angle: 0, borderColor: "blue", url: "demos/samegame/samegame.qml", device: 1, name: "SameGame"}, - {x:1400, y:-500, angle:5, borderColor: "grey", url: "demos/tweetsearch/tweetsearch.qml", device: 2, name: "TweetSearch"}, - {x:-1800, y:-100, angle: -4, borderColor: "orange", url: "demos/rssnews/rssnews.qml", device: 3, name: "Rss Reader"}, - {x:1700, y:200, angle: -3, borderColor: "orange", url: "demos/boot/BootScreen.qml", device: 4, name: "Particles"}, - {x:-1700, y: 800, angle: 5, borderColor: "red", url: "demos/photosurface/photosurface.qml", device: 5, name: "Photo surface"}, - {x:1600, y:1100, angle: -4, borderColor: "red", url: "demos/particledemo/particledemo.qml", device: 6, name: "Multitouch"}, - {x:-200, y:1600, angle: 3, borderColor: "orange", url: "demos/slidepuzzle/slidepuzzle.qml", device: 7, name: "Slide puzzle"}, - {x:3000, y:2000, angle: 3, borderColor: "orange", url: "demos/canvasclock/canvasClock.qml", device: 7, name: "Canvas clock"}, - {x:700, y:1900, angle: -3, borderColor: "orange", url: "demos/shaders/main.qml", device: 7, name: "Shaders"}] - -var imageSources = ["phone1","phone2", "phone3","tablet1", "medical_device", "laptop1", "laptop2", "tv"] +var positions = [{x:-100, y:-850, angle: 0, url: "demos/calqlatr/Calqlatr.qml", device: 0, name: "Calqlatr"}, + {x:700, y:-900, angle: 0, url: "demos/samegame/samegame.qml", device: 1, name: "SameGame"}, + {x:1400, y:-500, angle:0, url: "demos/tweetsearch/tweetsearch.qml", device: 2, name: "TweetSearch"}, + {x:-1200, y:-600, angle: 0, url: "demos/canvasclock/canvasClock.qml", device: 4, name: "Canvas clock"}, + {x:-1900, y:0, angle: 0, url: "demos/rssnews/rssnews.qml", device: 3, name: "Rss Reader"}, + {x:1700, y:200, angle: 0, url: "demos/boot/BootScreen.qml", device: 4, name: "Particles"}, + {x:-2000, y:800, angle: 0, url: "demos/slidepuzzle/slidepuzzle.qml", device: 5, name: "Slide puzzle"}, + {x:1600, y:1100, angle: 0, url: "demos/particledemo/particledemo.qml", device: 6, name: "Multitouch"}, + {x:1100, y:2000, angle: 0, url: "demos/photosurface/photosurface.qml", device: 7, name: "Photo surface"}, + {x:-1100, y:1700, angle: 0, url: "demos/shaders/main.qml", device: 7, name: "Shaders"}] + +var imageSources = ["phone1.svg","phone2.svg", "phone3.svg","tablet1.svg", "medical_device.svg", "laptop1.svg", "laptop2.svg", "tv.svg"] var widths = [358, 361, 366, 758, 600, 888, 888, 708] var heights = [723, 707, 721, 565, 489, 513, 513, 565] -var scales = [0.6, 0.6, 0.6, 0.8, 1.4, 1.4, 1.5, 2] -var demoWidths = [324, 324, 324, 644, 484, 644, 644, 644] -var demoHeights = [484, 484, 484, 404, 324, 404, 404, 404] +var scales = [0.6, 0.6, 0.6, 1.0, 1.2, 1.2, 1.2, 1.5] +var demoWidths = [322, 322, 322, 642, 482, 642, 642, 642] +var demoHeights = [482, 482, 482, 402, 322, 402, 402, 402] var maskHorizontalOffsets = [1, 1, 1, 1, 1, 1, 1, 1] -var maskVerticalOffsets = [27, 33, 16, 25, 46, 34, 34, 50] -var targetAngles = [-90, -90, -90, 0, 0, 0, 0, 0] +var maskVerticalOffsets = [26, 32, 15, 24, 45, 33, 33, 49] +var targetAngles = [-90, -90, 0, 0, 0, 0, 0, 0] var currentDemoId = -1 var objects = [] function initSlides(){ positions.forEach(function(pos){ - createNew(pos.x,pos.y,pos.angle, pos.borderColor, pos.url, pos.device, pos.name) + createNew(pos.x,pos.y,pos.angle, pos.url, pos.device, pos.name) }) } -function createNew(x,y,angle,borderColor,url,device,name){ +function createNew(x,y,angle,url,device,name){ var component = Qt.createComponent("Slide.qml") if (component.status === Component.Ready){ var object=component.createObject(canvas) object.device = device - object.imageSource = "images/" + imageSources[device] + ".svg" + object.imageSource = "images/" + imageSources[device] object.width = widths[device] object.height = heights[device] object.scale = scales[device] @@ -41,9 +41,9 @@ function createNew(x,y,angle,borderColor,url,device,name){ object.demoHeight = demoHeights[device] object.maskVerticalOffset = maskVerticalOffsets[device] object.maskHorizontalOffset = maskHorizontalOffsets[device] + object.targetAngle = targetAngles[device] object.rotation = angle object.uid = objects.length - object.borderColor = borderColor object.name = name object.x = x-object.width/2 object.y = y-object.height/2 @@ -52,7 +52,6 @@ function createNew(x,y,angle,borderColor,url,device,name){ if (url){ object.url = url; } - print ("object.url: "+object.url) objects.push(object) } } diff --git a/QtDemo/qml/QtDemo/main.qml b/QtDemo/qml/QtDemo/main.qml index 09adcd9..967dc48 100644 --- a/QtDemo/qml/QtDemo/main.qml +++ b/QtDemo/qml/QtDemo/main.qml @@ -5,6 +5,7 @@ import "style.js" as Style Rectangle{ id: app clip: true + focus: true color: "white" property real homeScaleFactor: .2 property int homeCenterX: 0 @@ -13,6 +14,7 @@ Rectangle{ property real maxScaleFactor: 1 property real tapLimitX : 2 property real tapLimitY : 1 + property int navigationState: 0 //home, slide, dirty function calculateScales(){ if (app.width > 0 && app.height > 0){ @@ -25,7 +27,7 @@ Rectangle{ app.homeCenterY = bbox.centerY; app.minScaleFactor = app.homeScaleFactor / 10; app.maxScaleFactor = app.homeScaleFactor * 20; - Engine.updateObjectScales(app.width*0.8, app.width*0.8); //app.width, app.height); + Engine.updateObjectScales(app.width*0.9, app.height*0.9); //app.width, app.height); tapLimitX = Math.max(1,app.width * 0.02); tapLimitY = Math.max(1,app.height * 0.02); @@ -75,6 +77,13 @@ Rectangle{ spacing: app.height * 0.05 } + QuitDialog { + id: quitDialog + visible: false + + onYes: Qt.quit() + onNo: visible = false + } NumberAnimation { id: zoomAnimation @@ -116,7 +125,7 @@ Rectangle{ onRunningChanged: { if (!running) { - if (canvas.zoomInTarget !== app.homeScaleFactor) + if (navigationState === 1) Engine.loadCurrentDemo(); else Engine.releaseDemos(); @@ -124,10 +133,21 @@ Rectangle{ } } + Keys.onPressed: { + // Handle back-key + if (event.key === Qt.Key_MediaPrevious) { + if (app.navigationState !== 0) { + event.accepted = true; + canvas.goHome(); + } + else { + quitDialog.visible = true + } + } + } + Component.onCompleted: { - print("START TO INITIALIZE SLIDES") Engine.initSlides() - print("SLIDES READY") cloud1.start(); cloud2.start(); cloud3.start(); diff --git a/QtDemo/shaderfilereader.cpp b/QtDemo/shaderfilereader.cpp index 2b03c4b..2a4677b 100644 --- a/QtDemo/shaderfilereader.cpp +++ b/QtDemo/shaderfilereader.cpp @@ -32,6 +32,7 @@ QString ShaderFileReader::readFile(const QString &fileName) if (file.open(QIODevice::ReadOnly)) { QTextStream stream(&file); content = stream.readAll(); + file.close(); } return content; } |