forked from quickshell/quickshell
		
	feat: basic QtShell and ShellComponent types
This commit is contained in:
		
						commit
						23837e5195
					
				
					 9 changed files with 483 additions and 0 deletions
				
			
		
							
								
								
									
										82
									
								
								.clang-format
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								.clang-format
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,82 @@
 | 
			
		|||
AlignArrayOfStructures: None
 | 
			
		||||
AlignAfterOpenBracket: BlockIndent
 | 
			
		||||
AllowShortBlocksOnASingleLine: Always
 | 
			
		||||
AllowShortCaseLabelsOnASingleLine: true
 | 
			
		||||
AllowShortEnumsOnASingleLine: true
 | 
			
		||||
AllowShortFunctionsOnASingleLine: All
 | 
			
		||||
AllowShortIfStatementsOnASingleLine: AllIfsAndElse
 | 
			
		||||
AllowShortLambdasOnASingleLine: All
 | 
			
		||||
AllowShortLoopsOnASingleLine: true
 | 
			
		||||
BinPackArguments: false
 | 
			
		||||
BinPackParameters: false
 | 
			
		||||
Cpp11BracedListStyle: true
 | 
			
		||||
LambdaBodyIndentation: Signature
 | 
			
		||||
UseCRLF: false
 | 
			
		||||
UseTab: ForIndentation
 | 
			
		||||
SpacesInSquareBrackets: false
 | 
			
		||||
SpacesInParentheses: false
 | 
			
		||||
SpacesInCStyleCastParentheses: false
 | 
			
		||||
SpacesInAngles: Never
 | 
			
		||||
SpaceInEmptyParentheses: false
 | 
			
		||||
SpaceInEmptyBlock: false
 | 
			
		||||
SpaceBeforeSquareBrackets: false
 | 
			
		||||
SpaceBeforeRangeBasedForLoopColon: false
 | 
			
		||||
SpaceAfterCStyleCast: true
 | 
			
		||||
SpaceAfterLogicalNot: false
 | 
			
		||||
SpaceAfterTemplateKeyword: true
 | 
			
		||||
SpaceBeforeCaseColon: false
 | 
			
		||||
SpaceBeforeCpp11BracedList: true
 | 
			
		||||
SpaceBeforeCtorInitializerColon: false
 | 
			
		||||
SpaceBeforeInheritanceColon: false
 | 
			
		||||
SpaceBeforeParens: ControlStatementsExceptControlMacros
 | 
			
		||||
SortIncludes: CaseSensitive
 | 
			
		||||
PointerAlignment: Left
 | 
			
		||||
PackConstructorInitializers: NextLine
 | 
			
		||||
LineEnding: LF
 | 
			
		||||
InsertBraces: false
 | 
			
		||||
BreakConstructorInitializers: AfterColon
 | 
			
		||||
BreakBeforeBraces: Custom
 | 
			
		||||
BreakInheritanceList: AfterColon
 | 
			
		||||
AllowAllParametersOfDeclarationOnNextLine: false
 | 
			
		||||
AllowAllArgumentsOnNextLine: false
 | 
			
		||||
AlwaysBreakTemplateDeclarations: Yes
 | 
			
		||||
BraceWrapping:
 | 
			
		||||
  AfterClass: false
 | 
			
		||||
  AfterFunction: false
 | 
			
		||||
  AfterCaseLabel: false
 | 
			
		||||
  AfterEnum: false
 | 
			
		||||
  AfterNamespace: false
 | 
			
		||||
  AfterStruct: false
 | 
			
		||||
  AfterUnion: false
 | 
			
		||||
  AfterExternBlock: false
 | 
			
		||||
  BeforeCatch: false
 | 
			
		||||
  BeforeElse: false
 | 
			
		||||
  BeforeLambdaBody: false
 | 
			
		||||
  BeforeWhile: false
 | 
			
		||||
  IndentBraces: false
 | 
			
		||||
  SplitEmptyFunction: true
 | 
			
		||||
  SplitEmptyRecord: false
 | 
			
		||||
  SplitEmptyNamespace: false
 | 
			
		||||
  AfterControlStatement: MultiLine
 | 
			
		||||
