All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.qt.QtUtilities Maven / Gradle / Ivy

There is a newer version: 6.8.0
Show newest version
/****************************************************************************
**
** Copyright (C) 2009-2024 Dr. Peter Droste, Omix Visualization GmbH & Co. KG. All rights reserved.
**
** This file is part of Qt Jambi.
**
** $BEGIN_LICENSE$
** GNU Lesser General Public License Usage
** 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.
** 
** 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.
** $END_LICENSE$
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/

package io.qt;

import java.io.File;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import io.qt.InternalAccess.CallerContext;
import io.qt.core.QCoreApplication;
import io.qt.core.QMetaObject;
import io.qt.core.QVersionNumber;

/**
 * This class contains static members that gives information and performs QtJambi related tasks.
*/
public final class QtUtilities {
	
	private static final Map initializedPackages = new HashMap<>(Collections.singletonMap("io.qt.internal", Boolean.TRUE));
	static {
		initializePackage("io.qt.internal");
	}
	
	private QtUtilities() {}
	
	/**
	 * Enum for requirement.
	 * @see QtUtilities#loadQtLibrary(String, LibraryRequirementMode, String...)
	 * @see QtUtilities#loadUtilityLibrary(String, LibraryRequirementMode, String...)
	 */
	public enum LibraryRequirementMode{
		/**
		 * Application cannot run without specified library
		 */
        Mandatory,
        /**
         * Specified library is optional
         */
        Optional,
        /**
         * In case of bundled native libraries specified library
         * has to be extracted but not loaded.
         */
        ProvideOnly
    };
	
    public static boolean isAvailableQtLibrary(@NonNull String library) {
        return Utility.isAvailableQtLibrary(Utility.callerClassProvider().get(), library);
    }
    
    public static boolean isAvailableUtilityLibrary(@NonNull String library) {
    	return isAvailableUtilityLibrary(library, null);
    }
    
    public static boolean isAvailableUtilityLibrary(@NonNull String library, @NonNull String versionString) {
        return Utility.isAvailableLibrary(library, versionString);
    }
    
    public static void loadQtLibrary(@NonNull String library) {
    	Utility.loadQtLibrary(Utility.callerClassProvider().get(), library, LibraryRequirementMode.Mandatory);
    }
    
    public static void loadQtLibrary(@NonNull String library, @NonNull LibraryRequirementMode mode, @NonNull String @NonNull...platforms) {
    	Utility.loadQtLibrary(Utility.callerClassProvider().get(), library, mode, platforms);
    }

    public static void loadUtilityLibrary(@NonNull String library) {
    	Utility.loadUtilityLibrary(library, null, LibraryRequirementMode.Mandatory);
    }
    
    public static void loadUtilityLibrary(@NonNull String library, @NonNull LibraryRequirementMode mode, @NonNull String @NonNull...platforms) {
    	Utility.loadUtilityLibrary(library, null, mode, platforms);
    }
    
    public static void loadUtilityLibrary(@NonNull String library, @NonNull String version) {
    	Utility.loadUtilityLibrary(library, version, LibraryRequirementMode.Mandatory);
    }
    
    public static void loadUtilityLibrary(@NonNull String library, @NonNull String version, @NonNull LibraryRequirementMode mode, @NonNull String @NonNull...platforms) {
    	Utility.loadUtilityLibrary(library, version, mode);
    }

    public static void loadQtJambiLibrary(@NonNull String library) {
    	Utility.loadQtJambiLibrary(Utility.callerClassProvider().get(), library);
    }
    
    public static void loadJambiLibrary(@NonNull String library) {
    	Utility.loadJambiLibrary(Utility.callerClassProvider().get(), library);
    }
    
    public static void loadLibrary(@NonNull String lib) {
    	Utility.loadLibrary(lib);
    }
    
    /**
     * Use a class (e.g. from third party library) as gadget.
     * @see io.qt.QtAsGadget
     * @see io.qt.core.QMetaObject#forType(Class)
     */
    public static void useAsGadget(@Nullable Class clazz) {
    	Utility.useAsGadget(clazz);
    }
    
