diff --git a/Linphone/CMakeLists.txt b/Linphone/CMakeLists.txt index 660b4d2d1..60dbf5a38 100644 --- a/Linphone/CMakeLists.txt +++ b/Linphone/CMakeLists.txt @@ -4,6 +4,18 @@ project(Linphone VERSION 0.1 LANGUAGES CXX) set(CMAKE_AUTOMOC ON) set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON)#useful for config.h +include(application_info.cmake) +if(APPLE) + if(MS2_PLUGINS_LOCATION) + set(MSPLUGINS_DIR ${MS2_PLUGINS_LOCATION}) + else() + set(MSPLUGINS_DIR "Frameworks/mediastreamer2.framework/Versions/A/Libraries") + endif() +else() + set(MSPLUGINS_DIR "plugins/mediastreamer") +endif() +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake" "${CMAKE_CURRENT_BINARY_DIR}/config.h") set(LINPHONE_PACKAGES LinphoneCxx) list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules") @@ -21,8 +33,9 @@ set(APP_TARGETS ${LinphoneCxx_TARGET}) set(QT_DEFAULT_MAJOR_VERSION 6) -find_package(Qt6 REQUIRED COMPONENTS Core) -find_package(Qt6 REQUIRED COMPONENTS Quick Qml) +set(QT_PACKAGES Core Quick Qml)# Search Core at first for initialize Qt scripts for next find_packages. +#find_package(Qt6 REQUIRED COMPONENTS Core) +find_package(Qt6 REQUIRED COMPONENTS ${QT_PACKAGES}) qt6_standard_project_setup() set(_LINPHONEAPP_SOURCES main.cpp) @@ -33,6 +46,8 @@ add_subdirectory(model) add_subdirectory(view) add_subdirectory(core) + + qt6_add_executable(Linphone ${_LINPHONEAPP_SOURCES} ) @@ -45,22 +60,26 @@ qt6_add_qml_module(Linphone ) -set_target_properties(Linphone PROPERTIES +set_target_properties(${TARGET_NAME} PROPERTIES MACOSX_BUNDLE_GUI_IDENTIFIER org.linphone MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} MACOSX_BUNDLE TRUE WIN32_EXECUTABLE TRUE + OUTPUT_NAME "${EXECUTABLE_NAME}" ) +if(MSVC) + set_target_properties(${TARGET_NAME} PROPERTIES PDB_NAME "${EXECUTABLE_NAME}_app") +endif() foreach(T ${APP_TARGETS}) target_include_directories(${TARGET_NAME} SYSTEM PUBLIC $) target_link_libraries(${TARGET_NAME} PUBLIC ${T}) endforeach() - -target_link_libraries(${TARGET_NAME} - PRIVATE Qt6::Core Qt6::Quick Qt6::Qml) +foreach(T ${QT_PACKAGES}) + target_link_libraries(${TARGET_NAME} PRIVATE Qt6::${T}) +endforeach() install(TARGETS ${TARGET_NAME} BUNDLE DESTINATION . diff --git a/Linphone/application_info.cmake b/Linphone/application_info.cmake new file mode 100644 index 000000000..89f70bd0a --- /dev/null +++ b/Linphone/application_info.cmake @@ -0,0 +1,10 @@ +set(APPLICATION_DESCRIPTION "A libre SIP client") +set(APPLICATION_ID "com.belledonnecommunications.linphone") +set(APPLICATION_NAME Linphone60) +set(APPLICATION_URL "https://www.linphone.org") +set(APPLICATION_VENDOR "Belledonne Communications") +set(APPLICATION_LICENCE "GNU General Public License V3") +set(APPLICATION_LICENCE_URL "https://www.gnu.org/licenses/gpl-3.0.html") +set(APPLICATION_START_LICENCE "2010") + +set(EXECUTABLE_NAME linphone60) diff --git a/Linphone/config.h.cmake b/Linphone/config.h.cmake new file mode 100644 index 000000000..a8ce73734 --- /dev/null +++ b/Linphone/config.h.cmake @@ -0,0 +1,38 @@ +/******************************************************************************* +* config.h.cmake +* Copyright (C) 2017-2018 Belledonne Communications, Grenoble France +* +******************************************************************************** +* +* 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 2 +* 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. +* +*******************************************************************************/ + +#cmakedefine APPLICATION_DESCRIPTION "${APPLICATION_DESCRIPTION}" +#cmakedefine APPLICATION_ID "${APPLICATION_ID}" +#cmakedefine APPLICATION_NAME "${APPLICATION_NAME}" +#cmakedefine APPLICATION_VENDOR "${APPLICATION_VENDOR}" +#cmakedefine APPLICATION_URL "${APPLICATION_URL}" +#cmakedefine APPLICATION_LICENCE "${APPLICATION_LICENCE}" +#cmakedefine APPLICATION_LICENCE_URL "${APPLICATION_LICENCE_URL}" +#cmakedefine APPLICATION_SEMVER "${APPLICATION_SEMVER}" +#cmakedefine COPYRIGHT_RANGE_DATE "${COPYRIGHT_RANGE_DATE}" +#cmakedefine ENABLE_UPDATE_CHECK 1 +#cmakedefine EXECUTABLE_NAME "${EXECUTABLE_NAME}" +#cmakedefine MSPLUGINS_DIR "${MSPLUGINS_DIR}" +#cmakedefine ENABLE_APP_WEBVIEW "${ENABLE_APP_WEBVIEW}" +#cmakedefine QTKEYCHAIN_TARGET_NAME ${QTKEYCHAIN_TARGET_NAME} +#cmakedefine PDF_ENABLED + diff --git a/Linphone/core/CMakeLists.txt b/Linphone/core/CMakeLists.txt index 661d7b4ee..ad01b669b 100644 --- a/Linphone/core/CMakeLists.txt +++ b/Linphone/core/CMakeLists.txt @@ -1,5 +1,8 @@ list(APPEND _LINPHONEAPP_SOURCES core/App.cpp + core/path/Paths.cpp + core/setting/Settings.cpp + ) set(_LINPHONEAPP_SOURCES ${_LINPHONEAPP_SOURCES} PARENT_SCOPE) diff --git a/Linphone/core/path/Paths.cpp b/Linphone/core/path/Paths.cpp new file mode 100644 index 000000000..3c83cd906 --- /dev/null +++ b/Linphone/core/path/Paths.cpp @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2010-2020 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * 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, see . + */ + +#include +#include +#include +#include + +#include "config.h" + +#include "tool/Constants.hpp" + +#include "Paths.hpp" + +// ============================================================================= + +static inline bool dirPathExists (const QString &path) { + QDir dir(path); + return dir.exists(); +} +/* +static inline bool filePathExists (const QString &path, const bool& isWritable) { + QFileInfo info(path); + if (!dirPathExists(info.path())) + return false; + if( isWritable && !info.isWritable()) + return false; + QFile file(path); + return file.exists(); +} +*/ +static inline void ensureDirPathExists (const QString &path) { + QDir dir(path); + if (!dir.exists() && !dir.mkpath(path)) + qFatal("Unable to access at directory: `%s`", path.toStdString().c_str()); +} + +static inline void ensureFilePathExists (const QString &path) { + QFileInfo info(path); + ensureDirPathExists(info.path()); + + QFile file(path); + if (!file.exists() && !file.open(QIODevice::ReadWrite)) + qFatal("Unable to access at path: `%s`", path.toStdString().c_str()); +} + +static inline QString getReadableDirPath (const QString &dirname) { + return QDir::toNativeSeparators(dirname); +} + +static inline QString getWritableDirPath (const QString &dirname) { + ensureDirPathExists(dirname); + return getReadableDirPath(dirname); +} + +static inline QString getReadableFilePath (const QString &filename) { + return QDir::toNativeSeparators(filename); +} + +static inline QString getWritableFilePath (const QString &filename) { + ensureFilePathExists(filename); + return getReadableFilePath(filename); +} + +// ----------------------------------------------------------------------------- +// On Windows or Linux, the folders of the application are : +// bin/linphone +// lib/ +// lib64/ +// plugins/ +// share/ + + +// But in some cases, it can be : +// /linphone +// lib/ +// lib64/ +// share/ + +// On Mac, we have : +// Contents/ +// Frameworks/ +// MacOs/linphone +// Plugins/ +// Resources/ +// share/ + +static inline QDir getAppPackageDir () { + QDir dir(QCoreApplication::applicationDirPath()); + if (dir.dirName() == QLatin1String("MacOS")) { + dir.cdUp(); + } else if( !dir.exists("lib") && !dir.exists("lib64")){// Check if these folders are in the current path + dir.cdUp(); + if(!dir.exists("lib") && !dir.exists("lib64") && !dir.exists("plugins")) + qWarning() <<"The application's location is not correct: You have to put your 'bin/' folder next to 'lib/' or 'plugins/' folder."; + } + return dir; +} + +static inline QString getAppPackageDataDirPath() { + QDir dir = getAppPackageDir(); +#ifdef __APPLE__ + if (!dir.cd("Resources")) + { + dir.mkdir("Resources"); + dir.cd("Resources"); + } +#endif + if (!dir.cd("share")) + { + dir.mkdir("share"); + dir.cd("share"); + } + return dir.absolutePath(); +} + +static inline QString getAppPackageMsPluginsDirPath () { + QDir dir = getAppPackageDir(); + dir.cd(MSPLUGINS_DIR); + return dir.absolutePath(); +} + +static inline QString getAppPackagePluginsDirPath () { + return getAppPackageDir().absolutePath() + Constants::PathPlugins; +} + +static inline QString getAppAssistantConfigDirPath () { + return getAppPackageDataDirPath() + Constants::PathAssistantConfig; +} + +static inline QString getAppConfigFilePath () { + return QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + Constants::PathConfig; +} + +static inline QString getAppCallHistoryFilePath () { + return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + Constants::PathCallHistoryList; +} + +static inline QString getAppFactoryConfigFilePath () { + return getAppPackageDataDirPath() + Constants::PathFactoryConfig; +} + +static inline QString getAppRootCaFilePath () { + QString rootca = getAppPackageDataDirPath() + Constants::PathRootCa; + if(Paths::filePathExists(rootca)){// Packaged + return rootca; + } + return ""; +} + +static inline QString getAppFriendsFilePath () { + return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + Constants::PathFriendsList; +} + +static inline QString getAppMessageHistoryFilePath () { + return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + Constants::PathMessageHistoryList; +} + +static inline QString getAppPluginsDirPath () { + return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)+ Constants::PathPlugins; +} +// ----------------------------------------------------------------------------- + +bool Paths::filePathExists (const QString &path, const bool isWritable) { + QFileInfo info(path); + if (!dirPathExists(info.path())) + return false; + if( isWritable && !info.isWritable()) + return false; + QFile file(path); + return file.exists(); +} + + +// ----------------------------------------------------------------------------- + +QString Paths::getAppLocalDirPath () { + return getWritableDirPath(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) +"/"); +} + +QString Paths::getAssistantConfigDirPath () { + return getReadableDirPath(getAppAssistantConfigDirPath()); +} + +QString Paths::getAvatarsDirPath () { + return getWritableDirPath(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + Constants::PathAvatars); +} + +QString Paths::getCallHistoryFilePath () { + return getWritableFilePath(getAppCallHistoryFilePath()); +} + +QString Paths::getCapturesDirPath () { + return getWritableDirPath(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + Constants::PathCaptures); +} + +QString Paths::getCodecsDirPath () { + return getWritableDirPath(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + Constants::PathCodecs); +} + +QString Paths::getConfigDirPath (bool writable) { + return writable ? getWritableFilePath(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation)+QDir::separator()) : getReadableFilePath(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation)+QDir::separator()); +} + +QString Paths::getConfigFilePath (const QString &configPath, bool writable) { + QString path; + if( !configPath.isEmpty()){ + QFileInfo file(configPath); + if( !writable && (!file.exists() || !file.isFile())){// This file cannot be found. Check if it exists in standard folder + QString defaultConfigPath = getConfigDirPath(false); + file = QFileInfo(defaultConfigPath+QDir::separator()+configPath); + if( !file.exists() || !file.isFile()) + path = ""; + else + path = file.absoluteFilePath(); + }else + path = file.absoluteFilePath(); + }else + path = getAppConfigFilePath(); + return writable ? getWritableFilePath(path) : getReadableFilePath(path); +} + +QString Paths::getDatabaseFilePath (){ + return getWritableDirPath(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)) + Constants::PathDatabase; +} + +QString Paths::getFactoryConfigFilePath () { + return getReadableFilePath(getAppFactoryConfigFilePath()); +} + +QString Paths::getFriendsListFilePath () { + return getWritableFilePath(getAppFriendsFilePath()); +} + +QString Paths::getDownloadDirPath () { + return getWritableDirPath(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation) + QDir::separator()); +} + +QString Paths::getLimeDatabasePath (){ + return getWritableDirPath(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)) + Constants::PathLimeDatabase; +} + +QString Paths::getLogsDirPath () { + return getWritableDirPath(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + Constants::PathLogs); +} + +QString Paths::getMessageHistoryFilePath () { + return getReadableFilePath(getAppMessageHistoryFilePath());// No need to ensure that the file exists as this DB is deprecated +} + +QString Paths::getPackageDataDirPath () { + return getReadableDirPath(getAppPackageDataDirPath() + Constants::PathData); +} + +QString Paths::getPackageMsPluginsDirPath () { + return getReadableDirPath(getAppPackageMsPluginsDirPath()); +} + +QString Paths::getPackagePluginsAppDirPath () { + return getReadableDirPath(getAppPackagePluginsDirPath() + Constants::PathPluginsApp); +} + +QString Paths::getPackageSoundsResourcesDirPath (){ + return getReadableDirPath(getAppPackageDataDirPath() + Constants::PathSounds); +} + +QString Paths::getPackageTopDirPath (){ + return getReadableDirPath(getAppPackageDataDirPath()); +} + +QString Paths::getPluginsAppDirPath () { + return getWritableDirPath(getAppPluginsDirPath() + Constants::PathPluginsApp); +} + +QStringList Paths::getPluginsAppFolders() { + QStringList pluginPaths; + pluginPaths << Paths::getPluginsAppDirPath(); + pluginPaths << Paths::getPackagePluginsAppDirPath(); + return pluginPaths; +} + +QString Paths::getRootCaFilePath () { + return getReadableFilePath(getAppRootCaFilePath()); +} + +QString Paths::getToolsDirPath () { + return getWritableDirPath(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + Constants::PathTools); +} +QString Paths::getUserCertificatesDirPath () { + return getWritableDirPath(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + Constants::PathUserCertificates); +} + +QString Paths::getZrtpSecretsFilePath () { + return getWritableFilePath(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + Constants::PathZrtpSecrets); +} + +// ----------------------------------------------------------------------------- + +void Paths::migrate () { +} diff --git a/Linphone/core/path/Paths.hpp b/Linphone/core/path/Paths.hpp new file mode 100644 index 000000000..42fb9842f --- /dev/null +++ b/Linphone/core/path/Paths.hpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2010-2020 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * 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, see . + */ + +#ifndef PATHS_H_ +#define PATHS_H_ + +#include + +// ============================================================================= + +namespace Paths { + bool filePathExists (const QString &path, const bool isWritable = false); + + QString getAppLocalDirPath (); + QString getAssistantConfigDirPath (); + QString getAvatarsDirPath (); + QString getCallHistoryFilePath (); + QString getCapturesDirPath (); + QString getCodecsDirPath (); + QString getConfigDirPath (bool writable = true); + QString getConfigFilePath (const QString &configPath = QString(), bool writable = true); + QString getDatabaseFilePath (); + QString getDownloadDirPath (); + QString getFactoryConfigFilePath (); + QString getFriendsListFilePath (); + QString getLimeDatabasePath (); + QString getLogsDirPath (); + QString getMessageHistoryFilePath (); + QString getPackageDataDirPath (); + QString getPackageMsPluginsDirPath (); + QString getPackagePluginsAppDirPath (); + QString getPackageSoundsResourcesDirPath (); + QString getPackageTopDirPath (); + QString getPluginsAppDirPath (); + QStringList getPluginsAppFolders(); + QString getRootCaFilePath (); + QString getToolsDirPath (); + QString getUserCertificatesDirPath (); + QString getZrtpDataFilePath (); + QString getZrtpSecretsFilePath (); + + void migrate (); +} + +#endif // PATHS_H_ diff --git a/Linphone/core/setting/Settings.cpp b/Linphone/core/setting/Settings.cpp new file mode 100644 index 000000000..7826aee8c --- /dev/null +++ b/Linphone/core/setting/Settings.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2010-2020 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * 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, see . + */ + + +#include "Settings.hpp" + +#include + +#include "core/path/Paths.hpp" + + +// ============================================================================= + +Settings::Settings (QObject *parent) : QObject(parent) { +} + +Settings::~Settings() { +} + +QString Settings::getConfigPath(const QCommandLineParser &parser) { + QString filePath = parser.isSet("config") ? parser.value("config") : ""; + QString configPath; + if(!QUrl(filePath).isRelative()){ + //configPath = FileDownloader::synchronousDownload(filePath, Utils::coreStringToAppString(Paths::getConfigDirPath(false)), true)); + } + if( configPath == "") + configPath = Paths::getConfigFilePath(filePath, false); + if( configPath == "" ) + configPath = Paths::getConfigFilePath("", false); + return configPath; +} \ No newline at end of file diff --git a/Linphone/core/setting/Settings.hpp b/Linphone/core/setting/Settings.hpp new file mode 100644 index 000000000..9570ce4bb --- /dev/null +++ b/Linphone/core/setting/Settings.hpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2010-2020 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * 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, see . + */ + +#ifndef SETTINGS_H_ +#define SETTINGS_H_ + +#include +#include +#include + + +class Settings : public QObject { + Q_OBJECT +public: + Settings (QObject *parent = Q_NULLPTR); + virtual ~Settings (); + + QString getConfigPath(const QCommandLineParser &parser = QCommandLineParser()); +}; +#endif diff --git a/Linphone/model/CMakeLists.txt b/Linphone/model/CMakeLists.txt index 31ffc2d3b..7c10b9e3c 100644 --- a/Linphone/model/CMakeLists.txt +++ b/Linphone/model/CMakeLists.txt @@ -1,6 +1,8 @@ list(APPEND _LINPHONEAPP_SOURCES model/core/CoreModel.cpp model/core/CoreListener.cpp + + model/setting/SettingsModel.cpp ) set(_LINPHONEAPP_SOURCES ${_LINPHONEAPP_SOURCES} PARENT_SCOPE) diff --git a/Linphone/model/setting/SettingsModel.cpp b/Linphone/model/setting/SettingsModel.cpp new file mode 100644 index 000000000..383d2dcdd --- /dev/null +++ b/Linphone/model/setting/SettingsModel.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2010-2020 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * 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, see . + */ + + +#include "SettingsModel.hpp" + + +// ============================================================================= + +const std::string SettingsModel::UiSection("ui"); + +SettingsModel::SettingsModel (QObject *parent) : QObject(parent) { +} + +SettingsModel::~SettingsModel() { +} + + +bool SettingsModel::isReadOnly(const std::string& section, const std::string& name) const { + return mConfig->hasEntry(section, name+"/readonly"); +} + +std::string SettingsModel::getEntryFullName(const std::string& section, const std::string& name) const { + return isReadOnly(section, name)?name+"/readonly" : name; +} diff --git a/Linphone/model/setting/SettingsModel.hpp b/Linphone/model/setting/SettingsModel.hpp new file mode 100644 index 000000000..6ab059a19 --- /dev/null +++ b/Linphone/model/setting/SettingsModel.hpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2010-2020 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * 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, see . + */ + +#ifndef SETTINGS_MODEL_H_ +#define SETTINGS_MODEL_H_ + +#include +#include +#include +#include + + +class SettingsModel : public QObject { + Q_OBJECT +public: + SettingsModel (QObject *parent = Q_NULLPTR); + virtual ~SettingsModel (); + + bool isReadOnly(const std::string& section, const std::string& name) const; + std::string getEntryFullName(const std::string& section, const std::string& name) const; // Return the full name of the entry : 'name/readonly' or 'name' + + static const std::string UiSection; + + std::shared_ptr mConfig; +}; +#endif // SETTINGS_MODEL_H_ diff --git a/Linphone/tool/CMakeLists.txt b/Linphone/tool/CMakeLists.txt new file mode 100644 index 000000000..b1ba1c69b --- /dev/null +++ b/Linphone/tool/CMakeLists.txt @@ -0,0 +1,8 @@ +list(APPEND _LINPHONEAPP_SOURCES + tool/Constants.cpp + tool/Utils.cpp +) + +set(_LINPHONEAPP_SOURCES ${_LINPHONEAPP_SOURCES} PARENT_SCOPE) + + diff --git a/Linphone/tool/Constants.cpp b/Linphone/tool/Constants.cpp new file mode 100644 index 000000000..d5fa461d0 --- /dev/null +++ b/Linphone/tool/Constants.cpp @@ -0,0 +1,146 @@ +#include "Constants.hpp" + +constexpr char Constants::WindowIconPath[]; +constexpr char Constants::DefaultLocale[]; + +constexpr char Constants::LanguagePath[]; + +// The main windows of Linphone desktop. +constexpr char Constants::QmlViewMainWindow[]; +constexpr char Constants::QmlViewCallsWindow[]; +constexpr char Constants::QmlViewSettingsWindow[]; + +#ifdef ENABLE_UPDATE_CHECK +constexpr int Constants::VersionUpdateCheckInterval; +#endif // ifdef ENABLE_UPDATE_CHECK + +constexpr char Constants::MainQmlUri[]; + +constexpr char Constants::AttachVirtualWindowMethodName[]; +constexpr char Constants::AboutPath[]; + +constexpr char Constants::AssistantViewName[]; + +constexpr char Constants::ApplicationMinimalQtVersion[]; +constexpr char Constants::DefaultFont[]; +constexpr int Constants::DefaultFontPointSize; +constexpr char Constants::DefaultEmojiFont[]; +constexpr int Constants::DefaultEmojiFontPointSize; +QStringList Constants::getReactionsList(){ + return {"❤️", "👍", "😂", "😮", "😢"}; +} +constexpr char Constants::QtDomain[]; +constexpr size_t Constants::MaxLogsCollectionSize; +constexpr char Constants::SrcPattern[]; +constexpr char Constants::LinphoneLocaleEncoding[]; + +constexpr char Constants::PathAssistantConfig[]; +constexpr char Constants::PathAvatars[]; +constexpr char Constants::PathCaptures[]; +constexpr char Constants::PathCodecs[]; +constexpr char Constants::PathData[]; +constexpr char Constants::PathTools[]; +constexpr char Constants::PathLogs[]; +#ifdef APPLE +constexpr char Constants::PathPlugins[]; +#else +constexpr char Constants::PathPlugins[]; +#endif +constexpr char Constants::PathPluginsApp[]; +constexpr char Constants::PathSounds[]; +constexpr char Constants::PathUserCertificates[]; + +constexpr char Constants::PathCallHistoryList[]; +constexpr char Constants::PathConfig[]; +constexpr char Constants::PathDatabase[]; +constexpr char Constants::PathFactoryConfig[]; +constexpr char Constants::PathRootCa[]; +constexpr char Constants::PathFriendsList[]; +constexpr char Constants::PathLimeDatabase[]; +constexpr char Constants::PathMessageHistoryList[]; +constexpr char Constants::PathZrtpSecrets[]; + +// Max image size in bytes. (100Kb) +constexpr qint64 Constants::MaxImageSize; +constexpr int Constants::ThumbnailImageFileWidth; +constexpr int Constants::ThumbnailImageFileHeight; + +// In Bytes. +constexpr qint64 Constants::FileSizeLimit; + +constexpr char Constants::DefaultXmlrpcUri[]; +constexpr char Constants::DefaultUploadLogsServer[]; +constexpr char Constants::DefaultConferenceURI[]; +constexpr char Constants::DefaultVideoConferenceURI[]; +constexpr char Constants::DefaultLimeServerURL[]; +constexpr char Constants::DefaultFlexiAPIURL[]; +constexpr char Constants::RemoteProvisioningURL[]; +constexpr char Constants::DefaultAssistantRegistrationUrl[]; +constexpr char Constants::DefaultAssistantLoginUrl[]; +constexpr char Constants::DefaultAssistantLogoutUrl[]; + +constexpr char Constants::RemoteProvisioningBasicAuth[]; +constexpr char Constants::OAuth2AuthorizationUrl[]; +constexpr char Constants::OAuth2AccessTokenUrl[]; +constexpr char Constants::OAuth2RedirectUri[]; +constexpr char Constants::OAuth2Identifier[]; +constexpr char Constants::OAuth2Password[]; +constexpr char Constants::OAuth2Scope[]; +constexpr char Constants::DefaultOAuth2RemoteProvisioningHeader[]; + + + +#if defined(Q_OS_LINUX) || defined(Q_OS_WIN) +constexpr char Constants::H264Description[]; +#endif // if defined(Q_OS_LINUX) || defined(Q_OS_WIN) + +#ifdef Q_OS_LINUX +constexpr char Constants::LibraryExtension[]; +constexpr char Constants::H264InstallName[]; +#ifdef Q_PROCESSOR_X86_64 +constexpr char Constants::PluginUrlH264[]; +constexpr char Constants::PluginH264Check[]; +#else +constexpr char Constants::PluginUrlH264[]; +constexpr char Constants::PluginH264Check[]; +#endif // ifdef Q_PROCESSOR_X86_64 +#elif defined(Q_OS_WIN) +constexpr char Constants::LibraryExtension[]; +constexpr char Constants::H264InstallName[]; +#ifdef Q_OS_WIN64 +constexpr char Constants::PluginUrlH264[]; +constexpr char Constants::PluginH264Check[]; +#else +constexpr char Constants::PluginUrlH264[]; +constexpr char Constants::PluginH264Check[]; +#endif // ifdef Q_OS_WIN64 +#endif // ifdef Q_OS_LINUX +constexpr char Constants::VcardScheme[]; + +constexpr int Constants::CbsCallInterval; + +constexpr char Constants::RcVersionName[]; +constexpr int Constants::RcVersionCurrent; + +// TODO: Remove hardcoded values. Use config directly. +constexpr char Constants::LinphoneDomain[]; +constexpr char Constants::DefaultContactParameters[]; +constexpr char Constants::DefaultContactParametersOnRemove[]; +constexpr int Constants::DefaultExpires; +constexpr int Constants::DefaultPublishExpires; +constexpr char Constants::DownloadUrl[]; +constexpr char Constants::VersionCheckReleaseUrl[]; +constexpr char Constants::VersionCheckNightlyUrl[]; +constexpr char Constants::PasswordRecoveryUrl[]; +constexpr char Constants::CguUrl[]; +constexpr char Constants::PrivatePolicyUrl[]; +constexpr char Constants::ContactUrl[]; +constexpr char Constants::TranslationUrl[]; + +constexpr int Constants::MaxMosaicParticipants; + +constexpr char Constants::LinphoneBZip2_exe[]; +constexpr char Constants::LinphoneBZip2_dll[]; +constexpr char Constants::DefaultRlsUri[]; +constexpr char Constants::DefaultLogsEmail[]; + diff --git a/Linphone/tool/Constants.hpp b/Linphone/tool/Constants.hpp new file mode 100644 index 000000000..25cb2a5a6 --- /dev/null +++ b/Linphone/tool/Constants.hpp @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2021 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * 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, see . + */ + +#ifndef CONSTANTS_H_ +#define CONSTANTS_H_ + +#include +#include +#include + +#include "config.h" + +// ============================================================================= + +class Constants : public QObject{ + Q_OBJECT +public: + Constants(QObject * parent = nullptr) : QObject(parent){} + + //---------------------------------------------------------------------------------- + + static constexpr char DefaultLocale[] = "en"; + static constexpr char DefaultFont[] = "Noto Sans"; + static constexpr int DefaultFontPointSize = 10; +#ifdef __APPLE__ + static constexpr char DefaultEmojiFont[] = "Apple Color Emoji"; +#else + static constexpr char DefaultEmojiFont[] = "Noto Color Emoji"; +#endif + static constexpr int DefaultEmojiFontPointSize = 10; + static QStringList getReactionsList(); + + static constexpr size_t MaxLogsCollectionSize = 10485760*5; // 50MB. + +#ifdef ENABLE_UPDATE_CHECK + static constexpr int VersionUpdateCheckInterval = 86400000; // 24 hours in milliseconds. +#endif // ifdef ENABLE_UPDATE_CHECK + + static constexpr char DefaultXmlrpcUri[] = "https://subscribe.linphone.org:444/wizard.php"; + static constexpr char DefaultUploadLogsServer[] = "https://www.linphone.org:444/lft.php"; + static constexpr char DefaultContactParameters[] = "message-expires=2419200"; + static constexpr char DefaultContactParametersOnRemove[] = "message-expires=0"; + static constexpr int DefaultExpires = 600; + static constexpr int DefaultPublishExpires = 120; + static constexpr char DownloadUrl[] = "https://www.linphone.org/technical-corner/linphone"; + static constexpr char VersionCheckReleaseUrl[] = "https://linphone.org/releases"; + static constexpr char VersionCheckNightlyUrl[] = "https://linphone.org/snapshots"; + static constexpr char PasswordRecoveryUrl[] = "https://subscribe.linphone.org/login/email"; + static constexpr char CguUrl[] = "https://www.linphone.org/general-terms"; + static constexpr char PrivatePolicyUrl[] = "https://www.linphone.org/privacy-policy"; + static constexpr char ContactUrl[] = "https://www.linphone.org/contact"; + static constexpr char TranslationUrl[] = "https://weblate.linphone.org/projects/linphone-desktop/"; + + static constexpr int MaxMosaicParticipants = 6;// From 7, the mosaic quality will be limited to avoid useless computations + + static constexpr char LinphoneBZip2_exe[] = "https://www.linphone.org/releases/windows/tools/bzip2/bzip2.exe"; + static constexpr char LinphoneBZip2_dll[] = "https://www.linphone.org/releases/windows/tools/bzip2/bzip2.dll"; + static constexpr char DefaultRlsUri[] = "sips:rls@sip.linphone.org"; + static constexpr char DefaultLogsEmail[] = "linphone-desktop@belledonne-communications.com"; + + static constexpr char DefaultFlexiAPIURL[] = "https://subscribe.linphone.org/api/";// Need "/" at the end + static constexpr char RemoteProvisioningURL[] = "https://subscribe.linphone.org/api/provisioning"; + static constexpr char RemoteProvisioningBasicAuth[] = ""; +// OAuth2 settings + static constexpr char OAuth2AuthorizationUrl[] = ""; + static constexpr char OAuth2AccessTokenUrl[] = ""; + static constexpr char OAuth2RedirectUri[] = ""; + static constexpr char OAuth2Identifier[] = ""; + static constexpr char OAuth2Password[] = ""; + static constexpr char OAuth2Scope[] = ""; + static constexpr char DefaultOAuth2RemoteProvisioningHeader[] = "x-linphone-oauth2-token"; + + + Q_PROPERTY(QString PasswordRecoveryUrl MEMBER PasswordRecoveryUrl CONSTANT) + Q_PROPERTY(QString CguUrl MEMBER CguUrl CONSTANT) + Q_PROPERTY(QString PrivatePolicyUrl MEMBER PrivatePolicyUrl CONSTANT) + Q_PROPERTY(QString ContactUrl MEMBER ContactUrl CONSTANT) + Q_PROPERTY(QString TranslationUrl MEMBER TranslationUrl CONSTANT) + Q_PROPERTY(int maxMosaicParticipants MEMBER MaxMosaicParticipants CONSTANT) + Q_PROPERTY(QStringList reactionsList READ getReactionsList CONSTANT) + +// For Webviews + static constexpr char DefaultAssistantRegistrationUrl[] = "https://subscribe.linphone.org/register"; + static constexpr char DefaultAssistantLoginUrl[] = "https://subscribe.linphone.org/login"; + static constexpr char DefaultAssistantLogoutUrl[] = "https://subscribe.linphone.org/logout"; +//-------------- + + // Max image size in bytes. (1Mb) + static constexpr qint64 MaxImageSize = 1024000;// In Bytes. + static constexpr qint64 FileSizeLimit = 524288000;// In Bytes. + static constexpr int ThumbnailImageFileWidth = 100; + static constexpr int ThumbnailImageFileHeight = 100; + +//-------------------------------------------------------------------------------- +// LINPHONE +//-------------------------------------------------------------------------------- + + static constexpr char LinphoneDomain[] = "sip.linphone.org"; // Use for checking if config are a Linphone + static constexpr char WindowIconPath[] = ":/assets/images/linphone_logo.svg"; + static constexpr char ApplicationMinimalQtVersion[] = "5.10.0"; + static constexpr char DefaultConferenceURI[] = "sip:conference-factory@sip.linphone.org"; // Default for a Linphone account + static constexpr char DefaultVideoConferenceURI[] = "sip:videoconference-factory@sip.linphone.org"; // Default for a Linphone account + static constexpr char DefaultLimeServerURL[] = "https://lime.linphone.org/lime-server/lime-server.php"; // Default for a Linphone account + + static constexpr char PathAssistantConfig[] = "/" EXECUTABLE_NAME "/assistant/"; + static constexpr char PathAvatars[] = "/avatars/"; + static constexpr char PathCaptures[] = "/" EXECUTABLE_NAME "/captures/"; + static constexpr char PathCodecs[] = "/codecs/"; + static constexpr char PathData[] = "/" EXECUTABLE_NAME; + static constexpr char PathTools[] = "/tools/"; + static constexpr char PathLogs[] = "/logs/"; +#ifdef APPLE + static constexpr char PathPlugins[] = "/Plugins/"; +#else + static constexpr char PathPlugins[] = "/plugins/"; +#endif + static constexpr char PathPluginsApp[] = "app/"; + static constexpr char PathSounds[] = "/sounds/" EXECUTABLE_NAME; + static constexpr char PathUserCertificates[] = "/usr-crt/"; + + static constexpr char PathCallHistoryList[] = "/call-history.db"; + static constexpr char PathConfig[] = "/linphonerc"; + static constexpr char PathDatabase[] = "/linphone.db"; + static constexpr char PathFactoryConfig[] = "/" EXECUTABLE_NAME "/linphonerc-factory"; + static constexpr char PathRootCa[] = "/" EXECUTABLE_NAME "/rootca.pem"; + static constexpr char PathFriendsList[] = "/friends.db"; + static constexpr char PathLimeDatabase[] = "/x3dh.c25519.sqlite3"; + static constexpr char PathMessageHistoryList[] = "/message-history.db"; + static constexpr char PathZrtpSecrets[] = "/zidcache"; + + static constexpr char LanguagePath[] = ":/languages/"; + + // The main windows of Linphone desktop. + static constexpr char QmlViewMainWindow[] = "qrc:/ui/views/App/Main/MainWindow.qml"; + static constexpr char QmlViewCallsWindow[] = "qrc:/ui/views/App/Calls/CallsWindow.qml"; + static constexpr char QmlViewSettingsWindow[] = "qrc:/ui/views/App/Settings/SettingsWindow.qml"; + + static constexpr char MainQmlUri[] = "Linphone"; + + static constexpr char AttachVirtualWindowMethodName[] = "attachVirtualWindow"; + static constexpr char AboutPath[] = "qrc:/ui/views/App/Main/Dialogs/About.qml"; + + static constexpr char AssistantViewName[] = "Assistant"; + + static constexpr char QtDomain[] = "qt"; + static constexpr char SrcPattern[] = "/src/"; + static constexpr char LinphoneLocaleEncoding[] = "UTF-8";// Alternative is to use "locale" + static constexpr char VcardScheme[] = EXECUTABLE_NAME "-desktop:/"; + static constexpr int CbsCallInterval = 20; + static constexpr char RcVersionName[] = "rc_version"; + static constexpr int RcVersionCurrent = 6; // 2 = Conference URI + // 3 = CPIM on basic chat rooms + // 4 = RTP bundle mode + // 5 = Video Conference URI + // 6 = Publish expires +//-------------------------------------------------------------------------------- +// CISCO +//-------------------------------------------------------------------------------- +#if defined(Q_OS_LINUX) || defined(Q_OS_WIN) + static constexpr char H264Description[] = "Provided by CISCO SYSTEM,INC"; +#endif // if defined(Q_OS_LINUX) || defined(Q_OS_WIN) + +#ifdef Q_OS_LINUX + static constexpr char LibraryExtension[] = "so"; + static constexpr char H264InstallName[] = "libopenh264.so"; +#ifdef Q_PROCESSOR_X86_64 + static constexpr char PluginUrlH264[] = "http://ciscobinary.openh264.org/libopenh264-2.2.0-linux64.6.so.bz2"; + static constexpr char PluginH264Check[] = "45ba1aaeb6213c19cd9622b79788e16b05beabc4d16a3a74e57f046a0826fd77"; +#else + static constexpr char PluginUrlH264[] = "http://ciscobinary.openh264.org/libopenh264-2.2.0-linux32.6.so.bz2"; + static constexpr char PluginH264Check[] = "bf18e0e79c4a23018b0ea5ad6d7dd14fd1b6a6189d2f88fd56dece019fc415c8"; +#endif // ifdef Q_PROCESSOR_X86_64 +#elif defined(Q_OS_WIN) + static constexpr char LibraryExtension[] = "dll"; + static constexpr char H264InstallName[] = "openh264.dll"; +#ifdef Q_OS_WIN64 + static constexpr char PluginUrlH264[] = "http://ciscobinary.openh264.org/openh264-2.2.0-win64.dll.bz2"; + static constexpr char PluginH264Check[] = "799e08c418b6cdeadfbe18d027392158face4a5c901d41f83712a20f0d41ad7d"; +#else + static constexpr char PluginUrlH264[] = "http://ciscobinary.openh264.org/openh264-2.2.0-win32.dll.bz2"; + static constexpr char PluginH264Check[] = "2205097a3a309271e15879b25a905eb290cfdd7fd7a8a0c1037e0458e5dc1f21"; +#endif // ifdef Q_OS_WIN64 +#endif // ifdef Q_OS_LINUX + +//-------------------------------------------------------------------------------- +}; + +#endif diff --git a/Linphone/tool/Utils.cpp b/Linphone/tool/Utils.cpp new file mode 100644 index 000000000..7d6697ac0 --- /dev/null +++ b/Linphone/tool/Utils.cpp @@ -0,0 +1,935 @@ +/* + * Copyright (c) 2010-2020 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * 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, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" + +#ifdef PDF_ENABLED +#include +#include +#include "components/pdf/PdfWidget.hpp" +#endif + + +#include "Utils.hpp" +#include "UriTools.hpp" +#include "app/App.hpp" +#include "app/paths/Paths.hpp" +#include "app/providers/ImageProvider.hpp" +#include "components/core/CoreManager.hpp" +#include "components/other/colors/ColorListModel.hpp" +#include "components/other/colors/ColorModel.hpp" +#include "components/other/date/DateModel.hpp" +#include "components/contacts/ContactsListModel.hpp" +#include "components/contact/ContactModel.hpp" +#include "components/contact/VcardModel.hpp" +#include "components/settings/AccountSettingsModel.hpp" +#include "components/settings/SettingsModel.hpp" +#include "components/sip-addresses/SipAddressesModel.hpp" + + +#ifdef _WIN32 +#include +#endif + +// ============================================================================= +/* +namespace { +constexpr int SafeFilePathLimit = 100; + +} + +std::shared_ptr Utils::interpretUrl(const QString& address){ + bool usePrefix = CoreManager::getInstance()->getAccountSettingsModel()->getUseInternationalPrefixForCallsAndChats(); + auto interpretedAddress = CoreManager::getInstance()->getCore()->interpretUrl(Utils::appStringToCoreString(address), usePrefix); + if(!interpretedAddress){// Try by removing scheme. + QStringList splitted = address.split(":"); + if(splitted.size() > 0 && splitted[0] == "sip"){ + splitted.removeFirst(); + interpretedAddress = CoreManager::getInstance()->getCore()->interpretUrl(Utils::appStringToCoreString(splitted.join(":")), usePrefix); + } + } + return interpretedAddress; +} +char *Utils::rstrstr (const char *a, const char *b) { + size_t a_len = strlen(a); + size_t b_len = strlen(b); + + if (b_len > a_len) + return nullptr; + + for (const char *s = a + a_len - b_len; s >= a; --s) { + if (!strncmp(s, b, b_len)) + return const_cast(s); + } + + return nullptr; +} + +// ----------------------------------------------------------------------------- + +bool Utils::hasCapability(const QString& address, const LinphoneEnums::FriendCapability& capability, bool defaultCapability){ + auto addressCleaned = cleanSipAddress(address); + auto contact = CoreManager::getInstance()->getContactsListModel()->findContactModelFromSipAddress(addressCleaned); + if(contact) + return contact->hasCapability(capability); + else + return defaultCapability; +} + +//-------------------------------------------------------------------------------------- + +QDateTime Utils::addMinutes(QDateTime date, const int& min){ + return date.addSecs(min*60); +} + +QDateTime Utils::getOffsettedUTC(const QDateTime& date){ + QDateTime utc = date.toUTC();// Get a date free of any offsets. + auto timezone = date.timeZone(); + utc = utc.addSecs(timezone.offsetFromUtc(date));// add offset from date timezone + utc.setTimeSpec(Qt::OffsetFromUTC);// ensure to have an UTC date + return utc; +} + +QString Utils::toDateTimeString(QDateTime date, const QString& format){ + if(date.date() == QDate::currentDate()) + return toTimeString(date); + else{ + return getOffsettedUTC(date).toString(format); + } +} + +QString Utils::toTimeString(QDateTime date, const QString& format){ +// Issue : date.toString() will not print the good time in timezones. Get it from date and add ourself the offset. + return getOffsettedUTC(date).toString(format); +} + +QString Utils::toDateString(QDateTime date, const QString& format){ + return QLocale().toString(getOffsettedUTC(date), (!format.isEmpty() ? format : QLocale().dateFormat()) ); +} + +QString Utils::toDateString(QDate date, const QString& format){ + return QLocale().toString(date, (!format.isEmpty() ? format : QLocale().dateFormat()) ); +} + +// Return custom address to be displayed on UI. +// In order to return only the username and to remove all domains from the GUI, you may just change the default mode. +QString Utils::toDisplayString(const QString& str, SipDisplayMode displayMode){ + if(displayMode == SIP_DISPLAY_ALL) return str; + std::shared_ptr addr = linphone::Factory::get()->createAddress(str.toStdString()); + QString displayString; + if( addr && ( (displayMode & SIP_DISPLAY_USERNAME) == SIP_DISPLAY_USERNAME)) + displayString = Utils::coreStringToAppString(addr->getUsername()); + if(displayString.isEmpty()) + return str; + else + return displayString; +} + +QDate Utils::getCurrentDate() { + return QDate::currentDate(); +} + +DateModel* Utils::getCurrentDateModel() { + return new DateModel(QDate::currentDate()); +} + +QDate Utils::getMinDate() { + return QDate(1,1,1); +} +DateModel* Utils::getMinDateModel() { + return new DateModel(QDate(1,1,1)); +} +QDate Utils::toDate(const QString& str, const QString& format) { + return QDate::fromString(str, format); +} +DateModel* Utils::toDateModel(const QString& str, const QString& format) { + return new DateModel(toDate(str, format)); +} +QDate Utils::getDate(int year, int month, int day) { + auto d = QDate(year, month, day); + if(!d.isValid() ){ + auto first = QDate(year, month, 1); + if(first.isValid()) { + d = first.addDays(day-1); + } + } + return d; +} + +DateModel* Utils::getDateModel(int year, int month, int day) { + auto d = QDate(year, month, day); + if(!d.isValid() ){ + auto first = QDate(year, month, 1); + if(first.isValid()) { + d = first.addDays(day-1); + } + } + return new DateModel(d); +} + +int Utils::getFullYear(const QDate& date) { + return date.year(); +} + +int Utils::getMonth(const QDate& date) { + return date.month(); +} + +int Utils::getDay(const QDate& date) { + return date.day(); +} + +int Utils::getDayOfWeek(const QDate& date) { + return date.dayOfWeek(); +} + +bool Utils::equals(const QDate& d1, const QDate& d2){ + return d1 == d2; +} + +bool Utils::isGreatherThan(const QDate& d1, const QDate& d2) { + return d1 >= d2; +} + +//-------------------------------------------------------------------------------------- + +QString Utils::getDisplayName(const QString& address){ + QString displayName = getDisplayName(interpretUrl(address)); + return displayName.isEmpty() ? address : displayName; +} + +QString Utils::getInitials(const QString& username){ + if(username.isEmpty()) return ""; + + QRegularExpression regex("[\\s\\.]+"); + QStringList words = username.split(regex);// Qt 5.14: Qt::SkipEmptyParts + QStringList initials; + auto str32 = words[0].toStdU32String(); + std::u32string char32; + char32 += str32[0]; + initials << QString::fromStdU32String(char32); + for(int i = 1; i < words.size() && initials.size() <= 1 ; ++i) { + if( words[i].size() > 0){ + str32 = words[i].toStdU32String(); + char32[0] = str32[0]; + initials << QString::fromStdU32String(char32); + } + } + return App::getInstance()->getLocale().toUpper(initials.join("")); +} + +QString Utils::toString(const LinphoneEnums::TunnelMode& mode){ + switch(mode){ + case LinphoneEnums::TunnelMode::TunnelModeEnable : + //: 'Enable' : One word for button action to enable tunnel mode. + return QObject::tr("LinphoneEnums_TunnelModeEnable"); + case LinphoneEnums::TunnelMode::TunnelModeDisable : + //: 'Disable' : One word for button action to disable tunnel mode. + return QObject::tr("LinphoneEnums_TunnelModeDisable"); + case LinphoneEnums::TunnelMode::TunnelModeAuto : + //: 'Auto' : One word for button action to set the auto tunnel mode. + return QObject::tr("LinphoneEnums_TunnelModeAuto"); + default: + return ""; + } +} + +QImage Utils::getImage(const QString &pUri) { + QImage image(pUri); + QImageReader reader(pUri); + reader.setAutoTransform(true); + if(image.isNull()){// Try to determine format from headers instead of using suffix + reader.setDecideFormatFromContent(true); + } + return reader.read(); +} +QString Utils::getSafeFilePath (const QString &filePath, bool *soFarSoGood) { + if (soFarSoGood) + *soFarSoGood = true; + + QFileInfo info(filePath); + if (!info.exists()) + return filePath; + + const QString prefix = QStringLiteral("%1/%2").arg(info.absolutePath()).arg(info.baseName()); + const QString ext = info.completeSuffix(); + + for (int i = 1; i < SafeFilePathLimit; ++i) { + QString safePath = QStringLiteral("%1 (%3).%4").arg(prefix).arg(i).arg(ext); + if (!QFileInfo::exists(safePath)) + return safePath; + } + + if (soFarSoGood) + *soFarSoGood = false; + + return QString(""); +} +std::shared_ptr Utils::getMatchingLocalAddress(std::shared_ptr p_localAddress){ + QVector > addresses; + // Get default account + addresses.push_back(CoreManager::getInstance()->getCore()->createPrimaryContactParsed()); + auto accounts = CoreManager::getInstance()->getAccountList(); + foreach(auto account, accounts) + addresses.push_back(account->getParams()->getIdentityAddress()->clone()); + foreach(auto address, addresses){ + if( address->getUsername() == p_localAddress->getUsername() && address->getDomain() == p_localAddress->getDomain()) + return address; + } + return p_localAddress; +} +// Return at most : sip:username@domain +QString Utils::cleanSipAddress (const QString &sipAddress) { + std::shared_ptr addr = linphone::Factory::get()->createAddress(sipAddress.toStdString()); + if( addr) { + addr->clean(); + QStringList fields = Utils::coreStringToAppString(addr->asStringUriOnly()).split('@'); + if(fields.size() > 0){// maybe useless but it's just to be sure to have a domain + fields.removeLast(); + QString domain = Utils::coreStringToAppString(addr->getDomain()); + if( domain.count(':')>1) + fields.append('['+domain+']'); + else + fields.append(domain); + return fields.join('@'); + } + } + return sipAddress; +} +// Data to retrieve WIN32 process +#ifdef _WIN32 +#include +struct EnumData { + DWORD dwProcessId; + HWND hWnd; +}; +// Application-defined callback for EnumWindows +BOOL CALLBACK EnumProc(HWND hWnd, LPARAM lParam) { + // Retrieve storage location for communication data + EnumData& ed = *(EnumData*)lParam; + DWORD dwProcessId = 0x0; + // Query process ID for hWnd + GetWindowThreadProcessId(hWnd, &dwProcessId); + // Apply filter - if you want to implement additional restrictions, + // this is the place to do so. + if (ed.dwProcessId == dwProcessId) { + // Found a window matching the process ID + ed.hWnd = hWnd; + // Report success + SetLastError(ERROR_SUCCESS); + // Stop enumeration + return FALSE; + } + // Continue enumeration + return TRUE; +} +// Main entry +HWND FindWindowFromProcessId(DWORD dwProcessId) { + EnumData ed = { dwProcessId }; + if (!EnumWindows(EnumProc, (LPARAM)&ed) && + (GetLastError() == ERROR_SUCCESS)) { + return ed.hWnd; + } + return NULL; +} + +// Helper method for convenience +HWND FindWindowFromProcess(HANDLE hProcess) { + return FindWindowFromProcessId(GetProcessId(hProcess)); +} +#endif + +bool Utils::processExists(const quint64& p_processId) +{ +#ifdef _WIN32 + return FindWindowFromProcessId(p_processId) != NULL; +#else + return true; +#endif +} +QString Utils::getCountryName(const QLocale::Country& p_country) +{ + QString countryName; + switch(p_country) + { + case QLocale::Afghanistan: if((countryName = QCoreApplication::translate("country", "Afghanistan"))== "Afghanistan") countryName = "";break; + case QLocale::Albania: if((countryName = QCoreApplication::translate("country", "Albania"))== "Albania") countryName = "";break; + case QLocale::Algeria: if((countryName = QCoreApplication::translate("country", "Algeria"))== "Algeria") countryName = "";break; + case QLocale::AmericanSamoa: if((countryName = QCoreApplication::translate("country", "AmericanSamoa"))== "AmericanSamoa") countryName = "";break; + case QLocale::Andorra: if((countryName = QCoreApplication::translate("country", "Andorra"))== "Andorra") countryName = "";break; + case QLocale::Angola: if((countryName = QCoreApplication::translate("country", "Angola"))== "Angola") countryName = "";break; + case QLocale::Anguilla: if((countryName = QCoreApplication::translate("country", "Anguilla"))== "Anguilla") countryName = "";break; + case QLocale::AntiguaAndBarbuda: if((countryName = QCoreApplication::translate("country", "AntiguaAndBarbuda"))== "AntiguaAndBarbuda") countryName = "";break; + case QLocale::Argentina: if((countryName = QCoreApplication::translate("country", "Argentina"))== "Argentina") countryName = "";break; + case QLocale::Armenia: if((countryName = QCoreApplication::translate("country", "Armenia"))== "Armenia") countryName = "";break; + case QLocale::Aruba: if((countryName = QCoreApplication::translate("country", "Aruba"))== "Aruba") countryName = "";break; + case QLocale::Australia: if((countryName = QCoreApplication::translate("country", "Australia"))== "Australia") countryName = "";break; + case QLocale::Austria: if((countryName = QCoreApplication::translate("country", "Austria"))== "Austria") countryName = "";break; + case QLocale::Azerbaijan: if((countryName = QCoreApplication::translate("country", "Azerbaijan"))== "Azerbaijan") countryName = "";break; + case QLocale::Bahamas: if((countryName = QCoreApplication::translate("country", "Bahamas"))== "Bahamas") countryName = "";break; + case QLocale::Bahrain: if((countryName = QCoreApplication::translate("country", "Bahrain"))== "Bahrain") countryName = "";break; + case QLocale::Bangladesh: if((countryName = QCoreApplication::translate("country", "Bangladesh"))== "Bangladesh") countryName = "";break; + case QLocale::Barbados: if((countryName = QCoreApplication::translate("country", "Barbados"))== "Barbados") countryName = "";break; + case QLocale::Belarus: if((countryName = QCoreApplication::translate("country", "Belarus"))== "Belarus") countryName = "";break; + case QLocale::Belgium: if((countryName = QCoreApplication::translate("country", "Belgium"))== "Belgium") countryName = "";break; + case QLocale::Belize: if((countryName = QCoreApplication::translate("country", "Belize"))== "Belize") countryName = "";break; + case QLocale::Benin: if((countryName = QCoreApplication::translate("country", "Benin"))== "Benin") countryName = "";break; + case QLocale::Bermuda: if((countryName = QCoreApplication::translate("country", "Bermuda"))== "Bermuda") countryName = "";break; + case QLocale::Bhutan: if((countryName = QCoreApplication::translate("country", "Bhutan"))== "Bhutan") countryName = "";break; + case QLocale::Bolivia: if((countryName = QCoreApplication::translate("country", "Bolivia"))== "Bolivia") countryName = "";break; + case QLocale::BosniaAndHerzegowina: if((countryName = QCoreApplication::translate("country", "BosniaAndHerzegowina"))== "BosniaAndHerzegowina") countryName = "";break; + case QLocale::Botswana: if((countryName = QCoreApplication::translate("country", "Botswana"))== "Botswana") countryName = "";break; + case QLocale::Brazil: if((countryName = QCoreApplication::translate("country", "Brazil"))== "Brazil") countryName = "";break; + case QLocale::Brunei: if((countryName = QCoreApplication::translate("country", "Brunei"))== "Brunei") countryName = "";break; + case QLocale::Bulgaria: if((countryName = QCoreApplication::translate("country", "Bulgaria"))== "Bulgaria") countryName = "";break; + case QLocale::BurkinaFaso: if((countryName = QCoreApplication::translate("country", "BurkinaFaso"))== "BurkinaFaso") countryName = "";break; + case QLocale::Burundi: if((countryName = QCoreApplication::translate("country", "Burundi"))== "Burundi") countryName = "";break; + case QLocale::Cambodia: if((countryName = QCoreApplication::translate("country", "Cambodia"))== "Cambodia") countryName = "";break; + case QLocale::Cameroon: if((countryName = QCoreApplication::translate("country", "Cameroon"))== "Cameroon") countryName = "";break; + case QLocale::Canada: if((countryName = QCoreApplication::translate("country", "Canada"))== "Canada") countryName = "";break; + case QLocale::CapeVerde: if((countryName = QCoreApplication::translate("country", "CapeVerde"))== "CapeVerde") countryName = "";break; + case QLocale::CaymanIslands: if((countryName = QCoreApplication::translate("country", "CaymanIslands"))== "CaymanIslands") countryName = "";break; + case QLocale::CentralAfricanRepublic: if((countryName = QCoreApplication::translate("country", "CentralAfricanRepublic"))== "CentralAfricanRepublic") countryName = "";break; + case QLocale::Chad: if((countryName = QCoreApplication::translate("country", "Chad"))== "Chad") countryName = "";break; + case QLocale::Chile: if((countryName = QCoreApplication::translate("country", "Chile"))== "Chile") countryName = "";break; + case QLocale::China: if((countryName = QCoreApplication::translate("country", "China"))== "China") countryName = "";break; + case QLocale::Colombia: if((countryName = QCoreApplication::translate("country", "Colombia"))== "Colombia") countryName = "";break; + case QLocale::Comoros: if((countryName = QCoreApplication::translate("country", "Comoros"))== "Comoros") countryName = "";break; + case QLocale::PeoplesRepublicOfCongo: if((countryName = QCoreApplication::translate("country", "PeoplesRepublicOfCongo"))== "PeoplesRepublicOfCongo") countryName = "";break; + case QLocale::DemocraticRepublicOfCongo: if((countryName = QCoreApplication::translate("country", "DemocraticRepublicOfCongo"))== "DemocraticRepublicOfCongo") countryName = "";break; + case QLocale::CookIslands: if((countryName = QCoreApplication::translate("country", "CookIslands"))== "CookIslands") countryName = "";break; + case QLocale::CostaRica: if((countryName = QCoreApplication::translate("country", "CostaRica"))== "CostaRica") countryName = "";break; + case QLocale::IvoryCoast: if((countryName = QCoreApplication::translate("country", "IvoryCoast"))== "IvoryCoast") countryName = "";break; + case QLocale::Croatia: if((countryName = QCoreApplication::translate("country", "Croatia"))== "Croatia") countryName = "";break; + case QLocale::Cuba: if((countryName = QCoreApplication::translate("country", "Cuba"))== "Cuba") countryName = "";break; + case QLocale::Cyprus: if((countryName = QCoreApplication::translate("country", "Cyprus"))== "Cyprus") countryName = "";break; + case QLocale::CzechRepublic: if((countryName = QCoreApplication::translate("country", "CzechRepublic"))== "CzechRepublic") countryName = "";break; + case QLocale::Denmark: if((countryName = QCoreApplication::translate("country", "Denmark"))== "Denmark") countryName = "";break; + case QLocale::Djibouti: if((countryName = QCoreApplication::translate("country", "Djibouti"))== "Djibouti") countryName = "";break; + case QLocale::Dominica: if((countryName = QCoreApplication::translate("country", "Dominica"))== "Dominica") countryName = "";break; + case QLocale::DominicanRepublic: if((countryName = QCoreApplication::translate("country", "DominicanRepublic"))== "DominicanRepublic") countryName = "";break; + case QLocale::Ecuador: if((countryName = QCoreApplication::translate("country", "Ecuador"))== "Ecuador") countryName = "";break; + case QLocale::Egypt: if((countryName = QCoreApplication::translate("country", "Egypt"))== "Egypt") countryName = "";break; + case QLocale::ElSalvador: if((countryName = QCoreApplication::translate("country", "ElSalvador"))== "ElSalvador") countryName = "";break; + case QLocale::EquatorialGuinea: if((countryName = QCoreApplication::translate("country", "EquatorialGuinea"))== "EquatorialGuinea") countryName = "";break; + case QLocale::Eritrea: if((countryName = QCoreApplication::translate("country", "Eritrea"))== "Eritrea") countryName = "";break; + case QLocale::Estonia: if((countryName = QCoreApplication::translate("country", "Estonia"))== "Estonia") countryName = "";break; + case QLocale::Ethiopia: if((countryName = QCoreApplication::translate("country", "Ethiopia"))== "Ethiopia") countryName = "";break; + case QLocale::FalklandIslands: if((countryName = QCoreApplication::translate("country", "FalklandIslands"))== "FalklandIslands") countryName = "";break; + case QLocale::FaroeIslands: if((countryName = QCoreApplication::translate("country", "FaroeIslands"))== "FaroeIslands") countryName = "";break; + case QLocale::Fiji: if((countryName = QCoreApplication::translate("country", "Fiji"))== "Fiji") countryName = "";break; + case QLocale::Finland: if((countryName = QCoreApplication::translate("country", "Finland"))== "Finland") countryName = "";break; + case QLocale::France: if((countryName = QCoreApplication::translate("country", "France"))== "France") countryName = "";break; + case QLocale::FrenchGuiana: if((countryName = QCoreApplication::translate("country", "FrenchGuiana"))== "FrenchGuiana") countryName = "";break; + case QLocale::FrenchPolynesia: if((countryName = QCoreApplication::translate("country", "FrenchPolynesia"))== "FrenchPolynesia") countryName = "";break; + case QLocale::Gabon: if((countryName = QCoreApplication::translate("country", "Gabon"))== "Gabon") countryName = "";break; + case QLocale::Gambia: if((countryName = QCoreApplication::translate("country", "Gambia"))== "Gambia") countryName = "";break; + case QLocale::Georgia: if((countryName = QCoreApplication::translate("country", "Georgia"))== "Georgia") countryName = "";break; + case QLocale::Germany: if((countryName = QCoreApplication::translate("country", "Germany"))== "Germany") countryName = "";break; + case QLocale::Ghana: if((countryName = QCoreApplication::translate("country", "Ghana"))== "Ghana") countryName = "";break; + case QLocale::Gibraltar: if((countryName = QCoreApplication::translate("country", "Gibraltar"))== "Gibraltar") countryName = "";break; + case QLocale::Greece: if((countryName = QCoreApplication::translate("country", "Greece"))== "Greece") countryName = "";break; + case QLocale::Greenland: if((countryName = QCoreApplication::translate("country", "Greenland"))== "Greenland") countryName = "";break; + case QLocale::Grenada: if((countryName = QCoreApplication::translate("country", "Grenada"))== "Grenada") countryName = "";break; + case QLocale::Guadeloupe: if((countryName = QCoreApplication::translate("country", "Guadeloupe"))== "Guadeloupe") countryName = "";break; + case QLocale::Guam: if((countryName = QCoreApplication::translate("country", "Guam"))== "Guam") countryName = "";break; + case QLocale::Guatemala: if((countryName = QCoreApplication::translate("country", "Guatemala"))== "Guatemala") countryName = "";break; + case QLocale::Guinea: if((countryName = QCoreApplication::translate("country", "Guinea"))== "Guinea") countryName = "";break; + case QLocale::GuineaBissau: if((countryName = QCoreApplication::translate("country", "GuineaBissau"))== "GuineaBissau") countryName = "";break; + case QLocale::Guyana: if((countryName = QCoreApplication::translate("country", "Guyana"))== "Guyana") countryName = "";break; + case QLocale::Haiti: if((countryName = QCoreApplication::translate("country", "Haiti"))== "Haiti") countryName = "";break; + case QLocale::Honduras: if((countryName = QCoreApplication::translate("country", "Honduras"))== "Honduras") countryName = "";break; + case QLocale::HongKong: if((countryName = QCoreApplication::translate("country", "HongKong"))== "HongKong") countryName = "";break; + case QLocale::Hungary: if((countryName = QCoreApplication::translate("country", "Hungary"))== "Hungary") countryName = "";break; + case QLocale::Iceland: if((countryName = QCoreApplication::translate("country", "Iceland"))== "Iceland") countryName = "";break; + case QLocale::India: if((countryName = QCoreApplication::translate("country", "India"))== "India") countryName = "";break; + case QLocale::Indonesia: if((countryName = QCoreApplication::translate("country", "Indonesia"))== "Indonesia") countryName = "";break; + case QLocale::Iran: if((countryName = QCoreApplication::translate("country", "Iran"))== "Iran") countryName = "";break; + case QLocale::Iraq: if((countryName = QCoreApplication::translate("country", "Iraq"))== "Iraq") countryName = "";break; + case QLocale::Ireland: if((countryName = QCoreApplication::translate("country", "Ireland"))== "Ireland") countryName = "";break; + case QLocale::Israel: if((countryName = QCoreApplication::translate("country", "Israel"))== "Israel") countryName = "";break; + case QLocale::Italy: if((countryName = QCoreApplication::translate("country", "Italy"))== "Italy") countryName = "";break; + case QLocale::Jamaica: if((countryName = QCoreApplication::translate("country", "Jamaica"))== "Jamaica") countryName = "";break; + case QLocale::Japan: if((countryName = QCoreApplication::translate("country", "Japan"))== "Japan") countryName = "";break; + case QLocale::Jordan: if((countryName = QCoreApplication::translate("country", "Jordan"))== "Jordan") countryName = "";break; + case QLocale::Kazakhstan: if((countryName = QCoreApplication::translate("country", "Kazakhstan"))== "Kazakhstan") countryName = "";break; + case QLocale::Kenya: if((countryName = QCoreApplication::translate("country", "Kenya"))== "Kenya") countryName = "";break; + case QLocale::Kiribati: if((countryName = QCoreApplication::translate("country", "Kiribati"))== "Kiribati") countryName = "";break; + case QLocale::DemocraticRepublicOfKorea: if((countryName = QCoreApplication::translate("country", "DemocraticRepublicOfKorea"))== "DemocraticRepublicOfKorea") countryName = "";break; + case QLocale::RepublicOfKorea: if((countryName = QCoreApplication::translate("country", "RepublicOfKorea"))== "RepublicOfKorea") countryName = "";break; + case QLocale::Kuwait: if((countryName = QCoreApplication::translate("country", "Kuwait"))== "Kuwait") countryName = "";break; + case QLocale::Kyrgyzstan: if((countryName = QCoreApplication::translate("country", "Kyrgyzstan"))== "Kyrgyzstan") countryName = "";break; + case QLocale::Laos: if((countryName = QCoreApplication::translate("country", "Laos"))== "Laos") countryName = "";break; + case QLocale::Latvia: if((countryName = QCoreApplication::translate("country", "Latvia"))== "Latvia") countryName = "";break; + case QLocale::Lebanon: if((countryName = QCoreApplication::translate("country", "Lebanon"))== "Lebanon") countryName = "";break; + case QLocale::Lesotho: if((countryName = QCoreApplication::translate("country", "Lesotho"))== "Lesotho") countryName = "";break; + case QLocale::Liberia: if((countryName = QCoreApplication::translate("country", "Liberia"))== "Liberia") countryName = "";break; + case QLocale::Libya: if((countryName = QCoreApplication::translate("country", "Libya"))== "Libya") countryName = "";break; + case QLocale::Liechtenstein: if((countryName = QCoreApplication::translate("country", "Liechtenstein"))== "Liechtenstein") countryName = "";break; + case QLocale::Lithuania: if((countryName = QCoreApplication::translate("country", "Lithuania"))== "Lithuania") countryName = "";break; + case QLocale::Luxembourg: if((countryName = QCoreApplication::translate("country", "Luxembourg"))== "Luxembourg") countryName = "";break; + case QLocale::Macau: if((countryName = QCoreApplication::translate("country", "Macau"))== "Macau") countryName = "";break; + case QLocale::Macedonia: if((countryName = QCoreApplication::translate("country", "Macedonia"))== "Macedonia") countryName = "";break; + case QLocale::Madagascar: if((countryName = QCoreApplication::translate("country", "Madagascar"))== "Madagascar") countryName = "";break; + case QLocale::Malawi: if((countryName = QCoreApplication::translate("country", "Malawi"))== "Malawi") countryName = "";break; + case QLocale::Malaysia: if((countryName = QCoreApplication::translate("country", "Malaysia"))== "Malaysia") countryName = "";break; + case QLocale::Maldives: if((countryName = QCoreApplication::translate("country", "Maldives"))== "Maldives") countryName = "";break; + case QLocale::Mali: if((countryName = QCoreApplication::translate("country", "Mali"))== "Mali") countryName = "";break; + case QLocale::Malta: if((countryName = QCoreApplication::translate("country", "Malta"))== "Malta") countryName = "";break; + case QLocale::MarshallIslands: if((countryName = QCoreApplication::translate("country", "MarshallIslands"))== "MarshallIslands") countryName = "";break; + case QLocale::Martinique: if((countryName = QCoreApplication::translate("country", "Martinique"))== "Martinique") countryName = "";break; + case QLocale::Mauritania: if((countryName = QCoreApplication::translate("country", "Mauritania"))== "Mauritania") countryName = "";break; + case QLocale::Mauritius: if((countryName = QCoreApplication::translate("country", "Mauritius"))== "Mauritius") countryName = "";break; + case QLocale::Mayotte: if((countryName = QCoreApplication::translate("country", "Mayotte"))== "Mayotte") countryName = "";break; + case QLocale::Mexico: if((countryName = QCoreApplication::translate("country", "Mexico"))== "Mexico") countryName = "";break; + case QLocale::Micronesia: if((countryName = QCoreApplication::translate("country", "Micronesia"))== "Micronesia") countryName = "";break; + case QLocale::Moldova: if((countryName = QCoreApplication::translate("country", "Moldova"))== "Moldova") countryName = "";break; + case QLocale::Monaco: if((countryName = QCoreApplication::translate("country", "Monaco"))== "Monaco") countryName = "";break; + case QLocale::Mongolia: if((countryName = QCoreApplication::translate("country", "Mongolia"))== "Mongolia") countryName = "";break; + case QLocale::Montenegro: if((countryName = QCoreApplication::translate("country", "Montenegro"))== "Montenegro") countryName = "";break; + case QLocale::Montserrat: if((countryName = QCoreApplication::translate("country", "Montserrat"))== "Montserrat") countryName = "";break; + case QLocale::Morocco: if((countryName = QCoreApplication::translate("country", "Morocco"))== "Morocco") countryName = "";break; + case QLocale::Mozambique: if((countryName = QCoreApplication::translate("country", "Mozambique"))== "Mozambique") countryName = "";break; + case QLocale::Myanmar: if((countryName = QCoreApplication::translate("country", "Myanmar"))== "Myanmar") countryName = "";break; + case QLocale::Namibia: if((countryName = QCoreApplication::translate("country", "Namibia"))== "Namibia") countryName = "";break; + case QLocale::NauruCountry: if((countryName = QCoreApplication::translate("country", "NauruCountry"))== "NauruCountry") countryName = "";break; + case QLocale::Nepal: if((countryName = QCoreApplication::translate("country", "Nepal"))== "Nepal") countryName = "";break; + case QLocale::Netherlands: if((countryName = QCoreApplication::translate("country", "Netherlands"))== "Netherlands") countryName = "";break; + case QLocale::NewCaledonia: if((countryName = QCoreApplication::translate("country", "NewCaledonia"))== "NewCaledonia") countryName = "";break; + case QLocale::NewZealand: if((countryName = QCoreApplication::translate("country", "NewZealand"))== "NewZealand") countryName = "";break; + case QLocale::Nicaragua: if((countryName = QCoreApplication::translate("country", "Nicaragua"))== "Nicaragua") countryName = "";break; + case QLocale::Niger: if((countryName = QCoreApplication::translate("country", "Niger"))== "Niger") countryName = "";break; + case QLocale::Nigeria: if((countryName = QCoreApplication::translate("country", "Nigeria"))== "Nigeria") countryName = "";break; + case QLocale::Niue: if((countryName = QCoreApplication::translate("country", "Niue"))== "Niue") countryName = "";break; + case QLocale::NorfolkIsland: if((countryName = QCoreApplication::translate("country", "NorfolkIsland"))== "NorfolkIsland") countryName = "";break; + case QLocale::NorthernMarianaIslands: if((countryName = QCoreApplication::translate("country", "NorthernMarianaIslands"))== "NorthernMarianaIslands") countryName = "";break; + case QLocale::Norway: if((countryName = QCoreApplication::translate("country", "Norway"))== "Norway") countryName = "";break; + case QLocale::Oman: if((countryName = QCoreApplication::translate("country", "Oman"))== "Oman") countryName = "";break; + case QLocale::Pakistan: if((countryName = QCoreApplication::translate("country", "Pakistan"))== "Pakistan") countryName = "";break; + case QLocale::Palau: if((countryName = QCoreApplication::translate("country", "Palau"))== "Palau") countryName = "";break; + case QLocale::PalestinianTerritories: if((countryName = QCoreApplication::translate("country", "PalestinianTerritories"))== "PalestinianTerritories") countryName = "";break; + case QLocale::Panama: if((countryName = QCoreApplication::translate("country", "Panama"))== "Panama") countryName = "";break; + case QLocale::PapuaNewGuinea: if((countryName = QCoreApplication::translate("country", "PapuaNewGuinea"))== "PapuaNewGuinea") countryName = "";break; + case QLocale::Paraguay: if((countryName = QCoreApplication::translate("country", "Paraguay"))== "Paraguay") countryName = "";break; + case QLocale::Peru: if((countryName = QCoreApplication::translate("country", "Peru"))== "Peru") countryName = "";break; + case QLocale::Philippines: if((countryName = QCoreApplication::translate("country", "Philippines"))== "Philippines") countryName = "";break; + case QLocale::Poland: if((countryName = QCoreApplication::translate("country", "Poland"))== "Poland") countryName = "";break; + case QLocale::Portugal: if((countryName = QCoreApplication::translate("country", "Portugal"))== "Portugal") countryName = "";break; + case QLocale::PuertoRico: if((countryName = QCoreApplication::translate("country", "PuertoRico"))== "PuertoRico") countryName = "";break; + case QLocale::Qatar: if((countryName = QCoreApplication::translate("country", "Qatar"))== "Qatar") countryName = "";break; + case QLocale::Reunion: if((countryName = QCoreApplication::translate("country", "Reunion"))== "Reunion") countryName = "";break; + case QLocale::Romania: if((countryName = QCoreApplication::translate("country", "Romania"))== "Romania") countryName = "";break; + case QLocale::RussianFederation: if((countryName = QCoreApplication::translate("country", "RussianFederation"))== "RussianFederation") countryName = "";break; + case QLocale::Rwanda: if((countryName = QCoreApplication::translate("country", "Rwanda"))== "Rwanda") countryName = "";break; + case QLocale::SaintHelena: if((countryName = QCoreApplication::translate("country", "SaintHelena"))== "SaintHelena") countryName = "";break; + case QLocale::SaintKittsAndNevis: if((countryName = QCoreApplication::translate("country", "SaintKittsAndNevis"))== "SaintKittsAndNevis") countryName = "";break; + case QLocale::SaintLucia: if((countryName = QCoreApplication::translate("country", "SaintLucia"))== "SaintLucia") countryName = "";break; + case QLocale::SaintPierreAndMiquelon: if((countryName = QCoreApplication::translate("country", "SaintPierreAndMiquelon"))== "SaintPierreAndMiquelon") countryName = "";break; + case QLocale::SaintVincentAndTheGrenadines: if((countryName = QCoreApplication::translate("country", "SaintVincentAndTheGrenadines"))== "SaintVincentAndTheGrenadines") countryName = "";break; + case QLocale::Samoa: if((countryName = QCoreApplication::translate("country", "Samoa"))== "Samoa") countryName = "";break; + case QLocale::SanMarino: if((countryName = QCoreApplication::translate("country", "SanMarino"))== "SanMarino") countryName = "";break; + case QLocale::SaoTomeAndPrincipe: if((countryName = QCoreApplication::translate("country", "SaoTomeAndPrincipe"))== "SaoTomeAndPrincipe") countryName = "";break; + case QLocale::SaudiArabia: if((countryName = QCoreApplication::translate("country", "SaudiArabia"))== "SaudiArabia") countryName = "";break; + case QLocale::Senegal: if((countryName = QCoreApplication::translate("country", "Senegal"))== "Senegal") countryName = "";break; + case QLocale::Serbia: if((countryName = QCoreApplication::translate("country", "Serbia"))== "Serbia") countryName = "";break; + case QLocale::Seychelles: if((countryName = QCoreApplication::translate("country", "Seychelles"))== "Seychelles") countryName = "";break; + case QLocale::SierraLeone: if((countryName = QCoreApplication::translate("country", "SierraLeone"))== "SierraLeone") countryName = "";break; + case QLocale::Singapore: if((countryName = QCoreApplication::translate("country", "Singapore"))== "Singapore") countryName = "";break; + case QLocale::Slovakia: if((countryName = QCoreApplication::translate("country", "Slovakia"))== "Slovakia") countryName = "";break; + case QLocale::Slovenia: if((countryName = QCoreApplication::translate("country", "Slovenia"))== "Slovenia") countryName = "";break; + case QLocale::SolomonIslands: if((countryName = QCoreApplication::translate("country", "SolomonIslands"))== "SolomonIslands") countryName = "";break; + case QLocale::Somalia: if((countryName = QCoreApplication::translate("country", "Somalia"))== "Somalia") countryName = "";break; + case QLocale::SouthAfrica: if((countryName = QCoreApplication::translate("country", "SouthAfrica"))== "SouthAfrica") countryName = "";break; + case QLocale::Spain: if((countryName = QCoreApplication::translate("country", "Spain"))== "Spain") countryName = "";break; + case QLocale::SriLanka: if((countryName = QCoreApplication::translate("country", "SriLanka"))== "SriLanka") countryName = "";break; + case QLocale::Sudan: if((countryName = QCoreApplication::translate("country", "Sudan"))== "Sudan") countryName = "";break; + case QLocale::Suriname: if((countryName = QCoreApplication::translate("country", "Suriname"))== "Suriname") countryName = "";break; + case QLocale::Swaziland: if((countryName = QCoreApplication::translate("country", "Swaziland"))== "Swaziland") countryName = "";break; + case QLocale::Sweden: if((countryName = QCoreApplication::translate("country", "Sweden"))== "Sweden") countryName = "";break; + case QLocale::Switzerland: if((countryName = QCoreApplication::translate("country", "Switzerland"))== "Switzerland") countryName = "";break; + case QLocale::Syria: if((countryName = QCoreApplication::translate("country", "Syria"))== "Syria") countryName = "";break; + case QLocale::Taiwan: if((countryName = QCoreApplication::translate("country", "Taiwan"))== "Taiwan") countryName = "";break; + case QLocale::Tajikistan: if((countryName = QCoreApplication::translate("country", "Tajikistan"))== "Tajikistan") countryName = "";break; + case QLocale::Tanzania: if((countryName = QCoreApplication::translate("country", "Tanzania"))== "Tanzania") countryName = "";break; + case QLocale::Thailand: if((countryName = QCoreApplication::translate("country", "Thailand"))== "Thailand") countryName = "";break; + case QLocale::Togo: if((countryName = QCoreApplication::translate("country", "Togo"))== "Togo") countryName = "";break; + case QLocale::Tokelau: if((countryName = QCoreApplication::translate("country", "Tokelau"))== "Tokelau") countryName = "";break; + case QLocale::Tonga: if((countryName = QCoreApplication::translate("country", "Tonga"))== "Tonga") countryName = "";break; + case QLocale::TrinidadAndTobago: if((countryName = QCoreApplication::translate("country", "TrinidadAndTobago"))== "TrinidadAndTobago") countryName = "";break; + case QLocale::Tunisia: if((countryName = QCoreApplication::translate("country", "Tunisia"))== "Tunisia") countryName = "";break; + case QLocale::Turkey: if((countryName = QCoreApplication::translate("country", "Turkey"))== "Turkey") countryName = "";break; + case QLocale::Turkmenistan: if((countryName = QCoreApplication::translate("country", "Turkmenistan"))== "Turkmenistan") countryName = "";break; + case QLocale::TurksAndCaicosIslands: if((countryName = QCoreApplication::translate("country", "TurksAndCaicosIslands"))== "TurksAndCaicosIslands") countryName = "";break; + case QLocale::Tuvalu: if((countryName = QCoreApplication::translate("country", "Tuvalu"))== "Tuvalu") countryName = "";break; + case QLocale::Uganda: if((countryName = QCoreApplication::translate("country", "Uganda"))== "Uganda") countryName = "";break; + case QLocale::Ukraine: if((countryName = QCoreApplication::translate("country", "Ukraine"))== "Ukraine") countryName = "";break; + case QLocale::UnitedArabEmirates: if((countryName = QCoreApplication::translate("country", "UnitedArabEmirates"))== "UnitedArabEmirates") countryName = "";break; + case QLocale::UnitedKingdom: if((countryName = QCoreApplication::translate("country", "UnitedKingdom"))== "UnitedKingdom") countryName = "";break; + case QLocale::UnitedStates: if((countryName = QCoreApplication::translate("country", "UnitedStates"))== "UnitedStates") countryName = "";break; + case QLocale::Uruguay: if((countryName = QCoreApplication::translate("country", "Uruguay"))== "Uruguay") countryName = "";break; + case QLocale::Uzbekistan: if((countryName = QCoreApplication::translate("country", "Uzbekistan"))== "Uzbekistan") countryName = "";break; + case QLocale::Vanuatu: if((countryName = QCoreApplication::translate("country", "Vanuatu"))== "Vanuatu") countryName = "";break; + case QLocale::Venezuela: if((countryName = QCoreApplication::translate("country", "Venezuela"))== "Venezuela") countryName = "";break; + case QLocale::Vietnam: if((countryName = QCoreApplication::translate("country", "Vietnam"))== "Vietnam") countryName = "";break; + case QLocale::WallisAndFutunaIslands: if((countryName = QCoreApplication::translate("country", "WallisAndFutunaIslands"))== "WallisAndFutunaIslands") countryName = "";break; + case QLocale::Yemen: if((countryName = QCoreApplication::translate("country", "Yemen"))== "Yemen") countryName = "";break; + case QLocale::Zambia: if((countryName = QCoreApplication::translate("country", "Zambia"))== "Zambia") countryName = "";break; + case QLocale::Zimbabwe: if((countryName = QCoreApplication::translate("country", "Zimbabwe"))== "Zimbabwe") countryName = "";break; + default: { + countryName = QLocale::countryToString(p_country); + } + } + if( countryName == "") + countryName = QLocale::countryToString(p_country); + return countryName; +} +// Copy a folder recursively without erasing old file +void Utils::copyDir(QString from, QString to) { + QDir dir; + dir.setPath(from); + from += QDir::separator(); + to += QDir::separator(); + foreach (QString copyFile, dir.entryList(QDir::Files)) {// Copy each files + QString toFile = to + copyFile; + if (!QFile::exists(toFile)) + QFile::copy(from+copyFile, toFile); + } + foreach (QString nextDir, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {// Copy folder + QString toDir = to + nextDir; + QDir().mkpath(toDir);// no need to check if dir exists + copyDir(from + nextDir, toDir);//Go up + } +} + +QString Utils::getDisplayName(const std::shared_ptr& address){ + QString displayName; + if(address){ + displayName = CoreManager::getInstance()->getSipAddressesModel()->getDisplayName(address); + } + return displayName; +} + +std::shared_ptr Utils::getConfigIfExists (const QString &configPath) { + std::string factoryPath(Paths::getFactoryConfigFilePath()); + if (!Paths::filePathExists(factoryPath)) + factoryPath.clear(); + + return linphone::Config::newWithFactory(configPath.toStdString(), factoryPath); +} + +QString Utils::getApplicationProduct(){ +// Note: Keep '-' as a separator between application name and application type + return QString(APPLICATION_NAME"-Desktop").remove(' ')+"/"+QCoreApplication::applicationVersion(); +} + +QString Utils::getOsProduct(){ + QString version = QSysInfo::productVersion().remove(' ');// A version can be "Server 2016" (for Windows Server 2016) + QString product = QSysInfo::productType().replace(' ', '-'); // Just in case + return product+"/"+version; +} + +QString Utils::computeUserAgent(const std::shared_ptr& config){ + return QStringLiteral("%1 (%2) %3 Qt/%4 LinphoneSDK") + .arg(Utils::getApplicationProduct()) + .arg(SettingsModel::getDeviceName(config) + .replace('\\', "\\\\") + .replace('(', "\\(") + .replace(')', "\\)") + ) + .arg(Utils::getOsProduct()) + .arg(qVersion()); +} + +bool Utils::isMe(const QString& address){ + return !address.isEmpty() ? CoreManager::getInstance()->getAccountSettingsModel()->getUsedSipAddress()->weakEqual(Utils::interpretUrl(address)) : false; +} + +bool Utils::isMe(const std::shared_ptr& address){ + return address ? CoreManager::getInstance()->getAccountSettingsModel()->getUsedSipAddress()->weakEqual(address) : false; +} + +bool Utils::isAnimatedImage(const QString& path){ + if(path.isEmpty()) return false; + QFileInfo info(path); + if( !info.exists() || !QMimeDatabase().mimeTypeForFile(info).name().contains("image/")) + return false; + QImageReader reader(path); + return reader.canRead() && reader.supportsAnimation() && reader.imageCount() > 1; +} + +bool Utils::isImage(const QString& path){ + if(path.isEmpty()) return false; + QFileInfo info(path); + if( !info.exists() || CoreManager::getInstance()->getSettingsModel()->getVfsEncrypted()){ + return QMimeDatabase().mimeTypeForFile(info, QMimeDatabase::MatchExtension).name().contains("image/"); + }else if(!QMimeDatabase().mimeTypeForFile(info).name().contains("image/")) + return false; + QImageReader reader(path); + return reader.canRead() && reader.imageCount() == 1; +} + +bool Utils::isVideo(const QString& path){ + if(path.isEmpty()) return false; + return QMimeDatabase().mimeTypeForFile(path).name().contains("video/"); +} + +bool Utils::isPdf(const QString& path){ + if(path.isEmpty()) return false; + return QMimeDatabase().mimeTypeForFile(path).name().contains("application/pdf"); +} + +bool Utils::isSupportedForDisplay(const QString& path){ + if(path.isEmpty()) return false; + return !QMimeDatabase().mimeTypeForFile(path).name().contains("application");// "for pdf : "application/pdf". Note : Make an exception when supported. +} + +bool Utils::canHaveThumbnail(const QString& path){ + if(path.isEmpty()) return false; + return isImage(path) || isAnimatedImage(path) || isPdf(path) || isVideo(path); +} + +bool Utils::isPhoneNumber(const QString& txt){ + auto core = CoreManager::getInstance()->getCore(); + if(!core) + return false; + auto account = core->getDefaultAccount(); + return account && account->isPhoneNumber(Utils::appStringToCoreString(txt)); +} + +bool Utils::isUsername(const QString& txt){ + QRegularExpression regex("^(?$"); + QRegularExpressionMatch match = regex.match(txt); + return match.hasMatch(); // true +} + +bool Utils::isValidUrl(const QString& url){ + return QUrl(url).isValid(); +} + +QSize Utils::getImageSize(const QString& url){ + QString path; + QUrl urlDecode(url); + if(urlDecode.isLocalFile()) + path = QDir::toNativeSeparators(urlDecode.toLocalFile()); + else + path = url; + QFileInfo info(path); + if( !info.exists()) + return QSize(0,0); + QImageReader reader(path); + QSize s = reader.size(); + if( s.isValid()) + return s; + else + return QSize(0,0); +} + +QPoint Utils::getCursorPosition(){ + return QCursor::pos(); +} + +QString Utils::getFileChecksum(const QString& filePath){ + QFile file(filePath); + if (file.open(QFile::ReadOnly)) { + QCryptographicHash hash(QCryptographicHash::Sha256); + if (hash.addData(&file)) { + return hash.result().toHex(); + } + } + return QString(); +} +bool Utils::codepointIsEmoji(uint code){ + return (code >= 0x2600 && code <= 0x27bf) || (code >= 0x2b00 && code <= 0x2bff) || + (code >= 0x1f000 && code <= 0x1faff) || code == 0x200d || code == 0xfe0f; +} + +bool Utils::codepointIsVisible(uint code) { + return code > 0x00020; +} + +QString Utils::encodeEmojiToQmlRichFormat(const QString &body){ + QString fmtBody = ""; + QVector utf32_string = body.toUcs4(); + + bool insideFontBlock = false; + for (auto &code : utf32_string) { + if (Utils::codepointIsEmoji(code)) { + if (!insideFontBlock) { + fmtBody += QString("getSettingsModel()->getEmojiFont().family() + "\">"); + insideFontBlock = true; + } + } else { + if (insideFontBlock) { + fmtBody += ""; + insideFontBlock = false; + } + } + fmtBody += QString::fromUcs4(&code, 1); + } + if (insideFontBlock) { + fmtBody += ""; + } + return fmtBody; +} + +bool Utils::isOnlyEmojis(const QString& text){ + if(text.isEmpty()) return false; + QVector utf32_string = text.toUcs4(); + for (auto &code : utf32_string) + if(codepointIsVisible(code) && !Utils::codepointIsEmoji(code)) + return false; + return true; +} + + +QString Utils::encodeTextToQmlRichFormat(const QString& text, const QVariantMap& options){ + //QString images; + //QStringList imageFormat; + //for(auto format : QImageReader::supportedImageFormats()) +// imageFormat.append(QString::fromLatin1(format).toUpper()); + + QStringList formattedText; + bool lastWasUrl = false; + + if(options.contains("noLink") && options["noLink"].toBool()){ + formattedText.append(encodeEmojiToQmlRichFormat(text)); + }else{ + auto primaryColor = App::getInstance()->getColorListModel()->getColor("i")->getColor(); + auto iriParsed = UriTools::parseIri(text); + + for(int i = 0 ; i < iriParsed.size() ; ++i){ + QString iri = iriParsed[i].second.replace('&', "&") + .replace('<', "\u2063<") + .replace('>', "\u2063>") + .replace('"', """) + .replace('\'', "'"); + if(!iriParsed[i].first){ + if(lastWasUrl){ + lastWasUrl = false; + if(iri.front() != ' ') + iri.push_front(' '); + } + formattedText.append(encodeEmojiToQmlRichFormat(iri)); + }else{ + QString uri = iriParsed[i].second.left(3) == "www" ? "http://"+iriParsed[i].second : iriParsed[i].second ; + /* TODO : preview from link + //int extIndex = iriParsed[i].second.lastIndexOf('.'); + //QString ext; + //if( extIndex >= 0) + // ext = iriParsed[i].second.mid(extIndex+1).toUpper(); + //if(imageFormat.contains(ext.toLatin1())){// imagesHeight is not used because of bugs on display (blank image if set without width) + // images += ""+uri+""; + //}else{ + formattedText.append( "" + iri + ""); + lastWasUrl = true; + //} + } + } + } + if(lastWasUrl && formattedText.last().back() != ' '){ + formattedText.push_back(" "); + } + return "