BreakBeforeBinaryOperators: NonAssignment
 | 
			
		||||
BreakBeforeTernaryOperators: true
 | 
			
		||||
AlignOperands: AlignAfterOperator
 | 
			
		||||
InsertTrailingCommas: Wrapped
 | 
			
		||||
MaxEmptyLinesToKeep: 1
 | 
			
		||||
ExperimentalAutoDetectBinPacking: false
 | 
			
		||||
ColumnLimit: 100
 | 
			
		||||
IndentWidth: 2
 | 
			
		||||
TabWidth: 2
 | 
			
		||||
AllowAllConstructorInitializersOnNextLine: false
 | 
			
		||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
 | 
			
		||||
NamespaceIndentation: None
 | 
			
		||||
IncludeBlocks: Regroup
 | 
			
		||||
IncludeCategories:
 | 
			
		||||
  - Regex: '^<(cassert|cctype|cerrno|cfenv|cfloat|cinttypes|climits|clocale|cmath|csetjmp|csignal|cstdarg|cstdbool|cstddef|cstdint|cstdio|cstdlib|cstring|ctime|cuchar|cwchar|cwctype|algorithm|any|array|atomic|bitset|chrono|codecvt|complex|condition_variable|deque|exception|filesystem|forward_list|fstream|functional|future|initializer_list|iomanip|ios|iosfwd|iostream|istream|iterator|latch|limits|list|locale|map|memory|mutex|new|numeric|optional|ostream|queue|random|ratio|regex|scoped_allocator|set|shared_mutex|sstream|stack|stdexcept|streambuf|string|string_view|strstream|syncstream|system_error|thread|tuple|type_traits|typeindex|typeinfo|unordered_map|unordered_set|utility|valarray|variant|vector|version|assert.h|ctype.h|errno.h|fenv.h|float.h|inttypes.h|limits.h|locale.h|math.h|setjmp.h|signal.h|stdarg.h|stddef.h|stdint.h|stdio.h|stdlib.h|string.h|time.h|uchar.h|wchar.h|wctype.h)>$'
 | 
			
		||||
    Priority: 0
 | 
			
		||||
  - Regex: '^<.*>$'
 | 
			
		||||
    Priority: 1
 | 
			
		||||
  - Regex: '^".*"$'
 | 
			
		||||
    Priority: 2
 | 
			
		||||
  - Regex: '.+'
 | 
			
		||||
    Priority: 3
 | 
			
		||||
							
								
								
									
										54
									
								
								.clang-tidy
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								.clang-tidy
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,54 @@
 | 
			
		|||
WarningsAsErrors: '*'
 | 
			
		||||
HeaderFilterRegex: '.*\.hpp'
 | 
			
		||||
FormatStyle: file
 | 
			
		||||
Checks: >
 | 
			
		||||
  -*,
 | 
			
		||||
  bugprone-*,
 | 
			
		||||
  -bugprone-easily-swappable-parameters,
 | 
			
		||||
  concurrency-*,
 | 
			
		||||
  cppcoreguidelines-*,
 | 
			
		||||
  -cppcoreguidelines-owning-memory,
 | 
			
		||||
  -cppcoreguidelines-avoid-magic-numbers,
 | 
			
		||||
  -cppcoreguidelines-pro-bounds-constant-array-index,
 | 
			
		||||
  -cppcoreguidelines-avoid-const-or-ref-data-members,
 | 
			
		||||
  google-build-using-namespace.
 | 
			
		||||
  google-explicit-constructor,
 | 
			
		||||
  google-global-names-in-headers,
 | 
			
		||||
  google-readability-casting,
 | 
			
		||||
  google-runtime-int,
 | 
			
		||||
  google-runtime-operator,
 | 
			
		||||
  misc-*,
 | 
			
		||||
  -misc-no-recursion,
 | 
			
		||||
  -misc-non-private-member-variables-in-classes,
 | 
			
		||||
  modernize-*,
 | 
			
		||||
  -modernize-return-braced-init-list,
 | 
			
		||||
  -modernize-use-trailing-return-type,
 | 
			
		||||
  performance-*,
 | 
			
		||||
  portability-std-allocator-const,
 | 
			
		||||
  readability-*,
 | 
			
		||||
  -readability-function-cognitive-complexity,
 | 
			
		||||
  -readability-function-size,
 | 
			
		||||
  -readability-identifier-length,
 | 
			
		||||
  -readability-magic-numbers,
 | 
			
		||||
  -readability-uppercase-literal-suffix,
 | 
			
		||||
  -readability-braces-around-statements,
 | 
			
		||||
  -readability-redundant-access-specifiers,
 | 
			
		||||
  tidyfox-*,
 | 
			
		||||