    /**
     * Define a package (e.g. from third party library) to let all its classes considered to be gadgets.
     * @see io.qt.QtAsGadget
     * @see io.qt.core.QMetaObject#forType(Class)
     */
    public static void usePackageContentAsGadgets(@NonNull String _package) {
    	Utility.usePackageContentAsGadgets(_package);
    }

    public static @Nullable File jambiDeploymentDir() {
        return Utility.jambiDeploymentDir();
    }
    
    /**
     * @deprecated Use {@link #jambiDeploymentDir()} instead.
     * @return
     */
    @Deprecated(forRemoval=true)
    public static @Nullable File jambiTempDir() {
        return Utility.jambiDeploymentDir();
    }
    
    public static boolean initializePackage(@NonNull String packagePath){
    	Class callerClass = Utility.callerClassProvider().get();
    	if(callerClass==null)
    		callerClass = QtUtilities.class;
    	return initializePackage(callerClass.getClassLoader(), packagePath);
    }
    
    public static boolean initializePackage(java.lang.@StrictNonNull Package pkg){
    	Class callerClass = Utility.callerClassProvider().get();
    	if(callerClass==null)
    		callerClass = QtUtilities.class;
    	return initializePackage(callerClass.getClassLoader(), pkg);
    }
    
	private static boolean initializePackage(@Nullable ClassLoader classLoader, java.lang.@StrictNonNull Package pkg) {
		return pkg != null && initializePackage(classLoader, pkg.getName());
	}

	@NativeAccess
	public static boolean initializePackage(java.lang.@Nullable Class cls) {
		return cls != null && cls.getPackage() != null && initializePackage(cls.getClassLoader(), cls.getPackage().getName());
	}
	
	private static boolean initializePackage(@Nullable ClassLoader classLoader, @NonNull String packagePath) {
		synchronized (initializedPackages) {
			Boolean b = initializedPackages.get(packagePath);
			if (b != null) {
				return b;
			}
		}
		Class cls;
		try {
			try {
				cls = Class.forName(packagePath + ".QtJambi_LibraryUtilities");
			} catch (ClassNotFoundException e) {
				if(classLoader!=null && classLoader!=QtUtilities.class.getClassLoader()) {
					cls = Class.forName(packagePath + ".QtJambi_LibraryUtilities", true, classLoader);
				}else {
					throw e;
				}
			}
		} catch (NoClassDefFoundError t) {
			if (t.getCause() instanceof Error && t.getCause() != t)
				throw (Error) t.getCause();
			else if (t.getCause() instanceof RuntimeException)
				throw (RuntimeException) t.getCause();
			throw t;
		} catch (ExceptionInInitializerError t) {
			if (t.getCause() instanceof Error && t.getCause() != t)
				throw (Error) t.getCause();
			else if (t.getCause() instanceof RuntimeException)
				throw (RuntimeException) t.getCause();
			throw t;
		} catch (ClassNotFoundException e1) {
			synchronized (initializedPackages) {
				initializedPackages.put(packagePath, Boolean.FALSE);
			}
			return false;
		}
		try {
			Method initialize = cls.getDeclaredMethod("initialize");
			QtJambi_LibraryUtilities.internal.invokeMethod(initialize, null);
			synchronized (initializedPackages) {
				initializedPackages.put(packagePath, Boolean.TRUE);
			}
			return true;
		} catch (NoSuchMethodException | NoSuchMethodError t) {
			return true;
		} catch (NoClassDefFoundError t) {
			if (t.getCause() instanceof Error && t.getCause() != t)
				throw (Error) t.getCause();
			else if (t.getCause() instanceof RuntimeException)
				throw (RuntimeException) t.getCause();
			throw t;
		} catch (RuntimeException | Error t) {
			throw t;
		} catch (Throwable t) {
			java.util.logging.Logger.getLogger("io.qt.internal").log(java.util.logging.Level.WARNING,
					"initializePackage", t);
			throw new RuntimeException(t);
		}
	}
	
    public static QMetaObject.@NonNull DisposedSignal getSignalOnDispose(@NonNull QtObjectInterface object) {
    	return Utility.getSignalOnDispose(object, true);
    }
    