" + formattedText.join("") + "

"; +} + +QString Utils::getFileContent(const QString& filePath){ + QString contents; + QFile file(filePath); + if (!file.open(QFile::ReadOnly | QFile::Text)) + return ""; + return file.readAll(); +} +static QStringList gDbPaths; + +void Utils::deleteAllUserData(){ +// Store usable data like custom folders + gDbPaths.clear(); + gDbPaths.append(Utils::coreStringToAppString(linphone::Factory::get()->getDataDir(nullptr))); + gDbPaths.append(Utils::coreStringToAppString(linphone::Factory::get()->getConfigDir(nullptr))); +// Exit with a delete code + App::getInstance()->exit(App::DeleteDataCode); +} + +void Utils::deleteAllUserDataOffline(){ + qWarning() << "Deleting all data! "; + for(int i = 0 ; i < gDbPaths.size() ; ++i){ + QDir dir(gDbPaths[i]); + qWarning() << "Deleting " << gDbPaths[i] << " : " << (dir.removeRecursively() ? "Successfully" : "Failed"); + } +} + +//------------------------------------------------------------------------------------------------------- +// WIDGETS +//------------------------------------------------------------------------------------------------------- + +bool Utils::openWithPdfViewer(ContentModel * contentModel, const QString& filePath, const int& width, const int& height) { +#ifdef PDF_ENABLED + PdfWidget *view = new PdfWidget(contentModel); + view->setMinimumSize(QSize(width, height)); + view->show(); + view->open(filePath); + return true; +#else + return false; +#endif +} + +void Utils::setFamilyFont(QAction * dest, const QString& family){ + QFont font(dest->font()); + font.setFamily(family); + dest->setFont(font); +} +void Utils::setFamilyFont(QWidget * dest, const QString& family){ + QFont font(dest->font()); + font.setFamily(family); + dest->setFont(font); +} +QPixmap Utils::getMaskedPixmap(const QString& name, const QColor& color){ + QSize size; + QPixmap img = ImageProvider::computePixmap(name, &size); + QPixmap pxr( img.size() ); + pxr.fill( color ); + pxr.setMask( img.createMaskFromColor( Qt::transparent ) ); + return pxr; +} +*/ diff --git a/Linphone/tool/Utils.hpp b/Linphone/tool/Utils.hpp new file mode 100644 index 000000000..1e59055c4 --- /dev/null +++ b/Linphone/tool/Utils.hpp @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2010-2020 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * 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, see . + */ + +#ifndef UTILS_H_ +#define UTILS_H_ + +#include +#include +#include +#include +#include + +#include "Constants.hpp" + +class QAction; +class QWidget; +class DateModel; + +// ============================================================================= + +/* + * Define telling g++ that a 'break' statement has been deliberately omitted + * in switch block. + */ +#ifndef UTILS_NO_BREAK +#if defined(__GNUC__) && __GNUC__ >= 7 +#define UTILS_NO_BREAK __attribute__((fallthrough)) +#else +#define UTILS_NO_BREAK +#endif // if defined(__GNUC__) && __GNUC__ >= 7 +#endif // ifndef UTILS_NO_BREAK + +class ContentModel; + +class Utils : public QObject{ + Q_OBJECT +public: + Utils(QObject * parent = nullptr) : QObject(parent){} +/* + typedef enum{ + SIP_DISPLAY_USERNAME = 0, + SIP_DISPLAY_ALL = -1 + }SipDisplayMode; + Q_ENUM(SipDisplayMode) + + // Qt interfaces + Q_INVOKABLE static bool hasCapability(const QString& address, const LinphoneEnums::FriendCapability& capability, bool defaultCapability = true); +// ***** DATE TIME + Q_INVOKABLE static QDateTime addMinutes(QDateTime date, const int& min); + static QDateTime getOffsettedUTC(const QDateTime& date); + Q_INVOKABLE static QString toDateTimeString(QDateTime date, const QString& format = "yyyy/MM/dd hh:mm:ss"); + Q_INVOKABLE static QString toTimeString(QDateTime date, const QString& format = "hh:mm:ss"); + Q_INVOKABLE static QString toDateString(QDateTime date, const QString& format = ""); + Q_INVOKABLE static QString toDateString(QDate date, const QString& format = ""); + Q_INVOKABLE static QString toDisplayString(const QString& str, SipDisplayMode displayMode = SIP_DISPLAY_ALL); + Q_INVOKABLE static QDate getCurrentDate(); + Q_INVOKABLE static DateModel* getCurrentDateModel(); + Q_INVOKABLE static QDate getMinDate(); + Q_INVOKABLE static DateModel* getMinDateModel(); + Q_INVOKABLE static QDate toDate(const QString& str, const QString& format = "yyyy/MM/dd"); + Q_INVOKABLE static QDate getDate(int year, int month, int day); + Q_INVOKABLE static DateModel* toDateModel(const QString& str, const QString& format = "yyyy/MM/dd"); + Q_INVOKABLE static DateModel* getDateModel(int year, int month, int day); + Q_INVOKABLE static int getFullYear(const QDate& date); + Q_INVOKABLE static int getMonth(const QDate& date); + Q_INVOKABLE static int getDay(const QDate& date); + Q_INVOKABLE static int getDayOfWeek(const QDate& date); + Q_INVOKABLE static bool equals(const QDate& d1, const QDate& d2); // Override JS '==' operator + Q_INVOKABLE static bool isGreatherThan(const QDate& d1, const QDate& d2); // Override JS '>=' operator +//***** + static void cleanDisplayNameCache(const QString& address = "");// if "", clean all cache + Q_INVOKABLE static QString getDisplayName(const QString& address); + Q_INVOKABLE static QString getInitials(const QString& username); // Support UTF32 + Q_INVOKABLE static QString toString(const LinphoneEnums::TunnelMode& mode); + Q_INVOKABLE static bool isMe(const QString& address); + Q_INVOKABLE static bool isAnimatedImage(const QString& path); + Q_INVOKABLE static bool isImage(const QString& path); + Q_INVOKABLE static bool isVideo(const QString& path); + Q_INVOKABLE static bool isPdf(const QString& path); + Q_INVOKABLE static bool isSupportedForDisplay(const QString& path); + Q_INVOKABLE static bool canHaveThumbnail(const QString& path); + Q_INVOKABLE static bool isPhoneNumber(const QString& txt); + Q_INVOKABLE static bool isUsername(const QString& txt); // Check with Regex + Q_INVOKABLE static bool isValidUrl(const QString& url); + Q_INVOKABLE QSize getImageSize(const QString& url); + Q_INVOKABLE static QPoint getCursorPosition(); + Q_INVOKABLE static QString getFileChecksum(const QString& filePath); + static bool codepointIsEmoji(uint code); + static bool codepointIsVisible(uint code); + Q_INVOKABLE static bool isOnlyEmojis(const QString& text); + Q_INVOKABLE static QString encodeEmojiToQmlRichFormat(const QString &body); + Q_INVOKABLE static QString encodeTextToQmlRichFormat(const QString& text, const QVariantMap& options = QVariantMap()); + Q_INVOKABLE static QString getFileContent(const QString& filePath); + + Q_INVOKABLE static bool openWithPdfViewer(ContentModel *contentModel, const QString& filePath, const int& width, const int& height); // return true if PDF is enabled + +//---------------------------------------------------------------------------------- + + static inline QString coreStringToAppString (const std::string &str) { + if(Constants::LinphoneLocaleEncoding == QString("UTF-8")) + return QString::fromStdString(str); + else + return QString::fromLocal8Bit(str.c_str(), int(str.size()));// When using Locale. Be careful about conversion bijection with UTF-8, you may loss characters + } + + static inline std::string appStringToCoreString (const QString &str) { + if(Constants::LinphoneLocaleEncoding == QString("UTF-8")) + return str.toStdString(); + else + return qPrintable(str); + } + + // Reverse function of strstr. + static char *rstrstr (const char *a, const char *b); + // Return the path if it is an image else an empty path. + static QImage getImage(const QString &pUri); + // Returns the same path given in parameter if `filePath` exists. + // Otherwise returns a safe path with a unique number before the extension. + static QString getSafeFilePath (const QString &filePath, bool *soFarSoGood = nullptr); + static std::shared_ptr getMatchingLocalAddress(std::shared_ptr p_localAddress); + static QString cleanSipAddress (const QString &sipAddress);// Return at most : sip:username@domain + // Test if the process exists + static bool processExists(const quint64& p_processId); + + // Connect once to a member function. + template + static inline QMetaObject::Connection connectOnce ( + typename QtPrivate::FunctionPointer::Object *sender, + Func1 signal, + typename QtPrivate::FunctionPointer::Object *receiver, + Func2 slot + ) { + QMetaObject::Connection connection = QObject::connect(sender, signal, receiver, slot); + QMetaObject::Connection *deleter = new QMetaObject::Connection(); + + *deleter = QObject::connect(sender, signal, [connection, deleter] { + QObject::disconnect(connection); + QObject::disconnect(*deleter); + delete deleter; + }); + + return connection; + } + + // Connect once to a function. + template + static inline QMetaObject::Connection connectOnce ( + typename QtPrivate::FunctionPointer::Object *sender, + Func1 signal, + const QObject *receiver, + Func2 slot + ) { + QMetaObject::Connection connection = QObject::connect(sender, signal, receiver, slot); + QMetaObject::Connection *deleter = new QMetaObject::Connection(); + + *deleter = QObject::connect(sender, signal, [connection, deleter] { + QObject::disconnect(connection); + QObject::disconnect(*deleter); + delete deleter; + }); + + return connection; + } + static std::shared_ptr interpretUrl(const QString& address); + + + static QString getCountryName(const QLocale::Country& country); + static void copyDir(QString from, QString to);// Copy a folder recursively without erasing old file + static QString getDisplayName(const std::shared_ptr& address); // Get the displayname from addres in this order : Friends, Contact, Display address, Username address + static std::shared_ptr getConfigIfExists (const QString& configPath); + static QString getApplicationProduct(); + static QString getOsProduct(); + static QString computeUserAgent(const std::shared_ptr& config); + + static bool isMe(const std::shared_ptr& address); + + static void deleteAllUserData(); + static void deleteAllUserDataOffline();// When we are out of all events and core is not running (aka in main()) + + static void setFamilyFont(QAction * dest, const QString& family); + static void setFamilyFont(QWidget * dest, const QString& family); + static QPixmap getMaskedPixmap(const QString& name, const QColor& color); +*/ +}; + +#endif // UTILS_H_ diff --git a/Linphone/tool/config.h.cmake b/Linphone/tool/config.h.cmake new file mode 100644 index 000000000..8999ffb85 --- /dev/null +++ b/Linphone/tool/config.h.cmake @@ -0,0 +1,38 @@ +/******************************************************************************* +* config.h.cmake +* Copyright (C) 2017-2024 Belledonne Communications, Grenoble France +* +******************************************************************************** +* +* 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 2 +* 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. +* +*******************************************************************************/ + +#cmakedefine APPLICATION_DESCRIPTION "${APPLICATION_DESCRIPTION}" +#cmakedefine APPLICATION_ID "${APPLICATION_ID}" +#cmakedefine APPLICATION_NAME "${APPLICATION_NAME}" +#cmakedefine APPLICATION_VENDOR "${APPLICATION_VENDOR}" +#cmakedefine APPLICATION_URL "${APPLICATION_URL}" +#cmakedefine APPLICATION_LICENCE "${APPLICATION_LICENCE}" +#cmakedefine APPLICATION_LICENCE_URL "${APPLICATION_LICENCE_URL}" +#cmakedefine APPLICATION_SEMVER "${APPLICATION_SEMVER}" +#cmakedefine COPYRIGHT_RANGE_DATE "${COPYRIGHT_RANGE_DATE}" +#cmakedefine ENABLE_UPDATE_CHECK 1 +#cmakedefine EXECUTABLE_NAME "${EXECUTABLE_NAME}" +#cmakedefine MSPLUGINS_DIR "${MSPLUGINS_DIR}" +#cmakedefine ENABLE_APP_WEBVIEW "${ENABLE_APP_WEBVIEW}" +#cmakedefine QTKEYCHAIN_TARGET_NAME ${QTKEYCHAIN_TARGET_NAME} +#cmakedefine PDF_ENABLED + diff --git a/README.md b/README.md index 9a7810409..b8d1dae35 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ Qt6 application. -(export PATH=$PATH:~/Qt/6.5.2/gcc_64/bin) +export PATH=$PATH:~/Qt/6.5.2/gcc_64/bin +optional: export Qt6_DIR=~/Qt/6.5.2/gcc_64/lib/cmake/Qt6 mkdir build cd build @@ -24,6 +25,7 @@ cmake --build . --target install --parallel 10 - icon: generated icons - image: all images of the application. The format should be in svg and in monocolor to allow realtime updates. - lang: TS files used with Weblate. + - tool: internal library for generic tools. - cmake : Build and Installation scripts.