CheckOptions:
 | 
			
		||||
  performance-for-range-copy.WarnOnAllAutoCopies: true
 | 
			
		||||
  performance-inefficient-string-concatenation.StrictMode: true
 | 
			
		||||
  readability-braces-around-statements.ShortStatementLines: 1
 | 
			
		||||
  readability-identifier-naming.ClassCase: CamelCase
 | 
			
		||||
  readability-identifier-naming.ConstantCase: UPPER_CASE
 | 
			
		||||
  readability-identifier-naming.EnumCase: CamelCase
 | 
			
		||||
  readability-identifier-naming.FunctionCase: camelBack
 | 
			
		||||
  readability-identifier-naming.MemberCase: camelBack
 | 
			
		||||
  readability-identifier-naming.NamespaceCase: lower_case
 | 
			
		||||
  readability-identifier-naming.LocalConstantCase: camelBack
 | 
			
		||||
  readability-identifier-naming.MethodCase: camelBack
 | 
			
		||||
  readability-identifier-naming.ParameterCase: camelBack
 | 
			
		||||
  readability-identifier-naming.VariableCase: camelBack
 | 
			
		||||
 | 
			
		||||
  # does not appear to work
 | 
			
		||||
  readability-operators-representation.BinaryOperators: '&&;&=;&;|;~;!;!=;||;|=;^;^='
 | 
			
		||||
  readability-operators-representation.OverloadedOperators: '&&;&=;&;|;~;!;!=;||;|=;^;^='
 | 
			
		||||
							
								
								
									
										10
									
								
								.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
# build files
 | 
			
		||||
/build/
 | 
			
		||||
compile_commands.json
 | 
			
		||||
 | 
			
		||||
# clangd
 | 
			
		||||
/.cache
 | 
			
		||||
 | 
			
		||||
# direnv
 | 
			
		||||
/.envrc
 | 
			
		||||
/.direnv/
 | 
			
		||||
							
								
								
									
										35
									
								
								CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,35 @@
 | 
			
		|||
cmake_minimum_required(VERSION 3.20)
 | 
			
		||||
project(qtshell VERSION "0.0.1")
 | 
			
		||||
 | 
			
		||||
set(QT_MIN_VERSION "6.6.0")
 | 
			
		||||
set(CMAKE_CXX_STANDARD 20)
 | 
			
		||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
 | 
			
		||||
 | 
			
		||||
add_compile_options(-Wall -Wextra)
 | 
			
		||||
 | 
			
		||||
# nix workaround
 | 
			
		||||
if (CMAKE_EXPORT_COMPILE_COMMANDS)
 | 
			
		||||
	set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES})
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
if (NOT CMAKE_BUILD_TYPE)
 | 
			
		||||
	message(STATUS "CMAKE_BUILD_TYPE unset, defaulting to Debug.")
 | 
			
		||||
	set(CMAKE_BUILD_TYPE Debug)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
find_package(Qt6 REQUIRED COMPONENTS Qml QuickControls2)
 | 
			
		||||