    public static void initializeNativeObject(@NonNull QtObjectInterface object) {
    	Class cls = QtJambi_LibraryUtilities.internal.getClass(object);
    	CallerContext callerInfo = QtJambi_LibraryUtilities.internal.callerContextProvider().get();
    	if (callerInfo.declaringClass == null || !callerInfo.declaringClass.isAssignableFrom(cls)
				|| !"".equals(callerInfo.methodName)) {
			throw new RuntimeException(new IllegalAccessException(
					"QtUtilities.initializeNativeObject(...) can only be called from inside the given object's constructor. Expected: "
							+ cls.getName() + "., found: "
							+ (callerInfo.declaringClass == null ? "null" : callerInfo.declaringClass.getName()) + "."
							+ callerInfo.methodName));
		}
    	Utility.initializeNativeObject(callerInfo.declaringClass, object, Collections.emptyMap());
    }
    
    public static void initializeNativeObject(@NonNull QtObjectInterface object, QtArgument.@NonNull Stream arguments) {
    	Class cls = QtJambi_LibraryUtilities.internal.getClass(object);
    	CallerContext callerInfo = QtJambi_LibraryUtilities.internal.callerContextProvider().get();
    	if (callerInfo.declaringClass == null || !callerInfo.declaringClass.isAssignableFrom(cls)
				|| !"".equals(callerInfo.methodName)) {
			throw new RuntimeException(new IllegalAccessException(
					"QtUtilities.initializeNativeObject(...) can only be called from inside the given object's constructor. Expected: "
							+ cls.getName() + "., found: "
							+ (callerInfo.declaringClass == null ? "null" : callerInfo.declaringClass.getName()) + "."
							+ callerInfo.methodName));
		}
    	Utility.initializeNativeObject(callerInfo.declaringClass, object, arguments.arguments());
    }
    
    /**
     * Equivalent to {@link java.util.function.IntSupplier} with {@code byte} result.
     */
    @FunctionalInterface
    public interface ByteSupplier{ byte getAsByte(); }
    
    /**
     * Equivalent to {@link java.util.function.IntSupplier} with {@code short} result.
     */
    @FunctionalInterface
    public interface ShortSupplier{ short getAsShort(); }
    
    /**
     * Equivalent to {@link java.util.function.DoubleSupplier} with {@code float} result.
     */
    @FunctionalInterface
    public interface FloatSupplier{ float getAsFloat(); }

    /**
     * Equivalent to {@link java.util.function.IntSupplier} with {@code char} result.
     */
    @FunctionalInterface
    public interface CharSupplier{ char getAsChar(); }
    
    /**
     * Equivalent to {@link java.util.function.Supplier}.
     */
    @FunctionalInterface
    public interface Supplier extends java.util.function.Supplier, java.io.Serializable { }
    
    /**
     * Equivalent to {@link java.util.function.Consumer} with three arguments.
     */
    @FunctionalInterface
    public static interface Consumer3{
        public void accept(A a, B b, C c);
    }
    
    /**
     * Equivalent to {@link java.util.function.Consumer} with four arguments.
     */
    @FunctionalInterface
    public static interface Consumer4{
        public void accept(A a, B b, C c, D d);
    }
    
    /**
     * Equivalent to {@link java.util.function.Consumer} with five arguments.
     */
    @FunctionalInterface
    public static interface Consumer5{
        public void accept(A a, B b, C c, D d, E e);
    }
    
    /**
     * Equivalent to {@link java.util.function.Consumer} with six arguments.
     */
    @FunctionalInterface
    public static interface Consumer6{
        public void accept(A a, B b, C c, D d, E e, F f);
    }
    
    /**
     * Equivalent to {@link java.util.function.Consumer} with seven arguments.
     */
    @FunctionalInterface
    public static interface Consumer7{
        public void accept(A a, B b, C c, D d, E e, F f, G g);
    }
    
    /**
     * Equivalent to {@link java.util.function.Consumer} with eight arguments.
     */
    @FunctionalInterface
    public static interface Consumer8{
        public void accept(A a, B b, C c, D d, E e, F f, G g, H h);
    }
    
    /**
     * Equivalent to {@link java.util.function.Consumer} with nine arguments.
     */
    @FunctionalInterface
    public static interface Consumer9{
        public void accept(A a, B b, C c, D d, E e, F f, G g, H h, I i);
    }
    
    /**
     * Equivalent to {@link java.util.function.Consumer} with ten arguments.
     */
    @FunctionalInterface
    public static interface Consumer10{
        public void accept(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j);
    }
    
    /**
     * This function sets the value of the environment variable named varName.
     * @see https://doc.qt.io/qt/qtglobal.html#qputenv
     * @param varName
     * @param value
     */
    public static native boolean putenv(@NonNull String varName, @NonNull String value);

    /**
     * This function deletes the variable varName from the environment.
     * @see https://doc.qt.io/qt/qtglobal.html#qunsetenv
     * @param varName
     */
    public static native boolean unsetenv(@NonNull String varName);
    
    /**
     * This function gets the value of the environment variable named varName.
     * @see https://doc.qt.io/qt/qtglobal.html#	qEnvironmentVariable
     * @param varName
     * @return value
     */
    public static native @Nullable String getenv(@NonNull String varName);
    
    /**
     * This method allows to reinstall the QtJambi event notify callback as the last callback.
     * If other libraries register their event notify callback to Qt,
     * it is necessary to make sure QtJambi's callback is called at last.
     * This method can only be called from inside the main thread and before calling {@link QCoreApplication#exec()}.
     */
    public static native boolean reinstallEventNotifyCallback();
    
    /**
     * Third-party libraries must not overwrite Java's installed signal handlers. 
     * Several of these signal handlers are crucial for JVM to work.
     * This method saves the installed signal handlers for later restoring by {@link #restoreUnixSignalHandlers()}.
     */
    public static native boolean saveUnixSignalHandlers();
    
    /**
     * Third-party libraries must not overwrite Java's installed signal handlers. 
     * Several of these signal handlers are crucial for JVM to work.
     * This method restores the signal handlers previously saved by {@link #saveUnixSignalHandlers()}.
     */
    public static native boolean restoreUnixSignalHandlers();
    
    /**
     * Return the version of QtJambi
     * @return qtjambi version
     */
    public static @NonNull QVersionNumber qtjambiVersion() {
    	return new QVersionNumber(Utility.majorVersion(), Utility.minorVersion(), Utility.qtjambiPatchVersion());
    }
    
    /**
     * Checks if the current thread is UI thread and throws QThreadAffinityException otherwise.
     * @throws QThreadAffinityException
     */
    public static native void uiThreadCheck() throws QThreadAffinityException;
    
    /**
     * Checks if the current thread is the given object's thread and throws QThreadAffinityException otherwise.
     * @throws QThreadAffinityException
     */
    public static void threadCheck(io.qt.core.@Nullable QObject object) throws QThreadAffinityException{
    	threadCheck(QtJambi_LibraryUtilities.internal.checkedNativeId(object));
    }
    
    private static native void threadCheck(long objectId) throws QThreadAffinityException;
    
    /**
     * Reduces the number of native-to-java conversions by pre-filtering the events according to the given event types.
     * @param eventFilter
     * @param eventType
     * @param eventTypes
     * @return selective event filter
     */
    public static io.qt.core.@NonNull QObject asSelectiveEventFilter(io.qt.core.@StrictNonNull QObject eventFilter, io.qt.core.QEvent.@NonNull Type eventType, io.qt.core.QEvent.@NonNull Type @NonNull... eventTypes) {
    	return asSelectiveEventFilter(QtJambi_LibraryUtilities.internal.checkedNativeId(Objects.requireNonNull(eventFilter)), eventType, eventTypes);
    }
    
    private static native io.qt.core.@NonNull QObject asSelectiveEventFilter(long objectId, io.qt.core.QEvent.@NonNull Type eventType, io.qt.core.QEvent.@NonNull Type @NonNull... eventTypes);
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy