diff --git a/.gitignore b/.gitignore index 36d77999..80cf8f11 100644 --- a/.gitignore +++ b/.gitignore @@ -26,8 +26,8 @@ install-local/ .deploy.stamp # auto-gen files -src/app/qml_without_webengine.qrc src/app/resources.qrc +src/app/qml.qrc src/app/constant/JamiResources.qml # macOS diff --git a/CMakeLists.txt b/CMakeLists.txt index d5c6f3e0..567653aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -125,17 +125,32 @@ include(FindPython3) find_package(Python3 3.6 REQUIRED COMPONENTS Interpreter) set(PYTHON_EXEC ${Python3_EXECUTABLE}) -set(QML_RESOURCES ${APP_SRC_DIR}/resources.qrc) +# Resource auto-gen +# QML and related code files +# Check files in the app's src directory and force a reconfigure if it +# changes. +# Only include webengine resources if specified. if(WITH_WEBENGINE) - set(QML_RESOURCES_QML ${APP_SRC_DIR}/qml.qrc) -else() - execute_process( - COMMAND - ${PYTHON_EXEC} ${SCRIPTS_DIR}/gen-qrc-without-webengine.py - WORKING_DIRECTORY ${APP_SRC_DIR}) - set(QML_RESOURCES_QML - ${APP_SRC_DIR}/qml_without_webengine.qrc) + set(GEN_QML_QRC_ARGS "--with-webengine") endif() +file(GLOB_RECURSE + QML_FILES CONFIGURE_DEPENDS + ${APP_SRC_DIR}/*) +execute_process( + COMMAND + ${PYTHON_EXEC} ${SCRIPTS_DIR}/gen_qml_qrc.py ${GEN_QML_QRC_ARGS} + WORKING_DIRECTORY ${APP_SRC_DIR}) +set(QML_RESOURCES_QML ${APP_SRC_DIR}/qml.qrc) +# Image and misc. resources +# check files in the resources directory and force a reconfigure if it +# changes +file(GLOB_RECURSE + RES_FILES CONFIGURE_DEPENDS + ${PROJECT_SOURCE_DIR}/resources/*) +execute_process( + COMMAND ${PYTHON_EXEC} ${SCRIPTS_DIR}/gen_resources_qrc.py + WORKING_DIRECTORY ${APP_SRC_DIR}) +set(QML_RESOURCES ${APP_SRC_DIR}/resources.qrc) if (APPLE) include(FetchContent) @@ -148,16 +163,6 @@ if (APPLE) include_directories(${libqrencode_SOURCE_DIR}) endif() -# Resource auto-gen -# check files in the resources directory and force a reconfigure if it -# changes -file(GLOB_RECURSE - RES_FILES CONFIGURE_DEPENDS - ${PROJECT_SOURCE_DIR}/resources/*) -execute_process( - COMMAND ${PYTHON_EXEC} ${SCRIPTS_DIR}/gen_resources_qrc.py - WORKING_DIRECTORY ${APP_SRC_DIR}) - # library compatibility (boost, libnotify, etc.) add_definitions(-DQT_NO_KEYWORDS) diff --git a/extras/scripts/gen-qrc-without-webengine.py b/extras/scripts/gen-qrc-without-webengine.py deleted file mode 100755 index 329b3911..00000000 --- a/extras/scripts/gen-qrc-without-webengine.py +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright (C) 2022 Savoir-faire Linux Inc. -# -# Author: Kateryna Kostiuk -# Author: Amin Bandali -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -with open('qml_without_webengine.qrc', 'w') as outfile: - with open('qml.qrc', 'r') as infile: - line = infile.readline() - while line: - if 'EmojiPicker.qml' in line: - outfile.write('\tnowebengine/EmojiPicker.qml\n') - elif 'MediaPreviewBase.qml' in line: - outfile.write('\tnowebengine/MediaPreviewBase.qml\n') - else: - outfile.write(line) - line = infile.readline() diff --git a/extras/scripts/gen_qml_qrc.py b/extras/scripts/gen_qml_qrc.py new file mode 100644 index 00000000..05c01dd9 --- /dev/null +++ b/extras/scripts/gen_qml_qrc.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# Copyright (C) 2022 Savoir-faire Linux Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 +# USA. + +""" +Generate qrc file for qml and related code files recursively within the source +directory. +""" + +import os + +# These paths should be relative to the working directory of the +# script as set in the project CMakeLists, which should in turn be +# where the resources.qrc will be located (currently 'src/app'). +app_src_dir = os.path.join('..', '..', 'src', 'app') +resfile = os.path.join('qml.qrc') + + +def path_contains_dir(filepath, dir_str): + """ Return True if the given filepath contains the given directory. """ + # Split the filepath into its components + path_components = os.path.normpath(filepath).split(os.sep) + # Return True if the given directory is in the path + return dir_str in path_components + + +def posix_path(path): + """ + Force the use of POSIX path separators for the resource prefixes + and paths (useful only if versioning the qml.qrc file). + """ + return path.replace(os.sep, '/') + + +def gen_qml_qrc(with_webengine): + """ Generate the qml.qrc file. """ + print("Generating qml.qrc file ...") + with open(resfile, 'w', encoding='utf-8') as qrc: + qrc.write('\n') + for root, _, files in os.walk(app_src_dir): + # Skip the nowebengine directory if we can use webengine + if with_webengine and path_contains_dir(root, 'nowebengine'): + continue + # Skip the webengine directory if we can't use webengine + if not with_webengine and path_contains_dir(root, 'webengine'): + continue + filtered = [k for k in files if k.endswith('.qml') or + k.endswith('.js') or k.endswith('.html') or + k.endswith('.css') or k.endswith('.conf')] + # if there are no files of interest in this directory, skip it + if not filtered: + continue + # For now, get the relative resource prefix for this directory, + # remove the leading slash, and add it as a comment to the line. + # Ideally, we should use the actual resource prefix instead of /, + # but this will require some refactoring of the QML code. + prefix = root.split(app_src_dir)[-1][1:] + qrc.write( + f'\t \n') + for file in filtered: + relpath = os.path.relpath( + os.path.join(root, file), app_src_dir) + qrc.write(f'\t\t{posix_path(relpath)}\n') + qrc.write('\t\n') + qrc.write('') + + +if __name__ == '__main__': + # We can't use webengine if we're building for macOS app store + import argparse + parser = argparse.ArgumentParser() + parser.add_argument('--with-webengine', action='store_true', + default=False, help='Include webengine resources') + args = parser.parse_args() + gen_qml_qrc(args.with_webengine) diff --git a/src/app/commoncomponents/DataTransferMessageDelegate.qml b/src/app/commoncomponents/DataTransferMessageDelegate.qml index b3a5b2ac..3912857c 100644 --- a/src/app/commoncomponents/DataTransferMessageDelegate.qml +++ b/src/app/commoncomponents/DataTransferMessageDelegate.qml @@ -274,7 +274,9 @@ Loader { id: avComp Loader { Component.onCompleted: { - var qml = WITH_WEBENGINE ? "qrc:/commoncomponents/MediaPreviewBase.qml" : "qrc:/nowebengine/MediaPreviewBase.qml" + var qml = WITH_WEBENGINE ? + "qrc:/webengine/MediaPreviewBase.qml" : + "qrc:/nowebengine/MediaPreviewBase.qml" setSource( qml, { isVideo: mediaInfo.isVideo, html:mediaInfo.html } ) } } diff --git a/src/app/mainview/components/ChatViewFooter.qml b/src/app/mainview/components/ChatViewFooter.qml index ba754ba6..beb8d56e 100644 --- a/src/app/mainview/components/ChatViewFooter.qml +++ b/src/app/mainview/components/ChatViewFooter.qml @@ -104,14 +104,16 @@ Rectangle { } Loader { - id: empjiLoader - source: WITH_WEBENGINE ? "qrc:/commoncomponents/emojipicker/EmojiPicker.qml" : "qrc:/nowebengine/EmojiPicker.qml" + id: emojiPickerLoader + source: WITH_WEBENGINE ? + "qrc:/webengine/emojipicker/EmojiPicker.qml" : + "qrc:/nowebengine/EmojiPicker.qml" function openEmojiPicker() { item.openEmojiPicker() } Connections { - target: empjiLoader.item + target: emojiPickerLoader.item function onEmojiIsPicked(content) { messageBar.textAreaObj.insertText(content) } @@ -168,20 +170,20 @@ Rectangle { onEmojiButtonClicked: { JamiQmlUtils.updateMessageBarButtonsPoints() - empjiLoader.parent = JamiQmlUtils.mainViewRectObj + emojiPickerLoader.parent = JamiQmlUtils.mainViewRectObj - empjiLoader.x = Qt.binding(function() { + emojiPickerLoader.x = Qt.binding(function() { var buttonX = JamiQmlUtils.emojiPickerButtonInMainViewPoint.x + JamiQmlUtils.emojiPickerButtonObj.width - return buttonX - empjiLoader.width + return buttonX - emojiPickerLoader.width }) - empjiLoader.y = Qt.binding(function() { + emojiPickerLoader.y = Qt.binding(function() { var buttonY = JamiQmlUtils.audioRecordMessageButtonInMainViewPoint.y - return buttonY - empjiLoader.height - messageBar.marginSize + return buttonY - emojiPickerLoader.height - messageBar.marginSize - JamiTheme.chatViewHairLineSize }) - empjiLoader.openEmojiPicker() + emojiPickerLoader.openEmojiPicker() } onSendFileButtonClicked: jamiFileDialog.open() onSendMessageButtonClicked: { diff --git a/src/app/qml.qrc b/src/app/qml.qrc deleted file mode 100644 index fd4cdc7d..00000000 --- a/src/app/qml.qrc +++ /dev/null @@ -1,217 +0,0 @@ - - - MainApplicationWindow.qml - DaemonReconnectWindow.qml - constant/JamiQmlUtils.qml - constant/JamiStrings.qml - constant/JamiTheme.qml - commoncomponents/VideoView.qml - commoncomponents/LocalVideo.qml - commoncomponents/SettingParaCombobox.qml - commoncomponents/PreferenceItemDelegate.qml - commoncomponents/PasswordDialog.qml - commoncomponents/EditableLineEdit.qml - commoncomponents/MaterialLineEdit.qml - commoncomponents/PhotoboothView.qml - commoncomponents/JamiListView.qml - commoncomponents/DeleteAccountDialog.qml - commoncomponents/ConfirmDialog.qml - commoncomponents/CustomBorder.qml - commoncomponents/PushButton.qml - commoncomponents/JamiFileDialog.qml - commoncomponents/MaterialButton.qml - commoncomponents/ElidedTextLabel.qml - commoncomponents/SpinnerButton.qml - commoncomponents/UsernameLineEdit.qml - commoncomponents/Scaffold.qml - commoncomponents/LineEditContextMenu.qml - commoncomponents/BaseModalDialog.qml - commoncomponents/SimpleMessageDialog.qml - commoncomponents/ResponsiveImage.qml - commoncomponents/PresenceIndicator.qml - commoncomponents/DaemonReconnectPopup.qml - commoncomponents/SpinningAnimation.qml - commoncomponents/MediaPreviewBase.qml - settingsview/SettingsView.qml - settingsview/components/ChatviewSettings.qml - settingsview/components/FileTransferSettings.qml - settingsview/components/SettingsMenu.qml - settingsview/components/SettingsMenuButton.qml - settingsview/components/SettingsHeader.qml - settingsview/components/SystemSettings.qml - settingsview/components/RecordingSettings.qml - settingsview/components/UpdateSettings.qml - settingsview/components/AvSettingPage.qml - settingsview/components/AudioSettings.qml - settingsview/components/VideoSettings.qml - settingsview/components/GeneralSettingsPage.qml - settingsview/components/PluginSettingsPage.qml - settingsview/components/PluginListView.qml - settingsview/components/PluginPreferencesView.qml - settingsview/components/PluginPreferencesListView.qml - settingsview/components/CurrentAccountSettings.qml - settingsview/components/UserIdentity.qml - settingsview/components/JamiUserIdentity.qml - settingsview/components/SIPUserIdentity.qml - settingsview/components/AccountProfile.qml - settingsview/components/LinkedDevices.qml - settingsview/components/BannedContacts.qml - settingsview/components/AdvancedSettings.qml - settingsview/components/AdvancedJamiSecuritySettings.qml - settingsview/components/AdvancedSIPSecuritySettings.qml - settingsview/components/AdvancedMediaSettings.qml - settingsview/components/MediaSettings.qml - settingsview/components/AdvancedSDPSettings.qml - settingsview/components/AdvancedNameServerSettings.qml - settingsview/components/AdvancedVoiceMailSettings.qml - settingsview/components/AdvancedOpenDHTSettings.qml - settingsview/components/AdvancedPublicAddressSettings.qml - settingsview/components/AdvancedConnectivitySettings.qml - settingsview/components/AdvancedCallSettings.qml - settingsview/components/AdvancedChatSettings.qml - settingsview/components/SettingMaterialButton.qml - settingsview/components/ToggleSwitch.qml - settingsview/components/SettingSpinBox.qml - settingsview/components/SettingsComboBox.qml - settingsview/components/SettingsMaterialLineEdit.qml - settingsview/components/LevelMeter.qml - settingsview/components/DeviceItemDelegate.qml - settingsview/components/PluginItemDelegate.qml - settingsview/components/ContactItemDelegate.qml - settingsview/components/MediaCodecDelegate.qml - settingsview/components/NameRegistrationDialog.qml - settingsview/components/LinkDeviceDialog.qml - settingsview/components/RevokeDevicePasswordDialog.qml - wizardview/WizardView.qml - wizardview/components/WelcomePage.qml - wizardview/components/CreateAccountPage.qml - wizardview/components/CreateSIPAccountPage.qml - wizardview/components/ImportFromBackupPage.qml - wizardview/components/ImportFromDevicePage.qml - wizardview/components/ConnectToAccountManagerPage.qml - wizardview/components/ProfilePage.qml - wizardview/components/AccountCreationStepIndicator.qml - mainview/MainView.qml - mainview/components/PluginHandlerItemDelegate.qml - mainview/components/AboutPopUp.qml - mainview/components/SidePanel.qml - mainview/components/WelcomePage.qml - mainview/components/ChatView.qml - mainview/components/ConversationErrorsRow.qml - mainview/components/NewSwarmPage.qml - mainview/components/ChatViewHeader.qml - mainview/components/AccountComboBox.qml - mainview/components/CallStackView.qml - mainview/components/InitialCallPage.qml - mainview/components/CallOverlay.qml - mainview/components/ContactSearchBar.qml - mainview/components/OngoingCallPage.qml - mainview/components/ParticipantOverlay.qml - mainview/components/ProjectCreditsScrollView.qml - mainview/components/AccountComboBoxPopup.qml - mainview/components/SidePanelTabBar.qml - mainview/components/WelcomePageQrDialog.qml - mainview/components/ConversationSmartListContextMenu.qml - mainview/components/SwarmParticipantContextMenu.qml - mainview/components/CallViewContextMenu.qml - mainview/components/UserProfile.qml - mainview/components/SwarmDetailsPanel.qml - mainview/components/SwarmDetailsItem.qml - mainview/components/AddMemberPanel.qml - mainview/components/SelectScreen.qml - mainview/components/ScreenRubberBand.qml - mainview/components/ContactPicker.qml - mainview/components/PluginHandlerPicker.qml - mainview/components/ContactPickerItemDelegate.qml - mainview/components/RecordBox.qml - mainview/components/SipInputPanel.qml - mainview/components/ParticipantOverlayMenu.qml - mainview/js/selectscreenwindowcreation.js - mainview/js/screenrubberbandcreation.js - mainview/js/contactpickercreation.js - mainview/js/pluginhandlerpickercreation.js - mainview/components/FilterTabButton.qml - mainview/components/AccountItemDelegate.qml - mainview/components/ConversationListView.qml - mainview/components/SmartListItemDelegate.qml - mainview/components/BadgeNotifier.qml - mainview/components/ParticipantsLayer.qml - mainview/components/ParticipantsLayoutVertical.qml - mainview/components/ParticipantsLayoutHorizontal.qml - mainview/components/MainOverlay.qml - mainview/components/CallButtonDelegate.qml - mainview/components/CallActionBar.qml - commoncomponents/HalfPill.qml - commoncomponents/EditedPopup.qml - commoncomponents/MaterialToolTip.qml - mainview/components/ParticipantCallInStatusDelegate.qml - mainview/components/ParticipantCallInStatusView.qml - settingsview/components/TroubleshootSettings.qml - settingsview/components/LogsView.qml - commoncomponents/contextmenu/ContextMenuAutoLoader.qml - commoncomponents/contextmenu/BaseContextMenu.qml - commoncomponents/contextmenu/GeneralMenuItem.qml - commoncomponents/contextmenu/GeneralMenuSeparator.qml - mainview/components/ParticipantOverlayButton.qml - mainview/components/ParticipantControlLayout.qml - mainview/components/ChatViewFooter.qml - commoncomponents/emojipicker/EmojiPicker.qml - commoncomponents/emojipicker/emojiPickerLoader.js - commoncomponents/emojipicker/emojiPickerLoader.html - commoncomponents/emojipicker/emoji.js - mainview/components/MessageBarTextArea.qml - mainview/components/FilesToSendDelegate.qml - mainview/components/MessageBar.qml - mainview/components/FilesToSendContainer.qml - mainview/components/ReplyingContainer.qml - mainview/components/EditContainer.qml - commoncomponents/Avatar.qml - mainview/components/ConversationAvatar.qml - mainview/components/InvitationView.qml - commoncomponents/GeneralWebEngineView.qml - constant/JamiResources.qml - commoncomponents/BubbleLabel.qml - commoncomponents/BackButton.qml - commoncomponents/JamiSwitch.qml - mainview/components/UpdateToSwarm.qml - commoncomponents/TextMessageDelegate.qml - mainview/components/MessageListView.qml - commoncomponents/MessageBubble.qml - constant/MsgSeq.qml - commoncomponents/SBSContextMenu.qml - commoncomponents/SBSMessageBase.qml - commoncomponents/ReplyToRow.qml - commoncomponents/ReadStatus.qml - commoncomponents/GeneratedMessageDelegate.qml - commoncomponents/DataTransferMessageDelegate.qml - commoncomponents/ContactMessageDelegate.qml - mainview/components/ScrollToBottomButton.qml - commoncomponents/TypingDots.qml - commoncomponents/JamiScrollBar.qml - qtquickcontrols2.conf - commoncomponents/JamiFlickable.qml - AccountMigrationView.qml - settingsview/js/logviewwindowcreation.js - mainview/js/keyboardshortcuttablecreation.js - mainview/components/KeyboardShortcutTable.qml - mainview/components/KeyboardShortcutKeyDelegate.qml - mainview/components/KeyboardShortcutTabButton.qml - LayoutManager.qml - mainview/components/JamiIdentifier.qml - wizardview/components/NoUsernamePopup.qml - wizardview/components/AdvancedAccountSettings.qml - commoncomponents/InfoBox.qml - mainview/components/TipBox.qml - mainview/components/CustomizeTipBox.qml - mainview/components/BackupTipBox.qml - mainview/components/InformativeTipBox.qml - commoncomponents/TimestampInfo.qml - commoncomponents/MaterialTextField.qml - commoncomponents/ModalTextEdit.qml - commoncomponents/UsernameTextEdit.qml - mainview/components/DocumentsScrollview.qml - mainview/components/FilePreview.qml - mainview/components/MediaPreview.qml - mainview/components/CallInformationWindow.qml - - diff --git a/src/app/commoncomponents/GeneralWebEngineView.qml b/src/app/webengine/GeneralWebEngineView.qml similarity index 100% rename from src/app/commoncomponents/GeneralWebEngineView.qml rename to src/app/webengine/GeneralWebEngineView.qml diff --git a/src/app/commoncomponents/MediaPreviewBase.qml b/src/app/webengine/MediaPreviewBase.qml similarity index 98% rename from src/app/commoncomponents/MediaPreviewBase.qml rename to src/app/webengine/MediaPreviewBase.qml index 1192638c..eb06b93e 100644 --- a/src/app/commoncomponents/MediaPreviewBase.qml +++ b/src/app/webengine/MediaPreviewBase.qml @@ -26,6 +26,8 @@ import net.jami.Models 1.1 import net.jami.Constants 1.1 import net.jami.Adapters 1.1 +import "../commoncomponents" + WebEngineView { id: wev property bool isVideo diff --git a/src/app/commoncomponents/emojipicker/EmojiPicker.qml b/src/app/webengine/emojipicker/EmojiPicker.qml similarity index 91% rename from src/app/commoncomponents/emojipicker/EmojiPicker.qml rename to src/app/webengine/emojipicker/EmojiPicker.qml index a9dda179..eb8e0da9 100644 --- a/src/app/commoncomponents/emojipicker/EmojiPicker.qml +++ b/src/app/webengine/emojipicker/EmojiPicker.qml @@ -74,7 +74,7 @@ Rectangle { webChannel.registeredObjects: [jsBridgeObject] - onCompletedLoadHtml: ":/commoncomponents/emojipicker/emojiPickerLoader.html" + onCompletedLoadHtml: ":/webengine/emojipicker/emojiPickerLoader.html" onActiveFocusChanged: { if (visible) { @@ -88,10 +88,10 @@ Rectangle { ":qwebchannel.js")) emojiPickerWebView.runJavaScript( UtilsAdapter.qStringFromFile( - ":/commoncomponents/emojipicker/emoji.js")) + ":/webengine/emojipicker/emoji.js")) emojiPickerWebView.runJavaScript( UtilsAdapter.qStringFromFile( - ":/commoncomponents/emojipicker/emojiPickerLoader.js")) + ":/webengine/emojipicker/emojiPickerLoader.js")) emojiPickerWebView.runJavaScript( "init_emoji_picker(" + JamiTheme.darkTheme + ");") } diff --git a/src/app/commoncomponents/emojipicker/emoji.js b/src/app/webengine/emojipicker/emoji.js similarity index 100% rename from src/app/commoncomponents/emojipicker/emoji.js rename to src/app/webengine/emojipicker/emoji.js diff --git a/src/app/commoncomponents/emojipicker/emojiPickerLoader.html b/src/app/webengine/emojipicker/emojiPickerLoader.html similarity index 100% rename from src/app/commoncomponents/emojipicker/emojiPickerLoader.html rename to src/app/webengine/emojipicker/emojiPickerLoader.html diff --git a/src/app/commoncomponents/emojipicker/emojiPickerLoader.js b/src/app/webengine/emojipicker/emojiPickerLoader.js similarity index 100% rename from src/app/commoncomponents/emojipicker/emojiPickerLoader.js rename to src/app/webengine/emojipicker/emojiPickerLoader.js