find_package(LayerShellQt REQUIRED)
 | 
			
		||||
 | 
			
		||||
qt_standard_project_setup(REQUIRES 6.6)
 | 
			
		||||
 | 
			
		||||
qt_add_executable(qtshell
 | 
			
		||||
	src/cpp/main.cpp
 | 
			
		||||
	src/cpp/shell.cpp
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
qt_add_qml_module(qtshell URI QtShell)
 | 
			
		||||
 | 
			
		||||
# qml type registration requires this
 | 
			
		||||
target_include_directories(qtshell PRIVATE src/cpp)
 | 
			
		||||
 | 
			
		||||
target_link_libraries(qtshell PRIVATE Qt6::Qml Qt6::QuickControls2 LayerShellQtInterface)
 | 
			
		||||
							
								
								
									
										33
									
								
								Justfile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								Justfile
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
builddir := 'build'
 | 
			
		||||
 | 
			
		||||
with_cpphpp := 'find src -type f \( -name "*.cpp" -o -name "*.hpp" \) -print0 | xargs -0'
 | 
			
		||||
with_cpp := 'find src -type f -name "*.cpp" -print0 | xargs -0'
 | 
			
		||||
 | 
			
		||||
fmt:
 | 
			
		||||
    {{with_cpphpp}} clang-format -i
 | 
			
		||||
 | 
			
		||||
lint:
 | 
			
		||||
    {{with_cpp}} clang-tidy --load={{ env_var("TIDYFOX") }}
 | 
			
		||||
 | 
			
		||||
fixlint:
 | 
			
		||||
    {{with_cpp}} clang-tidy --load={{ env_var("TIDYFOX") }}
 | 
			
		||||
 | 
			
		||||
configure target='debug' *FLAGS='':
 | 
			
		||||
	cmake -B {{builddir}} \
 | 
			
		||||
		-DCMAKE_BUILD_TYPE={{ if target == "debug" { "Debug" } else { "Release" } }} \
 | 
			
		||||
		-DCMAKE_EXPORT_COMPILE_COMMANDS=ON {{FLAGS}}
 | 
			
		||||
 | 
			
		||||
	ln -sf {{builddir}}/compile_commands.json compile_commands.json
 | 
			
		||||
 | 
			
		||||
_configure_if_clean:
 | 
			
		||||
	@if ! [ -d {{builddir}} ]; then just configure; fi
 | 
			
		||||
 | 
			
		||||
build: _configure_if_clean
 | 
			
		||||
	cmake --build {{builddir}}
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	rm -f compile_commands.json
 | 
			
		||||
	rm -rf {{builddir}}
 | 
			
		||||
 | 
			
		||||
run *ARGS='': build
 | 
			
		||||
	{{builddir}}/qtshell {{ARGS}}
 | 
			
		||||
							
								
								
									
										51
									
								
								shell.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								shell.nix
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,51 @@
 | 
			
		|||
{ pkgs ? import <nixpkgs> {} }: let
 | 
			
		||||
  tidyfox = import (pkgs.fetchFromGitea {
 | 
			
		||||
    domain = "git.outfoxxed.me";
 | 
			
		||||
    owner = "outfoxxed";
 | 
			
		||||
    repo = "tidyfox";
 | 
			
		||||
    rev = "1f062cc198d1112d13e5128fa1f2ee3dbffe613b";
 | 
			
		||||
    sha256 = "kbt0Zc1qHE5fhqBkKz8iue+B+ZANjF1AR/RdgmX1r0I=";
 | 
			
		||||
  }) {};
 | 
			
		||||
 | 
			
		||||
  qtlayershell = pkgs.callPackage (import (pkgs.fetchFromGitea {
 | 
			
		||||
    domain = "git.outfoxxed.me";
 | 
			
		||||
    owner = "outfoxxed";
 | 
			
		||||
    repo = "layer-shell-qt-nokde";
 | 
			
		||||
    rev = "a50d30687cc03ae4da177033faf5f038c3e1a8b2";
 | 
			
		||||
    sha256 = "5fNwoCce74SSqR5XB3fJ8GI+D5cbkcLRok42k8R3XSw=";
 | 
			
		||||
  })) {}; #pkgs.callPackage (import /home/admin/programming/outfoxxed/layer-shell-qt) {};
 | 
			
		||||
in pkgs.mkShell {
 | 
			
		||||
  nativeBuildInputs = with pkgs; [
 | 
			
		||||
    just
 | 
			
		||||
    clang-tools_17
 | 
			
		||||
    cmake
 | 
			
		||||
 | 
			
		||||
    qt6.wrapQtAppsHook
 | 
			
		||||
    makeWrapper
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  buildInputs = with pkgs; [
 | 
			
		||||
    qt6.qtbase
 | 
			
		||||
    qt6.qtdeclarative
 | 
			
		||||
    qt6.qtwayland
 | 
			
		||||
    qtlayershell
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  TIDYFOX = "${tidyfox}/lib/libtidyfox.so";
 | 
			
		||||
 | 
			
		||||
  shellHook = ''
 | 
			
		||||
    export CMAKE_BUILD_PARALLEL_LEVEL=$(nproc)
 | 
			
		||||
 | 
			
		||||
    # Add Qt-related environment variables.
 | 
			
		||||
    # https://discourse.nixos.org/t/qt-development-environment-on-a-flake-system/23707/5
 | 
			
		||||
    setQtEnvironment=$(mktemp)
 | 
			
		||||
    random=$(openssl rand -base64 20 | sed "s/[^a-zA-Z0-9]//g")
 | 
			
		||||
    makeWrapper "$(type -p sh)" "$setQtEnvironment" "''${qtWrapperArgs[@]}" --argv0 "$random"
 | 
			
		||||
    sed "/$random/d" -i "$setQtEnvironment"
 | 
			
		||||
    source "$setQtEnvironment"
 | 
			
		||||
 | 
			
		||||
    # qmlls does not account for the import path and bases its search off qtbase's path.
 | 
			
		||||
    # The actual imports come from qtdeclarative. This directs qmlls to the correct imports.
 | 
			
		||||
    export QMLLS_BUILD_DIRS=$(pwd)/build:$QML2_IMPORT_PATH
 | 
			
		||||
  '';
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										63
									
								
								src/cpp/main.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/cpp/main.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,63 @@
 | 
			
		|||
#include <LayerShellQt/shell.h>
 | 
			
		||||
#include <qcommandlineoption.h>
 | 
			
		||||
#include <qcommandlineparser.h>
 | 
			
		||||
#include <qdir.h>
 | 
			
		||||
#include <qguiapplication.h>
 | 
			
		||||
#include <qlogging.h>
 | 
			
		||||
#include <qobject.h>
 | 
			
		||||
#include <qqmlapplicationengine.h>
 | 
			
		||||
#include <qstandardpaths.h>
 | 
			
		||||
#include <qstring.h>
 | 
			
		||||
 | 
			
		||||
#include "shell.hpp"
 | 
			
		||||
 | 
			
		||||
int main(int argc, char** argv) {
 | 
			
		||||
	const auto app = QGuiApplication(argc, argv);
 | 
			
		||||
	QGuiApplication::setApplicationName("qtshell");
 | 
			
		||||
	QGuiApplication::setApplicationVersion("0.0.1");
 | 
			
		||||
 | 
			
		||||
	QCommandLineParser parser;
 | 
			
		||||
	parser.setApplicationDescription("Qt based desktop shell");
 | 
			
		||||
	parser.addHelpOption();
 | 
			
		||||
	parser.addVersionOption();
 | 
			
		||||
 | 
			
		||||
	auto configOption = QCommandLineOption({"c", "config"}, "Path to configuration file.", "path");
 | 
			
		||||
	parser.addOption(configOption);
 | 
			
		||||
	parser.process(app);
 | 
			
		||||
 | 
			
		||||
	QString configPath;
 | 
			
		||||
	if (parser.isSet(configOption)) {
 | 
			
		||||
		configPath = parser.value(configOption);
 | 
			
		||||
	} else {
 | 
			
		||||
		configPath = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation);
 | 
			
		||||
		configPath = QDir(QDir(configPath).filePath("qtshell")).filePath("config.qml");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	qInfo() << "config file path:" << configPath;
 | 
			
		||||
 | 
			
		||||
	if (!QFile(configPath).exists()) {
 | 
			
		||||
		qCritical() << "config file does not exist";
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	CONFIG_PATH = configPath;
 | 
			
		||||
 | 
			
		||||
	LayerShellQt::Shell::useLayerShell();
 | 
			
		||||
 | 
			
		||||
	auto engine = QQmlApplicationEngine();
 | 
			
		||||
	engine.load(configPath);
 | 
			
		||||
 | 
			
		||||
	if (engine.rootObjects().isEmpty()) {
 | 
			
		||||
		qCritical() << "failed to load config file";
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	auto* shellobj = qobject_cast<QtShell*>(engine.rootObjects().first());
 | 
			
		||||
 | 
			
		||||
	if (shellobj == nullptr) {
 | 
			
		||||
		qCritical() << "root item was not a QtShell";
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return QGuiApplication::exec();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										96
									
								
								src/cpp/shell.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								src/cpp/shell.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,96 @@
 | 
			
		|||
#include "shell.hpp"
 | 
			
		||||
#include <utility>
 | 
			
		||||
 | 
			
		||||
#include <qfileinfo.h>
 | 
			
		||||
#include <qlogging.h>
 | 
			
		||||
#include <qobject.h>
 | 
			
		||||
#include <qobjectdefs.h>
 | 
			
		||||
#include <qqmlcomponent.h>
 | 
			
		||||
#include <qqmlcontext.h>
 | 
			
		||||
#include <qqmlengine.h>
 | 
			
		||||
#include <qqmllist.h>
 | 
			
		||||
#include <qtmetamacros.h>
 | 
			
		||||
 | 
			
		||||
QString CONFIG_PATH; // NOLINT
 | 
			
		||||
 | 
			
		||||
QtShell::QtShell(): QObject(nullptr), path(CONFIG_PATH), dir(QFileInfo(this->path).dir()) {
 | 
			
		||||
	CONFIG_PATH = "";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QtShell::componentComplete() {
 | 
			
		||||
	if (this->path.isEmpty()) {
 | 
			
		||||
		qWarning() << "Multiple QtShell objects were created. You should not do this.";
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (auto* component: this->mComponents) {
 | 
			
		||||
		component->prepare(this->dir);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QQmlListProperty<ShellComponent> QtShell::components() {
 | 
			
		||||
	return QQmlListProperty<ShellComponent>(
 | 
			
		||||
	    this,
 | 
			
		||||
	    nullptr,
 | 
			
		||||
	    &QtShell::appendComponent,
 | 
			
		||||
	    nullptr,
 | 
			
		||||
	    nullptr,
 | 
			
		||||
	    nullptr,
 | 
			
		||||
	    nullptr,
 | 
			
		||||
	    nullptr
 | 
			
		||||
	);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QtShell::appendComponent(QQmlListProperty<ShellComponent>* list, ShellComponent* component) {
 | 
			
		||||
	auto* shell = qobject_cast<QtShell*>(list->object);
 | 
			
		||||
 | 
			
		||||
	if (shell != nullptr) shell->mComponents.append(component);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ShellComponent::setSource(QString source) {
 | 
			
		||||
	if (this->mComponent != nullptr) {
 | 
			
		||||
		qWarning() << "cannot define ShellComponent.source while defining a component";
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this->mSource = std::move(source);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ShellComponent::setComponent(QQmlComponent* component) {
 | 
			
		||||
	if (this->mSource != nullptr) {
 | 
			
		||||
		qWarning() << "cannot define a component for ShellComponent while source is set";
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this->mComponent = component;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ShellComponent::prepare(const QDir& basePath) {
 | 
			
		||||
	if (this->mComponent == nullptr) {
 | 
			
		||||
		if (this->mSource == nullptr) {
 | 
			
		||||
			qWarning() << "neither source or a component was set for ShellComponent on prepare";
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		auto path = basePath.filePath(this->mSource);
 | 
			
		||||
		qDebug() << "preparing ShellComponent from" << path;
 | 
			
		||||
 | 
			
		||||
		auto* context = QQmlEngine::contextForObject(this);
 | 
			
		||||
		if (context == nullptr) {
 | 
			
		||||
			qWarning() << "ShellComponent was created without an associated QQmlEngine, cannot prepare";
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		auto* engine = context->engine();
 | 
			
		||||
 | 
			
		||||
		this->mComponent = new QQmlComponent(engine, path, this);
 | 
			
		||||
 | 
			
		||||
		if (this->mComponent == nullptr) {
 | 
			
		||||
			qWarning() << "could not load ShellComponent source" << path;
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	qDebug() << "Sending ready for ShellComponent";
 | 
			
		||||
	emit this->ready();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										59
									
								
								src/cpp/shell.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/cpp/shell.hpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,59 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <qdir.h>
 | 
			
		||||
#include <qlogging.h>
 | 
			
		||||
#include <qobject.h>
 | 
			
		||||
#include <qqmlcomponent.h>
 | 
			
		||||
#include <qqmlengine.h>
 | 
			
		||||
#include <qqmlintegration.h>
 | 
			
		||||
#include <qqmllist.h>
 | 
			
		||||
#include <qqmlparserstatus.h>
 | 
			
		||||
 | 
			
		||||
extern QString CONFIG_PATH; // NOLINT
 | 
			
		||||
 | 
			
		||||
class ShellComponent;
 | 
			
		||||
 | 
			
		||||
class QtShell: public QObject, public QQmlParserStatus {
 | 
			
		||||
	Q_OBJECT;
 | 
			
		||||
	Q_INTERFACES(QQmlParserStatus);
 | 
			
		||||
	Q_PROPERTY(QQmlListProperty<ShellComponent> components READ components FINAL);
 | 
			
		||||
	Q_CLASSINFO("DefaultProperty", "components");
 | 
			
		||||
	QML_ELEMENT;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	explicit QtShell();
 | 
			
		||||
 | 
			
		||||
	void classBegin() override {};
 | 
			
		||||
	void componentComplete() override;
 | 
			
		||||
 | 
			
		||||
	QQmlListProperty<ShellComponent> components();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	static void appendComponent(QQmlListProperty<ShellComponent>* list, ShellComponent* component);
 | 
			
		||||
 | 
			
		||||
	QList<ShellComponent*> mComponents;
 | 
			
		||||
	QString path;
 | 
			
		||||
	QDir dir;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class ShellComponent: public QObject {
 | 
			
		||||
	Q_OBJECT;
 | 
			
		||||
	Q_PROPERTY(QString source WRITE setSource);
 | 
			
		||||
	Q_PROPERTY(QQmlComponent* component MEMBER mComponent WRITE setComponent);
 | 
			
		||||
	Q_CLASSINFO("DefaultProperty", "component");
 | 
			
		||||
	QML_ELEMENT;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	explicit ShellComponent(QObject* parent = nullptr): QObject(parent) {}
 | 
			
		||||
 | 
			
		||||
	void setSource(QString source);
 | 
			
		||||
	void setComponent(QQmlComponent* component);
 | 
			
		||||
	void prepare(const QDir& basePath);
 | 
			
		||||
 | 
			
		||||
signals:
 | 
			
		||||
	void ready();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	QString mSource;
 | 
			
		||||
	QQmlComponent* mComponent = nullptr;
 | 
			
		||||
};
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue